/* Jiavelle site.css — v2 build 2026-09-10 against website/design/canvas-v2/ (the approved
   refined system: six rules) plus website/design/vision/DESIGN-LAWS.md and the measured
   contrast floor from website/design/redesign/readability/.
   RULE 1 one display line per screen · RULE 2 one caption slot that never moves (gutter in,
   64 up; phone 24 / 40) · RULE 3 the ground comes before the words (one feathered ivory
   scrim, never a box) · RULE 4 three faces: Marcellus display, Cormorant Garamond italic =
   exactly one quiet line per page, Noto Sans functional · RULE 5 one spacing scale
   (4 8 12 16 24 32 48 64 96 128 160; gutter 96, section 128, gaps 48/24) · RULE 6 contrast
   floor 4.5:1 (#8C8A84 retired for text; mute #5F5D57). One ground (ivory), one ink, one mute, one accent (sand).
   Two hairline colours only: var(--line) and rgba(30,30,28,.18). No box-shadow, no
   backdrop-filter, no border-radius, no scroll-behavior:smooth, no raw durations or curves. */

/* ============================== 1. TOKENS ============================== */
:root{
  /* colour — law 2.6. --grey (#8C8A84, 3.17:1) and --paper are RETIRED. */
  --ink:#1E1E1C; --mute:#5F5D57; --ivory:#F7F5F0; --sand:#D8CBB3;
  --line:#E4DFD5;                 /* hairline A: warm rule on ivory */
  --hair:rgba(30,30,28,.18);      /* hairline B: ink-tinted rule (the only other one) */

  /* faces — law 1.1. --fdisp / --fui are the per-language indirections. */
  --display:Marcellus,Georgia,"Times New Roman",serif;
  --quiet:"Cormorant Garamond",Georgia,serif;        /* rule 4: ONE quiet line per page */
  --ui:"Noto Sans",system-ui,sans-serif;
  --fdisp:var(--display);
  --fui:var(--ui);
  --fquiet:var(--quiet);
  --quiet-style:italic;

  /* fluid type — law 1.2 + addendum 1 (hero max 96 px, ratio 2.18 < 2.5) */
  --t-hero:clamp(2.75rem,1.543rem + 4.952vw,6rem);
  --t-h1:clamp(2.375rem,1.49rem + 3.62vw,4.75rem);
  --t-h2:clamp(2rem,1.44rem + 2.29vw,3.5rem);
  --t-h3:clamp(1.375rem,1.14rem + 0.95vw,2rem);
  --t-lead:clamp(1.125rem,1.03rem + 0.38vw,1.375rem);
  --t-body:clamp(1rem,0.98rem + 0.1vw,1.0625rem);
  --t-small:clamp(0.875rem,0.86rem + 0.1vw,0.9375rem);
  --t-eyebrow:clamp(0.6875rem,0.67rem + 0.1vw,0.75rem);
  --t-caps:var(--t-eyebrow);      /* uppercase label size; Arabic raises it (see below) */

  /* line-height — law 1.3. --lh-bump is +0.2 for Arabic and Chinese. */
  --lh-bump:0;
  --lh-hero:calc(1 + var(--lh-bump));
  --lh-h:calc(1.08 + var(--lh-bump));
  --lh-h3:calc(1.2 + var(--lh-bump));
  --lh-lead:calc(1.5 + var(--lh-bump));
  --lh-body:calc(1.65 + var(--lh-bump));
  --lh-small:calc(1.6 + var(--lh-bump));

  /* tracking — law 1.4. Every one of these is 0 in Arabic. */
  --tr-hero:-.015em; --tr-h:-.01em; --tr-body:0;
  --tr-caps:.2em;    --tr-nav:.18em; --tr-mark:.28em; --tr-sm:.1em;
  --tx-caps:uppercase;            /* Arabic has no case: becomes none */

  /* spacing — law 2.1: 4 8 12 16 24 32 48 64 96 128 160, nothing else */
  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:24px; --s6:32px;
  --s7:48px; --s8:64px; --s9:96px; --s10:128px; --s11:160px;
  --gutter:clamp(1.5rem,-0.171rem + 6.857vw,6rem);  /* rule 5 — 24 @390 -> 96 @1440 */
  --sec-y:clamp(4rem,8vw,8rem);       /* rule 5 — section 128 at 1440 */
  --slot-b:64px;                      /* rule 2 — the caption slot baseline (phone 40) */
  --nav-h:80px;                       /* law 6.2 — 80 floating, 56 shrunk */

  /* motion — law 3.1. Every transition in this file references these. */
  --e-out:cubic-bezier(.22,1,.36,1);
  --e-soft:cubic-bezier(.16,1,.3,1);
  --d-1:150ms; --d-2:250ms; --d-3:400ms; --d-4:900ms;   /* d-4 = ambient / one big reveal */

  --fa:2.33;                          /* frame aspect; build.py re-sets it on .scrub */
}
html[lang=ar]{
  --fdisp:"Noto Naskh Arabic",serif;
  --fquiet:"Noto Naskh Arabic",serif; --quiet-style:normal;
  --fui:"Noto Kufi Arabic","Noto Naskh Arabic","Noto Sans",sans-serif;
  --lh-bump:.2;
  --tr-hero:0; --tr-h:0; --tr-body:0; --tr-caps:0; --tr-nav:0; --tr-mark:0; --tr-sm:0;
  --tx-caps:none;
  --t-caps:var(--t-small);            /* 12 px caps are unreadable in Naskh; the canvas uses 15 */
}
html[lang=zh]{
  --fdisp:"Noto Serif SC","Songti SC",serif;
  --fquiet:"Noto Serif SC","Songti SC",serif; --quiet-style:normal;
  --fui:"Noto Sans SC","PingFang SC",sans-serif;
  --lh-bump:.2;
  --tr-hero:0; --tr-h:0;              /* never negative-track CJK */
}

