/* ==========================================================================
   COMPONENTS
   ========================================================================== */

/* ---- Nav ----
   REBUILT AUG 13 2026 from the full-system drop's Nav.jsx. THE COLLAPSE IS
   DRIVEN BY SCROLL POSITION, NOT BY A BREAKPOINT IN TIME: js/nav.js writes
   --nav-p (0..1) over a 150px ramp and every value below interpolates across
   that same travel, so the header is a continuous mechanism rather than two
   states with a fade between them. The distance is deliberately short — about
   a flick of the wheel — because a long ramp reads as lag, not machinery.
   --nav-q is the SIZE travel; on mobile it is only 55% of --nav-p because the
   expanded state is already tight there and a full-depth collapse would be
   movement for its own sake. The veil/rule/tail always ride the full --nav-p.

   THE COLLAPSED BAR IS FULLY OPAQUE, AND THAT IS NOT NEGOTIABLE — the measured
   note below survives from the previous nav and is why the drop's own brief
   was overruled on this point. The .is-scrolled class some pages hardcode is
   INERT since this rebuild; at --nav-p:0 the bar already carries the same top
   protection gradient the hero uses, so links always have ground under them. */
.nav {
  position: fixed;
  inset-inline: 0;
  top: 0;
  z-index: 100;
  --nav-p: 0;                       /* written by js/nav.js on every frame */
  --nav-q: var(--nav-p);            /* size travel; damped on mobile below */
  padding-block: calc(30px - 21px * var(--nav-q));   /* 30 → 9px */
  background: linear-gradient(180deg,
    rgba(3, 4, 15, calc(0.78 + 0.22 * var(--nav-p))) 0%,
    rgba(3, 4, 15, calc(0.42 + 0.58 * var(--nav-p))) 55%,
    rgba(3, 4, 15, var(--nav-p)) 100%);
  border-bottom: 1px solid rgba(57, 71, 80, calc(0.85 * var(--nav-p)));
  /* NO-REPEAT IS THE FIX FOR A 1px BLACK LINE AT REST, not a tidiness habit.
     The gradient's box is the PADDING box (background-origin default), but the
     paint area includes the transparent 1px border below it — and the default
     background-repeat tiled the gradient's FIRST row (alpha .78, near black)
     into that strip. Result: a hairline under the bar at --nav-p:0, sitting on
     the footage, vanishing once the bar went opaque. Isolated Aug 14 2026 by
     toggling one property at a time and diffing the pixel row (y=91 at 1440):
     border:none +69.8 brightness, background:none +69.8, tail/scrim/video 0. */
  background-repeat: no-repeat;
  will-change: padding-block;
}
/* OPAQUE, not 92% + blur. MEASURED 2026-08-04.
   The scrolled nav used to be rgba(3,4,15,0.92) with a 6px backdrop blur, which
   let 8% of whatever sits behind it through. That is invisible over the black
   page and it was invisible for months — until you jump to #tracks, which parks
   the hero's CTA row directly behind the bar: at that scroll position
   .hero__ctas spans viewport -28..22, so the solid WHITE "Enter the World"
   button sits under the nav. Eight percent of white is not nothing. It read as
   a lit rectangle inside the bar with the hero video moving behind it, ending in
   a hard horizontal edge a few pixels above the nav's own hairline.

   Isolated by removing one thing at a time and re-measuring the nav band:
     hiding .hero__ctas     changed it by max 19.0 across 6,495 px
     hiding .hero__content  changed it by max 19.0 across 6,495 px  (same pixels)
     hiding .hero__media    changed it by max  1.4 across     0 px
   So it was the buttons, not the footage — the video was just what you could see
   moving behind them.

   In the collapse model this holds because the gradient's bottom stop reaches
   alpha 1 at exactly the scroll distance (150px) that parks anything behind the
   bar — by the #tracks landing position --nav-p is 1 and the bar is solid. No
   blur: the system's glass belongs to the spine cards, and borrowing it here
   would soften an element whose whole job is to be a hard edge.
   "Visually connected underneath" is delivered by a short gradient TAIL below
   the bar instead, so the join is soft without the bar itself leaking. */
