
  /* Anti-FOUC + hidden scaffold.
     ⚠⚠ .ks-account-toggle JOINED THIS LIST 2026-07-13 (21st) — FOUND ON A REAL PHONE, and
     invisible on a fast desktop. Webflow authors it as a standalone coral-light PILL; the
     .ks-util rule that turns it into a plain text link only bites AFTER the script MOVES it
     into the utility row. Until then a member saw an EMPTY CREAM PAGE with one orphaned
     coral pill floating in the middle of it — every other element was gated and this was not.
     ⚠ THE GENERAL RULE, WIDER THAN THE GATE'S ORIGINAL JOB: ANY WEBFLOW-AUTHORED ELEMENT THE
     SCRIPT MOVES OR RESTYLES NEEDS THIS GATE, not just ones that paint DATA. Its pre-move
     STYLING is placeholder content exactly as much as a dummy number is. */
  [data-expiry-wrap="true"] { display: none; }
  .ks-greet-headline, .ks-greet-sub, .ks-greet-cta, .ks-account-toggle { visibility: hidden; }
  html[data-ks-ready="1"] .ks-greet-headline,
  html[data-ks-ready="1"] .ks-greet-sub,
  html[data-ks-ready="1"] .ks-greet-cta,
  html[data-ks-ready="1"] .ks-account-toggle { visibility: visible; }
  .ks-partial-note { display: none; }

  /* Greeting — headline + sub grouped, sub bigger + ink */
  /* ⚠⚠ S89 — THIS FILE NOW OWNS THE HEADLINE'S FAMILY, AND IT DID NOT BEFORE.
     Read live S89: the headline computed "Instrument Serif", SANS-SERIF while the
     subheading computed "Instrument Serif", SERIF — two different stacks on what is now
     ONE visual block. The headline's family was WEBFLOW'S, so "the subheading is the same
     font as the headline" was true BY AGREEMENT, NOT BY CONSTRUCTION: a family change in
     the Designer would have silently split the block. IT IS NOW TRUE BY CONSTRUCTION.
     ⚠ THE WEIGHT WAS ALSO A LIE THAT HAPPENED TO RENDER RIGHT. Webflow asked for 300;
     Instrument Serif ships ONE weight (400), so 300 rendered as 400 and nothing looked
     wrong. Pinned at 400 deliberately — DO NOT read 400 as "someone bolded it", and do
     not raise it: >=600 here is FAUX-BOLD, which is what S21's rule exists to stop.
     ⚠⚠ THE (0,2,0) FORM IS WHAT MAKES THIS FIRE AT ALL. Webflow wears .ks-card-value on
     this h2 as a combo base. A bare .ks-greet-headline rule is (0,1,0) and LOSES at every
     width — that is exactly how lever 1 of the coins-higher pass sat dead for 33 sessions.
     ⚠ SIZE IS STILL NOT SET HERE AT DESKTOP WIDTHS — Webflow owns it and nobody has ever
     read it. The mobile size is ours (30px, in the 600px block). */
  .ks-greet-headline,
  .ks-greet-headline.ks-card-value {
    font-family: 'Instrument Serif', serif;
    font-weight: 400;
  }
  .ks-greet-headline { margin-bottom: 4px; }
  /* ============================================================
     THE CONDITIONAL MESSAGE — HER S78 EDIT, BUILT S85, QUIETED BY HER S88.

     ⚠⚠ THE FILL IS GONE AND THAT IS HER RULING, NOT A REGRESSION. She saw the blue
     banner live at ?fake=zero the hour it shipped and called it "too in your face, and
     too close to the heading", and on the second look asked for a SUBHEADING under the
     greeting — same font, a little smaller, part of the greeting. SAME SPECIES AS S85
     KNOWINGLY REVERSING HER OWN S52 WHITE CARD. DO NOT "RESTORE" THE FILL, and do not
     read §DASH.2's "both loud fills are hers" as covering this one any more: THE GREEN
     STOP CARD IS THE ONLY LOUD FILL LEFT IN THE GREETING ZONE.

     ⚠⚠⚠ THIS IS A THIRD INSTRUMENT SERIF ELEMENT AND §DASH.2 SAYS THERE ARE EXACTLY TWO.
     RULED BY JENNIE, S88, WITH THE COST NAMED: the absolute rule was HERS (S21, exercising
     a standing veto over a narrower version), and its whole value was that it needed no
     footnote. THIS IS THE FOOTNOTE. The list is now: .ks-greet-headline · .ks-bank-label ·
     .ks-greet-accent, AND NOTHING ELSE. A FOURTH IS THE SIGNAL THE RULE HAS STOPPED
     MEANING ANYTHING — same shape as the coral tripwire. Do not "restore" the serif to any
     numeral, anywhere; that reversal is untouched.
     ✅ BLUE IS BACK TO ONE JOB. §DASH.2 gave #1C4A91 exactly one (the savings/impact
     NUMBER) and the banner had been a second. The ink ruling hands that back — the palette
     rule is WHOLE again, not carrying an exception. Do not re-widen it.
     ⚠⚠ SCOPE, CORRECTED S88 — IT NOW PAINTS ON THE ZERO STATE ONLY. The old note here
     said "this paints on EVERY greeting state." That was true until dashboard-tool.js
     @ff42b66 shipped: `zero` is the ONLY state carrying accent:true, and paintGreeting()
     toggles .ks-greet-accent ON .ks-greet-sub ITSELF (js line 147; line 153 removes it on
     the fallback path). READ THE JS, NOT THIS COMMENT, IF THEY EVER DISAGREE AGAIN.
     ⚠⚠ ONLY COLOUR / WEIGHT / TOP MARGIN LIVE ON THE ACCENT RULE.
     max-width: 42ch, font-size and line-height STAY on .ks-greet-sub — they are what hold
     the S86 width alignment (all three greeting-zone elements measure ONE width at
     <=600px) on every state that gets NO accent. Move them up here and every non-zero
     greeting silently loses its width.
     ⚠ THE TOP MARGIN OVERRIDE IS GONE AGAIN, ON PURPOSE. The 16/12px raise existed for
     ONE HOUR, to buy air around a bold sans line that had just lost its padding. A serif
     SUBHEADING wants the opposite — it belongs to the headline — so it takes the base
     rule's S86-tuned 8px like every other state. NO NEW NUMBER WAS INVENTED HERE.
     ⚠ THIS BLOCK WINS ON SOURCE ORDER, NOT SPECIFICITY. Both it and the base's
     `.ks-greet-sub.ks-card-sub` are (0,2,0); this block sits BELOW it, so it wins the tie.
     KEEP IT BELOW. Moved above the base rule, the family and size silently stop applying.
     ⚠ THE COMBO IS MATCHED DEFENSIVELY, AND THE ELEMENT NOW WEARS THREE CLASSES:
     ks-greet-sub ks-card-sub ks-greet-accent. The doc says the .ks-card-sub combo is
     harmless because Webflow sets no colliding property — but that was read about FONT,
     not BACKGROUND, and nobody has read background on it. The two-class variant
     .ks-greet-sub.ks-greet-accent (0,2,0) costs nothing and cannot lose to a Webflow
     combo. §0: AUDIT THE PAGE, NEVER THE FILE.
     ⚠ CONTRAST MEASURED, NOT ASSUMED: ink #1E1A19 on the page base #F2F1EB = 15.25:1.
     (It was 7.61:1 as blue text and 8.6:1 as white-on-blue. Every version cleared AAA;
     this one is not a contrast decision, it is a belongs-with-the-headline decision.)
     ⚠⚠ font-weight: 400 IS NOT OPTIONAL AND IS NOT A TASTE CALL. INSTRUMENT SERIF SHIPS
     ONE WEIGHT. Anything >=600 requested here is FAUX-BOLD — the browser smearing the
     strokes — which is the exact artifact §DASH.2 warns about. It is written out rather
     than left unset because the element inherits from a Webflow sub that may carry one.
     LIGHTNESS COMES FROM SIZE, NEVER WEIGHT.
     ⚠⚠ THE FAMILY IS PINNED HERE; THE HEADLINE'S IS WEBFLOW'S. This file does NOT own
     .ks-greet-headline's font-family — only its mobile size. So "same font as the
     headline" is TRUE TODAY BY AGREEMENT, NOT BY CONSTRUCTION. If the headline's family
     is ever changed in the Designer, this line does not follow it and nothing reports it.
     ⚠ THE MOBILE OVERRIDE BELOW CARRIES ITS OWN SIZE, as the base sub does.
     ⚠ 42ch NOW MEASURES AGAINST INSTRUMENT SERIF'S ZERO, not Quicksand's. The max-width
     is unchanged as a RULE and different as a MEASUREMENT — third time this element's
     rendered width has moved without the rule moving. It cannot bite while the string is
     fixed and short; read it live before assuming the S86 widths still line up.
     ============================================================ */
  /* S89 — THE SUBHEADING IS SERIF ON EVERY STATE, NOT JUST `zero`. Hers.
     The declarations below are the S88 .ks-greet-accent block, moved up onto the base
     rule verbatim — same family, weight, size, line-height and ink. NOTHING WAS RETUNED.
     ⚠⚠ .ks-greet-accent NOW STYLES NOTHING AND ITS RULES ARE DELETED, not left inert.
     paintGreeting STILL EMITS THE CLASS on `zero` (js ~147). That is deliberate: the
     class survives as a hook so a future state can be differentiated again without a
     dashboard-tool.js bump. DO NOT "restore" a rule for it to make the doc tidy.
     ⚠⚠ THE (0,2,0) FORM IS LOAD-BEARING, NOT BELT-AND-BRACES. Webflow wears .ks-card-sub
     on this element as a combo base and compiles the pair at (0,2,0). A single-class
     font-family here would LOSE at every width if Webflow ever sets one. Keep both
     selectors on any rule added to this element.
     ⚠ THIS BLOCK NOW CARRIES UP TO FOUR SENTENCES (capped + a bag in motion), where the
     accent only ever held one. line-height 1.25 was chosen by eye in S88 against a
     ONE-LINE string. READ IT LIVE on the capped case before assuming it still reads. */
  .ks-greet-sub,
  .ks-greet-sub.ks-card-sub {
    font-family: 'Instrument Serif', serif;
    font-weight: 400;
    color: #1E1A19;
    font-size: 26px;
    line-height: 1.25;
    max-width: 42ch;
    margin: 8px auto 0;
  }

  /* ============================================================
     "Your Credit Bank" — ONE AUTHORITY, 21st session, 2026-07-13.

     ⚠⚠ THIS RULE USED TO BE A WALL OF !important WHOSE ONLY JOB WAS TO FIGHT THE JS.
     paintBankLabel() wrote an inline style (14px, uppercase, 2px tracking, #5F5E5A — a
     hex that is not in the palette) and this block beat every property of it with
     !important. Both halves rendered; only one won; the loser was invisible and wrong.
     A ::first-letter rule sat below capitalising a lowercase string the script wrote.
     THAT IS FIVE AUTHORITIES FOR ONE LABEL.

     ✅ FIXED AT THE SOURCE (@b39b9bf): the inline cssText is DELETED and the script now
     writes the string 'Your Credit Bank' in title case. THE SCRIPT OWNS THE STRING; THIS
     RULE OWNS THE LOOK; NEITHER TOUCHES THE OTHER. There is nothing left to override, so
     the !important flags are gone and ::first-letter is gone with them.
     ⚠ DO NOT re-add an inline style in paintBankLabel(), and DO NOT re-add !important
     here. If this label ever looks wrong again, exactly one of these two places is lying.

     ⚠ IT IS ONE OF ONLY TWO ELEMENTS THAT KEEP INSTRUMENT SERIF (§DASH.2) — the other is
     .ks-greet-headline. Title case is what makes the surviving serif read as a CHOICE and
     not a leftover. The two decisions are ONE decision; do not undo one without the other.
     ============================================================ */
  /* ⚠ ENLARGED S214 — her ruling: "a lot larger, like Look what you've done". 52px matches the
     .ks-look-h heading so the two big serif headings rhyme. line-height tightened for the size. */
  .ks-bank-label {
    font-family: 'Instrument Serif', serif;
    /* ⚠ 67 -> 52 S282, HERS — an exact reversal of the S215 enlargement, back to the S214
       size, which is .ks-look-h's size and the rhyme that was intended. The mobile twin at
       the foot of this file stays 26px. ⚠ IF IT READS CRAMPED the lever is
       .ks-hero-card .ks-bank-label { margin: 0 0 6px }, which was sized against 67px. */
    font-size: 52px;
    line-height: 1.05;
    color: #1E1A19;
    text-align: center;
    margin: 22px 0 14px;
  }

  /* Coins hero */
  /* ⚠⚠ THE GAP EXISTS TO STOP THE TWO NUMERALS READING AS ONE NUMBER — S282, HERS.
     A real reader (age 9) read a 3 coin beside a 1 coin as "31". The coins overlapped by
     15px while each coin sat only 6px from its own label, so proximity said the numerals
     belonged together and the labels belonged to nothing. 20px here plus the units' own
     centring gives ~27px between the coins against 6px coin-to-label. THIS IS THE LEVER:
     one number, judged on a render. ⚠ IT KNOWINGLY REVERSES THE S88 "tuck" — the overlap
     was deliberate, not a bug, and it is being overturned rather than repaired. */
  .ks-coins-row { gap: 16px; align-items: flex-start; }
  /* ⚠⚠⚠ THE -15px OVERLAP IS DELETED, NOT COMMENTED OUT — S282. It read as "31".
     ⚠ THE TIER LABELS' padding: 0 12px IS WRITTEN INLINE BY dashboard-tool.js (tierEl
     .style.cssText) AND IT STAYS. It was added at S214 to clear this overlap; with the
     overlap gone it still separates the two tier columns, so it is NOT inert and removing
     it costs a JS bump for nothing. ⚠ IF THE COIN BOX EVER CHANGES SIZE AGAIN, only two
     numbers move together now, not three: the box and .ks-coin-num's font-size. */

  /* ⚠⚠ THE HAIRLINE — S282, HERS, AFTER SEEING THE GAP ALONE ON A REAL RENDER.
     ⚠⚠⚠ IT IS A BACKGROUND GRADIENT, NEVER A border-left, AND THAT IS NOT A STYLE
     PREFERENCE. A border is exactly as tall as the element it sits on, and the two
     columns are NOT always the same height — three tier lines on clothing against one
     on toys makes the toy column shorter, and the line would stop short with nothing
     erroring. A BACKGROUND CONTRIBUTES NO LAYOUT, so its height is stated outright and
     cannot drift with the tier lists. Same reasoning as home.css v43's amber answer rule.
     ⚠⚠ THE SELECTOR IS THE ADJACENT SIBLING ON PURPOSE: a member on The Basics renders
     ONE coin unit, and + means there is nothing to draw a divider beside. A rule on the
     ROW would paint a line down a single-coin bank.
     ⚠ 110px = the 87px coin + its 6px label gap + the label, so the line closes under
     the label and never reaches the ragged bottom of the tier lists. top 4px sinks it
     below the coin's own top edge so it reads as a column rule, not a crop mark.
     ⚠ 16px of padding matches the 16px row gap, so the line sits centred in the space
     with the same air either side. THE TWO NUMBERS MOVE TOGETHER.
     ⚠ #C9C7BC is the hairline grey already used on the landing pages — not a new value. */
  /* ⚠⚠⚠ BOTH SELECTORS TEST THE INLINE style ATTRIBUTE AND THAT IS LOAD-BEARING, NOT
     CLEVERNESS — CAUGHT BY HER S282 BEFORE IT SHIPPED. paintCoins hides a coin with
     unit.style.display = 'none', and `+` MATCHES ON DOM ORDER, NOT ON VISIBILITY. So a
     bare `.ks-coin-unit + .ks-coin-unit` is correct for THE BASICS (clothing shows, the
     hidden toy unit is the one carrying the rule, nothing paints) and WRONG FOR THE TOY
     CHEST, where the CLOTHING unit is the hidden one and the rule lands on the only
     visible coin — a hairline with nothing on the far side of it, and 16px of padding
     shoving it off centre. An entire plan.
     ⚠⚠ THE COUPLING: paintCoins writes the literal `display: flex` / `display: none`, so
     [style*="display: flex"] is exact today. IF THAT LINE EVER BECOMES A classList TOGGLE
     THIS RULE STOPS MATCHING AND THE HAIRLINE SIMPLY DISAPPEARS — ugly, never a lie, and
     the padding goes with it so nothing lands off centre. THAT IS THE SAFE DIRECTION AND
     IT IS WHY THIS WAS TAKEN OVER A JS COMMIT. Grep paintCoins before changing either. */
  .ks-coin-unit[style*="display: flex"] + .ks-coin-unit[style*="display: flex"] {
    padding-left: 16px;
    background: linear-gradient(#C9C7BC, #C9C7BC) left 0 top 4px / 1px 110px no-repeat;
  }

  /* ============================================================
     THE COIN BOX — TAKEN OVER FROM THE DESIGNER, S88.
     ⚠⚠ .ks-coin IS A WEBFLOW DESIGNER STYLE AND HAS NEVER BEEN IN THIS FILE. Same
     situation .ks-coin-num was in for thirty-three sessions before S53. This commit takes
     ownership of it, so the size stops living in a place nothing here can read.
     ⚠ TWO SELECTORS ON PURPOSE (§0's combo rule): the descendant form is (0,2,0) so it
     beats a single-class Webflow rule outright and ties a Webflow combo (our <link> sits
     above the head box, so a tie goes to us); the bare form survives a markup reshape.
     ⚠⚠ THE IMAGE IS EXPLICITLY SIZED 130x130 IN THE DESIGNER — position:static,
     object-fit:fill, NOT a percentage. Shrink the box alone and a 130px image spills out
     of an 87px hole. The img rule is not optional and does not travel separately.
     ⚠ SIZE CHANGES HERE ARE SIZE CHANGES TO THE TUMBLE TOO — the drop+bounce animates
     the box, so it scales with it. Watch the ENTRANCE, not only the resting frame.
     ============================================================ */
  .ks-coin,
  .ks-coins-row .ks-coin { width: 87px; height: 87px; }
  .ks-coin img,
  .ks-coins-row .ks-coin img { width: 100%; height: 100%; }

  /* ============================================================
     THE ENGRAVED NUMERAL — RULED BY JENNIE, SESSION 53. IT REVERSES §DASH.2.

     §DASH.2 rejected gold on the grounds that "the coin gold lives in the PNG art; a gold
     hex would only ever duplicate it." THAT REJECTION WAS ABOUT DECORATION. Here the
     fill's whole job is to make the numeral part of the metal instead of an ink label
     lying on top of it, which is the case the rule never anticipated. Claude recommended
     the palette-legal option (keep the ink, add one light edge) and JENNIE OVERRULED IT
     KNOWINGLY. ⚠⚠ THIS IS THE ONLY SANCTIONED GOLD ON THE PAGE. Anywhere else it is
     still rejected. DO NOT "restore" the ink fill here.

     ⚠⚠ THIS ELEMENT IS AUTHORED IN WEBFLOW, NOT HERE. ks-coin-num is a Designer style,
     absolutely positioned inside .ks-coin. This file has never owned it until now.
     ⚠ READ LIVE, SESSION 54, NOT DERIVED: it wears ONE class (no combo base — the trap
     that killed coins-higher lever 1 does NOT apply here).

     ⚠⚠ AND IT WAS STILL INSTRUMENT SERIF 400 / 50px. MEASURED, NOT ASSUMED.
     §DASH.13 records the coin numerals as having gone Quicksand 600 in the 21st session
     when Jennie killed the serif-numeral exception. THAT CHANGE NEVER REACHED THE COIN —
     it is a Designer style and nothing here owned it, so the reversal applied to
     .ks-imp-n and .ks-hcw-n and quietly missed the one numeral a member actually looks
     at. SAME SPECIES AS COINS-HIGHER LEVER 1: recorded as done, never once live.
     ⚠ SO THE font-family BELOW IS NOT A NEW DECISION. It is Jennie's Session 21 ruling
     finally being applied. Do not read it as a fresh departure from §DASH.2 — it IS
     §DASH.2.
     ⚠ QUICKSAND ALSO HOLDS AN ENGRAVING AND A SERIF DOES NOT: Instrument Serif ships one
     weight (400) and its hairlines have barely more width than the shadow edge, which
     swallows the stroke. Quicksand 600 gives roughly triple the stroke area to cut into.
     ⚠⚠ 44px, NOT 50. A SAME-SIZE FAMILY SWAP IS NOT A NEUTRAL SWAP (§DASH.2) — Quicksand
     600 is optically heavier than Instrument Serif 400, which is why .ks-panel-h came
     down 26 -> 22 on the same kind of change. 50px Quicksand on a 90px coin reads chunky,
     worst on a two-digit balance. Chosen by looking at all three live, not derived.
     ⚠ §DASH.3 records 26px and the Session 53 handoff records 36px. BOTH WERE WRONG and
     both had been sitting in the doc unread. THIS FILE NOW OWNS THE SIZE, so those
     figures are dead — the shadow offsets are calibrated to 44px and travel with it.

     ⚠ TWO SELECTORS, ON PURPOSE (§0's combo rule). The descendant form is (0,2,0) so it
     beats any single-class Webflow rule outright; the bare form is the survivor if the
     coin markup is ever reshaped. KEEP BOTH.

     ⚠⚠ DOING THIS HERE RATHER THAN IN THE DESIGNER CONTAINS THE BLAST RADIUS, AND THAT
     IS A REASON, NOT A CONVENIENCE. dashboard.css loads on /dashboard ONLY, so the
     checkout coin chip (#ksc-bank), which may reuse this class, IS NOT TOUCHED. Editing
     the Designer style WOULD have reached it. If checkout should ever match, that is a
     separate and deliberate decision, not a side effect of this one.

     ⚠⚠ LIGHT SOURCE = DIRECTLY ABOVE. SAMPLED OFF THE ACTUAL COIN PNG, SESSION 54, NOT
     GUESSED — the first build of this rule guessed top-left and was wrong.
     Inner face: top #F2DB90 (lum 218.5) · top-left #F1D88B (215.8) · bottom-right
     #ECCD77 (205.4) · bottom #EBCA73 (202.7). The gradient is VERTICAL: top-to-bottom
     drops 15.8, and the diagonal's 10.4 is just that same gradient's vertical component.
     There is no meaningful left bias. HENCE ZERO HORIZONTAL OFFSET.
     ⚠ THE DARK SHADOW SITS ON THE LIGHT-SOURCE SIDE and the pale one opposite. That
     inversion is the whole effect: the groove's upper lip faces away from the light and
     the lower lip catches it. Get it backwards and the numeral BULGES instead of cutting.
     TO FLIP IT: swap the two Y offsets.
     ⚠ IF THE COIN ART IS EVER REPLACED, RE-SAMPLE. These offsets are matched to this PNG.

     ⚠ THE NUMERAL FADES IN AT 460ms as part of the tumble (COIN_SPIN cross-fades it at
     frame 6). A text-shadow rides along with opacity correctly — but JUDGE THE ENTRANCE,
     not only the resting frame.

     ⚠⚠ THE FILL IS A MEASURED VALUE, NOT A TASTE CALL. DO NOT DARKEN IT ON INSTINCT.
     The coin surface is #F0D78A (lum 215). A groove reads as a groove when its floor sits
     roughly 25-45 lum BELOW the surface — shadowed, not painted. #D9AF4A is lum 177, a
     gap of 38.
     ⚠ THE FIRST BUILD USED #A9761C (lum 124) — A GAP OF 91 — AND IT FAILED FOR EXACTLY
     THIS REASON. Every engraving cue was present and correct; the fill simply overpowered
     them, so the eye read a dark mark SITTING ON the coin with a shadow behind it. THE
     INSTINCT TO "MAKE IT DARKER SO IT READS" IS THE BUG. Darkening undoes the effect.
     ⚠ THE REAL COST, AND IT IS REAL: an engraved numeral has LOWER CONTRAST than ink, and
     this is the single most important number on the page. If it is ever reported as hard
     to read at a glance, THE ANSWER IS NOT A DARKER GOLD — it is a larger numeral, a
     heavier weight, or abandoning the treatment. Ruled with that named and accepted.
     ============================================================ */
  /* ⚠⚠ S88 — 44px -> 29px, BECAUSE THE COIN WENT 130 -> 87 (1/3 smaller, HERS). The
     numeral is not independently sized; it is sized TO THE COIN. If the coin ever moves
     again, this moves with it.
     ⚠⚠ THE NUMERAL WILL NOT RE-CENTRE ON ITS OWN. It is position:absolute with inset:0
     and the Designer gave it a HARD-CODED 50px line-height that does not scale with
     font-size — so a smaller numeral would sit low in the new box. The flex block below
     is what re-centres it, and line-height:1 is what kills the 50px.
     ⚠ THIS CENTRING IS THE ONE PART OF THIS COMMIT THAT WAS REASONED, NOT MEASURED.
     LOOK AT THE NUMERAL FIRST after this ships.
     ⚠ THE SHADOW OFFSETS BELOW ARE UNCHANGED AT 1px — they were calibrated to a 44px
     numeral, so the groove is now proportionally heavier. If the engraving reads muddy at
     29px the answer is A LARGER OR HEAVIER NUMERAL, NEVER A DEEPER GOLD (see below). */
  .ks-coin-num,
  .ks-coin .ks-coin-num {
    font-family: 'Quicksand', sans-serif;
    font-weight: 600;
    font-size: 29px;
    line-height: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #D9AF4A;
    text-shadow:
      0 -1px 0 rgba(120, 84, 16, 0.55),
      0  1px 0 rgba(255, 250, 222, 0.95);
  }

  /* ⚠ .ks-savings-block AND .ks-sv-br WERE DELETED HERE AT S166 — SIX RULES, NOT FIVE.
     The Webflow element was removed from /dashboard in the Designer (verified 0 in the
     SERVED markup, not just the DOM), so every rule that styled it became inert. Two of
     the six were .ks-sv-br, a <br> created by paintSavings() — RETIRED AT S163 — so no
     search for "savings" would ever have found them. DO NOT RESTORE ANY OF IT: the block
     carried HARDCODED PLACEHOLDER NUMBERS ("$487 worth of clothes and toys. That's 23 so
     far.") and "Look what you've done" replaced it. dashboard-tool.js still hides it on
     paintLook's first line, null-guarded, now a harmless no-op — keep that line. */

  /* Account panel — column + open/close */
  .ks-account-panel { display: none; }
  .ks-account-panel.is-open { display: block; }
  .ks-account-toggle,
  .ks-account-panel { max-width: 420px; margin-left: auto; margin-right: auto; }

  /* Account & Settings toggle — coral, centered, gap above */
  .ks-account-toggle,
  .ks-account-toggle:link,
  .ks-account-toggle:visited {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 9px;
    width: fit-content;
    margin: 44px auto 0;
    font-size: 16px;
    font-weight: 600;
    color: #D65A35;
    text-decoration: none;
    padding: 11px 22px;
    border: 1px solid #F0C9B5;
    border-radius: 50px;
    background: #F7E4D9;
    cursor: pointer;
  }
  .ks-account-toggle::before {
    content: "\2699";
    font-size: 17px;
    line-height: 1;
    color: #D65A35;
  }
  .ks-account-toggle::after {
    content: "\25BE";
    font-size: 18px;
    color: #D65A35;
    transition: transform 240ms ease;
  }
  .ks-account-toggle.is-open::after { transform: rotate(180deg); }

  /* Section headers */
  .ks-account-panel .ks-card-title { display: none; }

  .ks-acc-head {
    display: flex; align-items: center; justify-content: flex-start; gap: 10px;
    max-width: 420px; margin: 0 auto; padding: 14px 2px;
    font-size: 16px; font-weight: 500; color: #1E1A19;
    cursor: pointer; user-select: none;
    /* It is a <button> now (WCAG 2.1.1 / 4.1.2 — a div cannot be a control).
       Everything below strips the browser's default button chrome. Do NOT
       remove the focus rule: a keyboard member needs to see where she is. */
    width: 100%;
    background: none;
    border: none;
    font-family: inherit;
    text-align: left;
    -webkit-appearance: none;
    appearance: none;
  }
  .ks-acc-head:focus-visible {
    outline: 2px solid #D65A35;
    outline-offset: 2px;
    border-radius: 6px;
  }
  .ks-acc-head::after {
    content: "\25B8"; font-size: 17px; color: #211B1A;
    transition: transform 240ms ease;
  }
  .ks-acc-head.is-open::after { transform: rotate(90deg); }

  /* Section body */
  .ks-acc-body {
    max-width: 420px; margin: 0 auto; overflow: hidden; text-align: left;
    transition: max-height 260ms ease, opacity 200ms ease;
  }
  .ks-account-panel .ks-card-value,
  .ks-account-panel .ks-card-sub { text-align: left; }

  /* Browse CTA — anchored at the very bottom */
  .ks-greet-cta { margin-top: 36px; margin-bottom: 0; }

  /* Membership */
  /* ⚠ QUICKSAND. The card is display:none (.ks-mem-hidden) so this paints for nobody today —
     but if it is ever un-hidden it must not resurrect a serif the type system no longer has. */
  .ks-membership-plan {
    font-family: 'Quicksand', sans-serif; font-weight: 600; font-size: 24px; color: #1E1A19; margin-top: 2px;
  }
  .ks-membership-status {
    font-size: 14px; font-weight: 500; color: #4E9360; margin-top: 2px;
  }
  /* Cancelled and paused are not good news. Don't confirm them in the success green. */
  .ks-membership-status[data-tone="off"] { color: #75736E; }
  .ks-membership-manage,
  .ks-membership-manage:link,
  .ks-membership-manage:visited {
    display: inline-block; background: #D65A35; color: #EEEFE3;
    font-size: 14px; font-weight: 600; text-decoration: none;
    padding: 9px 20px; border-radius: 50px; margin-top: 12px;
    border: none; cursor: pointer;
  }
  .ks-membership-manage:hover { background: #BE4C2E; }

  /* Hero card — paper on cream (Level 1).
     ⚠ WIDTH IS SET IN THE 19th-SESSION BLOCK BELOW (420, not 480). Do not
     re-add a max-width here — two authorities for one number is how this box
     grew three duplicate rules. */
  /* ⚠⚠⚠ THE BANK IS #EDECE0 ON A WHITE PAGE — S214. She is changing the PAGE background to
     plain white in Webflow, so the bank inverts: a warm off-white card on white instead of a
     white card on cream. ⚠⚠ THE FILL ALONE READS 1.19 ON WHITE — NEARLY INVISIBLE — so the
     DROP SHADOW IS LOAD-BEARING, not decoration; it is the only thing separating the card from
     the page. Do not weaken it. ⚠ this is the CSS drop shadow (she wanted the COIN shadow in
     the source art, but the CARD shadow stays in CSS). ⚠ interior text measured on #EDECE0:
     ink 14.52, impact-blue 7.25, muted 3.99 and cycle-line #8A897F 2.96 — the last two are the
     same knowing sub-4.5 acceptance already made on the email footer; ink carries the weight. */
  .ks-hero-card {
    margin: 0;
    background: #EDECE0;
    border-radius: 22px;
    box-shadow: 0 12px 34px -10px rgba(30,26,25,0.28);
  }
  /* Tightened inside the card. ⚠ NO !important — see the .ks-bank-label block above. */
  /* ⚠ 16px -> 6px S215, HERS — the swaps-ready line reads as a SUBHEADING of the bank title
     rather than a separate line. .ks-swaps-ready keeps its own 16px BELOW it, so only the
     space ABOVE the sub closes. */
  .ks-hero-card .ks-bank-label { margin: 0 0 6px; }

  /* Tier dots — coin breakdown ladder */
  .ks-tier-row { display: flex; align-items: center; gap: 7px; }
  /* ⚠⚠⚠ THE TIER LABELS WERE TOUCHING — S214, and the FIRST fix (margin-right on .ks-tier-row)
     WAS THE WRONG ELEMENT: each coin has its OWN .ks-coin-tier (flex-direction:column, one row
     each), so "9 Essentials" and "1 Elevated" sit under TWO DIFFERENT COINS, not as siblings in
     one row. The real cause is .ks-coin-unit + .ks-coin-unit { margin-left:-15px } (line ~167) —
     the coins OVERLAP on purpose, but that pulls the second coin's tier LABEL left under the
     first coin's label. Fix: give each tier label horizontal padding so the labels clear the
     15px overlap while the COINS stay tucked. Scoped to .ks-coin-tier, not the coins. */

  .ks-dot { width: 7px; height: 7px; border-radius: 50%; flex: none; }
  /* ⚠⚠ ONE TIER LANGUAGE EVERYWHERE — HER RULING S213. These repoint onto the SHIPPED
     BROWSE SCHEME (browse-tool.js @ac7b175): essentials NO MARK, elevated blue, special
     brand yellow. The old grey / green / amber was a THIRD tier vocabulary nobody had
     swept, and green means TOYS in the signup palette, so a green dot on a TIER read
     doubly wrong. Found only because the S197 browse repoint never looked at this file.
     ⚠⚠ ESSENTIALS IS display:none, NOT A COLOUR CHANGE. .ks-tier-row is a flex row, so
     the 7px gap collapses on its own with the dot gone — the same device browse used for
     its own bag dots. THE LABEL STILL NAMES THE TIER, so nothing is encoded in colour alone.
     ⚠⚠⚠ TWO CONSUMERS, NOT ONE: coinTierHTML() in the credit bank AND the My Closet find
     cards via TIER_DOT. Both move together, deliberately. Do not "scope" this to the bank.
     ⚠ MEASURED, NOT EYEBALLED: blue reads 8.65 on the white card. #EDA920 reads 2.04,
     UNDER the 3.0 bar for a graphical mark — carried anyway because it is what browse
     already ships and re-splitting the language costs more than it buys. IF THE PALETTE
     EVER GETS A PASS, #A67C0A (3.37) is the measured-safe gold and BOTH surfaces move. */
  /* ⚠⚠⚠ ESSENTIALS GETS A DOT AGAIN — HER RULING S214, reversing the S213 "essentials no dot".
     "one blue, one green": essentials GREEN, elevated BLUE. ⚠ GREEN ALREADY MEANS TOYS (signup)
     AND IMPACT (the Look card right below), so this makes green a tier meaning too — her call,
     made knowingly. Reusing #1F5C38 (the Look card's green, reads 6.68 on the #EDECE0 bank) so
     it is the SAME green already on the page, not a fourth one. ⚠⚠ TWO CONSUMERS: the bank AND
     the My Closet find cards via TIER_DOT — the green dot appears in both. */
  .ks-dot--ess  { background: #1F5C38; }
  .ks-dot--elev { background: #28498D; }
  .ks-dot--spec { background: #EDA920; }

  /* Plan chip — coral-light pill under the greeting sub */
  /* ⚠ LIVES IN THE UTILITY ROW NOW (moved there by buildUtilityRow). It hides itself on a
     null/unknown plan — which is also the CANCELLED member — so the row must read fine
     without it. */
  .ks-plan-chip {
    display: block;
    width: fit-content;
    /* ⚠⚠⚠ NO MARGIN — S214. Two prior fixes both broke: `18px auto 0` stranded the chip in the
       centre (auto side margins eat free space in a flex-end row), and `18px 0 0` DROPPED IT
       BELOW its row-mates (a top margin in an align-items:center row pushes one item down). The
       header clearance the chip needed belongs on the .ks-util ROW (below), not the item, so the
       chip stays level with Manage Membership / Account & Settings. */
    margin: 0;
    padding: 7px 15px;
    background: #F7E4D9;
    color: #D65A35;
    font-size: 11px;
    font-weight: 600;
    line-height: 1;
    border-radius: 50px;
    text-align: center;
  }

  /* Swaps-ready line — the headline inside the card */
  .ks-swaps-ready {
    font-size: 15px;
    line-height: 1.5;
    color: #75736E;
    text-align: center;
  }
  .ks-swaps-ready b { font-weight: 600; color: #1E1A19; }

  /* Cycle bar */
  .ks-cycle-bar-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    font-size: 13px;
    color: #75736E;
    margin-bottom: 8px;
  }
  .ks-cycle-bar-head b { font-weight: 600; color: #1E1A19; }
  .ks-cycle-bar-track {
    height: 7px;
    background: #EEEFE3;
    border-radius: 50px;
    overflow: hidden;
  }
  .ks-cycle-bar-fill {
    display: block;
    height: 100%;
    width: 0;
    background: #D65A35;
    border-radius: 50px;
  }
  /* ⚠⚠⚠ THE EARNED SENTENCE — S214. Relocated from the retired .ks-sec-impact rail block into
     the BANK FOOTER, her ruling. paintImpact() writes .ks-bank-earned and appends it after the
     cycle bar. One sentence, muted, under a cream-grey divider so the bank has a clear footer.
     ⚠ THIS SURVIVED A NAVY EXPERIMENT AND ITS REVERT — the navy version was cream-on-navy; this
     is the white-card version. Do not re-add navy colours. */
  .ks-hero-card .ks-bank-earned {
    margin-top: 14px;
    padding-top: 14px;
    border-top: 1px solid #C9C7BC;   /* ⚠ #EEEFE3 is invisible on #EDECE0 (1.02); C9C7BC reads 1.43 */
    /* ⚠ S215, HERS — this shipped as system-ui and was the ONLY element on the card not in
       the house face. Quicksand matches every other body line in the bank. */
    font-family: 'Quicksand', sans-serif;
    font-size: 13px;
    line-height: 1.5;
    color: #75736E;
    text-align: center;
  }
  .ks-hero-card .ks-bank-earned b { color: #1E1A19; font-weight: 600; }

  /* ---------- SCRIPT-INJECTED SECTIONS ---------- */
  .ks-closet-sec { max-width: 480px; margin: 36px auto 0; text-align: left; }
  /* ⚠ FLAT. Only the HERO is elevated (§DASH.8: elevated = the payoff, flat = admin).
     The rule existed and was never applied — every card carried the same shadow, so
     nothing said which one you were meant to feel like you were holding. */
  .ks-panel { background: #FFFFFF; border: 1px solid #EEEFE3; border-radius: 22px; box-shadow: none; padding: 24px; margin-bottom: 20px; }

  /* ⚠ .ks-sec-head IS DEAD as of 2026-07-13 (19th session). It was the big centered
     serif title that floated ABOVE the closet card. Headings now live INSIDE the
     panel (.ks-panel-h). No caller passes headText any more, so nothing emits this.
     Left in place, not deleted — same treatment as coinTierString/openAccountPanel.
     ⚠ QUICKSANDED ANYWAY. It paints for nobody, but a serif rule sitting here is a lie about
     the type system, and the next session would read it as a third survivor. */
  .ks-sec-head { font-family: 'Quicksand', sans-serif; font-weight: 600; font-size: 32px; color: #1E1A19; text-align: center; margin: 0 0 16px; }

  .ks-closet-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 12px; }
  .ks-find { border: 1px solid #EEEFE3; border-radius: 14px; overflow: hidden; background: #FFFFFF; }
  .ks-find-ph { aspect-ratio: 3/4; background: #EEEFE3; overflow: hidden; }
  .ks-find-ph img { width: 100%; height: 100%; object-fit: cover; display: block; }
  .ks-find-body { padding: 10px 10px 12px; }
  .ks-find-nm { font-size: 13px; font-weight: 600; color: #1E1A19; line-height: 1.3; margin-bottom: 3px; text-align: left; }
  .ks-find-sz { font-size: 12px; color: #75736E; margin-bottom: 7px; text-align: left; }
  .ks-find-tier { display: flex; align-items: center; gap: 6px; font-size: 11px; color: #75736E; font-weight: 500; text-align: left; }

  .ks-showall {
    display: block; width: 100%; margin-top: 16px; padding: 11px; border-radius: 99px;
    border: 1px solid #F0C9B5; background: transparent; color: #D65A35;
    font-family: inherit; font-size: 14px; font-weight: 600; cursor: pointer;
  }

  /* ⚠ .ks-act-label IS DEAD as of 2026-07-13 (19th session) — the small uppercase
     micro-label above the activity list. Replaced by .ks-panel-h. Nothing emits it. */
  .ks-act-label { font-size: 12px; font-weight: 600; color: #75736E; letter-spacing: .04em; margin-bottom: 10px; text-align: left; }

  /* VERTICAL, WITH A REAL SHAPE. The feed moved into the ~290px rail, and the old
     horizontal shape (34px icon | title + detail | right-floated date) had nowhere to put
     the date at that width — it collided with the title or wrapped badly. A plain column
     stack gave three left-aligned things in a row with nothing telling them apart. Now: a
     HEADER LINE (icon left, date hard right) and the text beneath it, full width. DOM order
     is icon -> main -> when, so `order` does the rearranging — no markup change, no hook
     touched. */
  /* ⚠⚠⚠ FIXED S214 — her finding: "whats going on with recent activity? the floating date and
     nothing next to the dot." THE BUG WAS THE WRAP: flex-wrap:wrap + .ks-act-main flex:1 0 100%
     forced the title onto a SECOND full-width line, stranding the icon and the date alone on
     row one. NOW A NORMAL THREE-COLUMN ROW on ONE line: icon, title/detail (flex:1), date.
     align-items:flex-start so a two-line detail keeps icon+date pinned to the top. The emit
     order in the JS is already icon -> main -> when, so no JS change is needed. */
  .ks-act-row {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 16px 0 18px;
    border-bottom: 1px solid #EEEFE3;
  }
  .ks-act-row:last-of-type { border-bottom: none; padding-bottom: 2px; }
  .ks-act-row .ks-act-main { flex: 1; margin-top: 0; text-align: left; }
  .ks-act-row .ks-act-when { flex: none; }
  .ks-act-icon {
    width: 34px; height: 34px; border-radius: 10px;   /* rounded squares, not circles */
    flex: none; display: flex; align-items: center; justify-content: center; font-size: 14px;
  }
  /* ✅ GOLD REMOVED 2026-07-13. #FBF1DC / #8A6511 were a live palette violation —
     gold is EXPLICITLY rejected (§DASH.2: the coin gold lives in the PNG art; a gold
     hex would only ever duplicate it). Flagged three sessions, now ruled. Cream tile,
     muted-grey glyph. An 'earn' event is a STATUS, not an action — it must not reach
     for coral either (that would be the fourth coral). ZERO NEW HEXES. */
  .ks-act-icon--earn { background: #EEEFE3; color: #75736E; }
  .ks-act-icon--swap { background: #F7E4D9; color: #D65A35; }
  .ks-act-main { min-width: 0; }
  .ks-act-title { font-size: 14px; font-weight: 600; color: #1E1A19; line-height: 1.45; text-align: left; }
  .ks-act-detail { font-size: 13px; color: #75736E; margin-top: 4px; line-height: 1.55; text-align: left; }
  .ks-act-when { font-size: 12px; color: #75736E; flex: none; padding-top: 0; }

  /* YOUR CONTRIBUTION (§DASH.13). SCRIPT-INJECTED — DO NOT REBUILD IT AS A CODE EMBED; the
     last one was dragged out of its container in Navigator and silently deleted.
     ⚠ THE NUMERAL IS BLUE #1C4A91 BECAUSE THAT IS BLUE'S ONE JOB (§DASH.2). Not decorative.
     ⚠⚠ S85: THE HEX WAS CORRECTED FROM #28498D. #28498D WAS AN EYEDROPPED NEAR-MISS off a
     PNG, from the same list that carried the wrong coral (#D65A35) and the wrong green
     (#4E9360). JENNIE CONFIRMED HER BRAND BLUE IS #1C4A91. /signup still paints #28498D on
     the shop-first fork — DIFFERENT FILE, OWN PIN BUMP, NOT SWEPT HERE.
     ⚠ IT HIDES AT ZERO, PER STAT LINE. That rule lives in the JS — do not add a CSS hide. */
.ks-imp-stat {
    display: flex;
    align-items: center;   /* ⚠ WAS baseline. A 2-line label HUNG BELOW THE NUMERAL:
                              baseline pins the 32px numeral's baseline to line ONE, so the
                              numeral rides above line 1 and line 2 ("family") drops out the
                              bottom, under the digit. THE RAIL IS ~220px AND THE APPROVED
                              COPY IS 38 CHARS — IT WILL ALWAYS WRAP THERE. The wrap is not
                              the bug; the hang was. Do not "fix" this by shortening the copy
                              (locked, §DASH.13) or shrinking the numeral (it is the payoff). */
    gap: 10px;
    padding: 7px 0;
  }
  /* ⚠⚠ QUICKSAND 600 — THE NUMERAL EXCEPTION IS REVERSED, RULED BY JENNIE 2026-07-13 (21st).
     §DASH.2 used to carve the numerals OUT of the Quicksand rule and keep them serif. That
     exception is DEAD. THE RULE IS NOW ABSOLUTE: Instrument Serif lives on EXACTLY TWO
     ELEMENTS — .ks-greet-headline and .ks-bank-label — AND NOWHERE ELSE. No footnote, no
     exception anyone has to remember. That is WHY it was reversed: two surviving serifs read
     as a CHOICE, five read as LEFTOVERS. Do not "restore" the serif to any numeral. */
.ks-imp-n {
    font-family: 'Quicksand', sans-serif;
    font-weight: 600;                /* ceiling 600, NEVER 700 */
    font-size: 32px;
    line-height: 1;
    color: #1C4A91;
    flex: 0 0 auto;
    min-width: 30px;                 /* ⚠ "1" IS NARROWER THAN "4", so a shrink-to-fit numeral
                                        column made the two labels START AT DIFFERENT x. The
                                        rows didn't share a text margin. min-width + tabular
                                        figures lock the column. ⚠ Holds to 2 digits; a 3-digit
                                        count will push again — fine, and named so it isn't a
                                        mystery later. */
    text-align: left;
    font-variant-numeric: tabular-nums;
  }
  .ks-imp-l {
    font-size: 13px;
    line-height: 1.4;
    color: #1E1A19;                  /* PAYLOAD, not secondary text — this is what she came to read. */
    text-align: left;
  }
  /* "Member since" IS genuinely secondary — an account fact under two payoff stats. */
  .ks-imp-since {
    font-size: 12.5px;
    color: #75736E;
    margin-top: 12px;
    padding-top: 12px;
    border-top: 1px solid #EEEFE3;
    text-align: left;
  }

  /* ============================================================
     "LOOK WHAT YOU'VE DONE" - THE TWO NUMBERS. S163, HER RULING.
     Main column, directly under the credit bank card. It REPLACES the savings inset
     (deleted from the Webflow hero) and takes the sent-in count OUT of the rail, so
     items_received no longer appears anywhere on this page.

     ⚠⚠⚠ THE SERIF RULE IS RETIRED HERE, KNOWINGLY, HER CALL S163. The July ruling
     above .ks-imp-n ("Instrument Serif lives on EXACTLY TWO ELEMENTS ... do not restore
     the serif to any numeral") was put back to her with its own reasoning quoted, and she
     chose the serif design she had already seen rendered. So this block carries serif on
     FOUR elements. DO NOT "CORRECT" IT BACK TO QUICKSAND. .ks-imp-n itself is UNCHANGED -
     the rail numeral stays Quicksand 600 and that comment still governs THAT rule.

     ⚠⚠ min-width:0 IS LOAD-BEARING, ON BOTH THE STAT AND THE LABEL. A flex item
     defaults to min-width:auto, so a label that cannot shrink OVERFLOWS THE CARD instead
     of wrapping - "kept in circul..." ran off the right edge at $12,480 / 248. And
     white-space:nowrap made it WORSE, not better. Do not add nowrap, do not remove either
     min-width.

     ⚠⚠ align-items:center, NEVER baseline. The same trap .ks-imp-stat already carries:
     a two-line label baseline-aligned to a 40px numeral hangs off the bottom of it.

     ⚠ SPACE-BETWEEN pushes both stats to the card edges - hers. A LONE stat CENTRES
     instead, via :only-child, so a half state is not a number stranded on the left. Half
     states DO render: the hide is PER STAT LINE and it lives in the JS, not here.
     ============================================================ */
  /* ⚠⚠⚠ THE INK CARD — HER RULING S213, AND IT IS THE ONE NON-WHITE CARD ON THIS PAGE.
     A celebration that wears the same white box as every information card reads as one.
     ⚠⚠ SCOPED TO .ks-sec-look .ks-panel AND NEVER TO THE BARE .ks-panel, which every
     section on this dashboard wears — one unscoped fill turns the whole page dark, the
     same shape as the S200 signup bug where the fill went on the SECTION and the viewport
     went blue edge to edge. (0,2,0) beats the base rule's (0,1,0), so this wins on
     SPECIFICITY and does not depend on source order.
     ⚠⚠⚠ THE FILL WENT INK FIRST AND SHE REVERSED IT ON THE LIVE RENDER, S214: "the almost
     black background is a little jarring, and it makes the celebration take over the page."
     IT IS NOW #1F5C38 — one of the THREE DARK GREENS she approved at S73, live already as
     the bottom stop of the Toy Chest card gradient. NOT INVENTED, and NOT brand green.
     ⚠⚠⚠ BRAND GREEN #309359 CANNOT CARRY THIS CARD AND WAS ASKED FOR AND MEASURED DOWN:
     cream reads 3.32 on it, white 3.86, the numerals 2.49, the labels 2.27 — every element
     fails. That is the S73 rule exactly, and it is why these three greens exist at all:
     DARKEN THE GREEN, NEVER WHITEN THE TEXT ON THE OLD GREEN. Do not "restore" #309359.
     ⚠ MEASURED ON #1F5C38: cream #EEEFE3 6.84, gold #F7DE8A 5.96, line #C9C7BC 4.68.
     ⚠ THE NUMERALS ARE #F7DE8A — HER S69 GOLD, an approved palette value. The #F3CA7A that
     shipped at @296508e existed only in an S213 mockup and reads 5.12 here; the approved
     gold is both hers and better. Do not reintroduce F3CA7A.
     ⚠⚠⚠ AND THE GREEN FILL WAS REVERSED TOO, ON ITS OWN LIVE RENDER, S214: "id rather have
     no background at all ... the green background takes over the whole page, and its not
     supposed to." THE CARD NOW HAS NO FILL AT ALL. Ink lasted one commit, green lasted one
     commit; the direction across all three was the same and it was always DOWNWARD IN WEIGHT.
     ⚠⚠ THE FILL IS transparent AND NOT A REMOVED RULE, ON PURPOSE — .ks-panel's own white
     is what would show through, so this must actively override it. Deleting this rule does
     NOT give you a backgroundless card, it gives you the white one back.
     ⚠⚠⚠ THIS IS WHAT KILLED THE GOLD, AND IT IS ARITHMETIC RATHER THAN TASTE. ON THE CREAM
     PAGE #F2F1EB: light gold #F7DE8A reads 1.18, brand yellow #EDA920 1.80, amber #E5AD43
     1.79 — ALL UNREADABLE. The ONLY gold that survives on cream is #A67C0A at 3.37, and
     that is LARGE-TEXT ONLY. So the S213 "numbers in gold, to rhyme with the coin bank"
     idea died with the fill, and green became the through-line instead. DO NOT PUT A GOLD
     NUMERAL BACK ON THIS CARD WHILE IT HAS NO FILL.
     ⚠ MEASURED ON CREAM: dark green #1F5C38 7.01, mid green #256F43 5.40, ink 15.25, muted
     #75736E 4.19. ⚠ THE 13px LABEL AT 4.19 IS UNDER THE 4.5 AA LINE AND IS ACCEPTED
     KNOWINGLY, the same call already made on the email footer at 4.0.
     ⚠⚠ BRAND GREEN #309359 READS 3.41 ON CREAM, so it is usable for LARGE TEXT here even
     though it can never be a fill. It is NOT used today. If it is ever wanted on the
     heading, that is the reason it would be allowed — not a reversal of the S73 rule.
     ⚠ ON INK AND ON GREEN, FOR THE RECORD: on ink cream 14.87 / line 10.17 / muted 3.64;
     on #1F5C38 cream 6.84 / gold #F7DE8A 5.96 / line #C9C7BC 4.68. Rollback pins carry them. */
  /* ⚠⚠ FULLY BORDERLESS — her ruling S214 ("hairline boxes need to be removed"). The Look
     card kept the bare .ks-panel border + radius + padding; the other sections were stripped
     but this scoped rule only cleared the background. Now it clears the box too. */
  .ks-sec-look .ks-panel { background: transparent; border: 0; border-radius: 0; box-shadow: none; }

  /* ⚠⚠⚠ THE EDITORIAL PASS — S214, her final layout after trying ink, green, left-rules and
     boxes. The bank is the ONE card (white, above); every other section drops fill/border/
     shadow, CENTRES, and is separated by a HAIRLINE TOP DIVIDER with generous space. Her call:
     "horizontal dividers and center alignment." THESE OVERRIDE THE BARE .ks-panel on
     specificity (0,2,0). Do not delete the bare rule — off-dashboard callers use it.
     ⚠ .ks-sec-impact is RETIRED (its text moved to the bank footer; paintImpact display:none's
     it) so it is not listed here. ⚠ .ks-sec-look is already transparent above and already
     centred by its own rules — it is in this list only for the shared reset, no divider. */
  .ks-sec-activity .ks-panel,
  .ks-sec-review   .ks-panel,
  .ks-sec-hcw      .ks-panel {
    background: transparent;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    padding: 0;
    margin: 0;
    text-align: center;
  }
  /* ⚠⚠ ONE SPACE ABOVE THE DIVIDER LINE, NOT TWO — S214. This rule shipped with BOTH
     padding-top:44 AND margin-top:44, which stacked to 88px, and Look added 20px below itself
     on top of that: ~108px void on mobile, exactly the "still too much space" she flagged. The
     divider needs ONE gap above its line. 28px padding (space between line and content) with
     the margin providing the space above the line, and Look's own bottom margin dropped to 0
     so nothing doubles. */
  .ks-sec-activity .ks-panel,
  .ks-sec-hcw      .ks-panel {
    border-top: 1px solid #C9C7BC;
    padding-top: 28px;
    margin-top: 28px;
  }
  /* ⚠⚠ padding-bottom 24 -> 8 S215, HERS — the space under "items given / second lives" was
     the PANEL'S OWN PADDING, not a margin on the row (row, stat and section all measure 0).
     SCOPED TO .ks-sec-look SO THE BANK CARD KEEPS ITS 24px. It also beats the mobile
     .ks-panel { padding: 20px 18px } on specificity, deliberately — same gap at both widths. */
  .ks-sec-look .ks-panel { margin-bottom: 0; padding-bottom: 8px; }
  /* HOW CREDITS WORK is the quiet footer — muted heading. */
  .ks-sec-hcw .ks-panel-h { color: #75736E; }

  .ks-look-h {
    font-family: 'Instrument Serif', serif;
    font-weight: 400;
    font-size: 52px;
    line-height: 1.05;
    color: #1F5C38;
    margin-bottom: 12px;
    text-align: center;
  }
  /* ⚠ THE SPARK SITS ON THE HEADING'S OWN CENTRE LINE, so .ks-look-h becomes a flex row and
     the heading text is wrapped in a <span> by paintLook. em-sized, so it scales with the
     heading at every breakpoint and needs no mobile twin. currentColor, so it can never
     disagree with the heading. */
  /* ⚠⚠ THE HEADING TEXT CENTRES ON THE CARD, NOT THE LEAF+TEXT UNIT — her ruling S214: the
     note "should be centered below the TEXT above it not including the icon." The heading is
     an inline-flex sized to its <span> of text; centring that block centres the TEXT. The leaf
     is absolutely positioned against the span (position:relative on the h) so it hangs off the
     left WITHOUT adding layout width — the text's centre is the card's centre, and the centred
     note underneath now lines up. Robust to the phone wrap because nothing hard-codes a width. */
  /* ⚠⚠⚠ FIXED AGAIN S214 — the absolute right:100% version SHIPPED THE LEAF OFF-SCREEN (it
     resolved against the whole inline-flex heading, not the text span, and vanished at f708802).
     ROBUST METHOD: the heading is a normal CENTRED flex row [leaf][span]; the leaf is given a
     NEGATIVE right margin equal to its own width so it contributes ZERO layout width. The text
     then centres on the card as if the leaf weren't there, the note lines up under it, and the
     leaf hangs into the left gutter — visible, and correct at any width including the phone wrap.
     No positioning context, no hard-coded widths, nothing to break. */
  .ks-look-h { display: flex; align-items: center; justify-content: center; }
  .ks-look-h .ks-look-spark { margin-right: 0.24em; margin-left: -0.86em; }
  /* ⚠⚠ THE LEAF IS THE ONE GOLD LEFT ON THIS CARD, AND #A67C0A IS THE ONLY GOLD THAT CAN BE
     ON CREAM AT ALL (3.37, and a mark only needs 3.0). It sets `color` rather than a fill,
     because the SVG draws itself in currentColor — one value, and the icon can never
     disagree with itself. ⚠ SHE ASKED FOR A LEAF OVER A RECYCLE MARK KNOWING BOTH: reuse
     sits ABOVE recycling in the waste hierarchy and the chasing-arrows symbol is the one
     the FTC Green Guides treat as a recyclability claim, which is not what KidSwaps does. */
  /* ⚠ SIZED IN em SO IT SCALES WITH THE HEADING; colour is the one cream-safe gold #A67C0A.
     Positioning is handled by the .ks-look-spark absolute rule above — no transform hacks. */
  .ks-look-spark { width: 0.62em; height: 0.62em; color: #A67C0A; }
  /* ⚠⚠ THE NOTE MOVED UP — HERS. The order is heading → note → numbers, so it stops being
     a bottom signature. It is still emitted LAST in paintLook until the JS half ships, and
     that intermediate state is harmless: right colours, old order. */
  .ks-look-note {
    font-family: 'Instrument Serif', serif;
    font-weight: 400;
    font-style: italic;
    font-size: 20px;
    line-height: 1.4;
    color: #1E1A19;
    margin: 0 0 26px;
    text-align: center;
  }
  .ks-look-row {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 18px;
  }
  .ks-look-stat {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    min-width: 0;
    /* ⚠⚠ EQUAL HALVES, S163, AFTER SEEING IT RENDER. space-between alone left the gap
       as a LEFTOVER: fine in a mockup frame and fine at 607px, but on a ~1000px card the two
       stats sat at opposite edges with a lake between them and read as two separate facts
       rather than a pair. flex:1 1 0 gives each stat exactly half the row, so the second one
       always starts at the midpoint whatever the numerals measure.
       ⚠ IT ALSO FIXES SOMETHING NOBODY HAD HIT YET: with shrink-to-fit, a wide numeral
       moved where its own label started, so $12,480 and $101 would not align across states.
       ⚠ space-between above is now inert but HARMLESS — left as the fallback if these
       flex values are ever removed. Do not read it as the thing doing the spacing. */
    flex: 1 1 0;
  }
  /* ⚠ A LONE STAT CENTRES, and it has to be justify-content now, NOT margin:0 auto.
     Under flex:1 1 0 the only child already FILLS the row, so auto margins have nothing left
     to distribute and the stat would sit hard left. The common half state is savings-only. */
  .ks-look-stat:only-child { justify-content: center; }
  /* ⚠ THE DIVIDER EXISTS ONLY WHEN THERE ARE TWO STATS TO DIVIDE — the adjacent-sibling
     selector cannot fire on a lone stat, so the half state needs no branch. CLAUDE'S CALL,
     REVERSIBLE. rgba white over the ink is a TINT of the card, not a faded brand colour. */
  .ks-look-stat + .ks-look-stat { border-left: 1px solid #C9C7BC; }
  .ks-look-n {
    font-family: 'Instrument Serif', serif;
    font-weight: 400;
    font-size: 44px;
    line-height: 1;
    color: #1F5C38;
    flex: 0 0 auto;
    font-variant-numeric: tabular-nums;
  }
  .ks-look-l {
    font-size: 13px;
    line-height: 1.35;
    color: #75736E;
    min-width: 0;
    text-align: left;
  }
  /* THE COUNT-UP'S FINISHING GESTURE. CSS owns the animation, JS only adds the class -
     the same split .ks-greet-accent already uses. INERT UNTIL THE JS HALF SHIPS, which is
     what makes it safe to ride this commit.
     ⚠ prefers-reduced-motion kills the pop, and the JS kills the count-up on the same
     query, so the two die together and the member sees the real number sitting still. */
  @keyframes ks-look-pop {
    0%   { transform: scale(0.94); }
    55%  { transform: scale(1.03); }
    100% { transform: scale(1); }
  }
  .ks-look-n.is-pop { animation: ks-look-pop 400ms cubic-bezier(.34,1.4,.64,1) both; }
  @media (prefers-reduced-motion: reduce) {
    .ks-look-n.is-pop { animation: none; }
  }

  /* ⚠ .ks-empty-h GOES QUICKSAND 600, 21st session (§DASH.2 / §DASH.13). It is NOT one of
     the two elements that keep the serif. ⚠ 18px, DELIBERATELY SMALLER THAN .ks-panel-h's
     22px — it sits INSIDE the closet panel, BENEATH that panel's own heading. Sizing it
     equal would put two competing headings in one card. */
  .ks-empty { text-align: center; padding: 16px 8px 4px; }
  .ks-empty-h { font-family: 'Quicksand', sans-serif; font-weight: 600; font-size: 18px; color: #1E1A19; margin-bottom: 8px; text-align: center; }
  .ks-empty-p { font-size: 14px; color: #75736E; line-height: 1.7; max-width: 360px; margin: 0 auto; text-align: center; }
  .ks-empty-cta {
    display: inline-block; margin-top: 18px; padding: 12px 26px; border-radius: 99px;
    border: 1px solid #F0C9B5; background: transparent; color: #D65A35;
    font-size: 14px; font-weight: 600; text-decoration: none;
  }

  /* Dividers deleted: three hairlines in a ~290px card is fussy, and space separates
     just as well. The numeral now sits in a CREAM ROUNDED SQUARE — the exact shape and
     colour as .ks-act-icon beside it, so the rail and the feed speak one language. */
  .ks-hcw-row { display: flex; gap: 13px; padding: 0 0 20px; border-bottom: none; }
  .ks-hcw-row:last-child { padding-bottom: 0; }
  /* ⚠ QUICKSAND 600 — the serif numeral exception is REVERSED (see .ks-imp-n above). */
  .ks-hcw-n {
    width: 32px; height: 32px; border-radius: 10px; flex: none;
    background: #EEEFE3; color: #75736E;
    font-family: 'Quicksand', sans-serif; font-weight: 600; font-size: 17px;
    display: flex; align-items: center; justify-content: center;
  }
  .ks-hcw-t { font-size: 14px; font-weight: 600; color: #1E1A19; margin-bottom: 3px; text-align: left; }
  .ks-hcw-b { font-size: 13px; color: #75736E; line-height: 1.65; text-align: left; }

  /* ⚠ .ks-rev-h GOES QUICKSAND 600, 21st session. Matches .ks-panel-h at 22px — the review
     card's heading IS that card's panel heading; it just carries its own class. */
  .ks-rev-h { font-family: 'Quicksand', sans-serif; font-weight: 600; font-size: 22px; line-height: 1.2; color: #1E1A19; margin: 0 0 8px; }
  .ks-rev-p { font-size: 14px; color: #75736E; line-height: 1.7; margin: 0 0 18px; }
  .ks-rev-cta {
    display: inline-block; padding: 12px 26px; border-radius: 99px;
    border: 1px solid #F0C9B5; background: transparent; color: #D65A35;
    font-size: 14px; font-weight: 600; text-decoration: none;
  }

  @media (max-width: 600px) {
    .ks-closet-grid { grid-template-columns: repeat(2, 1fr); }
    .ks-sec-head { font-size: 26px; }
  }

  /* Nothing inside the hero card is real until the script paints it - the coins have
     no number, and the savings line still holds Webflow's placeholder ($487 / 23).
     Hide the whole card until the page is marked ready, so a member never sees
     invented numbers. Keyed to the same data-ks-ready gate the anti-FOUC pattern
     already uses, so the 4s failsafe still guarantees it appears.
     ⚠ .ks-sec-impact NEEDS NO GATE: it is script-injected, so it does not exist in the
     Designer and has no placeholder content to flash. Safe by construction. */
  html:not([data-ks-ready="1"]) .ks-hero-card,
  html:not([data-ks-ready="1"]) .ks-section--membership { visibility: hidden; }

  /* ===== MEMBERSHIP CARD — lifted out of the account panel 2026-07-12 =====
     ARL §17602(d): the cancel path must be a prominently located control, not
     something behind a disclosure. This card is visible; one click reaches the
     Stripe portal. Do NOT put it back inside .ks-account-panel.
     ⚠ IT IS 420px AND STAYS 420px. It was swept into the 900px desktop widener
     by mistake and spent a session as a near-empty band holding three short
     lines. It is deliberately NOT in that media query any more. */
  .ks-section--membership {
    max-width: 420px;
    margin: 44px auto 0;
    padding: 22px 24px;
    background: #FFFFFF;
    border: 1px solid #EEEFE3;
    border-radius: 18px;
    text-align: left;
  }

  /* The panel's title-hiding rule no longer reaches this card. It needs a real
     heading now — it is a standalone section, not an accordion row. */
  .ks-section--membership .ks-card-title {
    display: block;
    font-family: 'Quicksand', sans-serif;
    font-size: 13px;
    font-weight: 600;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: #75736E;
    margin: 0 0 10px;
  }

  .ks-section--membership .ks-membership-plan { margin-top: 0; }

  /* Coral OUTLINE, not solid. Solid coral is the ONE action (Browse), and this
     button must not compete with it — but it must still read unmistakably as a
     button (ARL: cancellation has to be easy to find). */
  .ks-section--membership .ks-membership-manage,
  .ks-section--membership .ks-membership-manage:link,
  .ks-section--membership .ks-membership-manage:visited {
    background: transparent;
    color: #D65A35;
    border: 1px solid #D65A35;
    margin-top: 16px;
  }
  .ks-section--membership .ks-membership-manage:hover {
    background: #D65A35;
    color: #EEEFE3;
  }

  /* Email prefs: native checkboxes were raw browser blue — a 10th colour nobody chose.
     GREEN, not coral: a checked preference is a STATUS, not an action, and coral would
     have been the FOURTH coral (§DASH.2's tripwire, firing correctly again). */
  .ks-pref-toggle { accent-color: #4E9360; }

  /* Contact support computed to rgb(0,0,238) — raw browser blue — DESPITE carrying
     .ks-cta. Nothing was styling it. Coral TEXT, never a solid coral button. */
  .ks-account-panel a.ks-cta { color: #D65A35; text-decoration: none; }
  .ks-account-panel a.ks-cta:hover { color: #BE4C2E; text-decoration: underline; }

  /* Remove: a destructive action should be quiet, not blue. Its inline opacity:0.6 is
     deleted at source in the embed (§DASH.2: no opacity for colour). */
  .ks-child-remove { color: #75736E; }

  /* ACCOUNT PANEL (§DASH.10). Flat white — elevated = the payoff, flat = admin (§DASH.8).
     ⚠ COLOUR IS DELIBERATELY UNTOUCHED. .ks-card-sub inherits ink and that is CORRECT: an
     address / email / checkbox label is PAYLOAD, not secondary text. Greying reads disabled. */
  .ks-account-panel.is-open {
    background: #FFFFFF;
    border: 1px solid #EEEFE3;
    border-radius: 18px;
    padding: 4px 22px;
    margin-top: 14px;
  }

  /* Rows. The divider is the real fix for the spacing lie: head+body is now
     bounded ABOVE by a line, so a body can no longer look like it belongs to
     the NEXT section (it did — the gap below a body was smaller than the gap
     between closed heads). Chevron to the right edge = the row reads as a control. */
  .ks-account-panel .ks-acc-head {
    padding: 16px 0;
    font-weight: 600;
    border-top: 1px solid #EEEFE3;
  }
  .ks-account-panel > .ks-acc-head:first-child { border-top: none; }
  .ks-account-panel .ks-acc-head::after {
    margin-left: auto;
    font-size: 15px;
    color: #75736E;
  }

  /* Body attaches UP to its own head.
     ⚠⚠ THE PADDING IS GATED ON .is-open, AND IT HAS TO BE. max-height:0 CANNOT
     COMPRESS PADDING — the browser clamps the content box to zero and the padding
     still stands, so an unconditional padding-bottom put 18px of dead space under
     every CLOSED row. (box-sizing:border-box does not fix this: a border-box element
     cannot shrink below its own padding.) The head is the body's previous sibling and
     openAcc adds .is-open BEFORE it measures scrollHeight, so the measurement already
     includes this padding. No JS change. */
  .ks-account-panel .ks-acc-head.is-open + .ks-acc-body { padding: 0 0 18px 2px; }

  /* Hierarchy. Body text was inheriting full body size — as large as its own
     heading, so nothing said "this is a section, that is its content." */
  .ks-account-panel .ks-card-sub { font-size: 14px; line-height: 1.6; }
  .ks-account-panel .ks-card-value { font-size: 15px; font-weight: 600; }

  /* THE HELP HELPER LINE. Replaces the dead .ks-section--help rule - that class
     does not exist and never did (read live 2026-07-13: 0 matches in the DOM). The
     Help card is the ONLY card in the panel carrying a mailto CTA, so name it
     STRUCTURALLY instead of by a class name someone hoped existed. */
  .ks-account-panel .ks-card:has(a.ks-cta) .ks-card-sub,
  .ks-account-panel .ks-children-empty { color: #75736E; }

  /* ⚠ .code-embed-5 + .ks-lifetime-value-wrap hide rules are GONE (20th) — both matched
     nothing, and one carried a comment telling the next session to rebuild a deleted embed. */

  /* ---------- SHIPPING ADDRESS: EDIT (§ADDR, 2026-07-13) ---------- */
  /* ZERO NEW HEXES. Coral #D65A35 / hover #BE4C2E / muted grey #75736E / ink #1E1A19 / cream #EEEFE3. */
  /* NO OPACITY FOR COLOUR (§DASH.2). */

  /* Edit = a quiet coral TEXT affordance, never a button-shaped thing.
     The solid coral Browse CTA is already on this page; a second solid coral here
     would be the fourth coral (§DASH.2 tripwire). */
  .ks-account-panel .ks-addr-edit {
    background: none;
    border: none;
    appearance: none;
    padding: 0;
    margin-top: 10px;
    font-family: inherit;          /* LOAD-BEARING: a <button> does NOT inherit the page font */
    font-size: 14px;
    font-weight: 600;
    color: #D65A35;
    cursor: pointer;
  }
  .ks-account-panel .ks-addr-edit:hover { color: #BE4C2E; }
  .ks-account-panel .ks-addr-edit:focus-visible {
    outline: 2px solid #D65A35;
    outline-offset: 2px;
    border-radius: 4px;
  }

  /* The form */
  .ks-account-panel .ks-addr-form { margin-top: 12px; }
  .ks-account-panel .ks-addr-row { display: block; margin-bottom: 10px; }
  .ks-account-panel .ks-addr-label {
    display: block;
    font-size: 12px;
    font-weight: 600;
    color: #75736E;
    margin-bottom: 4px;
  }
  .ks-account-panel .ks-addr-input {
    width: 100%;
    box-sizing: border-box;
    font-family: inherit;          /* inputs don't inherit either */
    font-size: 14px;
    color: #1E1A19;
    background: #FFFFFF;
    border: 1px solid #EEEFE3;
    border-radius: 10px;
    padding: 9px 11px;
  }
  .ks-account-panel .ks-addr-input:focus { outline: none; border-color: #D65A35; }

  /* State is two characters. Give it a short field so the shape teaches the rule. */
  .ks-account-panel .ks-addr-input[data-addr="state"] { max-width: 90px; }
  .ks-account-panel .ks-addr-input[data-addr="zip"]   { max-width: 140px; }

  .ks-account-panel .ks-addr-actions {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-top: 14px;
  }

  /* Save = coral OUTLINE pill. Same treatment as .ks-showall / .ks-empty-cta.
     Deliberately NOT solid (§DASH.2). */
  .ks-account-panel .ks-addr-save {
    background: none;
    appearance: none;
    font-family: inherit;
    font-size: 14px;
    font-weight: 600;
    color: #D65A35;
    border: 1px solid #D65A35;
    border-radius: 999px;
    padding: 8px 18px;
    cursor: pointer;
  }
  .ks-account-panel .ks-addr-save:hover { color: #BE4C2E; border-color: #BE4C2E; }
  .ks-account-panel .ks-addr-save:focus-visible {
    outline: 2px solid #D65A35;
    outline-offset: 2px;
  }
  /* Disabled while saving. A real hex, never an opacity. */
  .ks-account-panel .ks-addr-save:disabled {
    color: #75736E;
    border-color: #75736E;
    cursor: default;
  }

  /* Cancel = quiet. A way out should never compete with the way forward. */
  .ks-account-panel .ks-addr-cancel {
    background: none;
    border: none;
    appearance: none;
    padding: 0;
    font-family: inherit;
    font-size: 14px;
    color: #75736E;
    cursor: pointer;
  }
  .ks-account-panel .ks-addr-cancel:hover { color: #1E1A19; }
  .ks-account-panel .ks-addr-cancel:focus-visible {
    outline: 2px solid #D65A35;
    outline-offset: 2px;
    border-radius: 4px;
  }

  /* Status regions. These EMPTY rather than hide (a screen reader will not announce
     text written into a display:none region that is then revealed) — so they must
     collapse to nothing when empty, or they leave a permanent gap. */
  .ks-account-panel .ks-addr-status,
  .ks-account-panel .ks-addr-saved { font-size: 13px; line-height: 1.5; }
  .ks-account-panel .ks-addr-status:not(:empty) { margin-top: 10px; }
  .ks-account-panel .ks-addr-saved:not(:empty)  { margin-top: 10px; color: #75736E; }

/* ---------- ADDRESS CHECK: THE CONFIRM STEP (§ADDR-VERIFY, Session 51) ---------- */
  /* Shown ONLY when the server answers needs_confirm. Three codes share one block:
     corrected (shows both candidates), flagged and not_found (message only).
     ⚠⚠ SHE CAN ALWAYS PROCEED. Every variant carries a save-anyway. Shippo flags real
     occupied addresses as undeliverable and cannot see a missing apartment at all, so a
     hard block would lock a member out of an address that is perfectly fine.
     ZERO NEW HEXES. */

  .ks-account-panel .ks-addr-confirm { margin-top: 14px; }

  .ks-account-panel .ks-addr-confirm-msg {
    font-size: 14px;
    line-height: 1.5;
    color: #1E1A19;
  }

  /* The two candidates, corrected only. Bordered so the pair reads as ONE thing to
     choose between rather than two loose paragraphs. */
  .ks-account-panel .ks-addr-choices {
    margin-top: 12px;
    border: 1px solid #EEEFE3;
    border-radius: 12px;
    overflow: hidden;
  }
  .ks-account-panel .ks-addr-choice { padding: 10px 12px; }
  .ks-account-panel .ks-addr-choice + .ks-addr-choice { border-top: 1px solid #EEEFE3; }

  .ks-account-panel .ks-addr-choice-label {
    display: block;
    font-size: 12px;
    letter-spacing: 0.4px;
    text-transform: uppercase;
    color: #75736E;
    margin-bottom: 4px;
  }

  /* ⚠⚠ THIS RENDERS THE EXACT STRING THAT WILL BE STORED, VERBATIM. Shippo answers in
     capitals because that is how USPS prints labels; if it does, she sees capitals and
     chooses knowing that. DO NOT PRETTIFY IT HERE. Showing her one thing and saving
     another is the single failure this whole block exists to prevent. */
  .ks-account-panel .ks-addr-choice-value {
    font-size: 14px;
    line-height: 1.5;
    color: #1E1A19;
  }

  .ks-account-panel .ks-addr-confirm-actions {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-top: 14px;
    flex-wrap: wrap;
  }

  /* Primary = coral OUTLINE pill. Copies .ks-addr-save's LOOK, not its NAME — this
     button is not "save", it is "use this one". Outline, never solid (§DASH.2). */
  .ks-account-panel .ks-addr-confirm-go {
    background: none;
    appearance: none;
    font-family: inherit;
    font-size: 14px;
    font-weight: 600;
    color: #D65A35;
    border: 1px solid #D65A35;
    border-radius: 999px;
    padding: 8px 18px;
    cursor: pointer;
  }
  .ks-account-panel .ks-addr-confirm-go:hover { color: #BE4C2E; border-color: #BE4C2E; }
  .ks-account-panel .ks-addr-confirm-go:focus-visible {
    outline: 2px solid #D65A35;
    outline-offset: 2px;
  }
  .ks-account-panel .ks-addr-confirm-go:disabled {
    color: #75736E;
    border-color: #75736E;
    cursor: default;
  }

  /* Secondary = quiet text. It is a REAL choice, not a way out, but it must not
     compete with the recommended one. */
  .ks-account-panel .ks-addr-confirm-alt {
    background: none;
    border: none;
    appearance: none;
    padding: 0;
    font-family: inherit;
    font-size: 14px;
    color: #75736E;
    cursor: pointer;
  }
  .ks-account-panel .ks-addr-confirm-alt:hover { color: #1E1A19; }
  .ks-account-panel .ks-addr-confirm-alt:focus-visible {
    outline: 2px solid #D65A35;
    outline-offset: 2px;
    border-radius: 4px;
  }
  .ks-account-panel .ks-addr-confirm-alt:disabled { color: #75736E; cursor: default; }

  /* THE PAGE GRID (§DASH.12). 2/3 MAIN + 1/3 RAIL. MAIN: bank -> closet -> how-credits.
     RAIL: contribution -> activity -> review. ⚠ THE RAIL RETIRED .is-solo — a missing card
     just shortens a column; there is no track to collapse. .ks-split/.ks-2up are GONE. */
  .ks-grid { display: block; }
  .ks-col  { min-width: 0; }

  @media (min-width: 940px) {
    .ks-grid {
      display: grid;
      grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
      gap: 20px;
      align-items: start;          /* ⚠ NOT stretch — a short card must not be
                                      inflated to match a tall neighbour. That was
                                      the canyon under "My closet". */
      margin-top: 30px;
    }
    .ks-col {
      display: flex;
      flex-direction: column;
      gap: 20px;
    }
    /* ⚠⚠ THE RAIL IS STICKY AGAIN — THE SAFE VERSION ONLY, RULED BY JENNIE S73, BUILT S85.
       THE COMMENT THAT STOOD HERE SAID SHE DECLINED IT (2026-07-13). THAT WAS TRUE AND IS
       NOW STALE — S73 REVERSED IT. The stale text was removed rather than left beside the
       new rule: an orphaned comment lying confidently is the worst artifact this project
       produces.

       WHY THE NAIVE VERSION IS STILL FORBIDDEN, because the reason has not changed: the
       rail holds the ACTIVITY FEED (10 rows). A PLAIN position:sticky ELEMENT TALLER THAN
       THE VIEWPORT PINS AT ITS TOP AND ITS BOTTOM BECOMES UNREACHABLE — the last activity
       rows could never be scrolled to. max-height + overflow-y:auto is what dissolves that:
       it pins AND scrolls internally, so nothing is ever out of reach. DO NOT "SIMPLIFY"
       THIS BY DROPPING EITHER LINE — they are one mechanism, not a rule plus a precaution.
       ⚠ IT DEPENDS ON THE GRID'S align-items:start ABOVE. Under the default (stretch) the
       rail is inflated to the row's full height and sticky has nothing to travel through.
       ⚠ A STICKY UTILITY ROW IS STILL REJECTED ("nothing sticky on heading"). Unchanged. */
    .ks-rail {
      position: sticky;
      top: 20px;
      max-height: calc(100vh - 40px);
      overflow-y: auto;
    }

    /* ⚠⚠ THIS OVERRIDE IS SCOPED TO >=940 ON PURPOSE, 21st session. IT USED TO SIT AT THE
       TOP LEVEL, AND THAT WAS A LATENT BUG THE MOBILE REORDER WOULD HAVE DETONATED:
       display:contents removes the RAIL'S BOX, not the rail ELEMENT — so `.ks-rail .ks-panel-h`
       KEEPS MATCHING below 940. Once the cards interleave into one column, "Your contribution"
       and "Recent activity" would have rendered 2px smaller than "My closet" sitting directly
       beneath them, for no reason a member could ever see. A DESCENDANT SELECTOR SURVIVES
       display:contents. Do not lift this back out. */
    .ks-rail .ks-panel-h { font-size: 20px; }   /* fits one line in a ~290px rail */
  }

  /* Sections inside a column own no spacing of their own — the column's gap does.
     .ks-closet-sec ships margin:36px auto 0 and .ks-panel ships margin-bottom:20px;
     both would double up here. */
  .ks-grid .ks-closet-sec { max-width: none; margin: 0; }
  .ks-grid .ks-panel      { margin-bottom: 0; }

  /* ---------- THE HERO ----------
     ⚠ NOT a banner. §DASH.3's ruling stands: it is the payoff, a held object. It is
     no longer STRANDED, which was the actual complaint — the rail now sits beside it.
     Its own margin is gone; the grid places it. */
  .ks-hero-card { max-width: none; padding: 26px 24px 22px; }
  .ks-hero-card .ks-swaps-ready    { margin: 0 0 16px; }
  .ks-hero-card .ks-cycle-bar-wrap { margin: 18px 0 8px; }
  .ks-hero-card .ks-cycle-line     { margin-top: 8px !important; }

  /* THE ONE ACTION. Centred under the greeting, not inside the credit card.
     Inside the hero it read as a left-aligned pill hanging off the savings inset — it is
     the PAGE's action, not that card's conclusion. width:fit-content + auto side margins
     centre it regardless of what the parent's text-align happens to be. */
  .ks-greet-cta {
    display: block;
    width: fit-content;
    margin: 22px auto 0;
    padding: 15px 42px;
    white-space: nowrap;   /* it was breaking to "Browse the / closet" on a phone */
    max-width: none;       /* S166 - see the note on the row rule below */
  }
/* ---------- SEND-A-BAG (§SB step 7a) ----------
     ⚠ THE ROW EXISTS BECAUSE OF THE AUTO MARGINS. .ks-greet-cta carries `margin:22px auto 0`
     and those AUTO side-margins EAT THE FREE SPACE — drop a second pill beside it and both
     get shoved off-centre. It cannot be faked with inline JS styles. Hence a real rule.
     ⚠ THE ROW DEGRADES SAFELY: with ONE child + justify-content:center a solo CTA centres
     exactly as it does today. Most members never see the button (cancelled / no bag history /
     free bag used) and there is NO GAP where it would have been.
     ⚠ .ks-sb-cta COPIES .ks-rev-cta's LOOK, NOT ITS NAME. Coral OUTLINE — border #F0C9B5,
     transparent bg, #D65A35 text. PROVEN PALETTE-LEGAL. It is NOT a fourth solid coral
     (§DASH.2). Do not make it solid. Do not reuse .ks-rev-* — that is the review card's.
     ⚠ font-family is DELIBERATELY ABSENT, matching .ks-rev-cta: buttons inherit on this site
     (Webflow's normalize sets button{font-family:inherit}). Proven live, 25th session. */
  .ks-cta-row {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 14px;
    margin-top: 22px;      /* the CTA's own 22px, MOVED here — see below */
  }
  .ks-cta-row .ks-greet-cta {
    /* ⚠⚠ max-width:none IS THE #DASH-CTA-CLIP FIX (S166) AND IT IS NOT COSMETIC.
       WEBFLOW SETS max-width:200px ON .ks-greet-cta — read off the live cascade, sheet 1,
       no media query, so it applies at EVERY width. "See The Closet Standard" needs 221px,
       and white-space:nowrap above means it cannot wrap, so 21px of the label rendered
       OUTSIDE the coral pill. Nothing clips it (every ancestor is overflow:visible), so it
       was white text on cream — invisible, and it reads exactly like a clipped button.
       ⚠ THE <=600 BLOCK ALREADY BEAT THIS CAP (42ch, S86) AND THAT IS WHY THE FAULT ONLY
       EVER SHOWED ABOVE 600px. This is that same fix, extended to the band it missed.
       ⚠ (0,2,0) BEATS WEBFLOW'S (0,1,0) ON SPECIFICITY, not on source order. Do not
       "simplify" it down to a bare .ks-greet-cta — that ties Webflow and wins only because
       our <link> happens to come later. AUDIT THE PAGE, NOT THE FILE (§0).
       ⚠ THE <=600 OVERRIDE STILL WINS ON A PHONE: same (0,2,0), later in the file, so
       max-width:42ch survives there. Measured 257px at 602px viewport; do not re-cap it. */
    max-width: none;
    margin: 0;             /* ⚠ (0,2,0) — beats BOTH the base rule and the <=600 override.
                              The row now owns the top margin. Zeroing this is what stops the
                              auto margins from pushing the pair apart. */
  }

  .ks-sb-cta {
    display: inline-block;
    padding: 15px 36px;
    border-radius: 99px;
    border: 1px solid #F0C9B5;
    background: transparent;
    color: #D65A35;
    font-size: 16px;                 /* matches .ks-greet-cta, measured live */
    font-weight: 600;                /* ceiling 600, NEVER 700 */
    white-space: nowrap;
    cursor: pointer;
  }
  .ks-sb-cta:hover { border-color: #D65A35; }
  .ks-sb-cta:focus-visible { outline: 2px solid #1E1A19; outline-offset: 3px; }
  .ks-sb-cta[disabled] { color: #75736E; border-color: #EEEFE3; cursor: default; }

  /* CHECK 1's STOP line. It takes the button's SLOT — two sentences cannot sit in a flex row
     beside a pill. ⚠ CLAUDE'S CALL ON PLACEMENT, NOT JENNIE'S. Reversible. */
  /* ============================================================
     THE BAG-IN-MOTION STOP LINE — A CARD, RULED BY JENNIE, SESSION 53.

     WHAT IT IS: the Check-1 branch of the send-a-bag fork (§SB). A member with a bag
     already out gets this INSTEAD of a button. It is the single most-seen state of that
     feature, because the normal loop keeps a bag in motion almost all the time.

     ⚠⚠ IT MOVES THE GREEN FROM THE TEXT TO THE RULE — A PARTIAL REVERSAL OF SESSION 42,
     RULED KNOWINGLY. Session 42 made this line Quicksand 600 / 20px / #309359 to stop it
     reading as a footnote, and that worked. It still had no SURFACE, so it read as loose
     text floating under the greeting. The card gives it one; the colour stops having to
     carry the message alone. THE MESSAGE DOES NOT GET QUIETER — size and weight are
     unchanged, only the fill goes to ink and the green becomes the rule.

     ⚠ SQUARE ON THE RULED EDGE (radius 0 on the left). A 4px rule inside a rounded corner
     fights the curve and reads as a printing error.
     ⚠ WHITE + 1px #EEEFE3, matching .ks-find's card treatment — no new hex, and #309359 is
     the brand-file green already live on this element since Session 42.

     ⚠⚠ THIS ELEMENT SITS OUTSIDE .ks-hero-card, IN THE GREETING BLOCK, WHERE NOTHING ELSE
     HAS A SURFACE. That makes it the only card in that zone. JUDGE IT IN PLACE, on the
     live page — it may read as deliberately singled out, or as a lone box. It was ruled
     with that named and accepted.

     ⚠ THE ICON IS NEW VOCABULARY FOR THIS AREA — the page carries no icons near the
     greeting today. IT IS DELIBERATELY ONE SELF-CONTAINED BLOCK so it can be dropped
     without touching anything else: delete the ::before rule (and its mobile sibling) and
     set padding-left back to 18px / 14px. The card carries the intent without it.
     ⚠ INLINE SVG, NOT AN ICON FONT — no new dependency, no network request, and NO JS
     CHANGE, so this whole edit stays a CSS-only diff with no dashboard-tool.js bump.
     ⚠ POSITIONED, NOT FLEXED, ON PURPOSE: .ks-sb-stop's contents are written by
     paintBagButton(). A flex container would turn any future second child into a second
     flex item and reflow the card silently. Absolute positioning cannot be surprised by
     the markup.
     ⚠ THE ICON IS DECORATIVE — the sentence says everything. It is a background image on
     a pseudo-element, so it is invisible to a screen reader by construction. Correct;
     do not "fix" it by giving it alt text or a content string.

     ⚠⚠ THE 17px MOBILE OVERRIDE LIVES IN @media (max-width:600px) AND MOVED WITH THIS
     RULE — the padding and the icon offsets are down there beside it. CHANGE ONE, CHECK
     THE OTHER.
     ============================================================ */
  .ks-sb-stop {
    position: relative;
    font-family: 'Quicksand', sans-serif;
    font-weight: 600;
    font-size: 20px;
    line-height: 1.4;
    color: #FFFFFF;
    text-align: left;
    max-width: 42ch;
    margin: 14px auto 0;
    padding: 14px 18px 14px 47px;
    background: #256F43;
    border: 1px solid #256F43;
    border-radius: 14px;
  }
  .ks-sb-stop::before {
    content: "";
    position: absolute;
    left: 18px;
    top: 17px;
    width: 20px;
    height: 20px;
    background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23FFFFFF' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M7 17m-2 0a2 2 0 1 0 4 0a2 2 0 1 0 -4 0'/%3E%3Cpath d='M17 17m-2 0a2 2 0 1 0 4 0a2 2 0 1 0 -4 0'/%3E%3Cpath d='M5 17h-2v-11a1 1 0 0 1 1 -1h9v12m-4 0h6m4 0h2v-6h-8m0 -5h5l3 5'/%3E%3C/svg%3E") center / contain no-repeat;
  }
  /* ---------- IN-CARD SECTION HEADINGS ----------
     ⚠⚠ THIS BASE RULE HAS BEEN LOST TWICE, FROM OPPOSITE DIRECTIONS. It was written a
     session before the JS that emits it (so it matched nothing), and then deleted by a
     style-box rebuild that sliced at the wrong marker (so the headings silently fell back
     to Quicksand at body size). Both times it rendered "fine" and both times it was wrong.
     A THIRD LOSS IS A PATTERN, NOT AN ACCIDENT.
     .ks-panel-h IS EMITTED BY dashboard-tool.js — 5 sites as of S163:
     My closet, Recent activity (x3 branches), and How credits work.
     (⚠ IT WAS 6. "Your contribution" carried the sixth and its heading was RETIRED at
     S163 when the sent-in number moved to .ks-look-h in the main column. The rail card it
     left behind is deliberately HEADLESS — a replacement heading is HER copy, not ours.)
     (The review card and the empty states carry .ks-rev-h / .ks-empty-h, NOT this class.)
     A CSS RULE AND THE JS THAT EMITS ITS CLASS ARE ONE ARTIFACT SPLIT ACROSS TWO FIELDS.

     ⚠⚠ QUICKSAND 600, 21st session (§DASH.2 / §DASH.13). It was Instrument Serif 26px.
     The serif now survives on EXACTLY TWO ELEMENTS — .ks-greet-headline and .ks-bank-label
     — plus the NUMERALS (.ks-imp-n / .ks-hcw-n / the coins), which are a deliberate,
     Jennie-vetoed exception. THIS IS NOT ONE OF THEM. Do not "restore" the serif here.
     ⚠ 22px, ruled by Jennie. Quicksand 600 is optically heavier than Instrument Serif 400
     at the same size, which is why it does not stay at 26.
     ⚠ CEILING IS 600. NEVER 700. */
  .ks-panel-h {
    font-family: 'Quicksand', sans-serif;
    font-weight: 600;
    font-size: 22px;
    line-height: 1.2;
    color: #1E1A19;
    text-align: left;
    margin: 0 0 20px;          /* was 16 — the heading was crowding the card below it */
  }

  /* ---------- THE UTILITY ROW ----------
     Account chrome, top-right of the PAGE (not the site navbar — that is a global
     Webflow element and would need member-gating on every public surface).
         Active · Manage membership          ⚙ Account & Settings ▾
     ⚠ THE MEMBERSHIP CARD IS GONE FROM THE PAGE BUT NOT FROM THE DOM. It is hidden,
     because .ks-membership-plan still lives inside it and paint() still writes to it,
     and because .ks-section--membership is named by the data-ks-ready gate AND by
     setCTA's manage-branch scroll target. Deleting it breaks three things silently. */
  .ks-mem-hidden { display: none; }

  .ks-util {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    gap: 22px;
    /* ⚠ HEADER CLEARANCE LIVES HERE, ON THE ROW — S214. The chip needed lifting off the sticky
       header; putting it on the chip dropped the chip below its row-mates. margin-top on the
       whole row lifts all three together and keeps them level. */
    margin-top: 18px;
    margin-bottom: 4px;
  }
  .ks-util-mem { display: flex; align-items: center; gap: 7px; font-size: 14px; }
  .ks-util-sep { color: #75736E; }

  /* ⚠ STATUS ONLY RENDERS WHEN IT IS NOT "ACTIVE", AND THAT IS A RULING, NOT A HIDE.
     A green "Active" beside the greeting is pure noise — the plan chip two inches away
     already says she has a live plan. The word only carries information when it says
     CANCELLED or PAUSED, and the script sets data-tone="off" on exactly those two.
     ⚠ IT FAILS SAFE: before paint() runs there is no data-tone at all, so the Webflow
     placeholder stays hidden rather than flashing a status nobody wrote.
     ⚠ ONE-LINE REVERSAL if a status is ever wanted at rest: delete these two rules. */
  .ks-util .ks-membership-status { margin-top: 0; font-size: 14px; }
  .ks-util .ks-membership-status:not([data-tone="off"]) { display: none; }
  .ks-util-mem:has(.ks-membership-status:not([data-tone="off"])) .ks-util-sep { display: none; }

  /* ⚠ MANAGE MEMBERSHIP IS THE CANCEL PATH. This strips the solid coral pill down to a
     plain coral text link. CA ARL §17602(d) permits a "direct link or button", and this
     link is now at the TOP of the page instead of the bottom — more prominent, not less.
     ⚠ SHAHIN RULES ON LINK-VS-BUTTON. If he wants the button back it is THIS RULE ONLY —
     the position and the prominence do not change. Do not move the element to do it. */
  .ks-util .ks-membership-manage,
  .ks-util .ks-membership-manage:link,
  .ks-util .ks-membership-manage:visited {
    display: inline;
    background: none;
    border: none;
    padding: 0;
    margin: 0;
    border-radius: 0;
    font-size: 14px;
    font-weight: 600;
    color: #D65A35;
    text-decoration: none;
  }
  .ks-util .ks-membership-manage:hover {
    background: none;
    color: #BE4C2E;
    text-decoration: none;
  }

  /* Account & Settings loses the coral-light pill and becomes a peer of the link beside
     it. It keeps its gear ::before and chevron ::after — those are on the base rule. */
  .ks-util .ks-account-toggle,
  .ks-util .ks-account-toggle:link,
  .ks-util .ks-account-toggle:visited {
    margin: 0;
    padding: 0;
    background: none;
    border: none;
    border-radius: 0;
    font-size: 14px;
  }
  .ks-util .ks-account-toggle:hover { color: #BE4C2E; text-decoration: none; }
  .ks-util .ks-account-toggle:hover::after { color: #BE4C2E; }

  /* The gear glyph goes. ⚠ content:none, not display:none — the ::after chevron is a
     SEPARATE pseudo-element and must survive; it is the only thing telling a member this
     is a disclosure and not a link. */
  .ks-util .ks-account-toggle::before { content: none; }

  /* ---------- THE CLOSET GRID ----------
     3 columns in a ~590px main column. The old 4-col rule was written for a 900px
     card that no longer exists. */
  @media (min-width: 940px) {
    .ks-closet-grid { grid-template-columns: repeat(3, 1fr); }

    /* Accordion rows fill the panel they live in — both were authored at 420. */
    .ks-acc-head,
    .ks-acc-body { max-width: none; }

    .ks-dash-wrap { max-width: 900px; }
    /* ⚠ .ks-account-panel is NOT widened here any more — it is a 360px dropdown. */
  }

  /* ---------- ACCOUNT & SETTINGS: A REAL DROPDOWN ----------
     Anchored to its own button, not dumped in the page flow.
     ⚠ .ks-util-acct is position:relative. Without it the absolute panel hangs off the
     page, not the button.
     ⚠ max-height + overflow-y: the panel holds five sections and a form. It must be able
     to scroll rather than run off the bottom of the viewport. This does NOT fight the
     accordion — accResize measures scrollHeight on .ks-acc-body inside, which is
     unaffected by an ancestor scroll container. */
  .ks-util-acct { position: relative; }

  .ks-account-panel {
    position: absolute;
    top: calc(100% + 12px);
    right: 0;
    z-index: 60;
    width: 360px;                      /* was 420 — the accordion rows left a canyon
                                          between the label and the chevron. The address
                                          form still fits: 360 - 44 padding = 316px. */
    max-width: calc(100vw - 40px);
    max-height: 72vh;
    overflow-y: auto;
    margin: 0;
    text-align: left;
  }
  /* .is-open already flips display:none -> block (authored above). The card treatment is
     the panel's own: white, cream border, radius 18. A dropdown gets a SHADOW because it
     floats above the page — that is depth, not status, so it does not break §DASH.8's
     elevated-is-the-payoff rule. */
  .ks-account-panel.is-open { box-shadow: 0 18px 40px -16px #C9C7BC; }

  /* Below the breakpoint a 360px floating card is worse than an inline one. */
  @media (max-width: 939px) {
    .ks-account-panel {
      position: static;
      width: auto;
      max-width: none;
      max-height: none;
      overflow: visible;
      margin-top: 12px;
    }
  }

  /* Reactivate scrolls a cancelled member to the manage link. A scroll that lands on
     nothing visible is a scroll that failed. Flag it for two seconds so she can see
     WHERE she was taken. Coral-light tint, no new hex. */
  .ks-membership-manage.is-flagged {
    background: #F7E4D9;
    border-radius: 6px;
    box-shadow: 0 0 0 4px #F7E4D9;
  }

  /* ---------- BREATHING ROOM AT THE FOOT ----------
     The last cards were butting straight into the site footer. */
  .ks-grid { margin-bottom: 64px; }

  /* MOBILE PASS (§DASH.12). Four bugs, none visible at 900px — read it on a phone.
     ⚠ THE LESSON: A DESKTOP-FIRST RULE THAT REMOVES SPACING (margin:0, because a grid gap
     will provide it) IS A TRAP UNLESS THE GAP EXISTS AT EVERY WIDTH THE REMOVAL DOES. */
  @media (max-width: 939px) {
    .ks-dash-wrap { padding-left: 16px; padding-right: 16px; }

    /* The stack owns its own spacing again.
       ⚠ margin-top was 22 — tightened to 14 as one of the four coins-higher levers. */
    .ks-grid { display: flex; flex-direction: column; gap: 16px; margin-top: 14px; margin-bottom: 44px; }

    /* ============================================================
       ⚠⚠ THE MOBILE REORDER — 21st session. THE ONE RULE THAT MAKES IT POSSIBLE.

       RULED ORDER (Jennie): credit bank -> your contribution -> recent activity ->
       review prompt -> my closet -> how credits work.

       `order` ALONE CANNOT DO THIS, AND THAT IS THE WHOLE TRAP. Below 940 the grid's
       children are TWO WRAPPERS (.ks-main, .ks-rail) — `order` can only shuffle those two
       boxes, never interleave their contents. And this sequence REQUIRES interleaving:
       Recent activity lives in the RAIL and must sit ABOVE My closet, which lives in MAIN.

       `display: contents` DISSOLVES THE WRAPPER BOXES. The six cards become direct flex
       children of .ks-grid, and `order` then works PER CARD. No JS. No DOM move. No hook
       touched. The columns still exist in the DOM — only their boxes are gone.

       ⚠ THE GAP SURVIVES: .ks-grid is the flex container and gap applies between ITS items,
       which are now the six cards themselves. The .ks-col gap it replaces is redundant here.
       ⚠ THE TRAP IT SETS IN RETURN: a descendant selector like `.ks-rail .ks-panel-h` KEEPS
       MATCHING through display:contents — the element is still in the rail, it just has no
       box. That override is therefore scoped to >=940 (see the grid block above). ANY FUTURE
       RULE SCOPED TO .ks-main OR .ks-rail MUST ASK ITSELF THE SAME QUESTION.
       ============================================================ */
    .ks-col { display: contents; }

    /* ⚠ REORDERED S85, HER RULING: recent activity and my closet go to the BOTTOM. Both
       are empty for a member's first weeks and were holding prime slots. ⚠ THIS IS THE
       MOBILE ORDER ONLY. Above 940px the columns are real and order is DOM order, which is
       paint()'s CALL ORDER in dashboard-tool.js — A SEPARATE FILE AND A SEPARATE PIN BUMP.
       ⚠⚠ THE OLD "paintImpact MUST STAY ABOVE paintActivity" RULE IS DEAD AS OF S163 AND
       ITS REASON WENT WITH IT. It was the SUMMARY of that feed, and the line it summarised
       — the sent-in count — has LEFT for .ks-sec-look. What is left in that card is
       credits earned and Member since, which summarise nothing, so it now sits LAST. */
    .ks-hero-card    { order: 1; }   /* credit bank */
    .ks-sec-look     { order: 2; }   /* look what you've done — S163. It takes the slot
                                        contribution used to hold, because the two numbers
                                        a member came to read now live in it. */
    .ks-sec-review   { order: 3; }   /* review prompt */
    .ks-sec-activity { order: 4; }   /* recent activity — moved down S85 */
    .ks-sec-closet   { order: 5; }   /* my closet — moved down S85 */
    /* ⚠ HOW CREDITS WORK IS LAST ON MOBILE — her ruling S214: reference copy a member reads
       once belongs at the very bottom. order:9 keeps it after activity/closet and after the
       retired impact block, no matter what re-numbers above it. */
    .ks-sec-hcw      { order: 9; }   /* how credits work — S214, forced to the very bottom */
    .ks-sec-impact   { order: 7; }   /* credits earned + Member since — S163. Her ruling
                                        put it at the BOTTOM OF THE RAIL, and there is no
                                        rail below 940, so it goes last here too.
                                        CLAUDE'S CALL, REVERSIBLE. */

    /* ⚠ hero padding-top was 22 — tightened to 16, a coins-higher lever. */
    .ks-panel     { padding: 20px 18px; border-radius: 18px; }
    .ks-hero-card { padding: 16px 18px 18px; border-radius: 18px; }

    /* The utility row: PLAN CHIP CENTRED ALONE ON LINE ONE, the two links side by side
       beneath it. HER RULING, S89. Built S91.
       ⚠⚠ THIS WAS RECORDED IN TWO PLACES AS "STRUCTURALLY IMPOSSIBLE" AND IT WAS A
       FLEXBOX LIMIT, NOT A STRUCTURAL ONE. The old reading was right about the mechanism
       and wrong about the conclusion: in FLEX the only way to give the chip a line of its
       own is flex-basis:100%, WHICH ALSO STRETCHES IT — a coral pill becomes a full-width
       band. So the panel was handed the full-width cell instead and the toggle was dragged
       down with it. THE TWO-LINE LAYOUT WAS NEVER A DECISION.
       ✅ GRID SPANS A ROW WITHOUT STRETCHING THE ITEM. That is the entire fix.
       ⚠⚠ display:contents REMOVES .ks-util-acct's BOX, NOT THE ELEMENT. The toggle and the
       panel become grid items of .ks-util WHILE STAYING SIBLINGS IN THE DOM — not a DOM
       move, not a float (floating on mobile is still rejected, §DASH.12). The panel then
       spans the full container, so it ends up WIDER than it was, not narrower. The old
       collapse warning is DEFUSED, not worked around.
       ⚠ THIS BLOCK IS <=939px, NOT <=600px, AND THAT IS WHERE THESE RULES HAVE ALWAYS
       LIVED. The doc recorded them as <=600 for several sessions; the line number was
       right and the block was wrong. 601-939px ran the identical two-line layout and was
       logged as a separate suspected defect. IT WAS THE SAME RULES. Observed at 700px
       S91, not derived.
       ⚠ .ks-util-acct's position:relative is authored at TOP LEVEL (not in the 940 block),
       so display:contents makes it inert HERE — and it does not need to bite, because
       below 940 the panel is already position:static. THE >=940 DROPDOWN ANCHOR CANNOT BE
       REACHED BY THIS BLOCK AT ALL.
       ⚠ TIGHTENING THE ROW WAS OFFERED AS A FIFTH COINS-HIGHER LEVER (~14px) AND JENNIE
       DECLINED — the row keeps its breathing room. Do not re-propose it. */
    .ks-util { display: grid; grid-template-columns: 1fr 1fr; align-items: center;
               gap: 10px 18px; margin-bottom: 12px; }
    .ks-util-acct      { display: contents; }
    .ks-plan-chip      { grid-column: 1 / -1; justify-self: center; }
    .ks-util-mem       { grid-column: 1; justify-self: end; }
    .ks-account-toggle { grid-column: 2; justify-self: start; }
    .ks-account-panel  { grid-column: 1 / -1; width: 100%; }

    .ks-greet-cta { padding: 15px 36px; }
  }

  /* ============================================================
     COINS HIGHER ON THE PHONE — 21st session, ruled by Jennie.
     THE COMPLAINT: the credit bank — the thing she opens this page to see — sat below
     the fold on a phone. FOUR LEVERS, NONE SUFFICIENT ALONE, ~33px total:
       1. greeting 40 -> 30px                    (here)
       2. CTA top margin 22 -> 14px              (here)
       3. .ks-grid margin-top 22 -> 14px         (in the 939 block above)
       4. hero padding-top 22 -> 16px            (in the 939 block above)
     ⚠ A FIFTH LEVER — tightening the utility row — WAS OFFERED AND DECLINED. It STAYS
     declined. ⚠ ITS OLD JUSTIFICATION IS DEAD AS OF S91: "the row cannot collapse to one
     line anyway" was the flexbox limit talking. The row is TWO LINES BY HER RULING now,
     not by a constraint — see the .ks-util note above.
     ⚠ STICKY IS REJECTED, BOTH THE RAIL AND THE UTILITY ROW. The row is tightened IN
     FLOW or not at all.
     ============================================================ */
    /* Instrument Serif ships ONE weight (400) — lightness comes from SIZE, not weight.
       At 56px this was breaking "Good morning," / "Jennie" across two lines. It was then
       40px; 30px is lever 1 of the coins-higher pass. ⚠ IT IS ONE OF THE TWO SURVIVING
       SERIF ELEMENTS (§DASH.2) — the size changes, the family does not. */
@media (max-width: 600px) {
/* ⚠⚠ COMBO TRAP — THIS RULE SHIPPED AS ONE CLASS AND NEVER FIRED.
       Webflow wears .ks-card-value on this H2 (a combo-BASE — §DASH.3 names it and
       says it is not a hook). Webflow compiles that to `.ks-greet-headline.ks-card-value`
       = specificity (0,2,0). A single-class rule is (0,1,0) and LOSES — at every width,
       regardless of source order. A MEDIA QUERY ADDS NO SPECIFICITY.
       MEASURED 2026-07-13, not derived: the live headline is 56px (Webflow's), two lines,
       not the 30px this line has "set" for sessions. LEVER 1 OF THE COINS-HIGHER PASS HAS
       NEVER ONCE BEEN LIVE. Fixing it recovers 78px (112 -> 34).
       ⚠ THE FILE DOES NOT OWN THIS ELEMENT'S SIZE. Nor .ks-greet-cta's background
       (#E54F25 — off-palette, still unruled). AUDIT THE PAGE, NOT THE FILE.
       ⚠ .ks-greet-sub is ALSO a combo (.ks-card-sub) and is FINE — a combo only bites
       when Webflow sets the SAME property. Do not "fix" it. */
    .ks-greet-headline,
    .ks-greet-headline.ks-card-value { font-size: 30px; line-height: 1.12; }
    .ks-greet-sub,
    .ks-greet-sub.ks-card-sub { font-size: 22px; margin-top: 8px; }
    /* ⚠ THE SUBHEADING TAKES ITS OWN SIZE HERE, exactly as the base sub does two lines
       up. 22px against a 30px headline — the same subheading STEP the desktop pair has at
       26px, not a second decision. The family, weight and colour ride down from the base
       rule untouched. ⚠ THE CLASS IS STILL NAMED ks-greet-accent AND THAT NAME IS NOW
       HISTORICAL — it was a blue banner for one day. Renaming it costs a dashboard-tool.js
       bump (paintGreeting emits it), so it stays. DO NOT read "accent" as "coloured". */
    /* S89 — the 22px moved onto .ks-greet-sub two lines up (serif on every state now).
       The .ks-greet-accent override that lived here is DELETED, not commented out. */
    /* ⚠ THE CARD'S PADDING AND ITS ICON OFFSETS TRAVEL WITH THIS SIZE (Session 54).
       Dropping the font alone would leave desktop padding around phone-sized text. */
    .ks-sb-stop        { font-size: 17px; padding: 12px 14px 12px 42px; }
    .ks-sb-stop::before { left: 14px; top: 14px; width: 18px; height: 18px; }
    .ks-greet-cta      { margin-top: 14px; }   /* lever 2 — was 22 (inherited from the base rule) */
/* ⚠ THE PILLS STACK ON A PHONE. Both are white-space:nowrap and each measures 200px
       against ~375px of usable width — they CANNOT share a line, and tightening them enough
       to fit would gut the ONE ACTION on a 320px screen (13px of padding per side).
       ⚠ THE ~60px THIS COSTS IS ALREADY PAID FOR: fixing lever 1 (the combo trap) recovered
       78px. The coins end up HIGHER than before the button existed. Do not "reclaim" this
       by shrinking .ks-greet-cta. */
    .ks-cta-row   { margin-top: 18px; flex-direction: column; gap: 10px; }
    /* THE ACTION MATCHES THE BANDS - S86. At <=600 the pills already stack, so the
       200px cap bought nothing and left the ONE ACTION at half the width of the message
       above it and the status below it. Same width, different SHAPE (50px pill vs 14px
       band) is what says "this one is a button". DO NOT unify the radius.
       max-width is 42ch to match .ks-greet-sub / .ks-sb-stop, and font-size comes up to
       17px so 42ch measures the SAME there as it does on them.
       (0,2,0) - it must beat the base rule's width:fit-content and the 200px cap. */
    /* ⚠⚠ S282, HERS — THIS REVERSES THE S86 "MATCH THE BANDS" RULING ABOVE, KNOWINGLY.
       The pill now hugs its label instead of running the full 42ch. ⚠ max-width STAYS
       EXPLICITLY SET and this selector STAYS (0,2,0): it is the #DASH-CTA-CLIP fix beating
       Webflow's own max-width:200px on .ks-greet-cta, and simplifying it to one class is a
       tie that loses silently. ⚠ white-space:nowrap on the base rule is load-bearing — the
       label once broke to "Browse the / closet". ⚠ BOTH PILLS MOVE OR NEITHER.
       ⚠ THE PADDING IS SET HERE, NOT IN THE 939 BLOCK, so 601-939 is untouched. */
    .ks-cta-row .ks-greet-cta,
    .ks-cta-row .ks-sb-cta { width: fit-content; max-width: 100%; font-size: 16px; padding: 13px 26px; }
    .ks-sb-stop        { margin-top: 16px; }
    .ks-panel-h        { font-size: 20px; }
    .ks-rev-h          { font-size: 20px; }
    .ks-bank-label     { font-size: 26px; }    /* ⚠ NO !important — nothing to fight now */
    .ks-imp-n          { font-size: 30px; }
    /* HER PHONE SPEC, S163: 24 / 32 / 12 / 16. Side by side at BOTH widths — the
       stacked-on-mobile version was built and REJECTED. Do not restack it. */
    .ks-look-h         { font-size: 34px; }
    .ks-look-n         { font-size: 30px; }
    .ks-look-l         { font-size: 12px; }
    .ks-look-note      { font-size: 17px; }
  }
