/* ===== 1. tokens (fallbacks — brand.js overrides at runtime) ===== */
:root{
  --ivory:#F6F1EA; --ink:#0E0D0B; --metal:#B8935A; --metal-deep:#7A5E33; --bone:#EBE4D8; --stone:#8C857B;
  --font-display:"Cormorant Garamond", Georgia, serif; --font-ui:"Manrope", system-ui, sans-serif;
  --on-metal:var(--ink); /* recomputed at runtime by applyBrand from the metal's relative luminance */

  /* semantic layer — every component below reads GROUND/TYPE/RULE, never --ivory/--ink directly,
     so a section can flip to the inverted (ink-ground) context with zero per-component overrides. */
  --ground:var(--ivory);
  --type:var(--ink);
  --type-2:color-mix(in srgb, var(--ink) 62%, var(--ivory)); /* muted text on the light ground */
  --rule:color-mix(in srgb, var(--ink) 12%, var(--ivory));
  --panel:color-mix(in srgb, var(--ground) 92%, var(--type));

  --r:2px; --r-lg:4px; --gutter:clamp(20px, 5vw, 64px); --measure:60ch;
  --ease:cubic-bezier(.16,.84,.44,1);
}
/* Inverted context: a section carrying .inv (the manifesto — the only one on the page) sits on ink with ivory
   type and a translucent-ivory hairline — components inherit this automatically via the same
   var(--ground)/var(--type)/var(--type-2)/var(--rule) reads. .btn-primary is untouched: it stays
   metal with the runtime-computed --on-metal label in both contexts. */
.inv{
  --ground:var(--ink);
  --type:var(--ivory);
  --type-2:var(--bone);
  --rule:color-mix(in srgb, var(--ivory) 18%, transparent);
}

/* ===== 2. reset ===== */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{margin:0;background:var(--ground);color:var(--type);font-family:var(--font-ui);line-height:1.6;-webkit-font-smoothing:antialiased;overflow-x:hidden}
img{max-width:100%;height:auto;display:block}
button{font:inherit;color:inherit;background:none;border:0;padding:0;cursor:pointer}
a{color:inherit}
:focus-visible{outline:2px solid var(--metal);outline-offset:3px;border-radius:2px}
.skip{position:absolute;left:-999px}
.skip:focus{left:var(--gutter);top:8px;background:var(--type);color:var(--ground);padding:8px 14px;z-index:99;border-radius:var(--r)}

/* ===== 3. type ===== */
h1,h2,h3{font-family:var(--font-display);font-weight:500;letter-spacing:-.01em;line-height:1.05;margin:0;text-wrap:balance;overflow-wrap:anywhere}
/* every surface fed by brand.js / content.js: a long unbroken client string must wrap, not overflow */
.wordmark,.foot p,.foot a,.eyebrow{overflow-wrap:anywhere;min-width:0}
.display{font-size:clamp(44px, 9.5vw, 132px)}
.display em,.display i{font-style:italic;font-weight:400}
.h2{font-size:clamp(28px, 4.2vw, 52px)}
.eyebrow{display:inline-block;font-family:var(--font-ui);font-size:11px;font-weight:600;letter-spacing:.22em;text-transform:uppercase;color:var(--type-2)}
.chip-sample{display:inline-block;vertical-align:middle;margin-left:4px;font-size:10.5px;letter-spacing:.12em;text-transform:uppercase;border:1px dashed var(--type-2);border-radius:6px;padding:2px 7px;color:var(--type-2)}

/* ===== 4. masthead ===== */
.mast{position:sticky;top:0;z-index:20;display:flex;align-items:center;gap:20px;padding:22px var(--gutter);background:transparent;border-bottom:1px solid transparent;transition:background .3s var(--ease),border-color .3s var(--ease)}
.mast.scrolled{background:color-mix(in srgb, var(--ground) 92%, transparent);backdrop-filter:blur(10px);border-bottom-color:var(--bone)}
.mast .wordmark{display:flex;align-items:center;gap:10px;font-family:var(--font-display);font-size:20px;letter-spacing:.01em;text-decoration:none;color:var(--type);transition:opacity .2s var(--ease)}
.mast .wordmark img{width:28px;height:28px}
.mast nav{display:flex;gap:26px;margin-left:auto;font-size:13px}
/* 44px of target, same 13px label: the box grows, the type does not. The underline sweep is
   pinned to the text's own line rather than the box, so the taller target does not float it away. */
