/* ═════════════════════════════════════════════════════════════════════════════
   v22.css — the Meet Iris site's shared below-the-fold sheet.
   Home (/) · Suppliers (/suppliers) · Together (/together).

   ⚠ LOADED NON-BLOCKING. The critical slice — header, drawer closed geometry and
   hero — is inlined in each page's <head>, exactly as home.html does it. This
   file must therefore never carry anything the first paint needs.

   ⚠⚠ THE ARTEFACTS SET ~700 INLINE HEX VALUES AND DECLARE NO CUSTOM PROPERTIES
   (A14 measured that and it is correct). This sheet does NOT copy that. The
   house convention is `:root` custom properties — home.html, landing.html and
   the warroom all do it — and it is the only thing that makes the token table
   auditable by a gate rather than by eye. Every value below is the artefact's
   own, carried across unchanged; only the mechanism differs.

   ALL USER-FACING COPY IS DRAFT (Rule 5). See each page's [DRAFT] manifest.
   ═════════════════════════════════════════════════════════════════════════════ */

/* ─────────────────────────────────────────────────────────────────────────────
   1 · TOKENS — AND THIS FILE IS *NOT* THEIR HOME. READ THIS BEFORE EDITING.

   ⚠⚠ THERE IS DELIBERATELY NO `:root` BLOCK IN THIS FILE. Do not add one.
   The live declaration is inlined in each of the three pages' critical <style>,
   because tokens must exist BEFORE first paint and this sheet is deliberately
   non-blocking (BRIEF_home §3: "No render-blocking CSS or JS"). A `:root` here
   would arrive after the header and hero had already painted, so the masthead
   would flash unstyled.

   That means three identical copies live in home.html, for-suppliers.html and
   together.html. Three copies of one table is the rot class this record names,
   so it is GUARDED rather than trusted: `v22TokenParity.test.mjs` (repo root)
   asserts the three inline blocks are byte-identical to each other and that
   every `var(--…)` used in this file is defined in them. If you add a token,
   add it to all three pages and the guard will tell you if you missed one.

   Values are the run brief §5 table, verified present in all three artefacts.
   ───────────────────────────────────────────────────────────────────────────── */

/* ─────────────────────────────────────────────────────────────────────────────
   2 · SECTION SHELL
   ───────────────────────────────────────────────────────────────────────────── */
.sec{padding:clamp(46px,7vh,86px) max(clamp(24px,5vw,64px),var(--safe-l)) clamp(46px,7vh,86px) max(clamp(24px,5vw,64px),var(--safe-r));border-top:1px solid var(--hair-gold)}
.sec--band{background:var(--band);border-top:0}
.sec--paper{background:var(--paper);border-top:1px solid rgba(31,58,48,.12)}
.sec--flush{border-top:0}
.wrap{max-width:1180px;margin:0 auto}
.stack{display:flex;flex-direction:column}
.lede{display:flex;flex-direction:column;gap:10px;max-width:56ch}

.eyebrow{font-size:10px;font-weight:500;letter-spacing:.3em;text-transform:uppercase;color:var(--on-green-gold)}
.sec--band .eyebrow,.sec--paper .eyebrow{color:var(--gold-text)}
.kicker{font-size:9.5px;font-weight:500;letter-spacing:.34em;text-transform:uppercase;color:var(--on-green-gold)}

h2.h{font-family:var(--play);font-weight:400;font-size:clamp(25px,3.2vw,40px);line-height:1.16;color:var(--paper)}
h3.h{font-family:var(--play);font-weight:400;font-size:clamp(22px,2.8vw,33px);line-height:1.18;color:var(--paper)}
.sec--band h2.h,.sec--band h3.h,.sec--paper h2.h,.sec--paper h3.h{color:var(--ink-head)}
/* ⚠⚠ THE EMPHASIS GOLD FLIPS BY SURFACE, VIA A TOKEN — NOT BY SECTION SELECTOR.
   It used to be `.sec--band .h em, .sec--paper .h em`, which cannot reach an
   ivory panel nested inside a DARK section: several splits on Home carry
   `background:var(--band)` inline while their section is night green, so the
   gold `<em>` in "Iris knows your wedding" rendered #E7CF92 on ivory — measured
   1.33:1 against a 3.0 floor for 31px display type. Inheriting through a custom
   property fixes every nesting, present and future; `.on-light` is the hook for
   a light panel inside a dark section. */
.h em{font-style:italic;color:var(--h-em)}
.sec--band,.sec--paper,.on-light{--h-em:var(--gold-text)}
/* ⚠ and the rest of the light-surface treatment travels with it, so a panel does
   not have to repeat six inline colours to sit on ivory inside a dark section. */
.on-light .eyebrow,.on-light .kicker{color:var(--gold-text)}
.on-light h2.h,.on-light h3.h{color:var(--ink-head)}
.on-light p.body{color:var(--ink)}
.on-light .player__step{color:var(--gold-text)}
.on-light .player__title{color:var(--ink-head)}
.on-light .player__note{color:var(--ink)}
.on-light .player__cost{color:var(--amber)}

p.body{font-size:clamp(14.5px,1.8vh,17px);line-height:1.65;color:rgba(243,239,228,.82)}
.sec--band p.body,.sec--paper p.body{color:var(--ink)}
/* ⚠⚠ CLASS-ONLY TWINS, BECAUSE `p.body` IS ELEMENT-QUALIFIED AND A CAPTION IS NOT
   A `<p>`. Found by the walk's contrast sweep at W4: two `<figcaption class="body">`
   on together's two-desks band measured IVORY ON IVORY, ratio 1.00 — text that is
   present, correctly spelled, in the DOM, and completely invisible. No structural
   guard in this repo could see it: the class is right, the element exists, the
   page parses. `dom-presence-is-not-dress`, at its worst reading.
   ⚠ THE TWINS DO NOT OVERRIDE ANYTHING. `p.body` is 0,1,1 and `.body` is 0,1,0,
   so every existing `<p class="body">` keeps resolving through the qualified rule
   to the identical value; these only reach the elements the qualified rules never
   could. The typography rule above is deliberately left alone.
   ⚠ AND THE REASON THIS IS A RULE RATHER THAN A MARKUP FIX: changing the two
   captions to `<p>` would have fixed the instance and left the next non-`<p>`
   `.body` just as invisible. */
.body{color:rgba(243,239,228,.82)}
.sec--band .body,.sec--paper .body{color:var(--ink)}
p.body--sm{font-size:clamp(14px,1.75vh,16px);line-height:1.6}

/* ─────────────────────────────────────────────────────────────────────────────
   3 · REVEALS. ~30 elements sit at opacity:0 and are revealed by the observer
   in v22.js. ⚠ IF THE OBSERVER DOES NOT SHIP, THESE ARE INVISIBLE FOR EVER —
   whole section headings among them (A1). `.no-js` is the belt: with scripting
   off the rule never applies and everything is simply visible.
   ───────────────────────────────────────────────────────────────────────────── */
[data-rv]{opacity:0;transform:translateY(22px);transition:opacity .4s var(--ease),transform .4s var(--ease)}
/* ⚠⚠ 0.9s → 0.4s, 1 SEP 2026, THE WEBSITE STORY, W1. HIS WALK MEASURED THE COST:
   "arrive at a section fast and it reads EMPTY for a second" — the whole ivory
   band and the inner-circle band drew blank at 1440. Re-measured before the
   change in a real browser on all FIVE consuming pages: computed
   `transition-duration: 0.9s, 0.9s`, and computed opacity 500ms after arriving
   at a block by anchor was 0. The property this now has to hold is legibility
   within 500ms, and it is asserted rather than eyeballed.
   ⚠ THE VALUE IS SPELLED `.4s`, NOT `0.4s`, because the old one was `.9s` and
   `VS_BRIEF_the_website_story.md` §2 W0 asks for "its 0.9s" — a needle on the
   literal `0.9s` matched NOTHING in this file. A guard anchored on a spelling
   is this record's own class of rot; W5's row anchors on the computed property.
   ⚠⚠ AND IT REACHES TWO PAGES THIS ARC MAY NOT EDIT. `for.html` (3 [data-rv])
   and `for-wedding-photographers.html` (15) both load this sheet — W0 §5. The
   change is right for them too and they are WALKED, never edited. */