/* ============================== 2. BASE ============================== */
*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0;background:var(--ivory);color:var(--ink);
  font-family:var(--fui);font-weight:400;font-size:var(--t-body);
  line-height:var(--lh-body);letter-spacing:var(--tr-body);
  font-variant-numeric:lining-nums;            /* law 11.21 / audit 21 + 38: no old-style figures */
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;
}
a{color:inherit;text-decoration:none}
img{max-width:100%;display:block}
button{font:inherit;color:inherit}
h1,h2,h3{font-family:var(--fdisp);font-weight:400;margin:0;letter-spacing:var(--tr-h);line-height:var(--lh-h)}
h3{font-size:var(--t-h3);line-height:var(--lh-h3)}
:where(a,button,input,textarea,select,[tabindex]):focus-visible{outline:2px solid var(--ink);outline-offset:3px}
.wrap{max-width:1440px;margin:0 auto;padding-inline:var(--gutter)}
.num{unicode-bidi:isolate;direction:ltr}
[id]{scroll-margin-top:calc(var(--nav-h) + var(--s5))}   /* the nav floats: anchors must clear it */

/* eyebrow / uppercase label — one rule, everywhere */
.kick,.eyebrow{font-size:var(--t-caps);font-weight:500;letter-spacing:var(--tr-caps);text-transform:var(--tx-caps);color:var(--mute);line-height:var(--lh-small);margin:0 0 var(--s3)}

/* ============================== 3. ATMOSPHERE (law 7.3) ============================== */
.grain{
  position:fixed;inset:0;z-index:45;pointer-events:none;opacity:.07;mix-blend-mode:multiply;
  background-size:200px 200px;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><filter id='n' color-interpolation-filters='sRGB'><feTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0  0 0 0 0 0  0 0 0 0 0  0 0 0 .55 0'/></filter><rect width='200' height='200' filter='url(%23n)'/></svg>");
}
.vig{position:absolute;inset:0;pointer-events:none;background:radial-gradient(120% 90% at 50% 40%,rgba(30,30,28,0) 58%,rgba(30,30,28,.16) 100%)}
/* RULE 3 — the ground comes before the words. One feathered wash of the page's own ivory,
   bottom-anchored, over the bottom 62 % (canvas-v2 Stop1-6). No box, no blur, no text glow.
   The stops are steeper than a straight 0->96 ramp because the plateau has to reach the
   TOP of the slot, not just its baseline: ~.90 is the alpha at which --mute still clears
   4.5:1 over the darkest ground in the story (design/redesign/readability/AUDIT.md), and
   the plateau is MEASURED, not chosen. A stop that carries more words (the three callouts,
   the end block) gets a taller ground, never a different one.
   .top = the nav strip. .h = the taller, softer ground the first screen's head needs
   (ink only, so far less alpha). .side = the inline-end column on the callout stop. */
.scrim{position:absolute;left:0;right:0;bottom:0;height:62%;pointer-events:none;
  background:linear-gradient(180deg,
    rgba(247,245,240,0) 0%,rgba(247,245,240,.34) 16%,rgba(247,245,240,.72) 32%,
    rgba(247,245,240,.90) 46%,rgba(247,245,240,.95) 62%,rgba(247,245,240,.97) 80%,
    rgba(247,245,240,.985) 100%)}
/* more words on the screen = more ground, same wash (rule 3) */
.pin:has(.callouts.on) .scrim,.pin:has(.end.on) .scrim{height:80%}
.scrim.top{top:0;bottom:auto;height:22%;
  background:linear-gradient(180deg,rgba(247,245,240,.90) 0%,rgba(247,245,240,.52) 52%,rgba(247,245,240,0) 100%)}
.scrim.h,.scrim.side{opacity:0;transition:opacity var(--d-3) var(--e-out)}
.scrim.h{height:92%;
  background:linear-gradient(180deg,
    rgba(247,245,240,0) 0%,rgba(247,245,240,.42) 18%,rgba(247,245,240,.68) 36%,
    rgba(247,245,240,.84) 54%,rgba(247,245,240,.90) 74%,rgba(247,245,240,.92) 100%)}
/* the callout column is 325 px wide inside a 96 px gutter, so the plateau has to hold for
   421 px from the inline end before it may start feathering: 64 % of a 46 % band. */
.scrim.side{left:auto;inset-inline-end:0;top:0;bottom:0;width:46%;height:auto;
  --wash:rgba(247,245,240,.96) 0%,rgba(247,245,240,.94) 48%,rgba(247,245,240,.92) 64%,
    rgba(247,245,240,.60) 78%,rgba(247,245,240,.22) 90%,rgba(247,245,240,0) 100%;
  background:linear-gradient(270deg,var(--wash))}
/* mirrored, not flipped: scaleX(-1) would put the opaque end of the band in the middle
   of the frame and show a hard edge. The band is re-drawn from the inline end instead. */
html[dir=rtl] .scrim.side{background:linear-gradient(90deg,var(--wash))}
.pin:not(.headgone) .scrim.h{opacity:1}
.pin:has(.callouts.on) .scrim.side{opacity:1}

/* the 1 px progress rail — law 4.6. transform only, never width. */
.rail{position:fixed;inset-inline:0;top:0;height:1px;background:var(--hair);z-index:60;pointer-events:none}
.rail i{display:block;height:100%;background:var(--ink);transform:scaleX(0);transform-origin:0 50%}

