/* ═════════════════════════════════════════════════════════════════════════════
   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)}
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 .9s var(--ease),transform .9s var(--ease)}
[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)}
.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)}

