@charset "utf-8";
/* ═══════════════════════════════════════════════════════════════════════════
   AMERICAN MOVERS OF AMERICA — marketing homepage
   Concept: THE OPEN DOOR. "Nothing loads behind a closed door."

   🔴 HOUSE LAW ENFORCED IN THIS FILE
      · Ground is MID-TONE #4B545E  (Y = 0.1215, CIELAB L* = 41.45, inside the
        client's L* 40–62 band). It is painted explicitly on <body>. There is
        no prefers-color-scheme block and no [data-theme] block: one look.
      · NO BOXES around content. Every separation is TYPE, a HAIRLINE, or SPACE.
        border-radius / box-shadow appear ONLY on: the UFO medallion (a logo
        mark), buttons + inputs + the persistent tab (controls), the light band
        on the door (a light source), and the pzft bar (a page-wide band).
      · Every horizontal rule on this page is a DOOR SLAT. That is the motif.
      · No pure #ffffff on any glyph. Warm off-white ink only.
      · Fonts are self-hosted. No Google Fonts, no CDN, no preconnect.
      · No html{scroll-behavior:smooth} — it fights Lenis.
      · No body{overflow-x:clip} — it breaks ScrollTrigger pin measurement.
      · No backdrop-filter anywhere — it breaks position:fixed children, which
        is exactly what the pinned door creates.
   ═══════════════════════════════════════════════════════════════════════════ */


/* ── FONTS ────────────────────────────────────────────────────────────────
   Four files, four requests.
   Chakra Petch: three genuinely different static cuts on disk. There is NO 400
   cut — never request it or the browser synthesises a fake light weight.
   JetBrains Mono: jetbrains-mono-400/-500/-600.woff2 on disk are BYTE-IDENTICAL
   (md5 570751c5f8b418972c1976160ba6ed85, 31,340 B each) — three copies of one
   VARIABLE font, fvar wght 400–800. Declared ONCE with font-weight:400 800; the
   other two files are deliberately never referenced. Three declarations would
   pull the same 31KB three times for one typeface.
   The unicode-range covers U+00B7 (the · separator) and U+2000-206F (the ’ in
   "doesn't"). Both are load-bearing for this build's copy.
   ────────────────────────────────────────────────────────────────────────── */
@font-face{
  font-family:'Chakra Petch'; font-style:normal; font-weight:500; font-display:swap;
  src:url('assets/fonts/chakra-petch-500.woff2?v=1') format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:'Chakra Petch'; font-style:normal; font-weight:600; font-display:swap;
  src:url('assets/fonts/chakra-petch-600.woff2?v=1') format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:'Chakra Petch'; font-style:normal; font-weight:700; font-display:swap;
  src:url('assets/fonts/chakra-petch-700.woff2?v=1') format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:'JetBrains Mono'; font-style:normal; font-weight:400 800; font-display:swap;
  src:url('assets/fonts/jetbrains-mono-400.woff2?v=1') format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}


/* ── TOKENS ───────────────────────────────────────────────────────────────
   Contrast COMPUTED with the WCAG 2.x relative-luminance formula, not guessed.
   ON --ground #4B545E (L* 41.45):
     --ink      #E8CFA6  5.34:1  AA body
     --ink-dim  #DCC5A0  4.53:1  AA body
     --accent-txt #FADFA2 4.71:1 AA body — the gold tint licensed for SMALL text
     --accent-2 #7EEFF2  4.52:1  AA body — links
     --accent   #F0C25A  3.67:1  large text (≥18.66px bold) + non-text ONLY
     --hairline #909BA8  2.17:1  DECORATIVE RULE ONLY, never carries a glyph
   ON --ground-2 #3A424B (L* 31.06): ink 7.84 · ink-dim 6.65 · gold 5.38 · cyan 6.64
   ON --ground-3 #12161B (L*  7.06): ink 15.83 · gold 10.87 · cyan 13.42
   AAA (7:1) is MATHEMATICALLY IMPOSSIBLE on this ground — pure white itself only
   reaches 6.12:1. We target AA and say so on accessibility.html.
   ────────────────────────────────────────────────────────────────────────── */
:root{
  --ground:#4B545E; --ground-2:#3A424B; --ground-3:#12161B; --pzft-bar:#0D0D0D;
  --scrim:#232A32;
  --ink:#E8CFA6; --ink-dim:#DCC5A0;
  --hairline:#909BA8; --hairline-dn:#3D4650;
  --accent:#F0C25A; --accent-txt:#FADFA2;
  --accent-2:#7EEFF2; --accent-2-hi:#A6F3F5;
  /* ROLE COLOURS — each element gets its OWN colour so the eye has somewhere to go.
     brand  #A6F3F5 cyan-lt  6.14:1  the wordmark, the eyebrow — the cool voice
     ink    #E8CFA6 sand     5.10:1  headlines — the warm voice that leads
     dim    #DCC5A0 tan      4.59:1  body copy, recedes
     gold   #FADFA2 gold-txt 5.91:1  markers + active states only               */
  --brand:#A6F3F5; --brand-dim:#7EEFF2;
  --row-hover:#5E6976;
  --grad:linear-gradient(100deg,#00eff0,#8040f0 48%,#d000f0);
  --ease:cubic-bezier(.22,1,.36,1);
  --s1:4px; --s2:8px; --s3:14px; --s4:22px; --s5:32px; --s6:48px; --s7:68px;

  --display:'Chakra Petch', ui-monospace, 'SF Mono', Menlo, sans-serif;
  --mono:'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace;
  --sans:-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;

  /* Type scale. Every value verified at 390 / 768 / 1024 / 1440. */
  --fs-h1:clamp(2.45rem, 1.60rem + 3.60vw, 4.60rem);   /* 39.6 · 53.2 · 62.5 · 73.6 */
  --fs-h2:clamp(1.85rem, 1.15rem + 2.90vw, 3.10rem);   /* 29.7 · 40.7 · 48.1 · 49.6 */
  --fs-h3:clamp(1.15rem, 0.95rem + 0.85vw, 1.55rem);   /* 18.5 · 21.7 · 23.9 · 24.8 */
  --fs-lead:clamp(1.06rem, 0.95rem + 0.50vw, 1.32rem); /* 17.2 · 19.0 · 20.3 · 21.1 */
  --fs-body:clamp(1.00rem, 0.94rem + 0.28vw, 1.125rem);/* 16.1 · 17.2 · 17.9 · 18.0 */
  --fs-small:clamp(0.875rem, 0.85rem + 0.12vw, 0.95rem);
  --fs-label:clamp(0.76rem, 0.72rem + 0.16vw, 0.875rem);
  --fs-data:clamp(0.875rem, 0.85rem + 0.14vw, 1.00rem);
  --fs-marker:clamp(1.20rem, 0.95rem + 0.95vw, 1.55rem);

  --navh:64px;
  --wrap:1180px;
}

/* ── RESET ────────────────────────────────────────────────────────────────── */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;max-width:100%}
/* 🔴 NO scroll-behavior:smooth — Lenis owns the scroll. Two engines = rubber band. */
body{
  margin:0; max-width:100%;
  background:var(--ground);           /* 🔴 THE MID-TONE GROUND, painted explicitly */
  color:var(--ink);
  font:400 var(--fs-body)/1.58 var(--sans);
  -webkit-font-smoothing:antialiased; -moz-osx-font-smoothing:grayscale;
  text-rendering:optimizeLegibility;
  hyphens:none;
}
/* 🔴 height:auto is NOT optional. The <img> tags carry width/height attributes so
   they reserve space while loading; without height:auto the WIDTH scales to the
   container while the HEIGHT stays at the attribute value. Verified rig bug. */