/* ============================== 4. COMPONENTS ============================== */
/* one button component — law 8.5, four states */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:var(--s3);
  height:56px;padding:0 var(--s6);border:1px solid var(--ink);border-radius:0;
  background:transparent;color:var(--ink);font-family:var(--fui);font-weight:500;
  font-size:var(--t-caps);letter-spacing:var(--tr-nav);text-transform:var(--tx-caps);
  white-space:nowrap;cursor:pointer;
  transition:background-color var(--d-2) var(--e-out),color var(--d-2) var(--e-out),scale var(--d-1) var(--e-out);
}
.btn.fill{background:var(--ink);color:var(--ivory)}
.btns{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s4)}
@media (hover:hover){
  .btn:hover{background:var(--ink);color:var(--ivory)}
  .btn.fill:hover{background:transparent;color:var(--ink)}
}
.btn:active{scale:.98}
.btn:focus-visible{outline:2px solid var(--ink);outline-offset:3px}

/* the drawn-underline link — law 8.2 */
.lnk{
  position:relative;display:inline-block;color:var(--ink);font-weight:500;
  font-size:var(--t-caps);letter-spacing:var(--tr-nav);text-transform:var(--tx-caps);
  padding-bottom:var(--s2);margin-inline-end:var(--s6);
  border-bottom:1px solid var(--hair);
}
.lnk:after{
  content:"";position:absolute;inset-inline-start:0;bottom:-1px;width:100%;height:1px;
  background:var(--ink);transform:scaleX(0);transform-origin:0 50%;
  transition:transform var(--d-2) var(--e-out);
}
.lnk:hover:after,.lnk:focus-visible:after{transform:scaleX(1)}
.lnk.g{color:var(--mute);border-bottom-color:var(--line)}

/* masked display line — law 4.5. Guarded by html.js so a JS failure renders plain text. */
.mask{display:block;overflow:hidden;padding-bottom:.12em;margin-bottom:-.12em}
.mask>span{display:inline-block}
html.js .mask>span{transform:translateY(110%);transition:transform var(--d-4) var(--e-soft)}
html.js :is(.in,.hero-in,.mask.in) .mask>span,html.js .mask.in>span{transform:none}

/* section reveal — law 9.3 (never hide the body), law 11.21 (no parked will-change) */
html.js .reveal{opacity:0;transform:translateY(16px);transition:opacity var(--d-3) var(--e-out),transform var(--d-3) var(--e-out)}
html.js .reveal.in{opacity:1;transform:none}
/* children stagger 40 ms — law 3.4. animation, not transition, so hover transforms stay free. */
@keyframes rise{from{opacity:0}to{opacity:1}}
html.js .reveal :is(.doors,.grid,.stats,.steps)>*{opacity:0}
html.js .reveal.in :is(.doors,.grid,.stats,.steps)>*{animation:rise var(--d-3) var(--e-out) both}
html.js .reveal.in :is(.doors,.grid,.stats,.steps)>:nth-child(2){animation-delay:40ms}
html.js .reveal.in :is(.doors,.grid,.stats,.steps)>:nth-child(3){animation-delay:80ms}
html.js .reveal.in :is(.doors,.grid,.stats,.steps)>:nth-child(4){animation-delay:120ms}
html.js .reveal.in :is(.doors,.grid,.stats,.steps)>:nth-child(5){animation-delay:160ms}
html.js .reveal.in :is(.doors,.grid,.stats,.steps)>:nth-child(6){animation-delay:200ms}
html.js .reveal.in :is(.doors,.grid,.stats,.steps)>:nth-child(7){animation-delay:240ms}
html.js .reveal.in :is(.doors,.grid,.stats,.steps)>:nth-child(8){animation-delay:280ms}
html.js .reveal.in :is(.doors,.grid,.stats,.steps)>:nth-child(9){animation-delay:320ms}
html.js .reveal.in :is(.doors,.grid,.stats,.steps)>:nth-child(n+10){animation-delay:360ms}

/* ============================== 5. NAV (law 6.1–6.3) ============================== */
nav{
  position:fixed;inset-inline:0;top:0;z-index:50;background:none;border:0;color:var(--ink);
  transition:transform var(--d-3) var(--e-out),background-color var(--d-3) var(--e-out);
}
nav .wrap{
  display:flex;align-items:center;justify-content:space-between;gap:var(--s6);
  height:var(--nav-h);font-size:var(--t-caps);font-weight:500;letter-spacing:var(--tr-nav);
  text-transform:var(--tx-caps);transition:height var(--d-3) var(--e-out);
}
nav.small .wrap{height:56px}
nav.hide{transform:translateY(-110%)}
nav.open,nav.solid{transform:none}
nav.solid{background:var(--ivory);border-bottom:1px solid var(--line)}
/* law 6.4: no mix-blend-mode. site.js may flag a dark stop with nav.on-dark. */
nav{transition:transform var(--d-3) var(--e-out),background-color var(--d-3) var(--e-out),color var(--d-3) var(--e-out)}
nav.on-dark:not(.solid){color:var(--ivory)}
nav.on-dark:not(.solid) .langs a{color:rgba(247,245,240,.65)}
nav.on-dark:not(.solid) .langs a.on{color:var(--ivory)}
.sq{width:22px;height:22px;flex:none;background:url(/assets/mark.svg) center/contain no-repeat}
nav.on-dark:not(.solid) .sq{background-image:url(/assets/mark-dark.svg)}
.logo{font-family:var(--fdisp);font-size:21px;letter-spacing:var(--tr-mark);text-transform:none;display:flex;align-items:center;gap:var(--s3);flex:none}
nav.small .logo{font-size:17px;transition:font-size var(--d-3) var(--e-out)}
.nl-wrap{display:flex;align-items:center;gap:var(--s6)}
.nl-wrap a{position:relative;transition:opacity var(--d-1) var(--e-out)}
@media (hover:hover){.nl-wrap a:hover{opacity:.6}}
.langs{display:flex;gap:var(--s3);flex:none}
.langs a{color:var(--mute);letter-spacing:0;transition:color var(--d-1) var(--e-out)}  /* never track a language token */
.langs a.on{color:var(--ink)}
@media (hover:hover){.langs a:hover{color:var(--ink)}}
.menu{display:none;appearance:none;-webkit-appearance:none;background:none;border:0;padding:0;font:inherit;color:inherit}

