/* ═════════════════════════════════════════════════════════════
   REGARDE · NOIR
   One midnight. One gold. Everything emerges from the dark.

   PART I  (lines to "PART II") is the locked NOIR stylesheet,
   lifted verbatim from opus5_noir/index.html. Do not edit it.
   PART II is the extension layer for the pages the locked file
   never had. Every rule in it is derived from a primitive above;
   see DESIGN_SYSTEM.md §9 for the derivation table.
   ═════════════════════════════════════════════════════════════ */

/* ─────────────────────────  PART I — LOCKED  ───────────────── */

:root{
  --ink:#08080a;
  --ink-raised:#0c0c0f;
  --ink-edge:#16161a;
  --bone:#ece6db;
  --bone-2:#b6b0a5;
  --bone-3:#726d65;
  --gold:#c39a5b;

  --serif:"Didot","Bodoni 72","Bodoni 72 Oldstyle",Didot,"Times New Roman",serif;
  --grot:"Helvetica Neue",Helvetica,Arial,sans-serif;
  --mono:"SF Mono",SFMono-Regular,Menlo,Consolas,monospace;

  --gutter:clamp(20px,5.2vw,84px);
  --rule:1px solid #1c1c20;
  --ease:cubic-bezier(.16,.84,.44,1);
}

*,*::before,*::after{box-sizing:border-box;}
html{-webkit-text-size-adjust:100%;}
body{
  margin:0;
  background:var(--ink);
  color:var(--bone-2);
  font-family:var(--grot);
  font-size:clamp(15px,.62vw + 13px,17px);
  line-height:1.66;
  letter-spacing:.005em;
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}
img{display:block;max-width:100%;height:auto;}
a{color:inherit;text-decoration:none;}
h1,h2,h3,p,figure,blockquote{margin:0;}
ul,ol{margin:0;padding:0;list-style:none;}
::selection{background:var(--gold);color:var(--ink);}
.vh{position:absolute;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;}
:focus-visible{outline:1px solid var(--gold);outline-offset:4px;}

/* ── type primitives ───────────────────────────────────────── */
.serif{font-family:var(--serif);font-weight:400;color:var(--bone);}
.mono{
  font-family:var(--mono);
  font-size:.66rem;
  letter-spacing:.24em;
  text-transform:uppercase;
  color:var(--bone-3);
  font-weight:400;
}
.micro{
  font-family:var(--grot);
  font-size:.625rem;
  letter-spacing:.42em;
  text-transform:uppercase;
  color:var(--bone-3);
  font-weight:500;
}
.lede{
  font-size:clamp(1.02rem,.5vw + .92rem,1.2rem);
  line-height:1.62;
  color:var(--bone-2);
  max-width:33ch;
}

/* the wordmark — REGARD stands roman, the E turns gold and italic. */
.wordmark{font-family:var(--serif);font-weight:400;color:var(--bone);white-space:nowrap;}
.wordmark .e{
  color:var(--gold);
  font-style:italic;
  padding-left:.012em;
  padding-right:.06em;
}

/* ── shell ─────────────────────────────────────────────────── */
.bar{
  position:fixed;inset:0 0 auto 0;z-index:60;
  display:flex;align-items:center;justify-content:space-between;
  gap:16px;
  padding:16px var(--gutter);
  border-bottom:1px solid transparent;
  background:transparent;
  transition:background .6s var(--ease),border-color .6s var(--ease),padding .6s var(--ease);
}
.bar.settled{
  background:rgba(8,8,10,.9);
  -webkit-backdrop-filter:saturate(120%) blur(14px);
  backdrop-filter:saturate(120%) blur(14px);
  border-bottom-color:#141418;
  padding-top:12px;padding-bottom:12px;
}
.bar .wordmark{font-size:1.12rem;letter-spacing:.18em;}
.bar nav{display:flex;gap:clamp(14px,2.4vw,32px);align-items:center;}
.bar nav a{position:relative;padding:6px 0;}
.bar nav a::after{
  content:"";position:absolute;left:0;right:100%;bottom:2px;height:1px;
  background:var(--bone-3);transition:right .5s var(--ease);
}
.bar nav a:hover::after{right:0;}
.bar nav a.keyline{color:var(--bone-2);}

main{display:block;}

/* every band carries a printed index in its left gutter */
.band{
  position:relative;
  padding:clamp(78px,11vh,150px) var(--gutter);
  border-top:var(--rule);
}
.band-index{
  display:flex;align-items:baseline;gap:14px;
  margin-bottom:clamp(30px,5vh,58px);
}
.band-index .n{
  font-family:var(--mono);font-size:.66rem;letter-spacing:.16em;color:var(--gold);
  opacity:.85;
}
.band-index .rule{flex:0 0 34px;height:1px;background:#22221f;transform:translateY(-3px);}
.band-index h2{
  font-family:var(--serif);
  font-size:clamp(1.32rem,1.5vw + .95rem,1.85rem);
  font-weight:400;color:var(--bone);letter-spacing:-.012em;
}
/* only one gold per viewport: bands that spend gold elsewhere mute the index */
.band.spent .band-index .n{color:var(--bone-3);opacity:1;}

/* ── hero ──────────────────────────────────────────────────── */
.hero{
  position:relative;
  min-height:100svh;
  display:grid;
  grid-template-columns:minmax(0,1.02fr) minmax(0,.98fr);
  align-items:stretch;
}
.hero-plate{position:relative;overflow:hidden;background:var(--ink);}
.hero-plate img{
  width:100%;height:100%;object-fit:cover;object-position:64% 38%;
}
/* the image does not sit on a background — it dissolves into it */
.hero-plate::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:
    linear-gradient(90deg,var(--ink) 0%,rgba(8,8,10,.78) 9%,rgba(8,8,10,0) 38%),
    linear-gradient(0deg,var(--ink) 0%,rgba(8,8,10,0) 30%),
    linear-gradient(180deg,rgba(8,8,10,.5) 0%,rgba(8,8,10,0) 18%);
}
.hero-type{
  position:relative;z-index:2;
  display:flex;flex-direction:column;justify-content:center;
  padding:clamp(96px,14vh,150px) 0 clamp(44px,7vh,80px) var(--gutter);
  padding-right:clamp(12px,3vw,40px);
}
.hero-kicker{display:flex;align-items:center;gap:12px;margin-bottom:clamp(22px,4vh,40px);}
.hero-kicker .dot{width:4px;height:4px;background:var(--bone-3);border-radius:50%;flex:none;}
.hero-mark{
  font-family:var(--serif);
  font-size:clamp(3.5rem,13.2vw,11.2rem);
  line-height:.82;
  letter-spacing:-.028em;
  color:var(--bone);
  margin-left:-.055em;
}
.hero-mark .e{color:var(--gold);font-style:italic;letter-spacing:-.01em;}
.hero-sub{
  margin-top:clamp(20px,3.4vh,34px);
  font-family:var(--serif);
  font-size:clamp(1.28rem,2vw + .55rem,2.15rem);
  line-height:1.24;
  letter-spacing:-.014em;
  color:var(--bone);
  max-width:15ch;
}
.hero-sub em{font-style:italic;color:var(--bone-2);}
.hero-body{margin-top:clamp(18px,2.6vh,26px);max-width:34ch;}
.hero-acts{
  display:flex;flex-wrap:wrap;align-items:center;gap:clamp(14px,2.4vw,28px);
  margin-top:clamp(28px,4.6vh,46px);
}
.hero-scroll{
  position:absolute;left:var(--gutter);bottom:clamp(18px,3vh,32px);z-index:3;
  display:flex;align-items:center;gap:10px;
}
.hero-scroll .line{
  display:block;width:52px;height:1px;background:#2a2a2e;position:relative;overflow:hidden;
}
.hero-scroll .line::after{
  content:"";position:absolute;inset:0;background:var(--bone-3);
  transform:translateX(-100%);
  animation:draw 3.4s var(--ease) infinite;
}
@keyframes draw{
  0%{transform:translateX(-100%);}
  46%{transform:translateX(0);}
  92%,100%{transform:translateX(100%);}
}

/* ── buttons ───────────────────────────────────────────────── */
.btn{
  display:inline-flex;align-items:center;gap:12px;
  min-height:46px;padding:13px 26px;
  font-family:var(--grot);font-size:.66rem;font-weight:500;
  letter-spacing:.34em;text-transform:uppercase;
  border:1px solid #2e2e33;color:var(--bone);
  background:transparent;cursor:pointer;
  transition:border-color .55s var(--ease),color .55s var(--ease),background .55s var(--ease);
}
.btn:hover{border-color:var(--bone-3);background:#0f0f13;}
.btn .arrow{transition:transform .55s var(--ease);}
.btn:hover .arrow{transform:translateX(5px);}
.link-quiet{
  display:inline-flex;align-items:center;gap:9px;min-height:44px;
  font-family:var(--grot);font-size:.66rem;font-weight:500;
  letter-spacing:.34em;text-transform:uppercase;color:var(--bone-3);
  transition:color .55s var(--ease);
}
.link-quiet:hover{color:var(--bone-2);}
.link-quiet .arrow{transition:transform .55s var(--ease);}
.link-quiet:hover .arrow{transform:translateX(5px);}

/* ── 01 statement ──────────────────────────────────────────── */
.statement{padding-bottom:clamp(84px,13vh,168px);}
.statement-lines{
  font-family:var(--serif);
  font-size:clamp(1.85rem,4.4vw + .35rem,4.15rem);
  line-height:1.12;
  letter-spacing:-.026em;
  color:var(--bone);
  max-width:26ch;
}
.statement-lines span{display:block;}
.statement-lines .dim{color:#5f5b55;}
.statement-lines .it{font-style:italic;}
.statement-foot{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));
  gap:clamp(20px,3vw,44px);
  margin-top:clamp(46px,7vh,84px);
  padding-top:26px;border-top:var(--rule);
}
.statement-foot p{max-width:30ch;font-size:.95rem;line-height:1.7;}
.statement-foot .micro{margin-bottom:10px;display:block;}