img{max-width:100%;height:auto;display:block}
/* 🔴 THE TWO DRIFT IMAGES MUST ESCAPE THE RESET. Both are declared width:132% — the
   lateral travel budget for the fx27 drift — and the max-width:100% above silently
   clamped them back to the viewport. Measured: .strip img computed 1440px instead of
   1901px at a 1440 viewport, so fx.js's x=(vw-iw)/2 evaluated to 0 and then ADDED up to
   +194px of drift, sliding the photo off its own host and leaving a 100–148px slab of
   bare plate down the left edge at every scroll position. The hero had the identical
   bug and was only saved by the opaque scrim happening to cover the hole. */
.hero-media img,.strip img{max-width:none}
svg{display:block}
a{color:inherit}
button{font:inherit;color:inherit}
h1,h2,h3,h4,p,figure,ul,ol,dl{margin:0}
ul,ol{padding:0;list-style:none}
table{border-collapse:collapse}
::selection{background:var(--accent);color:var(--ground-3)}
/* .qform is display:grid, which would otherwise beat the UA's [hidden] rule */
[hidden]{display:none!important}

:focus-visible{outline:2px solid var(--accent);outline-offset:2px}  /* 3.67:1 — clears WCAG 2.4.11 */
:focus:not(:focus-visible){outline:none}

.vh{position:absolute!important;width:1px;height:1px;margin:-1px;padding:0;
  overflow:hidden;clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}

.skip{position:absolute;left:var(--s4);top:-100px;z-index:200;
  background:var(--accent);color:var(--ground-3);
  font:600 var(--fs-label)/1.1 var(--mono);letter-spacing:.12em;text-transform:uppercase;
  padding:14px 18px;text-decoration:none;transition:top .18s var(--ease)}
.skip:focus{top:12px}

.wrap{width:100%;max-width:var(--wrap);margin-inline:auto;
  padding-inline:clamp(18px,4vw,40px)}

/* ── GRAIN — MANDATORY, NOT DECORATION ────────────────────────────────────
   The eye compresses tonal difference in dark values and resolves it sharply in
   MID values, so an 8-bit gradient that is perfectly smooth on #0a0d12 will
   visibly BAND on #4B545E. Every scrim, wipe, light band and vignette on this
   build sits under this layer. It does not move, it is load-bearing for colour
   fidelity, and it ships regardless of prefers-reduced-motion.
   Tile is an inline feTurbulence data: URI — zero external requests.
   ────────────────────────────────────────────────────────────────────────── */
.grain{
  position:fixed;inset:0;z-index:6;pointer-events:none;
  opacity:.04;mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='g' x='0' y='0' width='100%25' height='100%25'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23g)'/%3E%3C/svg%3E");
  background-size:140px 140px;
}
@supports not (mix-blend-mode:overlay){ .grain{opacity:.03} }

/* ── TYPE ROLES ───────────────────────────────────────────────────────────── */
h1,.h1{font:700 var(--fs-h1)/0.98 var(--display);letter-spacing:-.015em;
  max-width:15ch;text-wrap:balance}
h2,.h2{font:700 var(--fs-h2)/1.02 var(--display);letter-spacing:-.010em;
  max-width:20ch;text-wrap:balance}
h3,.h3{font:600 var(--fs-h3)/1.20 var(--display);letter-spacing:0;
  max-width:28ch;text-wrap:balance}

.lead{font:500 var(--fs-lead)/1.50 var(--display);max-width:46ch;color:var(--ink-dim);
  text-wrap:pretty}
p{max-width:64ch;text-wrap:pretty}
.small{font-size:var(--fs-small);line-height:1.55;max-width:58ch;color:var(--ink-dim)}
.label{font:600 var(--fs-label)/1.10 var(--mono);letter-spacing:.20em;
  text-transform:uppercase;color:var(--brand)}   /* cool voice — never the same as a headline */
