/* ============================================================================
   afinar.app — site tokens
   Design commission return, 2026-08-06. Frames F1/F2/F3 are built from this
   file. A value in a frame that is not in this file is a bug, not a decision.

   PROVENANCE — three kinds of value live here, marked on every line:
     [SHIPPING]  transcribed from DESIGN_LANGUAGE.md §4a, itself a verbatim
                 mirror of DualTrack/Appearance.swift. Code is the source; if
                 this disagrees with Appearance.swift, the code is right.
     [BRAND]     SPEC.md §12 (name, palette, type) and §11a (record red).
     [SITE]      derived for this commission. Nothing outside the site depends
                 on these. Every one of them is stated below with its reason.

   THE ONE TRAP, from DESIGN_LANGUAGE §4a: amber changes value between skins.
   Interaction on a light ground is --amber (#8F6A16). The Console amber
   #D4A73A is 1.9:1 on paper and is declared here only so that reaching for it
   is a visible mistake. Do not lighten either amber: §4a records 4.67:1 for
   white on light amber and 3.87:1 for light amber on ivory, neither with
   margin.
   ============================================================================ */

:root {

  /* --- Ground ------------------------------------------------------------ */
  --paper:            #F7F3EB;  /* [SITE] page ground. Warm family, one step
                                   lighter and cleaner than the app's chassis:
                                   §4a says a page is paper, the machine sits
                                   on it, and they should not be the same
                                   surface. Ink on this: 14.9:1. */
  --paper-raised:     #EFEAE0;  /* [SHIPPING] panelBar/Paper. Alternate section
                                   band. The site borrows the app's own second
                                   surface rather than inventing one. */
  --paper-sunk:       #E9E3D5;  /* [SHIPPING] panelChassis/Paper — the app's
                                   ivory. Table headers, card edges: the places
                                   the page is standing in for a device. */

  /* --- Ink --------------------------------------------------------------- */
  --ink:              #1A1815;  /* [SHIPPING] labelPrimary/Paper. 13.9:1 on the
                                   app's ivory, 14.9:1 on --paper. */
  --ink-secondary:    #3A352C;  /* [SHIPPING] labelSecondary/Paper. 9.5:1. Body
                                   copy sits here, not on --ink: a page of
                                   maximum-contrast body text reads as a
                                   document, not a page. */
  --ink-tertiary:     #5C574C;  /* [SHIPPING] labelTertiary/Paper. 5.8:1 — the
                                   contrast floor. Nothing goes below this. */
  --hairline:         #C8C1AF;  /* [SHIPPING] seamWindow + keycapEdge/Paper.
                                   Structure is hairline seams, never a
                                   background-colour change (DESIGN_LANGUAGE
                                   §2, §3 zones ruling). */

  /* --- Signal — one meaning each, no new hues (DESIGN_LANGUAGE §4) -------- */
  --amber:            #8F6A16;  /* [SHIPPING] amberAction/Paper. Interaction and
                                   selection on a light ground: links, the
                                   primary action, the brand mark. */
  --amber-on:         #FBF8F1;  /* [SHIPPING] amberOn/Paper. Text ON an amber
                                   fill. 4.67:1, no margin, do not lighten. */
  --amber-console:    #D4A73A;  /* [BRAND/SHIPPING] amberAction/Console. NEVER
                                   on paper — 1.9:1. Declared so that a frame
                                   using it is visibly wrong. It is correct
                                   inside every app screenshot on the page,
                                   because displays never invert (§11a rule 1). */
  --record-red:       #B8402F;  /* [BRAND] SPEC §11a: the one hex that never
                                   moves, either skin. Recording only. */

  /* --- The deep object --------------------------------------------------- */
  --console:          #0F0E0C;  /* [SHIPPING] panelChassis/Console. The dark app
                                   window is the one deep object on the page. */
  --console-bar:      #131110;  /* [SHIPPING] panelBar/Console. */
  --console-glass:    #0C0B09;  /* [SHIPPING] display glass, both skins. */
  --console-label:    #E6E1D7;  /* [SHIPPING] labelPrimary/Console — type on a
                                   dark band. */

  /* --- Type ---------------------------------------------------------------
     DISPLAY FACE CHANGED 2026-08-06, at Albizu's direction, from a reference
     frame. This overrides SPEC §12's Bricolage Grotesque. It is a BRAND
     ruling, not a site decision: §12 needs amending or this site and the app's
     brand moments will disagree. Body and label faces are unchanged and still
     §12's.
     The reference is a closed-aperture geometric with a high x-height. Poppins
     is the closest face on Google Fonts; if the original is identified later,
     swapping it is one line here and nothing else. -------------------------- */
  --font-display:  'Recoleta', 'Fraunces', Georgia, serif;
  --display-vars:  'SOFT' 44, 'WONK' 1, 'opsz' 96;
  --font-body:     'Hanken Grotesk', 'Helvetica Neue', Helvetica, sans-serif;
  --font-mono:     'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, monospace;

  /* Ramp. Desktop values; the mobile overrides are at the foot of this file.
     Ratio is roughly 1.28, tightened at the top so the hero can be large
     without the H2s having to shout. */
  --type-hero:        70px;   --lh-hero:    1.06;  --track-hero:   -0.012em;
  --type-h2:          42px;   --lh-h2:      1.14;  --track-h2:     -0.008em;
  --type-h3:          26px;   --lh-h3:      1.20;  --track-h3:     -0.012em;
  --type-lead:        22px;   --lh-lead:    1.50;
  --type-body:        19px;   --lh-body:    1.62;
  --type-small:       16px;   --lh-small:   1.55;
  --type-label:       11px;   --lh-label:   1.00;  --track-label:   0.14em;

  --weight-display:   600;    /* Bricolage at 600. 700 reads as a poster. */
  --weight-body:      400;
  --weight-medium:    500;

  /* --- Spacing. 4px base; the only sizes that exist. --------------------- */
  --s1:   4px;   --s2:   8px;   --s3:  12px;   --s4:  16px;
  --s5:  24px;   --s6:  32px;   --s7:  48px;   --s8:  64px;
  --s9:  96px;   --s10:128px;   --s11:160px;   --s12:200px;

  /* --- Layout ------------------------------------------------------------ */
  --page:            1440px;  /* [SITE] the frame width this design is drawn at */
  --content:         1200px;  /* [SITE] 12 columns of 78px, 24px gutters */
  --measure:          660px;  /* [SITE] prose column. ~72 characters at 19px. */
  --gutter:           120px;  /* [SITE] (1440 - 1200) / 2 */
  --col-gap:           24px;
  --nav-h:             72px;

  /* --- Radii. Control radius is the app's own. --------------------------- */
  --r-control:          6px;  /* [SHIPPING] DESIGN_LANGUAGE §4: "radius 6 like
                                 every other control there." */
  --r-shot:            25px;  /* [SITE] the macOS window corner, MEASURED off
                                 13-web-score-songsterr.png: the capture's own
                                 baked corner starts 63px in at 3024 native,
                                 which is 25px at the 1200 display width. Used
                                 only to round the screen RECORDINGS, whose
                                 corners are square because they are full-screen
                                 grabs. The PNG captures already carry theirs and
                                 must never be given a second one. */
  --r-plate:            4px;  /* [SITE] direction plates */

  /* --- Elevation. One shadow. The page has one deep object; it does not
         need a scale of shadows. ---------------------------------------- */
  --shadow-object: 0 48px 88px -32px rgba(26, 24, 21, 0.34),
                   0 8px 24px -12px rgba(26, 24, 21, 0.18);

  /* --- Ink bleed ------------------------------------------------------------
     [SITE] The soft edge from the reference frame. On paper it reads as ink
     spreading very slightly into an uncoated sheet, which is why it is allowed
     here at all: it is a material effect, not a glow. Display type only. Body
     and label type stay crisp, because a blurred paragraph is a legibility
     failure and would breach §6's accessibility-is-material rule. Same hue as
     the ink, so contrast is unchanged: it thickens the stroke, it does not
     wash it. Do not raise the radius. ---------------------------------------- */
  /* WITHDRAWN with the serif. A high-contrast serif has real thick/thin
     modulation, so the faked printed edge is redundant and muddies the thins. */
  --bleed:           none;
  --bleed-light:     none;

  --dur-fade:        220ms;   /* [SITE] the only motion the brief permits
                                 outside the app captures */
  --ease:            cubic-bezier(0.2, 0, 0.2, 1);
}