.mast nav a{position:relative;display:inline-flex;align-items:center;min-height:44px;text-decoration:none;color:var(--type-2);letter-spacing:.06em;text-transform:uppercase;padding:4px 2px;transition:color .2s var(--ease)}
.mast nav a::after{content:"";position:absolute;left:2px;right:100%;bottom:calc(50% - 0.9em);height:1px;background:var(--metal);transition:right .25s var(--ease)}
.mast .cta-inquire{min-height:44px;padding:0 22px;font-size:13px}   /* 44: it is a tap target */
@media (hover:hover) and (pointer:fine){
  .mast .wordmark:hover{opacity:.72}
  .mast nav a:hover{color:var(--type)}
  .mast nav a:hover::after{right:0}
}
@media(max-width:767px){.mast nav{display:none}}

/* ===== 5. buttons ===== */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:8px;min-height:48px;padding:0 28px;border-radius:999px;font-family:var(--font-ui);font-weight:600;font-size:14px;letter-spacing:.02em;text-decoration:none;transition:transform .25s var(--ease),background .25s var(--ease),box-shadow .25s var(--ease),color .25s var(--ease)}
.btn-primary{background:var(--metal);color:var(--on-metal)}
.btn-primary:active{transform:translateY(0)}
.btn-ghost{border:1px solid var(--type);color:var(--type)}
.btn[aria-disabled="true"]{background:var(--panel);color:var(--type-2);pointer-events:none}
@media (hover:hover) and (pointer:fine){
  .btn-primary:hover{transform:translateY(-1px);box-shadow:0 10px 24px -10px color-mix(in srgb, var(--metal) 55%, transparent)}
  .btn-ghost:hover{background:var(--type);color:var(--ground)}
}

/* ===== 6. footer ===== */
.foot{border-top:1px solid var(--rule);padding:56px var(--gutter) 40px;display:grid;gap:28px;grid-template-columns:1fr;font-size:14px;color:var(--type-2)}
@media(min-width:768px){.foot{grid-template-columns:2fr 1fr 1fr}}
.foot h3{font-family:var(--font-display);font-size:16px;font-weight:500;color:var(--type);margin-bottom:8px}
.foot a{text-decoration:none;border-bottom:1px solid var(--rule);transition:border-color .2s var(--ease),color .2s var(--ease)}
@media (hover:hover) and (pointer:fine){
  .foot a:hover{color:var(--type);border-color:var(--type)}
}

/* ===== 7. hero — scroll-scrubbed cinematic stage ===== */
/* .staged is added by renderHero(): with no JS there is no stage, so the section must not
   reserve 480vh of empty scroll. --mast-h is measured at runtime (0 without JS), which pulls
   the stage up under the transparent masthead without hard-coding its height. */
.hero{position:relative;min-height:100vh;background:var(--ground)}
.hero.staged{height:480vh;min-height:0;margin-top:calc(-1 * var(--mast-h, 0px))}
/* Two equal auto rows, each centring its item: the copy holds the upper half (clear of the
   silk's light line, which sweeps the lower half) and the scroll cue holds the lower. */
.hero .stage{position:sticky;top:0;height:100vh;width:100%;overflow:hidden;display:grid;grid-auto-rows:1fr;place-items:center;background:var(--ground)}

/* The poster carries the fold until the sequence paints; then they cross-fade. */
.hero .hero-poster{position:absolute;inset:0;width:100%;height:100%;max-width:none;object-fit:cover;transition:opacity .6s var(--ease)}
.hero .hero-canvas{position:absolute;inset:0;width:100%;height:100%;opacity:0;transition:opacity .6s var(--ease)}
.hero[data-painted="1"] .hero-canvas{opacity:1}
.hero[data-painted="1"] .hero-poster{opacity:0}

/* A soft ivory veil so the copy reads over the brightest part of the silk. */
.hero .hero-scrim{position:absolute;inset:0;pointer-events:none;background:radial-gradient(72% 56% at 50% 52%, color-mix(in srgb, var(--ivory) 60%, transparent), transparent 72%)}