/* ============================== 6. THE PINNED HERO (laws 4, 6.1) ============================== */
.scrub{position:relative;height:560vh;background:var(--ivory)}   /* site.js sets the real height */
.pin{position:sticky;top:0;height:100vh;overflow:hidden}
@supports (height:100dvh){.pin{height:100dvh}}
canvas.scrubc{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block;background:none}
.poster{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;transition:opacity var(--d-3) var(--e-out)}
.poster.off{opacity:0}

/* the words layer: head in a flexible top row, captions pinned to the bottom row,
   so nothing jumps when .head goes. */
.over{
  position:absolute;inset:0;display:grid;grid-template-rows:1fr auto;align-items:end;
  padding-block:calc(var(--nav-h) + var(--s5)) var(--slot-b);pointer-events:none;
}
.head{grid-row:1;align-self:end;display:flex;align-items:flex-end;justify-content:space-between;gap:var(--s7);transition:opacity var(--d-3) var(--e-out)}
.head>div:first-child{display:flex;flex-direction:column;transition:opacity var(--d-3) var(--e-out)}
.head.gone>div:first-child,.head.gone .hint{opacity:0}
.pin .kick{color:var(--ink)}
.pin h1{font-size:var(--t-hero);line-height:var(--lh-hero);letter-spacing:var(--tr-hero);max-width:14em;text-shadow:none}
.pin .lead,.head p{font-size:var(--t-lead);line-height:var(--lh-lead);max-width:46ch;margin:var(--s5) 0 0;color:var(--ink)}

/* SCROLL hint: a word and a 1 px 56 px line. No chip, no percentage. */
.hint{
  flex:none;display:flex;flex-direction:column;align-items:center;gap:var(--s3);
  font-size:var(--t-caps);letter-spacing:var(--tr-caps);text-transform:var(--tx-caps);
  color:var(--ink);white-space:nowrap;background:none;padding:0;text-shadow:none;
  transition:opacity var(--d-3) var(--e-out);
}
.hint .line{display:block;width:1px;height:56px;background:var(--ink)}
.hint:not(:has(.line)):after{content:"";display:block;width:1px;height:56px;background:var(--ink)}

/* RULE 2 — one caption slot, and it never moves: the gutter in, --slot-b up, on every
   stop, every language, phone and desktop. No box, no blur, no fixed height. */
.caps{grid-row:2;display:grid;align-items:end;max-width:none;position:relative}
@media (min-width:1001px){.caps.phone{display:none}}   /* desktop story: h0..h5 */
.cap{
  grid-area:1/1;justify-self:start;align-self:end;max-width:40rem;
  opacity:0;transform:translateY(34px);background:none;padding:0;
  transition:opacity var(--d-3) var(--e-out),transform var(--d-3) var(--e-out);
}
.cap.on{opacity:1;transform:none}
.cap.past{opacity:0;transform:translateY(-34px)}
html:not(.js) .caps{display:block}
html:not(.js) .cap{position:static;opacity:1;transform:none;margin-bottom:var(--s5)}
.cap b{display:block;font-family:var(--fdisp);font-weight:400;font-size:var(--t-h2);line-height:var(--lh-h);letter-spacing:var(--tr-h);max-width:12em;margin-bottom:var(--s4)}
.cap p{margin:0;color:var(--mute);font-size:var(--t-lead);line-height:var(--lh-lead);max-width:46ch}

/* numbered callouts for the three-layers stop — law 4.4, hairline not box */
/* RULE 1 — the three spec callouts are NOT a second hero: 15 px, inline-end column, on
   their own right-edge scrim. Only "Three layers." is display on that screen. */
.callouts{
  position:absolute;inset-inline-end:var(--gutter);top:20%;
  display:flex;flex-direction:column;gap:var(--s6);width:min(300px,26vw);pointer-events:none;
}
.callout{
  border-inline-start:1px solid var(--ink);padding-inline-start:var(--s5);
  display:flex;flex-direction:column;gap:var(--s1);
  transition:opacity var(--d-3) var(--e-out),transform var(--d-3) var(--e-out);
}
.callout .kick,.callout .eyebrow{color:var(--ink);margin:0}
.callout b{display:block;font-weight:500;font-size:var(--t-small);line-height:var(--lh-small);color:var(--ink)}
.callout p{margin:0;color:var(--mute);font-size:var(--t-small);line-height:var(--lh-small)}
html.js .callout{opacity:0;transform:translateX(24px)}
html.js .callouts.on .callout{opacity:1;transform:none}
html.js .callouts.on .callout:nth-child(2){transition-delay:40ms}
html.js .callouts.on .callout:nth-child(3){transition-delay:80ms}