/* ============================================================================
   COMPONENT SPECS — written as the rules themselves, per the commission.
   The frames use these classes. Nothing below introduces a value that is not
   a token above.
   ============================================================================ */

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink-secondary);
  font-family: var(--font-body);
  font-size: var(--type-body);
  line-height: var(--lh-body);
  font-weight: var(--weight-body);
}

/* --- Type ---------------------------------------------------------------- */

h1, h2, h3 {
  font-family: var(--font-display);
  font-variation-settings: var(--display-vars);
  font-weight: var(--weight-display);
  color: var(--ink);
  margin: 0;
  text-wrap: balance;
}
h1 { font-size: var(--type-hero); line-height: var(--lh-hero); letter-spacing: var(--track-hero); text-shadow: var(--bleed); }
h2 { font-size: var(--type-h2);   line-height: var(--lh-h2);   letter-spacing: var(--track-h2); max-width: 880px; text-shadow: var(--bleed); }
h3 { font-size: var(--type-h3);   line-height: var(--lh-h3);   letter-spacing: var(--track-h3); text-shadow: var(--bleed); }

p { margin: 0; text-wrap: pretty; }

.lead { font-size: var(--type-lead); line-height: var(--lh-lead); color: var(--ink-secondary); }
.small { font-size: var(--type-small); line-height: var(--lh-small); }