/* Grades — Task 4 sets data-grade from the chosen occasion via window.__hero.setGrade(). */
.hero .hero-grade{position:absolute;inset:0;pointer-events:none;background:transparent;backdrop-filter:none;-webkit-backdrop-filter:none;transition:background .8s var(--ease),backdrop-filter .8s var(--ease)}
.hero[data-grade="candle"] .hero-grade{background:color-mix(in srgb, var(--metal) 8%, transparent)}
/* midnight also flips the overlay copy to ivory (below), so the tint has to be deep enough to
   carry light type over the brightest part of the silk — 22% was not, at any frame.
   DUSK, NOT TAUPE (review round 1): a flat ink wash over a warm ivory silk just averages out to
   beige. The colour has to come off the frame first — backdrop-filter desaturates and cools what
   is underneath, so the silk stops reading as warm fabric — and only then does the ink wash settle
   it. That also means the heavy 34% floor is no longer doing the contrast work, so the vignette
   is lighter and the bottom of the stage keeps its depth instead of turning to mud.
   No new colour token: the cooling is a filter on the frame, so a reskin still owns every hue. */
.hero[data-grade="midnight"] .hero-grade{
  backdrop-filter:saturate(.38) brightness(.82) contrast(1.06);
  -webkit-backdrop-filter:saturate(.38) brightness(.82) contrast(1.06);
  background:
    linear-gradient(to top, color-mix(in srgb, var(--ink) 20%, transparent), transparent 40%),
    color-mix(in srgb, var(--ink) 56%, transparent)}
/* FIX ROUND 1 — the contrast floor must not depend on backdrop-filter.
   Lightening the wash (62% -> 56%) and the vignette (34% -> 20%) was only safe BECAUSE the filter
   was darkening the frame underneath. In a browser without it the wash is all there is, and the
   H1 measured 4.37–4.48:1 — under the 4.5 floor at every sample point. So where the filter is not
   supported, the old wash comes straight back: it looked flatter, but flat and readable beats
   handsome and illegible. Tokens only, same two layers, no filter involved.
   verify/layout-audit.mjs re-runs the whole midnight scrub with the filter forced off and this
   block's own declarations applied, so the fallback is measured, not assumed. */
@supports not ((backdrop-filter:saturate(1)) or (-webkit-backdrop-filter:saturate(1))){
  .hero[data-grade="midnight"] .hero-grade{background:
    linear-gradient(to top, color-mix(in srgb, var(--ink) 34%, transparent), transparent 32%),
    color-mix(in srgb, var(--ink) 62%, transparent)}
}
/* The hint lives in .stage, not .hero-copy, so it needs the remap by name — without it the
   "Scroll" cue was stone type over the graded frame (1.99:1 when it was measured, on the 62% wash
   this grade still falls back to; the filtered version is darker again). */
.hero[data-grade="midnight"] .hero-copy,
.hero[data-grade="midnight"] .hero-hint{--type:var(--ivory);--type-2:var(--bone);
  --rule:color-mix(in srgb, var(--ivory) 26%, transparent)}   /* same remap as .inv */
/* The hint is 11px uppercase over a photograph. Bone cleared 4.0:1 there, not 4.5 — it takes
   full ivory, which is the same measured 5.3:1 the headline gets. */
.hero[data-grade="midnight"] .hero-hint{--type-2:var(--ivory)}

.hero .hero-copy{position:relative;z-index:2;display:grid;justify-items:center;gap:clamp(12px,1.8vh,22px);text-align:center;padding:0 var(--gutter);width:100%;max-width:min(1080px,94vw);color:var(--type)}
.hero .hero-copy .eyebrow{color:var(--type-2)}
.hero .hero-sub{margin:0;font-family:var(--font-display);font-style:italic;font-weight:400;font-size:clamp(19px,2.4vw,30px);line-height:1.3;color:var(--type-2)}
.hero .hero-actions{margin-top:clamp(6px,1.4vh,16px)}
/* Task 4 fills #occasions with the chip row; empty it must take no space. */
.hero .occasions:empty{display:none}
.hero .hero-hint{align-self:end;padding-bottom:clamp(22px,5vh,52px);font-family:var(--font-ui);font-size:11px;font-weight:600;letter-spacing:.22em;text-transform:uppercase;color:var(--type-2)}
.hero .reveal-line{will-change:opacity,transform}

