/* Generated from Design/directions/build.py by Web/theme/tools/port.py.
   Edit the prototype and re-run, or adopt this file and delete the
   tool — but do not edit both. */

*,*::before,*::after{box-sizing:border-box}
body{margin:0}
img{max-width:100%;display:block}
a{color:inherit}
h1,h2,h3,p,ul,figure,blockquote{margin:0}
ul{padding:0;list-style:none}
.ribbon{position:sticky;top:0;z-index:99;display:flex;gap:18px;align-items:baseline;
  flex-wrap:wrap;padding:9px 22px;background:#1d1f1e;color:#fff;
  font:500 12px/1.4 ui-monospace,SFMono-Regular,Menlo,monospace}
.ribbon span{opacity:.62}
.ribbon .type{margin-left:auto;opacity:.45}
.slot{position:relative;display:flex;align-items:center;justify-content:center;
  text-align:center;overflow:hidden}
.slot span{font:400 11px/1.5 ui-monospace,Menlo,monospace;letter-spacing:.1em;
  text-transform:uppercase;opacity:.5}
.slot em{display:block;font-style:normal;opacity:.6;margin-top:3px}
.nav a{white-space:nowrap}
.ratio-16x9{aspect-ratio:16/9}
/* Added 0.4.9 with the home grid's move to 3:2. `.ratio-16x9` stays because
   svaflo_slot() takes the ratio by name and nothing should break if a name that
   is no longer used is passed; it is simply unused now. */
.ratio-3x2{aspect-ratio:3/2}
.ratio-4x5{aspect-ratio:4/5}
.ratio-1x1{aspect-ratio:1/1}
@media (prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}

:root{
  --paper:#FBF8F2; --paper-2:#F4EFE5; --ink:#2C302C; --soft:#5C635B;
  --sage:#3E5D4E; --terracotta:#B0512C; --line:rgba(44,48,44,.13);
}

/* ── THE TYPE SCALE, DECLARED IN x-HEIGHT ─────────────────────────────────────
   0.4.42 on the phone, extended to every width in 0.4.43.

   ⚠ THE SITE HAS TWO TYPEFACES AND HAD NO RULE CONNECTING THEM. Measured over
   every text element on all eleven pages:

       Mulish     x-height = 0.502 × font-size
       Cormorant  x-height = 0.388 × font-size
       → Cormorant must be set 1.29× larger to READ the same size

   Without that number every size was picked in isolation and the hierarchy came
   out accidental. On About it came out INVERTED, and — measured at five widths,
   which is the part 0.4.42 got wrong by only checking 1280 — at every width:

       width   aside   body    lead    opener
        761     8.27    8.27    6.56    7.72     ← lead AND opener lose to body
        900     8.27    8.27    6.56    7.99     ← same
       1024     8.27    8.27    6.92    9.09
       1280     8.27    8.27    8.11   10.81     ← the one width that looked mild

   The grey supporting copy was the largest body text on the page at every
   width, and the ink-coloured belief statement the smallest.

   THE TOKENS BELOW ARE THE FIX, and they are tokens so the scale can be tuned
   or reverted in one place — RJ: *"we can revert if it doesn't work."* The
   phone block near the end of this stylesheet overrides all four.

   ⚠ THE RATIO IS THE PART TO KEEP EVEN IF THE NUMBERS CHANGE. Any future
   pairing of these two faces must clear 1.29× or it reads wrong whatever the
   stylesheet says. Re-measure if either face is replaced — the design system
   is reopened and Cormorant may not survive it. */
/* ── TWO BODY TIERS, NOT ELEVEN — 0.4.91, 4 September ─────────────────────────
   `Design/STUDY-body-size-4-Sep.md`, approved by RJ on 4 September.

   ⚠ THE FAULT THIS FIXES IS THE ONE THIS FILE ALREADY DIAGNOSED FOR HEADINGS.
   audience.css records it in its own words — *"seven display sizes inside a
   six-pixel band… that is why it read as flat"* — and fixed it in 0.4.18. The
   body copy had the same fault in a NARROWER band and nobody had looked,
   because body copy is not what anyone inspects when they inspect a type scale.

   Measured over every p, li, dd and blockquote of 45+ characters on all
   thirteen pages, 384 blocks at 1440px: TWENTY-TWO size-and-face combinations,
   NINETEEN x-height tiers, and ELEVEN of them inside a 2.1px band holding 366
   of the blocks. Two tenths of a pixel apart in places. Nothing in that band is
   distinguishable to a reader. It did not read as a scale because it was not
   one — it was one size applied inconsistently.

   The two tiers below are the two LARGEST groups already on the site. Nothing
   is invented; nine sizes are deleted. The step between them is 12%, which is
   perceptible where 0.2px is not.

   ⚠ DECLARED IN x-HEIGHT, WHICH IS WHY THE PIXELS LOOK UNRELATED. Cormorant
   must be set 1.29× larger than Mulish to read the same (0.386 vs 0.5023 of
   font-size, re-measured on the live site 4 September, not taken from the
   record). 17 × 1.29 = 22; 15 × 1.29 = 19.5. If either face is replaced the
   TIERS stay at 8.5 and 7.5 and the pixels are recalculated from the new
   faces' own ratios — that is the whole reason the scale is in x-height.

   ⚠⚠ 1.29 IS ALSO THE Mulish `ch`-TO-CHARACTER RATIO AND THE TWO ARE
   UNRELATED. See the measure note further down this file before assuming one
   explains the other. They collide by coincidence and it is a trap.

   ⚠ `--t-aside` IS RETIRED AND KEPT AS AN ALIAS. 13.5px Mulish (x 6.78) was
   the site's smallest body size and it is now the detail tier. The alias means
   about.css's one remaining use keeps working; do not give it a value of its
   own again without re-reading the study. */
:root{
  --t-detail:15px;                   /* Mulish    → x 7.53 */
  --t-detail-c:19.5px;               /* Cormorant → x 7.53 */
  --t-body:17px;                     /* Mulish    → x 8.54  — the anchor */
  --t-body-c:22px;                   /* Cormorant → x 8.49 */
  --t-aside:var(--t-detail);         /* retired 0.4.91 — was 13.5px, x 6.78 */
  --t-lead:clamp(23px,1.9vw,25px);   /* Cormorant → x 8.92 … 9.70  — display */
  --t-open:clamp(26px,2.3vw,28px);   /* Cormorant → x 10.09 … 10.86 — display */
}
body{background:var(--paper);color:var(--ink);
  font:300 17px/1.85 Mulish,system-ui,sans-serif}
.wrap{max-width:1180px;margin:0 auto;padding:0 clamp(24px,6vw,84px)}
h1,h2{font-family:'Cormorant Garamond',Georgia,serif;font-weight:300;
  letter-spacing:-.008em;line-height:1.08}
h1{font-size:clamp(52px,7vw,104px)}
h2{font-size:clamp(34px,4.4vw,58px)}
h3{font-family:'Cormorant Garamond',serif;font-weight:400;font-size:27px;line-height:1.2}
/* Eyebrow rules live at the END of this stylesheet, not here — see the note
   down there. Leaving this comment so nobody adds them back at the top. */
p{max-width:34rem}

/* ── THE MEASURE, AND THE `ch` TRAP — 0.4.91 ──────────────────────────────────
   163 of 384 desktop body blocks — 42% — were set beyond 85 characters a line.
   Comfortable is 45–75. The cap above has existed all along and had simply
   never been extended past `p`: `dd`, `li` and the two `person-lead` variants
   all computed to `max-width:none`.

   ⚠⚠ `ch` IS NOT A CHARACTER. It is the advance width of "0", which in both of
   these faces is wider than the average letter. Measured on the live site:

       Mulish              1ch = 1.29 characters
       Cormorant Garamond  1ch = 1.20 characters

   So a rule reading `max-width:68ch` sets Mulish to EIGHTY-EIGHT characters,
   not sixty-eight. That is how `.aitem-main` sat at 74ch — read as a safe cap
   by whoever wrote it — and rendered at 92. The study that produced this work
   recommended "about 68ch" meaning 68 CHARACTERS, and shipping that number as
   a `ch` value would have left the page wider than the 85 it set out to fix.

   ⚠ AND 1.29 IS ALSO THE Cormorant-to-Mulish x-HEIGHT FACTOR, WHICH IS A
   COINCIDENCE. Two unrelated ratios, the same number, in the same stylesheet.
   Do not use one to derive the other.

   THE TARGET IS 72 CHARACTERS, which is 56ch in Mulish and 60ch in Cormorant.
   Both were already in the file — `.qa dd` and `.clients .person-note` at 56ch,
   `.session .person-lead` at 62ch — so this adopts the house value rather than
   inventing one. Capped in 0.4.91: `.outcomes dd`, `.facts dd`,
   `.arg-body .person-lead`, `.aitem-main` (74ch → 56ch).

   ⚠ A max-width cannot make a block narrower than its column, so none of this
   touches a phone, where 0 blocks were over 85 to begin with. That is exactly
   why it survived: every measure check this project has run was run narrow. */

/* ── THE STICKY MASTHEAD ──────────────────────────────────────────────────────
   RJ, 26 August: like flibbrconsulting.com. That header was read rather than
   guessed at — `position:sticky; top:0; z-index:40`, an OPAQUE background, a
   1px hairline underneath, no shadow, no blur, and no change of height on
   scroll. This is the same, in this palette.

   THE BACKGROUND MUST BE OPAQUE. The page alternates two grounds, so a
   translucent header would show whichever band happens to be passing under it
   and change colour as you scroll. `--paper` matches the ground the hero sits
   on, which is why nothing appears to change at the top of the page.

   THE HAIRLINE IS NOT THERE AT REST, and that is deliberate. Flibbr's sits on
   white and can afford a permanent rule; the home page is LOCKED and a line
   under the masthead is a change to its resting composition. `.is-stuck` is
   added by assets/js/main.js once the page has scrolled, so the header is
   exactly as locked until it is actually overlapping something. With
   JavaScript off there is no line and the header still sticks. */
.site-header{position:sticky;top:0;z-index:40;background:var(--paper);
  border-bottom:1px solid transparent}
.site-header.is-stuck{border-bottom-color:var(--line)}

/* ⚠ THE WORDPRESS ADMIN BAR. It is `position:fixed` and 32px tall, and
   WordPress pushes the page down with `html{margin-top:32px}` — which moves
   the document, not the viewport. A sticky element at `top:0` therefore sticks
   UNDERNEATH it and loses its top 32px. Invisible to every visitor and
   permanently wrong for RJ, who is the one person always logged in. */
/* ── AND IT COMPACTS ON SCROLL ────────────────────────────────────────────────
   RJ chose this over flibbrconsulting.com's fixed-height header, having seen
   both at the same scroll position.

   The number behind it: the masthead is 153px on a 900px screen — fifteen per
   cent of it, held permanently, on a page whose first principle is that space
   is the subject. At full height it cut the section heading beneath it in
   half. Compacted it is 78px and the heading clears.

   The wordmark drops 26px → 22px with the padding, so the bar tightens as one
   thing rather than the type floating in a thinner band.

   ⚠ SCOPED ABOVE THE PHONE BREAKPOINT, and it has to be. The phone block at
   the end of this stylesheet sets `.site-header .wrap{padding-block:24px 20px}`
   — but the rule below is more specific, so without the media query it would
   beat that and squeeze a header which is already only 84px and needs none of
   this. Seventh equal-specificity trap on this project; the fix is the same
   every time, which is to say where a rule applies rather than to hope about
   the order it lands in.

   The transition is disabled for anyone who asks for reduced motion — the
   blanket rule near the top of this stylesheet already covers it. */
@media (min-width:761px){
  .site-header .wrap{transition:padding .22s ease}
  .site-header.is-stuck .wrap{padding-block:18px}
  /* ⚠ 36, NOT THE 34 THE OLD RATIO WOULD GIVE. The text shrank 26 → 22 when
     stuck, which on the lockup is 40 → 34. **34px puts the ink at 96px wide and
     §11's minimum for the full lockup is 100.** 36px is the smallest size that
     stays legal, at 102px. The shrink is subtler than it was; the floor is not
     negotiable. */
  .site-header.is-stuck .brand img{height:36px}
}

.admin-bar .site-header{top:32px}
/* …and the bar is 46px on a tablet, and stops being fixed at all below 600px,
   where it scrolls away with the page and the offset must go back to zero.
   Both numbers are WordPress's, not ours. These sit here rather than in the
   phone block at the end of the file because that block never touches
   `.admin-bar` and cannot conflict with them. */
@media (max-width:782px){.admin-bar .site-header{top:46px}}
@media (max-width:600px){.admin-bar .site-header{top:0}}