/* Mono is print on the panel: labels beside things, never inside them
   (DESIGN_LANGUAGE §2 SILKSCREEN). On the site it is confined to the tier
   table's column heads, the footer's legal row, and annotation. It is NOT an
   eyebrow: home.md's structural rulings ban eyebrows outright. */
.mono {
  font-family: var(--font-mono);
  font-size: var(--type-label);
  line-height: var(--lh-label);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--ink-tertiary);
}

/* No image may exceed its column. There was no such rule, which is how a
   1440px hero survived on a 390px phone (2026-08-22). */
img { max-width: 100%; }

a { color: var(--amber); text-decoration: none; }
a:hover { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }

/* --- Layout -------------------------------------------------------------- */

/* THE FRAME IS FLUID (2026-08-22). It was two fixed widths — 1440px above
   480px and 390px below — with nothing in between, so every viewport from
   481px to 1439px was handed a 1440px page and `overflow: hidden` ate the
   difference: 160px on a 13" MacBook, 606px on an iPad in portrait, 959px at
   481px where the page was twice the viewport. The width is now a MAXIMUM and
   the gutter carries the shrink, so the design is pixel-identical at 1440 and
   fluid below it. `--content` stays the 12-column measure the design is drawn
   to; the wrap's max-width is that measure plus its two gutters. */
.page { width: 100%; max-width: var(--page); margin: 0 auto; background: var(--paper); overflow: hidden; }
.wrap { width: 100%; max-width: calc(var(--content) + var(--gutter) * 2); margin: 0 auto; padding-inline: var(--gutter); }
.measure { max-width: var(--measure); }

/* Section anatomy: 160px of air above and below, 96px for a deliberate short
   beat, a hairline only where two ideas need separating. Sections are told
   apart by air and by ground, never by a box. */
.section      { padding: var(--s11) 0; }
.section--short { padding: var(--s9) 0; }
.section--raised { background: var(--paper-raised); }
.section + .section { border-top: 0; }
.rule { height: 1px; background: var(--hairline); border: 0; margin: 0; }

/* Heading + prose block. The heading is the benefit; the paragraph follows at
   the prose measure, never the full column. */
.block > h2 + p,
.block > h2 + .lead { margin-top: var(--s5); }
.block > p + p { margin-top: var(--s4); }

/* --- Nav ----------------------------------------------------------------- */