/* ⚠⚠ PICTURES FADE ONLY — NO translateY ON A BLOCK THAT CARRIES AN IMAGE.
   A 22px lift on a photograph reads as the picture arriving late rather than as
   the section arriving; on the calendar rows it also fought the frame's own
   `order:-1` at 390. Copy still lifts; pictures do not.
   ⚠ `:has()` rather than a marker class ON PURPOSE. A marker would need adding
   at every picture site on three pages AND would silently miss the two trade
   pages, which is the "hand-kept coverage list" this record already names. This
   is derived from what the element CONTAINS, so it cannot go stale.
   ⚠ The sheet already relies on `:has()` (`.player__win:has(>.realshot)`), so
   this adds no new support floor. */
[data-rv]:has(img),[data-rv]:has(picture),[data-rv].frame,[data-rv].phone{transform:none}
[data-rv].in{opacity:1;transform:none}
/* ⚠ THE NO-JS BELT, AND IT IS NOT OPTIONAL. `<html class="no-js">` is removed
   synchronously by an inline script in each page's <head> — home.html's own
   convention, line 311. With scripting off the class stays and every revealed
   element is simply visible. Without this, ~30 elements including whole section
   headings are invisible for ever to a reader with JS disabled. */
html.no-js [data-rv]{opacity:1;transform:none}

@keyframes fadeUp{from{opacity:0;transform:translateY(16px)}to{opacity:1;transform:none}}
@keyframes floaty{0%,100%{transform:translateY(0)}50%{transform:translateY(-7px)}}
@keyframes kenburns{0%{transform:scale(1.04)}100%{transform:scale(1.13) translate3d(-1.5%,-1.4%,0)}}
/* ⚠ @keyframes sealLight is NOT here. It is declared in Home's artefact and used
   by nothing (A13, narrowed: Home only). Dead CSS is not carried across. */

/* ─────────────────────────────────────────────────────────────────────────────
   4 · THE STORY PLAYER. Ten instances, three timers. See v22.js §3.
   ───────────────────────────────────────────────────────────────────────────── */
/* ⚠⚠ EVERY FRAME IS ONE ELEMENT STACKED IN GRID CELL 1/1, NOT A LOOSE cap+win
   PAIR SHARING NAMED AREAS. The artefact does the latter, which means a frame
   is TWO sibling elements and can therefore never carry `role="tabpanel"` —
   one tab cannot control two panels, and `display:contents` on a panel is still
   dropped from the a11y tree by some AT. One element per frame fixes that.
   Two things fall out of it for free:
     · the row height is the tallest frame, so nothing jumps on advance — and the
       artefact's hand-tuned `min-height:clamp(300px,42vh,400px)` magic numbers
       stop being load-bearing;
     · the ≤900px collapse is one line on .frame instead of a grid-area rewrite. */
.player{display:grid;grid-template-columns:minmax(0,1fr)}
.frame{grid-area:1/1;display:grid;grid-template-columns:minmax(0,.78fr) minmax(0,1.22fr);gap:clamp(20px,3.4vw,46px);align-items:center;opacity:0;transform:translateY(14px);z-index:1;transition:opacity .6s var(--ease),transform .6s var(--ease);pointer-events:none}
.frame[data-on]{opacity:1;transform:none;z-index:2;pointer-events:auto}
.player--72 .frame{grid-template-columns:minmax(0,.72fr) minmax(0,1.28fr)}
.player--74 .frame{grid-template-columns:minmax(0,.74fr) minmax(0,1.26fr)}
.player--70 .frame{grid-template-columns:minmax(0,.7fr) minmax(0,1.3fr)}
.player__cap{display:flex;flex-direction:column;gap:10px}
.player__win{min-width:0}

.player__step{font-size:10px;font-weight:500;letter-spacing:.26em;text-transform:uppercase;color:var(--on-green-gold)}
.sec--band .player__step,.sec--paper .player__step{color:var(--gold-text)}
.player__title{font-family:var(--play);font-size:clamp(19px,2.4vw,28px);line-height:1.2;color:var(--paper)}
.sec--band .player__title,.sec--paper .player__title{color:var(--ink-head)}
.player__note{font-size:clamp(14px,1.75vh,16.5px);line-height:1.6;color:rgba(243,239,228,.82)}
.sec--band .player__note,.sec--paper .player__note{color:var(--ink)}
.player__cost{font-size:13px;color:var(--amber-on-green)}
.sec--band .player__cost,.sec--paper .player__cost{color:var(--amber)}

/* the dot rail — a real tablist */
.dots{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:clamp(10px,1.6vh,16px)}
/* ⚠⚠ THE HIT AREA IS A DELIBERATE DEVIATION FROM THE ARTEFACT, NOT A COPY OF IT.
   The artefact's dots are `height:3px; padding:0` — a 3px tall tap target. Gate 8
   requires ≥44px. §5 says give them a ≥44px TRANSPARENT hit area with padding and
   do NOT enlarge the visible bar, so the button is 44px tall and fully
   transparent, and the 3px rule is painted by ::before. */
.dot{position:relative;height:44px;min-width:44px;display:inline-flex;align-items:center;justify-content:flex-start;background:transparent;border:0;padding:0 4px;margin:0;cursor:pointer;-webkit-tap-highlight-color:transparent;touch-action:manipulation}
.dot::before{content:'';display:block;height:3px;width:9px;background:rgba(231,207,146,.28);transition:width .5s var(--ease),background .5s var(--ease)}
.dot[aria-selected="true"]::before{width:26px;background:var(--gold-2)}
.sec--band .dot::before,.sec--paper .dot::before{background:rgba(31,58,48,.2)}
.sec--band .dot[aria-selected="true"]::before,.sec--paper .dot[aria-selected="true"]::before{background:var(--gold-text)}
.dots__tail{margin-left:auto;font-size:11px;letter-spacing:.18em;text-transform:uppercase;color:var(--gold-2);display:inline-flex;align-items:center;min-height:44px}
.sec--band .dots__tail,.sec--paper .dots__tail{color:var(--gold-text)}

/* ⚠ ≤900px THE PLAYER STACKS AND min-height GOES TO 0. Without the reset the
   desktop min-height reserves a screen's worth of empty space above the fold on
   a phone. §5's collapse table, and it is right. */
/* ⚠ ≤900px THE FRAME STACKS TO ONE COLUMN, CAPTION ABOVE ITS SCREEN. §5's
   collapse table. And the caption leads, deliberately: §5's "the animated
   screens are decorative on mobile — they must not be the first thing in the
   viewport". Document order already puts the cap first, so one line does it. */