.data{font:500 var(--fs-data)/1.45 var(--mono);font-variant-numeric:tabular-nums;color:var(--ink)}
/* 🔴 GOLD GLYPH RULE, corrected 2026-08-13. WCAG large text is >=24px, OR >=18.66px AND
   weight >=700. Weight 600 does NOT qualify, so --accent #F0C25A (3.67:1 on the ground)
   is illegal on every marker at every viewport — the design system's claim that "19.0px
   at weight 600 clears it" is arithmetically wrong and was measured failing at 390 and 768.
   Every gold GLYPH under 24px therefore takes --accent-txt #FADFA2 (4.71:1, AA body),
   which is the tint the token block already licenses for small text. Gold keeps every
   NON-TEXT job it had: fills, rules, ticks, the dotted sample underline, the focus ring —
   all of which clear the 3:1 non-text floor at 3.67:1. */
.marker{font:600 var(--fs-marker)/1.00 var(--mono);color:var(--accent-txt)}

/* Every headline line box gets clipped — required by the cascade, and it is what
   stops the skew bleed from creating a horizontal scrollbar. */
.split-line{display:block;overflow:hidden;padding-bottom:.06em}
/* .split-word is what stops the line breaker from splitting a WORD between two
   character boxes. Without it the hero reads "The price do / esn't move." */
.split-word{display:inline-block;white-space:nowrap}
.split-char{display:inline-block;will-change:transform,opacity}

/* ── HAIRLINES = DOOR SLATS ───────────────────────────────────────────────── */
.rule{border:0;border-top:1px solid var(--hairline);margin:var(--s3) 0 0;width:100%}
.rule-dn{border:0;border-top:1px solid var(--hairline-dn);margin:0;width:100%}

/* ── SECTION SHELL ────────────────────────────────────────────────────────── */
section{position:relative;scroll-margin-top:calc(var(--navh) + 8px)}
.sec{padding-block:clamp(38px,5.4vh,58px)}
.sechead{margin-bottom:var(--s5)}
.sechead .top{display:flex;align-items:baseline;gap:var(--s4);flex-wrap:wrap}
.sechead .rule{margin-top:var(--s3)}
.sechead h2{margin-top:var(--s4)}
.sechead .lead{margin-top:var(--s4)}

/* Full-bleed plates. The wipe is driven by fx.js; the defaults below are the
   FINAL state, so with JS blocked the page still reads correctly. */
.plate-2{background:var(--ground-2)}
.plate-3{background:var(--ground-3)}
.wipe{--wl:0vh;--wr:0vh;margin-top:-6vh;padding-top:calc(6vh + clamp(38px,5.4vh,58px));
  clip-path:polygon(0 var(--wl),100% var(--wr),100% 100%,0 100%)}
.wipe-f{--wl:0vh;--wr:0vh;margin-top:-6vh;padding-top:6vh;
  clip-path:polygon(0 var(--wl),100% var(--wr),100% 100%,0 100%)}

/* ── CONTROLS ─────────────────────────────────────────────────────────────
   Buttons, inputs and nav controls MAY have shape — they are controls, not
   content. This is the ONLY licensed use of border-radius on the page.
   ────────────────────────────────────────────────────────────────────────── */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:10px;
  font:600 1rem/1.20 var(--mono);letter-spacing:.12em;text-transform:uppercase;
  min-height:48px;padding:14px 26px;border:0;border-radius:999px;
  background:var(--accent);color:var(--ground-3);          /* 10.87:1 */
  text-decoration:none;cursor:pointer;position:relative;overflow:hidden;
  transition:background-color .18s var(--ease),transform .18s var(--ease)}