.nav::after {
  content: "";
  position: absolute;
  left: 0; right: 0; top: 100%;
  height: 22px;
  pointer-events: none;
  background: linear-gradient(180deg, rgba(3, 4, 15, calc(0.9 * var(--nav-p))) 0%, rgba(3, 4, 15, 0) 100%);
}
.nav__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-6);
}
/* The mark SCALES rather than being swapped for an initial — the identity
   thins with the bar instead of being replaced by a different one. */
.nav__mark {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-display);
  font-weight: var(--display-wght);
  font-stretch: var(--display-stretch);
  font-variation-settings: "wdth" var(--display-wdth), "wght" var(--display-wght);
  text-transform: uppercase;
  font-size: calc(19px - 4.5px * var(--nav-q));       /* 19 → 14.5px */
  letter-spacing: var(--tracking-heading);
  text-decoration: none;
  white-space: nowrap;
  color: var(--color-white);
  text-shadow: 0 0 3px rgba(3, 4, 15, 0.98), 0 1px 2px rgba(3, 4, 15, 0.92);
}
.nav__mark img {
  width: calc(20px - 5px * var(--nav-q));             /* 20 → 15px */
  height: calc(20px - 5px * var(--nav-q));
}
.nav__links {
  display: flex;
  gap: calc(34px - 15px * var(--nav-q));              /* 34 → 19px */
  list-style: none;
  margin: 0; padding: 0;
}
/* THE NAV SITS ON FOOTAGE, SO IT CANNOT USE --text-secondary.
   The cold palette's secondary (#9DB2C0) is materially darker than the warm
   bone it replaced; over a bright frame it measures ~1.3:1 and the inactive
   labels disappear. Links over imagery read from --spine-glow at reduced alpha
   and carry the two-pass legibility shadow instead. */
.nav__links a {
  text-decoration: none;
  font-family: var(--font-label);
  font-weight: 600;
  font-size: var(--fs-label);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: rgba(228, 232, 235, 0.82);
  text-shadow: 0 0 3px rgba(3, 4, 15, 0.98), 0 1px 2px rgba(3, 4, 15, 0.92);
}
.nav__links a:hover, .nav__links a[aria-current="page"] { color: var(--color-white); }

/* SEVEN ITEMS DO NOT FIT THE ROW AT ITS NARROWEST, SO THE GAP TIGHTENS EARLY.
   The row is only used from 769px up; below that the fullscreen menu takes
   over. With six items it cleared 769px with 27px to spare. The Album entry
   added Aug 27 2026 pushed the list PAST the container's right edge there, and
   the overflow was INVISIBLE to scrollWidth because .nav is position:fixed —
   it showed up only in a screenshot, as a clipped label at the right edge.
   Measured at 769px with the longest label considered: gap 34 -> 62px over,
   28 -> 26 over, 24 -> 2 over, 22 -> clears by 10px.
   22px is the value because the row ALREADY reaches 19px once scrolled, so
   this is the scrolled spacing arriving early on narrow screens rather than a
   new number in the design. The scrolled endpoint stays 19px, unchanged.
   840 is the upper bound: "Album" clears the row unaided from 804px, so this
   covers that with margin and stops before widths that never needed it.
   IF AN EIGHTH ITEM IS EVER ADDED, RE-MEASURE — do not assume this still holds. */
@media (min-width: 769px) and (max-width: 840px) {
  .nav__links { gap: calc(22px - 3px * var(--nav-q)); }   /* 22 → 19px */
}

/* Mobile travels less — see the header note. 760 is the collapse spec's own
   breakpoint (it pairs with --nav-h-max in tokens.css); the fullscreen menu
   below keeps its historical 768. */
@media (max-width: 760px) {
  .nav {
    --nav-q: calc(var(--nav-p) * 0.55);
    padding-block: calc(18px - 8px * var(--nav-q));   /* 18 → ~13.6px */
  }
  .nav__mark { font-size: calc(17px - 3px * var(--nav-q)); }
  .nav__mark img { width: calc(17px - 3px * var(--nav-q)); height: calc(17px - 3px * var(--nav-q)); }
}