@media (max-width:900px){
  .player,.player--72 .frame,.player--74 .frame,.player--70 .frame,.frame{min-height:0}
  /* ⚠⚠ THE THREE VARIANT SELECTORS ARE NAMED HERE AND THEIR ABSENCE WAS A LIVE
     DEFECT ON SIX PLAYERS. This rule is specificity 0,1,0; `.player--72 .frame`
     and its two siblings above are 0,2,0 and BEAT it, so a variant player never
     collapsed on a phone — it kept the desktop caption|window split. Measured at
     390 before this line: `fs` held two columns of 114.688px + 203.922px, a 114px
     caption column, so "She reads the payment schedule." wrapped to three or four
     words a line. It affects Home's money and appointments, Suppliers' three
     players and Together's two — SIX players, and every one of them on the width
     that matters most.
     ⚠ It was found and reported during the suppliers-carousel arc and left alone
     as out of scope ("this section only"). It is IN scope now: those players are
     the content of the feature carousel, and at 390 two of the five features were
     unreadable. Both sibling pages are re-walked and screenshotted before/after
     (Rule 38) — the change makes them collapse properly, which is what every
     other player on the site already did. */
  .frame,.player--72 .frame,.player--74 .frame,.player--70 .frame{grid-template-columns:minmax(0,1fr);gap:clamp(16px,2.6vh,24px)}
}

/* ⚠⚠ THE NO-JS FALLBACK, AND IT IS THE SAME TRAP AS THE REVEALS. Every frame
   sits at opacity:0 and is lit by [data-on], which only JS sets. With scripting
   off that is TEN PLAYERS OF INVISIBLE CONTENT — the whole product story on all
   three pages. `grid-area:auto` is the load-bearing line: without it every frame
   stays in cell 1/1 and they pile on top of each other. The dot rail goes
   because it drives nothing. */
html.no-js .frame{grid-area:auto;opacity:1;transform:none;z-index:auto;pointer-events:auto}
html.no-js .player{gap:clamp(20px,3.4vh,34px)}
html.no-js .dots{display:none}

/* ─────────────────────────────────────────────────────────────────────────────
   5 · THE DRAWN WINDOW AND PHONE FRAMES
   ───────────────────────────────────────────────────────────────────────────── */
.win{background:var(--paper);border:1px solid var(--hair-ink-2);box-shadow:0 30px 60px -32px rgba(0,0,0,.6);display:flex;flex-direction:column;overflow:hidden}
.win__bar{display:flex;align-items:center;gap:7px;padding:10px 12px;background:var(--chrome);border-bottom:1px solid rgba(31,58,48,.14)}
.win__bar i{width:9px;height:9px;border-radius:50%;background:rgba(31,58,48,.18);flex:none}
.win__bar i:first-child{background:var(--rule)}
/* ⚠ 10px IS THE FLOOR FOR THE CHROME CAPTION AND 12px FOR PANEL CONTENT (§5).
   Nothing in a window frame goes below 12px on mobile; this caption is the one
   exception and it stays at 10px by name. */
.win__cap{margin-left:7px;font-size:10px;letter-spacing:.16em;text-transform:uppercase;color:var(--ink-mute)}
.win__flag{margin-left:auto;font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--pos)}
.win__body{padding:clamp(14px,2vw,22px);display:flex;flex-direction:column;gap:10px}

/* a drawn row with a dotted leader */
.row{display:flex;justify-content:space-between;gap:10px;padding:9px 0;border-bottom:var(--dotted)}
.row:last-child{border-bottom:0}
.row__k{font-size:13.5px;color:var(--ink)}
.row__v{font-size:13px;color:var(--ink-quiet)}
.row__v--ink{color:var(--ink-head)}
.row__v--pos{color:var(--pos)}
.row__v--amber{color:var(--amber)}

/* ⚠ ANYTHING IRIS AUTHORED CARRIES A 3px #C9A96A LEFT EDGE. One mark, every
   size — §5's first non-negotiable. And she speaks in Cormorant italic and is
   NEVER normalised to the body font. Both rules live in this one class so a
   gate can count its uses. */
.iris{border-left:3px solid var(--rule);background:var(--band);padding:11px 13px;display:flex;flex-direction:column;gap:9px}
.iris__say{font-family:var(--corm);font-style:italic;font-size:15px;line-height:1.5;color:var(--pos)}
.iris--dark{background:rgba(254,252,247,.05)}
.iris--dark .iris__say{color:var(--gold-2)}

.phone{border:1px solid rgba(231,207,146,.42);border-radius:22px;background:var(--phone);padding:8px 8px 12px;box-shadow:0 26px 52px -24px rgba(0,0,0,.65)}
.phone__notch{display:flex;justify-content:center;padding:1px 0 7px}
.phone__notch span{width:34px;height:3px;border-radius:3px;background:rgba(243,239,228,.2)}
.phone__screen{position:relative;width:100%;aspect-ratio:9/19;background:var(--panel);border:1px solid rgba(231,207,146,.18);overflow:hidden}

/* the desk + phone showcase */
.showcase{position:relative;display:flex;justify-content:center;align-items:flex-end;padding-bottom:clamp(0px,3vw,34px)}
.showcase__desk{width:100%;max-width:640px;background:var(--paper);border:1px solid rgba(31,58,48,.2);box-shadow:0 34px 70px -34px rgba(0,0,0,.5);overflow:hidden}
.showcase__screen{position:relative;width:100%;aspect-ratio:16/10;background:var(--panel)}
.showcase__phone{position:absolute;right:-6px;bottom:0;width:clamp(120px,17%,168px)}
/* ≤700px the phone leaves its overlap and centres under the desk at 150px */
@media (max-width:700px){
  .showcase{flex-direction:column;align-items:center}
  .showcase__phone{position:relative;right:auto;bottom:auto;width:150px;margin:-40px auto 0}
}

/* ─────────────────────────────────────────────────────────────────────────────
   6 · GRIDS. ⚠ NO `repeat(auto-fit, …)` ON ANY 3-, 4- OR 5-CARD ROW, AND NO
   BARE `1fr` HOLDING TEXT. Traps 5 and 6, and the artefacts break both — Home's
   journey row is auto-fit at 230px, Suppliers' triad at 240px, and `[data-triad]`
   is a bare repeat(3,1fr) on two pages. The brief's rule wins over the artefact's
   value here and it is said out loud (A13).
   ───────────────────────────────────────────────────────────────────────────── */
.split{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:clamp(24px,4vw,54px);align-items:center}
.split--start{align-items:start}
.split--78{grid-template-columns:minmax(0,.78fr) minmax(0,1.22fr);gap:clamp(26px,4vw,52px)}
.split--tight{gap:clamp(20px,3.4vw,42px);align-items:stretch}
@media (max-width:900px){.split,.split--78,.split--tight{grid-template-columns:minmax(0,1fr)}}

.triad{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:clamp(16px,2.6vw,26px)}
@media (max-width:1000px){.triad{grid-template-columns:minmax(0,1fr)}}