.nav {
  height: var(--nav-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-bottom: 1px solid var(--hairline);
}
.nav__mark {
  display: inline-flex;
  align-items: center;
  gap: calc(var(--s3) + var(--s1) / 2);
  font-family: var(--font-display);
  font-weight: var(--weight-display);
  font-size: 30px;
  letter-spacing: -0.01em;
  color: var(--ink);
  font-variation-settings: var(--display-vars);
}
/* The tile: 36px beside a 30px wordmark (ruled 2026-09-25; was 22px / 21px). */
.nav__mark img { display: block; width: calc(var(--s6) + var(--s1)); height: calc(var(--s6) + var(--s1)); }
.nav__links { display: flex; align-items: center; gap: var(--s6); }
.nav__link {
  font-size: var(--type-small);
  color: var(--ink-secondary);
  display: flex;
  align-items: center;
  gap: var(--s2);
}
.nav__link:hover { color: var(--ink); text-decoration: none; }

/* Features menu. CSS-only so it works in a plain static page with no script.
   The panel is the five feature pages, in the order nav-footer.md fixes.

   THE HOVER REGION IS ONE CONTINUOUS AREA (fixed 2026-08-20). It used to be
   two: the panel sat --s3 below the trigger on its own margin, and a margin is
   not hoverable by anything. Aiming at an item meant crossing 12px of dead
   floor, :hover went false on the way down, and the menu shut before it could
   be reached — reported live by Albizu. The offset is now padding on
   .nav__menu, which IS the hover parent, with a matching negative margin so
   the strip's layout is unchanged and the panel lands on the same pixel.
   Nothing here may reintroduce a margin, a gap, or a transform between the
   trigger and the panel. */
.nav__menu {
  position: relative;
  display: flex;
  align-items: center;
  padding: var(--s3) 0;
  margin: calc(var(--s3) * -1) 0;
}
.nav__menu > .nav__link { cursor: default; }
.nav__panel {
  position: absolute;
  top: 100%;
  left: calc(var(--s5) * -1);
  min-width: 210px;
  background: var(--paper);
  border: 1px solid var(--hairline);
  border-radius: var(--r-control);
  box-shadow: 0 20px 40px -16px rgba(26, 24, 21, 0.24);
  padding: var(--s3) 0;
  display: flex;
  flex-direction: column;
  z-index: 10;
  /* Closed. It opens instantly and closes on a 180ms grace, so a pointer that
     clips a corner on its way to an item does not lose the menu. Re-entering
     inside the grace cancels it outright — the open rule's 0s delays win the
     moment :hover is true again. visibility, not display, because display
     cannot be waited on; hidden also keeps the links out of the tab order,
     which is what makes :focus-within open it rather than fight it. */
  opacity: 0;
  visibility: hidden;
  transition: opacity 140ms var(--ease) 180ms, visibility 0s linear 320ms;
}
.nav__menu:hover .nav__panel,
.nav__menu:focus-within .nav__panel {
  opacity: 1;
  visibility: visible;
  transition: opacity 90ms var(--ease) 0s, visibility 0s linear 0s;
}
@media (prefers-reduced-motion: reduce) {
  .nav__panel,
  .nav__menu:hover .nav__panel,
  .nav__menu:focus-within .nav__panel { transition-duration: 0s; }
}
.nav__panel a {
  font-size: var(--type-small);
  color: var(--ink-secondary);
  padding: var(--s2) var(--s5);
}
.nav__panel a:hover { color: var(--ink); background: var(--paper-raised); text-decoration: none; }

/* --- Format picker -------------------------------------------------------
   A stepped viewer, not a carousel: nothing advances on its own, and every
   option is addressable so a reader goes straight to their own case instead
   of waiting for it. Radio + :checked so it works in a static page with no
   script. The stage is 800px because below ~560 the app's silkscreen stops
   being legible and the capture becomes decoration.
   ------------------------------------------------------------------------- */

.picker { margin-top: var(--s8); }
.picker__radio { position: absolute; opacity: 0; pointer-events: none; }
.picker__body { display: grid; grid-template-columns: 340px 1fr; gap: var(--s9); align-items: start; }
.picker__rail { display: flex; flex-direction: column; }
.picker__opt {
  display: block;
  font-family: var(--font-body);
  font-size: var(--type-lead);
  line-height: 1.3;
  color: var(--ink-tertiary);
  padding: var(--s4) 0;
  border-bottom: 1px solid var(--hairline);
  cursor: pointer;
  transition: color var(--dur-fade) var(--ease);
}
.picker__opt:first-child { border-top: 1px solid var(--hairline); }
.picker__opt:hover { color: var(--ink-secondary); }
.picker__desc { display: none; font-size: var(--type-small); line-height: 1.6; color: var(--ink-secondary); padding: var(--s4) 0 0; }
.picker__panel { display: none; }
.picker__stage figure { margin: 0; }
/* Captures come in two window ratios (3024×1898 and 3164×2038). Pin the box to
   the taller one and anchor the top, so every window's top and side edges land
   in the same place as tabs change; only the bottom edge varies, by 12px, on
   the three older captures. */
.picker__stage figure > a { display: block; aspect-ratio: 3164 / 2038; }
.picker__stage figure > a > img { width: 100%; height: 100%; object-fit: contain; object-position: top; }
.picker__figcap { font-size: var(--type-small); color: var(--ink-tertiary); margin-top: var(--s4); display: flex; align-items: center; gap: var(--s3); }
.picker__zoom { color: var(--amber); }

.picker__radio:focus-visible + .picker__body .picker__opt { outline: none; }

#fmt-1:checked ~ .picker__body [for="fmt-1"],
#fmt-2:checked ~ .picker__body [for="fmt-2"],
#fmt-3:checked ~ .picker__body [for="fmt-3"],
#fmt-4:checked ~ .picker__body [for="fmt-4"],
#fmt-5:checked ~ .picker__body [for="fmt-5"],
#fmt-6:checked ~ .picker__body [for="fmt-6"] { color: var(--ink); font-weight: var(--weight-medium); }

#fmt-1:checked ~ .picker__body .picker__desc--1,
#fmt-2:checked ~ .picker__body .picker__desc--2,
#fmt-3:checked ~ .picker__body .picker__desc--3,
#fmt-4:checked ~ .picker__body .picker__desc--4,
#fmt-5:checked ~ .picker__body .picker__desc--5,
#fmt-6:checked ~ .picker__body .picker__desc--6,
#fmt-1:checked ~ .picker__body .picker__panel--1,
#fmt-2:checked ~ .picker__body .picker__panel--2,
#fmt-3:checked ~ .picker__body .picker__panel--3,
#fmt-4:checked ~ .picker__body .picker__panel--4,
#fmt-5:checked ~ .picker__body .picker__panel--5,
#fmt-6:checked ~ .picker__body .picker__panel--6 { display: block; }

/* Enlarge. :target overlay, so it needs no script and closing is a link. */
.lightbox {
  position: fixed;
  inset: 0;
  background: rgba(26, 24, 21, 0.88);
  display: none;
  align-items: center;
  justify-content: center;
  padding: var(--s7);
  z-index: 100;
}
.lightbox:target { display: flex; }
.lightbox__dismiss { position: absolute; inset: 0; }
.lightbox img { position: relative; max-width: 100%; max-height: 100%; height: auto; border-radius: var(--r-shot); }

/* --- Buttons. One primary action per view; everything else is a link.
       The keycap: flat rounded rect, 1px edge, pressed = darken + 1px down
       (DESIGN_LANGUAGE §3). ------------------------------------------------ */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-body);
  font-size: var(--type-small);
  font-weight: var(--weight-medium);
  border-radius: var(--r-control);
  border: 1px solid transparent;
  padding: var(--s3) var(--s5);
  white-space: nowrap;
  cursor: pointer;
  transition: background var(--dur-fade) var(--ease), transform var(--dur-fade) var(--ease);
}
/* The primary action is INK, not amber. --amber (#8F6A16) is shipping code and
   cannot be lightened — DESIGN_LANGUAGE §4a records white-on-amber at 4.67:1
   with no margin — but at button size that low-chroma gold reads olive. Small
   amber areas (links, the mark, table ticks) are fine; a large flat fill is
   not. Ink is 14.9:1 on paper, matches the one deep object on the page, and
   hands amber back to the hover state so it keeps its meaning. */