.nav__toggle {
  display: none;
  background: none;
  border: 1px solid var(--border-subtle);
  color: var(--text-primary);
  padding: var(--space-2) var(--space-3);
  font-family: var(--font-mono);
  cursor: pointer;
}

@media (max-width: 768px) {
  .nav__links {
    position: fixed;
    inset: 0;
    top: 0;
    background: var(--color-black);
    flex-direction: column;
    justify-content: center;
    align-items: center;
    gap: var(--space-8);
    transform: translateY(-100%);
    transition: transform var(--motion-base) var(--ease-standard);
  }
  .nav__links.is-open { transform: translateY(0); }
  .nav__links a { font-size: var(--fs-h3); }
  .nav__toggle { display: block; z-index: 101; position: relative; }
}

/* ---- Buttons ---- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  /* Buttons are interface type — Rajdhani, like the nav and every chip.
     The display face at button size closes up and stops being readable. */
  font-family: var(--font-label);
  font-weight: 600;
  font-size: var(--fs-label);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  text-decoration: none;
  padding: var(--space-3) var(--space-6);
  /* 44px MINIMUM — THE TOUCH TARGET (Aug 21 2026).

     This height is padding-derived: --space-3 (12px) top and bottom against a
     --fs-label line. --space-3 is a fixed 12px but --fs-label is FLUID, so the
     button shrinks with the viewport — and it is smallest exactly where the
     target matters. MEASURED across all ten root pages: 47.4px at 1440, and at
     390 connect.html's "Join the Signal" came out at 42px, the number
     css/purchase.css already had written down.

     A min-height rather than more padding, because padding would move every
     button on the site at every width to fix the one width that is short.
     Nothing at 1440 changes: 44 is under the 47.4 those already measure.

     IT ALSO CATCHES THE OVERRIDES. .track-focus-panel__actions .btn sets its
     own tighter padding (0.55rem) to keep five actions on one row and measured
     40.2px at BOTH widths — the worst targets on the site, and the ones the
     "42px site-wide" note missed. min-height lifts them to 44 without touching
     the horizontal padding that row depends on.

     css/purchase.css pinned this on its three CTAs first and said the site-wide
     version belonged here. It is here now, and that pin is gone — one source of
     truth, so a future change to this number reaches the purchase page too. */
  min-height: 44px;
  border: 1px solid var(--color-white);
  border-radius: var(--radius-sharp);
  transition: background var(--motion-fast) var(--ease-standard),
              color var(--motion-fast) var(--ease-standard);
  cursor: pointer;
}
.btn--primary { background: var(--color-white); color: var(--color-black); }
/* color is re-declared, not inherited. An <a class="btn btn--primary"> (merch.html)
   otherwise loses it on hover: a:hover in css/base.css is (0,1,1) and beats the
   (0,1,0) .btn--primary rule above, repainting the label bone on a bone
   background. .btn--ghost:hover already re-declares color and was never hit;
   purchase.html uses <button> and was never hit either. */
.btn--primary:hover { background: var(--color-bone); border-color: var(--color-bone); color: var(--color-black); }
.btn--ghost { background: transparent; color: var(--text-primary); }
.btn--ghost:hover { background: var(--color-white); color: var(--color-black); }
.btn:disabled { opacity: 0.4; cursor: not-allowed; }