/* end stop — law 4.7. No card, bottom-left, two buttons, opens at p >= 0.90. */
.end{
  position:absolute;inset-inline:0;bottom:0;padding:0 var(--gutter) var(--slot-b);
  opacity:0;transform:translateY(16px);pointer-events:none;
  transition:opacity var(--d-4) var(--e-soft),transform var(--d-4) var(--e-soft);
}
.end.on{opacity:1;transform:none;pointer-events:auto}
.end{display:flex;flex-direction:column;align-items:flex-start;gap:var(--s5);max-width:34rem}
.end b,.end p{margin:0}
.end b{display:block;font-family:var(--fdisp);font-weight:400;font-size:var(--t-h2);line-height:var(--lh-h);letter-spacing:var(--tr-h);max-width:12em}
.end p{color:var(--mute);font-size:var(--t-lead);line-height:var(--lh-lead);max-width:46ch}
.end .lnk{margin:0 var(--s4) 0 0}
.pin.ended .caps,.pin.ended .hint,.pin.ended .callouts{opacity:0;transition:opacity var(--d-3) var(--e-out)}

/* ============================== 7. STATIC HERO (inner pages) ============================== */
.hero{display:grid;grid-template-columns:5fr 7fr;align-items:center;gap:var(--s8);padding:calc(var(--nav-h) + var(--s7)) 0 var(--s8)}
.hero h1{font-size:var(--t-h1);max-width:14em;margin:0 0 var(--s5)}
.hero p{font-size:var(--t-lead);line-height:var(--lh-lead);color:var(--mute);max-width:50ch;margin:0 0 var(--s6)}
.hero .im{background:var(--ivory);aspect-ratio:4/3;overflow:hidden}
.hero .im img{width:100%;height:100%;object-fit:cover}

/* ============================== 8. SECTIONS ============================== */
.sec{padding:var(--sec-y) 0}
.sec h2{font-size:var(--t-h2);max-width:16em;margin:0 0 var(--s6)}
.sub{font-size:var(--t-lead);line-height:var(--lh-lead);color:var(--mute);max-width:50ch;margin:0 0 var(--s7)}
.grp{font-size:var(--t-caps);letter-spacing:var(--tr-caps);text-transform:var(--tx-caps);color:var(--mute);border-bottom:1px solid var(--line);padding-bottom:var(--s3);margin:var(--s9) 0 var(--s5)}
.grp:first-of-type{margin-top:0}

/* the genre doors — 7 across when there are exactly 7, else auto-fit; 24 / 16 gap */
.doors{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:var(--s5)}
.doors:has(>:nth-child(7)):not(:has(>:nth-child(8))){grid-template-columns:repeat(7,1fr)}
.doors:has(>:nth-child(9)):not(:has(>:nth-child(10))){grid-template-columns:repeat(5,1fr)}
.door{display:flex;flex-direction:column;gap:var(--s3);color:var(--ink)}
.door .im{background:var(--ivory);aspect-ratio:4/5;overflow:hidden}
.door img{width:100%;height:100%;object-fit:cover}
.dl{display:flex;justify-content:space-between;align-items:baseline;gap:var(--s2);font-size:var(--t-small);line-height:var(--lh-small);padding:0;border:0}
.dl>span:first-child{position:relative}
.dl>span:first-child:after{content:"";position:absolute;inset-inline-start:0;bottom:-2px;width:100%;height:1px;background:var(--ink);transform:scaleX(0);transform-origin:0 50%;transition:transform var(--d-3) var(--e-out)}
.dl>span:last-child{color:var(--mute);white-space:nowrap}
.dl>small{flex:none;font-size:var(--t-caps);letter-spacing:var(--tr-caps);text-transform:var(--tx-caps);color:var(--mute);margin:0}
.dl:after{content:"\2192";flex:none;color:var(--mute);opacity:0;transform:translateX(-4px);transition:opacity var(--d-2) var(--e-out),transform var(--d-2) var(--e-out)}
html[dir=rtl] .dl:after{content:"\2190";transform:translateX(4px)}
@media (hover:hover){
  .door,.card{transition:transform var(--d-3) var(--e-out)}
  .door img,.card img{transition:transform var(--d-3) var(--e-out)}
  .door:hover,.card:hover{transform:translateY(-8px)}
  .door:hover img,.card:hover img{transform:scale(1.04)}
  .door:hover .dl>span:first-child:after{transform:scaleX(1)}
  .door:hover .dl:after{opacity:1;transform:none}
}

/* the factory band — one ground, no per-section background (law 5.1) */
.fac{background:none}
.fac .wrap{display:grid;grid-template-columns:1fr 1fr;gap:var(--s8);align-items:center}
.fac h2{margin-bottom:var(--s5)}
.fac p{font-size:var(--t-body);line-height:var(--lh-body);color:var(--mute);max-width:62ch;margin:0 0 var(--s7)}
.fac .im{aspect-ratio:4/3;overflow:hidden;background:var(--ivory)}
.fac img{width:100%;height:100%;object-fit:cover}

/* proof numbers */
.stats{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--s5);border-top:1px solid var(--hair);padding-top:var(--s5)}
.stats>div,.stat{display:flex;flex-direction:column;gap:var(--s2)}
.stat b,.stats b{display:block;font-family:var(--fdisp);font-weight:400;font-size:var(--t-h3);line-height:var(--lh-h3);font-variant-numeric:lining-nums}
.stat small,.stats small,.stat .kick,.stat .eyebrow{font-size:var(--t-caps);letter-spacing:var(--tr-caps);text-transform:var(--tx-caps);color:var(--mute);margin:0}

/* the home contact block — left-aligned, h2 at the h2 scale (audit 23, 24) */
.contact{padding:var(--sec-y) 0;text-align:start}
.contact h2{font-size:var(--t-h2);max-width:16em;margin:0 0 var(--s4)}
.contact p{color:var(--mute);font-size:var(--t-lead);line-height:var(--lh-lead);max-width:50ch;margin:0 0 var(--s6)}

footer{border-top:1px solid var(--line);margin-top:var(--sec-y)}
footer .wrap{display:flex;flex-wrap:wrap;justify-content:space-between;gap:var(--s3) var(--s5);padding-block:var(--s5);font-size:var(--t-caps);letter-spacing:var(--tr-sm);color:var(--mute)}