@media (max-width:600px){
  /* Portrait crops out most of the frame, so the veil sits over the copy (upper half) only —
     centred it washed the light line straight out of the fold. */
  .hero .hero-scrim{background:radial-gradient(96% 40% at 50% 28%, color-mix(in srgb, var(--ivory) 62%, transparent), transparent 76%)}
  /* 480vh measured 4051px at 390x844: nearly five phone screens of thumb-work before the first
     word of the promise. 300vh is ~2500px there — still a long, unhurried scrub, and still far
     more than the 180 frames need to read as motion. The engine derives its progress from the
     section's ACTUAL rect height (scrollable = rect.height - innerHeight in scroll-cinematic.js),
     never from the 480 in the rule above, so the scrub math needs no change: the same 0..1 just
     covers less distance. */
  .hero.staged{height:300vh}
}

/* Review round 1: the eyebrow was landing inside the masthead's band from 768px up (measured
   y 42.7–60.3 against a mast of 0–89 at 1440x900) — the wordmark and the eyebrow reading as one
   crowded stack. The copy now clears the masthead by carrying its measured height as top padding,
   plus 18px of breathing room so the eyebrow never sits on the masthead's own baseline.
   Padding rather than margin, and a single mast-h rather than a doubled one, because the stage's
   `1fr` rows are minmax(auto,1fr): the copy row grows to fit its content, so the padding lands on
   the eyebrow one-for-one instead of being halved by centring. Measured after the change: eyebrow
   top 118 / 118 / 134 at 1440x900 / 1280x720 / 768x1024, against a mast bottom of 89 — asserted at
   all six widths by verify/layout-audit.mjs. Phones keep their own rule above: at 375 the copy was
   already clear (120 vs 109) and moving it would have pushed it off the mobile scrim. */
@media (min-width:601px){
  .hero .hero-copy{padding-top:calc(var(--mast-h, 0px) + 18px)}
}

/* Reduced motion: no scrub, so no scroll distance to scrub through — the stage is one still
   screen showing the poster, and the overlay copy stays at full opacity (the engine, which is
   what writes inline opacity, never runs). */
@media (prefers-reduced-motion: reduce){
  .hero.staged{height:100vh}
  .hero .hero-canvas{display:none}
  .hero .hero-poster{opacity:1}
}

/* ===== 8. motion primitives (react-bits ports, Mode B) + the occasion chips ===== */
/* SplitText — app.js wraps each word in .sw and stages it with --i. The spans only exist behind
   body.motion-on, so there is nothing to unwind for a coarse pointer or a reduced-motion visitor. */
.split .sw{display:inline-block;opacity:0;transform:translateY(.42em);
  transition:opacity .55s var(--ease),transform .55s var(--ease);transition-delay:calc(var(--i,0) * 55ms)}
.split.in .sw{opacity:1;transform:none}

/* ScrollReveal — an IntersectionObserver adds .in once per element. Runs on touch too (it is the
   reading rhythm of the page); prefers-reduced-motion switches it off at the bottom of this file. */
.sr{opacity:0;transform:translateY(18px);transition:opacity .7s var(--ease),transform .7s var(--ease);
  transition-delay:calc(var(--i,0) * 90ms)}
.sr.in{opacity:1;transform:none}

/* SpotlightCard — --mx/--my are written by app.js on pointermove, fine pointer only; the default
   50%/50% keeps the gradient centred if it is ever painted without a move. */
.spot{position:relative;isolation:isolate}
.spot::before{content:"";position:absolute;inset:0;pointer-events:none;opacity:0;
  transition:opacity .45s var(--ease);
  background:radial-gradient(42% 64% at var(--mx,50%) var(--my,50%), color-mix(in srgb, var(--metal) 18%, transparent), transparent 72%)}
@media (hover:hover) and (pointer:fine){
  .spot:hover::before,.spot:focus-within::before{opacity:1}
}

/* the occasion chips. Layout only on the container — #occasions is engine-driven (scroll-cinematic
   reasserts inline opacity/transform/visibility on it every frame), so state lives on the chips. */
.hero .occasions{display:flex;flex-wrap:wrap;justify-content:center;gap:8px;max-width:min(760px,92vw)}
.chip{min-height:44px;padding:0 18px;display:inline-flex;align-items:center;border-radius:999px;
  border:1px solid var(--rule);background:color-mix(in srgb, var(--ground) 55%, transparent);
  font-family:var(--font-ui);font-size:13px;letter-spacing:.04em;color:var(--type-2);
  transition:color .25s var(--ease),border-color .25s var(--ease),background .25s var(--ease)}