.btn--primary { background: var(--ink); color: var(--paper); }
.btn--primary:hover { background: var(--amber); color: var(--amber-on); text-decoration: none; }
.btn--primary:active { transform: translateY(1px); }
.btn--lg { font-size: var(--type-lead); padding: var(--s4) var(--s7); }
.btn--quiet { background: transparent; color: var(--ink); border-color: var(--hairline); }

/* The state a control is in when the thing behind it does not exist yet.
   RULED 2026-08-20 (Albizu): every download CTA reads `Coming Soon` until
   there is a build. Same keycap, same size, same place — no fill, hairline
   edge, tertiary ink at 5.8:1, and no hover or press, because nothing
   happens. It is the shape of the action with the action taken out.
   Carried on a <span role="button" aria-disabled="true">: not a link, not
   focusable, and never href="#". This is NOT the dashed-amber placeholder
   idiom — that marked things that must not ship; this one ships. */
.btn--soon {
  background: none;
  color: var(--ink-tertiary);
  border-color: var(--hairline);
  cursor: default;
}

/* --- Screenshot framing --------------------------------------------------
   Captures are 3024x1898 window grabs with their own rounded corners and
   transparent corner pixels. Do NOT clip them or add a border: that draws a
   second corner inside the real one. Elevation is a drop-shadow filter, which
   follows the alpha, not a box-shadow, which would square it off.
   Display width 1200 (full column) or 840 (inset). Never smaller than 560 —
   below that the rail's silkscreen stops being legible and the shot is
   decoration. -------------------------------------------------------------- */