/* off-scale inline styles used to live in build.py; they are on the scale now */
.gh{font-size:var(--t-h3);line-height:var(--lh-h3);margin:var(--s5) 0 var(--s4)}
.sh{font-size:var(--t-h3);line-height:var(--lh-h3);margin:0 0 var(--s5)}
.sh:has(+.sub){margin-bottom:var(--s2)}
.sh+.sub{margin:0 0 var(--s6)}
.btns.pad{padding:var(--s5) 0 var(--s9)}
.facband{margin:0 0 var(--s8)}
.facband img{width:100%;aspect-ratio:21/9;object-fit:cover}
.grid.tight{margin-bottom:var(--s7)}

/* ============================== 9. COLLECTION ============================== */
.pagehead{padding:calc(var(--nav-h) + var(--s8)) 0 var(--s7)}
.pagehead h1{font-size:var(--t-h1);max-width:14em;margin:0 0 var(--s3)}
.pagehead p{color:var(--mute);font-size:var(--t-lead);line-height:var(--lh-lead);max-width:50ch;margin:0}
.series-nav{display:flex;flex-wrap:wrap;gap:var(--s2) var(--s5);font-size:var(--t-caps);letter-spacing:var(--tr-nav);text-transform:var(--tx-caps);border-top:1px solid var(--line);padding:var(--s4) 0;margin-bottom:var(--s7)}
.series-nav a{position:relative;color:var(--mute);padding:var(--s1) 0;transition:color var(--d-1) var(--e-out)}
.series-nav a:hover{color:var(--ink)}
.series-nav a.on{color:var(--ink);border-bottom:1px solid var(--ink)}
.grid{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s7) var(--s5);margin-bottom:var(--s9)}
.card{display:flex;flex-direction:column;gap:var(--s3);color:var(--ink)}
.card .im{background:var(--ivory);aspect-ratio:4/5;overflow:hidden}
.card img{width:100%;height:100%;object-fit:cover}
.card h3,.steps h3{font-family:var(--fdisp);font-weight:400;font-size:var(--t-lead);line-height:var(--lh-h3);letter-spacing:var(--tr-h);margin:0}
.card p{margin:0;color:var(--mute);font-size:var(--t-small);line-height:var(--lh-small)}

/* ============================== 10. PRODUCT ============================== */
.prod{display:grid;grid-template-columns:7fr 5fr;gap:var(--s8);padding:calc(var(--nav-h) + var(--s7)) 0 var(--s9);align-items:start}
.prod .im{background:var(--ivory);aspect-ratio:4/5;overflow:hidden;position:sticky;top:calc(var(--nav-h) + var(--s5))}
.prod .im img{width:100%;height:100%;object-fit:cover}
.prod h1{font-size:var(--t-h1);max-width:14em;margin:0 0 var(--s4)}
.prod .desc{font-size:var(--t-body);line-height:var(--lh-body);color:var(--mute);max-width:62ch;margin:0 0 var(--s6)}
.spec{border-top:1px solid var(--line);margin:0 0 var(--s6)}
.spec div{display:grid;grid-template-columns:170px 1fr;gap:var(--s5);padding:var(--s3) 0;border-bottom:1px solid var(--line);font-size:var(--t-small);line-height:var(--lh-small)}
.spec div span:first-child{color:var(--mute);font-size:var(--t-caps);letter-spacing:var(--tr-caps);text-transform:var(--tx-caps);padding-top:2px}
.note{font-size:var(--t-small);line-height:var(--lh-small);color:var(--mute);margin:0 0 var(--s6)}
.pn{display:grid;grid-template-columns:1fr auto 1fr;align-items:center;gap:var(--s5);font-size:var(--t-caps);letter-spacing:var(--tr-nav);text-transform:var(--tx-caps);color:var(--mute);border-top:1px solid var(--line);padding:var(--s5) 0 var(--s9)}
.pn>span:last-child{text-align:end}
.pn a{color:var(--ink)}
.pn .prev:before{content:"\2190\00a0"}
.pn .next:after{content:"\00a0\2192"}
html[dir=rtl] .pn .prev:before{content:"\2192\00a0"}
html[dir=rtl] .pn .next:after{content:"\00a0\2190"}
.pn .lnk{margin-inline-end:0}

/* ============================== 11. FACTORY ============================== */
.two{display:grid;grid-template-columns:1fr 1fr;gap:var(--s8);align-items:start;padding:0 0 var(--s8)}
.two h2{font-size:var(--t-h3);margin:0 0 var(--s4)}
.two p{color:var(--mute);font-size:var(--t-body);line-height:var(--lh-body);max-width:62ch;margin:0}
.steps{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--s5);margin:0 0 var(--s9)}
.steps div{border-top:1px solid var(--line);padding-top:var(--s4)}
.steps b{display:block;font-family:var(--fdisp);font-weight:400;font-size:var(--t-h3);line-height:var(--lh-h3);margin-bottom:var(--s3);font-variant-numeric:lining-nums}
.steps h3{margin:0 0 var(--s1)}
.steps p{margin:0;color:var(--mute);font-size:var(--t-small);line-height:var(--lh-small)}
.tbl{border-top:1px solid var(--line);margin-bottom:var(--s5)}
.tbl div{display:grid;grid-template-columns:220px 1fr;gap:var(--s5);padding:var(--s3) 0;border-bottom:1px solid var(--line);font-size:var(--t-small);line-height:var(--lh-small)}
.tbl div span:first-child{color:var(--mute)}