/* ── 02 le trait ───────────────────────────────────────────── */
.trait{
  display:grid;
  grid-template-columns:minmax(0,1.06fr) minmax(0,1fr);
  gap:clamp(30px,5vw,86px);
  align-items:center;
}
.plate{position:relative;overflow:hidden;background:#0a0a0c;}
.plate img{width:100%;height:100%;object-fit:cover;display:block;}
.plate::after{
  content:"";position:absolute;inset:0;pointer-events:none;
  background:
    linear-gradient(180deg,rgba(8,8,10,.5) 0%,rgba(8,8,10,0) 22%,rgba(8,8,10,0) 74%,var(--ink) 100%),
    linear-gradient(90deg,rgba(8,8,10,.55) 0%,rgba(8,8,10,0) 24%);
}
.plate--tall{aspect-ratio:4/5;}
.trait-copy h3{
  font-family:var(--serif);
  font-size:clamp(2.1rem,3.4vw + .6rem,3.5rem);
  line-height:1.04;letter-spacing:-.026em;color:var(--bone);
}
.trait-copy h3 .it{font-style:italic;}
.trait-copy .lede{margin-top:22px;}
.spec{margin-top:clamp(30px,4.4vh,46px);border-top:var(--rule);}
.spec li{
  display:grid;grid-template-columns:9.5ch 1fr;gap:16px;align-items:baseline;
  padding:13px 0;border-bottom:var(--rule);
}
.spec dt,.spec .k{
  font-family:var(--mono);font-size:.6rem;letter-spacing:.2em;
  text-transform:uppercase;color:#5b5751;
}
.spec .v{font-size:.94rem;color:var(--bone-2);}
.price-row{
  display:flex;align-items:baseline;gap:16px;flex-wrap:wrap;
  margin-top:clamp(26px,3.6vh,38px);
}
.price{
  font-family:var(--serif);font-size:clamp(1.5rem,1.6vw + 1.05rem,2.05rem);
  color:var(--gold);letter-spacing:-.01em;
}
.price-note{font-family:var(--mono);font-size:.62rem;letter-spacing:.2em;text-transform:uppercase;color:#5b5751;}
.trait-wide{margin-top:clamp(34px,5.4vh,68px);}
.trait-wide .plate{aspect-ratio:16/9;}
.trait-wide .cap{
  display:flex;justify-content:space-between;gap:18px;flex-wrap:wrap;
  margin-top:12px;padding-top:11px;border-top:var(--rule);
}
.trait-wide .cap span{font-family:var(--mono);font-size:.6rem;letter-spacing:.2em;text-transform:uppercase;color:#5b5751;}

/* ── 03 editorial ──────────────────────────────────────────── */
.editorial{padding-left:0;padding-right:0;}
.editorial .band-index{padding:0 var(--gutter);}
.ed-frame{position:relative;}
.ed-frame .plate{aspect-ratio:2/1;}
.ed-quote{
  position:relative;
  margin:clamp(-70px,-6vw,-34px) var(--gutter) 0;
  max-width:46ch;
  z-index:2;
}
.ed-quote blockquote{
  font-family:var(--serif);
  font-size:clamp(1.45rem,2.5vw + .6rem,2.55rem);
  line-height:1.16;letter-spacing:-.022em;color:var(--bone);
}
.ed-quote blockquote .it{font-style:italic;color:var(--bone-2);}
.ed-quote cite{
  display:block;margin-top:20px;font-style:normal;
  font-family:var(--mono);font-size:.62rem;letter-spacing:.24em;
  text-transform:uppercase;color:#5b5751;
}
.ed-strip{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));
  gap:clamp(20px,3vw,54px);
  margin:clamp(48px,7vh,90px) var(--gutter) 0;
  padding-top:26px;border-top:var(--rule);
}
.ed-strip p{font-size:.95rem;max-width:32ch;}
.ed-strip .micro{display:block;margin-bottom:10px;}

/* ── 04 la routine ─────────────────────────────────────────── */
.routine{background:linear-gradient(180deg,#0a0a0d 0%,#08080a 100%);}
.routine-grid{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,.86fr);
  gap:clamp(32px,5vw,80px);align-items:start;
}
.routine-head h3{
  font-family:var(--serif);
  font-size:clamp(2.1rem,3.6vw + .6rem,3.6rem);
  line-height:1.04;letter-spacing:-.026em;color:var(--bone);
}
.routine-head h3 .it{font-style:italic;}
.routine-head .lede{margin-top:22px;}
.routine-plate{margin-top:clamp(28px,4vh,44px);}
.routine-plate .plate{aspect-ratio:3/2;}

.ledger{border-top:1px solid #232327;}
.ledger li{position:relative;border-bottom:1px solid #17171b;}
.ledger .row{
  display:grid;grid-template-columns:2.6ch 1fr auto;gap:clamp(12px,2vw,26px);
  align-items:baseline;padding:20px 0;
}
.ledger .idx{font-family:var(--mono);font-size:.6rem;letter-spacing:.14em;color:#4d4944;}
.ledger .name{
  font-family:var(--serif);font-size:clamp(1.12rem,1vw + .85rem,1.4rem);
  color:var(--bone);letter-spacing:-.005em;
}
.ledger .role{display:block;margin-top:5px;font-size:.88rem;color:#7d786f;letter-spacing:.005em;}
.ledger .amt{font-family:var(--mono);font-size:.78rem;letter-spacing:.06em;color:#8b867d;}
.ledger li::after{
  content:"";position:absolute;left:0;bottom:-1px;height:1px;width:0;
  background:#3a352c;transition:width .8s var(--ease);
}
.ledger li:hover::after{width:100%;}

.tally{margin-top:26px;}
.tally .apart{
  display:flex;justify-content:space-between;align-items:baseline;gap:16px;
  padding-bottom:16px;
  font-family:var(--mono);font-size:.66rem;letter-spacing:.18em;
  text-transform:uppercase;color:#5b5751;
}
.tally .apart s{text-decoration-thickness:1px;text-underline-offset:2px;}
.tally .together{
  display:flex;justify-content:space-between;align-items:baseline;gap:16px;
  padding-top:20px;border-top:1px solid #232327;
}
.tally .together .label{
  font-family:var(--grot);font-size:.625rem;font-weight:500;
  letter-spacing:.42em;text-transform:uppercase;color:var(--bone-2);
}
.tally .together .sum{
  font-family:var(--serif);font-size:clamp(2rem,2.6vw + 1.1rem,3.1rem);
  color:var(--gold);letter-spacing:-.02em;line-height:1;
}
.tally .fine{margin-top:16px;font-size:.86rem;color:#6d6860;max-width:34ch;}
.routine-acts{margin-top:clamp(26px,4vh,40px);}

/* ── 05 record ─────────────────────────────────────────────── */
.record-grid{
  display:grid;grid-template-columns:minmax(0,.9fr) minmax(0,1.1fr);
  gap:clamp(30px,5vw,80px);align-items:start;
}
.record-copy p{max-width:34ch;}
.record-copy p + p{margin-top:16px;}
.slots{display:grid;gap:14px;}
.slot{
  border:1px solid #17171b;
  padding:clamp(20px,2.4vw,30px);
  min-height:118px;
  display:flex;flex-direction:column;justify-content:space-between;gap:22px;
  background:linear-gradient(180deg,#0a0a0d,#08080a);
}
.slot .head{display:flex;justify-content:space-between;align-items:baseline;gap:16px;}
.slot .who{font-family:var(--mono);font-size:.6rem;letter-spacing:.2em;text-transform:uppercase;color:#3f3c38;}
.slot .stars{display:flex;gap:6px;}
.slot .stars i{width:5px;height:5px;border:1px solid #2b2b2f;border-radius:50%;display:block;}
.slot .empty-rule{height:1px;background:#141418;}
.slot .empty-rule + .empty-rule{margin-top:11px;width:72%;}

/* ── 06 email ──────────────────────────────────────────────── */
.notify{
  border-top:var(--rule);
  padding-top:clamp(84px,13vh,168px);
  padding-bottom:clamp(84px,13vh,168px);
}
.notify-inner{max-width:56ch;}
.notify h2{
  font-family:var(--serif);
  font-size:clamp(2rem,4vw + .5rem,3.75rem);
  line-height:1.06;letter-spacing:-.028em;color:var(--bone);
}
.notify h2 .it{font-style:italic;color:var(--bone-2);}
.notify .lede{margin-top:22px;max-width:38ch;}
.form{margin-top:clamp(32px,4.6vh,48px);}
.field{
  display:flex;align-items:stretch;gap:0;
  border-bottom:1px solid #2e2e33;
  transition:border-color .55s var(--ease);
}
.field:focus-within{border-bottom-color:var(--gold);}
.field input{
  flex:1;min-width:0;
  background:transparent;border:0;outline:none;
  color:var(--bone);
  font-family:var(--serif);
  font-size:clamp(1.05rem,1vw + .8rem,1.35rem);
  padding:16px 0;
  letter-spacing:.005em;
}
.field input::placeholder{color:#4d4944;font-family:var(--serif);}
.field button{
  flex:none;background:transparent;border:0;cursor:pointer;
  padding:0 4px 0 20px;color:var(--bone-2);
  font-family:var(--grot);font-size:.625rem;font-weight:500;
  letter-spacing:.42em;text-transform:uppercase;
  display:inline-flex;align-items:center;gap:10px;min-height:44px;
  transition:color .55s var(--ease);
}
.field button:hover{color:var(--gold);}
.field button .arrow{transition:transform .55s var(--ease);}
.field button:hover .arrow{transform:translateX(5px);}
.form-note{margin-top:14px;font-family:var(--mono);font-size:.6rem;letter-spacing:.18em;text-transform:uppercase;color:#4d4944;}
.form-done{
  margin-top:22px;font-family:var(--serif);
  font-size:clamp(1.05rem,1vw + .8rem,1.3rem);color:var(--bone);
  opacity:0;transform:translateY(6px);
  transition:opacity .7s var(--ease),transform .7s var(--ease);
}
.form-done.on{opacity:1;transform:none;}

/* ── footer ────────────────────────────────────────────────── */
footer{border-top:var(--rule);padding:clamp(56px,8vh,96px) var(--gutter) clamp(36px,5vh,56px);}
.foot-e{
  display:flex;align-items:baseline;justify-content:center;
  gap:clamp(10px,2.6vw,30px);
  font-family:var(--serif);
  font-size:clamp(2rem,7.6vw,5.6rem);
  color:#4a4640;letter-spacing:0;line-height:1;
}
.foot-e i{font-style:normal;}
.foot-e .e{color:var(--gold);font-style:italic;font-size:1.16em;}
.foot-line{
  margin:clamp(24px,3.6vh,36px) auto 0;text-align:center;max-width:44ch;
  font-family:var(--serif);font-size:clamp(1rem,.7vw + .84rem,1.16rem);
  color:#8b867d;line-height:1.5;
}
.foot-line em{font-style:italic;color:var(--bone-2);}
.foot-bar{
  display:flex;flex-wrap:wrap;gap:16px 30px;justify-content:space-between;align-items:center;
  margin-top:clamp(44px,7vh,80px);padding-top:22px;border-top:var(--rule);
}
.foot-nav{display:flex;flex-wrap:wrap;gap:14px 26px;}
.foot-nav a{min-height:44px;display:inline-flex;align-items:center;transition:color .5s var(--ease);}
.foot-nav a:hover{color:var(--bone-2);}

/* ── motion: light brought up on each section ──────────────── */
.js .rise{opacity:0;transform:translateY(20px);filter:blur(7px);}
.js .rise.lit{
  opacity:1;transform:none;filter:blur(0);
  transition:opacity 1.15s var(--ease),transform 1.15s var(--ease),filter 1.15s var(--ease);
}
.js .lit-img img{opacity:0;transform:scale(1.045);}
.js .lit-img.lit img{
  opacity:1;transform:none;
  transition:opacity 1.7s var(--ease),transform 2.4s var(--ease);
}
@media (prefers-reduced-motion:reduce){
  .js .rise,.js .lit-img img{opacity:1;transform:none;filter:none;}
  .hero-scroll .line::after{animation:none;transform:translateX(0);}
  *{transition-duration:.01ms !important;animation-duration:.01ms !important;}
}

/* ── responsive ────────────────────────────────────────────── */
@media (max-width:1000px){
  .hero{grid-template-columns:1fr;min-height:auto;}
  .hero-type{
    order:2;padding:clamp(34px,6vh,56px) var(--gutter) clamp(46px,7vh,72px);
  }
  .hero-plate{order:1;aspect-ratio:4/5;max-height:78svh;}
  .hero-plate::after{
    background:
      linear-gradient(0deg,var(--ink) 0%,rgba(8,8,10,.72) 12%,rgba(8,8,10,0) 46%),
      linear-gradient(180deg,rgba(8,8,10,.7) 0%,rgba(8,8,10,0) 30%);
  }
  .hero-scroll{display:none;}
  .hero-mark{font-size:clamp(2.8rem,16vw,6.4rem);}
  .hero-sub{max-width:20ch;}
  .trait,.routine-grid,.record-grid{grid-template-columns:1fr;}
  .trait .plate--tall{aspect-ratio:3/2;}
  .ed-quote{margin-top:clamp(-30px,-5vw,-18px);max-width:none;}
  .ed-frame .plate{aspect-ratio:3/2;}
}
@media (max-width:620px){
  .bar nav a:not(.keyline){display:none;}
  .statement-lines{max-width:none;}
  .ledger .row{grid-template-columns:2.4ch 1fr;row-gap:6px;}
  .ledger .amt{grid-column:2;justify-self:start;}
  .field button{padding-left:14px;letter-spacing:.28em;}
  .foot-e{font-size:clamp(1.7rem,10vw,3rem);gap:8px;}
}

/* ═══════════════════  PART II — EXTENSION LAYER  ═══════════════
   Everything below is new. Nothing below introduces a colour, a
   font, an easing or a shape that is not already in Part I.
   ═════════════════════════════════════════════════════════════ */

/* ── state: what the data layer has no number for ──────────── */
/* `hidden` is written into the static HTML by tools/sync.mjs and set
   again by regarde.js. It has to beat the display rules the layout
   primitives set, which is the whole of what this rule is for. */
[hidden]{display:none !important;}

/* ── skip link (a11y; visually absent until focused) ────────── */
.skip{
  position:absolute;left:-9999px;top:0;z-index:100;
  padding:12px 20px;background:var(--ink-raised);color:var(--bone);
  font-family:var(--grot);font-size:.625rem;font-weight:500;
  letter-spacing:.42em;text-transform:uppercase;border:1px solid #2e2e33;
}
.skip:focus{left:var(--gutter);top:12px;}

/* ── the bar, extended for a site rather than a page ───────── */
/* derived from: .bar nav a (keyline underline), unchanged in kind */
.bar nav a[aria-current="page"]{color:var(--bone);}
.bar nav a[aria-current="page"]::after{right:0;background:#3a352c;}

/* the index disclosure — the small-screen navigation.
   <details> so it opens with JavaScript disabled. */
.bar-index{position:relative;display:none;}
.bar-index > summary{
  list-style:none;cursor:pointer;
  display:inline-flex;align-items:center;gap:10px;
  min-height:44px;padding:6px 0;
  font-family:var(--grot);font-size:.625rem;font-weight:500;
  letter-spacing:.42em;text-transform:uppercase;color:var(--bone-2);
}
.bar-index > summary::-webkit-details-marker{display:none;}
.bar-index > summary::marker{content:"";}
.bar-index .mark{
  position:relative;display:block;width:11px;height:11px;flex:none;
  transition:transform .55s var(--ease);
}
.bar-index .mark::before,.bar-index .mark::after{
  content:"";position:absolute;left:0;top:5px;width:11px;height:1px;background:var(--bone-3);
}
.bar-index .mark::after{transform:rotate(90deg);}
.bar-index[open] .mark{transform:rotate(45deg);}
.index-panel{
  position:absolute;top:calc(100% + 14px);right:0;
  min-width:min(78vw,300px);
  max-height:calc(100svh - 120px);overflow:auto;
  padding:22px 26px 26px;
  background:rgba(8,8,10,.97);
  -webkit-backdrop-filter:saturate(120%) blur(14px);
  backdrop-filter:saturate(120%) blur(14px);
  border:1px solid #17171b;
}
.index-panel .micro{display:block;margin-bottom:14px;}
.index-panel a{
  display:block;padding:9px 0;
  font-family:var(--serif);font-size:1.16rem;color:var(--bone-2);
  letter-spacing:-.008em;
  border-bottom:1px solid #141418;
  transition:color .5s var(--ease);
}
.index-panel a:last-of-type{border-bottom:0;}
.index-panel a:hover,.index-panel a[aria-current="page"]{color:var(--bone);}
.index-panel a .it{font-style:italic;color:var(--bone-3);}

/* ── page head — the interior-page opener ──────────────────── */
/* derived from: .hero-type (vertical rhythm) + .band-index (kicker) */
.page-head{
  position:relative;
  padding:clamp(118px,17vh,196px) var(--gutter) clamp(40px,6vh,72px);
}
.page-head .kicker{display:flex;align-items:center;gap:12px;margin-bottom:clamp(20px,3.4vh,32px);flex-wrap:wrap;}
.page-head .kicker .dot{width:4px;height:4px;background:var(--bone-3);border-radius:50%;flex:none;}
.page-title{
  font-family:var(--serif);
  font-size:clamp(2.6rem,6.6vw + .3rem,6.2rem);
  line-height:.98;letter-spacing:-.03em;color:var(--bone);
  margin-left:-.03em;max-width:14ch;
}
.page-title .it{font-style:italic;color:var(--bone-2);}
.page-title .e{color:var(--gold);font-style:italic;}
.page-head .lede{margin-top:clamp(20px,3vh,30px);max-width:38ch;}
.page-head .hero-acts{margin-top:clamp(26px,4vh,40px);}
/* a page head that carries a wide plate under the type */
.head-plate{margin-top:clamp(36px,6vh,72px);}
.head-plate .plate{aspect-ratio:16/9;}
.head-plate .cap{
  display:flex;justify-content:space-between;gap:18px;flex-wrap:wrap;
  margin-top:12px;padding-top:11px;border-top:var(--rule);
}
.head-plate .cap span{font-family:var(--mono);font-size:.6rem;letter-spacing:.2em;text-transform:uppercase;color:#5b5751;}

/* ── the catalogue grid ────────────────────────────────────── */
/* derived from: .plate--tall + .ledger row typography + .ledger hover */
.grid-cat{
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));
  gap:clamp(26px,3.4vw,54px) clamp(20px,2.6vw,40px);
}
.cat{position:relative;display:flex;flex-direction:column;}
.cat .plate{aspect-ratio:4/5;}
.cat-body{
  display:flex;align-items:flex-start;justify-content:space-between;
  gap:14px;margin-top:16px;padding-top:14px;border-top:var(--rule);
}
.cat .name{
  font-family:var(--serif);font-size:clamp(1.16rem,.9vw + .92rem,1.42rem);
  color:var(--bone);letter-spacing:-.008em;line-height:1.15;display:block;
}
.cat .cat-cat{
  display:block;margin-top:7px;
  font-family:var(--mono);font-size:.6rem;letter-spacing:.2em;
  text-transform:uppercase;color:#5b5751;
}
.cat .claim{display:block;margin-top:9px;font-size:.9rem;color:#7d786f;max-width:24ch;}
.cat .amt{font-family:var(--mono);font-size:.78rem;letter-spacing:.06em;color:#8b867d;flex:none;padding-top:3px;}
.cat .state{
  font-family:var(--mono);font-size:.58rem;letter-spacing:.16em;
  text-transform:uppercase;color:#4d4944;flex:none;padding-top:4px;text-align:right;
  max-width:11ch;line-height:1.5;
}
/* a linked card draws its rule across, exactly as a ledger row does */
.cat.is-link .cat-body{position:relative;}
.cat.is-link .cat-body::after{
  content:"";position:absolute;left:0;top:-1px;height:1px;width:0;
  background:#3a352c;transition:width .8s var(--ease);
}
.cat.is-link:hover .cat-body::after{width:100%;}
.cat.is-link .name{transition:color .5s var(--ease);}
.cat.is-link:hover .name{color:#fff8ec;}
/* an unbuilt product is quieter than a built one, never broken-looking */
.cat.is-bench .plate::after{
  background:
    linear-gradient(180deg,rgba(8,8,10,.62) 0%,rgba(8,8,10,.34) 30%,rgba(8,8,10,.34) 68%,var(--ink) 100%),
    linear-gradient(90deg,rgba(8,8,10,.6) 0%,rgba(8,8,10,.2) 30%);
}
.cat-note{
  margin-top:clamp(34px,5vh,56px);padding-top:22px;border-top:var(--rule);
  display:flex;justify-content:space-between;gap:18px 40px;flex-wrap:wrap;align-items:baseline;
}
.cat-note p{max-width:44ch;font-size:.92rem;color:#7d786f;}

/* ── product gallery (the hero product template) ───────────── */
/* derived from: .plate at three ratios + .trait-wide caption rule */
.gallery{display:grid;gap:clamp(14px,1.8vw,24px);grid-template-columns:repeat(2,minmax(0,1fr));}
.gallery figure{margin:0;}
.gallery .g-1{grid-column:1 / -1;}
.gallery .g-1 .plate{aspect-ratio:16/9;}
.gallery .g-2 .plate{aspect-ratio:4/5;}
.gallery .g-3 .plate{aspect-ratio:4/5;}
.gallery .cap{
  display:flex;justify-content:space-between;gap:14px;flex-wrap:wrap;
  margin-top:11px;padding-top:10px;border-top:var(--rule);
}
.gallery .cap span{font-family:var(--mono);font-size:.58rem;letter-spacing:.18em;text-transform:uppercase;color:#5b5751;}

/* ── the state panel — where a cart would be, and is not ───── */
/* derived from: .slot (border, raised ground) + .btn */
.state-panel{
  border:1px solid #17171b;
  background:linear-gradient(180deg,#0a0a0d,#08080a);
  padding:clamp(22px,2.6vw,32px);
  margin-top:clamp(28px,4vh,42px);
}
.state-panel .who{
  font-family:var(--mono);font-size:.6rem;letter-spacing:.2em;
  text-transform:uppercase;color:#5b5751;display:block;
}
.state-panel .line{
  margin-top:12px;font-family:var(--serif);
  font-size:clamp(1.14rem,1vw + .88rem,1.44rem);
  line-height:1.3;color:var(--bone);letter-spacing:-.012em;max-width:26ch;
}
.state-panel .fine{margin-top:12px;font-size:.88rem;color:#6d6860;max-width:36ch;}
.state-panel .acts{margin-top:clamp(20px,2.8vh,28px);display:flex;flex-wrap:wrap;gap:16px 24px;align-items:center;}

/* ── prose (maison passages, policies) ─────────────────────── */
/* derived from: .lede measure + .spec hairlines */
.prose{max-width:60ch;}
.prose p{margin-top:18px;color:var(--bone-2);}
.prose p:first-child{margin-top:0;}
.prose .lead{
  font-family:var(--serif);
  font-size:clamp(1.34rem,1.7vw + .9rem,1.9rem);
  line-height:1.3;letter-spacing:-.018em;color:var(--bone);
  max-width:24ch;
}
.prose .lead .it{font-style:italic;color:var(--bone-2);}
.prose h3{
  margin-top:clamp(38px,5.4vh,60px);padding-top:20px;border-top:var(--rule);
  font-family:var(--serif);font-size:clamp(1.24rem,1.1vw + .95rem,1.6rem);
  color:var(--bone);letter-spacing:-.014em;font-weight:400;
}
.prose h3 + p{margin-top:14px;}
.prose ul{margin-top:16px;}
.prose ul li{
  position:relative;padding-left:22px;margin-top:9px;color:var(--bone-2);font-size:.96rem;
}
.prose ul li::before{
  content:"";position:absolute;left:0;top:.72em;width:9px;height:1px;background:#3a352c;
}
.prose .fine{margin-top:22px;font-size:.86rem;color:#6d6860;}
.prose em{font-style:italic;color:var(--bone);}

/* passages — the maison's three short blocks */
.passages{display:grid;gap:clamp(38px,6vh,74px);max-width:62ch;}
.passage{padding-top:24px;border-top:var(--rule);}
.passage:first-child{border-top:0;padding-top:0;}
.passage .micro{display:block;margin-bottom:16px;}
.passage h3{
  font-family:var(--serif);font-weight:400;
  font-size:clamp(1.62rem,2.4vw + .8rem,2.5rem);
  line-height:1.1;letter-spacing:-.022em;color:var(--bone);max-width:20ch;
}
.passage h3 .it{font-style:italic;color:var(--bone-2);}
.passage p{margin-top:18px;max-width:52ch;}

/* ── question & answer ─────────────────────────────────────── */
/* derived from: .spec hairline rows + .ledger hover underline */
.qa{border-top:var(--rule);max-width:74ch;}
.qa details{position:relative;border-bottom:var(--rule);}
.qa summary{
  list-style:none;cursor:pointer;
  display:flex;align-items:baseline;justify-content:space-between;gap:20px;
  padding:20px 0;min-height:44px;
  font-family:var(--serif);font-size:clamp(1.06rem,.8vw + .88rem,1.28rem);
  color:var(--bone);letter-spacing:-.008em;line-height:1.35;
  transition:color .5s var(--ease);
}
.qa summary::-webkit-details-marker{display:none;}
.qa summary::marker{content:"";}
.qa summary:hover{color:#fff8ec;}
.qa .mark{position:relative;display:block;width:11px;height:11px;flex:none;
  transform:translateY(-2px);transition:transform .55s var(--ease);}
.qa .mark::before,.qa .mark::after{
  content:"";position:absolute;left:0;top:5px;width:11px;height:1px;background:#4d4944;
}
.qa .mark::after{transform:rotate(90deg);}
.qa details[open] .mark{transform:translateY(-2px) rotate(45deg);}
.qa details[open] summary{color:var(--bone);}
.qa .answer{padding:0 0 24px;max-width:56ch;}
.qa .answer p{color:var(--bone-2);font-size:.98rem;}
.qa .answer p + p{margin-top:14px;}
.qa details::after{
  content:"";position:absolute;left:0;bottom:-1px;height:1px;width:0;
  background:#3a352c;transition:width .8s var(--ease);
}
.qa details:hover::after{width:100%;}

/* ── two-column band layout used by several interior pages ─── */
.split{
  display:grid;grid-template-columns:minmax(0,.92fr) minmax(0,1.08fr);
  gap:clamp(30px,5vw,80px);align-items:start;
}
.split--even{grid-template-columns:minmax(0,1fr) minmax(0,1fr);}
.split-aside .micro{display:block;margin-bottom:12px;}
.split-aside p{max-width:32ch;font-size:.95rem;}
.split-aside p + p{margin-top:14px;}

/* a quiet directory of routes, used on the support page */
.routes{border-top:var(--rule);}
.routes li{border-bottom:var(--rule);}
.routes a,.routes .row{
  display:flex;align-items:baseline;justify-content:space-between;gap:20px;
  padding:17px 0;min-height:44px;
}
.routes .t{font-family:var(--serif);font-size:1.12rem;color:var(--bone);letter-spacing:-.006em;}
.routes .d{font-family:var(--mono);font-size:.6rem;letter-spacing:.18em;text-transform:uppercase;color:#5b5751;text-align:right;}
.routes li{position:relative;}
.routes li::after{
  content:"";position:absolute;left:0;bottom:-1px;height:1px;width:0;
  background:#3a352c;transition:width .8s var(--ease);
}
.routes li:hover::after{width:100%;}

/* ── the creators route ────────────────────────────────────── */
.terms{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));
  gap:clamp(20px,3vw,46px);
  margin-top:clamp(34px,5vh,58px);padding-top:24px;border-top:var(--rule);
}
.terms .k{
  font-family:var(--mono);font-size:.6rem;letter-spacing:.2em;
  text-transform:uppercase;color:#5b5751;display:block;margin-bottom:10px;
}
.terms .v{font-family:var(--serif);font-size:clamp(1.3rem,1.4vw + .95rem,1.75rem);color:var(--bone);letter-spacing:-.014em;display:block;}
.terms p{margin-top:8px;font-size:.88rem;color:#7d786f;max-width:26ch;}

/* ── footer, extended to carry a site ──────────────────────── */
.foot-cols{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));
  gap:clamp(24px,3vw,52px);
  margin-top:clamp(44px,7vh,80px);padding-top:26px;border-top:var(--rule);
}
.foot-cols .micro{display:block;margin-bottom:14px;}
.foot-cols a{
  display:block;padding:7px 0;font-size:.92rem;color:#7d786f;
  transition:color .5s var(--ease);
}
.foot-cols a:hover,.foot-cols a[aria-current="page"]{color:var(--bone-2);}

/* ── responsive, extension layer ───────────────────────────── */
@media (max-width:1000px){
  .grid-cat{grid-template-columns:repeat(2,minmax(0,1fr));}
  .split{grid-template-columns:1fr;}
  .head-plate .plate{aspect-ratio:3/2;}
}
@media (max-width:820px){
  .bar > nav{display:none;}
  .bar-index{display:block;}
}
@media (max-width:620px){
  .grid-cat{grid-template-columns:1fr;gap:clamp(30px,6vh,44px);}
  .cat .plate{aspect-ratio:3/2;}
  .cat .claim{max-width:none;}
  .gallery{grid-template-columns:1fr;}
  .gallery .g-2 .plate,.gallery .g-3 .plate{aspect-ratio:3/2;}
  .page-title{max-width:none;}
  .cat-body{flex-wrap:wrap;}
  .terms{gap:26px;}
}

/* ═══════════  PART II · CATALOGUE EXTENSION (2026-08-18)  ═══════
   Sixty-five objects arrived where six had been. Nothing below adds a
   colour, a font, an easing, a radius or a shadow that Part I does not
   already own; every rule is a longer sentence in the same vocabulary.
   ═════════════════════════════════════════════════════════════ */

/* the one-line cue under a catalogue box — shade, size, texture, format.
   derived from: .cat .cat-cat, one step quieter */
.cat .cue{
  display:block;margin-top:9px;
  font-family:var(--mono);font-size:.575rem;letter-spacing:.13em;
  text-transform:uppercase;color:#4d4944;line-height:1.6;max-width:30ch;
}

/* a shelf heading inside the grid — a full-width ruled line, not a box.
   derived from: .band-index rule + .cat-body hairline */
.cat-head{
  grid-column:1 / -1;
  display:flex;align-items:baseline;justify-content:space-between;gap:18px;
  margin:clamp(18px,3vh,34px) 0 -6px;padding-bottom:13px;border-bottom:var(--rule);
  scroll-margin-top:96px;
}
.cat-head:first-child{margin-top:0;}
.cat-head .serif{
  font-family:var(--serif);font-size:clamp(1.24rem,1vw + 1rem,1.62rem);
  color:var(--bone);letter-spacing:-.012em;
}
.cat-head .mono{font-family:var(--mono);font-size:.58rem;letter-spacing:.2em;text-transform:uppercase;color:#4d4944;}

/* the filter row — .btn, reduced to its type and its border */
.filters{
  display:flex;flex-wrap:wrap;gap:9px;
  margin-bottom:clamp(26px,4vh,44px);
}
.chip{
  appearance:none;background:transparent;cursor:pointer;
  min-height:44px;padding:0 15px;
  border:1px solid #232327;color:#7d786f;
  font-family:var(--grot);font-size:.6rem;letter-spacing:.2em;text-transform:uppercase;
  display:inline-flex;align-items:center;gap:9px;
  transition:border-color .5s var(--ease),color .5s var(--ease);
}
.chip .mono{font-family:var(--mono);font-size:.58rem;letter-spacing:.08em;color:#4a4640;}
.chip:hover{border-color:var(--bone-3);color:var(--bone-2);}
.chip.is-on{border-color:#3f3c38;color:var(--bone);}
.chip.is-on .mono{color:var(--bone-2);}  /* the gold law: the wordmark E already spends it */
.filter-note{
  flex-basis:100%;margin-top:4px;
  font-family:var(--mono);font-size:.58rem;letter-spacing:.18em;text-transform:uppercase;color:#4d4944;
}
/* with JavaScript off there is nothing to filter with, so the row is not
   offered at all and the full grid stands — the same contract as .rise */
html:not(.js) .filters{display:none;}
.cat.is-off,.cat-head.is-off{display:none;}

/* the shelf jump — the bar's own disclosure, laid out wide */
.jump{margin-bottom:clamp(20px,3vh,32px);border-top:var(--rule);border-bottom:var(--rule);}
.jump > summary{
  list-style:none;cursor:pointer;min-height:46px;
  display:flex;align-items:center;justify-content:space-between;gap:14px;
}
.jump > summary::-webkit-details-marker{display:none;}
.jump .mark{width:9px;height:9px;border-right:1px solid #4a4640;border-bottom:1px solid #4a4640;transform:rotate(45deg) translateY(-3px);transition:transform .5s var(--ease);}
.jump[open] .mark{transform:rotate(225deg) translateY(-3px);}
.jump-panel{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));
  gap:2px 26px;padding:6px 0 20px;
}
.jump-panel a{
  display:flex;align-items:baseline;justify-content:space-between;gap:12px;
  min-height:40px;padding:8px 0;
  font-size:.9rem;color:var(--bone-2);
}
.jump-panel a .mono{font-family:var(--mono);font-size:.58rem;letter-spacing:.14em;color:#4a4640;}
.jump-panel a:hover{color:var(--bone);}

/* the merged-variant strip — .plate--tall at catalogue scale */
.variants{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));
  gap:clamp(18px,2.6vw,38px);margin-top:clamp(26px,4vh,42px);
}
.variants .plate{aspect-ratio:4/5;}
.variants .name{
  display:block;margin-top:13px;padding-top:12px;border-top:var(--rule);
  font-family:var(--serif);font-size:1.08rem;color:var(--bone);letter-spacing:-.006em;
}

/* provenance — who the label belongs to. derived from: .spec + .fine */
.prov{margin-top:clamp(24px,3.4vh,36px);padding-top:18px;border-top:var(--rule);}
.prov .micro{display:block;margin-bottom:11px;}
.prov p{font-size:.92rem;color:#7d786f;max-width:38ch;}
.prov .fine{margin-top:10px;font-family:var(--mono);font-size:.6rem;letter-spacing:.16em;text-transform:uppercase;color:#5b5751;}

/* the reason a pairing exists, printed under it in the ledger */
.ledger .why{
  display:block;margin-top:7px;max-width:52ch;
  font-size:.84rem;line-height:1.6;color:#5f5b55;
}
.ledger a.name{color:var(--bone);}
.ledger a.name:hover{color:#fff8ec;}
.cluster-note{margin-top:14px;font-size:.86rem;color:#5f5b55;max-width:34ch;}

/* the render disclosure under a product plate — .gallery .cap, alone */
.fig-note{margin-top:clamp(20px,3vh,30px);}
.fig-note .cap{
  display:flex;justify-content:space-between;gap:14px;flex-wrap:wrap;
  padding-top:11px;border-top:var(--rule);
}
.fig-note .cap span{font-family:var(--mono);font-size:.575rem;letter-spacing:.16em;text-transform:uppercase;color:#4d4944;}

@media (max-width:820px){
  .cat-head{margin-top:clamp(14px,2.4vh,26px);}
}
@media (max-width:620px){
  .filters{gap:8px;}
  .chip{padding:0 12px;letter-spacing:.16em;}
  .cat .cue{max-width:none;}
  .variants{grid-template-columns:repeat(2,minmax(0,1fr));}
  .fig-note .cap span{flex-basis:100%;}
}

/* ═══════  PART II · COMPOSITION PASS (2026-08-18, founder review)  ═══
   The catalogue shipped as a text ledger with pictures in it. Everything
   below is layout only — no new colour, font, easing, radius or shadow,
   and Part I is untouched. Three rules drive it:
     1. a plate is in the first viewport of every product page;
     2. discovery collapses instead of standing as a wall of controls;
     3. vertical rhythm on a 65-object catalogue is not the rhythm of a
        seven-band landing page, so the product routes carry their own.
   ═════════════════════════════════════════════════════════════ */

/* ── the product head: the plate stands beside the headline ──
   derived from: .hero (1.02fr/.98fr) + .page-head vertical rhythm */
.prod-head{
  position:relative;
  display:grid;
  grid-template-columns:minmax(0,1.04fr) minmax(0,.96fr);
  gap:clamp(28px,4vw,68px);
  align-items:start;
  padding:clamp(104px,15vh,168px) var(--gutter) clamp(34px,5vh,60px);
}
.prod-head .prod-type{min-width:0;}
.prod-head .page-title{margin-top:0;font-size:clamp(2.3rem,3.6vw + .6rem,4.1rem);max-width:15ch;}
.prod-head .lede{margin-top:clamp(16px,2.4vh,26px);max-width:36ch;}
.prod-head .hero-sub{margin-top:clamp(14px,2vh,22px);}
.prod-head .price-row{margin-top:clamp(16px,2.4vh,26px);}
.prod-head .state-panel{margin-top:clamp(20px,3vh,32px);}
.prod-plate{position:sticky;top:clamp(74px,9vh,96px);}
.prod-plate .plate{aspect-ratio:4/5;}
.prod-plate .cap{
  display:flex;justify-content:space-between;gap:14px;flex-wrap:wrap;
  margin-top:11px;padding-top:10px;border-top:var(--rule);
}
.prod-plate .cap span{font-family:var(--mono);font-size:.575rem;letter-spacing:.16em;text-transform:uppercase;color:#4d4944;}

/* a product route is one object, not a seven-act landing page: the bands
   keep the same structure and lose the landing page's breathing room */
.prod .band{padding:clamp(50px,6.4vh,86px) var(--gutter);}
.prod .band-index{margin-bottom:clamp(22px,3.2vh,36px);}
.prod .notify-inner{padding:0;}
.prod footer{padding-top:clamp(46px,6vh,78px);}

/* ── the gallery: each reading keeps its own ratio ──────────
   derived from: .gallery (Part II) + .plate at three ratios.
   Two readings sit side by side; a third goes wide across the top,
   because a macro squeezed into a 16:9 slot is not a macro. */
.gal{display:grid;gap:clamp(14px,1.8vw,24px);grid-template-columns:repeat(2,minmax(0,1fr));}
.gal figure{margin:0;min-width:0;}
.gal .gal-wide{grid-column:1 / -1;}
.gal .gal-wide .plate{aspect-ratio:16/9;}
.gal .gal-square .plate{aspect-ratio:1/1;}
.gal .gal-tall .plate{aspect-ratio:4/5;}
.gal .cap{
  display:flex;justify-content:space-between;gap:14px;flex-wrap:wrap;
  margin-top:11px;padding-top:10px;border-top:var(--rule);
}
.gal .cap span{font-family:var(--mono);font-size:.575rem;letter-spacing:.16em;text-transform:uppercase;color:#5b5751;}
@media (max-width:620px){
  .gal{grid-template-columns:1fr;}
  .gal .cap span{flex-basis:100%;}
}

/* ── catalogue: denser boxes, fewer section breaks ─────────── */
.cat-body{margin-top:13px;padding-top:12px;}
.cat .claim{margin-top:7px;font-size:.86rem;}
.cat .cue{margin-top:7px;}
.grid-cat{gap:clamp(22px,2.6vw,40px) clamp(18px,2.2vw,34px);}
/* the shelf name a card belongs to, kept on the card now that the
   catalogue groups by department rather than by shelf */
.cat-head .mono .sub{color:#3f3c38;margin-left:10px;}

/* the catalogue opener is one viewport, not two */
.cat-head-open{padding:clamp(104px,15vh,168px) var(--gutter) clamp(28px,4vh,46px);}
.cat-head-open .page-title{max-width:11ch;}
.cat-head-open .lede{margin-top:clamp(16px,2.4vh,26px);max-width:44ch;}
.cat-open-band{padding-top:clamp(26px,3.4vh,44px);}

/* ── the purchase slot ─────────────────────────────────────────
   One control, two states, driven entirely by the data layer:
   `data-unpriced` shows the reserve action, `data-priced` shows the
   buy action. Nothing here decides which — the toggle already does. */
.buy{display:flex;flex-wrap:wrap;gap:12px 18px;align-items:center;}
.buy .btn.is-buy{border-color:#3f3c38;color:var(--bone);}
.buy .btn.is-buy:hover{border-color:var(--gold);}
.buy .fine{
  flex-basis:100%;margin-top:2px;
  font-family:var(--mono);font-size:.575rem;letter-spacing:.16em;
  text-transform:uppercase;color:#4d4944;
}

@media (max-width:1000px){
  .prod-head{grid-template-columns:1fr;gap:clamp(26px,4vh,40px);padding-top:clamp(92px,13vh,140px);}
  .prod-plate{position:static;}
  .prod-head .page-title{max-width:none;}
}
@media (max-width:620px){
  .prod-head{padding-top:clamp(84px,12vh,120px);}
  .gallery--4{grid-template-columns:1fr;}
  .prod-plate .cap span{flex-basis:100%;}
}

/* ═══════  PART III · THE BOX (2026-08-19, store open)  ═══════════
   The buy control is now the live state on every product page. Two
   lines sit under it: the standing note (why checkout is not charging
   yet) and the live confirmation, which is empty until it is clicked.
   Both reuse `.buy .fine` — this part only distinguishes the spoken
   line from the standing one, and introduces no new colour, font,
   easing, radius or shadow that Part I does not already define. */
.buy .fine.buy-said{color:var(--gold);opacity:0;transition:opacity var(--slow,.6s) ease;}
.buy .fine.buy-said.on{opacity:1;}
.buy .fine.buy-said:empty{display:none;}

/* ═══════  PART IV · LA BOITE — the box, read back  (2026-08-19)  ══
   The founder's note was that there is no cart and no way to check
   out. This part is the cart. Nothing below adds a colour, a font, an
   easing, a radius or a shadow that Part I does not already own, and
   Part I is untouched:

     the line row     is .ledger, given a plate and two controls
     the thumbnail    is .plate--tall at 78px
     the quantity     is .chip, reduced to one character
     the total        is .tally, which the bundle already prints
     the checkout     is .state-panel, which the product pages already use
     Remove           is .link-quiet, unchanged

   The gold law holds: the only gold on the page is the total, and the
   band that carries it is marked `.spent` so its index number steps
   back to bone-3.
   ═════════════════════════════════════════════════════════════ */

/* ── the way to the box, in the bar ─────────────────────────
   derived from: .bar nav a (keyline underline), unchanged in kind.
   The count is `hidden` in the static HTML and stays that way with
   JavaScript off — the entry is offered, a number that cannot be read
   is not claimed. */
.bar nav a.cart-link{display:inline-flex;align-items:center;gap:8px;min-height:44px;}
.cart-count{
  font-family:var(--mono);font-size:.56rem;letter-spacing:.06em;
  color:var(--bone-2);line-height:1;
  padding:4px 6px;border:1px solid #232327;
}
.index-panel a.cart-link{display:flex;align-items:baseline;justify-content:space-between;gap:12px;}

/* ── the box page ───────────────────────────────────────────── */
.boite-lines{border-top:1px solid #232327;}
.boite-line{
  position:relative;
  display:grid;
  grid-template-columns:78px minmax(0,1fr) auto auto auto;
  gap:clamp(16px,2.2vw,32px);
  align-items:center;
  padding:clamp(18px,2.4vh,26px) 0;
  border-bottom:1px solid #17171b;
}
/* the ledger's own hover: a rule drawn across, never a lift or a glow */
.boite-line::after{
  content:"";position:absolute;left:0;bottom:-1px;height:1px;width:0;
  background:#3a352c;transition:width .8s var(--ease);
}
.boite-line:hover::after{width:100%;}

.boite-thumb{display:block;width:78px;aspect-ratio:4/5;flex:none;}
.boite-who{min-width:0;}
.boite-who .name{
  display:block;
  font-family:var(--serif);font-size:clamp(1.06rem,.9vw + .84rem,1.3rem);
  color:var(--bone);letter-spacing:-.006em;line-height:1.2;
  transition:color .5s var(--ease);
}
.boite-who .name:hover{color:#fff8ec;}
.boite-variant{
  display:block;margin-top:7px;
  font-family:var(--mono);font-size:.58rem;letter-spacing:.18em;
  text-transform:uppercase;color:#7d786f;
}
.boite-unit{
  display:block;margin-top:6px;
  font-family:var(--mono);font-size:.575rem;letter-spacing:.14em;
  text-transform:uppercase;color:#8b867d;
}

/* ── the quantity — .chip, cut down to one character ────────── */
.boite-qty{display:inline-flex;align-items:center;gap:2px;}
.boite-q{
  appearance:none;background:transparent;cursor:pointer;
  width:44px;min-height:44px;padding:0;
  border:1px solid #232327;color:#8b867d;
  font-family:var(--mono);font-size:.9rem;line-height:1;
  display:inline-flex;align-items:center;justify-content:center;
  transition:border-color .5s var(--ease),color .5s var(--ease);
}
.boite-q:hover:not([disabled]){border-color:var(--bone-3);color:var(--bone);}
.boite-q[disabled]{color:#2e2e33;border-color:#17171b;cursor:default;}
.boite-n{
  min-width:3ch;text-align:center;
  font-family:var(--mono);font-size:.78rem;letter-spacing:.06em;color:var(--bone);
}
.boite-amt{
  font-family:var(--mono);font-size:.82rem;letter-spacing:.06em;color:#8b867d;
  justify-self:end;white-space:nowrap;
}
.boite-drop{
  appearance:none;background:transparent;border:0;cursor:pointer;
  display:inline-flex;align-items:center;min-height:44px;padding:0;
  font-family:var(--grot);font-size:.6rem;font-weight:500;
  letter-spacing:.28em;text-transform:uppercase;color:#8b867d;
  transition:color .55s var(--ease);
}
.boite-drop:hover{color:var(--bone-2);}

.boite-empty{
  font-family:var(--serif);font-size:clamp(1.24rem,1.4vw + .9rem,1.72rem);
  line-height:1.3;letter-spacing:-.016em;color:var(--bone-2);max-width:30ch;
}
.boite-empty + .link-quiet{margin-top:clamp(18px,2.6vh,26px);}
.boite-live{
  margin-top:16px;font-family:var(--mono);font-size:.6rem;letter-spacing:.16em;
  text-transform:uppercase;color:#8b867d;
  opacity:0;transition:opacity .6s var(--ease);
}
.boite-live.on{opacity:1;}
.boite-live:empty{display:none;}

/* ── the total, and the way out ─────────────────────────────── */
.boite-tally{margin-top:clamp(26px,3.6vh,40px);}
.boite-tally .apart{padding-bottom:14px;}
.boite-checkout{max-width:52ch;}
.boite-checkout .fine.buy-said{color:var(--gold);opacity:0;transition:opacity .6s ease;}
.boite-checkout .fine.buy-said.on{opacity:1;}
.boite-checkout .fine.buy-said:empty{display:none;}
.boite-checkout .btn[disabled]{color:#5b5751;border-color:#17171b;cursor:default;}
.boite-checkout .btn[disabled]:hover{background:transparent;border-color:#17171b;}

/* ── the shade / flavour pick, inside a buy slot ─────────────
   derived from: .filters + .chip, unchanged. Two objects in the
   catalogue are one formula told in more than one reading, and the
   box has to carry which reading was chosen. */
.buy-pick{margin:14px 0 4px;}
.buy-pick .micro{display:block;margin-bottom:10px;}
.buy-pick .picks{display:flex;flex-wrap:wrap;gap:8px;}
/* The slot is a wrapping flex row. The standing note, the spoken line and
   the way to the box are sentences rather than chips, so each takes a row
   of its own instead of being squeezed into a narrow column beside the
   next one. Nothing else in the slot moves. */
.buy .fine,.buy .buy-go{flex:0 0 100%;min-width:0;}
.buy .buy-go{margin-top:6px;}

/* Below 820px the bar hands the whole of navigation to the index
   disclosure. The way to the box does not go with it: a cart a reader
   has to open a panel to find is the complaint this pass exists to
   answer. The nav stays on the bar carrying that one entry, and the
   index panel keeps its own copy for the reader already in there. */
@media (max-width:820px){
  .bar > nav{display:flex;}
  .bar nav a:not(.cart-link){display:none;}
  .boite-line{grid-template-columns:70px minmax(0,1fr) auto auto;gap:16px 20px;}
  .boite-thumb{width:70px;}
  .boite-drop{grid-column:2 / -1;justify-self:start;}
}
@media (max-width:620px){
  .boite-line{grid-template-columns:58px minmax(0,1fr) auto;row-gap:14px;column-gap:16px;}
  .boite-thumb{width:58px;grid-column:1;grid-row:1 / 3;}
  .boite-who{grid-column:2 / 4;grid-row:1;}
  .boite-qty{grid-column:2;grid-row:2;}
  .boite-amt{grid-column:3;grid-row:2;justify-self:end;}
  .boite-drop{grid-column:2 / 4;grid-row:3;justify-self:start;}
  .boite-checkout .acts{gap:14px 18px;}
}

/* ═══════  PART V · THE COMPOSITION FLOOR (2026-08-19, founder review)  ══
   The founder's note, read at ~2000px: prose-only bands stand as one narrow
   column with the right half to two-thirds of the viewport left as dead
   black. Everything below is layout only — no new colour, font, easing,
   radius or shadow, and Part I is untouched. No measure is widened: the
   33ch lede, the 52ch passage and the 56ch letter keep the measures
   DESIGN_SYSTEM.md §3 fixes. What changes is what stands beside them, and
   it is always something the house already owns:

     1. a plate with its two-span caption   — .plate + .gal .cap
     2. a hairline route index              — .routes
     3. the ledger, carrying its own plate  — .ledger + .boite-thumb
     4. the questions, in two columns       — .qa, unchanged in kind

   Every new column collapses at 1000px on the same breakpoint .split uses,
   and every new plate re-ratios on the phone exactly as .head-plate and
   .cat .plate already do.
   ═════════════════════════════════════════════════════════════ */

/* one caption rule for every plate this part introduces —
   derived from: .gal .cap / .head-plate .cap, unchanged */
.notify-plate .cap,.head-plate-side .cap,.rail-plate .cap{
  display:flex;justify-content:space-between;gap:14px;flex-wrap:wrap;
  margin-top:11px;padding-top:10px;border-top:var(--rule);
}
.notify-plate .cap span,.head-plate-side .cap span,
.rail-plate .cap span{
  font-family:var(--mono);font-size:.6rem;letter-spacing:.2em;
  text-transform:uppercase;color:#5b5751;
}

/* ── 1. the letter, given something to stand beside ──────────
   derived from: .prod-head (the type stands beside a plate).
   The plate is square so the band's height is unchanged — the form
   already stood about as tall as the column beside it now is. */
.notify-split{
  display:grid;
  grid-template-columns:minmax(0,1.06fr) minmax(0,.94fr);
  gap:clamp(30px,5vw,80px);align-items:start;
}
.notify-split .notify-inner{max-width:56ch;}
.notify-plate{margin:0;min-width:0;}
.notify-plate .plate{aspect-ratio:1/1;}

/* ── 2. an interior page head with a right-hand column ───────
   derived from: .prod-head (grid, plate beside the type) + .routes.
   Two fillings: a plate where the page is about objects, and the page's
   own section index where it is about terms. */
.head-split{
  display:grid;
  grid-template-columns:minmax(0,1.06fr) minmax(0,.94fr);
  gap:clamp(30px,5vw,80px);align-items:end;
}
.head-split .head-type{min-width:0;}
.head-split .head-type .lede{margin-top:clamp(20px,3vh,30px);}
.head-plate-side{margin:0;min-width:0;}
.head-plate-side .plate{aspect-ratio:1/1;}
.head-aside{min-width:0;}
.head-aside > .micro{display:block;margin-bottom:14px;}
.head-aside .routes{margin-top:0;}

/* ── 3. a rail beside a run of passages ──────────────────────
   derived from: .prod-plate (sticky plate column) + .ed-quote (the
   pull-quote) — the maison's three passages are 62ch of argument with
   nothing on the other side of them. */
.passage-rail{
  display:grid;
  grid-template-columns:minmax(0,62ch) minmax(0,1fr);
  gap:clamp(30px,5vw,84px);align-items:start;
}
.passage-rail .passages{max-width:none;}
.rail{position:sticky;top:clamp(96px,12vh,132px);min-width:0;max-width:760px;margin-left:auto;}
.rail-plate{margin:0;}
.rail-plate .plate{aspect-ratio:4/5;}
.rail-note{margin-top:clamp(30px,4.4vh,46px);padding-top:22px;border-top:var(--rule);}
.rail-note blockquote{
  font-family:var(--serif);
  font-size:clamp(1.3rem,1.5vw + .92rem,1.85rem);
  line-height:1.2;letter-spacing:-.02em;color:var(--bone);max-width:22ch;
}
.rail-note blockquote .it{font-style:italic;color:var(--bone-2);}
.rail-note cite{
  display:block;margin-top:16px;font-style:normal;
  font-family:var(--mono);font-size:.6rem;letter-spacing:.24em;
  text-transform:uppercase;color:#5b5751;
}

/* ── 4. a .split whose left column is a lede ─────────────────
   derived from: .split, ratio only. The lede holds the 33ch measure
   DESIGN_SYSTEM.md §3 fixes, so on a wide viewport the column is
   narrowed to the copy rather than the copy stretched to the column. */
.split--lede{grid-template-columns:minmax(0,.66fr) minmax(0,1.34fr);}

/* ── 5. the pairing ledger, carrying the object's own plate ──
   derived from: .ledger (Part I) + .boite-thumb (Part IV). "What it sits
   next to" printed three names and a 52ch reason into the left quarter of
   the band; the neighbour's own catalogue plate now opens the row and the
   reason takes the column that was empty. */
.ledger--pair .row{
  grid-template-columns:2.6ch 88px minmax(0,1.05fr) minmax(0,1.4fr) auto;
  align-items:start;padding:18px 0;
}
.ledger--pair .idx{padding-top:6px;}
.ledger--pair .thumb{display:block;width:88px;aspect-ratio:4/5;}
.ledger--pair .why{max-width:none;margin-top:0;padding-top:4px;}
.ledger--pair .name{line-height:1.15;}
/* the neighbour arrives with its own number, exactly as every other
   ledger row in the house does — .ledger .amt, on the same toggle the
   catalogue card uses, so an object that ever loses its price degrades
   to its state label rather than to a hole */
.ledger--pair .pair-amt{justify-self:end;text-align:right;padding-top:5px;}
.ledger--pair .pair-amt .amt{display:block;max-width:11ch;line-height:1.5;}

/* the department index on the home page — .ledger, in an aside column.
   "Where it reaches" named nine departments and printed none of them.
   Each one now gets the row the routine ledger already has: the index,
   the name, the note the data layer carries for it, and how many objects
   are on it. The department note takes its own column so the row is one
   line and the band does not double in height to say nine things. */
.dept-ledger{margin-top:14px;}
.dept-ledger .row{
  grid-template-columns:2.6ch minmax(0,.9fr) minmax(0,1.1fr) auto;
  align-items:baseline;padding:15px 0;
}
.dept-ledger .role{margin-top:0;}
@media (max-width:820px){
  .dept-ledger .row{grid-template-columns:2.6ch minmax(0,1fr) auto;row-gap:6px;}
  .dept-ledger .name{grid-column:2;grid-row:1;}
  .dept-ledger .amt{grid-column:3;grid-row:1;}
  .dept-ledger .role{grid-column:2 / -1;grid-row:2;}
}

/* ── 6. the questions, in two columns at width ───────────────
   derived from: .qa, unchanged in kind. Nine disclosures in one 74ch
   column left the right half of the band black and made the band taller
   than it needed to be; two columns fix both. */
@media (min-width:1200px){
  .qa--two{
    max-width:none;border-top:0;border-bottom:var(--rule);
    display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
    column-gap:clamp(40px,5vw,86px);align-content:start;
  }
  .qa--two > details{border-top:var(--rule);border-bottom:0;}
  .qa--two .answer{max-width:none;}
}

/* ── 7. the box, read back beside its own terms ──────────────
   derived from: .split + .split-aside. With JavaScript off the band is a
   single sentence; the notes beside it are the same facts the tally and
   the checkout panel print once they can be read. */
.boite-split{align-items:start;}
.boite-split .boite-checkout{margin-top:clamp(26px,3.6vh,40px);}

/* ── 8. responsive ───────────────────────────────────────────
   the same 1000px fold .split already uses, and the same phone re-ratio
   .head-plate and .cat .plate already use. */
@media (max-width:1000px){
  /* .split--lede is declared below the Part II fold rule, so it has to
     repeat it here or it would out-order the collapse on a phone */
  .notify-split,.head-split,.passage-rail,.split--lede{grid-template-columns:1fr;}
  .head-split{align-items:start;}
  .head-aside,.head-plate-side{margin-top:clamp(30px,5vh,48px);}
  .passage-rail .passages{max-width:62ch;}
  .rail{position:static;margin-top:clamp(38px,6vh,64px);}
  .notify-plate{margin-top:clamp(34px,5vh,52px);}
  .notify-plate .plate,.head-plate-side .plate,.rail-plate .plate{aspect-ratio:16/9;}
  .ledger--pair .row{grid-template-columns:2.6ch 78px minmax(0,1fr) auto;row-gap:10px;}
  .ledger--pair .thumb{width:78px;grid-column:2;grid-row:1;}
  .ledger--pair .row > span:nth-child(3){grid-column:3;grid-row:1;}
  .ledger--pair .pair-amt{grid-column:4;grid-row:1;}
  .ledger--pair .why{grid-column:2 / -1;grid-row:2;}
}
@media (max-width:620px){
  .ledger--pair .row{grid-template-columns:64px minmax(0,1fr) auto;}
  .ledger--pair .thumb{width:64px;grid-column:1;grid-row:1;}
  .ledger--pair .row > span:nth-child(3){grid-column:2;grid-row:1;}
  .ledger--pair .idx{display:none;}
  .ledger--pair .pair-amt{grid-column:3;grid-row:1;}
  .ledger--pair .why{grid-column:1 / -1;grid-row:2;}
}

/* ═══════  PART VI · THE BODY LAYER (2026-08-20, typographic repair)  ══
   The defect this part repairs: every page set its body copy in the
   interface sans at regular weight, inherited from ONE declaration —
   `body{font-family:var(--grot)}` in Part I. 2,084 elements per page
   state, across all 76 pages, in 24 families, none of which declared a
   face of its own. It read as UI text pasted into a magazine.

   The repair is a single inherited flip expressed through tokens, plus
   the measure, colour and line-breaking discipline that a body layer is
   supposed to carry. Parts I–V are untouched and byte-identical; every
   rule below lands later in the cascade.

   WHY THIS FACE. Charter (Matthew Carter, 1987) is a TEXT-optical
   serif — low contrast, large x-height, drawn to survive coarse
   rendering. It is the correct companion to a Didot: the same rational
   French skeleton, the opposite optical class. The display face never
   descends into the body; a face built for 15px does that work instead.

   WHY NOTHING IS DOWNLOADED. System stack only. Charter ships with
   macOS and iOS; Iowan Old Style, Palatino and Georgia carry the rest.
   Zero network requests, zero embedded files, zero licence exposure —
   DESIGN_SYSTEM.md §3 ("three system stacks, no downloads") survives
   intact, now with a fourth stack drawn from the same well.

   THE LABEL LAYER IS IMMUNE BY CONSTRUCTION. Every intentional grot use
   in Parts I–V re-states `font-family:var(--grot)` explicitly (.micro,
   .btn, .link-quiet, .skip, .bar-index summary, .chip, .field button,
   .tally .together .label, .boite-drop, .picks button). Nothing below
   re-states them, so the tracked-caps label layer — 3,096 instances,
   46 signatures — is carried through unchanged. Verified by harness.

   THE LEDE HOLDS AT ~34ch, ON PURPOSE (director, 2026-08-20). The
   45–75ch window is a RUNNING-TEXT rule. `.lede` is a display-adjacent
   device, and its column is fixed by `.split--lede` at .66fr — 402px at
   1440, where 45ch would need 490px. Reaching the window would mean
   dropping the lede to ~16px and killing the hierarchy, or changing a
   locked grid. It stays where the locked design put it.

   DIMMING STAYS MEANING. The three dimmed tiers are re-struck, not
   flattened: they keep their order and their warmth, and every one of
   them now clears WCAG AA on the ground (they were 4.56 / 3.62 / 2.97).
   ═════════════════════════════════════════════════════════════ */

:root{
  /* the fourth system stack, alongside --serif / --grot / --mono */
  --text-serif:Charter,"Bitstream Charter","Charis SIL","Iowan Old Style",
               "Palatino Linotype",Palatino,"Book Antiqua",Georgia,serif;

  /* the body layer, tokenised — every consumer below reads these */
  --font-body:var(--text-serif);
  --body-size:clamp(15.2px,.56vw + 13.1px,17.2px);
  --body-leading:1.60;
  --body-tracking:.001em;
  --body-color:#beb7a9;          /* 10.0:1 on --ink */
  --body-measure:66ch;           /* running text, inside 45–75ch */

  /* the lede — display-adjacent, deliberately outside the window */
  --lede-size:clamp(1.0rem,.46vw + .9rem,1.16rem);
  --lede-leading:1.58;
  --lede-measure:34ch;

  /* the dimmed ramp. hierarchy preserved, all three clear AA */
  --body-dim-1:#9d968b;          /* 6.8:1  was #7d786f (4.56) */
  --body-dim-2:#8d867c;          /* 5.6:1  was #6d6860 (3.62) */
  --body-dim-3:#7f786e;          /* 4.6:1  was #5f5b55 (2.97) */
}

/* ── the one flip. everything that inherited the defect is repaired here ── */
body{
  font-family:var(--font-body);
  font-size:var(--body-size);
  line-height:var(--body-leading);
  letter-spacing:var(--body-tracking);
  color:var(--body-color);
  -webkit-hyphens:manual;
  hyphens:manual;                /* never hyphenate automatically */
  text-wrap:pretty;              /* no single-word last lines */
}

/* ── the lede ──────────────────────────────────────────────── */
.lede{
  font-size:var(--lede-size);
  line-height:var(--lede-leading);
  color:var(--body-color);
  max-width:min(var(--lede-measure),100%);
}
/* Consecutive ledes had no separation anywhere in Parts I–V, so two
   paragraphs set as .lede ran together as one block. .record-copy,
   .qa .answer and .split-aside all already own this rule; the lede was
   the one running-text primitive that did not. Same idiom, one step
   larger because the lede is the larger type. */
.lede + .lede{margin-top:clamp(15px,1.9vh,21px);}

/* ── running body, held inside the 45–75ch window ──────────── */
/* min() so a narrow column wins on its own terms and no layout moves */
.split-aside p,
.ed-strip p,
.cat-note p,
.prose p,
.prose li,
.qa .answer p,
.passage p,
.record-copy p,
.statement-foot p,
.terms p{
  max-width:min(var(--body-measure),100%);
  text-wrap:pretty;
}

.split-aside p{font-size:.98rem;line-height:1.62;}
.ed-strip p{font-size:.98rem;line-height:1.62;}
.cat-note p{font-size:.95rem;color:var(--body-dim-1);}
.spec .v{font-size:.96rem;}

/* ── the dimmed tiers, re-struck for thinner serif strokes ─── */
.ledger .role,
.cat .claim,
.terms p,
.foot-cols a,
.cat-note p{color:var(--body-dim-1);}
.tally .fine,
.state-panel .fine,
.prose .fine{color:var(--body-dim-2);}
.ledger .why,
.cluster-note{color:var(--body-dim-3);}

.ledger .role{font-size:.9rem;line-height:1.5;letter-spacing:0;}
.cat .claim{font-size:.9rem;line-height:1.45;}

/* ── anchored arrivals clear the fixed bar ─────────────────────
   Part I sets `.bar{position:fixed}` (69px settled, 77px not) and no
   scroll offset was ever declared against it. Anchors whose id sits on a
   bare heading landed at y=0, entirely behind the bar — 21 fragments,
   both widths, and identically with JavaScript off, which is what proves
   the reveal was never involved. Bands survived only because
   `.band{padding-top}` happens to be taller than the bar: an accident,
   and on the product route it is not even true.

   A band must not be pushed twice, so its offset is the REMAINDER — what
   is left after its own top padding has done the work. The padding comes
   in three regimes and the token mirrors each one without altering it:

     .band          clamp(78px,11vh,150px)   Part I
     .notify        clamp(84px,13vh,168px)   Part I
     .prod .band    clamp(50px,6.4vh,86px)   Part III — the tight route

   max() is the safety: a band whose padding already exceeds the target
   only ever gains air, never loses it. The target lands every band header
   at ~112px, which clears the unsettled 77px bar by 35px.

   If a band's padding is ever retuned in Parts I–V, retune its token
   here in the same edit. */
:root{--band-pad:clamp(78px,11vh,150px);}
.notify{--band-pad:clamp(84px,13vh,168px);}
.prod .band{--band-pad:clamp(50px,6.4vh,86px);}

:where([id]){scroll-margin-top:clamp(92px,12vh,120px);}
.band[id]{scroll-margin-top:max(16px,calc(112px - var(--band-pad)));}
main[id]{scroll-margin-top:16px;}
.cat-head{scroll-margin-top:clamp(92px,12vh,120px);}

/* ═══════  PART VII · THE PURCHASE SURFACES, MADE STILL  ══════════
   (2026-08-20, founder review of checkout)

   The founder's note: *"the checkout page feels a bit weird… the right
   button looks oddly placed and when i click the other button it moves
   the right one down."* Both halves are one fault. A purchase surface
   that rearranges itself the instant it is used is not a surface a
   reader can aim at, and the second half of it — a note that appears
   BESIDE the note already standing there — is also two sentences
   saying nearly the same thing at once.

   Everything below is layout, and it is layout in one direction only:
   space that a state change will need is reserved before the change
   happens, so that no state change can move a neighbour. No new
   colour, font, easing, radius or shadow; Parts I–VI are byte-
   untouched (`sed -n '1,1591p' regarde.css | shasum -a 256`).

     the action row      is .acts, unchanged in kind — one row, one line
     the one note slot   is .fine, given a single grid cell to stand in
     the count reserve   is .cart-count, given its own width to fill
     the box column      is .split, ratio only (Part V §4, reversed)
     the closing pair    is .record-grid's .9fr/1.1fr, unchanged
   ═════════════════════════════════════════════════════════════ */

/* ── 1. the count in the bar reserves its own place ───────────
   `paintCount()` un-hides the count on the first add. The bar is
   `justify-content:space-between`, so a nav that grows by the width of
   a badge drags every entry in it sideways — measured at 1440: eleven
   elements moved on one click, none of them the one that was pressed.
   The badge now holds a two-character slot from the first paint and an
   empty box makes it invisible rather than absent. `paintCount()` drops
   the static `hidden` and carries emptiness on `.is-none` instead: the
   UA's own `[hidden]` rule cannot be talked out of `display:none` by an
   author declaration, and `!important` is not a house habit. With
   JavaScript off the attribute stands, nothing is reserved and nothing
   ever moves, which is the same guarantee by a shorter route. */
.cart-count{
  display:inline-block;
  /* the only `content-box` in the file, and it is what makes the reserve
     say what it means: two characters of the badge's own mono and one
     line of it, measured without the padding and border Part IV already
     set, so the empty slot and the filled one are the same box */
  box-sizing:content-box;
  min-width:2ch;min-height:1em;text-align:center;
}
/* An inline box with nothing in it has no line box, so it is aligned by
   its bottom edge instead of by a baseline — which moved the badge down
   7px on the first add wherever its row is baseline-aligned (the index
   panel, and the way to the box inside a slot). A zero-width space is
   content: it costs no width, it gives the empty badge the same baseline
   the filled one has, and `visibility:hidden` keeps it out of the
   accessibility tree and out of a selection. */
.cart-count.is-none{visibility:hidden;}
.cart-count.is-none::before{content:"\200B";}

/* ── 2. the purchase slot — one action row, one note slot ─────
   Before: `.buy` was a wrapping flex row and its three sentences each
   took a row of their own, so the slot was five rows tall and the link
   beside it in `.acts` floated, vertically centred, in the black to the
   right of all five. Adding a sixth row moved it again.

   Now the controls stand together on one row — the add, the way to the
   box, and the way to the rest of the catalogue are one cluster, in
   that order — and everything the slot has to SAY happens in one slot
   underneath, which cannot grow because both sentences are already
   standing in it. */
.acts > .buy{flex:1 1 100%;min-width:0;}
.buy-acts{
  flex:0 0 100%;min-width:0;
  display:flex;flex-wrap:wrap;align-items:center;
  gap:12px clamp(18px,1.8vw,26px);
}
.buy .buy-acts .buy-go{flex:0 1 auto;margin-top:0;}
.buy-pick{flex:0 0 100%;min-width:0;margin:0 0 2px;}

/* ── 3. the one note slot ────────────────────────────────────
   derived from: .fine, given a grid of exactly one cell. The standing
   sentence and the spoken one occupy the same cell, so the slot is as
   tall as the taller of the two from first paint and a press swaps
   which one is visible — never how much room they need. The standing
   line goes `visibility:hidden`, not `display:none`, because it is the
   line that reserves the height.

   The spoken line keeps `role="status"`: it is still the only element
   that announces, and the standing line is not a live region, so a
   press is announced exactly once. */
.buy-note{display:grid;}
/* the slot takes the measure of the sentence standing above it in the
   same panel — 36ch of the body serif is 264px, and `ch` on this line is
   the mono's, which is narrower, so 36ch here was 198px and broke the
   note into four short lines under a 900px row. In the routine's second
   slot, which has no panel around it, it had no measure at all and ran
   to 773px at 1920. One measure, both places. */
.buy .buy-note{max-width:48ch;}
.buy-note > .buy-line{grid-column:1;grid-row:1;margin-top:0;min-width:0;}
.buy-note.is-said > [data-buy-note],
.buy-note.is-said > [data-boite-note]{visibility:hidden;}
.buy-note > .buy-said{
  color:var(--gold);opacity:0;transition:opacity .6s var(--ease);
}
.buy-note > .buy-said.on{opacity:1;}
.buy-note > .buy-said:empty{display:none;}

/* ── 4. LA BOITE — the box takes the wide column ──────────────
   derived from: .split, ratio only — Part V §4's .66fr/1.34fr, the
   other way round. The band's subject is the list of objects and the
   number under it; the terms beside it are two short notes at a 32ch
   measure and a route index. Before this, the list was squeezed into
   the .92fr column and the notes were given the 1.08fr one — and one of
   those notes was the sentence already printed under the total. */
.boite-split{grid-template-columns:minmax(0,1.34fr) minmax(0,.66fr);}
/* and the box itself is measured, not stretched: 92ch is the widest the
   ledger, its spoken line and the pair that closes it ever get, so the
   three of them share one right edge at every width instead of the list
   running 240px past the total at 1920. The column keeps its 1.34fr —
   what changes is that the content inside it stops. */
.boite-col{max-width:92ch;}

/* ── 5. the spoken line of the box, given a place ─────────────
   Removing a line or changing a quantity spoke into a status line that
   appeared out of nothing between the list and the total and pushed
   the total down — a sentence with no place, which is how it read. It
   now sits tight under the list it is talking about, in a slot that is
   there whether or not it has anything in it, and it fades rather than
   arrives. `role="status"` is unchanged. */
.boite-live{
  margin-top:12px;
  /* the reserve is one line of this line's own leading, stated rather
     than inherited, so the empty slot and the spoken one are the same
     height to the pixel — 1.5em was 14.40px against a 15.36px line and
     pushed the total down by a hair on every press */
  line-height:1.6;min-height:1.6em;
}
.boite-live:empty{display:block;}

/* the amounts column holds a width, so a line going from $84 to $126
   cannot pull the quantity controls 9px sideways under the reader's
   cursor — the same reserve `.boite-n` already keeps for the digit */
.boite-amt{min-width:5ch;text-align:right;}

/* ── 6. the total and the way out, side by side ───────────────
   derived from: .record-grid (.9fr/1.1fr, Part I). In the wide column
   the tally's two `space-between` rows would have stretched a label and
   a figure to opposite ends of 800px, and the checkout panel would have
   stood alone under it with the rest of the band black. They close the
   band together instead: the number, then the door. Both keep the
   margin they already carried, so an empty box — where both are
   `hidden` — reserves nothing at all. */
.boite-close{
  display:grid;grid-template-columns:minmax(0,.9fr) minmax(0,1.1fr);
  gap:clamp(26px,3.4vw,56px);align-items:start;
}
/* a total whose label and figure are held apart by `space-between` gets
   further apart every pixel its cell grows, so it keeps a measure; the
   panel keeps one too and is pushed to the right edge of the pair, which
   is the ledger's own right edge — the column the amounts and Remove
   already stand in. */
.boite-close > .boite-tally{max-width:38ch;}
.boite-close > .boite-checkout{justify-self:end;width:100%;}
.boite-split .boite-checkout{max-width:44ch;}

/* ── 7. the fold ─────────────────────────────────────────────
   `.split` collapses at 1000px in Part II and `.boite-line` re-lays
   itself at 820px. The ratio above is declared BELOW that fold rule and
   at the same specificity, so it would otherwise out-order the collapse
   and hold two columns on a phone — the same trap Part V §8 records for
   `.split--lede`. It is repeated here for the same reason. The closing
   pair goes with the line, at 820px. */
@media (max-width:1000px){
  .boite-split{grid-template-columns:1fr;}
}
@media (max-width:820px){
  .boite-close{grid-template-columns:1fr;}
  .boite-close > .boite-tally{max-width:none;}
  .boite-split .boite-checkout{max-width:none;}
}

/* ═══════  PART VIII · THE THUMB AND THE FOLD  ════════════════════
   (2026-08-20, the founder reading the store on his own iPhone)

   *"these cart sections on mobile are brutal… they should fit
   correctly on mobile. and desktop."*

   A 390×844 desktop window is not a phone, and the checks that had
   been run were run in one. Under real device emulation — Playwright's
   own descriptors, so the pixel ratio, the touch flag and the user
   agent are the device's — two faults stand on a phone that do not
   stand in a desktop window narrowed to the same number, and a third
   was reported and turned out to be the harness mismeasuring:

     1. AN ARROW LEFT BEHIND. `.btn` and `.link-quiet` are inline-flex
        with a `gap`, so a label is one flex item and its arrow is
        another. Squeeze the control below its own content and the
        LABEL shrinks and wraps while the arrow stays pinned after the
        label's full, unshrunken box. Measured on the routine's action
        band: at 390 the arrow of "Add La Routine to the box" stood
        88.2px past the end of "THE BOX", and the arrow of "Or all
        sixty-five, one at a time" stood 232.6px past the end of "A
        TIME" — a quarter of the screen of black between a label and
        the mark that belongs to it. It reproduces at 360, 375, 390 and
        412, which is most of the phones there are, and not at 430,
        which is the one a 430px desktop window would have shown.
     2. TARGETS FOR A CURSOR. The cart line's own name link is 20.3px
        tall, the footer's links 37.5px, the wordmark 28.7px. Each is a
        fine mouse target and a poor thumb one.
     3. NOT A FAULT. A note in `.ed-strip` and a spec value on a 360px
        Android both read as short columns until the measure itself was
        measured properly. Both are inside the window. §3 records what
        was wrong with the reading and writes no rule.

   Nothing below adds a colour, a font, an easing, a radius or a
   shadow. Parts I–VII are byte-untouched:
   `sed -n '1,1768p' regarde.css | shasum -a 256`
   → 83282be30e4d48513040bac9ddb2f40c2fd383229911f71f0a7e2022fd4343ab

   HOW THIS PART AVOIDS THE TRAP PARTS V AND VII BOTH RECORD.
   `.split--lede` shipped once declared BELOW Part II's 1000px fold
   rule, so it held two columns on a phone; `.boite-split` repeated it
   and had to repeat the fold with it. §1 and §3 below carry NO width
   breakpoint at all — they are true at every width, so there is no
   later media query for them to be out-ordered by. §2 is a query, but
   it is a query about the INPUT DEVICE and not about the width, so no
   width rule anywhere in this file can reach it. And the whole class
   is now gated: `tools/responsive.mjs` fails on any grid that stands
   in more than one column below the fold unless it is a declared row
   grid, and `--trap` proves it fails by injecting the fault.
   ═════════════════════════════════════════════════════════════ */

/* ── 1. the arrow belongs to its label ────────────────────────
   derived from: .btn and .link-quiet, Part I, with the INNER layout
   changed and nothing else. `display:block` on a flex item is what it
   already computed to — what changes is that the label and the arrow
   stop being two flex items and become one line of text, so the arrow
   is laid out by the line breaker along with the last word and lands
   where the label ends. The control's own width is untouched: as a
   flex item its base size is still its max-content, and it still
   shrinks the same way.

   The two numbers that hold the geometry still:

     line-height   the `gap` centred a one-line label in the box; a
                   block has to fill it instead. 18px + 13px padding
                   twice + 1px border twice = the 46px .btn already
                   stood at. 22px + 11px twice = the 44px .link-quiet
                   already stood at. Both measured identical to the
                   pixel at 430, 768, 1280, 1440 and 1920.
     margin-left   in a flex row the label's trailing space was
                   trimmed and the 12px/9px `gap` was the whole
                   distance. In a line of text that space is set, so
                   the margin is the REMAINDER — 5.5px and 2.5px — and
                   the arrow stands exactly where it stood. */
.buy-acts > .btn,
.buy-acts > .link-quiet,
.state-panel .acts > .btn,
.state-panel .acts > .link-quiet{display:block;}
.buy-acts > .btn,
.state-panel .acts > .btn{line-height:18px;}
.buy-acts > .link-quiet,
.state-panel .acts > .link-quiet{line-height:22px;padding-block:11px;}
.buy-acts > .btn > .arrow,
.state-panel .acts > .btn > .arrow{margin-left:5.5px;}
.buy-acts > .link-quiet > .arrow,
.state-panel .acts > .link-quiet > .arrow{margin-left:2.5px;}
/* the badge kept the 9px the flex gap held between it and the arrow,
   and there is no space between them in the source to help */
.buy-acts > .link-quiet > .cart-count{margin-left:9px;}

/* ── 2. the thumb ─────────────────────────────────────────────
   `(hover:none) and (pointer:coarse)` is the only honest way to ask
   the question this section is asking. It is not a width: an iPad at
   834 has a thumb and a laptop at 834 does not, and a 44px floor is
   about the thumb. It is also not a width in the other sense — no
   width rule in this file, at any breakpoint, can out-order it.

   Two idioms, and which one is used says something:
     PADDING OUT, MARGIN BACK   grows the HIT BOX and leaves the page
        exactly where it was. Used where the line is set inside a
        composition that is already right — the wordmark on the bar,
        the name on a cart line — and verified: at 390 the name's box
        grew 24px and NOTHING else on the page moved by so much as a
        pixel.
     PADDING, AND THE PAGE GIVES WAY   grows the target for real. Used
        where the targets TILE — the footer's columns — because there
        a hit box that overhangs its neighbour is worse than a small
        one: two overlapping targets is a coin toss, and a small one is
        merely a small one. The footer grows 56px on a phone. That is
        the price and it is the right price. */
@media (hover:none) and (pointer:coarse){
  /* padding out, margin back */
  .bar > .wordmark{padding-block:8px;margin-block:-8px;}
  /* the cart link is already 44 and is excluded: giving it the same
     treatment shrank its margin box and pulled the whole nav 8px down.
     These carry 6px of padding already, so the numbers are 14 out and
     8 back — and the underline the bar draws on hover is measured from
     the padding box, so it is put back where it was drawn. */
  .bar nav a.micro:not(.cart-link){padding-block:14px;margin-block:-8px;}
  .bar nav a.micro:not(.cart-link)::after{bottom:10px;}
  .boite-who .name{padding-block:12px;margin-block:-12px;}
  .ledger .row > .name{padding-block:8px;margin-block:-8px;}

  /* padding, and the page gives way */
  .foot-cols a{padding-block:11px;}
  .jump-panel a{min-height:44px;}
  /* "Top" is 26.7px wide, which is a target no thumb can find twice */
  .foot-nav a{min-width:44px;justify-content:center;}
}

/* ── 3. the measure, and why nothing is done about it ─────────
   A third rule stood here for part of this pass and has been struck,
   because the fault it answered was in the harness and not in the
   page. `.ed-strip` auto-fits at a 220px floor, which on a landscape
   phone at 814 seats three 226.8px tracks; the first measure read
   those tracks as 27.9 characters and this part widened the floor to
   240px to open them. Measured properly — the content box over the
   advance of the note's own string, rather than the widest line a
   ragged four-line paragraph happened to reach — the track seats 32.7
   characters, which is inside the window and always was. The same
   correction cleared `.spec .v` on a 360px Android: 223.7px reads as
   31.7 characters, not 26.9.

   The floor is back at Part I's 220px and no rule is written here. A
   measure that is fine does not get widened because a harness said
   otherwise, and the harness now says what it means: see the note on
   THE MEASURE IS THE COLUMN in tools/responsive.mjs.

   One thing was seen while measuring and is left alone on purpose:
   the spec row's key track is 9.5ch of the BODY serif — 80.3px on a
   360px screen — while the two longest keys the catalogue uses,
   "Ingredients" and "Compression", set 84.7px in the label mono. They
   overrun their track by 4.4px into a 16px gap, so nothing collides
   and nothing wraps. Widening the key would narrow the value, which
   is the column that carries the sentence. It stays as it is. */

/* ═══════  PART IX · ONE MARK, ONE MEANING  ═══════════════════════
   (2026-08-20, the founder clicking through the bar, and reading
   the questions on a wide screen)

   *"the header nav … gets glitchy or weird when i click other
   pages"* — and *"this drop down for questions looks bad when i
   open only one"*.

   ── WHAT WAS REPORTED ABOUT THE BAR, AND WHAT IS TRUE ──────────
   Five faults were described by a model reading screenshots rather
   than measuring. Measured over 144 real arrivals — every route ×
   390/768/1440/1920 × {mouse, keyboard, back/forward, cursor left
   at rest} — two are real, one is real with the wrong cause, and
   two do not happen at all.

     REAL · TWO MARKS AT ONCE. `.bar nav a::after` is asked to carry
        two unrelated meanings on one channel: Part I draws it on
        :hover in --bone-3, Part II draws it on [aria-current] in
        #3a352c. Both can therefore stand at once, and in 8 of 9
        cursor-at-rest states at 1440 both did — Support + La Boîte,
        La Boîte + The letter, Catalogue + Support, the very pairs
        the report named.
        And the hierarchy is INVERTED. On the ink ground the hover
        mark reads 3.90:1 and the current-page mark 1.64:1, so the
        mark meaning "your cursor is here" is 2.4× louder than the
        mark meaning "you are here". The reader is being told the
        wrong thing, more loudly.

     REAL, WRONG CAUSE · THE INDICATOR VANISHES. On home it is
        genuinely absent — the bar's nav has no entry for home, the
        wordmark is the home link and it does not sit in the nav, so
        there is nothing to mark. On Support it is not absent: it
        measures 76.84px every single time. It is invisible. 1.64:1
        is below any floor a hairline can be seen at.

     NOT A DESYNC · "on The Letter page, MAISON still reads active".
        There is no Letter page. `The letter` is href="#notify", a
        same-document fragment that exists on all seven pages, so
        clicking it never navigates and the route you were on is
        still, correctly, the route you are on. Across 144 arrivals
        [aria-current] never once disagreed with location.pathname.

     DOES NOT HAPPEN · LAG, JITTER, AN OFFSET BEFORE SETTLING. The
        current-page mark is static markup with nothing animating on
        it. Sampled every frame from 5ms after first paint to
        1600ms on three routes: 183–191 samples, ONE used width each
        (76.84 / 64.84 / 96.91) and one y. Nothing settles because
        nothing moves. The hover mark does draw across in ~500ms —
        that is §7's directional hover, and it is the design.

     DOES NOT HAPPEN · NEIGHBOURS SHIFTING SIDEWAYS. Every nav item
        held the same x in all 144 arrivals, and the active state
        changes `color` and nothing else: font-weight 500 and
        letter-spacing 4.2px measured identical in every sample at
        every width. No metric the layout reads is touched, so no
        neighbour can move. The bar does shift 4px VERTICALLY, all
        items together — that is `.bar.settled` trading 16px of
        padding for 12px on scroll, Part I's own gesture.

   ── THE RULE THIS PART WRITES ──────────────────────────────────
   **One mark, one meaning.** A channel that says "you are here" may
   not also say "your cursor is here". The bar was the only place in
   the house that broke it: `.foot-nav a:hover`, `.foot-cols a:hover`
   and `.index-panel a:hover` all answer a nav hover by warming the
   type and drawing nothing at all. §7 lists that as a hover in good
   standing — "a border warms" — so the bar is brought into line
   with the rest of the house rather than given something new.

   Nothing below adds a colour, a font, an easing, a radius or a
   shadow. --bone-3 and --bone-2 are Part I's own tokens, and
   --bone-3 is the value Part I already paints this very underline
   with. Parts I–VIII are byte-untouched:
   `sed -n '1,1924p' regarde.css | shasum -a 256`
   → 11435975970d74512ae51efd739596b9cc59f3a33ad0b5a8ccdffb8ce822b2eb
   ═════════════════════════════════════════════════════════════ */

/* ── 1. the mark that means "you are here" ────────────────────
   Raised from #3a352c to the --bone-3 the hover mark was already
   using: 1.64:1 → 3.90:1 on the ink. Nothing else about it changes
   — same 1px, same position, same full width, still static, still
   written by [aria-current] in the markup and by nothing else. */
.bar nav a[aria-current="page"]::after{background:var(--bone-3);}

/* ── 2. hover gives the channel back ──────────────────────────
   `:not([aria-current="page"])` is what keeps this off the current
   route: without it this rule and Part II's both compute to (0,2,3)
   and the later one — this one — would collapse the very mark §1
   has just made visible. The current route keeps its rule under the
   cursor; every other entry answers with type instead.

   Part I's transition on `right` is left exactly where it is and
   simply never has two values to move between any more. The colour
   warm borrows `.foot-nav a`'s transition verbatim, so the bar and
   the footer answer a hover at the same speed on the same curve. */
.bar nav a{transition:color .5s var(--ease);}
.bar nav a:not([aria-current="page"]):hover::after{right:100%;}
.bar nav a:not([aria-current="page"]):hover{color:var(--bone-2);}
/* `The letter` idles at --bone-2 already (.keyline), so a warm to
   --bone-2 would be no warm at all. It is a fragment and can never
   be a route, so it can never carry the mark §1 owns, and taking
   its type to --bone cannot be misread as "you are here" while the
   one rule on the bar is standing somewhere else. */
.bar nav a.keyline:not([aria-current="page"]):hover{color:var(--bone);}

/* ── 3. the keyboard keeps its own channel ────────────────────
   Nothing here touches :focus or :focus-visible. Part I's gold
   outline stands untouched, and it was never part of the collision:
   focus draws no underline, which is exactly why the keyboard path
   measured ONE mark per arrival in the before-run while the mouse
   path measured two. The two states are separate and stay separate.
   This is written down because the obvious "fix" — hanging the
   active state off :focus — would merge them. */

/* ── 4. the questions stand in two stacks, not in one grid ────
   *"this drop down for questions looks bad when i open only one —
   should both open the text at the same time?"*  No. Pairing two
   unrelated questions so they open together is a false claim about
   the copy and doubles what the reader has to skip. The fault is
   not the pairing, it is that there WAS a pairing at all.

   Part V's `.qa--two` places eight <details> as eight items in one
   two-track grid, so they land in four ROWS — and a grid row is as
   tall as its tallest cell while `align-items` stretches the short
   one to match. Open one question and its neighbour across the row
   is stretched with it, carrying the difference as black inside its
   own box, under its own closed summary. Measured at 1440, opening
   each question alone: 74.19, 99.28, 124.38, 138.38 and 188.56px of
   dead black in the sibling column — and 64.19px still left with
   all eight open, because the rows are not equal even then. The
   founder's screenshot is the 99.28px case: "Can I buy anything
   today?" open on the right, "Is Regarde open?" closed on the left.

   The rows are the whole defect, so the rows are removed. Each
   column becomes its own block stack (`.qa-col` in the markup), the
   grid places two stacks instead of eight cells, and opening an
   item can only push the items BELOW IT IN ITS OWN COLUMN. There is
   no longer a row for a sibling to be tied to.

   Three consequences, all of them wanted:
     · reading order becomes column-major — left column top to
       bottom, then right — and the DOM order is that order, so what
       a screen reader announces and where the Tab sequence goes are
       the visual order and not a transposition of it. Below 1200
       the two stacks concatenate into exactly the same sequence.
     · `align-items:start` stops the two stacks being stretched to
       each other's height, which is the same fault one level up.
     · the closing hairline moves from the grid to each stack, so a
       column ends under its own last question instead of at a rule
       floating below the shorter of the two.
   Multiple questions stay open at once on purpose: a reader
   comparing shipping against returns needs both, and <details>
   without a name attribute is what allows it. */
@media (min-width:1200px){
  .qa--two{align-items:start;border-bottom:0;}
  .qa--two > .qa-col{min-width:0;border-bottom:var(--rule);}
  .qa--two > .qa-col > details{border-top:var(--rule);border-bottom:0;}
}

/* ═══════  PART X · THE LABEL LAYER, MADE READABLE  ═══════════════
   (2026-08-22, launch hardening)

   ONE JOB: ACCESS. The constitutional live-state audit measured a
   systemic `color-contrast` failure on every route at both widths —
   193 violating node instances across 12 route/viewport scans, in
   navigation, kickers, metadata, captions, prices, filter status and
   footer labels. Part VI repaired the BODY layer and left the LABEL
   layer where it was. The label layer is the part a visitor navigates
   and shops by — the shade cue under a catalogue card, the price note,
   the department index — so it is the part repaired here.

   The one systemic cause: `--bone-3` (#726d65) reads 3.90:1 on the ink
   and carries `.micro`, `.mono`, the whole bar, `.link-quiet` and most
   captions. Below it sat a second, unregistered ramp of hardcoded
   values — #6d6860 (3.62), #5f5b55 (2.97), #5b5751 (2.79), #4d4944
   (2.24), #4a4640 (2.14), #3f3c38 (1.82) — used for exactly the text a
   shopper needs to orient: prices, shade cues, form notes, filter
   status, route descriptions, ledger indices. Every one is re-struck
   below.

   The ramp keeps its ORDER and its WARMTH. It is the same warm grey
   family Part I drew, moved up the luminance scale until it can be
   read. Dimming still means what it meant; it no longer means invisible.

     --label-strong  #c3bcb0  10.62:1   navigation, control text
     --label         #a8a196   7.82:1   metadata, captions, kickers
     --label-quiet   #948d82   6.09:1   the quietest readable tier
     --bone-3        #948d82   6.09:1   token raised at the source,
                                        so any consumer this part
                                        does not name is still safe
     --line-strong   #606069   3.22:1   control boundaries (1.4.11)

   Nothing above 4.5:1 is required to change and nothing above it was
   changed: --bone (16.11), --bone-2 (9.28) and --gold (7.71) are
   Part I's own values, untouched.

   WHAT THIS PART DOES NOT DO. It adds no component, removes no
   component and moves no measured pixel of the composition. The store
   Parts II–IX draw — the catalogue, the cards, the prices, the box and
   the checkout — is untouched except in the one dimension that was
   failing: whether its labels can be read.

   Parts I–IX are byte-untouched:
   `sed -n '1,2082p' regarde.css | shasum -a 256`
   → 62675394f6f60c03cd84ae87438122dcaa61eaddad9230674938e4bc07c771b0
   ═════════════════════════════════════════════════════════════ */

/* ── A1. the label ramp, re-struck ──────────────────────────── */
:root{
  --label-strong:#c3bcb0;   /* 10.6:1 on --ink */
  --label:#a8a196;          /*  7.8:1 */
  --label-quiet:#948d82;    /*  6.1:1 */
  --line-strong:#606069;    /*  3.2:1 — non-text, WCAG 1.4.11 */
  --line-soft:#33333a;      /*  hairlines that only divide */

  /* the token itself, raised at the source: 3.90:1 → 6.09:1 */
  --bone-3:#948d82;
}

/* ── A2. the primitives ─────────────────────────────────────── */
.micro,.mono{color:var(--label);}
.link-quiet{color:var(--label);}
.link-quiet:hover{color:var(--bone);}

/* ── A3. navigation reads first ─────────────────────────────── */
.bar nav a{color:var(--label-strong);}
.bar nav a.keyline{color:var(--label-strong);}
.bar nav a[aria-current="page"]{color:var(--bone);}
.bar-index summary{color:var(--label-strong);}
.index-panel a{color:var(--label-strong);}
.foot-cols .micro,.foot-bar .mono{color:var(--label);}
.foot-nav a{color:var(--label-strong);}
.foot-line{color:var(--label);}

/* ── A4. every hardcoded sub-floor value, by selector ───────── */
.statement-lines .dim,
.ledger .why,
.cluster-note{color:var(--body-dim-3);}

.tally .fine,
.state-panel .fine,
.prose .fine,
.buy .fine,
.terms p{color:var(--body-dim-2);}

.spec dt,.spec .k,
.price-note,
.ed-quote cite,
.rail-note cite,
.tally .apart,
.head-plate .cap span,
.trait-wide .cap span,
.gallery .cap span,
.gal .cap span,
.fig-note .cap span,
.prod-plate .cap span,
.notify-plate .cap span,
.head-plate-side .cap span,
.rail-plate .cap span,
.state-panel .who,
.routes .d,
.terms .k,
.cat .cat-cat,
.cat .state,
.cat .cue,
.cat-head .mono,
.cat-head .mono .sub,
.chip .mono,
.filter-note,
.jump-panel a .mono,
.prov .fine,
.slot .who,
.ledger .idx,
.form-note,
.boite-checkout .btn[disabled]{color:var(--label-quiet);}

.field input::placeholder{color:var(--label-quiet);opacity:1;}
.foot-e{color:#6f6a62;}   /* 3.5:1 — a 7-letter decorative mark,
                             aria-label carries the meaning */

/* ── A5. control boundaries reach 3:1 ───────────────────────── */
.btn,
.skip,
.field,
.chip,
.cart-count,
.boite-q{border-color:var(--line-strong);}
.chip.is-on,
.buy .btn.is-buy{border-color:var(--label-quiet);}
.jump .mark{border-right-color:var(--line-strong);border-bottom-color:var(--line-strong);}
.qa .mark::before,.qa .mark::after{background:var(--line-strong);}

/* the dividing hairlines are lifted just enough to be seen as
   structure; they carry no information and no floor applies */
:root{--rule:1px solid var(--line-soft);}
.ledger,.tally .together{border-top-color:var(--line-soft);}
.ledger li,.slot,.index-panel,.state-panel{border-color:var(--line-soft);}

/* ── A6. the keyboard is louder than a hairline ─────────────── */
:focus-visible{outline:2px solid var(--gold);outline-offset:3px;}
.skip:focus,.skip:focus-visible{outline:2px solid var(--gold);outline-offset:3px;}

/* ── A7. touch targets ──────────────────────────────────────── */
.index-panel a,
.foot-cols a,
.routes a{min-height:44px;display:flex;align-items:center;}
.routes a{align-items:baseline;}

/* ── A8. the bar always has a ground to be read against ──────────
   Part I leaves the bar transparent until it settles, which is the
   right gesture and an unguaranteed one: at the top of a page the
   wordmark and every nav item sit directly on whatever the hero
   image happens to be. axe reports these nodes as INCOMPLETE — "background
   color could not be determined because element contains an image
   node" — which is not a pass, it is an unanswered question, and the
   answer depends on the photograph.

   The gesture is kept and the question is closed: an ink scrim under
   the bar, fading out below it. Against the near-black top of every
   current plate it is invisible; against a bright frame it is the
   difference between a legible bar and a decorative one. It is
   removed the moment `.settled` gives the bar its own ground, so
   nothing is drawn twice. */
.bar::before{
  content:"";position:absolute;inset:0 0 auto 0;height:200%;
  background:linear-gradient(180deg,
    rgba(8,8,10,.90) 0%,
    rgba(8,8,10,.58) 44%,
    rgba(8,8,10,0) 100%);
  pointer-events:none;z-index:-1;
  transition:opacity .6s var(--ease);
}
.bar.settled::before{opacity:0;}
@media (prefers-reduced-motion:reduce){
  .bar::before{transition:none;}
}

/* ── A9. the bar's own targets reach the thumb ───────────────────
   Measured in a real browser: the wordmark is 117×29 and a desktop
   nav item 65–145×28. Both clear WCAG 2.5.8's 24×24 minimum and
   neither is comfortable under a thumb. The boxes are NOT resized —
   Part I's `::after` underline is positioned against the bottom of
   the anchor box, and growing the box would strand the mark ~10px
   below its own word. An inert `::before` expands the HIT AREA to
   44px around the existing centre line instead, so the target grows
   and not one measured pixel of the composition moves. */
.bar .wordmark{position:relative;}
.bar .wordmark::before,
.bar nav a::before{
  content:"";position:absolute;left:0;right:0;top:50%;
  height:44px;transform:translateY(-50%);
}

/* ── A10. the row links reach the thumb ─────────────────────────
   Measured in a real browser at 390px: the serif name link inside a
   ledger row (`/routine`, "what it sits next to") and inside a box
   line is 20–23px tall — under WCAG 2.5.8's 24×24 minimum, and well
   under a thumb. These are NOT inline links in a sentence, so the
   inline exception does not apply to them.

   The boxes are NOT resized. Part I positions the underline rule
   against the bottom of the anchor box, and growing the box would
   strand that rule below its own word. As in A9, an inert `::before`
   expands the HIT AREA around the existing centre line instead, so
   the target grows and not one measured pixel of the composition
   moves.

   The two get different amounts because the rows differ. A ledger row
   is 122–144px tall with 23px of clear space above the name and 77px
   below, so 44px fits with room to spare. A box line packs the name,
   the quantity control and the amount into one grid, so it takes the
   24px that clears the criterion and nothing more. */
.ledger .name,
.boite-line .name{position:relative;}
.ledger .name::before,
.boite-line .name::before{
  content:"";position:absolute;left:0;right:0;top:50%;
  transform:translateY(-50%);
}
.ledger .name::before{height:44px;}
.boite-line .name::before{height:24px;}

/* ── A11. the inactive control is still a control ────────────────
   Measured on `/boite` with one of an object in the box: the "−" is
   disabled at quantity 1 and paints #2e2e33 on the ink — 1.48:1, which
   is not dim, it is gone. WCAG 1.4.3 exempts an inactive component from
   the contrast floor, so this is conformant and it is still wrong: on a
   purchase surface a reader has to be able to see that the control
   exists and is refusing, or the row reads as broken.

   The tier is deliberately BELOW the readable ramp. A disabled control
   that reaches --label-quiet (6.09:1) looks active, which trades one
   defect for a worse one. #55555c is 2.61:1 — perceptible as a mark,
   unmistakably recessed against the live "+" beside it at 6.09:1. */
:root{--label-off:#55555c;}
.boite-q[disabled]{color:var(--label-off);border-color:#2b2b31;}