/* ---- Hero ---- */
.hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  align-items: flex-end;
  overflow: hidden;
  background: var(--color-black);
}
.hero__media {
  position: absolute;
  inset: 0;
  z-index: 0;
}
.hero__media img {
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: center 20%;
  opacity: 0;
  animation: hero-reveal var(--motion-hero) var(--ease-standard) forwards;
}
.hero__media video {
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: center 20%;
  opacity: 0;
  animation: hero-reveal var(--motion-hero) var(--ease-standard) forwards;
}
@keyframes hero-reveal {
  from { opacity: 0; transform: scale(1.04); }
  to   { opacity: 1; transform: scale(1); }
}
.hero__sound-toggle {
  position: absolute;
  right: var(--space-6);
  bottom: var(--space-6);
  z-index: 3;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-secondary);
  background: rgba(3, 4, 15, 0.55);
  border: 1px solid var(--border-subtle);
  padding: var(--space-2) var(--space-3);
  cursor: pointer;
  transition: border-color var(--motion-fast) var(--ease-standard),
              color var(--motion-fast) var(--ease-standard);
}
.hero__sound-toggle:hover, .hero__sound-toggle[aria-pressed="true"] {
  color: var(--text-primary);
  border-color: var(--text-primary);
}
@media (max-width: 768px) {
  .hero__sound-toggle { right: var(--space-4); bottom: var(--space-4); }
}
.hero__scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(3,4,15,0.15) 0%, rgba(3,4,15,0.55) 55%, rgba(3,4,15,0.95) 100%);
  z-index: 1;
}
.hero__content {
  position: relative;
  z-index: 2;
  width: 100%;
  padding-block: var(--space-16) var(--space-16);
}
.hero__eyebrow {
  display: block;
  margin-bottom: var(--space-4);
}
.hero__title {
  font-size: var(--fs-hero);
  margin-bottom: var(--space-4);
}
.hero__statement {
  color: var(--text-secondary);
  font-size: var(--fs-body-lg);
  max-width: 52ch;
  margin-bottom: var(--space-8);
}
.hero__ctas {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
}

/* ---- Section header ---- */
.section-header h2 { margin-bottom: var(--space-2); }
.section-header p { color: var(--text-secondary); }

/* ---- Entry point cards ---- */
.entry-card {
  border: var(--border-hairline);
  padding: var(--space-8);
  text-decoration: none;
  color: var(--text-primary);
  display: block;
  transition: border-color var(--motion-fast) var(--ease-standard),
              background var(--motion-fast) var(--ease-standard);
}
.entry-card:hover, .entry-card:focus-visible {
  border-color: var(--text-primary);
  background: var(--bg-surface);
}
.entry-card__label { margin-bottom: var(--space-2); }
.entry-card p { color: var(--text-secondary); }

/* ---- Messenger card ---- */
.messenger-card {
  display: grid;
  gap: var(--space-4);
}
.messenger-card__portrait {
  aspect-ratio: 4 / 5;
  overflow: hidden;
  background: var(--bg-surface);
}
.messenger-card__portrait img { width: 100%; height: 100%; object-fit: cover; }
.messenger-card__archetype { display: block; margin-bottom: var(--space-1); }
.messenger-card p { color: var(--text-secondary); font-size: var(--fs-body); }

/* ---- Featured block (release / transmission) ---- */
.featured-block {
  display: grid;
  grid-template-columns: minmax(240px, 380px) 1fr;
  gap: var(--space-12);
  align-items: center;
}
.featured-block__media {
  aspect-ratio: 4 / 5;
  background: var(--bg-surface);
  overflow: hidden;
  border: var(--border-hairline);
}
.featured-block__media img { width: 100%; height: 100%; object-fit: cover; }
.featured-block__body .label { display: block; margin-bottom: var(--space-3); }
.featured-block__body p { color: var(--text-secondary); }
@media (max-width: 768px) {
  .featured-block { grid-template-columns: 1fr; }
  .featured-block__media { max-width: 320px; }
}