/* ============================== 12. CONTACT PAGE ============================== */
.cgrid{display:grid;grid-template-columns:1fr 1fr;gap:var(--s8);padding:0 0 var(--s9)}
.clist div{padding:var(--s4) 0;border-bottom:1px solid var(--line)}
.clist .eyebrow{display:block;font-size:var(--t-caps);letter-spacing:var(--tr-caps);text-transform:var(--tx-caps);color:var(--mute);margin-bottom:var(--s1)}
.clist .btns{padding:var(--s5) 0 0;border:0}
.clist a{font-size:var(--t-lead)}
form label{display:block;font-size:var(--t-caps);letter-spacing:var(--tr-caps);text-transform:var(--tx-caps);color:var(--mute);margin:var(--s5) 0 var(--s2)}
form input,form textarea{width:100%;border:0;border-bottom:1px solid var(--hair);background:none;font:inherit;font-size:var(--t-body);padding:var(--s2) 0;color:var(--ink);border-radius:0;transition:border-color var(--d-2) var(--e-out)}
form input:hover,form textarea:hover{border-bottom-color:var(--ink)}
form input:focus,form textarea:focus{border-bottom-color:var(--ink)}
form textarea{min-height:96px;resize:vertical}
form .btn{margin-top:var(--s6)}
button.lnk{background:none;border:0;border-bottom:1px solid var(--ink);cursor:pointer;margin-top:var(--s6);padding:0 0 var(--s2)}
.draft{font-size:var(--t-caps);letter-spacing:var(--tr-sm);color:var(--mute);padding:var(--s2) 0;text-align:center;border-bottom:1px solid var(--line)}

/* ====================== 12b. THE QUIET LINE (rule 4) ====================== */
/* Cormorant Garamond italic has exactly one job and one place: the sub-line under the page
   head (product, series, collection, factory, contact) and, on the home page, the contact
   invitation — never body, never UI, never twice on one page. Last in the cascade on
   purpose: it must beat the per-section p rules above. */
.quiet,.pagehead p,.hero p,.prod .desc,.scrub~.contact p{
  font-family:var(--fquiet);font-style:var(--quiet-style);font-weight:400;
  font-size:var(--t-h3);line-height:var(--lh-h3);letter-spacing:0;
  color:var(--mute);max-width:46ch;margin-block:0 var(--s6);
}

/* ============================== 13. VIEW TRANSITIONS (law 10) ============================== */
@view-transition{navigation:auto}
.vt-adult-quilts{view-transition-name:vt-adult-quilts}
.vt-adult-bedcovers{view-transition-name:vt-adult-bedcovers}
.vt-adult-pillows{view-transition-name:vt-adult-pillows}
.vt-adult-sets{view-transition-name:vt-adult-sets}
.vt-kids-quilts{view-transition-name:vt-kids-quilts}
.vt-kids-pillows{view-transition-name:vt-kids-pillows}
.vt-kids-sets{view-transition-name:vt-kids-sets}
.vt-multi-pillows{view-transition-name:vt-multi-pillows}
.vt-sleeping-bags{view-transition-name:vt-sleeping-bags}

/* ============================== 14. PHONE (<= 1000 px) ============================== */
@media (max-width:1000px){
  :root{--nav-h:64px}
  nav .wrap{gap:var(--s3)}
  .langs{margin-inline-start:auto}
  .menu{display:block;position:relative;width:40px;height:40px;flex:none;cursor:pointer}
  .menu:before,.menu:after{content:"";position:absolute;inset-inline:8px;height:1px;background:var(--ink);transition:top var(--d-2) var(--e-out),transform var(--d-2) var(--e-out)}
  .menu:before{top:16px}
  .menu:after{top:24px}
  nav.open .menu:before{top:20px;transform:rotate(45deg)}
  nav.open .menu:after{top:20px;transform:rotate(-45deg)}
  .nl-wrap{display:none;position:absolute;inset-inline:0;top:100%;flex-direction:column;align-items:stretch;gap:0;padding:var(--s1) var(--gutter) var(--s3);background:var(--ivory);border-bottom:1px solid var(--line)}
  nav.open .nl-wrap{display:flex}
  .nl-wrap>a.nl{display:block;padding:var(--s4) 2px;border-bottom:1px solid var(--line)}
  .nl-wrap>a.nl:last-child{border-bottom:0}

  /* full-bleed hero on the PHONE story: 196 native 9:16 frames, so cover loses nothing.
     site.js swaps the set and the stops; the <picture> poster is already the phone frame. */
  .scrub{height:380vh;--fa:var(--fa-phone,.5625)}    /* no-JS / reduced-motion fallback height */
  .pin{top:0;height:100vh}
  canvas.scrubc{object-fit:cover;object-position:50% 50%}
  :root{--slot-b:40px}
  .over{grid-template-rows:1fr auto auto;padding-block:calc(var(--nav-h) + var(--s4)) var(--slot-b)}
  /* PhoneHero.dc.html: eyebrow, 44 px line, body line, then SCROLL last */
  .head{flex-direction:column;align-items:flex-start;gap:var(--s4)}
  .head>div:first-child{order:1}
  .hint{order:2}
  .pin .lead,.head p{margin-top:var(--s4);font-size:var(--t-body);max-width:none}
  .hint{flex-direction:row;align-items:center;gap:var(--s3)}
  .hint .line,.hint:not(:has(.line)):after{width:40px;height:1px}
  .caps{grid-row:2}
  .caps.desk{display:none}                           /* the phone set (p0..p5) is the story here */
  /* --t-h2 is already 32 px at 390, --t-lead 18 px (PhoneStop.dc.html) */
  .cap{max-width:none;justify-self:stretch}
  .cap p{max-width:34ch}
  /* the frame is upright, so there is less picture to protect: 62 % -> 54 % */
  .scrim{height:54%}
  .scrim.top{height:18%}
  .scrim.h{height:86%}
  .scrim.side{display:none}                          /* a side column is meaningless at 390 */
  /* callouts join the flow under the caption, and take no room on the other six stops */
  .callouts{position:static;grid-row:3;width:auto;gap:var(--s4);margin-top:var(--s4)}
  html.js .callouts:not(.on){display:none}
  .callout{padding-inline-start:var(--s4);gap:2px}
  .end{gap:var(--s4)}
  .end .btn{flex:1 1 auto}

  /* the doors become a swipe row */
  .doors,.doors.five,.doors:has(>:nth-child(7)):not(:has(>:nth-child(8))),.doors:has(>:nth-child(9)):not(:has(>:nth-child(10))){
    display:flex;grid-template-columns:none;gap:var(--s4);
    overflow-x:auto;overscroll-behavior-inline:contain;
    scroll-snap-type:x mandatory;scroll-padding-inline-start:var(--gutter);
    padding-inline:var(--gutter);margin-inline:calc(-1 * var(--gutter));
    -webkit-overflow-scrolling:touch;
  }
  .door{width:236px;flex:0 0 236px;scroll-snap-align:start}

  .hero{grid-template-columns:1fr;gap:var(--s6);padding:calc(var(--nav-h) + var(--s6)) 0 var(--s7)}
  .pagehead{padding:calc(var(--nav-h) + var(--s6)) 0 var(--s6)}
  .fac .wrap{grid-template-columns:1fr;gap:var(--s6)}
  .stats{grid-template-columns:1fr 1fr;gap:var(--s5)}
  .grid{grid-template-columns:1fr 1fr;gap:var(--s6) var(--s4)}
  .prod{grid-template-columns:1fr;gap:var(--s6);padding:calc(var(--nav-h) + var(--s6)) 0 var(--s8)}
  .prod .im{position:static}
  .two,.cgrid{grid-template-columns:1fr;gap:var(--s7)}
  .steps{grid-template-columns:1fr 1fr}
  .spec div,.tbl div{grid-template-columns:1fr;gap:var(--s1)}
  .pn{grid-template-columns:1fr;gap:var(--s3);justify-items:start}
  .pn>span:last-child{text-align:start}
}