.shot { display: block; width: 100%; height: auto; filter: drop-shadow(0 48px 68px rgba(26, 24, 21, 0.30)); }
.shot--inset { width: 840px; }

/* --- Direction plate — DELIBERATELY ABSENT FROM THE SHIPPING STYLESHEET -----
   The dashed-amber `.plate` is the design return's ANNOTATION idiom: image
   direction and notes-to-the-builder, carried inside the frame so copy and
   image were chosen together (BRIEF-marketing-handoff §7). Its own header
   says it does not ship — and on 2026-08-20 five of them shipped anyway,
   transcribed straight out of the frames onto /auto-scroll/, /changelog/,
   /press/, /help/ and /help/auto-scroll/. A journalist on /press/ read
   `ASSET ZIP · DOES NOT EXIST YET`.

   The rules live on in docs/design-returns/tokens.css, which is where the
   frames load their CSS from and where the annotation belongs. They are gone
   from here so this stylesheet CANNOT draw one: if a plate is ever
   transcribed again it lands unstyled and obvious instead of arriving
   looking deliberate. Do not restore them. Delete the .plate element and
   drop the real asset in its place, exactly as the frame headers instruct.
   -------------------------------------------------------------------- */

/* --- Tier table. The most-quoted table on a product site (rebuild §5), so it
       is real semantic markup, left-aligned, no zebra, hairlines only. ----- */

.tier-table { width: 100%; border-collapse: collapse; font-size: var(--type-small); }
.tier-table th, .tier-table td { text-align: left; padding: var(--s4) var(--s5); border-bottom: 1px solid var(--hairline); }
.tier-table thead th { background: var(--paper-sunk); color: var(--ink); font-family: var(--font-mono); font-size: var(--type-label); letter-spacing: var(--track-label); text-transform: uppercase; font-weight: var(--weight-medium); }
.tier-table td:nth-child(2), .tier-table td:nth-child(3),
.tier-table th:nth-child(2), .tier-table th:nth-child(3) { width: 128px; text-align: center; }
.tier-table .yes { color: var(--amber); }
.tier-table .no  { color: var(--ink-tertiary); }

/* --- Footer -------------------------------------------------------------- */

.footer { background: var(--paper-raised); border-top: 1px solid var(--hairline); padding: var(--s9) 0 var(--s7); }
.footer__cols { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--s7); }
.footer__col { display: flex; flex-direction: column; gap: var(--s3); }
.footer__head { font-family: var(--font-mono); font-size: var(--type-label); letter-spacing: var(--track-label); text-transform: uppercase; color: var(--ink-tertiary); margin-bottom: var(--s2); }
.footer a { color: var(--ink-secondary); font-size: var(--type-small); }
.footer a:hover { color: var(--ink); }
.footer__legal { display: flex; justify-content: space-between; align-items: baseline; margin-top: var(--s8); padding-top: var(--s5); border-top: 1px solid var(--hairline); color: var(--ink-tertiary); font-size: var(--type-small); }

/* ============================================================================
   MOBILE — 390. The strip in F3-mobile.png is drawn at these values.
   ============================================================================ */

/* THE GUTTER LADDER (2026-08-22). The only thing that changes between 1440
   and 480 is how much air sits either side of the content. Above 1280 the
   design is untouched. Each step keeps the frame narrower than the viewport,
   which is what the old two-width system could not do. */
@media (max-width: 1280px) { :root { --gutter: 72px; } }
@media (max-width: 1024px) { :root { --gutter: 48px; } }
@media (max-width:  768px) { :root { --gutter: 32px; } }