/* ---- Audio player ---- */
.audio-player {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  border: var(--border-hairline);
  padding: var(--space-4);
  background: var(--bg-surface);
}
.audio-player__cover { width: 56px; height: 56px; object-fit: cover; flex-shrink: 0; }
.audio-player__body { flex: 1; min-width: 0; }
.audio-player__meta { display: flex; flex-direction: column; margin-bottom: var(--space-2); }
.audio-player__title { font-family: var(--font-display); font-size: var(--fs-body); }
.audio-player__artist { font-family: var(--font-mono); font-size: var(--fs-caption); color: var(--text-muted); }
.audio-player__controls {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
}
.audio-player__play {
  width: 40px; height: 40px;
  border: 1px solid var(--color-white);
  background: transparent;
  color: var(--text-primary);
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  transition: background var(--motion-fast) var(--ease-standard), color var(--motion-fast) var(--ease-standard);
}
.audio-player__play:hover { background: var(--color-white); color: var(--color-black); }
.audio-player__play:disabled { opacity: 0.4; cursor: not-allowed; }
.audio-player__time { font-family: var(--font-mono); font-size: var(--fs-caption); color: var(--text-muted); min-width: 3.2em; }
.audio-player__scrub { flex: 1; min-width: 80px; accent-color: var(--color-bone); }
.audio-player__volume { width: 80px; accent-color: var(--color-bone); }
.audio-player__status { margin: var(--space-2) 0 0; font-size: var(--fs-caption); color: var(--text-muted); min-height: 1em; }
@media (max-width: 480px) {
  .audio-player { flex-wrap: wrap; }
  .audio-player__volume { display: none; }
}

/* ---- Archive filter bar ---- */
.filter-bar {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-bottom: var(--space-8);
}
.filter-chip {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  background: transparent;
  color: var(--text-secondary);
  border: 1px solid var(--border-subtle);
  padding: var(--space-2) var(--space-4);
  cursor: pointer;
  transition: border-color var(--motion-fast) var(--ease-standard),
              color var(--motion-fast) var(--ease-standard),
              background var(--motion-fast) var(--ease-standard);
}
.filter-chip:hover { border-color: var(--text-primary); color: var(--text-primary); }
.filter-chip[aria-pressed="true"] {
  background: var(--color-white);
  color: var(--color-black);
  border-color: var(--color-white);
}
.archive-card { text-decoration: none; color: var(--text-primary); display: block; }
.archive-card__media {
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border: var(--border-hairline);
  margin-bottom: var(--space-3);
}
.archive-card__media img { width: 100%; height: 100%; object-fit: cover; transition: transform var(--motion-slow) var(--ease-standard); }
.archive-card:hover .archive-card__media img, .archive-card:focus-visible .archive-card__media img { transform: scale(1.03); }
.archive-card p { color: var(--text-secondary); }

/* ---- Newsletter ---- */
.newsletter {
  border-top: var(--border-hairline);
  border-bottom: var(--border-hairline);
  text-align: center;
}
.newsletter__inner { max-width: 56ch; margin-inline: auto; }
.newsletter h1, .newsletter h2 { font-family: var(--font-display-stencil); } /* h1: connect.html runs this block as a page (Aug 12 2026) */

/* THE HEADING IS CAPPED SO ITS LONGEST WORD FITS THE MEASURE (Aug 20 2026).

   Reported as "Connected is not centered" on connect.html, and it was: three of
   the four lines were centred to the pixel and one was not. MEASURED at 1440,
   "Stay Connected to the Signal" wrapped to four lines inside the 523px column
   (.newsletter__inner is 56ch):

     line        width    centre      page centre 720
     Stay        241px    720         centred
     Connected   609px    762         85px PAST the right edge
     to the      341px    720         centred
     Signal      360px    720         centred

   The cause is not a centring bug and there is nothing wrong with
   `text-align: center`. --fs-hero is clamp(2.75rem, 9vw, 8.25rem), so at 1440
   the h1 renders at 129.6px, and at that size the single word "Connected"
   measures 609px. A word that cannot break and is wider than its line box
   overflows to the right in LTR, and centring has nothing left to do — the box
   is 523px and the word simply does not fit in it.

   It only breaks WIDE. The column stops growing at 56ch while 9vw does not, so
   the two cross somewhere past ~1160px; at 900 the word measures 447px and at
   390 it is 293px, both comfortably inside, and both were centred correctly.
   That is why this reads as a desktop-only fault.

   6.75rem = 108px is the cap. "Connected" scales at 4.699px of width per 1px of
   font-size (609 / 129.6, letter-spacing is em-based so it scales too), which
   puts the word at 507px — inside the 523px column with 16px to spare. The
   largest size that would still fit is 111.3px; 108 is that number with the
   rounding headroom taken off rather than sat on.

   NOT FIXED BY `overflow-wrap: break-word` — that would hyphenlessly snap the
   word to "Connec / ted", which is worse than the fault. NOT fixed by widening
   .newsletter__inner either: that element also sets the measure for the form
   and the privacy copy below it, and they are the right width already. */