.chip[aria-checked="true"]{color:var(--type);border-color:var(--metal);
  background:color-mix(in srgb, var(--metal) 14%, transparent)}
.hero[data-grade="midnight"] .chip{background:color-mix(in srgb, var(--ink) 42%, transparent)}
@media (hover:hover) and (pointer:fine){
  .chip:hover{color:var(--type);border-color:var(--metal)}
}

/* The masthead sits OUTSIDE .hero, so it cannot inherit the grade remap — but at the top of the
   page it is transparent over the stage, and ink-on-dusk is not readable. app.js mirrors the
   chosen grade onto <html> for exactly this; once the masthead is scrolled it paints its own
   ivory ground again and the default colours are right. */
html[data-hero-grade="midnight"] .mast:not(.scrolled){--type:var(--ivory);--type-2:var(--bone)}

@media (max-width:600px){
  /* The masthead is transparent and the stage runs under it; the chip row makes the copy block
     tall enough that the eyebrow would sit behind the wordmark. Push the copy clear of it and
     tighten the chips so six of them still land in two rows. */
  .hero .hero-copy{margin-top:var(--mast-h,0px)}
  .hero .occasions{gap:6px;max-width:100%}
  .chip{padding:0 13px;font-size:12px;letter-spacing:.02em}
}

/* Touch line swap: on a coarse pointer SplitText is off, so a rewritten hero line crossfades
   rather than teleporting. The transition lives on this inner span because scroll-cinematic.js
   writes inline opacity on .reveal-line every frame; reduced motion kills it via the last rule. */
.line-fade{display:inline;transition:opacity .2s var(--ease)}
.line-fade.out{opacity:0}

/* ===== 9. the promise + how it works ===== */
.wrap{max-width:1120px;margin:0 auto;padding:0 var(--gutter)}
.promise{padding:clamp(76px,13vh,150px) 0 clamp(56px,9vh,110px)}
.promise .rule{height:1px;background:var(--metal);margin:18px 0 clamp(30px,5vh,58px)}
.promise-grid{display:grid;gap:clamp(30px,4vw,60px);grid-template-columns:1fr}
@media(min-width:768px){.promise-grid{grid-template-columns:repeat(3,1fr)}}
.promise-title{font-size:clamp(25px,2.7vw,36px);margin:0 0 10px}
.promise-item p{margin:0;max-width:40ch;color:var(--type-2);font-size:15.5px}

.how{padding:0 0 clamp(76px,13vh,150px)}
.beats{display:grid;gap:16px;grid-template-columns:1fr;margin-top:clamp(24px,4vh,44px)}
@media(min-width:768px){.beats{grid-template-columns:repeat(3,1fr)}}
.beat{padding:clamp(26px,3vw,38px);border:1px solid var(--rule);border-radius:var(--r-lg);
  background:var(--panel);overflow:hidden}
.beat>*{position:relative;z-index:1}
.beat-n{display:block;font-family:var(--font-display);font-size:clamp(34px,3.4vw,48px);line-height:1;
  color:var(--metal-deep);margin-bottom:14px}
.beat-title{font-size:clamp(21px,2vw,27px);margin:0 0 8px}
.beat p{margin:0;color:var(--type-2);font-size:15px}
/* spec §7's corporate note: one quiet line under the beats, no colour of its own. */
.how-note{margin:clamp(20px,3vh,32px) 0 0;color:var(--type-2);font-size:14px;letter-spacing:.01em}

/* ===== 10. the manifesto in motion (inverted ink) + the occasion marquee ===== */
/* .inv remaps ground/type/rule, so nothing below names a colour of its own. */
.manifesto{background:var(--ground);color:var(--type);overflow:hidden;
  padding:clamp(84px,16vh,180px) 0 clamp(52px,9vh,110px)}
.manifesto .wrap{max-width:1180px}
.manifesto-lines{display:grid;gap:clamp(4px,1.2vh,14px)}
.mline{margin:0;font-family:var(--font-display);font-weight:400;font-size:clamp(36px,7.2vw,104px);
  line-height:1.03;letter-spacing:-.015em;text-wrap:balance;overflow-wrap:anywhere}