@media (max-width: 480px) {
  :root {
    --type-hero:  38px;  --track-hero: -0.018em;
    --type-h2:    29px;
    --type-h3:    22px;
    --type-lead:  19px;
    --type-body:  17px;
    --gutter:     20px;
    --nav-h:      56px;
  }
  .section { padding: var(--s8) 0; }
  .section--short { padding: var(--s7) 0; }
  .footer__cols { grid-template-columns: repeat(2, 1fr); gap: var(--s6); }
}

/* THE WIDEST GRID COLLAPSES EARLY (2026-08-22). `760px 1fr` cannot wait for
   the 900px breakpoint the other grids use. With a 96px gap it needs
   760 + 96 + a readable second column, and the arithmetic is unforgiving:
   the second column is only (viewport - 1000) through the 72px-gutter band, so
   it is 87px at 901px wide and does not reach 200px until about 1200. An 87px
   prose column is broken even at the widths where it does not technically
   overflow — which is exactly how it escaped the first sweep, because the grid
   CONTAINER stayed in bounds while its starved second column was pushed out
   past the gutter. Collapsed below 1200, it is one full-width column instead. */
@media (max-width: 1200px) {
  [style*="grid-template-columns: 760px 1fr"] { grid-template-columns: 1fr !important; }
}

/* THE INLINE GRIDS COLLAPSE (2026-08-22). The markup carries 76 inline
   `grid-template-columns`, 63 of them with a FIXED pixel column — up to
   `760px 1fr` — so a narrow viewport could not shrink them and the frame's
   `overflow: hidden` simply cut them off. An inline declaration can only be
   beaten by `!important`; these selectors name the exact values they correct,
   so the whole block can be deleted the day those inline styles become
   classes. Nothing here changes the design above 900px.

   `20px 1fr` is deliberately ABSENT: it is a bullet marker beside its text,
   and it must stay side by side at every width. */
@media (max-width: 900px) {
  [style*="grid-template-columns: 400px 1fr"],
  [style*="grid-template-columns: 380px 1fr"],
  [style*="grid-template-columns: 280px 1fr"],
  [style*="grid-template-columns: 240px 1fr"],
  [style*="grid-template-columns: 64px 340px 1fr"],
  [style*="grid-template-columns: 1fr 440px"],
  [style*="grid-template-columns: 1fr 1px 1fr"] { grid-template-columns: 1fr !important; }

  /* Wide bands halve before they stack, so a tablet keeps a sense of columns. */
  [style*="grid-template-columns: repeat(4, 1fr)"],
  [style*="grid-template-columns: repeat(3, 1fr)"] { grid-template-columns: repeat(2, 1fr) !important; }

  /* The footer went straight from four columns to two at 480, so everything
     between was four columns of link text that cannot shrink below their own
     words — the last thing overflowing anywhere on the site. */
  .footer__cols { grid-template-columns: repeat(2, 1fr); }
  .footer__legal { flex-wrap: wrap; gap: var(--s3); }

  /* A flex row that cannot fit should fold, not push the page sideways. No
     inline style declares flex-wrap anywhere, so this needs no override
     weight, and it is inert wherever the row already fits. It is what stopped
     the iPad page's hero CTA — a `flex: none` button beside a paragraph —
     shoving that paragraph off a 360px Android. */
  [style*="display: flex"] { flex-wrap: wrap; }

  /* A comparison table has to keep its columns side by side to BE a
     comparison, so stacking it would destroy the thing it is for. It scrolls
     inside its own column instead, and the page itself never scrolls. */
  .tier-table { display: block; overflow-x: auto; max-width: 100%; }
}

@media (max-width: 600px) {
  [style*="grid-template-columns: repeat(4, 1fr)"],
  [style*="grid-template-columns: repeat(3, 1fr)"],
  [style*="grid-template-columns: repeat(2, 1fr)"],
  [style*="grid-template-columns: 1fr 1fr"] { grid-template-columns: 1fr !important; }
}

/* THE PICKER BECOMES AN ACCORDION ON NARROW SCREENS (2026-08-22, Albizu's
   ruling, after mammouth.ai). Collapsing the two-column picker to one column
   stacked the whole rail above the single stage, which left the screenshot
   below all six options — off the bottom of the phone, effectively invisible.
   His call: the picture belongs to the item you tapped, up in the list, not
   parked underneath it.

   No markup changed and no script added. The rail and the stage are given
   `display: contents`, which drops their boxes so their children become items
   of `.picker__body` directly, and `order` then interleaves each option with
   its own description and its own capture. The radios already make it
   one-open-at-a-time, and the existing `:checked` rules already reveal the
   right description and panel — this only moves them next to each other.

   `display: contents` removes the BOX, not the element, so the descendant
   selectors above (`.picker__stage figure > a`, which pins the capture's
   aspect ratio) keep matching. */