.trio{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:clamp(18px,3vw,34px)}
@media (max-width:1000px){.trio{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:700px){.trio{grid-template-columns:minmax(0,1fr)}}

/* the five-up icon rail → 3 up ≤1000px, 2 up ≤560px */
.chips{display:grid;grid-template-columns:repeat(5,minmax(0,1fr));gap:1px;background:rgba(231,207,146,.22);border:1px solid rgba(231,207,146,.26)}
@media (max-width:1000px){.chips{grid-template-columns:repeat(3,minmax(0,1fr))}}
@media (max-width:560px){.chips{grid-template-columns:repeat(2,minmax(0,1fr))}}
.chip{background:var(--panel);padding:16px 8px;display:flex;flex-direction:column;align-items:center;gap:7px;text-align:center}
.chip span{font-size:9.5px;letter-spacing:.14em;text-transform:uppercase;color:var(--on-green-ivory)}

/* the six-tile file grid — Home §4, bare repeat(3,1fr) in the artefact */
.tiles{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:clamp(8px,1.4vw,14px)}
@media (max-width:700px){.tiles{grid-template-columns:repeat(2,minmax(0,1fr))}}

/* the dream-board wall — 4 up, 3 up ≤900, 2 up ≤560 */
.wall{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px}
@media (max-width:900px){.wall{grid-template-columns:repeat(3,minmax(0,1fr))}}
@media (max-width:560px){.wall{grid-template-columns:repeat(2,minmax(0,1fr))}}
.wall__tile{position:relative;aspect-ratio:3/4;background:var(--night);border:1px solid var(--hair-ink);overflow:hidden}
.wall__tile img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.wall__add{aspect-ratio:3/4;border:1px dashed rgba(169,136,78,.5);display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;text-align:center;padding:8px}

/* pill/tag rows */
.tags{display:flex;flex-wrap:wrap;gap:8px}
.tag{font-size:12.5px;color:rgba(243,239,228,.86);border:1px solid rgba(231,207,146,.3);padding:8px 12px}
.tag--solid{color:var(--night);background:var(--gold-2);border-color:var(--gold-2)}

/* ─────────────────────────────────────────────────────────────────────────────
   7 · BUTTONS AND LINKS. ⚠ EVERY INTERACTIVE TARGET ≥44px ON A 390px VIEWPORT
   (gate 8) — asserted by the harness, not eyeballed.
   ⚠⚠ AND THE GLOBAL a:hover CONFLICT IS RESOLVED HERE. The artefacts declare
   `a:hover{color:#FEFCF7}` globally AND a gold `#F0DCA6` on 21 of them via the
   inert `style-hover` attribute. The two disagree. The declared style-hover
   values win on the elements that carried them; the global stays for body links.
   ───────────────────────────────────────────────────────────────────────────── */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:.7em;min-height:44px;padding:15px 24px;font-size:10.5px;font-weight:500;letter-spacing:.2em;text-transform:uppercase;white-space:nowrap;border-radius:0;cursor:pointer;transition:background .28s var(--ease),border-color .28s var(--ease),color .28s var(--ease)}
.btn--sm{padding:14px 17px;font-size:10px;letter-spacing:.14em}
.btn--gold{background:var(--brand);border:1px solid var(--rule);color:var(--gold)}
.btn--gold:hover{background:var(--brand-press);color:var(--gold)}
.btn--ghost{border:1px solid rgba(231,207,146,.5);color:var(--gold-2);background:transparent}
.btn--ghost:hover{border-color:var(--gold-2);background:rgba(231,207,146,.07);color:var(--gold)}
/* ⚠⚠ A GHOST BUTTON ON AN IVORY BAND IS GOLD ON CREAM, AND THAT IS 1.33:1.
   MEASURED, NOT SUSPECTED: `feat-the-website-story` W3 put one on the trades
   band and the walk's contrast sweep read rgb(231,207,146) on rgb(243,239,228)
   at 1.33 against a 4.5 floor for 10px text — the same failure v22TokenParity §5
   already forbids at the TOKEN level (#C9A96A measures 2.19:1) but which nothing
   stopped at the COMPONENT level.
   ⚠ THIS FIXES THE CLASS, NOT THE INSTANCE. Swapping that one button for
   `.btn--ink` would have left the next ghost button on ivory just as unreadable,
   and there was no rule to red-fire on it. The cascade already does this for
   headings, body copy and eyebrows via `.sec--band`/`.on-light`; the button
   family was simply missing from that list. */
.sec--band .btn--ghost,.sec--paper .btn--ghost,.on-light .btn--ghost{border-color:var(--hair-ink);color:var(--ink-head)}
.sec--band .btn--ghost:hover,.sec--paper .btn--ghost:hover,.on-light .btn--ghost:hover{border-color:var(--ink-head);background:rgba(31,58,48,.05);color:var(--ink-head)}
.btn--solid{color:var(--night);background:var(--gold-2);border:1px solid var(--gold-2)}
.btn--solid:hover{background:var(--gold)}
.btn__arrow{font-family:var(--corm);font-style:italic;font-size:1.3em;line-height:1}

/* the drawn in-panel affordances. These are PICTURES OF BUTTONS, not buttons —
   they are <span>, they take no focus and they fire nothing. Kept as spans on
   purpose: a real <button> here would be a keyboard stop that does nothing. */
.pill{display:inline-flex;align-items:center;font-size:10px;font-weight:500;letter-spacing:.18em;text-transform:uppercase;padding:10px 15px}
.pill--go{color:var(--band);background:var(--brand)}
.pill--alt{color:var(--ink-panel);border:1px solid rgba(31,58,48,.28)}

/* ─────────────────────────────────────────────────────────────────────────────
   8 · THE EMAIL CAPTURE. See v22.js §5 and the log's F1 — the drawn form is one
   email field, and both live endpoints require a second field, so the second is
   revealed on submit rather than shown at rest.
   ───────────────────────────────────────────────────────────────────────────── */
.cap{display:flex;flex-direction:column;align-items:center;gap:12px;width:100%}
.cap__form{display:flex;flex-wrap:wrap;justify-content:center;gap:10px;width:100%;max-width:470px}
.cap__field{flex:1 1 220px;min-width:min(100%,210px);min-height:44px;border:1px solid rgba(231,207,146,.34);background:var(--panel);padding:15px 18px;font-size:14px;color:var(--band)}
.cap__field::placeholder{color:rgba(243,239,228,.55)}
.cap__second{flex:1 1 100%;display:none}
.cap__form[data-stage="2"] .cap__second{display:flex}
.cap__msg{font-size:13px;line-height:1.5;color:var(--gold-2);min-height:1.5em;text-align:center;flex:1 1 100%}
.cap__msg[data-bad]{color:var(--amber-on-green)}
.cap__label{font-size:9.5px;font-weight:500;letter-spacing:.24em;text-transform:uppercase;color:var(--on-green-gold);flex:1 1 100%;text-align:left}

/* ─────────────────────────────────────────────────────────────────────────────
   9 · FOOTER
   ───────────────────────────────────────────────────────────────────────────── */
.foot{border-top:1px solid rgba(231,207,146,.2);padding:clamp(22px,3.6vh,34px) max(clamp(24px,5vw,64px),var(--safe-l)) calc(clamp(22px,3.6vh,34px) + var(--safe-b)) max(clamp(24px,5vw,64px),var(--safe-r))}
.foot__in{max-width:1180px;margin:0 auto;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:18px}
.foot__nav{display:flex;flex-wrap:wrap;gap:clamp(14px,3vw,30px)}
/* ⚠ min-width AS WELL AS min-height — the browser gate measured Together's
   "Plans" at 41×44 on a 390px viewport. Gate 8 is an assertion, not an eyeball. */
.foot__nav a{font-size:10px;letter-spacing:.2em;text-transform:uppercase;color:rgba(231,207,146,.72);display:inline-flex;align-items:center;justify-content:center;min-height:44px;min-width:44px}
.foot__nav a:hover{color:var(--gold)}
.foot__mark{display:flex;align-items:center;gap:14px}
.foot__mark svg{height:22px;width:auto;display:block}