.mline:nth-child(2){font-style:italic;color:var(--type-2)}
/* staircase indent — the three lines read as one thought, not a list */
@media(min-width:768px){
  .mline:nth-child(2){margin-left:clamp(24px,6vw,120px)}
  .mline:nth-child(3){margin-left:clamp(48px,12vw,240px)}
}

/* the section's ONE ambient: the six occasions drifting past, the strip rendered twice so the
   -50% loop is seamless. The duplicate is aria-hidden in the markup. */
.marquee{margin-top:clamp(44px,9vh,110px);padding:14px 0;overflow:hidden;
  border-top:1px solid var(--rule);border-bottom:1px solid var(--rule);
  -webkit-mask-image:linear-gradient(90deg,transparent,var(--ground) 9%,var(--ground) 91%,transparent);
  mask-image:linear-gradient(90deg,transparent,var(--ground) 9%,var(--ground) 91%,transparent)}
.mq-track{display:flex;width:max-content;animation:mq-slide 46s linear infinite}
.mq-strip{display:flex;align-items:center;gap:clamp(12px,2vw,22px);padding-right:clamp(12px,2vw,22px);
  white-space:nowrap;font-family:var(--font-display);font-style:italic;
  font-size:clamp(19px,2.4vw,30px);color:var(--type-2)}
.mq-strip::after{content:"\00B7";color:var(--metal)}
.mq-dot{color:var(--metal)}
@keyframes mq-slide{from{transform:translate3d(0,0,0)}to{transform:translate3d(-50%,0,0)}}
@media (hover:hover) and (pointer:fine){
  .marquee:hover .mq-track{animation-play-state:paused}
}

/* ===== 11. the ledger of real nights + why me ===== */
.nights{padding:clamp(76px,13vh,150px) 0 clamp(56px,9vh,110px)}
.ledger{margin-top:clamp(24px,4vh,44px);border-top:1px solid var(--metal)}
.night{display:grid;gap:clamp(12px,2vw,30px);grid-template-columns:1fr;
  padding:clamp(26px,4vh,48px) 0;border-bottom:1px solid var(--rule)}
@media(min-width:900px){
  .night{grid-template-columns:minmax(160px,.85fr) minmax(0,1.7fr) minmax(0,1.5fr);align-items:start}
  .night-meta{display:grid;gap:7px;justify-items:start}
}
.night-meta{display:flex;flex-wrap:wrap;gap:8px 16px;align-items:center;
  font-family:var(--font-ui);font-size:11.5px;font-weight:600;letter-spacing:.18em;
  text-transform:uppercase;color:var(--type-2)}
.night-meta span:first-child{color:var(--metal-deep)}
.night-title{margin:0 0 10px;font-size:clamp(29px,4.1vw,58px);font-style:italic;font-weight:400}
.night-note{margin:0;max-width:46ch;font-size:15.5px;color:var(--type-2)}
.night-shot{position:relative;margin:0;overflow:hidden;border-radius:var(--r-lg);isolation:isolate}
.night-shot img{width:100%;aspect-ratio:16/9;object-fit:cover;transition:transform .9s var(--ease)}
.night-shot .chip-sample{position:absolute;top:10px;left:10px;margin:0;
  background:color-mix(in srgb, var(--ground) 78%, transparent);
  border-color:var(--type-2);color:var(--type)}

/* GlareHover (react-bits Animations/GlareHover, ported) — app.js publishes --gx/--gy on
   pointermove behind the motion gate; the paint itself only exists for a hovering fine pointer. */
.glare{position:relative}
.glare::after{content:"";position:absolute;inset:0;z-index:1;pointer-events:none;opacity:0;
  transition:opacity .5s var(--ease);
  background:radial-gradient(40% 56% at var(--gx,50%) var(--gy,50%),
    color-mix(in srgb, var(--ivory) 48%, transparent), transparent 72%)}
@media (hover:hover) and (pointer:fine){
  .glare:hover::after,.glare:focus-within::after{opacity:1}
  .night-shot:hover img{transform:scale(1.035)}
}