@media (max-width: 900px) {
  /* `align-items: stretch` is NOT redundant: the desktop rule sets
     `align-items: start` for the two-column grid, and it carries into this
     flex context, where it makes every row shrink to its own text — which
     showed up as hairlines of six different lengths. */
  .picker__body { display: flex; flex-direction: column; gap: 0; align-items: stretch; }
  .picker__rail, .picker__stage { display: contents; }

  .picker__body [for="fmt-1"] { order: 1; }
  .picker__desc--1           { order: 2; }
  .picker__panel--1          { order: 3; }
  .picker__body [for="fmt-2"] { order: 4; }
  .picker__desc--2           { order: 5; }
  .picker__panel--2          { order: 6; }
  .picker__body [for="fmt-3"] { order: 7; }
  .picker__desc--3           { order: 8; }
  .picker__panel--3          { order: 9; }
  .picker__body [for="fmt-4"] { order: 10; }
  .picker__desc--4           { order: 11; }
  .picker__panel--4          { order: 12; }
  .picker__body [for="fmt-5"] { order: 13; }
  .picker__desc--5           { order: 14; }
  .picker__panel--5          { order: 15; }
  .picker__body [for="fmt-6"] { order: 16; }
  .picker__desc--6           { order: 17; }
  .picker__panel--6          { order: 18; }

  /* The row now says it is a row: title left, chevron right, and the chevron
     turns down when the item is open — the affordance the desktop layout did
     not need, because there the stage was already visible beside the list. */
  .picker__opt { display: flex; align-items: center; justify-content: space-between; gap: var(--s4); }
  .picker__opt::after {
    content: "";
    flex: none;
    width: 7px; height: 7px;
    border-right: 1.5px solid currentColor;
    border-bottom: 1.5px solid currentColor;
    transform: rotate(-45deg);
    transition: transform var(--dur-fade) var(--ease);
  }

  .picker__panel { padding-bottom: var(--s6); }
  .picker__desc { padding-bottom: var(--s4); }

  /* The caption and its zoom link are a flex row that cannot fit side by side
     in a phone column, so they stack instead of squeezing into two ragged
     halves. */
  .picker__figcap { flex-wrap: wrap; gap: var(--s2) var(--s3); }
}

/* Open: the chevron points down. Kept out of the media query's ordering block
   for legibility, but scoped to the same width — on desktop there is no
   chevron to turn. */
@media (max-width: 900px) {
  #fmt-1:checked ~ .picker__body [for="fmt-1"]::after,
  #fmt-2:checked ~ .picker__body [for="fmt-2"]::after,
  #fmt-3:checked ~ .picker__body [for="fmt-3"]::after,
  #fmt-4:checked ~ .picker__body [for="fmt-4"]::after,
  #fmt-5:checked ~ .picker__body [for="fmt-5"]::after,
  #fmt-6:checked ~ .picker__body [for="fmt-6"]::after { transform: rotate(45deg); }
}

/* THE NAV WRAPS (2026-08-22, Albizu's ruling). Its link row is 500px of fixed
   content, so below roughly 700px it could not sit beside the wordmark and the
   frame's overflow rule ate it — the site had NO mobile navigation at all, on
   any page. The ruling was wrap, not hide: the wordmark takes the first row,
   the links flow onto the next, and every destination stays visible and
   tappable. No drawer, no checkbox hack, no script, and nothing put behind an
   affordance the reader has to learn.

   The Features menu is untouched on purpose. Its trigger and panel must stay
   one continuous hover region — see the rule above it — and :focus-within is
   what opens it for a tap, so it works on a phone without becoming a second
   mechanism. */
@media (max-width: 760px) {
  .nav {
    height: auto;
    flex-wrap: wrap;
    align-items: flex-start;
    row-gap: var(--s4);
    padding-block: var(--s4);
  }
  .nav__mark { flex: 0 0 100%; }
  .nav__links { flex-wrap: wrap; row-gap: var(--s4); column-gap: var(--s6); }
}