/* ─────────────────────────────────────────────────────────────────────────────
   10 · REDUCED MOTION. Kills every animation and transition, idles all ten
   players, and renders all revealed content visible. ⚠ v22.js ALSO ADDS A
   `change` LISTENER — the artefacts read the query once at mount and never
   again (A7), so a viewer who flips the OS setting mid-visit kept the timers.
   ───────────────────────────────────────────────────────────────────────────── */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation:none !important;transition:none !important}
  html{scroll-behavior:auto}
  [data-rv]{opacity:1;transform:none}
  /* ⚠⚠ UNDER REDUCED MOTION EVERY FRAME IS SHOWN, UNSTACKED, IN DOCUMENT ORDER.
     Gate 7 requires "all revealed content visible", and the cross-fade is
     exactly the animation being suppressed — so the ten players become plain
     stacked prose rather than one frame with nine hidden behind it.
     `grid-area:auto` is again load-bearing: without it all four frames stay in
     cell 1/1 and overlap. The dot rail goes, because with no timer and every
     frame already on screen it drives nothing and would be thirty-seven dead
     keyboard stops across the site. */
  .player{gap:clamp(18px,3vh,28px)}
  .frame{grid-area:auto;opacity:1;transform:none;z-index:auto;pointer-events:auto}
  .dots{display:none}
}

/* ─────────────────────────────────────────────────────────────────────────────
   11 · THE GHOST APP SCREENS.

   ⚠⚠ THESE ARE THE SIX EMPTY `<image-slot>`s, AND THEY ARE THE ONE PIECE OF
   GENUINELY NEW WORK (§3). They are DRAWN HTML, not screenshots — §3's method 2,
   taken because method 1 is not available to this arc: the app is a Vite SPA
   behind a Firebase auth bootstrap and an allowlist gate, and the e2e rig's own
   law is "no real data, ever". Drawn stays sharp at every density and costs no
   bytes. **The slot ids are kept on what replaces them**, so a future swap to a
   real capture is one line. (§3 calls the attribute `data-slot`; it does not
   exist anywhere in any artefact — they are `id=`, and the ids are what is kept.)

   ⚠ GHOST DATA IS FICTIONAL ONLY. No real client, supplier, staff or venue name,
   no real email, phone number, address or financial data. No watermark: they
   should read as the real product. §3's rules, followed.

   ⚠ NOTHING HERE GOES BELOW 12px ON MOBILE except the window chrome caption,
   which §5 pins at 10px by name. The type scales with cqw so a 390px viewport
   still reads — `container-type:inline-size` on the screen, which is how the
   outgoing home.html does its phone and desk mockups too.
   ───────────────────────────────────────────────────────────────────────────── */
.ghost{position:absolute;inset:0;container-type:inline-size;background:var(--panel);color:var(--band);overflow:hidden;font-size:clamp(6px,2.1cqw,13px)}