/* why me — the portrait cut with the metal line running through the section */
.why{position:relative;overflow:hidden;padding:clamp(76px,13vh,150px) 0 clamp(72px,11vh,130px)}
.why::before{content:"";position:absolute;left:0;right:0;top:clamp(160px,26vh,320px);height:1px;
  background:var(--metal);opacity:.5}
.why-grid{position:relative;z-index:1;display:grid;gap:clamp(28px,5vw,64px);grid-template-columns:1fr}
@media(min-width:900px){.why-grid{grid-template-columns:minmax(0,.85fr) minmax(0,1.15fr);align-items:start}}
.portrait{position:relative;margin:0;overflow:hidden;border-radius:var(--r-lg)}
.portrait-plate{display:grid;place-items:center;aspect-ratio:4/5;
  background:var(--panel);border:1px solid var(--rule)}
.portrait-mark{font-family:var(--font-display);font-size:clamp(58px,7vw,104px);
  letter-spacing:.08em;color:var(--metal-deep)}
.portrait-plate .chip-sample{position:absolute;bottom:12px;left:12px;margin:0}
.why-para{margin:0 0 15px;max-width:52ch;font-size:16px;color:var(--type-2)}
.why-copy .eyebrow{margin:0 0 14px}
.why-para:first-of-type{font-family:var(--font-display);font-size:clamp(23px,2.7vw,34px);
  line-height:1.34;color:var(--type)}
.connections-title{margin:clamp(26px,4vh,42px) 0 12px}
.connections{display:flex;flex-wrap:wrap;gap:8px;margin:0;padding:0;list-style:none}
.connections li{padding:7px 15px;border:1px solid var(--rule);border-radius:999px;
  font-size:13px;letter-spacing:.02em;color:var(--type-2)}
.connections-note{margin:14px 0 0;max-width:52ch;font-size:13.5px;color:var(--type-2)}
.signoff{position:relative;z-index:1;margin:clamp(48px,8vh,96px) auto 0;max-width:26ch;text-align:center;
  font-family:var(--font-display);font-style:italic;font-size:clamp(26px,4vw,52px);
  line-height:1.22;color:var(--type)}
.signoff::before{content:"";display:block;width:64px;height:1px;background:var(--metal);
  margin:0 auto clamp(20px,3vh,34px)}

/* The closing CTA — the last thing on the page, sitting directly under the "you're family"
   sign-off that ends "Why me" (spec §8). No panel, no border: after a page of rules and cards the
   ending earns air instead of another box, so the rhythm is carried by space and the button is the
   only object in it. Tokens only; the metal comes in via .btn-primary, which already computes its
   own label colour at runtime. Centred at every width — it is one column of three short things. */
.inquiry-cta{padding:clamp(30px,5vh,64px) 0 clamp(104px,16vh,190px);text-align:center}
.inquiry-cta:empty{display:none}
.inquiry-inner{display:grid;justify-items:center;gap:clamp(12px,2vh,20px)}
.inquiry-heading{max-width:18ch;font-size:clamp(34px,5.2vw,68px);line-height:1.06}
.inquiry-sub{margin:0;max-width:44ch;font-size:16px;color:var(--type-2)}
.inquiry-actions{margin:clamp(12px,2.4vh,24px) 0 0}

/* Reduced motion: the reveals are simply already there, and the spotlight never paints. */
@media (prefers-reduced-motion: reduce){
  .sr{opacity:1;transform:none}
  .spot::before{display:none}
  /* the manifesto lines render static and fully visible (no word spans are ever created), the
     marquee holds still, and the glare never paints. */
  .split .sw{opacity:1;transform:none}
  .mq-track{transform:none}
  .glare::after{display:none}
}

/* ===== 12. the inquiry page + form ===== */
.inquiry-page{max-width:680px;margin:0 auto;padding:clamp(64px,11vh,120px) var(--gutter) clamp(88px,14vh,170px)}
.inquiry-page h1{font-size:clamp(38px,6vw,64px)}
.inquiry-page>p{margin:14px 0 clamp(36px,6vh,56px);max-width:52ch;color:var(--type-2);font-size:16px}
/* 404.html's one link home. The reset sets a{color:inherit}, so inside a --type-2 paragraph a bare
   link would be invisible — it gets full type colour and a metal hairline instead of a browser
   underline. Same tokens as the footer's links, no new colour. */