.btn:hover{background:#F7D183}
.btn:active{transform:translateY(1px)}
.btn-cyan{background:var(--accent-2);color:var(--ground-3)}  /* 13.42:1 */
.btn-cyan:hover{background:var(--accent-2-hi)}
.btn-sm{min-height:42px;padding:11px 20px;font-size:.8125rem}
.btn[disabled]{opacity:.62;cursor:progress}
/* Submit-state fill drain — the gold empties left to right. */
.btn .drain{position:absolute;inset:0;background:var(--ground-2);
  transform:scaleX(0);transform-origin:left center;pointer-events:none}
.btn.is-sending .drain{transform:scaleX(1);transition:transform .9s linear}
.btn.is-sending{color:var(--ink)}
.btn .btn-t{position:relative;z-index:1}

/* Underlined inputs — never boxes. 16px fixed: anything smaller triggers iOS
   Safari's zoom-on-focus, which yanks the viewport mid-form, on the only
   contact path this site has. */
.field{display:flex;flex-direction:column;position:relative;min-width:0;max-width:none}
.field > label{margin-bottom:10px}
/* The gold underline GROWS left→right under whichever input has focus (140ms).
   It is painted as a background layer on the border box rather than an
   ::after on .field, because .field also holds the error line and the
   checkboxes — an ::after at bottom:0 would land under those, not the input. */
input[type="text"],input[type="email"],input[type="tel"],input[type="date"],select,textarea{
  width:100%;font:400 1rem/1.20 var(--sans);color:var(--ink);
  background-color:transparent;border:0;border-bottom:2px solid var(--hairline);
  border-radius:0;padding:12px 0;min-height:44px;-webkit-appearance:none;appearance:none;
  background-image:linear-gradient(var(--accent),var(--accent));
  background-repeat:no-repeat;background-origin:border-box;
  background-position:0 100%;background-size:0% 2px;
  transition:background-size .14s var(--ease)}
textarea{font-family:var(--sans);line-height:1.5;resize:vertical;min-height:88px}
select{background-image:
    linear-gradient(45deg,transparent 50%,var(--ink) 50%),
    linear-gradient(135deg,var(--ink) 50%,transparent 50%),
    linear-gradient(var(--accent),var(--accent));
  background-position:calc(100% - 13px) 55%,calc(100% - 7px) 55%,0 100%;
  background-size:6px 6px,6px 6px,0% 2px;padding-right:30px}
select:focus{background-size:6px 6px,6px 6px,100% 2px}
select option{color:#12161B;background:#DCC5A0}
::placeholder{color:var(--ink-dim);opacity:.72}
input:focus,textarea:focus{background-size:100% 2px}
/* 🔴 NO outline:none HERE. It used to read
      input:focus,select:focus,textarea:focus{outline:none}
   which beats the global :focus-visible rule on specificity (0-1-1 vs 0-1-0) and left
   17 of the 40 keyboard tab stops on this page with NO focus indicator at all — proven
   by byte-identical focused/unfocused screenshots of #q-email, #q-size and #q-consent.
   The growing gold underline it was meant to replace the ring with is painted at
   background-position:0 100% with background-origin:border-box, i.e. inside the same 2px
   strip the opaque border-bottom occupies — and borders paint OVER background-image, so
   the underline was completely invisible. Both halves are fixed: the ring is restored,
   and the focused border itself turns gold so the underline has somewhere to show. */
input:focus-visible,select:focus-visible,textarea:focus-visible{border-bottom-color:var(--accent)}
input:disabled,select:disabled,textarea:disabled{opacity:.42;cursor:not-allowed}
.field.is-bad input,.field.is-bad select,.field.is-bad textarea{border-bottom-color:var(--accent-txt)}
.err{display:block;font-size:var(--fs-small);line-height:1.45;color:var(--accent-txt); /* 4.71:1 */
  margin-top:8px;max-width:46ch;opacity:0;transition:opacity .18s var(--ease)}
.err.is-on{opacity:1}

/* Checkbox rows — a control, laid out on type not in a box. */
.check{display:flex;align-items:flex-start;gap:11px;margin-top:var(--s3);cursor:pointer;
  max-width:52ch}
/* A native unchecked checkbox paints a solid #fff square, which is both the
   loudest thing on the plate and a pure-white surface the house bans. Drawn
   instead: a hairline square that fills gold when ticked. It is a control, so
   the 2px radius is licensed. */
.check input{appearance:none;-webkit-appearance:none;flex:none;
  width:20px;height:20px;margin:1px 0 0;cursor:pointer;
  display:grid;place-content:center;
  background:transparent;border:2px solid var(--hairline);border-radius:2px;
  transition:background-color .16s var(--ease),border-color .16s var(--ease)}
.check input::before{content:"";width:11px;height:11px;transform:scale(0);
  transition:transform .14s var(--ease);background:var(--ground-3);
  clip-path:polygon(14% 44%,0 65%,50% 100%,100% 16%,80% 0,43% 62%)}
.check input:checked{background:var(--accent);border-color:var(--accent)}
.check input:checked::before{transform:scale(1)}
.check input:hover{border-color:var(--ink)}
.check input:disabled{opacity:.42;cursor:not-allowed}
.check span{font-size:var(--fs-small);line-height:1.45;color:var(--ink)}
/* the native date picker glyph is near-black; lift it onto the plate */
input[type="date"]::-webkit-calendar-picker-indicator{
  filter:invert(1) brightness(1.7);opacity:.85;cursor:pointer}

/* Segmented Residential | Commercial — control, so shape is legal, but it is a
   pair of underlines rather than a pair of pills. */
.seg{display:flex;gap:var(--s5);margin:0}
.seg .opt{position:relative}
.seg input{position:absolute;opacity:0;width:100%;height:100%;left:0;top:0;margin:0;cursor:pointer}
.seg label{display:block;padding:10px 2px 9px;cursor:pointer;color:var(--ink-dim);
  font:600 var(--fs-label)/1.1 var(--mono);letter-spacing:.20em;text-transform:uppercase;
  color:var(--ink-dim);border-bottom:2px solid var(--hairline);
  transition:color .18s var(--ease),border-color .18s var(--ease)}
.seg input:checked + label{color:var(--accent-txt);border-bottom-color:var(--accent);font-weight:700}
.seg input:focus-visible + label{outline:2px solid var(--accent);outline-offset:3px}

/* ══ NAV ══════════════════════════════════════════════════════════════════
   🔴 NO backdrop-filter, ever — it breaks position:fixed children, which is
   exactly what the pinned door below creates.
   ═════════════════════════════════════════════════════════════════════════ */
.nav{position:fixed;inset:0 0 auto;z-index:50;height:var(--navh);
  background:transparent;border-bottom:1px solid transparent;
  transition:background-color .22s var(--ease),border-color .22s var(--ease)}
.nav.is-stuck{background:var(--ground);border-bottom-color:var(--hairline-dn)}
.nav .wrap{display:flex;align-items:center;gap:var(--s5);height:100%}
.mark{display:block;text-decoration:none;flex:none;line-height:1}
.mark .m1{display:block;font:700 19px/1 var(--display);letter-spacing:.02em;color:var(--brand)}
.mark .m2{display:block;font:600 var(--fs-label)/1 var(--mono);letter-spacing:.28em;
  color:var(--brand-dim);margin-top:5px}
.navlinks{margin-left:auto;display:flex;align-items:center;gap:var(--s5)}
.navlinks a{text-decoration:none;font:600 var(--fs-label)/1.1 var(--mono);
  letter-spacing:.14em;text-transform:uppercase;color:var(--ink-dim);white-space:nowrap;
  padding:6px 0;border-bottom:1px solid transparent;transition:border-color .18s var(--ease)}
.navlinks a:hover{color:var(--brand);border-bottom-color:var(--brand)}
.nav .btn{margin-left:var(--s4);flex:none}
/* The three links disappear entirely below 900 — no hamburger. The page is six
   sections; scrolling IS the navigation, and killing the menu kills a whole
   class of overlap bugs. The portal stays reachable from section 4 and the gold
   CTA never leaves the bar.
   🔴 900, not the spec'd 768: measured in Chromium at exactly 768 the wordmark
   (175px) + three tracked mono links (375px + gaps) + the pill (177px) need
   791px inside a 707px content box, and the CTA was clipped off the right edge.
   Tightening gaps and type recovered ~85px of the 84px needed — no margin at
   all across platform font metrics — so the breakpoint moves instead. */
@media (max-width:899px){
  .navlinks{display:none}
  .nav .btn{margin-left:auto}
}
@media (max-width:767px){
  :root{--navh:56px}
  .nav .btn{min-height:40px;padding:10px 16px;font-size:.6875rem;letter-spacing:.1em}
  .mark .m1{font-size:17px}
}

/* ══ 1 · HERO ═════════════════════════════════════════════════════════════ */
.hero{min-height:100vh;min-height:100lvh;display:flex;align-items:flex-start;
  padding-top:clamp(96px,22vh,206px);padding-bottom:84px;overflow:hidden}
.hero-media{position:absolute;inset:0;overflow:hidden;z-index:0}
/* 132% width is the lateral travel budget for the fx27 drift (max excursion
   ±13.5vw). Wrapper clips it; the page never scrolls sideways. */
.hero-media img{position:absolute;top:0;left:0;width:132%;height:100%;
  object-fit:cover;object-position:70% 50%;will-change:transform}
/* Left-anchored scrim: every hero glyph sits at >=8.68:1 over the photograph.
   Below 1024 the type column is a much larger share of the width, so the ramp
   never reaches full transparency — otherwise "MOVING TO" lands on the lit
   side of the truck with no contrast floor at all. */
.hero-scrim{position:absolute;inset:0;z-index:1;
  background:linear-gradient(100deg,var(--scrim) 0%,var(--scrim) 46%,rgba(35,42,50,0) 78%)}
@media (max-width:1023px){
  .hero-scrim{background:linear-gradient(100deg,var(--scrim) 0%,var(--scrim) 60%,
    rgba(35,42,50,.72) 84%,rgba(35,42,50,.5) 100%)}
}
.hero .wrap{position:relative;z-index:2}
.hero-col{max-width:34rem}
.eyebrow-wide{display:inline}
.eyebrow-short{display:none}
@media (max-width:559px){.eyebrow-wide{display:none}.eyebrow-short{display:inline}}
.hero h1{margin-top:var(--s5)}
.hero .lead{margin-top:var(--s4);max-width:42ch}
.hero-form{margin-top:var(--s6)}
.hero-fields{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:var(--s5);margin-top:var(--s5)}
@media (max-width:559px){.hero-fields{grid-template-columns:1fr;gap:var(--s4)}}
.hero-acts{display:flex;align-items:center;gap:var(--s4);flex-wrap:wrap;margin-top:var(--s5)}
.step{font:600 var(--fs-label)/1.1 var(--mono);letter-spacing:.20em;text-transform:uppercase;
  color:var(--ink-dim)}
.reassure{margin-top:var(--s3);font:600 var(--fs-label)/1.4 var(--mono);letter-spacing:.14em;
  text-transform:uppercase;color:var(--ink-dim);max-width:none}
.cue-hold{position:absolute;left:0;right:0;bottom:30px;z-index:2;pointer-events:none}
.cue{display:inline-flex;align-items:center;gap:12px;
  font:600 12px/1 var(--mono);letter-spacing:.28em;text-transform:uppercase;color:var(--ink-dim);
  border-top:1px solid var(--hairline);padding-top:14px;max-width:none}
.cue i{display:block;width:1px;height:14px;background:var(--accent);transform-origin:top center;
  animation:tick 1.6s var(--ease) infinite}
@keyframes tick{0%{transform:scaleY(0)}45%{transform:scaleY(1)}100%{transform:scaleY(0)}}

/* ══ 2 · THE DOOR ═════════════════════════════════════════════════════════ */
.open-in{padding-block:clamp(38px,6vh,62px) clamp(22px,3vh,32px)}
.scene{position:relative;background:var(--ground-3);
  height:100vh;height:100lvh;overflow:hidden}
.scene-in{height:100%;display:grid;grid-template-columns:minmax(0,58fr) minmax(0,42fr);align-items:stretch}
/* --open defaults to 100% = door already up. If GSAP never loads, the visitor
   gets the finished open truck rather than a dead grey door. fx.js sets it to
   0% the moment it wires the scrub, and restores 100% on teardown.
   Second fallback: if the photo itself 404s, --ground-2 under the CSS door is
   still a legitimate finished surface — there is never a hole. */
.stage{position:relative;overflow:hidden;background:var(--ground-2);--open:100%}
.stage img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  object-position:center;transition:opacity .32s var(--ease)}
.stage img.alt{opacity:0}
.stage.show-alt img.main{opacity:0}
.stage.show-alt img.alt{opacity:1}

/* THE DOOR. Drawn in CSS: crisp at every DPR, zero bytes.
   22px slat pitch, 2px dark seam, 1px highlight lip = the corrugation of a
   roll-up door. Stops are percentages of the tile so that shrinking
   background-size compresses the slats instead of destroying the pattern —
   that is the detail that makes it read as ROLLING onto a drum rather than
   wiping. clip-path insets from the BOTTOM, so the interior is revealed
   bottom-up. That is what a real roll-up door does. */
/* 🔴 SLAT CONTRAST RAISED 2026-08-13. The original stops #3A424B / #3D4650 / #4A5460 are
   1.06–1.13:1 against each other: at --open:0 the stage rendered as a featureless dark
   slab occupying 58% x 100lvh, and the visitor's arrival frame did not read as a door at
   all. Face #4C5764 against seam #2E3640 is 1.53:1 and lip #5A6673 against the seam is
   1.83:1 — visible corrugation, still nowhere near stripes. */
.door{position:absolute;inset:0;z-index:2;
  background-image:linear-gradient(180deg,
    #4C5764 0%, #4C5764 86.36%,
    #2E3640 86.36%, #2E3640 95.45%,
    #5A6673 95.45%, #5A6673 100%);
  background-repeat:repeat;background-size:100% 22px;
  clip-path:inset(0 0 var(--open) 0)}
/* the light side — the sun comes from frame left in the source photography */
.door::after{content:"";position:absolute;inset:0;
  background:linear-gradient(90deg,rgba(18,22,27,.34) 0%,rgba(18,22,27,0) 30%)}
/* THE LIGHT BAND — rides the door's rising edge. The single most beautiful
   frame in the build: a bar of warm light climbing a cold grey door. */
/* top is pulled 2px INSIDE the stage so that at --open:0 the band sits on the door's
   bottom edge and is visible from the first frame, rather than being half-clipped by the
   stage's own overflow:hidden. */
.light{position:absolute;left:0;right:0;z-index:3;height:3px;opacity:0;
  top:calc(100% - var(--open) - 2px);transform:translateY(-50%);
  background:linear-gradient(90deg,rgba(240,194,90,0),#F0C25A 18%,#FFEDC6 50%,#F0C25A 82%,rgba(240,194,90,0));
  box-shadow:0 0 34px 6px rgba(240,194,90,.42),0 6px 26px rgba(240,194,90,.28)}

.manifest{display:flex;flex-direction:column;justify-content:center;
  padding:var(--s5) clamp(18px,3vw,40px);min-width:0;overflow-y:auto}
.man-list{border-top:1px solid var(--hairline-dn)}
.man-row{display:grid;grid-template-columns:auto 1fr auto;align-items:baseline;gap:var(--s3);
  width:100%;text-align:left;background:none;border:0;border-radius:0;
  border-bottom:1px solid var(--hairline-dn);
  padding:var(--s3) 0 var(--s3) 16px;cursor:pointer;position:relative;
  transition:color .18s var(--ease)}
.man-row::before{content:"";position:absolute;left:0;top:50%;width:2px;height:1.2em;
  margin-top:-.6em;background:var(--accent);transform:scaleY(0);transform-origin:center;
  transition:transform .2s var(--ease)}
.man-row[aria-pressed="true"]::before{transform:scaleY(1)}
.man-row .n{font:600 var(--fs-label)/1 var(--mono);letter-spacing:.12em;color:var(--accent-txt)}
.man-row .t{font:600 var(--fs-h3)/1.2 var(--display);color:var(--ink-dim);
  transition:color .18s var(--ease)}
.man-row[aria-pressed="true"] .t{color:var(--ink)}
.man-row:hover .t{color:var(--ink)}
.man-row .p{font:600 var(--fs-data)/1 var(--mono);color:var(--accent-txt);
  transition:transform .22s var(--ease);display:inline-block}
.man-row[aria-pressed="true"] .p{transform:rotate(45deg)}
.man-copy{margin-top:var(--s4);max-width:46ch;font-size:var(--fs-body);color:var(--ink);
  transition:opacity .24s var(--ease)}
.man-copy.is-fading{opacity:0}
.man-copy > p{display:none}
.man-copy > p.is-on{display:block}
@media (max-width:899px){
  .scene{height:auto;overflow:visible;background:transparent}
  .scene-in{display:block;height:auto}
  .stage{height:62vh;height:62lvh}
  .manifest{padding:var(--s5) clamp(18px,4vw,40px) 0;overflow:visible;justify-content:flex-start}
}

/* ══ 3 · HOW THE MOVE RUNS ════════════════════════════════════════════════
   🔴 THE RIGHT COLUMN HAS A JOB. Body copy is capped at 64ch (~715px) inside an 1180px
   wrap, so at 1440 every beat ended at x≈980 while its hairline ran to x=1270 and the
   viewport to 1440 — the right third of the page sat empty for ~300vh. On a mid-tone
   ground a large empty field has no texture to carry it and reads as unfinished.
   The citation moves into that track as a right-aligned mono column at >=1100. It fills
   the void, it removes a third stacked block from every beat (which is ~40px off each
   one, six times), and it turns the rulebook reference into the structural device the
   concept already claims it is.
   Gold is legal on the beat number here: these five sit on --ground-2 #3A424B where
   #F0C25A measures 5.38:1, not on the ground where it would be 3.67:1. */
.beats{border-top:1px solid var(--hairline)}
.beat{display:grid;grid-template-columns:4.5rem minmax(0,1fr);gap:0 var(--s4);
  padding-block:var(--s4);border-bottom:1px solid var(--hairline)}
.beat .n{font:600 var(--fs-marker)/1 var(--mono);color:var(--accent)}
.beat h3{margin:0}
.beat p{margin-top:var(--s3);max-width:64ch}
.beat .cite{margin-top:var(--s3);font:400 var(--fs-small)/1.5 var(--mono);color:var(--ink-dim);
  letter-spacing:.02em;max-width:58ch}
@media (min-width:1100px){
  .beat{grid-template-columns:4.5rem minmax(0,1fr) 13rem}
  .beat .cite{grid-column:3;grid-row:1/-1;text-align:right;margin-top:0;align-self:start;
    max-width:none;padding-left:var(--s4);text-wrap:balance}
}
@media (max-width:767px){
  .beat{grid-template-columns:1fr;gap:var(--s2) 0}
  .beat .n{margin-bottom:var(--s2)}
}
/* the 21:9 strip — full-bleed, no radius, a hairline above and below */
.strip{position:relative;overflow:hidden;height:34vh;min-height:180px;
  border-top:1px solid var(--hairline);border-bottom:1px solid var(--hairline);
  margin-block:var(--s5)}
.strip img{position:absolute;top:0;left:0;width:132%;height:100%;object-fit:cover;
  object-position:center;will-change:transform}
.strip::after{content:"";position:absolute;inset:0;pointer-events:none;
  box-shadow:inset 0 0 0 1px rgba(144,155,168,.28)}
.links{margin-top:var(--s5);border-top:1px solid var(--hairline)}
.links a{display:block;text-decoration:none;border-bottom:1px solid var(--hairline);
  padding-block:16px}
.links a .t{font:600 var(--fs-h3)/1.25 var(--display);color:var(--accent-2);   /* 4.52:1 */
  transition:color .18s var(--ease);max-width:34ch;display:block}
.links a:hover .t{color:var(--accent-2-hi)}
.links a .d{display:block;margin-top:6px;font-size:var(--fs-small);line-height:1.5;
  color:var(--ink-dim);max-width:58ch}
/* The description moves into the right-hand track, on the same grid the citations use. */
@media (min-width:900px){
  .links a{display:grid;grid-template-columns:minmax(0,1fr) 22rem;gap:var(--s5);
    align-items:baseline}
  .links a .t{max-width:none}
  .links a .d{margin-top:0;text-align:right;max-width:none}
}
/* ── fx48 WORD GLOW — dim value RE-DERIVED, and it is not the spec's number.
   The design system says dim must go DARKER than the ground, because on the
   L*41 GROUND the demo's mid-luminance olive would sit at the ground's own
   luminance and vanish. That reasoning is correct — for the ground. But these
   five paragraphs sit on the L*31 BAND #3A424B, and there the arithmetic
   inverts: the brightest contrast ANY darker colour can reach on #3A424B is
   pure black at 2.34:1, and the spec's --dim #3A424C measures 1.13:1. Shipped
   literally it renders the back half of every policy paragraph invisible —
   confirmed in Chromium at 1440, not assumed. That destroys the effect's own
   stated intent: "you are meant to see the words you have not reached yet".
   So on the band, dim goes LIGHTER. #B1BBC1 = 4.60:1, which still passes AA
   for body text, ramping to --ink #E8CFA6 at 7.84:1 — a 1.78x luminance step
   plus a cool-to-warm hue shift, so the reveal reads clearly while every word
   is legible at every scroll position. The opacity ramp is dropped for the
   same reason: colour alone carries it, and nothing ever drops below AA.
   ────────────────────────────────────────────────────────────────────────── */
.glow{--dim:#B1BBC1;--lit:var(--ink)}
.glow .w{--l:0;display:inline-block;
  color:color-mix(in oklab, var(--dim), var(--lit) calc(var(--l)*100%));
  text-shadow:0 0 calc(var(--l)*12px) rgba(240,194,90,.18);
  transition:text-shadow 110ms linear;will-change:color}
@media (prefers-reduced-motion:reduce){
  .glow .w{--l:1!important;color:var(--lit)!important;text-shadow:none}
}
/* color-mix is the only mechanism here; where it is unsupported the words
   simply inherit --ink and the paragraph reads as static. */
@supports not (color:color-mix(in oklab,#000,#fff 50%)){
  .glow .w{color:var(--ink)}
}

/* ══ 4 · CLIENT PORTAL ════════════════════════════════════════════════════ */
.prow{border-bottom:1px solid var(--hairline);padding-block:var(--s4)}
@media (max-width:767px){}
.frag{margin-top:var(--s5);font-size:.9em}
.frag .cap{display:block;margin-bottom:var(--s3)}
.tscroll{overflow-x:auto;-webkit-overflow-scrolling:touch}
table.est{width:100%;min-width:520px;font:500 var(--fs-data)/1.45 var(--mono);
  font-variant-numeric:tabular-nums;text-align:left}
table.est caption{text-align:left;font:600 var(--fs-label)/1.1 var(--mono);
  letter-spacing:.20em;text-transform:uppercase;color:var(--ink);padding-bottom:var(--s3)}
table.est th{font:600 var(--fs-label)/1.1 var(--mono);letter-spacing:.14em;
  text-transform:uppercase;color:var(--ink);font-weight:600;
  border-bottom:1px solid var(--hairline);padding:0 var(--s3) 10px 0;white-space:nowrap}
table.est td{border-bottom:1px solid var(--hairline);padding:12px var(--s3) 12px 0;color:var(--ink)}
table.est th.num,table.est td.num{text-align:right;padding-right:0}
table.est tbody tr{transition:background-color .16s var(--ease)}
table.est tbody tr:hover{background:var(--row-hover)}   /* 1.096:1 — perceptible on mid grey */
/* Odometer. Transient only: fx.js restores the plain number when the roll
   lands, so the resting state is pixel-identical to the markup. */
.od{display:inline-block;height:1.45em;overflow:hidden;vertical-align:bottom;width:1ch}
.odc{display:block;transition:transform .9s var(--ease)}
.odc b{display:block;height:1.45em;line-height:1.45;font-weight:500}
/* .reveal carries NO hidden state in CSS — fx.js sets the start inline, so with
   JS blocked all four rows are simply visible. */

/* ══ 5 · GET MY ESTIMATE ══════════════════════════════════════════════════ */
/* minmax(0,Nfr), NOT percentages: `58% 42%` plus a 68px gap is 100% + 68px and
   pushed the document 28px wide at exactly 1024 — measured, then fixed. */
.quote-grid{display:grid;grid-template-columns:minmax(0,58fr) minmax(0,42fr);
  gap:0 var(--s7);align-items:start}
@media (max-width:1023px){.quote-grid{grid-template-columns:1fr;gap:var(--s7) 0}}
.qform{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:var(--s4) var(--s5)}
.qform .full{grid-column:1/-1}
@media (max-width:559px){.qform{grid-template-columns:1fr}}
.qacts{grid-column:1/-1;margin-top:var(--s2)}
.qacts .btn{min-width:230px}
@media (max-width:767px){.qacts .btn{width:100%}}
.qacts .reassure{margin-top:var(--s3)}
.formerr{margin-bottom:var(--s3);font-size:var(--fs-small);color:var(--accent-txt);max-width:52ch}
.next .rule{margin:var(--s3) 0 var(--s4)}
.next p + p{margin-top:var(--s4)}
.done{border-top:1px solid var(--hairline);padding-top:var(--s5)}
.done h3{margin-bottom:var(--s3)}
.hint{display:block;margin-top:10px;font-size:var(--fs-small);line-height:1.5;
  color:var(--ink-dim);max-width:46ch}

/* ══ 6 · FOOTER ═══════════════════════════════════════════════════════════ */
.foot{position:relative;z-index:2;background:var(--ground-3);color:var(--ink)}
.foot-in{padding-block:clamp(32px,4.5vh,50px) var(--s5);text-align:center}
.licence{font:600 var(--fs-label)/1.5 var(--mono);letter-spacing:.16em;text-transform:uppercase;
  color:var(--ink);margin-bottom:var(--s4)}
.fineprint{font-size:var(--fs-small);line-height:1.6;color:var(--ink-dim);
  max-width:72ch;margin-inline:auto}

/* ── pzft: footer credit + legal nav — RunKeepAI brand gradient, self-contained.
   🔴 Do NOT simplify the @supports guard or the solid-cyan fallback away: without
   them the word "RunKeepAI" renders as invisible text on any engine that misses
   background-clip. One licensed substitution: hover colour is --accent. ── */
.pzft-footer{background:#0d0d0d;border-top:1px solid #1e1e1e;padding:26px 20px 30px}
.pzft-inner{max-width:1200px;margin:0 auto;display:flex;flex-direction:column;
  align-items:center;gap:11px;text-align:center}
.pzft-legal{display:flex;align-items:center;flex-wrap:wrap;justify-content:center;font-size:12px}
.pzft-legal a{color:#8a8a8a;text-decoration:none;padding:0 12px;letter-spacing:.04em;transition:color .2s}
.pzft-legal a:hover{color:var(--accent)}
.pzft-sep{color:#3a3a3a}
.pzft-copy{color:#8a857c;font-size:11.5px;letter-spacing:.03em;max-width:none}
/* 🔴 CANONICAL LOCKUP — the medallion and the wordmark are ONE unit. Never place the
   UFO on its own somewhere else on the page with "RunKeepAI" set separately below it.
   Mike, 2026-08-13: "why do you keep changing my fucking logo". They travel together. */
.pzft-credit{display:inline-flex;align-items:center;gap:9px;
  font-size:12px;color:#8a8a8a;text-decoration:none;letter-spacing:.03em;white-space:nowrap}
.pzft-ufo{width:26px;height:26px;flex:none;border-radius:50%;object-fit:contain;
  background:radial-gradient(circle at 50% 38%,#1c2440 0%,#131a30 46%,#0b0f1e 78%,#070a14 100%);
  box-shadow:0 0 0 1px rgba(0,239,240,.18),0 0 14px rgba(0,239,240,.16);
  padding:3px;                                                /* keeps the saucer off the rim */
  filter:drop-shadow(0 0 5px rgba(0,239,240,.45)) saturate(1.08)}
.pzft-rk{color:#00eff0;font-weight:600}                       /* fallback: solid cyan */
@supports ((-webkit-background-clip:text) or (background-clip:text)){
  .pzft-rk{
    background:linear-gradient(100deg,#00eff0,#8040f0 48%,#d000f0);
    -webkit-background-clip:text;background-clip:text;
    -webkit-text-fill-color:transparent;color:transparent;
    filter:drop-shadow(0 0 10px rgba(128,64,240,.35));transition:filter .25s}
  .pzft-credit:hover .pzft-rk{filter:drop-shadow(0 0 16px rgba(0,239,240,.6)) brightness(1.12)}
}
@media (prefers-reduced-motion:reduce){.pzft-legal a,.pzft-rk{transition:none}}
.pzft-footer{padding-bottom:calc(30px + env(safe-area-inset-bottom))}

/* ══ PERSISTENT TAB ═══════════════════════════════════════════════════════
   Keeps the only contact path reachable at every scroll depth without spending
   one of the six sections. Desktop: right edge, rotated. Mobile: bottom bar.
   ═════════════════════════════════════════════════════════════════════════ */
/* 🔴 NO rotate(180deg) AND NO transform-origin:100% 0 HERE. That pair rotated the box
   about its own TOP-RIGHT corner and mapped it to x[1440..1476] on a 1440 viewport —
   measured rect.left = 1440 at every scroll position, i.e. one of the three mandated
   placements of the single CTA verb rendered entirely off-screen, as a keyboard-focusable
   anchor a sighted user could never see. writing-mode:vertical-rl already supplies the
   vertical run on its own; the 180deg was a doubled flip. */
.tab{position:fixed;z-index:60;text-decoration:none;
  right:0;top:50%;transform:translateY(-50%);
  writing-mode:vertical-rl;text-orientation:mixed;
  font:600 12px/1 var(--mono);letter-spacing:.22em;text-transform:uppercase;
  background:var(--accent);color:var(--ground-3);padding:20px 12px;
  border-radius:4px 0 0 4px;
  transition:background-color .18s var(--ease)}
.tab:hover{background:#F7D183}
@media (max-width:1023px){
  .tab{right:auto;left:0;top:auto;bottom:0;width:100%;
    writing-mode:horizontal-tb;transform:none;border-radius:0;
    padding:16px 20px calc(16px + env(safe-area-inset-bottom));text-align:center;
    letter-spacing:.14em;border-top:1px solid rgba(18,22,27,.28)}
  /* clear the fixed bottom bar so nothing is ever covered by it */
  .pzft-footer{padding-bottom:calc(84px + env(safe-area-inset-bottom))}
  .hero{padding-bottom:calc(120px + env(safe-area-inset-bottom))}
  /* the bottom bar occupies the cue's slot and says the same thing louder */
  .cue-hold{display:none}
}

/* ══ REDUCED MOTION — global backstop ═════════════════════════════════════
   The GRAIN layer is deliberately NOT affected: it does not move and it is
   load-bearing for colour fidelity on a mid-tone ground.
   ═════════════════════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms!important;animation-iteration-count:1!important;
    transition-duration:.001ms!important;scroll-behavior:auto!important}
  .cue i{animation:none;transform:scaleY(1)}
  .door{display:none}
  .light{display:none}
  .scene{height:auto;overflow:visible;background:transparent}
  .scene-in{display:grid}
  .stage{height:62vh;height:62lvh}
  .wipe{clip-path:none}
}
@media (prefers-reduced-motion:reduce) and (max-width:899px){
  .scene-in{display:block}
}

/* ══ PRINT ════════════════════════════════════════════════════════════════ */
@media print{
  .nav,.tab,.grain,.cue,.scene,.strip{display:none!important}
  body{background:#fff;color:#111}
  .plate-2,.plate-3,.foot{background:#fff;color:#111}
}