/* the desk: a rail and a working area */
.ghost--desk{display:grid;grid-template-columns:26% 1fr}
.ghost__rail{background:var(--night);border-right:1px solid var(--hair-gold-2);padding:6% 5%;display:flex;flex-direction:column;gap:5%}
.ghost__brand{display:flex;align-items:center;gap:.5em;font-family:var(--play);font-size:1.35em;color:var(--gold)}
.ghost__rail nav{display:flex;flex-direction:column;gap:.55em}
.ghost__rail nav b{font-weight:400;font-size:1em;color:var(--on-green-ivory);padding:.42em .5em;border-left:2px solid transparent}
.ghost__rail nav b[data-on]{color:var(--gold);border-left-color:var(--rule);background:rgba(240,220,166,.07)}
.ghost__main{padding:5.5% 5%;display:flex;flex-direction:column;gap:4.5%;min-width:0}
.ghost__top{display:flex;align-items:baseline;justify-content:space-between;gap:1em}
.ghost__h{font-family:var(--play);font-size:1.7em;color:var(--paper)}
.ghost__count{font-family:var(--play);font-size:1.5em;color:var(--gold-2)}
.ghost__lbl{font-size:.85em;letter-spacing:.18em;text-transform:uppercase;color:var(--on-green-gold)}
.ghost__grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:.6em}
.ghost__card{border:1px solid var(--hair-gold-2);padding:.75em .7em;display:flex;flex-direction:column;gap:.3em;min-width:0}
.ghost__card b{font-family:var(--play);font-weight:400;font-size:1.5em;color:var(--paper)}
.ghost__card span{font-size:.85em;letter-spacing:.14em;text-transform:uppercase;color:var(--on-green-ivory)}
.ghost__list{display:flex;flex-direction:column}
.ghost__row{display:flex;justify-content:space-between;gap:.8em;padding:.55em 0;border-bottom:1px solid rgba(231,207,146,.14);min-width:0}
.ghost__row span:first-child{color:var(--band);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ghost__row span:last-child{color:var(--on-green-ivory);white-space:nowrap;flex:none}
.ghost__row span[data-pos]{color:var(--pos-on-green)}
.ghost__row span[data-amber]{color:var(--amber-on-green)}
.ghost__iris{border-left:2px solid var(--rule);background:rgba(254,252,247,.06);padding:.6em .7em;font-family:var(--corm);font-style:italic;font-size:1.25em;line-height:1.35;color:var(--gold-2)}

/* the phone: a header, a body and her seal in the nav */
.ghost--phone{display:flex;flex-direction:column;font-size:clamp(5px,4.4cqw,11px)}
.ghost__ph-top{padding:9% 8% 5%;display:flex;flex-direction:column;gap:.35em;border-bottom:1px solid var(--hair-gold-2)}
.ghost__ph-top b{font-family:var(--play);font-weight:400;font-size:1.6em;color:var(--paper)}
.ghost__ph-top span{font-size:.95em;letter-spacing:.14em;text-transform:uppercase;color:var(--on-green-gold)}
.ghost__ph-body{flex:1;padding:7% 8%;display:flex;flex-direction:column;gap:.65em;min-height:0;overflow:hidden}
.ghost__ph-cta{border:1px solid var(--rule);background:var(--brand);color:var(--gold);text-align:center;padding:.7em .5em;font-size:.95em;letter-spacing:.14em;text-transform:uppercase}
.ghost__ph-nav{display:flex;align-items:center;justify-content:space-around;padding:4% 6% calc(6% + var(--safe-b));border-top:1px solid var(--hair-gold-2);background:var(--night)}
.ghost__ph-nav i{width:1.5em;height:1.5em;border-radius:50%;border:1px solid rgba(240,220,166,.34);display:block;flex:none}
/* ⚠ HER SEAL IS THE MIDDLE BUTTON IN THE PHONE NAV — the product grammar the
   story brief §1 records from the v12 app mocks, carried rather than invented. */
.ghost__ph-nav i[data-seal]{width:2.1em;height:2.1em;border-color:var(--rule);background:radial-gradient(circle at 40% 35%,var(--gold) 0,var(--rule) 55%,#8A6D2F 100%)}

/* ─────────────────────────────────────────────────────────────────────────────
   12 · THE MAIL CARD AND THE ATTACHMENT CHIP.

   ⚠⚠ THESE LIVE HERE, NOT IN home.css, AND THE BROWSER GATE IS WHY. They were
   written into home.css while Home was being built, and Suppliers uses them too —
   but Suppliers loads v22.css + suppliers.css and never home.css. So on
   /suppliers every one of these elements fell back to the BODY colour (--band,
   an ivory) on a white drawn panel: measured 1.12:1 against a 4.5 floor, i.e.
   effectively invisible. Nothing in the source looked wrong; only rendering the
   page and measuring the composited colour found it.
   ⚠ If a component is used by more than one page, it belongs in this file.
   ───────────────────────────────────────────────────────────────────────────── */
/* ── the mail card ───────────────────────────────────────────────────────────── */
.mail{display:flex;gap:10px;font-size:13.5px;color:var(--paper)}
.mail dt{color:var(--on-green-ivory);min-width:26px}
.mail--ink{color:var(--ink-panel)}
.mail--ink dt{color:var(--ink-mute);min-width:34px}
.attach{display:flex;align-items:center;gap:11px;border:1px solid rgba(231,207,146,.22);padding:11px 13px;background:rgba(254,252,247,.05)}
.attach--ink{border-color:var(--hair-ink);background:var(--band)}
.attach i{width:24px;height:30px;background:var(--pdf);color:#fff;font-size:8px;font-style:normal;display:flex;align-items:center;justify-content:center;flex:none}
.attach b{font-size:13px;font-weight:300;color:var(--paper)}
.attach--ink b{color:var(--ink-panel)}
.attach span{font-size:11.5px;color:var(--on-green-ivory)}
.attach--ink span{color:var(--ink-mute)}


/* ═════════════════════════════════════════════════════════════════════════════
   12 · THE STORY BLOCKS — `st-*`. ADDED 1 SEP 2026, `feat-the-website-story` W1.

   The vocabulary `PREVIEW_home_the_story_01sep/index.html` introduces, carried
   from its `base.css` + `build_site.py` EXTRA. Values are the preview's own; the
   preview is a fixed 1440px document and this sheet is fluid, so a fixed px that
   would break a phone is expressed in this sheet's `clamp()` idiom at the SAME
   1440 value. Proportions are the preview's. Only the mechanism differs — the
   same departure, for the same reason, that §1 records for the token table.

   ⚠⚠ EVERY CLASS IS PREFIXED `st-`, AND THAT IS NOT TIDINESS. Seven of the names
   the brief lists are ALREADY DEFINED in this house and one of them would have
   failed silently and totally:
     · `.frame`   — v22.css §4 AND home.css. It is the story player's frame:
                    `opacity:0; pointer-events:none` unless JS sets `[data-on]`.
                    A picture given the preview's `.frame` would have been
                    INVISIBLE on every page, with no suite able to say so.
     · `.phone`   — v22.css §5, the device shell (22px radius, --phone ground)
     · `.iris`    — v22.css §5, her quote block (3px rule, --band ground)
     · `.tree`    — suppliers.css, the Drive leaf list
     · `.trades`  — suppliers.css
     · `.plan`    — together.css, the plan card
     · `.start`   — home.css
   ⚠ AND `.tree`/`.trades` LIVE IN A SHEET TWO OUT-OF-PEN PAGES LOAD. `for.html`
   and `for-wedding-photographers.html` both link `v22/suppliers.css` (W0 §5).
   Re-defining either would have changed what THEY draw, from a file this arc is
   allowed to edit, with nothing in the repo watching. Namespacing makes that
   impossible by construction rather than by care.
   ⚠ The prefix is also the census: `grep -o 'st-[a-z-]*' v22.css | sort -u` is
   the whole block, and no page outside the three carries a single `st-` class.

   ⚠ NO NEW TOKEN IS DECLARED HERE, DELIBERATELY (W0 §5.3). The token table has
   FIVE byte-identical copies and `v22TokenParity` reads THREE, so a new token
   added to the three v22 pages would make the two trade pages the ones that
   drift, silently. Everything below is built from the existing 41.

   ALL USER-FACING COPY IS DRAFT (Rule 5). See each page's [DRAFT] manifest.
   ═════════════════════════════════════════════════════════════════════════════ */

/* ── the concept band: three beats, the third one dark ── */
.st-beats{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:clamp(16px,2.4vw,24px)}
@media (max-width:1000px){.st-beats{grid-template-columns:minmax(0,1fr)}}
.st-beat{background:var(--paper);border:1px solid var(--hair-ink);padding:clamp(20px,2vw,26px) clamp(20px,2vw,26px) clamp(22px,2.2vw,28px);display:flex;flex-direction:column;gap:14px}
.st-beat__k{font-size:10px;letter-spacing:.3em;text-transform:uppercase;color:var(--gold-text);font-weight:500}
.st-beat h3{font-family:var(--play);font-weight:400;font-size:clamp(20px,2.1vw,24px);line-height:1.2;color:var(--ink-head)}
.st-beat p{font-size:clamp(14px,1.7vh,15px);line-height:1.6;color:var(--ink)}
.st-beat__shot{border:1px solid var(--hair-ink);overflow:hidden;background:var(--chrome);height:clamp(200px,26vw,300px);flex:none}
.st-beat__shot img{width:100%;height:100%;object-fit:cover;object-position:top center;display:block}
/* the third beat sits on the panel green so "when they meet" reads as the turn */
.st-beat--meet{background:var(--panel);color:var(--on-green-ivory);border-color:var(--hair-gold-2)}
.st-beat--meet h3{color:var(--paper)}
.st-beat--meet p{color:var(--on-green-ivory)}
.st-beat--meet .st-beat__k{color:var(--on-green-gold)}
.st-door{font-size:10.5px;letter-spacing:.2em;text-transform:uppercase;color:var(--gold-text);font-weight:500;margin-top:auto}
.st-beat--meet .st-door{color:var(--gold-2)}
.st-door a{color:inherit;display:inline-flex;align-items:center;min-height:44px}
/* ⚠ 44px ON THE LINK, NOT ON `.st-door`. Measured at 1440, 768 and 390 the two
   beat links rendered 14px tall — a real anchor under the house's own floor, and
   `.st-door` carries `margin-top:auto` so growing IT would have pushed the card
   layout instead of the target. The visible text does not move; the box grows
   around it. Two of two, on every width. */

/* ── the ask exchange (question above, answer below, both bordered) ── */
.st-ask{display:flex;flex-direction:column;gap:10px;font-size:13.5px;line-height:1.5}
.st-ask__q,.st-ask__a{padding:12px 14px;border:1px solid var(--hair-gold-2)}
.st-ask__q{background:rgba(240,220,166,.08);align-self:flex-end;max-width:90%}
.st-ask__a{background:var(--paper);color:var(--ink);align-self:flex-start;max-width:92%}
.st-ask__meta{display:block;font-size:9.5px;letter-spacing:.24em;text-transform:uppercase;color:var(--on-green-gold);margin-bottom:6px}
.st-ask__a .st-ask__meta{color:var(--gold-text)}

/* ── the proof strip: three figures in one ruled row ── */
.st-proof{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));border:1px solid var(--hair-gold-2)}
.st-proof>div{padding:clamp(20px,2.2vw,26px) clamp(20px,2.4vw,28px);display:flex;flex-direction:column;gap:6px;border-right:1px solid var(--hair-gold-2)}
.st-proof>div:last-child{border-right:0}
.st-proof .st-big{font-family:var(--play);font-size:clamp(30px,3.4vw,42px);line-height:1;color:var(--paper)}
.st-proof .st-big em{color:var(--gold-2);font-style:italic}
.st-proof .st-k{font-size:10px;letter-spacing:.3em;text-transform:uppercase;color:var(--on-green-gold)}
.st-proof p{font-size:14px;line-height:1.55;color:var(--on-green-ivory)}
@media (max-width:900px){
  .st-proof{grid-template-columns:minmax(0,1fr)}
  .st-proof>div{border-right:0;border-bottom:1px solid var(--hair-gold-2)}
  .st-proof>div:last-child{border-bottom:0}
}

/* ── the app in action: a wide desk frame and a phone beside it ── */
.st-action{display:grid;grid-template-columns:minmax(0,1.55fr) minmax(0,1fr);gap:clamp(24px,3vw,40px);align-items:end}
.st-frame{position:relative;border:1px solid var(--hair-gold-2);background:var(--panel);line-height:0;box-shadow:0 30px 60px -30px rgba(0,0,0,.55)}
.st-frame img{width:100%;display:block}
.st-frame--paper{border-color:var(--hair-ink);box-shadow:0 30px 60px -30px rgba(18,63,48,.35)}
/* ⚠ NOT `.phone`. v22.css §5's .phone is the drawn device shell and is still in
   use by the showcase; this is the story's own, at the preview's 250px. */
.st-phone{width:clamp(190px,17vw,250px);border-radius:34px;border:6px solid var(--phone);overflow:hidden;background:var(--phone);box-shadow:0 30px 60px -28px rgba(0,0,0,.6);line-height:0;justify-self:center;aspect-ratio:9/19}
.st-phone img{width:100%;height:100%;object-fit:cover;object-position:top;display:block}
@media (max-width:900px){
  .st-action{grid-template-columns:minmax(0,1fr);gap:clamp(18px,3vh,28px)}
  .st-phone{justify-self:center}
}

/* ── the two faces, each with its room chips ── */
.st-faces{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:clamp(20px,2.4vw,34px);margin-top:clamp(22px,2.6vh,34px)}
@media (max-width:900px){.st-faces{grid-template-columns:minmax(0,1fr)}}
.st-face{display:flex;flex-direction:column;gap:10px;border-top:1px solid var(--hair-gold-2);padding-top:18px}
.st-face .st-k{font-size:10px;letter-spacing:.3em;text-transform:uppercase;color:var(--on-green-gold);font-weight:500}
.st-face h3{font-family:var(--play);font-weight:400;font-size:clamp(20px,2.1vw,24px);line-height:1.2;color:var(--paper)}
.st-face p{font-size:clamp(14px,1.7vh,15px);line-height:1.6;color:var(--on-green-ivory)}
.sec--band .st-face,.sec--paper .st-face{border-top-color:var(--hair-ink)}
.sec--band .st-face .st-k,.sec--paper .st-face .st-k{color:var(--gold-text)}
.sec--band .st-face h3,.sec--paper .st-face h3{color:var(--ink-head)}
.sec--band .st-face p,.sec--paper .st-face p{color:var(--ink)}
.st-rooms{display:flex;flex-wrap:wrap;gap:8px}
/* ⚠ 44px, not the preview's 8px/12px padding. These are not controls and take no
   focus, but they sit in a thumb's way on a phone and the house floor is 44. */
.st-rooms span{font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;padding:8px 12px;min-height:34px;display:inline-flex;align-items:center;border:1px solid var(--hair-gold-2);color:var(--on-green-gold)}
.sec--band .st-rooms span,.sec--paper .st-rooms span{border-color:var(--hair-ink);color:var(--ink-head)}

/* ── the four-frame strip ── */
.st-strip{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:clamp(14px,1.6vw,20px)}
@media (max-width:1100px){.st-strip{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (max-width:700px){.st-strip{grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}}
.st-strip figure{display:flex;flex-direction:column;gap:12px}
.st-strip figcaption{font-size:13.5px;line-height:1.5;color:var(--on-green-ivory)}
.st-strip figcaption b{display:block;font-family:var(--play);font-weight:400;font-size:clamp(16px,1.6vw,18px);color:var(--paper);margin-bottom:4px}
.sec--band .st-strip figcaption,.sec--paper .st-strip figcaption{color:var(--ink)}
.sec--band .st-strip figcaption b,.sec--paper .st-strip figcaption b{color:var(--ink-head)}
.st-strip .st-frame{aspect-ratio:16/10;overflow:hidden}
.st-strip .st-frame img{height:100%;object-fit:cover;object-position:top left}

/* ── the calendar: a date rail and, beside it, the moment and its frame ── */
.st-cal{display:grid;grid-template-columns:200px minmax(0,1fr)}
@media (max-width:1100px) and (min-width:901px){.st-cal{grid-template-columns:160px minmax(0,1fr)}}
.st-cal__row{display:contents}
.st-cal__when{padding:26px 24px 26px 0;border-top:1px solid var(--hair-ink);display:flex;flex-direction:column;gap:4px}
.st-cal__when .st-d{font-family:var(--play);font-size:clamp(26px,2.6vw,34px);line-height:1;color:var(--ink-head)}
.st-cal__when .st-u{font-size:10px;letter-spacing:.3em;text-transform:uppercase;color:var(--gold-text);font-weight:500}
.st-cal__what{padding:26px 0 26px 28px;border-top:1px solid var(--hair-ink);border-left:1px solid var(--hair-ink);display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.15fr);gap:clamp(20px,2.4vw,28px);align-items:start}
.st-cal__what h3{font-family:var(--play);font-weight:400;font-size:clamp(20px,2.1vw,24px);line-height:1.2;color:var(--ink-head);margin-bottom:8px}
.st-cal__what p{font-size:clamp(14px,1.7vh,15px);line-height:1.6;color:var(--ink)}
.st-cal__what .st-frame{align-self:center}
@media (max-width:900px){
  .st-cal{grid-template-columns:minmax(0,1fr)}
  .st-cal__when{padding:22px 0 6px}
  /* ⚠ THE FRAME COMES ABOVE THE COPY ON A PHONE — the preview's `order:-1`, and
     W6's row. Without it the picture is four screens below the sentence it is
     the evidence for. */
  .st-cal__what{padding:0 0 26px;border-left:0;border-top:0;grid-template-columns:minmax(0,1fr);gap:14px}
  .st-cal__what .st-frame{order:-1}
}

/* ── her line, inside a moment ── */
.st-iris{border-left:2px solid var(--rule);padding:10px 16px;background:var(--paper);display:flex;flex-direction:column;gap:6px;margin-top:14px}
.st-iris .st-who{font-size:9.5px;letter-spacing:.3em;text-transform:uppercase;color:var(--gold-text);font-weight:500}
.st-iris .st-say{font-family:var(--corm);font-style:italic;font-size:clamp(17px,1.8vw,19px);line-height:1.4;color:var(--ink-head)}
.st-iris .st-act{font-size:10.5px;letter-spacing:.18em;text-transform:uppercase;color:var(--ink-head);border:1px solid var(--hair-ink);padding:8px 12px;align-self:flex-start;margin-top:4px}

/* ── a rule-bulleted list ── */
.st-list{display:flex;flex-direction:column;gap:10px;list-style:none}
.st-list li{display:flex;gap:12px;align-items:baseline;font-size:clamp(14.5px,1.75vh,15.5px);line-height:1.5}
.st-list li:before{content:'';width:14px;height:1px;background:var(--gold-2);flex:none;transform:translateY(-5px)}
.sec--band .st-list li:before,.sec--paper .st-list li:before{background:var(--gold-text)}

/* ── the trade cards. ⚠ IVORY CARD, DARK INK — his contrast fix, and never
      gold-on-ivory: --gold-2 on --band measures 2.19:1 (v22TokenParity §5). ── */
.st-trades{display:flex;flex-wrap:wrap;gap:10px}
.st-trades span{font-family:var(--corm);font-style:italic;font-size:clamp(19px,2vw,22px);padding:6px 14px;min-height:44px;display:inline-flex;align-items:center;color:var(--gold-2);border:1px solid var(--hair-gold-2)}
.sec--band .st-trades span,.sec--paper .st-trades span{color:var(--ink-head);border-color:var(--hair-ink-2);background:var(--paper)}

/* ── the two timelines ── */
.st-tl{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:clamp(16px,2vw,24px)}
@media (max-width:900px){.st-tl{grid-template-columns:minmax(0,1fr)}}
.st-tl>div{border:1px solid var(--hair-gold-2);padding:22px 24px}
.st-tl .st-k{display:block;font-size:10px;letter-spacing:.3em;text-transform:uppercase;color:var(--on-green-gold);font-weight:500;margin-bottom:10px}
.st-tl .st-r{display:flex;justify-content:space-between;gap:16px;padding:10px 0;border-bottom:1px dotted var(--hair-gold-2);font-size:14px}
.st-tl .st-r:last-child{border-bottom:0}
.st-tl .st-r i{font-family:var(--corm);font-style:italic;font-size:17px;color:var(--gold-2)}
.st-tl .st-r--bad i{color:var(--amber-on-green)}

/* ── the days-back ledger ── */
.st-days{width:100%;border-collapse:collapse;font-size:clamp(13px,1.7vh,15px)}
.st-days th{font-size:10px;letter-spacing:.3em;text-transform:uppercase;color:var(--gold-text);font-weight:500;text-align:left;padding:0 0 12px;border-bottom:1px solid var(--hair-ink)}
.st-days td{padding:14px 0;border-bottom:1px dotted var(--hair-ink);color:var(--ink)}
.st-days td.st-n{font-family:var(--play);font-size:clamp(18px,1.9vw,22px);color:var(--ink-head)}
.st-days td.st-now{font-family:var(--corm);font-style:italic;font-size:clamp(17px,1.8vw,20px);color:var(--gold-text)}
.st-days tfoot td{border-bottom:0;padding-top:18px;font-family:var(--play);font-size:clamp(20px,2.2vw,26px);color:var(--ink-head)}

/* ── the two plans ── */
.st-plans{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:clamp(16px,2vw,24px)}
@media (max-width:900px){.st-plans{grid-template-columns:minmax(0,1fr)}}
.st-plan{border:1px solid var(--hair-gold-2);padding:clamp(24px,2.6vw,30px) clamp(24px,2.6vw,30px) clamp(28px,3vw,34px);display:flex;flex-direction:column;gap:14px}
.st-plan .st-k{font-size:10px;letter-spacing:.3em;text-transform:uppercase;color:var(--on-green-gold);font-weight:500}
.st-plan h3{font-family:var(--play);font-weight:400;font-size:clamp(24px,2.6vw,30px);line-height:1.1;color:var(--paper)}
/* ⚠⚠ THE PRICING EMBARGO IS ABSOLUTE AND THIS IS THE ELEMENT THAT CARRIES IT.
   It prints `[price · your call]` exactly as the preview does. No figure, ever.
   `v22SiteContract` greps the SHIPPED BYTES for a plan price and W5 adds a row
   asserting this element's literal text on both cards. */
.st-price{font-family:var(--corm);font-style:italic;font-size:clamp(19px,2vw,22px);color:var(--gold-2)}
.st-plan ul{list-style:none;display:flex;flex-direction:column;gap:8px;font-size:clamp(14.5px,1.75vh,15px);line-height:1.5}
.st-plan li:before{content:'— ';color:var(--gold-2)}
.st-plan .btn{align-self:flex-start;margin-top:auto}
.st-pill{display:inline-flex;align-items:center;font-size:9.5px;letter-spacing:.3em;text-transform:uppercase;padding:6px 10px;border:1px solid var(--rule);color:var(--gold);align-self:flex-start}

/* ── the three privacy columns ── */
.st-privacy{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:clamp(16px,2vw,24px)}
@media (max-width:900px){.st-privacy{grid-template-columns:minmax(0,1fr)}}
.st-privacy div{border-top:1px solid var(--hair-ink);padding-top:16px;display:flex;flex-direction:column;gap:8px}
.st-privacy h3{font-family:var(--play);font-weight:400;font-size:clamp(18px,1.9vw,21px);color:var(--ink-head)}
.st-privacy p{font-size:clamp(13.5px,1.7vh,14.5px);line-height:1.6;color:var(--ink)}

/* ── the Drive before/after trees ── */
.st-drive{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:clamp(16px,2vw,24px)}
@media (max-width:900px){.st-drive{grid-template-columns:minmax(0,1fr)}}
.st-tree{border:1px solid var(--hair-ink);background:var(--paper);padding:20px 22px;font-size:13.5px;line-height:1.7;color:var(--ink);min-height:300px}
.st-tree .st-k{font-size:10px;letter-spacing:.3em;text-transform:uppercase;color:var(--gold-text);font-weight:500;margin-bottom:10px;display:flex;justify-content:space-between;gap:10px}
.st-tree .st-k i{font-style:normal;color:var(--ink-quiet)}
.st-tree ul{list-style:none}
.st-tree ul ul{padding-left:18px;border-left:1px dotted var(--hair-ink);margin-left:6px}
.st-tree li:before{content:'▸ ';color:var(--rule);font-size:10px}
.st-tree li.st-f:before{content:'· '}
.st-tree .st-mess li{color:var(--ink-quiet)}
.st-tree .st-mess li:before{content:'· '}
.st-tree b{font-weight:500;color:var(--ink-head)}
.st-tree--after{border-color:rgba(28,107,79,.35);box-shadow:0 20px 40px -30px rgba(18,63,48,.5)}

/* ── in your pocket: two phones, captioned ── */
.st-pocket{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:clamp(22px,2.6vw,34px);align-items:start}
@media (max-width:900px){.st-pocket{grid-template-columns:minmax(0,1fr)}}
.st-pocket figure{display:flex;flex-direction:column;gap:14px;align-items:center;text-align:center}
.st-pocket .st-phone{width:clamp(180px,16vw,230px);justify-self:auto}
.st-pocket figcaption{font-size:14px;line-height:1.55;color:var(--on-green-ivory);max-width:34ch}
.st-pocket figcaption b{display:block;font-family:var(--play);font-weight:400;font-size:clamp(17px,1.8vw,19px);color:var(--paper);margin-bottom:4px}

/* ── the invitation card a supplier's Iris sends ── */
.st-invite{background:var(--paper);color:var(--ink);border:1px solid var(--hair-ink);display:grid;grid-template-columns:minmax(0,1fr) 260px;overflow:hidden}
@media (max-width:900px){.st-invite{grid-template-columns:minmax(0,1fr)}}
.st-invite__body{padding:clamp(24px,2.6vw,30px) clamp(26px,2.8vw,32px);display:flex;flex-direction:column;gap:12px}
.st-invite__body .st-from{font-size:10px;letter-spacing:.3em;text-transform:uppercase;color:var(--gold-text);font-weight:500}
.st-invite__body h3{font-family:var(--play);font-weight:400;font-size:clamp(23px,2.4vw,28px);line-height:1.15;color:var(--ink-head)}
.st-invite__body p{font-size:clamp(14px,1.75vh,15px);line-height:1.6}
.st-invite__side{background:var(--panel);padding:26px 24px;display:flex;flex-direction:column;gap:10px;justify-content:center}
.st-invite__side .st-r{display:flex;justify-content:space-between;gap:12px;font-size:13px;color:var(--on-green-ivory);border-bottom:1px dotted var(--hair-gold-2);padding:8px 0}
.st-invite__side .st-r b{font-weight:500;color:var(--gold)}

/* ── the closing register. ⚠⚠ IT LIVES HERE, NOT IN A PER-PAGE SHEET, AND THAT
      IS A DEFECT THIS WAVE FOUND IN ITSELF. W2 cut home.css to `.start` and
      `.start__seal` and W3 then wrote the SAME block onto for-suppliers.html —
      which links suppliers.css, not home.css, so the section would have rendered
      undressed. `dom-presence-is-not-dress` in one wave. Three pages using one
      block means the block belongs in the sheet all three load. ── */
.st-start{max-width:900px;margin:0 auto;text-align:center;display:flex;flex-direction:column;align-items:center;gap:clamp(18px,3vh,30px)}
.st-start__seal{width:clamp(46px,5.4vw,58px);height:auto;display:block;animation:floaty 6s ease-in-out infinite}
.st-credit{font-size:9px;letter-spacing:.3em;text-transform:uppercase;color:rgba(240,220,166,.55)}