/* ⚠ `center`, NOT `baseline`, AND THE CHANGE IS FORCED — 0.4.97. The brand was
   text and baseline-aligned with the nav. It is now an <img>, and a replaced
   element baselines on its BOTTOM EDGE — so `baseline` would have hung the
   whole navigation off the spiral's tail. Centring is also what RJ chose for
   the logo's position, and it lands within 1.8px of what the Logo Master
   Document's own browser mockup does: measured there, the wordmark baseline
   sits 2px from the nav baseline on a 59px lockup. */
.site-header .wrap{display:flex;align-items:center;gap:40px;padding:52px 0}
/* ⚠ THE LOCKUP IS SIZED BY ITS WORDMARK, NOT BY ITS BOX, AND THAT IS WHY 40.
   The spiral is taller than the letters: measured on the master, the wordmark's
   cap height is only **0.433 of the lockup's file height**. Cormorant at the
   old 26px gave a 16px cap, so matching it exactly would need 37px — and 34px,
   which was proposed first by eye, would have shipped a SMALLER wordmark than
   the text it replaced AND a 96px ink width, under §11's 100px minimum.
   40px gives a 17.3px cap and 113px of ink. */
.brand{text-decoration:none;display:inline-flex;align-items:center;line-height:0}
.brand img{height:40px;width:auto;display:block}
.brand i{font-family:'Cormorant Garamond',serif;font-style:italic;font-size:15px;
  color:var(--soft);margin-left:10px;line-height:1.2}
.nav{margin-left:auto;display:flex;gap:30px;font-size:14px}
.nav a{text-decoration:none;color:var(--soft);padding-bottom:3px;
  border-bottom:1px solid transparent}
.nav a:hover{border-color:var(--line);color:var(--ink)}

.hero .wrap{display:grid;grid-template-columns:6fr 6fr;gap:clamp(36px,5vw,84px);
  align-items:center;padding:clamp(24px,4vw,56px) 0 clamp(64px,9vw,120px)}
.hero-copy{padding-left:clamp(0px,2vw,40px)}
.hero h1{margin-bottom:34px}
/* The subhead says both directions in one sentence, so it carries the hero on
   its own — the line that used to sit under it has been cut. */
.hero .lede{max-width:34ch}
/* Smaller box, smaller type. An outline pill is already the only bordered
   object on the page, so it does not need scale on top of that to be found. */
.btn{display:inline-block;margin-top:40px;padding:11px 24px;border-radius:999px;
  border:1px solid var(--sage);color:var(--sage);text-decoration:none;background:none;
  font:400 11.5px/1 Mulish,sans-serif;letter-spacing:.11em;text-transform:uppercase;
  transition:background .3s,color .3s}
.btn:hover{background:var(--sage);color:var(--paper)}
/* A real photograph is pre-cropped to its ratio, so it only needs a width. */
/* ⚠ THE BACKGROUND IS FOR THE SECONDS BEFORE THE PICTURE ARRIVES. The slots are
   reserved correctly — width and height attributes are on every img, so nothing
   reflows — but a reserved slot with nothing in it is a white hole, and on a
   phone on a slow connection the Signature Sessions page showed roughly 500px
   of one. Paper-2 is the same ground the alternating sections use, so the gap
   reads as part of the page rather than as a fault. It is painted over the
   moment the image decodes and costs nothing. */
.photo{width:100%;height:auto;background:var(--paper-2)}
/* A credit line for the person in the frame, not a caption about the picture,
   so it is legible rather than incidental.
   NO OPACITY. It was at .62, which the contrast script cannot see — it
   measures colour against colour and knows nothing about alpha. 5.84:1 on
   paper became roughly 3.4:1 in practice, and the check said it passed. */
.hero-figure figcaption{font-size:13px;color:var(--soft);margin-top:16px;
  max-width:46ch;line-height:1.6;letter-spacing:.01em}
.slot{background:var(--paper-2);color:var(--ink)}
section{padding:clamp(64px,9vw,132px) 0}
/* ── ANCHOR LANDINGS UNDER THE STICKY MASTHEAD — 0.4.98 ──────────────────────
   The five hero buttons became in-page links on 6 September, so every one of
   them now depends on where a `#section` jump lands. The masthead is
   `position:sticky`, and a jump puts the section's box top at the viewport top
   with the header sitting over it.

   ⚠⚠ THE DEFECT WAS INVISIBLE WHILE LOGGED IN, AND THAT IS THE PART WORTH
   REMEMBERING. WordPress's admin bar sets `html{scroll-padding-top:46px}` of its
   own. Every measurement taken from an admin session therefore showed the
   heading landing clear — 27px of daylight on a phone — while a real visitor,
   who has no admin bar and no such rule, got the heading **19px behind the
   masthead**. It was only found by zeroing the property and hiding the bar to
   simulate a logged-out load. **Measure anchors and sticky headers with the
   admin bar out of the way, or measure nothing.**

   ⚠ DESKTOP NEEDS NO RULE AND MUST NOT GET ONE. Measured logged-out at 1710px:
   header 73px against a section padding of 132px, so the first line lands 59px
   clear on its own. Adding scroll-padding there would push every anchor landing
   down by that amount and open a band of empty paper above the heading.

   ⚠ THE BREAKPOINT IS 1023, NOT 760, AND THE TABLET IS WHY. `section` padding is
   `clamp(64px,9vw,132px)` and the stuck header is 76px above 760px — so at 761px
   the padding is 68.5px and the heading is **7.5px under the header**, the same
   fault as the phone in a range nobody would have thought to check. One value
   covers the whole span: at 390px it leaves 21px of air, at 761px 32px, at
   1023px 56px — which is where the desktop already sits. */
@media (max-width:1023px){html{scroll-padding-top:40px}}
/* ⚠ THE FOLD CONTROL IS HIDDEN EVERYWHERE BY DEFAULT AND TURNED ON IN THE PHONE
   BLOCK — this rule is the desktop half of the folds and it is not optional.
   The markup is emitted on every viewport, because the server does not know how
   wide the screen is; without this line a desktop reader gets the words "Read
   the full training recordShow less" sitting under three sections of About.
   Caught before release, but only because the desktop was rendered and looked
   at rather than reasoned about. The clipping itself is declared in the phone
   block and nowhere else, so a desktop section is never clipped and this rule
   has nothing to undo. */
.fold-l{display:none}
/* ⚠ THE SAME LESSON AS `.fold-l` DIRECTLY ABOVE, AND IT WAS WRITTEN AFTER THAT
   ONE BIT. The per-row disclosure of 0.4.79 is a PHONE device: on a desktop the
   description is never hidden, so the sign would be a `+` beside eleven
   already-open rows — an affordance that lies, which is the exact fault the
   reviews scroller's fade was rebuilt to avoid. The `+`/`−` is declared in the
   phone block and nowhere else, so this hides it everywhere else.

   ⚠ AND THE CURSOR GOES WITH IT. The `<label>` is still wired to its checkbox
   on a desktop — `for` does not care about viewports — so it still toggles a
   hidden box that controls nothing visible there. Harmless, but a pointer
   cursor would advertise a control that does nothing. The text still selects,
   which `pointer-events:none` would have cost. */
.rfold-i{display:none}
.rfold-l{cursor:auto}
/* The ground is assigned by the running order, not by the section. */
.bg-2{background:var(--paper-2)}
/* ── THE REVIEW WALL ──────────────────────────────────────────────────────────
   ⚠ COLUMNS, NOT A GRID, AND THE REVIEWS DECIDED IT. They run from 125 to 1,839
   characters. A grid gives every cell the height of the tallest in its row, so
   a one-sentence review would sit in a box built for a fifteen-line one and the
   page would be mostly air. Columns flow them at their own heights.

   `break-inside:avoid` is the whole reason this works — without it a review
   splits across the column boundary mid-sentence. */
.rwall{columns:3;column-gap:clamp(28px,3.4vw,54px);
  margin-top:clamp(38px,4.6vw,68px)}
.rwall .review{break-inside:avoid;-webkit-column-break-inside:avoid;
  page-break-inside:avoid;
  border-left:1px solid var(--line);padding-left:clamp(18px,1.8vw,26px);
  margin:0 0 clamp(30px,3.4vw,48px)}
/* ⚠ 18px IS AN EXPLICIT EXCEPTION TO THE TWO-TIER SCALE, WITH A NUMBER AGAINST
   IT — 0.4.91. x-height 6.95, so it sits between the two tiers and belongs to
   neither. It is one voice repeated forty-one times and its evenness is the
   point; it is also the longest page on the site. Measured at 375px before
   deciding:

       today, 18px Cormorant          23.3 screens
       detail tier, 19.5px            25.9 screens   +2.6
       body tier, 22px                31.3 screens   +7.9

   RJ took the exception on 4 September rather than spend 2.6 screens on a
   consistency no reader can see. ⚠ It is an EXCEPTION, not an oversight — if
   the tiers are ever revisited this is the rule to revisit with them, and the
   numbers above are what it costs. */
.rwall blockquote p{font-family:'Cormorant Garamond',serif;font-style:italic;
  font-weight:300;font-size:18px;line-height:1.52;color:var(--ink);
  max-width:none}
.rwall figcaption{margin-top:14px;font-size:11px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--soft)}
.rwall figcaption span{display:block;letter-spacing:.06em;margin-top:3px;
  text-transform:none;color:var(--sage)}

/* ── SCREEN-READER-ONLY TEXT ──────────────────────────────────────────────────
   ⚠ THE THEME MUST DEFINE THIS ITSELF. It did not: `.skip-link` and
   `.screen-reader-text` appear in header.php and in WordPress's own pagination
   markup, and no rule for them existed in any of the theme's stylesheets. The
   link was hidden anyway, because WordPress 7.1 injects a `.screen-reader-text`
   rule inline — measured at 1×1px with clip-path: inset(50%).

   So it worked by borrowing somebody else's stylesheet. One plugin dequeueing
   that inline style and "Skip to content" becomes a visible link above the
   wordmark on every page of the site. Defined here now.

   `:focus` restores it: a skip link nobody can see when they tab to it is not
   a skip link. */
.screen-reader-text,.skip-link{position:absolute;width:1px;height:1px;padding:0;
  margin:-1px;overflow:hidden;clip-path:inset(50%);border:0;
  word-wrap:normal!important}
.skip-link:focus{position:fixed;top:12px;left:12px;z-index:100;
  width:auto;height:auto;margin:0;padding:12px 20px;clip-path:none;overflow:visible;
  background:var(--paper);color:var(--ink);border:1px solid var(--ink);
  font:400 14px/1 Mulish,sans-serif;text-decoration:none}

/* An image a page names and the theme cannot find. Shown only to somebody who
   can fix it — see svaflo_photo(). */