#notfound a{color:var(--type);text-decoration:none;border-bottom:1px solid var(--metal)}
@media (hover:hover) and (pointer:fine){ #notfound a:hover{border-bottom-color:var(--type)} }

#inquiry-form{display:grid;gap:22px}
/* keeps a focused field clear of the sticky masthead on mobile, where the field would
   otherwise land partly underneath it; --mast-h is the real measured mast height
   (syncMastHeight in app.js), plus a fixed buffer for breathing room. */
.field{display:grid;gap:8px}
.field label{font-family:var(--font-ui);font-size:13px;font-weight:600;letter-spacing:.03em;color:var(--type)}
.field .optional{font-weight:400;letter-spacing:0;color:var(--type-2)}
/* scroll-margin-top lives on the focusable control itself, not the .field wrapper: focus-driven
   scrolling (what actually happens when a keyboard/mobile user lands on a field) scrolls the
   focused element into view using ITS OWN scroll-margin, not an ancestor's. --mast-h is the real
   measured mast height (syncMastHeight in app.js) plus a fixed buffer, so a focused field is never
   left under the sticky mast on mobile, at any viewport width. */
.field input,.field select,.field textarea{
  width:100%;min-height:44px;padding:10px 14px;border:1px solid var(--rule);border-radius:var(--r);
  background:var(--panel);color:var(--type);font:inherit;font-family:var(--font-ui);font-size:15px;
  scroll-margin-top:calc(var(--mast-h, 0px) + 20px);
  transition:border-color .2s var(--ease)}
.field textarea{min-height:130px;line-height:1.5;resize:vertical}
.field select{appearance:none;background-repeat:no-repeat;background-size:10px 7px;padding-right:38px;
  background-image:linear-gradient(45deg,transparent 50%,var(--type-2) 52%),linear-gradient(135deg,var(--type-2) 52%,transparent 50%);
  background-position:calc(100% - 20px) center,calc(100% - 14px) center}
.field input::placeholder,.field textarea::placeholder{color:var(--stone)}
@media (hover:hover) and (pointer:fine){
  .field input:hover,.field select:hover,.field textarea:hover{border-color:var(--metal-deep)}
}
/* invalid fields — no alarm hue in this palette, so attention comes from weight: the ink token
   replaces the hairline rule border, same as the metal-on-focus treatment reads as "active". */
.field-invalid input,.field-invalid select,.field-invalid textarea{border-color:var(--type);box-shadow:0 0 0 1px var(--type) inset}
/* the message that belongs to ONE field, wired to it with aria-describedby (app.js). Empty until
   something is wrong, so an untouched form carries no reserved gaps. */
.field-error{margin:0;font-family:var(--font-ui);font-size:13.5px;font-weight:600;letter-spacing:.01em;color:var(--type)}
.field-error:empty{display:none}

/* the honeypot: present in the DOM for a bot that fills every field blind, reachable by nobody
   real — off-screen (never display:none/visibility:hidden) and out of tab order via the
   tabindex="-1" already on the input in the markup. */
.field.hp{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;
  clip:rect(0,0,0,0);white-space:nowrap;border:0}

#inquiry-form .btn-primary{justify-self:start;margin-top:4px}

/* the no-JS fallback notice (Fix round 1): only ever painted when scripts are off, so it gets its
   own quiet card rather than inheriting body defaults. Same tokens as the rest of the page. */
.noscript-notice{margin:0;padding:16px 18px;max-width:48ch;border:1px solid var(--rule);
  border-radius:var(--r-lg);background:var(--panel);color:var(--type);font-size:14.5px;line-height:1.5}

#formStatus{margin-top:2px;scroll-margin-top:calc(var(--mast-h, 0px) + 20px)}
#formStatus:empty{display:none}
#formStatus p{margin:0 0 14px;max-width:48ch;font-size:15.5px;color:var(--type)}
#formStatus[data-state="success"]::before{content:"";display:block;width:36px;height:1px;background:var(--metal);margin-bottom:14px}
#formStatus[data-state="invalid"] p,#formStatus[data-state="throttled"] p{color:var(--type-2)}
.btn-retry{min-height:44px;padding:0 22px;font-size:13px}

/* reduced-motion override stays last — later tasks insert new sections above this line */
@media (prefers-reduced-motion: reduce){ *,*::before,*::after{transition:none !important;animation:none !important;scroll-behavior:auto !important} }