/* ============================== 15. RTL (law 11.20, contract RTL block) ============================== */
html[dir=rtl] .rail i{transform-origin:100% 50%}
html[dir=rtl] .lnk:after,html[dir=rtl] .dl>span:first-child:after{transform-origin:100% 50%}
html[dir=rtl] .lnk{margin-inline-end:var(--s6)}
html.js[dir=rtl] .callout{transform:translateX(-24px)}
html[dir=rtl] form textarea{resize:none}
html[dir=rtl] .pn>span:last-child{text-align:start}
html[dir=rtl] .pn>span:first-child{text-align:end}
@media (max-width:1000px){html[dir=rtl] .pn>span{text-align:start}}

/* ============================== 16. REDUCED MOTION (law 3.7) ============================== */
@media (prefers-reduced-motion:reduce){
  /* the hero collapses to one static frame with the words beneath it */
  .scrub{height:auto;min-height:0}
  .pin{position:relative;top:auto;height:auto;overflow:visible}
  canvas.scrubc{position:relative;inset:auto;width:100%;height:auto;aspect-ratio:var(--fa)}
  .poster{position:absolute;inset:0}
  .vig{display:none}
  .scrim{height:auto;inset:0;background:linear-gradient(180deg,rgba(247,245,240,.7) 0,rgba(247,245,240,0) 22%)}
  .scrim.h,.scrim.side{display:none}
  .over{position:static;display:block;padding:var(--s8) var(--gutter)}
  .head{display:block}
  .head.gone>div:first-child,.head.gone .hint{opacity:1}
  .hint{display:none}
  .caps{display:block}
  .cap{position:static;opacity:1;transform:none;max-width:62ch;margin-bottom:var(--s7)}
  .cap.past{opacity:1;transform:none}
  .callouts{position:static;width:auto;margin-top:var(--s7)}
  html.js .callout,html.js .callouts.on .callout{opacity:1;transform:none;transition:none}
  .end{position:static;opacity:1;transform:none;pointer-events:auto;max-width:1440px;margin:0 auto;padding:var(--s7) var(--gutter) 0}
  .pin.ended .caps,.pin.ended .hint,.pin.ended .callouts{opacity:1}

  /* transforms off, opacity kept */
  html.js .mask>span{transform:none;transition:none}
  html.js .reveal{transform:none;transition:opacity var(--d-3) var(--e-out)}
  html.js .reveal :is(.doors,.grid,.stats,.steps)>*{opacity:1}
  html.js .reveal.in :is(.doors,.grid,.stats,.steps)>*{animation:none}
  .door,.card,.door img,.card img{transition:opacity var(--d-2) var(--e-out)}
  .door:hover,.card:hover,.door:hover img,.card:hover img{transform:none}
  .btn:active{scale:1}
  nav,nav.hide{transform:none}
  nav .wrap,nav.small .logo{transition:none}
  .menu:before,.menu:after{transition:none}
}

/* ============================== 17. PRINT ============================== */
@media print{
  nav,footer,.rail,.grain,.vig,.scrim,.hint,.end,.series-nav,.pn{display:none}
  body{background:#fff;color:#000}
  .scrub{height:auto}
  .pin{position:static;height:auto;overflow:visible}
  canvas.scrubc,.poster{display:none}
  .over{position:static;display:block;padding:0}
  .caps{display:block}
  .cap{position:static;opacity:1;transform:none}
  html.js .reveal,html.js .mask>span,html.js .callout{opacity:1;transform:none}
  .doors,.grid{display:block}
}