.newsletter h1 { font-size: min(var(--fs-hero), 6.75rem); }
.newsletter p { color: var(--text-secondary); }
.newsletter-form {
  display: flex;
  gap: var(--space-3);
  margin-top: var(--space-6);
  flex-wrap: wrap;
  justify-content: center;
}
.newsletter-form__field {
  flex: 1 1 260px;
  background: var(--bg-surface);
  border: var(--border-hairline);
  color: var(--text-primary);
  padding: var(--space-3) var(--space-4);
  font-family: var(--font-body);
  font-size: var(--fs-body);
}
.newsletter-form__field:focus-visible { outline: 2px solid var(--focus-ring); outline-offset: 2px; }
.newsletter__privacy { margin-top: var(--space-3); font-size: var(--fs-caption); color: var(--text-muted); }
.newsletter__status { margin-top: var(--space-4); font-size: var(--fs-caption); min-height: 1.2em; }
.newsletter__status[data-state="error"] { color: var(--color-crimson-lit); }
.newsletter__status[data-state="info"] { color: var(--text-secondary); }
.newsletter__status[data-state="success"] { color: var(--text-secondary); }
.newsletter__powered { margin-top: var(--space-3); font-size: var(--fs-caption); color: var(--text-muted); }
.newsletter__powered a { color: inherit; text-decoration: none; border-bottom: 1px solid currentColor; opacity: 0.6; }
.newsletter__powered a:hover { opacity: 1; }

/* ---- Bio (homepage condensed version) ---- */
.bio {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-12);
  align-items: center;
}
.bio__media { border: var(--border-hairline); overflow: hidden; }
.bio__media img { width: 100%; height: 100%; object-fit: cover; }
.bio__body p { color: var(--text-secondary); font-size: var(--fs-body-lg); }
@media (max-width: 900px) {
  .bio { grid-template-columns: 1fr; }
}

/* ---- Simplified homepage footer ---- */
.footer--simple .footer__inner { justify-content: space-between; align-items: center; }
.footer--simple .footer__brand { display: flex; align-items: center; gap: var(--space-2); font-family: var(--font-display); font-weight: 700; }
.footer--simple .footer__tagline { color: var(--text-muted); font-size: var(--fs-caption); margin-top: var(--space-1); }

.release-card {
  border: var(--border-hairline);
  overflow: hidden;
}
.release-card__art { aspect-ratio: 1/1; overflow: hidden; }
.release-card__art img { width: 100%; height: 100%; object-fit: cover; }
.release-card__body { padding: var(--space-4); }
.release-card__body .label { display: block; margin-bottom: var(--space-1); }
.release-card__body h3 { font-size: var(--fs-h3); margin-bottom: var(--space-2); }
.release-card__body p { color: var(--text-secondary); font-size: var(--fs-body); margin-bottom: var(--space-3); }

/* ---- Empty state ---- */
.empty-state {
  border: 1px dashed var(--border-subtle);
  padding: var(--space-8);
  color: var(--text-secondary);
}
.empty-state .label { display: block; margin-bottom: var(--space-2); color: var(--text-muted); }

/* ---- Footer ---- */
.footer {
  border-top: var(--border-hairline);
  padding-block: var(--space-12);
}
.footer__inner {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--space-8);
}
.footer__nav, .footer__social {
  display: flex;
  gap: var(--space-6);
  list-style: none;
  margin: 0; padding: 0;
  flex-wrap: wrap;
}
.footer__nav a, .footer__social a {
  text-decoration: none;
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: var(--tracking-label);
  text-transform: uppercase;
  color: var(--text-secondary);
}
.footer__nav a:hover, .footer__social a:hover { color: var(--text-primary); }
.footer__copyright {
  color: var(--text-muted);
  font-size: var(--fs-caption);
  width: 100%;
  margin-top: var(--space-8);
}