.svaflo-missing{display:inline-block;padding:8px 12px;border:1px dashed #b32d2e;
  color:#b32d2e;font:400 13px/1.4 Mulish,sans-serif}


/* Her voice, on the second ground so it reads as a different register without
   a heading having to announce it. */
/* The mark is centred against the column, not pinned to its top. Aligned to
   the start it read as hanging — an object that had come loose rather than one
   that had been placed. Centred, it holds the left side of the section. */
/* "SVã flo is for both." is the conclusion of the section and is set as one —
   larger, in the display face, with air above it. */

/* ⚠ FOUR ORPHANED DECLARATIONS WERE REMOVED FROM HERE — 0.4.44, 29 August.
   This is the `.name` section from the prototype, and between the snapshots
   `2026-08-25-2046` and `-2048` SEVEN LINES WERE DELETED FROM IT — every one
   of them the line carrying the opening `{`:

       .name .wrap{display:grid;grid-template-columns:260px minmax(0,1fr);
       .mark-art{width:260px;height:auto;opacity:.92}
       .name-copy{max-width:48ch}
       .name .eyebrow{margin-bottom:26px}
       .name p{font-size:18.5px;line-height:1.8;color:var(--soft);…
       .name strong{color:var(--ink);font-weight:600;…
       .name p:last-child{color:var(--ink);…

   The indented continuations survived, leaving four declaration bodies with a
   closing brace and no opening one. A browser discards those silently, which is
   why nothing ever looked wrong — but a brace-counting parser does not, and
   `tools/check.php` could no longer find this stylesheet's phone block. That
   disabled its equal-specificity ordering check: the one its own comment calls
   the check that matters most, guarding the failure mode this project has had
   seven times. **The guard was off and nothing said so.**

   ⚠ DELETED RATHER THAN RESTORED, AND THAT IS THE DECISION TO UNDERSTAND.
   Measured on the live site before touching anything: `.name` matches ZERO
   elements and `.mark-art` zero — About's name section was rebuilt as `.aname`
   / `.name-grid` in about.css, which supersedes every one of those rules. Only
   `.name-copy` still exists, and about.css already sizes it. So the seven lines
   are dead code; putting them back would add rules matching nothing and a
   container cap the redesign deliberately dropped.

   The same corruption is still in `Design/directions/build.py`, which is where
   it happened. That file is a historical record now — port.py is retired — so it
   is left as found rather than edited to disagree with its own history. */

/* The original structure — figure left, caption right, aligned on the baseline
   — with the phrase held to one line by `nowrap`. The size is whatever lets
   twenty-three characters sit on that line beside the caption, which is why it
   is smaller than the bare numeral used to be. */
/* One sentence, set as a statement. The number inside it takes the sage; the
   rest stays in ink, so the figure carries without being a separate object. */
.scale .wrap{max-width:1000px}
/* Matches the gap every other eyebrow keeps from the statement beneath it. */
.scale .eyebrow{margin-bottom:26px}
/* ── `text-wrap:balance` — 0.4.89 ──────────────────────────────────────────
   RJ, 4 September: three of these statements were "breaking badly on desktop.
   Words hanging at the end of line breaks."

   ⚠ MEASURED BEFORE ANYTHING WAS CHANGED, AND THE FIRST TWO CANDIDATES DID
   NOTHING. `text-wrap:pretty` and `text-wrap:balance` were both applied to the
   Corporates statement at 1440px and NOT ONE BREAK MOVED — the computed value
   said `pretty` and `balance` respectively, so they were in force; they simply
   found nothing to improve. Chromium's balancer declines past six lines and
   that statement is seven, and `pretty` works on the last lines, which were
   already three words. **Confirming a property applied is not confirming it
   did anything.**

   Where the paragraph is inside the balancer's reach it is worth a great deal.
   Line ends were counted mechanically — a "hang" is a line ending on a function
   word — and the rag is the pixel spread between the shortest and longest line:

     Home `.scale`        5 lines · 1 hang · LAST LINE ONE WORD · rag 405px
       with balance       5 lines · 0 hangs ·      3 words      · rag 161px
     Institutions         4 lines · 3 hangs · LAST LINE ONE WORD · rag 387px
       with balance       4 lines · 2 hangs ·      3 words      · rag  44px

   ⚠ HOME WAS NOT ONE OF THE THREE RJ REPORTED, and it carried a one-word widow
   on the site's single most quoted line. Found by measuring all five rather
   than the three named.

   It is declared here on `.figure` rather than on `.challenge .figure` because
   the Home statement is `.scale .figure` at 54px and wants it just as much.
   Unsupported browsers drop the declaration and get today's rendering, which is
   the same fallback discipline as the `:has()` block at the foot of this file:
   the safe state is the current one. */
.figure{font-family:'Cormorant Garamond',serif;font-weight:300;
  font-size:clamp(30px,3.8vw,54px);line-height:1.22;color:var(--ink);max-width:24ch;
  text-wrap:balance}
.figure span{color:var(--sage)}

/* The number and the five doors were both on --paper with nothing between
   them, so they ran together as one long section. A hairline inside the wrap —
   aligned to the content column, not bled to the window — is the page's own
   vocabulary: it is what already separates the doors from each other and one
   diary entry from the next. Nothing new had to be invented for it. */
.doors-section h2{margin:12px 0 0}
.doors{margin-top:64px;display:grid;grid-template-columns:repeat(2,1fr);
  column-gap:clamp(40px,6vw,96px)}
.door{display:block;text-decoration:none;padding:34px 0;border-top:1px solid var(--line);
  position:relative}
.door:first-child,.door:nth-child(2){border-top:none}
.door h3{margin-bottom:9px}
/* ⚠ ABOUT'S GUIDE CARDS ARE h2 SINCE 0.4.12 AND MUST NOT CHANGE SIZE.
   Home's doors sit under their own section h2 and stay h3; About's guide has no
   heading above the cards, so there they are the top level and h3 skipped a
   rank. Same markup, two correct answers — see the note in the renderer.

   This rule reproduces the h3 appearance EXACTLY, because promoting a heading
   is an outline fix and must cost nothing visually: main.css sets bare
   `h3{font-weight:400;font-size:27px;line-height:1.2}` but
   `h2{font-size:clamp(34px,4.4vw,58px)}` at weight 300 — so without this the
   three About cards would jump from 27px to 58px. Measured off the live page
   before the change, not inferred. (0,1,1) beats the bare `h2`. */
.door h2{font-family:'Cormorant Garamond',serif;font-weight:400;font-size:27px;
  line-height:1.2;margin-bottom:9px}
.door p{font-size:var(--t-detail);color:var(--soft);max-width:34ch;line-height:1.75}

/* ⚠ THE CORNER ARROW IS GONE AND THIS REPLACES IT — RJ, 26 August.
   `.door .go` was pinned top-right at opacity .35, level with the heading and
   nowhere near the words. It read as an ornament. This sits under the copy,
   uses the same sage-and-hairline treatment as every other "more" link on the
   site, and carries words as well as an arrow. Same element on the journal
   cards, hence one class for both. */
.door-more{display:inline-block;margin-top:16px;color:var(--sage);font-size:14px;
  border-bottom:1px solid var(--line);padding-bottom:3px;
  transition:border-color .15s ease}
.door:hover .door-more{border-bottom-color:var(--sage)}

/* ⚠ THE BARE ARROW — RJ, 27 August. The three About cards read as headings
   rather than links, and he chose an arrow alone over words. It is a VARIANT,
   not a replacement: the five home doors and the journal cards keep "Read more
   →" and are not touched, because only svaflo_section_about_guide() emits this
   class.
   The hairline is dropped deliberately. `.door-more` is an inline-block with a
   border-bottom, so an arrow on its own would draw a ~12px stub of rule
   underneath it — which reads as a defect, not as a link. With no words to
   underline, the affordance has to come from somewhere else, so it moves on
   hover instead. Set larger than the 14px label it replaces: a lone glyph at
   label size is too quiet to be found. */
.door-more-bare{border-bottom:none;padding-bottom:0;font-size:19px;line-height:1;
  transition:transform .18s ease}
.door:hover .door-more-bare{transform:translateX(5px)}

.thinking-head{max-width:44ch}
.thinking h2{margin:12px 0 0}
.thinks{margin-top:64px;display:grid;grid-template-columns:repeat(3,1fr);
  column-gap:clamp(34px,4.5vw,70px);row-gap:clamp(34px,4vw,54px)}
/* Three observations, no headings. Set larger than body copy and given a lot
   of room, because with the lead-ins gone the words have to carry it. */
.think{max-width:40ch}
.think p{font-family:'Cormorant Garamond',serif;font-size:var(--t-detail-c);line-height:1.55;
  color:var(--ink);font-weight:300}
.thinking .more{margin-top:54px}

/* RJ: "the Know Angira section is poorly designed, feels out of synch with the
   rest of the page." It was a portrait-plus-bio module in a page that has no
   other modules. Rebuilt as the page's own two moves: a quotation at full
   measure, then a picture and a column of text. */
.person .eyebrow{margin-bottom:26px}
/* Back to 5/7 without sticky. The copy is short again now that the biography
   is behind the link, so there is nothing for the picture to travel past. */
/* Top-aligned. Centred, the picture and the type floated against each other's
   middles and neither had a shared edge; aligned to the top they start on the
   same line, which is what makes the two columns read as one composition. */
.person-body{display:grid;grid-template-columns:9fr 13fr;gap:clamp(40px,4.5vw,68px);
  align-items:start}
/* The modalities, as a caption on the method rather than a list inside a
   sentence. Same hairline treatment as every other caption on the page. */
/* Two paragraphs now, not a one-line caption, so it is set as readable text
   rather than as a label — a size up, a looser line, and space between the
   two. The hairline stays: it is what keeps this reading as belonging to the
   picture rather than as a second column of body copy. */
.portrait figcaption{border-top:1px solid var(--line);margin-top:18px;padding-top:16px;
  font-size:15px;line-height:1.72;color:var(--soft)}
.portrait figcaption p + p{margin-top:15px}
.person-copy p{margin-bottom:20px;color:var(--soft);font-size:var(--t-body)}
/* AFTER .person p, not before. Both selectors have the same specificity, so
   the earlier one lost and the quote rendered at 16px — invisible in the
   source, obvious the moment the page was looked at. */
.person-copy .lede{color:var(--ink);margin-bottom:28px;
  font-size:var(--t-body-c)}
.person strong{font-weight:600;color:var(--ink)}
/* THE GALLERY — quote and pictures in one grid.
   Two columns, every cell 16:9, every caption under the same hairline. The
   quote is a cell like the others: same width, attribution where a caption
   goes. That is the whole reason it reads as one grid rather than as a quote
   with pictures underneath it. */
.gallery{display:grid;grid-template-columns:repeat(2,1fr);
  column-gap:clamp(24px,3.4vw,48px);row-gap:clamp(34px,4.5vw,64px)}
.gallery figure{margin:0}
.gallery figcaption{border-top:1px solid var(--line);margin-top:16px;padding-top:13px}
.gallery figcaption strong{display:block;font-family:'Cormorant Garamond',serif;
  font-weight:400;font-size:21px;line-height:1.25;color:var(--ink)}
.gallery figcaption span{display:block;margin-top:4px;font-size:13.5px;color:var(--soft)}
/* The quote cell.
   RJ: "the lead text is all bunched up and stacked." It was — `max-width:24ch`
   held the type to little more than half the cell it sat in while the hairline
   beneath it ran the full width, so a 180-character sentence broke over seven
   short lines inside a wide box. The cap is gone; the quote uses the cell, at
   a smaller size and looser leading, and lands in four or five long lines.
   `aspect-ratio` gives the blockquote the same 16:9 box as the photograph
   beside it, so the two captions sit on the same line — the thing that makes
   this read as one grid. WeasyPrint does not implement `aspect-ratio`, so the
   render harness supplies the height a browser derives. */
/* ⚠ 3:2 SINCE 0.4.9, MATCHING THE PICTURE BESIDE IT. This ratio is not a style
   choice — it is what makes the quote stand exactly as tall as the photograph
   so the two captions sit on one line and the row reads as one grid. It must
   equal the ratio used by svaflo_section_home_gallery(), and there is a check
   asserting the two agree. */
.g-quote blockquote{display:flex;align-items:center;aspect-ratio:3/2}
.g-quote blockquote p{font-family:'Cormorant Garamond',serif;font-style:italic;
  font-weight:300;font-size:clamp(23px,2.3vw,28px);line-height:1.5;color:var(--ink);
  max-width:none;margin:0}
/* Credited exactly as she is under the hero photograph, on RJ's instruction. */
.g-quote figcaption{font-size:13px;color:var(--soft);line-height:1.6;
  letter-spacing:.01em}

.more a{color:var(--sage);text-decoration:none;border-bottom:1px solid var(--line);
  padding-bottom:3px;font-size:15px}


.week h2{margin:12px 0 44px}
.events li{display:grid;grid-template-columns:150px 1fr 220px;gap:20px;padding:26px 0;
  border-top:1px solid var(--line);align-items:baseline}
.events .when{font-size:13px;letter-spacing:.13em;text-transform:uppercase;color:var(--soft)}
.events .what{font-family:'Cormorant Garamond',serif;font-size:27px}
.events .where{font-size:14px;color:var(--soft);text-align:right}
.week .more{margin-top:42px}

/* REVIEWS — a horizontal scroller in place of the old summary panel.
   No cards and no borders: each review is a column of text separated by space
   and a hairline, which keeps it inside the page's own logic rather than
   importing a carousel from somewhere else. */
.reviews h2{margin:12px 0 0}

/* ⚠ A SCROLLER AGAIN — RJ, 26 August. It was one, then it was a two-across
   grid, and this is the third state. Both earlier ones are recorded so nobody
   changes it a fourth time without knowing what was already tried:

     · scroller, to 25 Aug — rejected in the browser pass. Eight reviews, three
       and a half visible, the rest behind a swipe with NOTHING to say a swipe
       was possible. The clipped card was supposed to be the signal and did not
       read as one.
     · grid, 25–26 Aug — all eight visible, nothing hidden, and not what the
       design was meant to be.

   So: a scroller with the missing affordance actually supplied. A rail you can
   see and drag, and the right edge fades so the row reads as continuing rather
   than as a card sliced by the window. `.at-end` drops the fade when there is
   nothing further right — a fade at the end of a list is a lie about what is
   there. main.js sets it; with no JS the fade simply stays on. */
.scroller{display:flex;gap:clamp(30px,4vw,58px);
  padding:50px clamp(24px,6vw,84px) 22px;margin:0 auto;max-width:1180px;
  overflow-x:auto;overscroll-behavior-x:contain;
  scroll-snap-type:x proximity;
  /* ⚠ THE RAIL IS DRAWN, NOT BORROWED FROM THE PLATFORM. Styling
     ::-webkit-scrollbar was the obvious way and it was MEASURED as an overlay
     bar taking zero layout space — which on a Mac means invisible until you
     already scroll, i.e. exactly the missing affordance this whole change is
     meant to supply. So the track and thumb are two background layers.
     `background-attachment:scroll` pins them to the element's box rather than
     to the content, so they stay put while the reviews move past. main.js
     sizes and positions the thumb; with no JS it sits at the left at its
     resting width, and the track still says a track is there. */
  scrollbar-width:none;
  background-image:linear-gradient(var(--sage),var(--sage)),
                   linear-gradient(var(--line),var(--line));
  background-repeat:no-repeat,no-repeat;
  background-size:var(--rail-w,22%) 2px,100% 1px;
  background-position:var(--rail-x,0) bottom,left bottom;
  background-attachment:scroll,scroll;
  /* Two mask layers, added together: the fade across everything ABOVE the
     rail, and a solid band over the rail itself. Masking the whole box in one
     gradient would fade out the right end of the very affordance being added. */
  -webkit-mask-image:linear-gradient(to right,#000 calc(100% - 78px),transparent),
                     linear-gradient(#000,#000);
  mask-image:linear-gradient(to right,#000 calc(100% - 78px),transparent),
             linear-gradient(#000,#000);
  -webkit-mask-size:100% calc(100% - 14px),100% 14px;
  mask-size:100% calc(100% - 14px),100% 14px;
  -webkit-mask-position:top left,bottom left;
  mask-position:top left,bottom left;
  -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat}
.scroller.at-end{-webkit-mask-image:none;mask-image:none}
.scroller::-webkit-scrollbar{height:0}
.scroller .review{flex:0 0 clamp(268px,30vw,392px);scroll-snap-align:start;
  border-left:1px solid var(--line);
  padding-left:clamp(20px,2vw,30px)}
.menu-label{display:none}
.scroller blockquote p{font-family:'Cormorant Garamond',serif;font-style:italic;
  font-weight:300;font-size:var(--t-body-c);line-height:1.46;color:var(--ink);max-width:none}
.scroller figcaption{margin-top:20px;font-size:12px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--soft)}
.scroller figcaption span{display:block;letter-spacing:.06em;margin-top:4px;
  text-transform:none}
.reviews .more{margin-top:0}

/* RJ: "the end section looks poorly constructed." It was four stacked blocks
   at body scale ending on a small text link. It closes on the same outline
   button the hero opens with, so the page ends where it began. */
.close{padding-bottom:clamp(80px,11vw,160px)}
.close .wrap{max-width:820px;padding-left:clamp(24px,10vw,180px)}

/* 16ch held one sentence. It now holds two, as one heading at one size, so the
   measure opens up — otherwise the same words break over twice as many lines
   in the same narrow column. */
.close h2{margin-bottom:30px;max-width:24ch}
.close p{color:var(--soft);font-size:var(--t-body)}
.close .btn{margin-top:44px}

/* ── THE CLOSING ASK WITH A PORTRAIT, 0.4.62 ─────────────────────────────────
   RJ, 1 September: the closing section looked bland. It measured so — the wrap
   above is an 820px column with a left indent of up to 180px, which on a 1710px
   screen leaves 616px of empty paper beside the heading, the emptiest area on
   any of these pages. The picture spends that indent rather than widening the
   band, so THE COPY DOES NOT MOVE: the grid gives the figure the space the
   padding was holding, and the heading stays at the x it sits at today.

   ⚠ 165px IS MEASURED, NOT CHOSEN. It is the cap line of the heading to the
   descender of the last line of the sentence under it — glyph to glyph, not box
   to box, which is 175 and sits visibly high. At 2:3 that is 110 wide. The 5px
   top margin is the same measurement: Cormorant's cap sits 5px below its line
   box at this size. Re-measure both if the type scale or either face changes.

   ⚠ THE HEADING SIZE IS SET HERE AND ONLY FOR THIS VARIANT. `home` is absent
   from $page_css in functions.php, so it never loads audience.css and its close
   heading fell through to the base h2 at 58px while the four audience-styled
   pages rendered 38px. Five pages one size, five the other, and nobody had
   noticed. This pins whichever pages carry a portrait.

   ⚠ THE SIZE FOLLOWS THE PICTURE, NOT THE PAGE, AND THAT IS THE USEFUL PART.
   The selector is `.close.has-figure h2`, so a page drops from 58px to 38px the
   moment a picture is set on it and needs no stylesheet of its own. That is why
   0.4.68 gave Gallery the portrait with NO CSS AT ALL — measured in the DOM
   before it was built, not assumed.

   ⚠ THE SCOPE HAS MOVED TWICE AND THIS COMMENT WAS STALE BOTH TIMES.
   It named About as excluded five days after 0.4.63 gave it the boxes, and named
   Gallery as excluded until 0.4.68. As of 0.4.68 the portrait is declared on
   home, audience, sessions, about and gallery. ACTIVITIES AND REVIEWS ARE STILL
   OUT, and that is still RJ's decision rather than an oversight — he was asked
   on 1 September and scoped it to Gallery alone. Do not add them on the
   reasoning that Gallery has it. Fixing the rest by moving `.close h2` into
   main.css unscoped would move pages nobody has looked at.

   ⚠ SPECIFICITY: (0,3,0) here against `.close .wrap` (0,2,0) above and the
   phone override further down, so this wins in both — which is why the phone
   rule below has to restate the padding rather than relying on the cascade. */
.close.has-figure .wrap{padding-left:0;padding-right:0;
  display:grid;grid-template-columns:auto 1fr;gap:61px;align-items:start}
.close.has-figure .close-portrait{margin:5px 0 0}
.close.has-figure .close-portrait img{display:block;height:165px;width:auto;
  background:var(--paper-2)}
.close.has-figure h2{font-size:clamp(26px,2.8vw,38px)}

/* ── THE SUBTEXT MEASURE, 0.4.73 ─────────────────────────────────────────────
   RJ, from the live desktop site: *"the first line is trailing long, the second
   lands really short."* It was. Measured at 1710px across all nine pages with a
   subtext, the two lines came out around **515px and 85px** — the second line a
   fragment of two or three words.

   ⚠ THE CAUSE IS THAT NOTHING EVER SIZED THIS PARAGRAPH. It was inheriting
   `p{max-width:34rem}` from line 83 — the site-wide paragraph measure, 544px —
   which is a sensible width for running body copy and far too wide for two short
   sentences beside a portrait. The copy column here is 649px, so 544 let the
   first line run almost full and left the remainder stranded.

   340px, AND THE NUMBER IS A MEASUREMENT, NOT A PREFERENCE. Every page's subtext
   was re-wrapped at 300, 320, 324, 328, 330, 332, 336, 340, 360, 380 and 400 and
   the two line widths read off each time:

     544 (today)  Home 535/86 · Individuals 543/59 · Corporates 511/94
     340          Home 289/331 · Individuals 289/313 · Corporates 331/274

   Worst imbalance falls from 484px to 61px, and every page stays on TWO lines.

   ⚠⚠ 332px IS A CLIFF AND 340 IS DELIBERATELY CLEAR OF IT. Home breaks to THREE
   lines at 330 and holds two at 332 — and a third line would push the text block
   past the 165px portrait and undo the alignment set in 0.4.71/0.4.72 on ten
   pages. 332 and 340 produce IDENTICAL line widths on every page, so 340 buys 8px
   of margin for nothing. **Do not tighten this below 340 without re-wrapping all
   nine pages.**

   ⚠ SCOPED TO `.close-copy`, WHICH ONLY EXISTS WHEN A PORTRAIT IS SET, so the
   close sections without one — Questions, and the journal index — keep the
   global measure and are untouched.

   ⚠ AND IT DOES NOTHING ON A PHONE, BY ARITHMETIC RATHER THAN BY A MEDIA QUERY.
   At 360px the copy column is about 312px, already narrower than 340, so the cap
   never binds. RJ: *"This is mostly on desktop."*

   ⚠ PLACED AFTER `p{max-width:34rem}`, not before it. Specificity (0,3,1) beats
   (0,0,1) either way, but 0.4.69 shipped a dead rule by sitting five lines above
   the thing it overrode — see trap 31. Order and specificity, both. */
.close.has-figure .close-copy p{max-width:340px}

/* ── THE PHONE: STACKED, AND THIS IS THE SECOND ANSWER ───────────────────────
   0.4.62 stacked it as a placeholder. 0.4.64 put it beside the copy at 88×132
   on RJ's instruction — *"Use the inset as inset next to the CTA, not over or
   below it."* **RJ looked at it live and reverted it: "Not looking good."**
   0.4.65 is that revert.

   ⚠ SO THIS IS A JUDGEMENT THAT HAS BEEN TAKEN BOTH WAYS, WITH THE SIDE-BY-SIDE
   VERSION ACTUALLY SHIPPED AND SEEN. Do not "fix" the stack back to a row on the
   reasoning that desktop does it that way — that experiment has run.

   What the measuring found, and it stands whoever revisits this: on a 375px
   screen the wrap is 327px of content, and the desktop rule (picture height =
   the text block) has NO solution — a narrower picture leaves a narrower column,
   which makes the text taller, which demands a taller and therefore wider
   picture. Measured across 70–120px of width, the picture is shorter than the
   text at every value, closest at 100 and still 81px short. Side by side
   therefore always means a picture that does not relate to the text beside it,
   which is most likely what RJ was reacting to. */

/* ═══ THE PULL-QUOTE — one component, three templates, 0.4.102 ══════════════
   A single quote set large, used by the five audience pages, by About's
   `voice` section and by Home's.

   ⚠⚠ IT LIVES HERE BECAUSE HOME LOADS main.css AND NOTHING ELSE. `home` is
   absent from `$page_css` in functions.php. It was written in audience.css,
   copied into about.css on 20 September when About needed it, and moved here
   the same day when Home needed it too — three copies was the point at which
   duplicating stopped being the cautious option. **Both of those files now
   carry a note saying so. Do not re-add it to either.**

   ⚠ THIS RULE DOES NOT SET THE TEXT MEASURE, and the number that looks like it
   does is not the one doing the work. main.css carries a site-wide
   `p{max-width:34rem}` and this sets none of its own, so the words set at
   **544px** and `max-width:44rem` caps the FIGCAPTION, which would otherwise
   run the full column while the quote above it stopped short. Measured on the
   live page after 0.4.10, not predicted. To change the measure deliberately,
   change it on `.pullquote blockquote p`.

   ⚠ THE QUOTATION MARKS ARE DRAWN HERE, NEVER TYPED INTO THE BOX. Typed marks
   get curled by svaflo_smarten(), and a paste from Word arrives with a third
   kind, so they would differ between pages. */
/* ⚠ THE HISTORY BELOW CAME FROM audience.css WITH THE COMPONENT IN 0.4.102.
   It is how the 44rem was arrived at, and it is kept because the first
   version of it credited the wrong number with doing the work. */
/* ═══ IN HER WORDS — the pull-quote, 0.4.8 ═══════════════════════════════════
   One sentence in Angira's voice, sitting between the argument and what happens
   in a session. Used by Corporates; empty and therefore absent on the others.

   ⚠ NO ASPECT RATIO, UNLIKE THE HOME PAGE'S QUOTE. That one shares a 16:9 box
   with the photograph beside it so their captions land on one line, which caps
   it at roughly 278 characters. This one has no neighbour to align with, so it
   sets as tall as the words need and length is not a constraint. Copying the
   ratio across would impose a limit that exists for a reason this section does
   not have.

   ⚠ THE MEASURE IS 44rem AND IT WAS 26ch, WHICH RESOLVED AGAINST THE WRONG
   FONT. `ch` is the width of the "0" glyph IN THE ELEMENT IT IS WRITTEN ON —
   and this rule is on the FIGURE, whose font is the body's Mulish at 17px, not
   the 38px Cormorant of the quote inside it. So "26 characters" came out as
   **265px**, and the corporate pull-quote set as a 265px ribbon **fourteen
   lines and 755px tall** in a 1180px column. Measured on the live page, not
   noticed by reading the CSS, and every one of the 952 checks passed while it
   was wrong — because nothing in the suite knows what a pull-quote should look
   like.

   26ch of the quote's OWN type is ~431px, which was the intent and is still
   too narrow: it gives nine lines. Measured across three real quote lengths,
   ~700px is the width where a long quote sets in five lines, a middling one in
   three, and a short one in one:

       26ch(431px)  9 lines · 38ch(630px)  6 · 42ch(696px)  5 · 50ch(828px)  4

   `rem` is used rather than `ch` because it cannot be captured by whatever font
   the element happens to inherit — which is the whole fault above.

   ⚠ AND THIS RULE DOES NOT SET THE TEXT MEASURE. Checked on the live page after
   0.4.10 went up, because the numbers did not match the prediction: the quote
   sets at **544px**, not 704. `main.css` line 45 carries a site-wide
   `p{max-width:34rem}` and `.pullquote blockquote p` sets no max-width of its
   own, so the global paragraph measure governs the words. What this rule
   actually does is cap the FIGCAPTION, which would otherwise run the full
   1180px column while the quote above it stopped at 544.

   So the ribbon was fixed by REMOVING the 265px cap, not by the 704px that
   replaced it. Both numbers are in the record because the first version of this
   comment claimed the second one was doing the work, and it is not. If the
   measure ever needs to change deliberately, change it on
   `.pullquote blockquote p`, where the text is. */

.pullquote figure{margin:0;max-width:44rem}
.pullquote blockquote{margin:0}
.pullquote blockquote p{font-family:'Cormorant Garamond',serif;font-style:italic;
  font-weight:300;font-size:clamp(24px,2.9vw,38px);line-height:1.42;color:var(--ink)}
.pullquote blockquote p::before{content:open-quote}
.pullquote blockquote p::after{content:close-quote}
/* ⚠ THE HEADING-TO-NEXT-THING MARGIN, WHICH main.css RESETS TO ZERO. A name
   sitting flush under a quote reads as the last line of the quote. */
.pullquote figcaption{margin-top:22px;font-size:13.5px;line-height:1.7;color:var(--soft)}

@media (max-width:760px){
  /* The quote's measure is already narrow; at 390px it uses the column
     rather than a 26-character ribbon down the middle. Moved from
     audience.css with the component in 0.4.102. */
  .pullquote figure{max-width:none}
  .close.has-figure .wrap{grid-template-columns:1fr;gap:26px;
    padding-left:24px;padding-right:24px}
  .close.has-figure .close-portrait{margin:0}
}

/* ⚠ THE RULE ON TOP IS THE ONLY THING SEPARATING THE FOOTER FROM THE PAGE, AND
   IT IS DELIBERATELY STRONGER THAN `--line`.

   0.4.30 gave the footer its own ground, `--paper-3:#EAE0CE`. RJ, having seen it
   live: *"The color change doesnt look good. Revert to earlier. Make the
   hairline separator bolder."* Reverted in full — the ground, the darkened body
   text, and the two internal rules that had been lifted to suit it.

   So the footer inherits `--paper` again and the boundary is carried by this one
   line. At `--line`'s 13% it was invisible, which is what started this. 30% is
   roughly the weight of the `.fcontact` underline: a rule a reader registers as
   drawn rather than as a rendering artefact.

   ⚠ NOT `--line`, AND NOT A CHANGE TO IT. That token is used on the sticky
   header, section dividers and the legal line; raising it there would thicken
   every hairline on the site to solve one seam. */
.site-footer{border-top:1px solid rgba(44,48,44,.30);padding:70px 0 54px;
  font-size:14px;color:var(--soft)}
/* ── THE FOOTER, REBUILT 0.4.26 ────────────────────────────────────────────────
   Three blocks, each a label, a sentence and one action — see footer.php for
   why. The old rules styled a wordmark and two bare link lists; every one of
   them is replaced rather than added to, because a stale `.fcols li` would keep
   styling nothing and read as intentional to whoever found it next. */
.fcols{display:grid;grid-template-columns:1.25fr 1fr 1fr;
  gap:clamp(30px,5vw,84px);align-items:start}
/* ⚠ THE LOCKUP HERE TOO SINCE 0.4.97 — the footer was setting the wordmark in
   Cormorant at 27px on every page, the same violation as the header. 44px gives
   a 19px cap against the 27px text's 18px, and 125px of ink. It sits a shade
   larger than the header's, which the old text did too. */
.fcols .brand{display:block;line-height:0;margin-bottom:18px}
.fcols .brand img{height:44px;width:auto;display:block}
.flabel{font:400 11px/1 Mulish,sans-serif;letter-spacing:.24em;
  text-transform:uppercase;color:var(--sage);margin:0 0 16px}
.fsent{font-family:'Cormorant Garamond',serif;font-weight:300;font-size:17px;
  line-height:1.55;color:var(--soft);margin:0 0 14px;max-width:38ch}
.fplace{font:300 12.5px/1.6 Mulish,sans-serif;color:var(--soft);margin:0 0 16px}
.fcontact{font-family:'Cormorant Garamond',serif;font-weight:300;font-size:18px;
  line-height:1.65;margin:0 0 14px}
/* Underlined rather than sage, because these are the two things in the footer a
   reader is most likely to want to click and copy. */
.fcontact a{color:var(--ink);text-decoration:none;
  border-bottom:1px solid rgba(44,48,44,.2)}
.fcontact a:hover{border-bottom-color:var(--ink)}
.flink{display:inline-block;font:400 12px/1 Mulish,sans-serif;letter-spacing:.1em;
  color:var(--sage);text-decoration:none;margin-right:20px;margin-top:2px}
.flink:hover{text-decoration:underline}
/* ⚠ ONE FOOTER LINK STACKS, AND ONLY ONE — 0.4.75. `.flink` is inline-block so
   that column two can sit Reviews and Activities side by side, which is
   deliberate. 0.4.74 added the FAQ link to column one and it inherited that,
   landing to the RIGHT of "Read more about Angira" rather than under it —
   RJ: *"take it below or above Angira. Not to the right."*

   Scoped to the one anchor rather than to `.flink`, so column two is untouched.
   `margin-right:0` because the inherited 20px does nothing on a block and would
   confuse anyone reading the box later. */
/* ⚠ 26px, AND THE NUMBER IS ARITHMETIC RATHER THAN TASTE — 0.4.88. At 10px
   these two links sat 28px apart, centre to centre. Every `.flink` carries a
   44px `::after` centred on its own text (see the tap-target block below), so
   two of them 28px apart OVERLAP BY 16, and the later one in source order
   paints on top.

   🔴 THE UPPER LINK WAS A 28px TARGET AND THE 16px BENEATH IT OPENED THE WRONG
   PAGE. Hit-tested on the live 0.4.87 at 360px: "Read more about Angira"
   reached 28px, the other five footer links 44–45, and every probe from 12px
   below the Angira text downward returned FAQs. On all thirteen pages.

       Angira text [0,12]   overlay [-16, 28]
       FAQs   text [28,40]  overlay [ 12, 56]   ← wins the shared strip

   Two centred 44px overlays need 44px between their centres. These had 28, so
   the margin carries the missing 16. Verified by applying it and re-measuring:
   28 → 44, the other five unchanged, footer 844 → 860.

   ⚠ NOTHING IS WRONG WITH THE OVERLAY, AND `getComputedStyle` SAYS OTHERWISE.
   It reports the pre-transform box as `top:6px; bottom:-38px`, which reads like
   an overlay hung below the text and sent me looking for a fault in the wrong
   rule. The stylesheet is the source of truth for what a rule intends.

   ⚠ AND THE GAP WAS INTRODUCED BY A FIX. 0.4.75 stacked this link because RJ
   asked for it below Angira rather than to the right. The stack was right; 10px
   was not enough, and no sweep ran afterwards to say so. These two are the only
   vertically stacked pair in the footer, which is why nothing else collides. */
.flink-stack{display:block;margin-right:0;margin-top:26px}

/* ⚠ `justify-content:space-between` WITH TWO SPANS, not a float. The legal line
   was one run of text; it is now two groups that have to sit at opposite ends
   and then stack on a phone, which a float cannot do. */
.legal{display:flex;justify-content:space-between;gap:24px;
  border-top:1px solid var(--line);margin-top:clamp(38px,5vw,60px);
  padding-top:22px;font-size:12.5px;max-width:none}

/* The legal words before their pages exist. ⚠ IT HAS TO LOOK DIFFERENT FROM THE
   LINK BESIDE IT — `Questions` is real and these are not, and if they read the
   same a reader clicks and nothing happens. Lighter, no underline, and
   `cursor:default` so the pointer does not promise anything either. Deleted by
   itself the moment the Legal menu has an item; see footer.php. */
.legal .fpending{color:var(--soft);opacity:.72;cursor:default}

/* ── EYEBROWS, LAST ────────────────────────────────────────────────────────
   `p.eyebrow` and not `.eyebrow`, and at the end of the file rather than the
   start. An eyebrow is a <p>, so any section rule of the form `.person p`
   has the same specificity and simply wins by coming later — which is what
   happened: "KNOW ANGIRA BETTER" was quietly rendering at 16px instead of
   11px. RJ spotted it as "the eyebrow size has increased".

   Fixing that one instance would have left the trap set for the next
   section. This makes the eyebrow win everywhere, permanently. */
/* Same story as the eyebrow, and found the same way — the closing section's
   lede was rendering at 17px because `.close p` outranked `.lede`. Three
   instances of one trap is a pattern, not three bugs: any element that can
   appear inside a section styled with `.section p` needs to outrank it. */
/* ONE SIZE, EVERY PAGE. RJ, 25 August: "the text below the hero headline is
   too big — we need to standardise this across pages."
   It was 29px here, 21px on About (set on his note), and 29px again on
   Corporates, which is three answers to one question. 21px is the size he
   already chose once; the measure opens to 34ch because a smaller face needs
   a longer line to hold the same shape.
   ⚠ THIS CHANGES THE LOCKED HOME PAGE. Both locks were recorded as "structure
     and copy settled, typographic refinement still open" — this is that. */
p.lede{font-family:'Cormorant Garamond',serif;font-style:italic;font-weight:300;
  font-size:var(--t-body-c);line-height:1.62;color:var(--soft);max-width:34ch}

/* A condition of the work rather than a claim about it, so it sits below the
   body size. Declared here and not beside the section: `.person-copy p` would
   outrank it exactly as it outranked the opener. */
/* The hairline is back on the note. It had moved onto the first body paragraph
   while that block existed; the restructure removed the block, and a rule that
   moved to an element that no longer exists is a rule that silently stopped
   drawing. */
p.person-note{font-size:var(--t-detail);line-height:1.75;color:var(--soft);max-width:52ch;
  margin-top:30px;padding-top:28px;border-top:1px solid var(--line)}

/* THE LEAD — the first three paragraphs, all at display scale.
   Below what the opener alone carried (37px), because three paragraphs of it
   at that size shouts where one stated. The hairline that used to close this
   block belongs to the note below it now.

   A statement, not a quotation: no quote marks, upright rather than italic,
   because it is the site describing her and not her speaking.

   Declared here for the reason this whole block exists — `.person-copy p` has
   the same specificity and wins on order. That is exactly what happened while
   this rule was still called `.person-opener` and the markup had moved on to
   `person-lead`: three paragraphs set at 31px, rendering at 16px, with no
   error anywhere. */
/* Sized to the picture. RJ: the three lead paragraphs should end level with
   the bottom of the photograph beside them. That is a measurement, not a
   preference — at 31px/1.42/22px the block ran 616px against a 581px image and
   pushed the hairline below the frame. The numbers below were arrived at by
   measuring the rendered box tree, not by eye; if the copy changes, re-measure
   rather than nudging. */
p.person-lead{font-family:'Cormorant Garamond',serif;font-weight:300;
  font-size:var(--t-body-c);line-height:1.48;color:var(--ink);
  max-width:none;margin-bottom:30px}

p.eyebrow{font:400 11px/1 Mulish,sans-serif;letter-spacing:.26em;
  text-transform:uppercase;color:var(--sage);margin-bottom:28px;max-width:none}
/* The brand name is never uppercase — CLAUDE.md, and it has gone wrong before. */
p.eyebrow.no-caps{text-transform:none;letter-spacing:.02em;
  font-family:'Cormorant Garamond',serif;font-size:19px}
/* The name inside anything that is otherwise set in small caps. THE FIRST
   DECLARATION IS UNSCOPED ON PURPOSE: it was written as `p.eyebrow
   .brand-inline`, so when the same wrapper was needed inside a button the
   protection simply was not there and the hero button rendered the name in
   caps, tilde and all. The transform exemption applies wherever the wrapper
   appears; only the fitting is per-context.
   (The forbidden spelling is deliberately not written out here — the build
   check greps the page for it, and a comment would be a false positive.) */
.brand-inline{text-transform:none}
/* Same face as the rest of the line — a second typeface mid-line reads as a
   mistake at this size — but upright, a size larger so the lowercase sits
   level with the caps beside it, and with most of the tracking taken out,
   because .26em turns a five-letter name into five separate letters. */
p.eyebrow .brand-inline{letter-spacing:.06em;font-size:12.5px}
.btn .brand-inline{letter-spacing:.02em;font-size:13px}
p.eyebrow .sep{display:inline-block;letter-spacing:0;margin:0 .55em}
/* ════ THE PHONE ═══════════════════════════════════════════════════════════
   Written 26 August, after rendering the pages at 390px for the first time.
   Before this the project had five media queries, four of them for tablet
   widths, and no phone layout at all — so every page overflowed its viewport
   by 205px and scrolled sideways.

   ONE BLOCK, and it lives here rather than scattered through the stylesheet,
   so "what does this look like on a phone" has one place to read.

   **760px, not 700 or 768.** It is the width at which the six-item nav stops
   fitting — measured, not chosen for being round. The per-page stylesheets
   keep their own 900px blocks for the tablet step; this is the step below.  */
/* ── THE MENU BREAKPOINT IS 1023px, NOT 760px, AND THE NAV DECIDED IT ─────────
   Added 0.4.39, immediately after Reviews and Activities went into the menu on
   29 August and took it from seven items to nine.

   ⚠ THIS WAS A REGRESSION AND IT WAS MEASURED, NOT PREDICTED. Nine items need
   **962px** of header. The nav row does not wrap, so between the old menu
   breakpoint (761px) and about 1000px the last item — Contact, the one the
   whole site points at — sat outside the viewport and the document scrolled
   sideways. Checked at nine widths from 761 to 1440: broken at 761, 800, 860
   and 900; clean from 1000 up.

   So the menu rules moved out of the phone block and into their own query.
   Below 1024px the masthead is a wordmark and MENU, on a tablet exactly as on
   a phone; above it, the nav row is untouched and identical to before.

   ⚠ THE PHONE BLOCK KEEPS EVERYTHING ELSE. Only the rules that make the menu a
   menu live here — the mobile header padding, the wordmark size and the
   tagline all stay at 760px, because a tablet still wants the full masthead.
   Two breakpoints doing two different jobs, rather than one doing both badly.

   ⚠ AND `flex-wrap` LIVES HERE, NOT IN THE PHONE BLOCK, which is where it was
   until today. The open menu takes its own row with `flex-basis:100%`, and a
   nowrap container cannot give it one — so at 900px the menu would have opened
   as a tall column beside the wordmark. The rule has to reach wherever the
   menu can open. */
@media (max-width:1023px){
  .site-header .wrap{flex-wrap:wrap;row-gap:0}

  .menu-label{display:block;margin-left:auto;cursor:pointer;
    font-size:11px;letter-spacing:.18em;text-transform:uppercase;
    color:var(--soft);padding:8px 0 8px 14px;white-space:nowrap}
  .menu-toggle:checked ~ .menu-label{color:var(--ink)}

  .nav{display:none}
  /* ⚠ `max-height` and `overflow-y`, because the header is sticky.
     The open menu lives INSIDE the header, so on a short viewport — a phone
     held sideways is about 390px tall — a nine-item menu is taller than the
     screen and there is no way to reach the last item or to close it again,
     because the toggle has scrolled off with everything else. Capping it
     against the viewport keeps the list scrollable inside a header that
     cannot itself scroll away. Nine items makes this matter more than seven
     did. */
  .menu-toggle:checked ~ .nav{display:flex;flex-direction:column;gap:0;
    order:3;flex-basis:100%;margin:14px 0 0;
    max-height:calc(100vh - 140px);overflow-y:auto;
    border-top:1px solid var(--line)}
  .nav a{display:block;padding:14px 0;font-size:16px;border-bottom:0;
    border-top:0;white-space:normal}
  .nav a + a{border-top:1px solid var(--line)}

  /* ── TAP TARGETS, AND THEY BELONG AT THIS BREAKPOINT, NOT AT 760px ──────────
     Moved here in 0.4.41. They were written in the phone block, which was right
     while 760px was also where the menu appeared. Moving the menu to 1023px in
     0.4.40 split the two apart and left a gap nobody had before: between 761px
     and 1023px — iPad portrait is 768px — the site showed a phone MENU while
     keeping desktop tap targets. Measured at 900px on Home: **15 of 21 targets
     under 44px**, back to 12–23px. A tablet is a touch device and was being
     handed a mouse's hit areas.

     ⚠ ONLY THE INVISIBLE ONES CAME UP HERE. The overlay moves no pixel, so it
     is free at any width and helps a mouse as much as a thumb. `.btn` padding
     and the `.fcontact` leading stayed at 760px on purpose — those are visible
     changes tuned for a phone, and widening them would redesign the tablet
     without anyone having looked at it.

     An `::after` rather than padding, because `.more a` is a word with a rule
     under it and padding pushes that rule away from the word. */
  /* ⚠ `p.probono a` JOINED THIS LIST IN 0.4.69, AND IT IS A REGRESSION BEING
     CLOSED, NOT NEW GROUND. The 29 August sweep finished at 153 targets with
     none under 44px. A re-audit at 0.4.68 swept 305 and found exactly one
     failure: "See the pro bono work" on Corporates, a 20px box with no overlay.
     It almost certainly arrived with the 0.4.62-0.4.65 close rewrite, which
     shortened the pro bono note; the note was restyled and never met this list.

     ⚠ THE LESSON IS THE ONE 0.4.37 ALREADY WROTE DOWN: a per-class fix cannot
     know what it has not met, so THE SWEEP IS THE DELIVERABLE. Three rounds
     were needed in August for the same reason. Re-sweep after any release that
     touches a link, rather than reasoning about which ones moved. */
  /* ⚠⚠ `p.person-note a` JOINED IN 0.4.93, AND IT IS THE SAME REGRESSION AGAIN,
     ONE FIELD LATER. The paragraph above was written about `p.probono a` at
     0.4.69 and it says the list cannot know what it has not met. The
     `p.person-note` cross-links shipped in **0.4.84** and never met it: a 22px
     box on `/circles/` at 375px, TWO of them at 900px — *"the corporate
     programmes"* and *"Signature Sessions"*. Every sweep from 0.4.84 to 0.4.92
     reported clean, because every sweep was reasoning about which links had
     moved rather than measuring all of them.

     ⚠ 0.4.92 made the box BIGGER, not smaller — `person-note` went 13.5px to
     15px with the two-tier scale. **It was failing for eight releases and the
     type change is what finally put a sweep on it.**

     ⚠ AND THE SWEEP THAT FOUND IT NAMED THE WRONG ELEMENT FIRST — a nav link
     at 22px, which turned out to be `display:none` at that width and caught
     mid-layout. The real one was two elements away. Re-measure a lone failure
     before naming it. */
  /* ⚠ `.signature .book a` JOINED THE LIST IN 0.4.96, AND IT WAS MISSING
     BEFORE. The booking link is the one action on Signature Therapies and it
     was an 11px box — the audit of 0.4.35 counted "13 of 13 on Signature
     Sessions" under 44px and this selector never made it into the fix. Setting
     it larger in the new call-out gets it to about 34px, which is still short,
     so it takes the overlay like every other link the site wants tapped. */
  .more a,.flink,.legal a,.brand,.menu-label,p.probono a,
  p.person-note a,.signature .book a{position:relative}
  .more a::after,.flink::after,.legal a::after,.brand::after,
  .menu-label::after,p.probono a::after,p.person-note a::after,
  .signature .book a::after{
    content:"";position:absolute;inset-inline:0;top:50%;
    transform:translateY(-50%);height:44px}


  /* ── AND THE TWO VISIBLE ONES, WHICH I ARGUED SHOULD STAY AT 760px ──────────
     I proposed leaving these on phones only, on the grounds that they move
     pixels and a tablet should not be redesigned unseen. Then I measured 900px
     with everything else fixed and five targets were still failing:
     the pill at 37px twice, and the footer email and both numbers at 23px.
     Leaving them is knowingly handing an iPad a 23px email link, which is the
     exact gap this release exists to close. The visible cost is a slightly
     taller pill and a more open footer contact block, below 1024px only. */
  .btn{padding:15px 26px}
  /* THE CONTACT LINES: 0.4.35 GOT THIS HALF RIGHT AND IT IS WORTH SAYING WHY.
     They are stacked with <br>, so two 44px overlays would have sat on top of
     each other — correct — and the answer was to open the leading instead.
     But leading moves the lines APART without making either one TALLER: the
     anchors were still 23px boxes with more air around them. Measured after
     release: 23px, unchanged. Spacing is not a tap target.

     So both, now: leading to hold them apart, and padding to grow the box.
     18px × 2.6 = 46.8px per line against a 45px box — they clear each other by
     under two pixels and never overlap.

     ⚠ AND THE UNDERLINE HAD TO STOP BEING A BORDER. `border-bottom` sits on the
     edge of the box, so padding the box drops the rule 11px below the words —
     the exact failure the ::after overlay exists to avoid elsewhere. A text
     decoration is drawn on the text and ignores padding entirely. Same weight,
     same colour, and it now hugs the word the way the border used to. */
  .fcontact{line-height:2.6}
  .fcontact a{display:inline-block;padding-block:11px;border-bottom:0;
    text-decoration:underline;text-decoration-thickness:1px;
    text-decoration-color:rgba(44,48,44,.2);text-underline-offset:5px}
  .fcontact a:hover{text-decoration-color:var(--ink)}

  /* ⚠ `.menu-label` IS IN THAT LIST AND SHOULD HAVE BEEN SINCE 0.4.35. It has
     measured **36px** since the first audit on 29 August, through three
     releases whose entire subject was tap targets — because each of those
     releases fixed the classes it already knew about and this one lives in the
     header, which nothing in that sweep had reason to look at. It is the most
     used control on the site and it is now shown at every width up to 1023px.
     The overlay rather than padding, again: padding here grows the masthead,
     which is the thing 0.4.35 spent 22px shrinking.
     No collision — the wordmark sits at the left of the header row and MENU at
     the right, so their hit areas never meet. */
}
/* ⚠ THAT CLOSING BRACE WAS MISSING FROM 0.4.41 UNTIL 0.4.44, AND NOTHING SAID SO.
   The 0.4.41 edit replaced a string ending in this block's `}` and did not put
   it back, so the phone block below was NESTED inside the 1023px block for three
   releases. That is valid CSS and it resolved to the same thing — 760 is inside
   1023, so the intersection is just max-width:760px — which is why every
   measurement taken in that time was correct and no page ever rendered wrong.

   What it broke was the checker. `tools/check.php` counts braces to find each
   media query, so the unclosed block swallowed the rest of the file and the
   phone block could not be found — disabling the equal-specificity ordering
   check, the one guarding the failure this project has had seven times.

   ⚠ THE LESSON IS ABOUT THE EDIT, NOT THE BRACE. An Edit whose `old_string`
   ends at a closing brace will take that brace with it. Anchor a replacement on
   something inside the block, or put the brace back in the same edit. */

@media (max-width:760px){

  /* The build ribbon is a note to us — type names and a reminder. It wrapped
     onto two lines and ate the top of every page. */
  .ribbon{display:none}

  /* THE HEADER. At 390px the wordmark broke across five lines — "SVã / flo /
     — / find / yourself" — and ran off the left edge, while the nav ran 205px
     off the right. Both fixed here.
     The tagline goes rather than wraps: it is set again in the footer, so
     nothing is lost by letting the mark stand alone at the top. */
  /* ⚠ THE SIDE PADDING HAS TO BE PUT BACK BY HAND HERE, and getting this
     wrong is what the first phone render showed: two rules — `.site-header
     .wrap` and `.hero .wrap` — override `.wrap` with the `padding` shorthand
     and a `0` in the horizontal slot. On a desktop that is invisible, because
     the wrap is 1180px inside a wider window and the empty space either side
     comes from `margin:0 auto`. At 390px there is no space either side, so
     the wordmark sat against the left edge and MENU was cut off by the right.
     Written as padding-block/padding-inline so the next person cannot make
     the same mistake by editing one number. */
  .site-header .wrap,.hero .wrap{padding-inline:24px}
  /* ⚠ `flex-wrap:wrap`, and it must be. The first attempt said `nowrap` to
     stop the wordmark breaking — but the open menu needs a row of its own
     beneath the header, which it takes with `flex-basis:100%`, and a nowrap
     container cannot give it one. The nav came up as a tall third column
     beside the wordmark, overlapping the hero. The wordmark is held on one
     line by `white-space:nowrap` on `.brand` instead, which is where that
     job actually belongs. */
  /* ⚠ 24px/20px BECAME 12px/10px, 29 August 2026, AND THE NOTE ABOVE THIS BLOCK
     ARGUES THE OTHER WAY ON PURPOSE. It says the phone header "is already only
     84px and needs none of this". That was true as a statement about the
     desktop compaction rule and it is left standing, because the reasoning is
     still right for what it was about. What it did not weigh is that 84px of a
     360×800 phone is 10.5% of the viewport held permanently, against 153px of a
     900px desktop screen being 15% held only until the first scroll. RJ chose
     56px on the phone on 29 August after seeing the measurement.
     12 + 10 + the 21px wordmark's line box ≈ 56px. Measured after building,
     not assumed — see AUDIT-mobile-UX-29-Aug.md. */
  .site-header .wrap{padding-block:12px 10px;gap:14px;align-items:center}
  .hero .wrap{padding-block:clamp(20px,5vw,34px) 56px}
  .hero-copy{padding-left:0}
  /* ⚠ 36 ON A PHONE TOO, AND NOT THE 21px-EQUIVALENT. The text dropped to 21px
     here; the proportional lockup would be 32px, whose ink is 91px — under
     §11's 100px floor. 36 is the smallest legal size and it still leaves the
     menu label room at 360px. */
  .brand img{height:36px}
  .brand{white-space:nowrap}
  .brand i{display:none}

  /* EVERY TWO-COLUMN THING, TO ONE. The hero puts its words above its
     picture — on a phone the headline is what the reader came for, and an
     image first pushes it under the fold. */
  .hero .wrap,.person-body,.doors,.thinks,.gallery,.fcols{
    grid-template-columns:1fr}

  /* ── THE SCALE, ON A PHONE ──────────────────────────────────────────────────
     The reasoning, the two constants and the before-measurements are with the
     base tokens near the top of this stylesheet. This block moves the DISPLAY
     tokens down: a phone column is 312px, and the desktop lead at 25px would
     set about four words to the line.

         detail  x 7.53   Mulish 15px       — NOT overridden here, see below
         body    x 8.54   Mulish 17px       — NOT overridden here, see below
         lead    x 8.15   Cormorant 21px
         opener  x 8.93   Cormorant 23px

     ⚠⚠ THE TWO BODY TIERS ARE NO LONGER OVERRIDDEN ON A PHONE — 0.4.91, and it
     is deliberate. `--t-body` used to drop to 15px here, which was a fiction:
     `body{font:300 17px…}` is not overridden, so 122 of the phone's blocks
     ALREADY rendered at 17px Mulish and only about.css's two `var(--t-body)`
     uses ever saw the 15. The token disagreed with the page. Width-invariant
     body tiers are what the study measured and what the site was mostly already
     doing; the display tokens above still step down, which is the part a 312px
     column actually needs.

     ⚠ Still ascending — detail 7.53 < body 8.54 < lead 8.15 … NO. Lead at 21px
     Cormorant is x 8.11, which is BELOW the body tier's 8.54. That is the
     0.4.90 inversion in a new place, and it is why `p.lede` below points at
     `--t-body-c` rather than `--t-lead`. Do not "tidy" it back onto `--t-lead`
     without re-measuring both in x-height. */
  :root{
    --t-lead:23px;
    --t-open:25px;
  }

  /* ── THE PERSON SECTION READ UPSIDE DOWN ON A PHONE ─────────────────────────
     RJ, 29 August, from an actual iPhone: the text under the photograph looks
     bigger than "A Somatic Soul Integrated System" and the copy beneath it,
     which matters more. He was right, and the cause is x-height rather than
     font-size:

         photo caption   15px Mulish              x-height 7.52px
         the real copy   16px Cormorant Garamond  x-height 6.18px

     The caption is a point SMALLER and reads 22% LARGER, because Cormorant has
     a very small x-height and Mulish a large one. Comparing the numbers in the
     stylesheet would never have shown it; it needs measuring what the two
     faces actually put on the glass.

     ⚠ AND THE 16px FLOOR WAS NEVER MEANT FOR A PHONE. `p.person-lead` is
     `clamp(16px,1.8vw,22px)`, and the note above that rule explains the floor:
     the three lead paragraphs were sized so they end level with the bottom of
     the photograph BESIDE them. That is a two-column measurement. Six lines
     above this one, `.person-body` collapses to a single column — so on a
     phone the constraint the floor exists to satisfy does not exist, and only
     its cost survives. This raises the floor where the picture is no longer
     beside anything, and touches neither the clamp's top nor the desktop.

     20px is not a new number: it is what Home's other body copy is already set
     at, in `.thinking` and `.gallery-section`. This section was the outlier.
     14px on the caption is likewise the site's own vocabulary for a grey aside
     — `p.person-note` is 13.5px. Result: x-height 7.72 against 7.02, the copy
     that matters now reading larger than the caption instead of smaller. */
  /* ⚠ 20px → `var(--t-lead)` (21px here) IN 0.4.90, AND IT IS THE SAME FIX AS
     THE ONE ABOVE RATHER THAN A CHANGE OF MIND. The note above reached 20px by
     borrowing what Home's other body copy was set at, which was right about the
     size and wrong about the method: the scale is DECLARED at the top of this
     file in x-height — `--t-lead` is 21px on a phone, x 8.11 — and this rule
     simply was not pointing at it. `p.lede` and the door pages' `person-lead`
     had the same fault and are fixed the same way in 0.4.90, so all four now
     resolve to one value that moves if the scale does. */
  .person-copy .person-lead{font-size:var(--t-body-c);line-height:1.5}
  .portrait figcaption p{font-size:var(--t-detail)}

  /* ── THE LEDE WAS SMALLER TO READ THAN THE CAVEAT — 0.4.90 ─────────────────
     RJ, 4 September. `p.lede` is `clamp(17px,1.7vw,21px)`, so a phone gets 17px
     Cormorant — **x-height 6.56px against `--t-aside`'s 6.78px**. The sentence
     under the h1 on all thirteen pages put less on the glass than the note at
     the bottom of the section. The full reasoning, the measurements and the two
     companion rules are in audience.css's phone block; this half is here
     because the lede is on every page and only five load that stylesheet.

     ⚠ `--t-lead` RATHER THAN A NUMBER. Desktop is untouched: the clamp's top is
     21px and `--t-lead` is `clamp(23px,1.9vw,25px)` there, so this rule is
     scoped to the phone block deliberately. Widening the lede on a desktop is a
     separate decision and it is not being taken here. */
  p.lede{font-size:var(--t-body-c)}
  /* One column on a phone. Two at 390px gives each review about 150px of
     measure, which is three words a line. */
  .rwall{columns:1}
  /* ⚠ `.scroller` IS NOT IN THAT LIST ANY MORE. It was, because it was a grid;
     it is a flex row now and `grid-template-columns` would do nothing while
     looking like it did something. Swiping is the natural gesture on a phone,
     so it stays a scroller here — narrower cards and a shorter fade. */
  .scroller{padding:34px 20px 20px;gap:26px;
    -webkit-mask-size:100% calc(100% - 12px),100% 12px;
    mask-size:100% calc(100% - 12px),100% 12px}
  .scroller .review{flex:0 0 78vw}
  .hero .wrap{gap:34px}
  .thinks,.doors{margin-top:40px;gap:34px}

  /* ── THE THREE SIGNS READ AS ONE BLOCK ON A PHONE — 0.4.79 ─────────────────
     RJ: *"the 3 signs on home… seem like a block of text whereas they are 3
     distinct points."*

     ⚠ IT IS ARITHMETIC, NOT TASTE, AND THE NUMBERS SAY SO. Measured at 375px:
     the three set at 20px Cormorant on a **31px line-height**, and the gap
     between them is **34px** — three pixels more than the space between two
     lines INSIDE a thought. At 4, 5 and 5 lines that is fourteen lines of
     evenly-spaced text with nothing to divide it. There was never a separator
     here: on a desktop `.thinks` is three columns and the separation is
     spatial, and the phone block above collapses it to one column and replaces
     it with nothing.

     ⚠ A DIVIDER BETWEEN, NOT A MARKER ON EACH. Two rules for three points
     rather than three. `_RESUME.md` §3.3 records the objection to the other
     shape — several instances of the site's one ornament inside a single block,
     against the scarcity principle — and this is the reading of it that adds
     the fewest. It is also not a new ornament at all: every `dl` on this site
     already divides its rows with this exact hairline, so this is the existing
     vocabulary doing the job it already does.

     34px of gap above the rule and 34px of padding below it, so the rule sits
     centred in the break rather than hanging off the thought above it. */
  .think + .think{border-top:1px solid var(--line);padding-top:34px}
  .gallery{gap:30px}

  /* The diary was three fixed columns — 150px, then flexible, then 220px.
     220px of "Women's circle · Kolkata" in a 390px viewport is where the
     second overflow on the home page came from. */
  .events li{grid-template-columns:1fr;gap:6px;padding:20px 0}
  .events .where{text-align:left}
  .events .what{font-size:23px}

  /* The closing section is indented on a desktop so it sits away from the
     page edge. There is no room to be away from anything at 390px. */
  .close .wrap{padding-left:24px}

  .fcols{gap:30px}
  /* ⚠ THE LEGAL LINE STACKS TOO. Two spans at opposite ends of a 342px phone
     leaves the copyright and the legal links jammed against the screen edges
     with a gap in the middle. */
  .legal{flex-direction:column;gap:8px}

  /* ── THE SECTION RHYTHM, ON A PHONE ─────────────────────────────────────────
     ⚠ `clamp(64px,9vw,132px)` NEVER LEFT ITS FLOOR HERE, and that is the whole
     bug. 9vw of 360px is 32px, below the 64px minimum, so every phone got the
     *desktop* minimum — 64px top and 64px bottom on every section. Measured:
     1,168px of padding on Home, 1,296px on About, 1,424px on Corporates,
     which is 11–13% of each page spent on nothing.

     40px here, not a smaller clamp, because a clamp that has already bottomed
     out is a number wearing a costume. Saves roughly 480px a page.

     ⚠ THIS IS A SPACING-SCALE CHANGE AND THE SCALE IS ONE OF THE FOUR THINGS
     REOPENED ON 25 AUGUST. RJ took the decision on 29 August with the
     measurement in front of him. It is deliberately confined to the phone
     block: the desktop rhythm is untouched and is still the open question. */
  section{padding:40px 0}


  /* ── TAP TARGETS ────────────────────────────────────────────────────────────
     Measured at 360×800: 11 of 11 links on Individuals under 44px, 13 of 13 on
     Signature Sessions, 12 of 12 on Contact. `.more a` was 12px tall. These are
     the links the site most wants tapped.

     ⚠ AN OVERLAY, NOT PADDING, AND THE REASON IS THE UNDERLINE. `.more a` is
     read as a word with a rule under it; padding the anchor pushes that rule
     away from the word and quietly redesigns the component. A transparent
     ::after centred on the link raises the hit area to 44px and moves not one
     visible pixel.

     `inset-inline:0` rather than `left/right:0` so it follows the text box, and
     `pointer-events` is left alone — the pseudo-element belongs to the anchor,
     so a tap on it is a tap on the link. */
  /* ⚠ THE OVERLAYS MOVED TO THE 1023px BLOCK IN 0.4.41 — see the note there.
     They used to live here, which meant a tablet showing the phone MENU still
     had 12px desktop tap targets. Measured at 900px on Home: 15 of 21 under
     44px. Nothing to declare in this block any more. */

  /* ⚠ MOVED TO THE 1023px BLOCK IN 0.4.41 — a tablet is a touch device too. */

  /* ⚠ MOVED TO THE 1023px BLOCK IN 0.4.41 — see the note there. */

  /* ── THE FOLDS ──────────────────────────────────────────────────────────────
     Six sections carry `fold` in fields.php — three on About, three on
     Corporates. Measured at 360×800, About's three are 4,202px of a
     11,659px page: 5.25 screens out of 14.6. Folded they cost about 360px.

     ⚠ THE CLIPPING IS DECLARED HERE AND NOWHERE ELSE, so it never has to be
     undone for a desktop. The control is the other way round: hidden globally
     next to `section{}` above, shown here. Both halves are needed — see the
     note on `.fold-l{display:none}`, which is there because the first version
     of this block forgot it and printed the label on every desktop.
     A desktop reader sees exactly what they saw before this release.

     Not zero: the eyebrow and the heading stay visible, so the fold says what
     it is holding rather than being an unlabelled band.

     ⚠⚠ 240px WAS TOO TIGHT AND THE FADE IS WHY — RAISED TO 340 IN 0.4.81.
     RJ, 2 September, of Corporates' `argument`: *"The read why it works
     mechanism is starting too soon. Allow a line or two to be read."*

     The clip measures from the top of the wrap, so what a reader gets is
     240px MINUS the heading — and the heading is the part that varies.
     Measured at 375px:

         SECTION      eyebrow  h2    heading block   body visible
         argument       24px   135px    187px          2.0 lines
         session        11px    84px    123px          4.2 lines
         clients        11px    56px     95px          6.1 lines

     ⚠ AND THE 96px FADE COVERED ALL OF IT. On `argument` the body occupied
     187→240px — fifty-three pixels, entirely inside the gradient. **There was
     no un-faded body text on that section at all**, which is why it read as a
     teaser rather than an opening. The other five folds were fine, so this
     never showed up as a general fault.

     `argument` is the outlier because its eyebrow WRAPS TO TWO LINES — *"Why
     SVã flo works where a briefing does not"* — and its h2 runs to three.
     Nothing else on the site does both.

     **340 with a 72px fade gives the worst case three clear lines**, checked by
     rendering it at 375px and looking, not by arithmetic. The generous sections
     get more, which is the cost of one number serving six headings of different
     heights. ⚠ Every fold still hides well over `MIN_HIDDEN` (main.js) — the
     smallest is `clients` at 477px — so raising the clip strips none of them. */
  /* ⚠ `:not(.fold-out)` — 0.4.86. `svaflo_fold_wrap()` now lifts a `.more`
     link out of the clipped wrap and re-emits it in a second wrap after the
     label, so that a "read all" destination is not hidden by the fold. Without
     this exclusion that second wrap gets clipped to 340px too, and a 23px link
     inside a 340px box is invisible for a different reason. See render.php. */
  /* ── THE CLIP IS A CUSTOM PROPERTY, NOT A NUMBER — 0.4.88 ──────────────────
     340 is still the answer for ten of the eleven folds and it is still the
     default here. What changed is that `clients` — the only fold on the site
     built from labelled groups rather than paragraphs — can now be clipped to a
     group boundary by main.js, so the cut does not land on a bare group label
     with its names below it.

     🔴 A CUSTOM PROPERTY BECAUSE AN INLINE `style.maxHeight` WOULD BREAK THE
     FOLD OPEN, SILENTLY. An inline style beats a stylesheet rule, so
     `.fold-t:checked ~ .wrap{max-height:none}` on the next line would stop
     winning and the fold would never open again. Written up before it was built
     — `Copy/institutions-full-page-draft.md` — and it is the whole reason that
     note exists. The property is set on the wrap; this rule reads it; the
     `:checked` rule still wins on specificity exactly as it did. */
  .fold > .wrap:not(.fold-out){max-height:var(--fold-clip,340px);overflow:hidden;position:relative}
  .fold-t:checked ~ .wrap{max-height:none;overflow:visible}

  /* ── THE ONE FOLD THAT CLIPS SOMETHING OTHER THAN `.wrap` — 0.4.87 ─────────
     Home's `person` was folded on RJ's instruction (see fields.php). Every
     other fold on the site opens its wrap with an eyebrow and a heading, so a
     340px clip lands in body copy. THIS ONE OPENS WITH A 641px PORTRAIT —
     measured at 388px, `.wrap` is a one-column grid of FIGURE 641 then
     `.person-copy` 1124. The ordinary rule would have clipped at 340 and shown
     the top half of the picture and not one word of the copy.

     So the wrap is released and `.person-copy` is clipped in its place. The
     portrait stays whole, the words fold under it.

     ⚠ AND main.js NEEDS NO CHANGE, BY LUCK RATHER THAN DESIGN — CHECK THIS IF
     EITHER FILE MOVES. `unfoldIfPointless()` reads `.wrap`, and its first guard
     is `if maxHeight === 'none' return`, written for the desktop case. Here the
     wrap genuinely is `none`, so the guard returns early and the fold is left
     alone rather than judged and stripped. The right outcome for the wrong
     reason: the rule that protects this is about desktops, not about portraits. */
  .person.fold > .wrap{max-height:none;overflow:visible}
  .person.fold .person-copy{max-height:340px;overflow:hidden;position:relative}
  .person.fold .person-copy::after{content:"";position:absolute;inset:auto 0 0;height:72px;
    background:linear-gradient(to bottom,transparent,var(--paper));pointer-events:none}
  .fold-t:checked ~ .wrap .person-copy{max-height:none;overflow:visible}
  .fold-t:checked ~ .wrap .person-copy::after{display:none}

  /* The fade is the affordance — it is what says "this continues". It has to
     go when the fold opens, or it sits over live copy. ⚠ `pointer-events:none`
     because it covers the last line of text and would otherwise eat taps on
     any link in it. Painted from the section's own ground, so it works over
     both bg-1 and bg-2 without a second rule.

     ⚠ 96px → 72px IN 0.4.81, and it is the same fix as the clip above rather
     than a second one. The fade eats the bottom of whatever is visible, so at
     240/96 it consumed every line `argument` had. Shortening it buys a clear
     line back on all six folds without raising the clip further, which is the
     cheaper half of the trade — 24px of legibility against 0px of extra scroll.

     🔴🔴 AND THE FIVE LINES ABOVE SPENT FOUR DAYS OUTSIDE THIS COMMENT — 0.4.81
     TO 0.4.87. The comment ended one line early, after "second rule", and the
     note that followed ran as bare text until a comment-close of its own. A CSS
     parser reads that text as the start of a selector, swallows everything up
     to the next brace, and DROPS THE DECLARATION BLOCK IT FINDS THERE. So this
     rule — the one directly beneath — never applied.

     ⚠⚠ AND WRITING THIS NOTE REPRODUCED THE BUG, IN THE COMMENT DESCRIBING IT.
     The first draft quoted the offending characters. A CSS comment does not
     nest and does not respect quotation marks, so the quotation closed the
     comment and everything after it — including the repair — ran as bare text
     again. Caught by a scanner that tracks comment state across the file, not
     by reading it. **Never put the two-character comment-close inside a
     comment; describe it in words.** The scanner is worth keeping: it also
     reports brace balance once comments are stripped, which is what makes a
     swallowed rule visible at all.

     ⚠ THE FADE DID NOT SHRINK IN 0.4.81. IT STOPPED EXISTING. Measured live at
     0.4.87 before the repair: `content` computed to `none` on all four
     Corporates fold wraps, so no pseudo-element was generated at all. Ten of
     the eleven folds on the site ended in a hard cut. Only Home's `person`
     faded, because `.person-copy::after` is declared ABOVE the stray text and
     the parser had not yet gone wrong.

     ⚠ AND `.bg-2 …::after` KEPT WORKING, WHICH IS WHY NOTHING LOOKED BROKEN.
     It sits after the invalid block, so it parsed — two of the four wraps
     reported a real `background-image` and no `content`. A background on a
     pseudo-element that does not exist is inert, and a DOM check for the rule
     would have found it present. **Only `content: none` said so.**

     ⚠ THE RELEASE THAT BROKE IT IS THE RELEASE THAT DOCUMENTED IT. Dated by
     unzipping the archives in Web/theme: 0.4.79 and 0.4.80 carry
     `.fold > .wrap::after{…height:96px…}` intact; the stray text first appears
     in 0.4.81, whose stated purpose was to shorten this fade. The change was
     verified by looking at the page, which showed more clear lines — exactly
     what deleting the fade also produces. **The measurement agreed with the
     intention for the wrong reason.**

     ⚠ AND IT MOVES A NUMBER IN A FILE THAT IS NOT THIS ONE. `_RESUME.md` §2.6
     records "worst case 3.0 clear lines" after 0.4.81. With no fade the real
     figure was 5.7 on Corporates `argument`. Restoring the fade restores 3.0.
     RJ was given both numbers and chose the fade — 4 September. */
  .fold > .wrap:not(.fold-out)::after{content:"";position:absolute;inset:auto 0 0;height:72px;
    background:linear-gradient(to bottom,transparent,var(--paper));
    pointer-events:none}
  .bg-2.fold > .wrap:not(.fold-out)::after{background:linear-gradient(to bottom,transparent,var(--paper-2))}
  .fold-t:checked ~ .wrap::after{display:none}

  /* The control. Sized as a real target from the start rather than padded up
     afterwards — 44px is the floor and this clears it. */
  /* ⚠ 16px, NOT 15px. 15 + 12px line + 15 + 1px border came to 43 — one pixel
     under the 44 this whole section exists to reach, and it shipped in 0.4.35
     because the number was reasoned about rather than measured. 16 gives 45. */
  .fold-l{display:block;margin:18px 24px 0;cursor:pointer;
    font:400 12px/1 Mulish,sans-serif;letter-spacing:.1em;text-transform:uppercase;
    color:var(--sage);padding:16px 26px 16px 0;border-top:1px solid var(--line);
    position:relative}
  /* ⚠ AND `[hidden]` HAS TO BE SAID OUT LOUD HERE. main.js sets `label.hidden`
     to retire a fold that saves nothing, but `hidden` is a UA-stylesheet
     `display:none` and the author `display:block` two lines up beats it. The
     label would have stayed on screen with the fold already gone. */
  .fold-l[hidden]{display:none}
  .fold-less{display:none}
  .fold-t:checked ~ .fold-l .fold-more{display:none}
  .fold-t:checked ~ .fold-l .fold-less{display:inline}

  /* ── THE SIGN — 0.4.88 ─────────────────────────────────────────────────────
     RJ asked on 3 September whether the gap between this control and the
     `.more` link beneath it was too tight. Measured: 0px box-to-box, ~16px of
     visible whitespace, and the label is a 45px target, so nothing was wrong
     with the spacing. Looking at it said what the ruler could not — the control
     is 12px tracked caps with NO SIGN THAT IT OPENS ANYTHING, sitting directly
     above an underlined link. The one that looks like a link leaves the page;
     the one that reveals a third of the section looks like a heading.

     So the answer was not the gap. It is the affordance the per-row folds have
     had since 0.4.79, borrowed unchanged: a `+` that loses its upright to
     become a `−`. Two bars rather than a glyph, so it is identical at any type
     size and does not depend on a font.

     ⚠ `padding-right:26px` ON THE LABEL ABOVE, or a long noun runs under the
     sign. "Read what a session looks like" is the longest in the theme.

     ⚠ AND NO `transition`. `.rfold-i` has none either and says why: a
     transition on a pseudo-element does not resolve when the selector that
     changed is structural, and it fails silently — the sign simply stays a `+`.
     That one was a `:has()`; this is `:checked ~`, which is not the same
     mechanism and might well have worked. Not worth finding out on a control. */
  .fold-l::before,.fold-l::after{content:"";position:absolute;right:0;top:50%;
    background:currentColor}
  .fold-l::before{width:13px;height:1.5px;margin-top:-.75px}
  .fold-l::after{width:1.5px;height:13px;margin-top:-6.5px;right:5.75px}
  .fold-t:checked ~ .fold-l::after{opacity:0}

  /* ⚠ THE FOCUS RING BELONGS TO THE LABEL, NOT THE INPUT. The input is
     `hidden`, so it cannot take focus and cannot show a ring; main.js gives the
     label `tabindex="0"` and it is the label a keyboard reader lands on. */
  .fold-l:focus-visible{outline:2px solid var(--sage);outline-offset:3px}

  /* ── ROWS THAT OPEN ONE AT A TIME — 0.4.79 ─────────────────────────────────
     RJ: *"make the individual therapy names expandable… Dont lay out the whole
     info in a scroll"*, then *"use this device elsewhere as well whereever
     useful."* Measured at 375px, two lists qualify: `practices` on Individuals
     and the FAQ answers. See svaflo_disclosure_row().

     ⚠ IT LIVES IN main.css BECAUSE IT SERVES TWO TEMPLATES. `practices` is on
     `audience`, the questions are on `faq` — which loads `about.css`. Putting
     the rules in either sheet would have meant maintaining two copies, and this
     file already records what happens when one copy drifts. Nothing else on the
     site uses `.rfold-`, so there is nothing here to collide with.

     ⚠ GATED ON `:has()`, AND THE GATE IS THE SAFETY. The checkbox sits in the
     `dd` and the label in the `dt` — they must, because `<input>` is invalid as
     a sibling of `dt`/`dd` — so `~` cannot reach from one to the other and only
     `:has()` can. **Written the other way round it would fail dangerously**: a
     browser without `:has()` drops the rule, and a bare `.rfold-b{display:none}`
     would then hide every description permanently with nothing to open it. So
     the whole block is inside `@supports`, and a browser without support gets
     precisely today's page — every row open, no control, nothing lost. */
  @supports selector(:has(*)){
    .rfold-l{display:flex;align-items:center;justify-content:space-between;
      gap:16px;min-height:44px;cursor:pointer}
    .rfold-n{flex:1 1 auto}

    /* The sign is drawn, not typed: a `+` and a `−` in Cormorant are different
       widths and different heights, so swapping the glyph would shift the row.
       Two bars, and the upright one goes — the crossbar never moves.

       ⚠ NO TRANSITION, AND IT IS NOT A STYLE CHOICE — IT DID NOT WORK.
       `transition:opacity .18s` was written here first and the sign stayed a
       `+` when the row opened. Proved in an injected rig at 375px before
       shipping: `width` and `background` set through the same
       `:has()` rule reach the pseudo-element correctly (99px, red), but with
       the transition present `opacity` reads `1`, and with `transition:none`
       the identical rule reads `0.2`. **A transition on a pseudo-element whose
       match changed through `:has()` does not resolve**, and it fails silently
       — the rule is in the sheet, the selector matches, `querySelectorAll`
       finds the element, and the paint never changes. Nothing else on this site
       animates a fold, so this costs nothing. */
    .rfold-i{display:block;flex:0 0 auto;position:relative;width:13px;height:13px}
    .rfold-i::before,.rfold-i::after{content:"";position:absolute;
      background:var(--sage)}
    .rfold-i::before{top:6px;left:0;width:13px;height:1.5px}
    .rfold-i::after{top:0;left:5.75px;width:1.5px;height:13px}
    .rfold-row:has(.rfold-t:checked) .rfold-i::after{opacity:0}

    .rfold-row:not(:has(.rfold-t:checked)) .rfold-b{display:none}

    /* ⚠ THE ROW'S OWN GAP MUST GO WHEN THE ROW IS SHUT. `.outcomes > div` and
       `.qa > div` both set a row gap for the stacked term-above-description
       layout; with the description gone that gap is dead space under every
       closed name, and eleven of them read as a loose, drifting list. */
    .rfold-row:not(:has(.rfold-t:checked)){row-gap:0}

    .rfold-l:focus-visible{outline:2px solid var(--sage);outline-offset:3px}
  }
}
