:where(.sl-body) *, :where(.sl-body) *::before, :where(.sl-body) *::after { box-sizing: border-box; }
/* Design rule R7 (see designRules.ts): ONE two-tier content-width system so scrolling reads
   as one cohesive column, never a patchwork of ad-hoc max-widths.
   --content-max      = the WIDE edge (card/tile grids, full-width media rows).
   --content-measure  = the TEXT edge (prose, lists, tables, section headers) — one readable
                        line length. Every text column uses .sl-prose / var(--content-measure);
                        never a bespoke 640/720/760/800 inline width. */
:where(.sl-body) { --content-max: 1120px; --content-measure: 820px; }
/* Shared centered text column (R7). Use for any prose/list/table content block. */
:where(.sl-body) .sl-prose { max-width: var(--content-measure); margin-left: auto; margin-right: auto; }

/* ══ HOW TALL A HERO IS — ONE DECISION, ONE HOME ═══════════════════════════════════════════════
   Ian, on his own live sites: "the hero for whatever reason is a bit shrunk height-wise. You can
   even see the hero is being cut off vertically, like the guy's head is being cut off... A lot of
   the best websites I've shown you have had much larger hero sections, so I think this is a
   SiteLaunch system mechanic that needs to be corrected."

   He was right, and it was a mechanic. Twenty-five separate places decided a hero's height before
   this rule: seventeen in this stylesheet, eight inside hero components. Twelve were screen-driven,
   five were bare pixel numbers, four were driven by how WIDE the window is — and those four were
   the newest, the component-level ones, including the home hero of every family. Caps ran from
   560px to 1000px with no stated reason for any of them. The full account, with the numbers and
   the five reference sites they were measured against, is in lib/heroBox.ts.

   THE RULE:  a hero is as tall as its own photograph needs, never taller than the screen, never
              shorter than a floor that is itself a share of the screen.

     min-height: max( FLOOR, min( WHAT THE PICTURE WANTS, WHAT THE SCREEN ALLOWS ) )

   There is deliberately NO max-height and no pixel cap. The whole rule is a MINIMUM, so a headline
   longer than the picture grows the band instead of being clipped — which is exactly what an
   `aspect-ratio` hero could not do, and why the picture's shape enters as a CEILING rather than as
   a fixed shape.

   WHAT A FAMILY MAY DIFFER ON. Two levers, both one value, both explicit — never another number:
     --sl-hero-fill    the share of the screen this family's hero may take (1 = the whole fold).
                       Lower it for a family whose hero is deliberately a band rather than a stage.
     --sl-hero-want    set to 0 by `.sl-hero-nopic` when a hero carries NO photograph. There is no
                       picture to show whole, so the picture term is meaningless and the floor is
                       the whole answer.
   Everything else a family legitimately differs on — where the copy sits in the frame, its padding,
   its wash — is layout and colour, and stays where it always was.

   AND ONE MORE THING THE OLD RULE GOT WRONG: the crop. `background-position: center` threw equal
   slices off the top and the bottom of every hero photograph with no idea where the subject was,
   and faces live in the upper third of a frame — 233px came off the top at 1920 wide. The bias is
   32% and it is a variable, so a page whose subject sits low says so (lib/heroBox reads a focal
   point off the media row when one has been measured). ══════════════════════════════════════ */
:where(.sl-body) {
  /* ── HOW MUCH OF THE FIRST SCREEN THE NAVIGATION HAS ALREADY SPENT ───────────────────────────
     96 was a house constant standing in for every family's nav at every width, and it was wrong
     for every family at every width. MEASURED, six home families, seven window sizes, on a built
     page (.hfix/m/B.json):

       family      wide    864 wide   phone
       estate        78        99       93
       bright        96       139      215
       community     53        53      138
       editorial     73       105       65
       retail        79       128      208
       bloom         89       133      185

     Every family wraps its nav links onto extra rows on a phone, and three of them then spend a
     fifth to a quarter of the screen on the menu bar. The hero's ceiling — "never taller than the
     screen" — was subtracting 96 from all of them, so on a phone it handed bright 119px of screen
     that did not exist, which is precisely how a booking control ended 42px past the bottom edge
     while every variable in the cascade said the hero fitted.

     So this is not a house constant any more. It is one value each family states for itself at
     each width where its own nav changes shape — the same "one value a family may differ on" the
     height rule already publishes for `--sl-hero-fill`. The table lives in ONE place: the block
     named THE FOLD BUDGET further down. 96 stays here as the fallback for anything that does not
     state one (interior templates, the hub chrome), because that is what they were built against.
     A family that redraws its nav must restate its number, and the fold check measures it. */
  --sl-nav-h: 96px;
  /* ── THE UNIT A HERO'S OWN TYPE AND AIR ARE MEASURED IN ───────────────────────────────────────
     THE LAST WIDTH-DRIVEN HEIGHT. Twenty-five places used to decide a hero's height and four of
     them were driven by how WIDE the window is; the rule above deleted all four. It missed the
     one that is not written as a height at all: a headline sized `8.2vw` is a height, because
     three lines of it are three times whatever the width says. Measured on bloom at 1440x720 —
     a laptop, and one of the sizes the reference document was measured at — the headline alone
     took 395px of a 720px screen, and the booking card that sits under it began at 556 and ran
     off the bottom of the window. The same headline in the same family at 1440x900 is correct.
     Nothing about it knew the window had lost 180px of height.

     `1vw` alone lets a window that is wide but SHORT order type it has no room for. `1.55svh` is
     the same size at the proportions the families were drawn at — 1vw and 1.55svh are both 14.4px
     at 1440x900, and 1.55 rather than 1.6 because that is the value at which nothing at his own
     window moves and a 2:1 laptop still gives back its 100px. Whichever is smaller: on a normal
     window the width still decides, and on a short one the screen does.

     A family uses it wherever its hero type or air was a bare `vw`. Everywhere else on the page a
     `vw` is honest, because everywhere else on the page there is no fold to bust. */
  --sl-hero-em: min(1vw, 1.55svh);
  /* The page's own column, captured here as a LENGTH. `--bk-col` itself cannot be read from a band:
     a band wearing one of the ten column words re-declares it as a percentage of that band, and a
     percentage inside a min-height is measured against a height, so `calc(var(--bk-col) / ratio)`
     silently answered 1440/1.7778 at 1440 wide and 1920/1.7778 at 1920 — the window, not the column,
     which is the exact mistake this whole file exists to stop. Declared at :root it is the number
     the page grid actually stops at, and it stays that number wherever it is read. */
  --sl-hero-page-col: var(--bk-col, 1320px);
  /* 16:9 — what the hero generators order, and what the photograph behind this round actually is.
     lib/heroBox overrides it per page from the media row's own measured shape. */
  --sl-hero-ratio: 1.7778;
  --sl-hero-focus-y: 32%;
  --sl-hero-fill: 1;
  /* The floor is a share of the SCREEN as well as a pixel number, so a 667-tall phone gets 414px of
     hero and still shows a clear third of the band beneath it, instead of being eaten by its own
     first screen. Both terms, whichever is smaller. */
  --sl-hero-floor-px: 520px;
  --sl-hero-floor-share: 62;
  /* What a hero with NO photograph is as tall as. The same 62% share, without the 520px — see the
     account on `.sl-hero-nopic`. Stated here so the three places that mark a hero pictureless all
     read one value instead of each writing `0px`. */
  --sl-hero-nopic-want: calc(var(--sl-hero-floor-share) * 1vh);
  /* ── WHERE THE WORDS SIT IN A PHOTOGRAPHIC HERO ───────────────────────────────────────────────
     THE FAULT THIS CLOSES. Making the hero taller stopped it cutting heads off and started
     printing the headline ACROSS one. Both halves of that were decided independently and neither
     knew about the other: the crop bias puts the subject in the TOP of the frame on purpose (32%,
     the line above), and every centred family put its copy in the MIDDLE of the same frame. A
     taller band moved the face down into the middle to meet it.

     MEASURED, on a built page, the same brand and the same 1600x1063 photograph, three families
     at three widths (.hface/shots/BEFORE-face.json). The head lands in the same place at every
     width because a `cover` crop is proportional — 6.8%-34.2% of the band at 1440, 10.8%-33.9% at
     864 and on a phone. The centred copy began at 10.5%-36.4%. So on nine measured heroes, five
     printed a run of words over the woman's face, worst on a phone: the bright headline with 42%
     of its own area over her forehead, the estate eyebrow 43%.

     THE RULE: over a photograph, the copy lives in the LOWER HALF of the band.

     WHY THAT AND NOT THE OTHER THREE LEVERS.
       A HEAVIER WASH would make the words legible, which they already are — measured 7:1 to 20:1
       against the pixels actually behind them, so legibility is not what is failing. It would also
       dim the photograph this round just spent its whole effort enlarging.
       THE CROP BIAS moves the subject, and both directions are wrong: down re-opens the cut heads
       the round closed, up cuts the crown.
       THE PHOTOGRAPH ITSELF — ordering heroes with the subject to one side and clean air for the
       words — is the real long-term answer and cannot fix one picture already in a client library.
     Moving the copy costs no picture, no contrast and no crop, and it is the answer this file
     already reached once: see `.hero-align-center` further down, "pushed to the LOWER half of the
     frame … the top of the frame is the picture, the bottom is the offer". That was scoped to one
     opt-in class so that no existing hero would move, which is why the six home families never got
     it. Here it is the house rule for the full-bleed form. `.hero-align-center` is deliberately
     left where it is: it is a live opt-in on interior pages, its own numbers were measured against
     that layout, and re-pointing it would move designs nobody asked to move.

     BOTH NUMBERS ARE SHARES OF THE BAND, never of the window — which is the mistake the height
     rule was undone for. Keyed to the window the bottom inset was 11vh: 93px on a phone, which
     pushes the copy back UP into the chin on a 520px band.
       COPY-TOP    the top of the band the copy stays out of. A FLOOR, not a position: when the
                   copy is too tall to fit beneath it the BAND grows, exactly as the height rule
                   already grows for a long headline, instead of the words climbing into the face.
       COPY-DROP   air under the last control, so this reads as the lower THIRD and not as the
                   floor. `.hero-align-center` learned that one the hard way — bottom-alignment
                   with no inset ran the BOOK NOW button off the bottom edge of the fold. */
  --sl-hero-copy-top: 0.5;
  --sl-hero-copy-drop: 0.09;
}
:where(.sl-body) .sl-hero-box, :where(.sl-body) .sl-hero-stack, :where(.sl-body) .hero {
  /* Composed HERE, on the hero's own element, and not on :root — that placement is the whole
     trick. A custom property containing var() resolves against the element it is DECLARED on, so
     `--sl-hero-min` written at :root would bake in the house ratio and a page's own
     `style="--sl-hero-ratio: …"` would be silently ignored. Declared here, the page wins. */
  --sl-hero-floor: min(var(--sl-hero-floor-px), calc(var(--sl-hero-floor-share) * 1vh));
  --sl-hero-cap: calc((100vh - var(--sl-nav-h)) * var(--sl-hero-fill));
  --sl-hero-want: calc(100vw / var(--sl-hero-ratio));
  /* THE CEILING OUTRANKS THE FLOOR, which it did not before. `max(FLOOR, min(WANT, CAP))` reads
     as "never taller than the screen" but does not say it: when the floor is the biggest of the
     three — which it is on every phone, where 100vw/ratio is only 260px — the floor wins and the
     band is taller than the screen it was supposed to fit inside. Wrapping the whole thing in the
     cap says the sentence the rule always claimed. Nothing on a desktop moves: there the cap was
     already the answer. */
  --sl-hero-min: min(max(var(--sl-hero-floor), min(var(--sl-hero-want), var(--sl-hero-cap))), var(--sl-hero-cap));
  min-height: var(--sl-hero-min);
  background-position: 50% var(--sl-hero-focus-y);
}
/* ══ A HERO THAT CARRIES A PHOTOGRAPH IS THE FIRST SCREEN ══════════════════════════════════════
   THE FAULT THIS CLOSES, and it is the one that cost a booking button. The copy in a photographic
   hero is pushed into the lower half of the band by a padding FLOOR — half the band's own minimum.
   A floor cannot shrink. So when the copy is taller than the half of the band left under it, the
   band grows by the difference, and it grows without limit: measured on bright at 390x844, a 520px
   minimum bought a 260px inset, the copy under it was 423px, and the band came to 731px inside a
   629px fold. The third hero control ended 42px past the bottom edge. Every variable said it fitted.

   There is no arithmetic that fixes that, because the inset is a share of the band and the band is
   the inset plus the copy — it is circular, and CSS cannot subtract a sibling's height. But the
   construction that answers it exactly needs no arithmetic at all:

     THE BAND IS THE FOLD, AND THE COPY SITS AT THE BOTTOM OF IT.

   `align-items: end` in a band whose minimum is the whole fold places the copy as low as the
   screen permits — which is the largest inset that exists. When the copy is short the inset is
   deep, deeper than the old half-the-band floor. When the copy is tall the inset gives way on its
   own, and the band still ends where the screen ends. The padding floor is deleted: bottom
   alignment already does its job, and unlike a floor it cannot push the button off the screen.

   AND IT ANSWERS HIS ORIGINAL COMPLAINT AT HIS OWN WINDOW. `--sl-hero-want` — 100vw divided by the
   photograph's shape — was the term that decided the height at 864 wide and nowhere else, and what
   it decided there was 576px in a 900px window: the shrunken hero he reported. A photograph used as
   a GROUND is not a thing you show whole; it is a thing you stand words on, and how tall it should
   be is a question about the screen, not about the file. So for the full-bleed form the floor is
   the fold, `want` no longer reaches the answer, and every one of these heroes is the first screen:
     864x900 estate  576 -> 801      390x844 estate  588 -> 751      1440x900 estate 804 -> 822
   A hero with NO photograph is untouched — it keeps the 62% share, because a flat colour field
   filling the whole screen is not a stage, it is a wall. ═══════════════════════════════════════ */
:where(.sl-body) .sl-hero-box:not(.sl-hero-nopic), :where(.sl-body) .sl-hero-stack:not(.sl-hero-nopic), :where(.sl-body) .hero:not(.sl-hero-nopic) { --sl-hero-floor: var(--sl-hero-cap); }
/* EXCEPT WHERE THE PICTURE IS A COMPOSITION AND NOT A GROUND, WHICH IS A DIFFERENT QUESTION.
   A full-bleed hero's photograph fills whatever band it is given, so "be the first screen" costs it
   nothing. A picture-column hero's photograph sits in a column INSIDE the page's own grid, and that
   grid stops growing at `--bk-col` — so past about 1500px of window its composition cannot get any
   bigger no matter how much screen arrives. Handing it the whole of a 1440-tall screen produced
   696px of empty band around a 671px composition: 51% air, which reads as unfinished rather than
   generous. I looked at it at 2560 before writing this line.
   So the band grows with the screen only as far as its own composition can follow, and the shape it
   stops at is the photograph's: the widest this composition will ever be is the page column, and a
   band that wide read at the picture's own ratio is as tall as it should ever get. One expression,
   no new number, and it moves with the picture:
     1440x900  min(827, 880) = 827   (the fold; nothing is capped here)
     1920x1080 min(1007, 880) = 880  (24% air, and it looks like a decision)
     2560x1440 min(1367, 880) = 880 */
:where(.sl-body) .sl-hero-stack:not(.sl-hero-nopic) {
  --sl-hero-floor: min(var(--sl-hero-cap), calc(var(--sl-hero-page-col) / var(--sl-hero-ratio)));
  /* AND `WANT` HAS NOTHING TO SAY HERE, so it says nothing. `--sl-hero-want` is `100vw / ratio` —
     the height at which a full-bleed photograph is shown WHOLE, which is a sentence about a picture
     that IS the band. This family's picture is one column of a composition; the band's height is not
     its height, and letting the term through simply handed the band the window width divided by 1.78
     (810px at 1440, 1440px at 2560) and overrode everything above. Same reasoning, and the same one
     value, as `.sl-hero-nopic`: no full-bleed picture to show whole, so the picture term goes away
     and the floor and the ceiling answer between them. */
  --sl-hero-want: 0px;
}
/* svh is the screen MINUS the phone browser's own chrome, which vh is not — without it a phone
   hero is measured against a screen taller than the one the visitor has. Chrome 108 / Safari 15.4,
   so the vh line above is the fallback and not the intent. */
@supports (height: 100svh) {
  :where(.sl-body) { --sl-hero-nopic-want: calc(var(--sl-hero-floor-share) * 1svh); }
  :where(.sl-body) .sl-hero-box, :where(.sl-body) .sl-hero-stack, :where(.sl-body) .hero {
    --sl-hero-floor: min(var(--sl-hero-floor-px), calc(var(--sl-hero-floor-share) * 1svh));
    --sl-hero-cap: calc((100svh - var(--sl-nav-h)) * var(--sl-hero-fill));
  }
}
/* A HERO WITH NO PHOTOGRAPH KEYS OFF THE SCREEN, BECAUSE THE SCREEN IS ALL IT HAS.
   This said `--sl-hero-want: 0px` — nothing to show whole, so the picture term goes away and the
   floor answers on its own. But the floor is `min(520px, 62svh)`, and on any screen taller than
   839px the 520px half of that wins and NOTHING about the screen can raise it. Measured on an
   invented client: 520px at 1440 wide, 520px at 1920, 520px at 2560 — a 4.9:1 strip on a large
   monitor, which is the owner's original complaint wearing a different costume.

   A pictureless hero has no photograph to be as tall as, so the only honest thing left to key off
   is the screen — and the house has already stated what share of a screen a hero owns: the 62 in
   the floor. So a hero with no photograph is that same 62% of the screen, with the 520px reading
   as what it always was — a convenience for SHORT screens, never a ceiling for tall ones.

     620-tall window   62svh = 384   (the floor was 384 too — nothing moves on small screens)
     900-tall window   62svh = 558   (was 520)
    1080-tall window   62svh = 670   (was 520)
    1440-tall window   62svh = 893   (was 520 — a 4.9:1 strip becomes a 2.9:1 stage)

   The screen ceiling still applies on top of this, so it can never overflow the first screen. */
:where(.sl-body) .sl-hero-nopic { --sl-hero-want: var(--sl-hero-nopic-want); }

/* ══ …AND ON AN INTERIOR PAGE THAT SHARE IS 70, BECAUSE 70 IS WHAT IT ALREADY WAS ══════════════
   THE FAULT THIS CLOSES, AND IT IS THIS ROUND'S OWN. The round was asked for a BIGGER hero. On
   four page types it delivered a smaller one, and three of the four shrank in the 864x900 window
   the owner actually browses in. Measured on an invented client, the same library and the same
   estate lever, built twice — once from this tree and once from the pre-hero commit:

     page type                   1440x900   1920x1080   864x900   390x844
     /about/                        —        756 -> 670  630 -> 558  591 -> 523
     /contact/                   630 -> 628  756 -> 670  630 -> 558  591 -> 523
     /faq/                       630 -> 558  756 -> 670  630 -> 558  591 -> 523
     the treatment-detail page      —        756 -> 704  630 -> 562  591 -> 523

   THE CAUSE, AND IT WAS A DELIBERATE DECISION RATHER THAN AN ACCIDENT. The rule above gives a
   pictureless hero 62% of the screen, and it took that 62 from the FLOOR term by analogy — "the
   house has already stated what share of a screen a hero owns". The analogy is the whole mistake.
   The floor's 62 was chosen for a hero that HAS a photograph, as the least it may be. What these
   four page types actually carried, drawn and signed off long before this round, was
   `clamp(520px, 70vh, 760px)` — and that arithmetic reproduces every single one of the BEFORE
   numbers above exactly: 70% of 900 is 630, of 1080 is 756, of 844 is 591, and the 520 floor is
   what a 640-tall phone got. So the number these pages want is not a new opinion; it is the one
   they were already drawn at, read back off the tree that drew them.

   TWO THINGS CHANGE HERE AND NOTHING ELSE DOES.
     THE SHARE   62 -> 70, scoped to the interior hero. The six home families keep their 62: this
                 is `.hero.sl-hero-nopic`, and no home family's hero carries `.hero` (they are
                 `.et-hero`/`.bh-hero`/`.bk-notch`/`.bk-wave`, each with `.sl-hero-box`). A design
                 the owner has approved is not this round's to move.
     THE 520px   was `min(520px, 62svh)` — which makes 520 a CEILING on any screen shorter than
                 839px, exactly the mistake the account above says it is undoing one line higher.
                 It is `min(520px, the screen budget)` now: 520 unless the screen genuinely cannot
                 afford it, which is the sentence it always claimed.

   WHAT THIS DOES NOT PUT BACK, said out loud rather than buried. The old rule had a 760px cap, so
   on a 1440-tall monitor these heroes were a 760px strip; they are 1008px now. And on a 360x640
   phone the screen ceiling wins at 408px where the old floor said 520px — the old number simply
   did not fit inside the phone's own screen, which is what put a booking button below the bottom
   edge, and the ceiling refusing it is this round working, not this round losing. ═══════════ */
/* ── AND 70 IS ONLY HALF THE ANSWER, BECAUSE THERE ARE TWO KINDS OF PICTURELESS HERO ─────────
   THE FAULT THIS CLOSES, and it is the last page type this round was still shrinking. The block
   above read the number 70 off `clamp(520px, 70vh, 760px)` — which was `.hero-image-bg`'s line,
   not `.hero`'s. A plain interior hero, painted as a flat colour or a brand gradient rather than
   as a photograph, carried `clamp(560px, 90vh, 880px)`: the very next declaration in the old
   stylesheet, ninety rather than seventy. Giving every pictureless hero the image-bg number took
   twenty percent off every gradient one. Measured on an invented client whose contact page is
   exactly that hero, and on the owner's own site, which has the same contact hero:

     Ashgrove /contact/    1440x900   810 -> 630     864x900 (his window)   810 -> 630
                           1920x1080  880 -> 756

   So it is two numbers, not one, and each is the number that page type was already drawn at:

     A PLAIN OR GRADIENT HERO   90 — `.hero`'s own old line.
     A PHOTOGRAPH'S FRAME WITH  70 — `.hero-image-bg`'s old line, unchanged from the block above,
     NO PHOTOGRAPH IN IT             which is where the four page types measured there sit.

   WHAT THE CEILING STILL TAKES BACK, measured rather than assumed, because 90vh of a 900px window
   is 810px and the chrome above an interior hero is 114px in a wide window and 156px in his:

     1440x900   90vh = 810, the screen allows 786   ->  786   (24px under the old 810)
     864x900    90vh = 810, the screen allows 744   ->  744   (66px under it)
     1920x1080  90vh = 972, the screen allows 966   ->  966   (the old rule's 880px cap: +86)
     2560x1440  90vh =1296, the screen allows 1326  -> 1296   (was 880: +416)

   The two cells the ceiling clips are cells where the OLD band ran past the bottom of the window —
   810 of band under 156 of chrome is 966 in a 900px screen. The band ends exactly at the fold now
   instead of 66px below it, and that is the same rule, unchanged, that put twenty-eight booking
   buttons back onto phone screens. Every other size is taller than it has ever been. ─────────── */
:where(.sl-body) { --sl-hero-interior-nopic-share: 70; --sl-hero-interior-plain-share: 90; }
:where(.sl-body) .hero.sl-hero-nopic {
  --sl-hero-want: calc(var(--sl-hero-interior-plain-share) * 1vh);
  --sl-hero-floor: min(var(--sl-hero-floor-px), var(--sl-hero-cap));
}
:where(.sl-body) .hero.hero-image-bg.sl-hero-nopic { --sl-hero-want: calc(var(--sl-hero-interior-nopic-share) * 1vh); }
/* svh, for the same reason the block above gives: vh on a phone is a screen taller than the one
   the visitor has. The vh line stays as the fallback for Chrome < 108 / Safari < 15.4. */
@supports (height: 100svh) {
  :where(.sl-body) .hero.sl-hero-nopic { --sl-hero-want: calc(var(--sl-hero-interior-plain-share) * 1svh); }
  :where(.sl-body) .hero.hero-image-bg.sl-hero-nopic { --sl-hero-want: calc(var(--sl-hero-interior-nopic-share) * 1svh); }
}

/* ══ THE FOLD BUDGET — WHAT EACH FAMILY'S NAVIGATION HAS ALREADY SPENT ═════════════════════════
   The whole account is on `--sl-nav-h` at the top of this file. In one line: the ceiling term
   subtracts the nav from the screen, it was subtracting a house constant of 96px from every family
   at every width, and the real numbers run from 53 to 215. On a phone every one of these navs
   wraps its links onto extra rows, so the error is worst exactly where the screen is smallest.

   Each number below is MEASURED on a built page, not designed: the distance from the top of the
   window to the top of that family's hero, which is what the visitor actually loses. It is stated
   here rather than in six template files so that "how much screen is left" is one decision with one
   home, and so that a family redrawing its nav has one place to correct.

   Three bands, because that is where these navs change shape: side by side, collapsed, and phone.
   A family that states nothing keeps the 96px fallback. ══════════════════════════════════════ */
:where(.sl-body) .et-hero  { --sl-nav-h: 78px; }
:where(.sl-body) .bh-hero  { --sl-nav-h: 96px; }
:where(.sl-body) .cm-hero  { --sl-nav-h: 53px; }
:where(.sl-body) .bk-split { --sl-nav-h: 73px; }
:where(.sl-body) .rt-hero  { --sl-nav-h: 79px; }
:where(.sl-body) .bl-hero  { --sl-nav-h: 89px; }
/* ── AND THE SEVENTH, WHICH IS EVERY PAGE THAT IS NOT THE HOME PAGE ──────────────────────────
   THE FAULT THIS CLOSES, AND IT IS THE ONE THE ROUND'S OWN CHECK CAUGHT ITSELF ON. The table
   above was written for the six HOME families and stopped there. Every other page of every
   site — about, contact, faq, a treatment page, a package page, a hub listing — draws its hero
   through one shared renderer, that renderer states no budget, and so all of them kept the
   96px fallback. The real chrome above an interior hero is the site header PLUS a breadcrumb
   bar, and it was measured on built pages of an invented client at all six window sizes:

     width band          header + breadcrumb        the guess it was using
     1440 / 1920 / 2560          114px                      96px   (18px out)
     864  (his own window)       156px                      96px   (60px out)
     390 / 360 (a phone)         232px                      96px  (136px out)

   The consequence, measured before this line existed: the home hero's band ended EXACTLY at the
   fold at all six sizes, and every interior hero overran it — by 18px on a monitor, 60px in his
   own window, and 136px on a phone, where it put the second booking button 47px under the
   bottom edge of the screen on five listing pages at once. Nothing was wrong with the height
   rule; it was being handed a screen 136px taller than the visitor's.

   This is why the round's own verifier found the first screen WORSE after the hero work: the
   old interior hero was a ~560px strip that under-ran its own wrong budget and got away with
   it. Making it as tall as the screen allows made the wrong budget visible everywhere at once.

   THE PHONE NUMBER CARRIES A TWO-LINE BREADCRUMB and still cannot promise one. A breadcrumb's
   height depends on the length of the page's own title: at 360px wide a short title takes one
   line (232px of chrome) and "IV Therapy for Grey Month Fatigue" wraps to two (260px). 232 is
   the honest common case; the fold check measures the real thing on every page and names any
   page whose chrome outgrows it, which is the only thing that can keep a measured table true. */
:where(.sl-body) .hero     { --sl-nav-h: 114px; }
@media (max-width: 900px) {
  :where(.sl-body) .et-hero  { --sl-nav-h: 99px; }
  :where(.sl-body) .bh-hero  { --sl-nav-h: 139px; }
  :where(.sl-body) .cm-hero  { --sl-nav-h: 53px; }
  :where(.sl-body) .bk-split { --sl-nav-h: 105px; }
  :where(.sl-body) .rt-hero  { --sl-nav-h: 128px; }
  :where(.sl-body) .bl-hero  { --sl-nav-h: 133px; }
  :where(.sl-body) .hero     { --sl-nav-h: 156px; }
}
@media (max-width: 560px) {
  :where(.sl-body) .et-hero  { --sl-nav-h: 93px; }
  :where(.sl-body) .bh-hero  { --sl-nav-h: 215px; }
  :where(.sl-body) .cm-hero  { --sl-nav-h: 138px; }
  :where(.sl-body) .bk-split { --sl-nav-h: 65px; }
  :where(.sl-body) .rt-hero  { --sl-nav-h: 208px; }
  :where(.sl-body) .bl-hero  { --sl-nav-h: 185px; }
  :where(.sl-body) .hero     { --sl-nav-h: 232px; }
}

/* ── AND THE TWO BARS THAT ARE NO LONGER THAT SHAPE ───────────────────────────────────────────
   The table above is measured, which means it is only true of the bar it was measured on. A brand
   that asks for a redrawn top bar — `theme_json.nav_scale = 'tall'`, `theme_json.nav_mobile =
   'drawer'` — is no longer described by it, and a stale number here is not a cosmetic error: this
   variable is what the hero subtracts from the screen, so understating it pushes the booking
   button off the bottom and overstating it squashes a hero for room nobody is using.

   Measured on IV Revival, 2026-09-17, on the built pages — window top to hero top, which is the
   thing this table holds:

       home     1440 → 108   (was 79, and 79 never counted the promo strip above it)
       home     ≤900 →  72   (was 128, then 208 on a phone — the bar that did not collapse)
       interior 1440 → 153   (was 114)
       interior ≤900 → 117   (was 156, then 232 on a phone)

   Both rules carry a body class, so they reach the brands that asked and nobody else; and the
   phone band replaces BOTH the 900 and the 560 rows above it, because a collapsed bar is one
   height all the way down. The tall rule is held above the breakpoint on purpose: a tall bar that
   has not also been told to collapse is a WRAPPED tall bar down there, which is a shape nothing
   has measured and no brand is currently in. ────────────────────────────────────────────────── */
@media (min-width: 901px) {
  :where(.sl-body).sl-nav-tall .rt-hero { --sl-nav-h: 108px; }
  :where(.sl-body).sl-nav-tall .hero    { --sl-nav-h: 153px; }
}
@media (max-width: 900px) {
  :where(.sl-body).sl-nav-drawer .rt-hero { --sl-nav-h: 72px; }
  :where(.sl-body).sl-nav-drawer .hero    { --sl-nav-h: 117px; }
}

/* ══ ON A PHONE A HERO LEAVES ROOM FOR ITS OWN CONTROLS ════════════════════════════════════════
   THE FAULT THIS CLOSES. On a phone the booking button IS the page, and it was under the bottom
   edge. Measured in a real phone emulation — device pixel ratio, touch points, a phone user agent
   and a reload after the device was attached, because a resized desktop window is not a phone and
   this repo has been caught by that before — on two invented estate clients at 390x844 and
   360x640: 15 controls below the bottom edge on Alderline and 13 on Ashgrove. The worst was a
   package page at 360x640 where "Book a Chair" ended 197px past the bottom and the phone number
   272px past it. A visitor who cannot see the button has no way to buy.

   NOTHING WAS WRONG WITH THE HEIGHT RULE, AND THE FOLD BUDGET ABOVE IS RIGHT. Both were checked
   before anything was changed. The interior chrome on a phone measured 232px on every page but
   one (a two-line breadcrumb made it 260), which is exactly what the table above claims, and the
   band's own minimum is capped at the screen. The band overran the screen because its CONTENT did:
   a min-height is a floor, and copy taller than the fold grows the band without limit.

   SO WHAT WAS ACTUALLY TOO BIG WAS THE COPY, and every part of it was a DESKTOP number reaching a
   phone. Measured on the built page at 360 wide:

     the headline   `clamp(3rem, 8.4vw, 6.4rem)`. 8.4vw is 30px at 360 wide — but the clamp's
                    FLOOR is 3rem, so a phone gets 48px type whatever its width. That is seven
                    characters to a line: "Meet Our Alderline Hydration Team" took THREE lines and
                    141px. The same shape of fault as the 620px hero cap this round removed — a
                    floor written for a monitor, biting hardest on the smallest screen.
     the insets     4rem top and 4rem bottom. 128px of a 640px screen, spent on air, before a word.
     the controls   a 1.05rem button in a 1.6 line box is 62px tall, and on a phone they stack full
                    width — two of them plus the gap is 139px, three is 216px.
     the order      on a package or treatment page the price block, three fact lines and a tagline
                    all sit BETWEEN the headline and the booking row: 245px of supporting detail
                    pushing the one control that earns money off the screen.

   THE RULE, SAID OUT LOUD: the first screen of a phone is the headline, the line that explains it,
   and the way to book. Everything else in the hero follows underneath. And a hero is a SMALLER
   share of a phone screen than of a monitor — deliberately. On a monitor the band is the whole
   fold because a photograph fills it; on a phone 232px of that fold is already spent on the header
   and the breadcrumb, so the band takes what is left and no more, and the controls come first
   inside it. That is a decision, not an accident, and this is where it is written down.

   WHY NOT SIMPLY SHRINK THE BAND. Because the band was never the thing overflowing — the copy was,
   and a shorter band with the same copy overflows by exactly as much. Nothing here touches
   `--sl-hero-min`, so every desktop size measured this round is byte-identical: the band that ends
   exactly at the fold at 1440, 1920, 2560 and the owner's own 864x900 is untouched.

   THE BREAKPOINT IS 560px, the same one the fold budget uses above, so that "a phone" means one
   thing in this file and not two. The class is named twice for the reason set out on
   `.sl-hero-box.sl-hero-box` — a lane's own `body.refine-… .hero-inner h1` outranks a plain
   `.hero h1`, and a phone rule that a lane can silently take back is not a rule. ══════════════ */
@media (max-width: 560px) {
  /* THE INSETS — a share of the phone's screen, not the monitor's 4rem. */
  :where(.sl-body) .hero.hero { padding-top: clamp(16px, 3vh, 28px); padding-bottom: clamp(16px, 3vh, 28px); }
  /* THE HEADLINE — A TERM THAT SCALES WITH THE SCREEN, WITH NO DESKTOP FLOOR UNDER IT. The whole
     fault was the 3rem floor: a phone got 48px type whatever its width, and 48px on a 360px screen
     is seven characters to a line. This is 34px at 360 wide, 37px at 390 and 42px on a 440-560px
     phone, so the headline still grows with the screen instead of freezing — and it is still the
     largest thing on the first screen by a wide margin.

     THE SIZE WAS CHOSEN BY MEASURING, NOT BY TASTE. It was set once at the smallest that certainly
     fits, then raised until the tightest interior first screen in two clients had 122px of clear
     screen under its lowest booking control. That is the headroom a client's own longer wording
     will spend. Bigger than this and a three-line headline on a 360x640 phone starts eating it. */
  :where(.sl-body) .hero.hero .hero-inner h1 { font-size: clamp(1.8rem, 9.4vw, 2.6rem); line-height: 1.06; }
  /* THE SUPPORTING LINE — one step down, so it reads as support and not as a second headline. */
  :where(.sl-body) .hero.hero .hero-inner .subhead { font-size: 1rem; line-height: 1.5; max-width: none; }
  /* THE CONTROLS — still full-width tap targets, which is right on a phone; only the box around
     the words gets phone-sized. 62px becomes 53px, and three of them save 27px. */
  :where(.sl-body) .hero.hero .cta-row { gap: 0.6rem; }
  :where(.sl-body) .hero.hero .cta-row .btn { padding: 0.85rem 1.35rem; font-size: 1rem; }
  /* THE ORDER — and ONE piece of spacing for the whole column, so that moving a block cannot leave
     it with a margin on one side and none on the other. Margins are zeroed and replaced by a gap
     for exactly that reason; every child of this column is already `block` or `flex`, so nothing
     changes shape by becoming a flex item. The `::after` reading-scrim is absolutely positioned
     and is therefore not a flex item at all. */
  :where(.sl-body) .hero.hero .hero-inner { display: flex; flex-direction: column; gap: 0.75rem; }
  :where(.sl-body) .hero.hero .hero-inner > * { margin-top: 0; margin-bottom: 0; order: 5; }
  :where(.sl-body) .hero.hero .hero-inner > .eyebrow { order: 1; align-self: flex-start; }
  :where(.sl-body) .hero.hero .hero-inner > h1 { order: 2; }
  :where(.sl-body) .hero.hero .hero-inner > .subhead { order: 3; }
  :where(.sl-body) .hero.hero .hero-inner > .cta-row { order: 4; }
  /* A hero that opted into bottom-alignment reserves a deep floor under the copy. On a monitor
     that is the lower third; on a phone it is 70px of the 408px the band has left. */
  :where(.sl-body) .hero-align-center.hero-align-center > .container { padding-bottom: clamp(16px, 3vh, 28px); }
}

/* ── AND ON A SHORT PHONE, THE EXPLANATION FOLLOWS THE BOOKING ROW ────────────────────────────
   THE ONE CELL THE RULE ABOVE COULD NOT REACH, and it is worth saying exactly why rather than
   nudging a number until it passes. A treatment page at 360x640 carries a 33-character headline,
   a seven-line supporting paragraph and two booking controls — and its chrome measured 260px, not
   the 232px the fold budget states, because its long title wrapped the breadcrumb onto a second
   line. That leaves 380px of screen for 408px of copy, and the second control ended 10px past the
   bottom edge. Shaving type and gaps closed about eleven of those pixels: enough to pass and not
   enough to be true, on the one page whose chrome is the worst in the fleet.

   So the sentence gets a second half instead: WHEN THE SCREEN IS SHORT, THE SUPPORTING LINE MOVES
   BELOW THE BOOKING ROW. The words are all still there, one scroll-free line lower; what changes
   is which of them the visitor meets first, and on a 640px screen that has to be the headline and
   the button. On a tall phone (844px) nothing moves — there the paragraph fits above the controls
   with room to spare, and it is measured at both sizes rather than assumed.

   720px is the boundary because it sits between the two phones this fleet is measured at (640 and
   844) and below the shortest tall phone in circulation. A page that needs this on a 844px screen
   is a page with too much copy, and the fold check will say so. ─────────────────────────────── */
@media (max-width: 560px) and (max-height: 720px) {
  :where(.sl-body) .hero.hero .hero-inner > .subhead { order: 5; }
}

/* ══ AND ON A SHORT LAPTOP, THE SAME SENTENCE ONE SCREEN SIZE UP ═══════════════════════════════
   THE FAULT THIS CLOSES, AND IT IS THE LAST THING THE ROUND'S OWN CHECK REFUSES. `fold-fit` opens
   every page at five window sizes. On two invented estate clients it now finds nothing at all at
   1440x900, 864x900, 390x844 or 360x640 — and four faults at 1440x720, a laptop, on the two
   package pages and nowhere else. Measured, in a real browser, on the built page:

     /iv-packages/chuckanut/  at 1440x720   band 832px in a 720px window   "Book Online" 30px below
     /iv-packages/grey-month/ at 1440x720   band 767px in a 720px window

   They are REAL. A visitor on a 1440x720 laptop cannot see the button that books a visit without
   scrolling, and nothing below the band is on the screen at all. And they are OLDER THAN THIS
   ROUND: the same two cells, the same two button names and the same 832 and 767, measured on the
   pre-hero build of the same client. So this is not a check holding the wrong bar and it is not a
   regression to undo — it is a fault the round's new check is the first thing ever to see.

   WHAT IS ACTUALLY TOO BIG, AND IT IS NOT THE BAND. The band's own minimum at 1440x720 is 520px
   and the screen allows 606. The band is 832 because its CONTENTS are: 64px of air, a 600px copy
   column, and 194px of reserved air beneath it. A min-height is a floor, so copy taller than the
   screen grows the band without limit — the same shape of fault as the phone, and the same repair.

   AND WHAT IS TOO BIG IN THE COPY IS THE SUPPORTING DETAIL, exactly as it was on the phone. On a
   package page the price block, three fact lines and a tagline sit BETWEEN the headline and the
   booking row. Measured at 1440x720: headline 76 + 38, supporting paragraph 161 + 24, price 40 +
   18, facts 14 + 86 + 18, tagline 35 + 18, controls 8 + 60. The stack between the headline and the
   button is 245px of a 720px screen, and its air was written in rem — a fixed number that does not
   know the screen got shorter, which is this file's oldest and most repeated fault.

   THE RULE: on a screen 760px or shorter, a hero that carries a PRICE tightens its supporting
   detail and its own air, so that the way to book stays on the first screen. Every word stays; the
   gaps between them, the size of the explaining paragraph, and the band's own insets become a
   share of the screen instead of a share of nothing.

   WHY IT ASKS WHAT THE HERO CARRIES, AND NOT EVERY HERO. Because tightening a hero that is not
   overflowing is a loss and nothing else. About, contact, FAQ and the hub listings carry a
   headline, a paragraph and two buttons; they fit at 1440x720 with room, before and after this
   round, and they are the four page types this same round was sent to stop shrinking. So the rule
   is asked of the supporting detail itself, in two steps, weakest repair first:

     A HERO THAT CARRIES FACT LINES gives back its own air — the band's insets become a share of
       the screen. That alone is 78px at 720, and it is all the second invented client's treatment
       page needed: its band was 736px in a 720px window and is 658px now.
     A HERO THAT ALSO CARRIES A PRICE tightens the detail as well. A price is the marker for the
       FULL stack — price, three fact lines and a tagline, 245px of a 720px screen — and only the
       package pages, where the fault actually is, carry one.

   A page on another client that carries the same blocks gets the same repair by the same rule; one
   that does not is left alone, because it does not have the problem.

   MEASURED AFTER: band 679px in a 720px window, the lowest booking control 84px clear of the
   bottom edge, and nothing at 1440x900, 1920x1080, 2560x1440 or 864x900 moves by a pixel — the
   query cannot match a window 761px tall or taller.

   THE CLASS IS NAMED TWICE, AND ONCE THREE TIMES, for the reason recorded on
   `.sl-hero-box.sl-hero-box`: the band's own bottom inset is written by a theme rule
   (`body.bands-paper .hero-image-bg`) which carries two classes AND a type, so it outranks
   `.hero.hero` and the first attempt at this silently did nothing — measured, 194px unmoved. An
   inset a theme can quietly take back is not an inset. ══════════════════════════════════════ */
@media (min-width: 561px) and (max-height: 760px) {
  /* THE BAND'S OWN AIR — a share of the screen, not 4rem of a monitor. 25px at 720, and it is back
     to the full 4rem by the time the window is 760px tall, which is where this query stops.
     THE RESERVED STRIP UNDER THE COPY KEEPS ITS 130px AND LOSES ONLY THE AIR. That 130px is not
     decoration: it is the room a trust row pulled up over the bottom of the hero sits in, and
     shrinking it would land badge labels on the booking buttons. Only the 4rem beside it moves. */
  :where(.sl-body) .hero.hero.hero {
    padding-top: clamp(1.5rem, 5svh, 4rem);
    padding-bottom: calc(clamp(1.5rem, 5svh, 4rem) + 130px);
  }
  :where(.sl-body) .hero.hero:has(.hero-facts) {
    padding-top: clamp(1rem, 3.5svh, 4rem);
    padding-bottom: calc(clamp(1rem, 3.5svh, 4rem) + 130px);
  }
  /* THE EXPLAINING PARAGRAPH — one step down, so it still reads as support. Five lines at 1.3rem
     is 161px of a 720px screen; the same five lines at 1.1rem is 132px. */
  :where(.sl-body) .hero.hero:has(.hero-facts) .hero-inner .subhead { font-size: 1.1rem; line-height: 1.5; }
  /* THE GAPS BETWEEN THE BLOCKS. Each one was a rem written against a 900px screen. Together they
     are 130px of a 720px screen spent on nothing, and roughly half of that comes back here. */
  :where(.sl-body) .hero.hero:has(.hero-facts) .hero-inner h1 { margin-bottom: 1rem; }
  :where(.sl-body) .hero.hero:has(.hero-facts) .hero-inner .subhead { margin-bottom: 0.75rem; }
  :where(.sl-body) .hero.hero:has(.hero-facts) .hero-price { margin-bottom: 0.6rem; }
  :where(.sl-body) .hero.hero:has(.hero-facts) .hero-facts { margin-top: 0.4rem; margin-bottom: 0.6rem; row-gap: 0.25rem; }
  :where(.sl-body) .hero.hero:has(.hero-facts) .hero-tagline { margin-bottom: 0.6rem; }
  /* ── AND THE HEADLINE, WHICH IS THE HALF THE FIRST ATTEMPT AT THIS BLOCK MISSED ────────────
     THE FAULT THIS CLOSES, and it is the last thing standing between this work and a publish.
     The block above asks what the hero CARRIES — fact lines, a price — and repairs only those.
     Measured on two invented estate clients, the page it therefore never touched is the one that
     is worst: /about/, which carries nothing but a headline, a paragraph and two buttons, and
     which came to 767px (Alderline) and 810px (Ashgrove) inside a 720px laptop window, with two
     booking buttons 38px under the bottom edge.

     ONE DECLARATION IS RESPONSIBLE FOR ALL OF IT, and this file has already named the mistake
     twice without fixing this instance of it. `.hero h1` is `clamp(3rem, 8.4vw, 6.4rem)`. On any
     window 1220px wide or wider that is pinned at its 6.4rem ceiling — 102.4px — whatever the
     screen's HEIGHT is. A 33-character headline at 102.4px inside the hero's own 760px column is
     THREE lines and 344px: 48% of a 720px screen, spent before a word of explanation. It is the
     same fault as the 3rem floor the phone block deleted and the same fault as the 8.2vw headline
     that `--sl-hero-em` exists for — a size written against a monitor's proportions, reaching a
     screen that does not have them.

     THE REPAIR IS THE PHONE BLOCK'S, ONE SCREEN SIZE UP: the ceiling is the smaller of the type
     scale and a tenth of the screen. 72px at 720, 76px at 760, and back to the full 6.4rem the
     moment the window is 1024px tall — so nothing on a monitor can move, by construction. At 72px
     the same headline wraps to two lines and 141px, and both /about/ pages come in at 536 and
     556 inside the 720px window with every control 200px clear of the bottom edge.

     AND THE PARAGRAPH AND THE GAPS GO WITH IT, for the same reason and by the same arithmetic the
     block above used on the pages that carry facts. They were scoped to `:has(.hero-facts)` for
     the honest reason that tightening a hero which is not overflowing is a loss — but that reason
     was measured on the pages that were failing THEN, and /about/ is failing now. */
  :where(.sl-body) .hero.hero .hero-inner h1 { font-size: clamp(3rem, 8.4vw, min(6.4rem, 10svh)); margin-bottom: 1rem; }
  :where(.sl-body) .hero.hero .hero-inner .subhead { font-size: 1.1rem; line-height: 1.5; margin-bottom: 0.75rem; }
}

/* ══ AND A LAPTOP IS NOT ONLY A SHORT WINDOW — IT IS A WIDE ONE THAT IS SHORT ══════════════════
   THE ONE CELL LEFT OVER, and it is worth being exact about why it needs its own sentence. The
   block above stops at a window 761px tall, which is the right place for it: below that the screen
   is genuinely small and every hero gives something back. The last fault the round's own check
   refuses is not on a small screen at all. It is a treatment page at 1440x900 — a normal desktop
   window — whose band measured 941px inside it, 41px past the bottom edge.

   NOTHING ABOUT THAT WINDOW IS SHORT. What is wrong is the SHAPE of it: 1440 wide by 900 tall is
   a laptop, wide enough that every term sized off the width takes its largest value, and not tall
   enough to carry the result. The same page in the owner's own 864x900 window is 718px and fits
   with room, because there the width is small and the type sized off it comes down on its own.
   So the question this asks is not "is the screen small" but "is the width telling the truth
   about how much room there is", and the answer is no on exactly one shape of window:

     WIDE ENOUGH FOR THE TYPE TO TAKE ITS CEILING   1100px and wider
     NOT TALL ENOUGH TO CARRY IT                    1000px tall and shorter

   1440x900 and 1440x720 are inside it. 1920x1080 and 2560x1440 are not — they are wide and they
   have the height, and nothing on them moves by a pixel. 864x900 is not — it is short but narrow,
   it is the window the owner actually browses in, and this round exists to stop it losing height.
   Phones are not: they are neither, and they have their own block above.

   WHAT IT ASKS FOR, and it is deliberately the weakest repair in the file rather than the surest.
   Only a hero that carries FACT LINES — the treatment and package pages, which are the only ones
   that overrun a 900px window — gives back its top air and the gaps between its supporting blocks.
   The headline is NOT touched here and neither is the paragraph: at 900px the type is not the
   thing that has to move, and shrinking it would take height off /about/, /contact/ and /faq/,
   which fit at this size and are three of the four page types this round was sent to stop
   shrinking. Measured, on the page that was failing: 941px -> 853px inside a 900px window, 47px
   of clear screen under the band, and the lowest booking control 127px above the bottom edge. ══ */
@media (min-width: 1100px) and (max-height: 1000px) {
  :where(.sl-body) .hero.hero.hero:has(.hero-facts) { padding-top: clamp(1rem, 3.5svh, 4rem); }
  :where(.sl-body) .hero.hero:has(.hero-facts) .hero-inner h1 { margin-bottom: 1rem; }
  :where(.sl-body) .hero.hero:has(.hero-facts) .hero-inner .subhead { margin-bottom: 0.75rem; }
  :where(.sl-body) .hero.hero:has(.hero-facts) .hero-price { margin-bottom: 0.6rem; }
  :where(.sl-body) .hero.hero:has(.hero-facts) .hero-facts { margin-top: 0.4rem; margin-bottom: 0.6rem; row-gap: 0.25rem; }
  :where(.sl-body) .hero.hero:has(.hero-facts) .hero-tagline { margin-bottom: 0.6rem; }
}

/* ══ HOW WIDE A PICTURE-COLUMN HERO'S PHOTOGRAPH IS — ONE RULE, THREE HOUSES ═══════════════════
   THE FAULT THIS CLOSES. The height rule above reaches only the three houses whose hero is a
   full-bleed GROUND (estate, bright, community): `--sl-hero-want: 100vw / ratio` grows with the
   window, so at 2560 wide their heroes are 1344px where they used to be 620. The other three draw
   the hero as a PICTURE IN A COLUMN, and every one of them wrote that column's width out as a
   pixel number — 624px in SplitHero (editorial), 620px on `.rt-hero` (retail), a 420px max-width
   on `.bl-hero-pic` (bloom). A picture that is 624px wide on a 1440 monitor is 624px wide on a
   2560 one, so its height cannot move either, and measured across three widths editorial came back
   566px, 566px, 566px. The shared rule was not being ignored: it had nothing to work on, because
   the one thing it keys off — how wide the photograph is — was a constant.

   THE RULE. A picture-column hero's photograph is a SHARE OF THE WINDOW, never narrower than the
   width its house was designed at. `max(14.4px, 1vw)` is that sentence: 1vw is 14.4px at 1440, so
   below 1440 the floor wins and NOTHING about any of the three designs moves, and above it the
   picture grows in exact proportion with the screen. The house's own number stays the house's own
   number — it is `--sl-hero-col-share`, the share, and share x 14.4 is the pixel width it used to
   hard-code (43.3 -> 623.5, 43.05 -> 619.9, 29.17 -> 420.0). Same shape as `--sl-hero-fill`: one
   value a family may differ on, and no other number anywhere.

   The picture's own ceiling (`.sl-hero-pic { max-height: 100svh - nav }`) still holds above this,
   so a wider picture can never overflow the first screen; and below 900px all three houses collapse
   to a single column, where a share of the width is not the question and this does not apply. */
:where(.sl-body) { --sl-hero-col-share: 43.3; }
/* Declared on BOTH names on purpose. A custom property is worked out where it is DECLARED and
   inherited as the finished value, so a house that sets its share on the picture's own frame —
   bloom does, because its picture is capped by a max-width rather than by a grid track — would
   otherwise inherit the band's answer and its share would do nothing. */
:where(.sl-body) .sl-hero-stack, :where(.sl-body) .sl-hero-frame { --sl-hero-col: calc(var(--sl-hero-col-share) * max(14.4px, 1vw)); }
/* THE LOWER HALF — the copy placement decided once, for every full-bleed hero that carries a
   photograph. The account is in the :root block above.
   `:not(.sl-hero-nopic)` is the whole scope and it is the honest one: with no photograph there is
   no subject to sit on, the band is a flat brand colour, and a block of type shoved to the bottom
   of an empty colour field is worse than a centred one. So a pictureless hero keeps its centring.
   Both properties are written because the families split between grid and flex; each reads the one
   that applies to it and ignores the other. No family declares a vertical alignment of its own any
   more — they were deleted in the same edit, so nothing here has to fight a scoped selector. */
:where(.sl-body) .sl-hero-box.sl-hero-box {
  /* A family states only its own two insets — never a vertical alignment, and never a top or
     bottom padding in a shorthand, because a shorthand from a scoped component selector outranks
     this file and silently takes the decision back. Each of the four sets these to what it had.
     The class is named twice for the reason set out on the rule below. */
  --sl-hero-pad-top: 48px;
  --sl-hero-pad-bottom: 48px;
  padding-top: var(--sl-hero-pad-top);
  padding-bottom: var(--sl-hero-pad-bottom);
  align-items: center;
  align-content: center;
}
/* THE CLASS IS NAMED TWICE ON PURPOSE, and it is not decoration.
   A family's blanket band rule is a two-class-plus-type selector — `.bh section` becomes
   `.bh[data-astro-cid-…] section[data-astro-cid-…]` once Astro scopes it — which outranks a plain
   `.sl-hero-box:not(.sl-hero-nopic)`. That is not hypothetical: it is how this exact fix failed
   the first time. Bright's band rhythm landed on its own hero, resolved to 48px at 390px wide, and
   put the headline back on the woman's forehead while every variable in the cascade said the copy
   was in the lower half. Naming the class twice lifts this to three classes so a family's rhythm
   cannot silently take the house decision back — the fault this whole file exists to stop. */
:where(.sl-body) .sl-hero-box.sl-hero-box:not(.sl-hero-nopic) {
  align-items: end;
  align-content: end;
  /* NO TOP FLOOR. It used to be `max(pad-top, --sl-hero-min * --sl-hero-copy-top)` and that one
     line is what pushed a booking control off a phone — see the account on the fold-tall band
     above. Bottom alignment inside a band that is the whole fold already places the copy as low as
     the screen allows, which is a deeper inset than the floor ever gave AND cannot grow the band.
     The family's own inset is all that is left here. */
  padding-top: var(--sl-hero-pad-top);
  padding-bottom: max(var(--sl-hero-pad-bottom), calc(var(--sl-hero-min) * var(--sl-hero-copy-drop)));
}
/* The split families draw their hero picture as an <img> in a column rather than as a full-bleed
   ground. Same decision, same variable: the frame takes the PICTURE's shape, so nothing is cropped
   at all. `min-height` keeps a wide panorama from becoming a letterbox strip beside a tall column
   of copy. */
:where(.sl-body) .sl-hero-pic {
  /* THE ANTI-LETTERBOX RULE IS A SHAPE, NOT A PIXEL NUMBER. This carried `min-height: 320px` — one
     of only three height decisions left in the system, and the only one still written as a bare
     number. What it was for is stated right here: keep a wide panorama from becoming a strip beside
     a tall column of copy. That is a statement about SHAPE, so say it as one: a hero picture is
     never flatter than 1.6 to 1. The 320 was doing damage in both directions — it forced bloom's
     420px-wide inset picture 40px taller than the photograph's own shape inside a band already
     46px over the screen, and on a phone it forced editorial's 330px-wide picture from its true
     220px to 320px, a hundred pixels of height nothing asked for. A 1.5 photograph is unchanged
     everywhere, because 1.5 is already less flat than 1.6. */
  width: 100%; aspect-ratio: min(var(--sl-hero-ratio), 1.6); height: auto;
  /* THE SAME CEILING THE FULL-BLEED FORM HAS, WHICH THIS ONE WAS MISSING.
     The rule is "as tall as the picture needs, never taller than the screen" — and until this line
     the split families only had the first half. Measured on the bloom family at 864x900, where the
     column collapses to full width and the reserved frame is a portrait: the picture drew itself
     877px tall on a 900px screen and pushed the headline it sits beside off the fold entirely.
     Nothing is clipped by this: an <img> under object-fit COVER simply shows a little less of
     itself, and no copy lives inside the frame. Same two variables as the band, so the answer moves
     with the family that changes them. */
  max-height: calc((100vh - var(--sl-nav-h)) * var(--sl-hero-fill));
  object-fit: cover; object-position: 50% var(--sl-hero-focus-y); display: block;
}
@supports (height: 100svh) {
  :where(.sl-body) .sl-hero-pic { max-height: calc((100svh - var(--sl-nav-h)) * var(--sl-hero-fill)); }
}

/* ══ THE FOLD RULE: THE BOOKING CONTROL IS PART OF THE FIRST SCREEN ════════════════════════════
   A visitor lands on the page and must be able to see how to book without scrolling. That is the
   one thing on a hero that costs the client money when it is wrong, and it was wrong: measured on
   an invented client, the bloom family's hero came to 1224px inside a 900px window and 918px on a
   390x844 phone, and BOTH of its booking controls — "Book A Visit" and the phone number — were
   off the bottom of the screen.

   WHY, AND IT IS NOT THE HEIGHT. The full-bleed families (estate, bright, community) put their
   words ON TOP of the picture, so the band's own ceiling — never taller than the screen — already
   holds the button inside the first screen. The picture-column families (bloom, editorial, retail)
   put the picture BESIDE or ABOVE the words, so the picture and the words are siblings and the
   ceiling above applies to the picture ALONE. The band is then words PLUS a full-screen picture,
   which is one and a half screens, and whatever comes after the picture in the stacking order goes
   over the edge. Editorial and retail survived that only by accident of source order: their copy
   happens to be written first. Bloom's is written between the headline and the picture, so the
   picture stood between a visitor and the button.

   THE RULE, in two parts, and neither of them is a height:

     1. A PICTURE NEVER STANDS BETWEEN THE HEADLINE AND THE BOOKING CONTROL. When a picture-column
        hero stacks, the picture goes LAST — after the words and after the button. Then no picture
        height, however tall, can push the button down, and the guarantee holds at every width for
        every family instead of depending on which order somebody happened to type the markup in.

     2. THE BOOKING CONTROL IS PLACED BY THE WORDS, NOT BY THE PICTURE. Side by side, bloom hung
        its booking card off the BOTTOM edge of the picture's row, so the button's position was a
        function of the picture's height: at 1440x720 the picture drew 467px and carried the button
        to y=822 in a 720px window, with "Book A Visit" cut in half by the fold. A booking column
        WRITTEN AFTER THE PICTURE inherits the picture's bottom edge as its own resting place, so
        that is the one this pins to the top of the row it shares. A column that leads its row —
        editorial's and retail's both do — already takes its place from the words, and is left
        exactly as its family drew it, centred or otherwise. Measured: editorial and retail are
        unchanged at every width; bloom's card moves to the top of the row and its buttons clear
        the fold at 720.

   Both parts are declared here, once, on two shared class names, and every picture-column family
   wears them. A family that adds a hero picture column gets the guarantee by naming its parts;
   nothing about the fold is decided inside a template again. ═══════════════════════════════════ */
/* `.sl-hero-stack`  the hero band of a picture-column family
   `.sl-hero-frame`  the picture's own frame inside it (or the picture itself, when it has none)
   `.sl-hero-words`  the part of that band that carries the booking control */
:where(.sl-body) .sl-hero-frame ~ .sl-hero-words { align-self: start; }
/* AND THE PICTURE-COLUMN BAND READS THE HEIGHT RULE TOO, WHICH IT NEVER HAS.
   `.sl-hero-box` was never on `.bl-hero`, `.bk-split` or `.rt-hero`, so for three of the six
   families the shared rule was not being overridden — it was not being read. Their bands had no
   floor and no ceiling; their height was whatever their picture's own shape happened to come to.
   That is the whole of the editorial fault: when the picture stopped being cropped to a fixed
   560px frame and started being drawn at the photograph's true 1.5, the band followed it down from
   712px to 568px, and nothing anywhere said a hero may not be that short. Measured at 1440x900,
   editorial 568 and retail 609 against a fold of 827 and 831.
   The same minimum, on the band itself. The picture keeps its own shape and its own ceiling; what
   changes is that the BAND now has a floor, and that floor is the first screen. It is not a new
   height decision and there is no new number: `.sl-hero-stack` was added to the ONE selector that
   composes and applies `--sl-hero-min`, at the top of this file. */
/* PART 3 OF THE FOLD RULE: NOR DOES A HEADLINE STAND BETWEEN THE VISITOR AND THE BOOKING CONTROL,
   WHEN THE SCREEN IS SHORT. Parts 1 and 2 got the picture out of the way and pinned the booking
   column to the top of its row. They left the row ABOVE it alone, and on a short screen that row is
   the whole problem: bloom writes its headline across both columns, so the booking card cannot
   start until the headline has finished. Measured at 1440x720 — a laptop — 86px of band padding
   plus a 314px headline plus a 58px gap put the card's first pixel at 547 in a 720px window and
   its phone number at 755. Nothing was wrong with the card; it was queued behind three lines of
   type.
   `max-height` is the right question to ask, because this is a fault of the SCREEN and not of the
   width: the identical page at 1440x900 is correct and needs no rearranging. Above 860px of window
   the family is drawn exactly as it was. Below it the booking column joins the headline's own row
   and takes the bottom of it, which is where the eye already is. The headline is untouched — it
   still spans the band, and its own 16-character measure keeps it clear of the column the card
   sits in. */
@media (min-width: 901px) and (max-height: 860px) {
  :where(.sl-body) .sl-hero-stack > .sl-hero-frame ~ .sl-hero-words { grid-row: 1; align-self: end; }
}
@media (max-width: 900px) {
  /* Below this the picture column stacks under the copy — all three families collapse at exactly
     this width, so the rule is stated once rather than three times. */
  :where(.sl-body) .sl-hero-stack > .sl-hero-frame { order: 9; }
  :where(.sl-body) .sl-hero-stack > .sl-hero-words { order: 8; }
  /* AND IT SHARES THE SCREEN, SO IT DOES NOT GET ALL OF IT.
     Stacked, the words and the picture are stacked on the same first screen, and the ceiling
     above — "never taller than the screen" — was being spent twice: once by the words and again,
     in full, by the picture. Measured at 864x900 that gave an 804px picture under a 420px column
     of words: a 1224px hero on a 900px screen. Half the screen each is the only division that does
     not privilege one over the other, and because the picture now comes LAST, any shortfall is
     taken out of the picture and never out of the button. `--sl-hero-fill` is the lever the rule
     already publishes for exactly this; nothing new is invented and no pixel is named.
       864x900   picture 804 -> 402, band 1224 -> 822 (the screen is 804)
       390x844   picture 367 (its own shape, under the 374 ceiling) — untouched */
  :where(.sl-body) .sl-hero-stack { --sl-hero-fill: 0.5; }
}

/* ══ WHERE A CROP SITS, FOR EVERY PICTURE ON THE PAGE THAT IS NOT THE HERO ══════════════════════
   The hero above is one slot. Sixty-two others fill a box with a photograph and take the middle of
   the file — `object-fit: cover` with no `object-position` is `50% 50%`, equal slices off the top
   and the bottom, blind to what is in either. Heads live at the TOP of a photograph, so that is the
   slice with a face in it, and the taller the box the more of it goes.

   This is the one rule that reads the answer. `--sl-focus-y` is set on the picture itself, by
   lib/photoFocus, from what the library knows about that frame — a portrait anchors at 12%, a
   person in a scene at 25%, and a picture of a room, a bag or a texture says nothing and so gets
   the 50% below, which is exactly what it renders at today. Nothing moves on a guess.

   Bare `img` on purpose: it is the lowest specificity there is, so any block that states its own
   `object-position` deliberately still wins — and the four that do now read this property, with
   their own number as the fallback, so the answer reaches them too. ═════════════════════════════ */
:where(.sl-body) img { object-position: 50% var(--sl-focus-y, 50%); }

:where(.sl-body), :where(.sl-body) { margin: 0; padding: 0; }
:where(.sl-body) { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
:where(.sl-body) {
  font-family: var(--font-body);
  color: var(--c-text);
  background: var(--c-bg);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
:where(.sl-body) img, :where(.sl-body) svg, :where(.sl-body) video { max-width: 100%; height: auto; display: block; }
:where(.sl-body) a { color: var(--c-link, var(--c-primary)); text-decoration: none; }
:where(.sl-body) a:hover { text-decoration: underline; }
:where(.sl-body) a:focus-visible { outline: 2px solid var(--c-focus); outline-offset: 2px; }
:where(.sl-body) h1, :where(.sl-body) h2, :where(.sl-body) h3, :where(.sl-body) h4, :where(.sl-body) h5, :where(.sl-body) h6 { font-family: var(--font-heading); color: var(--c-text); line-height: 1.2; margin: 0 0 0.5em; font-weight: var(--heading-weight, 700); }
:where(.sl-body) h1 { font-size: clamp(2.4rem, 5.5vw, 3.6rem); letter-spacing: -0.02em; }
:where(.sl-body) h2 { font-size: clamp(1.9rem, 3.5vw, 2.8rem); letter-spacing: -0.01em; }
:where(.sl-body) h3 { font-size: 1.3rem; }
:where(.sl-body) .section-header h2 { margin-bottom: 0.4rem; }
:where(.sl-body) .section-header p { font-size: 1.0625rem; color: var(--c-text-muted); }
:where(.sl-body) p { margin: 0 0 1em; }

/* --container-max is the OUTER page gutter; --content-max (1120) is the narrower card-band
   width. They are DIFFERENT numbers on purpose — do not conflate them, pointing .container at
   --content-max would silently narrow every site on the roster by 80px.
   Unset by default => falls back to 1200 => byte-identical for every brand without a composition. */
:where(.sl-body) .container { max-width: var(--container-max, 1200px); margin: 0 auto; padding: 0 1.25rem; }
:where(.sl-body) .section { padding: clamp(2.25rem, 4.5vw, 3.75rem) 0; }

/* ── THE PAGE GRID (shelf blocks) ─────────────────────────────────────────────────────────────
   Every band on a page must start its content on the SAME vertical line. Before this each block
   invented its own inset and its own column — 27 different horizontal padding formulas and 20
   different max-widths across 46 blocks — so a single page put text at five different left edges
   and six different widths as you scrolled. That is what "the formatting is all over the place"
   looks like from the outside; it is not a taste question, it is a missing grid.

   --bk-col deliberately equals the assembler's --container-max, and --bk-gutter equals its inset,
   so a shelf block and an ordinary section landing on the same page share one left edge.

   A block uses them like this, and nothing else:
       .bk-thing { padding: var(--bk-rhythm) var(--bk-pad); }

   AND THE SAME LINES HOLD A BAND'S PICTURE, not just its copy. --bk-pad fixes where the words
   start. A photograph stops on those two lines too. It may sit inside the column, or bleed the
   whole way across and off BOTH edges and simply BE the band — what it may never do is stop in
   between, out in the margin, where there is nothing beside it.

   That happens one way, and it is worth naming because three separate places in this system did
   it: the picture is positioned against the SECTION, whose padding box is full-bleed. `right: 0`
   then means the SCREEN's edge, and every percentage means a percentage of the screen, while
   every other number on the page is measured against a column that stops growing at --bk-col.
   Below about 2400px the two still overlap and it reads as a designed bleed. Above it they come
   apart: --bk-pad is 692px at 2560 and the picture's own cap is not, so the column retreats out
   from under the image. Measured on Névue: photograph 1940..2560, page column 700..1860.

   The fix is never a calc. Position the picture against the band's INNER wrapper — that element
   IS the column, the section's content box — and `right: 0` lands on the grid line at every
   width, with no token to keep in step.

   Guarded by G5 in scripts/grid-lint.mjs, which measures at 2560 because that is the only width
   where the fault is visible.

   --bk-pad is the whole grid in one property. It resolves to the gutter on a narrow screen and to
   "centre a 1200px column, then inset it" on a wide one, so the section stays full-bleed (its
   background still runs edge to edge) while its CONTENT lands on the shared line. Putting it on the
   SECTION rather than on an inner wrapper is deliberate: a wrapper can be overridden by any later
   family rule that sets its own max-width, and that is exactly how the grid was lost the first time.

   Narrow content — a paragraph that should not run 1160px wide — limits its own LINE LENGTH with
   --bk-measure. It must never re-centre a narrower wrapper with `margin: 0 auto`: that moves the
   left edge, which IS the defect. The column is fixed; what sits inside it is free.

   --bk-align is the family's text alignment, set once per family by the block route. Mixing centred
   and left-aligned bands down one page is the other half of what reads as "all over the place", so
   a block asks for the family's alignment instead of hard-coding `center`. */
:where(.sl-body) {
  /* MEASURED AGAINST THE REFERENCE THE CLIENT CHOSE (pureiv.com, 2026-09-06): their content
     column is 1311px inside a 1440px window — 57px of side margin. Ours was 1200 with 140px each
     side, so every band sat in a narrower box and the page read as a document. */
  --bk-col: 1320px;
  --bk-gutter: 1.25rem;
  --bk-pad: max(var(--bk-gutter), calc((100% - var(--bk-col)) / 2 + var(--bk-gutter)));
  /* For a band that is itself INSET from the page edge — a rounded card floating on the page, with
     its own horizontal margin of one gutter. It needs one gutter less of padding to land its
     content on the same line as every full-bleed band above it. */
  --bk-pad-inset: max(0px, calc((100% - var(--bk-col)) / 2));
  --bk-rhythm: clamp(3rem, 5.5vw, 4.75rem);
  --bk-rhythm-tight: clamp(1.5rem, 3vw, 2.25rem);
  --bk-measure: 68ch;
  /* ── THE COLUMN VOCABULARY. DECLARED HERE, PAINTED NOWHERE. ───────────────────────────────────
     This is an INERT DECLARATION and it is the whole of what is left of the column layer. It lists
     ten words a band could wear — `word:col:indent:flush` per entry, exactly the way --bk-gutter
     and --bk-band-scope are declared and parsed — and no rule in this file turns any of them into a
     width. Nothing on any page wears one. See "THE COLUMN LAYER — PARKED" further down this file
     for why: a rule that forced neighbouring bands to differ produced a page with no line down it,
     and the owner's verdict was that every section had its own mind.

     IT STAYS BECAUSE THE READERS OF IT ARE STILL HONEST WITHOUT IT PAINTING. scripts/grid-lint.mjs
     parses it into the left edges G1 would accept IF a page were allow-listed — and that allow-list
     is EMPTY, so G1 holds every page to ONE left edge, which is the rule as it stood before any of
     this. src/lib/bandComposition.ts computes the same lines from the same four fields, is imported
     by nothing, and scripts/bandcomposition-selftest.mjs fails if the two ever disagree. So the
     vocabulary and its assigner cannot drift apart while they are parked, and turning one word back
     on later is a deliberate act in three named places rather than an accident here.

     DO NOT hand-edit the string — run `node scripts/bandcomposition-selftest.mjs`, which prints the
     line it must read. And do not add a rule below that paints one of these words without reading
     the parked-layer note first. */
  --bk-columns: "full:full:0:none wide:1360:0:none column:1200:0:none inset:1040:0:none index:1320:0:none rail:1200:96:none figure-left:1280:0:start figure-right:1280:0:end bleed-photo:full:0:both bleed-ruled:full:0:both";
  /* The tracks the ten words point at. `--bk-col-text` IS --bk-col's own value: a band wearing
     `column` is the page exactly as it stands today, which is what makes `column` the safe word. */
  --bk-col-full: 100%;
  --bk-col-wide: 1360px;
  --bk-col-text: 1200px;
  --bk-col-inset: 1040px;
  --bk-col-index: 1320px;
  --bk-col-figure: 1280px;
  /* the extra inline-start inset the `rail` word adds so a hairline rail can live in the margin.
     0 everywhere else, so every other word's arithmetic is --bk-pad's, untouched. */
  --bk-col-indent: 0px;
  /* ── WHICH ELEMENTS ON A PAGE ARE BANDS. DECLARED HERE, ONCE. ────────────────────────────────
     The rules above already answer this correctly by asking whether the SECTION itself is a hero
     (`section:not([class*="hero"])`, further down this file). Three scripts asked it a fourth,
     fifth and sixth time and all three asked it the other way round — `s.closest('[class*="hero"]')`,
     which walks every ancestor as far as <body>. The renderer puts a `heromode-…` class on <body>
     for any brand whose record names a hero style, so on those sites EVERY band answered "yes, I
     am inside a hero" and both deploy gates measured nothing and printed their green line anyway.
     Measured on the built sites: 8 sections on a 72-page build, 11 on Top Tier, 13 on CHIdrate,
     zero surviving in each; 34 of the 334 built site folders carry a `heromode-` body class.
     So the scope is a token, parsed by the gates out of this one declaration, the same way
     --bk-gutter and the split-marker rule already are. It is inert at runtime — nothing consumes
     a string-valued custom property — and exists so that there is one place to change. */
  --bk-band-scope: "main section:not([class*='hero'])";
  /* ── THE PAGE STANDARD. DECLARED HERE, ONCE. ──────────────────────────────────────────────────
     Ian, 2026-08-19: "Even the margin, and you push everything to the left again. We spoke about
     this multiple times over and over. We finally fixed it in the very first dry run. You fuck it
     up again, so why is that?"
     Because it was never a rule. It was a patch. Centring was written as CSS scoped to the
     interior-page assembler, while FOUR of the five home templates declared `--bk-align: left`
     at the top of their own file — so the standard never governed them, and every new template
     was born misaligned and then patched by hand. That is the loop.
     A full-width band is CENTRED. That lives here, at the root, so a template that declares
     nothing inherits it and a NEW template cannot be born wrong. A lane's character is its type,
     its colour, its shapes and its photography — not where its headings sit.
     Split bands still range left: their copy sits beside a picture, which is composition. */
  --bk-align: center;
  /* Companions to --bk-align. text-align cannot steer a flex row or an auto margin, so a band
     whose copy follows the family while its button row stays hard-centred is the same defect one
     element down — which is exactly what the review found. These three always travel together. */
  --bk-justify: center;
  --bk-mi: auto;
}
/* THE STANDARD'S ONE EXCEPTION, DECLARED BESIDE IT. A split band holds its copy in a column
   beside a photograph; ranged left there is composition, not drift. It is written here rather
   than in the block route because an exception kept in a different file from the rule it excepts
   is how the rule got lost in the first place — and `standard-lint` now fails the build if any
   file other than this one declares these three tokens. */
/* THE COMPOSITION MARKERS, NAMED ONCE. Three different parts of the system had their own word for
   "this band's copy sits beside or over a picture, so ranged left is the design": the interior
   route stamps .bk-route-split, a home-page block stamps .bk-composed, and the split TREATMENT is
   .comp-split. The gate that polices alignment reads this very selector list out of this file, so
   adding a fourth name here is all it takes — there is no second list to keep in step, which is
   the mistake this whole file has been unlearning today. */
/* …and a sixth: the service-area band. It holds a heading and a paragraph in a left column beside
   a county map, which is the same composition as any other split — its heading ranges left because
   the map is next to it, not because the page drifted. Unnamed here it was the single left-aligned
   heading among six centred ones on Top Tier's home page, and G2 was right to ask about it and
   wrong about the answer. */
:where(.sl-body).sl-shelf :is(.bk-route-split, :where(.sl-body) .bk-composed, :where(.sl-body) .comp-split, :where(.sl-body) .img-text-section, :where(.sl-body) .sec-photo, :where(.sl-body) .section-service_area_map) {
  --bk-align: left;
  --bk-justify: flex-start;
  --bk-mi: 0;
}
/* …AND ONE BAND THAT ASKS FOR THE OPPOSITE. Every name above is a composition whose copy sits
   beside a picture, which ranges left — that is the rule and it is right. `.bk-prose-copy-centre`
   is a band whose OWNER asked for the copy down the middle anyway (Ian, on IV Revival's About
   band, 2026-09-18: "I don't like how you formatted the copy. Center it"), and a house rule is
   this file's opinion while the person whose website it is outranks it. Only a band that carries
   the class is affected, and nothing carries it unless a page record asks. It is declared here
   rather than in the block because alignment is a PAGE decision made in one file — the standard
   check fails the build on any other file declaring these three, which is how it caught the first
   attempt at this. */
:where(.sl-body).sl-shelf .bk-prose-copy-centre, :where(.sl-body) .bk-prose-copy-centre {
  --bk-align: center;
  --bk-justify: center;
  --bk-mi: auto;
}

/* …AND A CLIENT MAY SAY THE PAGE HAS ONE ALIGNMENT AND NO EXCEPTIONS.
   The exception above is right in principle: copy that sits BESIDE a picture is composed, and
   ranged left there is a design decision rather than drift. But it fires on six kinds of band, and
   on a page that carries several of them the reader does not see "composed" - they see a page
   where roughly half the headings are centred and half are not. Reported exactly that way: "there
   is a mix of how you have copy aligned; let's center it and keep it consistent."
   It is also plainly wrong on a PHONE, whichever brand it is: below the stacking width the picture
   is above the copy, not beside it, so the whole justification for ranging left has gone and the
   band is just the odd one out.
   `theme_json.align: "center"` sets this class. Absent it nothing changes, so every brand that has
   not asked renders byte-identical; and it is declared HERE, beside the exception it overrides,
   because these three tokens live in one file on purpose - standard-lint fails a build that
   declares them anywhere else. */
:where(.sl-body).sl-center-all :is(.bk-route-split, :where(.sl-body) .bk-composed, :where(.sl-body) .comp-split, :where(.sl-body) .img-text-section, :where(.sl-body) .sec-photo, :where(.sl-body) .section-service_area_map) {
  --bk-align: center;
  --bk-justify: center;
  --bk-mi: auto;
}

/* …AND ON A PHONE THE EXCEPTION IS SIMPLY OVER, FOR EVERY BRAND, WITHOUT ANYONE ASKING.
   The note above already said it: "It is also plainly wrong on a PHONE, whichever brand it is:
   below the stacking width the picture is above the copy, not beside it, so the whole
   justification for ranging left has gone." And then the only thing that acted on that sentence
   was an opt-in class a client had to request. So on every brand that never asked, a split band
   that stacked on a phone kept its desktop left alignment — the picture on top, the words ranged
   left under it, sitting between centred bands above and below. The owner, 2026-09-11: "on mobile
   you're aligning or margining everything to the left of the screen, whereas most of what we do on
   the desktop is centered... I feel like it almost always does it that way."
   It did, every time, on every client, and this is why.
   A split band's copy ranges left only while it is BESIDE its picture. Where each family stacks is
   its own business (900px here, 860 there, 768 somewhere else), so this does not guess at a single
   width for all of them — it takes the narrowest one, below which every split layout in the system
   has provably stacked, and centres there. Measured on the estate family: expert and conditions
   stack at 900, contact at 860, all stacked by 860. The families that stack wider still do not lose
   anything below this line, because below it they are all a single column. */
@media (max-width: 760px) {
  :where(.sl-body).sl-shelf :is(.bk-route-split, :where(.sl-body) .bk-composed, :where(.sl-body) .comp-split, :where(.sl-body) .img-text-section, :where(.sl-body) .sec-photo, :where(.sl-body) .section-service_area_map) {
    --bk-align: center;
    --bk-justify: center;
    --bk-mi: auto;
  }
}

/* On a SHELF page the assembler's own sections share the page with blocks, so its two centred,
   re-narrowed wrappers have to join the same grid — otherwise a hub page alternates a centred
   header with a left-aligned band and reads as two designs fighting. Scoped to body.sl-shelf on
   purpose: brands not on the shelf are untouched, byte for byte. */
:where(.sl-body).sl-shelf .container { max-width: var(--bk-col); }
/* the shelf's full-width convention is a CENTRED title, so the assembler's own section header
   and closing band join it — one band left-ranging among eight centred ones is the whole
   'disjointed' complaint in miniature */
:where(.sl-body).sl-shelf .section-header { text-align: center; }

/* A BAND DOES NOT RE-NARROW ITSELF INSIDE THE PAGE COLUMN.
   Two assembler bands set `max-width: var(--content-max)` in their own scoped style — 1120px — and
   then centre it inside the page's 1160px column, so they start 20px inside every other band on
   the page. Measured on Bolt at a realistic size: the product showcase and the credentials strip,
   at both widths, on two page types. Small enough to survive every check for weeks and large
   enough to be why a page "doesn't line up".
   On a shelf page the page owns the column and a band fills it. */
:where(.sl-body).sl-shelf :is(.prod-showcase, :where(.sl-body) .cards-center, :where(.sl-body) .credstrip, :where(.sl-body) .cred-strip) { max-width: 100%; margin-inline: 0; }
/* …AND THEY OBEY THE STANDARD, rather than a switch that predates it. These three pinned
   themselves left with `margin-inline: 0` unless the body happened to carry `sl-align-center`,
   which one blueprint of five sets. So on the other four, every hub page and every fall-through
   section put a CENTRED title inside a box hard against the left edge of a 1160px column: the
   title's optical centre landed ~250px left of the centre line of the content it captions, and on
   a hub page with no blocks at all the whole page read as left-hugging with a wasted right margin.
   That is the exact defect the centring round existed to close, surviving in a per-family switch
   written before there was a standard to switch to. They read the standard's own token now — which
   is `auto` at the root and `0` on a composed band, so the one case the switch was protecting is
   still protected, by the rule instead of by an exception. */
:where(.sl-body).sl-shelf .section-header, :where(.sl-body).sl-shelf .sl-prose, :where(.sl-body).sl-shelf .hub-intro { max-width: var(--bk-measure); margin-inline: var(--bk-mi); }
/* the assembler's closing band centres itself and narrows its container to 720px; on a shelf page
   that made it the one band out of step with everything above it */
/* The hub's own closing band is named beside the assembler's: it is the same band on a listing
   page, and its container was 1200px against everything else's 1160 — a second left edge, 20px
   out, on every listing page of every site. */
:where(.sl-body).sl-shelf :is(.final-cta, :where(.sl-body) .section-hub-cta) { text-align: center; padding-inline: var(--bk-pad); }
:where(.sl-body).sl-shelf :is(.final-cta, :where(.sl-body) .section-hub-cta) .container { max-width: var(--bk-col); padding-inline: 0; }

/* ── THE PAGE'S CENTRE LINE, AND ONE TYPE SCALE ───────────────────────────────────────────────
   Seen from above the page read as a left-hugging column with a wasted right margin, and every
   band a slightly different size — "it doesn't feel centered or balanced or consistent… feels
   like you took a bunch of sections from random places and threw them together".

   Two causes, both mine. Enforcing ONE left edge gave the page structure and no centre: every
   heading pinned hard left with copy stopping at a reading measure, so two thirds of the way
   across the screen was permanently empty. And each block carried its own heading size — nine
   blocks, nine scales — so nothing lined up as one family.

   A SPLIT band (heading held in a left column beside its copy — the reference's colour band) keeps
   its heading left: that is the composition. Every other band is full width, and its heading is
   the page's centre line, exactly as the reference sets "Signs and Symptoms of Dehydration" and
   "What Causes Dehydration?" — centred, with a centred standfirst under it, and the content full
   width beneath. That is what makes their page feel balanced with the same amount of copy.

   These live in global.css rather than in 46 components on purpose: one page-level decision, made
   once, that no individual block can drift away from. Family voice — typeface, weight, colour,
   letterfit — is untouched; only SIZE and ALIGNMENT are pulled onto one system. */
:where(.sl-body) {
  --bk-h2: clamp(1.75rem, 3vw, 2.6rem);
  --bk-h3: clamp(1.1rem, 1.35vw, 1.35rem);
  --bk-lead: clamp(1.02rem, 1.15vw, 1.16rem);
}
/* !important, deliberately, in exactly one place. Astro stamps a scope attribute onto every
   compound in a component's own styles, so `.bk-prose-editorial h2` compiles to
   `.bk-prose-editorial[data-astro-cid-x] h2[data-astro-cid-x]` — four classes and two elements,
   which outranks any sane page-level selector. Without this the shared type scale silently loses
   to nine different component defaults, which is exactly the "sizing changes from section to
   section" it exists to end. The alternative is editing 46 components and trusting the 47th. */
/* THE BAND'S OWN PADDING, guaranteed. Three separate complaints — an icon tile touching the top
   border of a band, another one almost clipped, and a footnote escaping to the far bottom-left of
   the page — were all one bug: several block sections computed padding: 0 despite their own rule
   setting it from the tokens. Whatever wins that cascade, the page grid cannot be left to a
   component to honour; it is the one thing every band must have. Set here, once.

   Compact strips opt out by name rather than by hoping to win a specificity fight: a trust strip
   and a marquee are deliberately tight to the band above them. */
/* …AND THE EXEMPTION HAS TO NAME THE CLASS THAT IS ACTUALLY ON THE ELEMENT. `.bk-mq` appears
   nowhere in this codebase — the marquee renders `.bk-marq` — so the one band the comment above
   calls "deliberately tight" was handed full section padding by the very rule written to spare it,
   and its own tight value lost to the !important. Measured at 76px top and bottom against an
   intended 36px: two lines of type floating in a 225px band of saturated colour. A class name
   guessed rather than checked is a rule that does nothing, which is this file's recurring lesson. */
/* …AND A BAND WHOSE CONTENT HANGS BELOW ITS OWN PANEL KEEPS THE ROOM IT KEPT FOR IT.
   The lifted contact band is drawn as a panel with an hours card lifted off its bottom edge — the
   overhang is the design, and the band reserves 150px of bottom padding to land it in. This rule
   is !important, so on an interior page it replaced that reserve with the ordinary rhythm and the
   NEXT band's ground sliced the card in half, through the middle of its "Book Appointment" button.
   Ian, 2026-09-18: "You cut off the section like they're chopping the cards." It only appeared the
   day this band became reachable from interior pages at all; on the home page, which this rule does
   not touch, it has always been right. Exempted by the class that is actually on the element —
   see the lesson directly above about a class name guessed rather than checked. */
:where(.sl-body).sl-shelf .bk-route > section:not(.bk-cs):not(.bk-marq):not(.bk-contact-lift):not([class*="-hero"]) {
  padding-block: var(--bk-rhythm) !important;
  padding-inline: var(--bk-pad) !important;
}
:where(.sl-body).sl-shelf .bk-route > section:is(.bk-cs, :where(.sl-body) .bk-marq) { padding-block: var(--bk-rhythm-tight) !important; padding-inline: var(--bk-pad) !important; }

/* ONE BAND, ONE PAINTING OF THE PICTURE.
   Every block paints its own ground from --bk-band, and --bk-band is INHERITED from the route
   wrapper — so a route that emits TWO blocks paints the band twice, once per block. With a colour
   that is invisible. With a photograph it is not: each block cover-crops the picture to its own
   height and restarts the veil, so the reader sees the same faces stacked twice with a hard seam
   between them, and page-rules counts one file as two photographs. Measured on Tidewater's
   glutathione page, where the table route (BlockRoute.astro, the `extras` card grid above its
   table) is the only route in the system that emits two blocks into one wrapper.
   The band belongs to the ROUTE, not to the block: paint it once on the wrapper — whose box is
   exactly the two blocks — and let the blocks sit on it.
   PHOTO ONLY, deliberately. On a colour band there is nothing to fix, and blanking those blocks
   makes them read as UNPAINTED, which merges them with unpainted neighbours and invents
   same-ground runs that were not there: measured, Vela's vitamin-c page went from one to three. */
:where(.sl-body).sl-shelf .bk-route.bk-band-photo:has(> section ~ section) { background: var(--bk-band); }
:where(.sl-body).sl-shelf .bk-route.bk-band-photo:has(> section ~ section) > section { --bk-band: transparent; }

:where(.sl-body).sl-shelf .bk-route section h2 { font-size: var(--bk-h2) !important; line-height: 1.14; }
:where(.sl-body).sl-shelf .bk-route section h3 { font-size: var(--bk-h3) !important; }
:where(.sl-body).sl-shelf .bk-route section h3 { font-size: var(--bk-h3); }

/* three levels deep, because the blocks nest their heading differently: some put the h2 straight
   in the section, some inside a copy column, some inside a copy column inside an inner wrapper.
   One checklist band sitting left among eight centred ones was exactly that third level. */
/* CENTRE THE WHOLE BAND, NOT JUST ITS TITLE. Centring the heading and leaving the lane's own
   left-ranging tokens in place produced bands with THREE alignments at once — a centred heading,
   a left-ranged paragraph, and a button row hard against the left margin 300px away from both.
   The closing call-to-action showed it on every brand. A full-width band is centred as a unit:
   the tokens the blocks already read are re-pointed, so copy centres and buttons centre with it.
   Split bands are untouched: their copy sits beside a photograph and belongs ranged left — see
   the exception declared with the standard above.
   This block used to carry !important, because the block route stamped the family's skin as an
   INLINE style on this very element and inline beats any stylesheet rule. That inline declaration
   is gone: the route no longer decides alignment at all, so the root standard simply reaches the
   blocks and nothing has to shout it down. */

/* BOTH PATHS, ONE RULE. Everything below was written as `.bk-route …`, which is the INTERIOR-page
   assembler. The five blueprint home pages render through their own templates and wrap their bands
   in `.bk-home` — so none of this reached them, and the home page is the page Ian actually looks
   at. That is the same fault as the eleven alignment declarations, one level up: a rule that names
   one code path is not a rule, it is a patch on that path. The selector now names both, and a band
   opts out only by being a COMPOSITION — a `.bk-composed` band, whose copy sits beside or over a
   photograph, which is the one case where ranged left is the design.

   DESCENDANT, not a child chain. The chain reached three levels and the prose block nests its
   heading four deep (section > in > copy > head > h2), so the one band type that most needed
   centring was the one the rule could not see — and it is the band Ian kept pointing at. Depth is
   not something a page-level rule should have to know. Card headings are h3, so h2 is safe. */
/* WHERE A BAND'S TITLE SITS — NAMED ONCE, FOR ALL THREE RENDERERS.
   This was seven near-identical selectors, each scoped to `:is(.bk-route, .bk-home)` — the
   interior route and the home templates. There is a THIRD renderer: the hub, which draws every
   listing page. It was never in the list, so on /iv-packages the section headings centred (a
   different rule reaches those) while the paragraph under them ranged left inside a centred
   measure, and the rows below started at the page's left edge. Measured: five bands, FOUR
   different left edges, on a page whose interior sibling has exactly one.
   Rewritten as one rule with the three renderers named in a single :is(), so a fourth is one
   word and there is no second list to keep in step. The hub marks its own bands `.bk-hub`
   rather than gaining a wrapper, because `main > section` is load-bearing in this file. */
:where(.sl-body).sl-shelf :is(
    :is(.bk-route:not(.bk-route-split), :where(.sl-body) .bk-home) section, :where(.sl-body) section.bk-hub
  
  ):not(.bk-composed):not(.bk-prose-has-photo):not([class*="hero"]) :is(
    h2, :where(.sl-body) [class$="-head"], :where(.sl-body) [class*="eyebrow"], :where(.sl-body) [class*="kicker"], :where(.sl-body) [class$="-intro"], :where(.sl-body) [class$="-sub"]
  ):not(:where(h3, :where(.sl-body) h4, :where(.sl-body) :has(h3), :where(.sl-body) :has(h4)) ~ *) {
  /* !important for the same reason the type scale needs it: a block's own
     `text-align: var(--bk-align)` carries Astro's scope attribute and outranks any page-level
     selector. The PAGE owns where a band's title sits; the block owns how it looks. */
  text-align: center !important;
  margin-inline: auto;
}
/* AN H3 OPENS A GROUP, AND ONCE A GROUP IS OPEN YOU ARE NOT IN THE BAND'S TITLE ANY MORE.
   This rule centres a band's TITLE, and it picks its targets by NAME - anything whose class ends
   in "-intro", "-head", "-sub". That reads a name and infers a position, and the inference is
   wrong the moment the same name is used for a paragraph deeper inside the band.
   Measured on a live listing page: a group heading at x=140, its own paragraph at x=413, and the
   list of items below it back at x=140. Three things in one group, the middle one starting 273px
   further right, because its class happened to end in "-intro" and this rule centred it with an
   !important. It reads as a paragraph that has come loose.
   The band's title is the run of headings BEFORE any group opens. h2 opens a band; h3 opens a
   group inside it - so anything standing after an h3, or after something CONTAINING one (the
   heading is often wrapped in a row with a link beside it), belongs to that group and keeps the
   group's alignment. Checked against twelve built pages before it was written: it un-centres the
   four paragraphs that had come loose and leaves all 109 correctly centred titles alone. */
/* a centred heading needs a measure or it runs the full 1160px and stops feeling like a title */
:where(.sl-body).sl-shelf :is(
    :is(.bk-route:not(.bk-route-split), :where(.sl-body) .bk-home) section, :where(.sl-body) section.bk-hub
  ):not(.bk-composed):not([class*="hero"]) h2 { max-width: 26ch; }
:where(.sl-body).sl-shelf :is(
    :is(.bk-route:not(.bk-route-split), :where(.sl-body) .bk-home) section, :where(.sl-body) section.bk-hub
  ):not(.bk-composed):not([class*="hero"]) :is([class$="-intro"], :where(.sl-body) [class$="-sub"]) { max-width: 64ch; }
/* the glyph tile is part of the heading group, so it centres with it. Both names: the blocks call
   it .bk-blk-icon and the prose block calls it .bk-prose-icon, and the one the rule missed sat
   stranded at the far left of a band whose heading had just been centred. */
:where(.sl-body).sl-shelf :is(
    :is(.bk-route:not(.bk-route-split), :where(.sl-body) .bk-home) section, :where(.sl-body) section.bk-hub
  ):not(.bk-composed):not([class*="hero"]) :is(.bk-blk-icon, :where(.sl-body) .bk-prose-icon) { margin-inline: auto; }
/* …AND ON A PHONE THE COMPOSED BANDS JOIN IT. The title rule above skips a `.bk-composed` band
   because its title sits BESIDE a picture, and the phone rule by the standard (760px) already says
   that premise is over once the band stacks. But that rule only re-points the tokens, and a token
   reaches nothing a block has written as a plain `text-align: left` - so on the owner's phone,
   2026-09-11, the reviews, the photo steps and the product menu on an invented client kept left
   headings between centred bands while two other composed bands, which read the token, centred.
   Twelve blocks were corrected at source the same day; this is the net under all of them and under
   the next block somebody writes. It reads the token rather than naming a side, so the one decision
   about where a phone's titles sit stays with the standard at the top of this file. */
@media (max-width: 760px) {
  :where(.sl-body).sl-shelf :is(
      :is(.bk-route, :where(.sl-body) .bk-home) section, :where(.sl-body) section.bk-hub
    ):not([class*="hero"]) :is(
      h2, :where(.sl-body) [class$="-head"], :where(.sl-body) [class*="eyebrow"], :where(.sl-body) [class*="kicker"], :where(.sl-body) [class$="-intro"], :where(.sl-body) [class$="-sub"]
    ):not(:where(h3, :where(.sl-body) h4, :where(.sl-body) :has(h3), :where(.sl-body) :has(h4)) ~ *) {
    text-align: var(--bk-align, center) !important;
    margin-inline: var(--bk-mi, auto);
  }
}
/* …and so does any CONTENT block narrower than the column. A band can fill its width and still
   LEAN: the editorial FAQ caps its list at 900px, a card grid whose last row holds two of three
   leaves the third slot empty on the right, a two-column body ends short in its second column.
   Measured as the centre of mass of each band's ink against the column's own centre, those sat
   9-21% left of centre under a heading that was perfectly centred — which is exactly the
   "content below it still leans to the left" that survived the centring round. In a full-width
   band the content centres with its title; in a split band it stays in its column. */
/* …BUT ONLY WHILE THE BAND IS STILL SPEAKING FOR ITSELF, WHICH IS THE SAME GUARD THE HEADING RULE
   ABOVE ALREADY CARRIES AND THIS ONE DID NOT. Both rules pick their targets by NAME - a class
   ending in "-body" - and the note above spells out why that is dangerous: the inference is wrong
   the moment the same name is used for a paragraph deeper inside the band. That is exactly what
   happened, one rule further down, and it shipped.
   Measured on Nevue's home page: the journey rail draws a numbered step as a heading and a
   paragraph in one column. The heading sat at x=675 and its OWN paragraph at x=822 - 147px
   further right, because the paragraph's class ends in "-body" and this rule centred it inside a
   column wider than its own measure. Four steps, four paragraphs adrift from the four headings
   they belong to, on the band that explains how the service works.
   So the same exclusion: once an h3 has opened a group, everything after it belongs to that group
   and keeps the group's left edge. A band's own content block still centres, because it stands
   before any h3. */
:where(.sl-body).sl-shelf :is(.bk-route:not(.bk-route-split), :where(.sl-body) .bk-home) section:not(.bk-composed):not([class*="hero"])
  :is([class$="-list"], :where(.sl-body) [class$="-grid"], :where(.sl-body) [class$="-cols"], :where(.sl-body) [class$="-rows"], :where(.sl-body) [class$="-body"], :where(.sl-body) [class$="-people"], :where(.sl-body) [class$="-cards"], :where(.sl-body) [class$="-items"]):not(:where(h3, :where(.sl-body) h4, :where(.sl-body) :has(h3), :where(.sl-body) :has(h4)) ~ *)
  { margin-inline: auto; }
/* a grid whose last row is short centres its tracks rather than hanging them on the left */
:where(.sl-body).sl-shelf :is(.bk-route:not(.bk-route-split), :where(.sl-body) .bk-home) section:not(.bk-composed):not([class*="hero"]) [class$="-grid"], :where(.sl-body).sl-shelf :is(.bk-route:not(.bk-route-split), :where(.sl-body) .bk-home) section:not(.bk-composed):not([class*="hero"]) [class$="-cards"] { justify-content: center; }
/* the plain prose measure was the worst offender — a 68ch column hard against the left edge with
   half the screen empty beside it. Full width, in two columns, like the reference's body copy. */
:where(.sl-body).sl-shelf :is(.bk-route:not(.bk-route-split), :where(.sl-body) .bk-home) :not(.bk-composed) > .bk-prose-copy { max-width: none; }
/* short copy centres its box; long copy fills the column in two text columns */
:where(.sl-body).sl-shelf .bk-route:not(.bk-route-split) .bk-prose-short .bk-prose-body { max-width: 62ch; margin-inline: auto; column-count: 1; }
:where(.sl-body).sl-shelf .bk-route:not(.bk-route-split) .bk-prose-short .bk-prose-cta { justify-content: center; }
/* a photograph already takes half the band; splitting the remaining half into two text
   columns squeezes the copy into slivers and leaves the second one short — the band Ian
   called "an unfinished section" was exactly that */
:where(.sl-body).sl-shelf .bk-route .bk-prose-has-photo .bk-prose-body { column-count: 1 !important; }
/* TWO COLUMNS NEED ENOUGH COPY TO FILL THEM. A short section is already narrowed to 62ch and
   centred by the rule above; splitting THAT into two columns gives two 250px slivers about six
   words wide, ragged on the right, floating in the middle of a full-width band. The short rule
   came first in the file and lost the tie to this one, so every brief section on the plainest
   rhythm shipped that way. Short copy is one column, always. */
:where(.sl-body).sl-shelf .bk-route:not(.bk-route-split) .bk-prose-l-measure:not(.bk-prose-short) .bk-prose-body { column-count: 2; column-gap: clamp(32px, 3.4vw, 56px); }
:where(.sl-body).sl-shelf .bk-route:not(.bk-route-split) .bk-prose-l-measure .bk-prose-body p { break-inside: avoid; }
@media (max-width: 860px) {
  :where(.sl-body).sl-shelf .bk-route:not(.bk-route-split) .bk-prose-l-measure .bk-prose-body { column-count: 1; }
}
/* A trust strip is a compact reassurance band, not a full section; keep it tight to the
   hero above it so it does not float in a sea of padding. */
:where(.sl-body) .section-trust_strip { padding-top: clamp(1.5rem, 3vw, 2.25rem); padding-bottom: clamp(1.5rem, 3vw, 2.25rem); }
:where(.sl-body) .section + .section { border-top: 1px solid var(--c-border); }

:where(.sl-body) .btn {
  display: inline-block;
  padding: 0.875rem 1.5rem;
  border-radius: var(--btn-radius);
  font-weight: 600;
  font-family: var(--font-body);
  font-size: 1rem;
  cursor: pointer;
  transition: transform .15s ease, box-shadow .15s ease;
  border: 1px solid transparent;
  text-decoration: none;
}
/* ── A FILLED CONTROL HAS A PLATE OF ITS OWN. IT IS NOT THE ROOM. ───────────────────────────────
   A FILLED CONTROL IS A SMALL ROOM was the previous answer here, and it was half right: the fill
   moved off `--c-primary` (which on a dark brand IS the page: 1.04:1, a button with no plate) and
   onto `--c-room`, the primary lifted until it steps off the page. But the room is the ground a
   BAND paints, and a control lands on bands the room does not have to step off — measured on the
   dark estate cell, one page carried FIVE different primary calls to action: 17.59:1 (the hero's
   light plate), 8.37:1 (the family's accent on a photograph), and three that were not buttons at
   all — 1.50:1 on the tinted band, 1.44:1 on the closing band, and 1.00:1 on a package card,
   because the room, the card and the button were all the same colour. A plate that has to be a
   band as well cannot also be measured against every band.
   So the plate is its OWN role, with two expressions:
     LIGHT  the room and its ink, which is exactly what this rule painted, byte for byte, on every
            light page in the fleet (`--c-room` IS `--c-primary` there and `--c-on-room` is what
            `.btn-primary` has always resolved).
     DARK   the page's light stock, which brand.ts guarantees is `#FFFFFF` on a dark ground (every
            other stock is re-derived dark, so the light-stock fallback chain lands on white), with
            the brand's own colour as its caps. That pairing is not new: it is what the ledger lane
            already gives the hero button and the nav chip, and it is the treatment that measured
            17.59:1 and 15.41:1 — the two the reviewer called the good ones. Making the third place
            agree is what turns five voices into one.
   `--c-control-ring` is read by the dark ring block near the foot of this file: a control that
   takes this plate has a plate and needs no rescue outline, so it turns the ring off for itself.
   The HOVER moves off `--c-primary-dark`, which on a dark page can BE the page (measured #08252C
   on #08252C — the primary vanished under the pointer, recorded as debt in ground-debt.json); it
   is now a step of the plate toward its own ink, which is a darkening on a white plate and the
   brand's dark on a light one. On a light page `--c-control-hover` resolves to `--c-primary-dark`,
   so the hover is byte-identical there too. */
:where(.sl-body) { --c-control: var(--c-room); --c-on-control: var(--c-on-room); --c-control-hover: var(--c-primary-dark); }
:where(.sl-body) .btn-primary { background: var(--c-control); color: var(--c-on-control); --c-control-ring: transparent; }
:where(.sl-body) .btn-primary:hover { background: var(--c-control-hover); text-decoration: none; }
/* Outline button: transparent fill so the label stays legible in BOTH contexts.
   On a light surface it reads as primary text + primary border; on a dark hero or
   CTA band (where the label/border are forced to surface-white) it reads as a clean
   white outline. A solid surface (white) fill here used to collapse to white-on-white
   wherever the text was also forced white, making the label invisible. */
:where(.sl-body) .btn-secondary { background: transparent; color: var(--c-link, var(--c-primary)); border-color: var(--c-link, var(--c-primary)); }
:where(.sl-body) .btn-secondary:hover { background: var(--c-primary); color: var(--c-on-primary); border-color: var(--c-primary); text-decoration: none; }
/* A TEXT BUTTON IS A LINK, NOT A BUTTON WITH THE FILL TAKEN OUT. This dropped the background and
   the horizontal padding but kept `.btn`'s 999px radius and drop shadow, so the shadow painted a
   54x44 oval NARROWER THAN ITS OWN LABEL — "Call" hanging out of both ends of a pill it was never
   going to fit. Nothing was overlapping and nothing was crushed; the pill was simply the wrong
   shape for a thing with no padding, and it read as deformed because it was.
   Used in exactly one place: the header Call link.
   Written `.btn.btn-text` (0,2,0) rather than `.btn-text` (0,1,0) on purpose: `.btn` picks its
   shadow back up 1,070 lines below this at equal specificity, where source order hands it the win.
   Being one class heavier settles it wherever either rule happens to sit. */
:where(.sl-body) .btn-text { background: transparent; color: var(--c-link, var(--c-primary)); padding: 0.5rem 0; }
/* Only the button CHROME gets the extra weight. Carrying `color` up here as well made the rule beat
   `.site-nav a` (0,1,1) too, which turned the header Call link from near-black to brand teal — about
   3.9:1 on white at 16px bold, an R15 warning invented while fixing something else. Keep the colour
   question exactly where it was. */
:where(.sl-body) .btn.btn-text { box-shadow: none; border-radius: 0; border-color: transparent; }

/* AN OUTLINE BUTTON TAKES THE BRAND COLOUR, WHICHEVER BAND IT LANDS ON.
   It is drawn in the brand's own colour with a matching outline, which is right on a pale band and
   invisible on a dark one - and for a brand whose colour IS near-black, a dark band makes the
   button vanish completely. Measured: a "Call Us" nobody can see, at 1.1 to 1 against the ground
   behind it, on ten pages across two brands.
   The rule below existed for dark HEROES, and its own comment said it mirrored "the dark CTA band
   treatment". That treatment did not exist. The closing band paints itself dark and sets its own
   ink for headings and copy, and the button was the one thing left behind - the same decision
   written in one place and missing from the other, which is the fault this repo pays for over and
   over. The closing band is named here so both are one rule rather than two kept in step by hand. */
:where(.sl-body) .hero-image-bg .btn-secondary, :where(.sl-body) .hero-video .btn-secondary, :where(.sl-body) .hero-gradient .btn-secondary, :where(.sl-body) .final-cta .btn-secondary, :where(.sl-body) .section-hub-cta .btn-secondary { color: var(--c-cta-text, var(--c-on-dark)); border-color: var(--c-cta-text, var(--c-on-dark)); }
:where(.sl-body) .hero-image-bg .btn-secondary:hover, :where(.sl-body) .hero-video .btn-secondary:hover, :where(.sl-body) .hero-gradient .btn-secondary:hover, :where(.sl-body) .final-cta .btn-secondary:hover, :where(.sl-body) .section-hub-cta .btn-secondary:hover { background: var(--c-cta-text, var(--c-surface)); color: var(--c-primary-dark); }

:where(.sl-body) .card {
  background: var(--c-surface);
  border: var(--card-border-width) solid var(--c-border);
  border-radius: var(--card-radius);
  padding: 1.5rem;
  box-shadow: var(--card-shadow);
}
:where(.sl-body) .cards-elevated .card:hover { box-shadow: var(--card-hover-shadow); transform: translateY(-2px); }

:where(.sl-body) .grid { display: grid; gap: 1.5rem; }
:where(.sl-body) .grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
/* Centered wrapping card row — an incomplete last row (e.g. 5 items) centers instead
   of leaving an empty grid slot. Preferred over .grid-3 for feature/step/review cards. */
:where(.sl-body) .cards-center { display: flex; flex-wrap: wrap; justify-content: center; gap: 1.5rem; max-width: var(--content-max); margin-left: auto; margin-right: auto; }
:where(.sl-body) .cards-center > .card { flex: 0 1 var(--sl-basis, 330px); }
@media (max-width: 768px) { :where(.sl-body) .cards-center > .card { flex-basis: 100%; } }
:where(.sl-body) .grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 768px) {
  :where(.sl-body) .grid-3, :where(.sl-body) .grid-4 { grid-template-columns: minmax(0, 1fr); }
}

/* Header */
:where(.sl-body) .site-header {
  position: sticky; top: 0; z-index: 50;
  background: var(--c-surface);
  border-bottom: 1px solid var(--c-border);
}
/* THE ANCHOR OFFSET LIVES HERE, BESIDE THE STICKY BAR THAT CREATES THE NEED FOR IT. It used to be
   typed out one lane at a time — thirteen identical `scroll-margin-top: 6rem` lines scattered
   through the shelf, one in each lane's chrome section, and nowhere else in this file. Adding a
   lane meant remembering to type a fourteenth copy, so `refine-dark-luxe` never got one and neither
   did a site carrying no lane at all: on those pages every in-page jump landed its target at the
   very top of the window with the sticky bar still covering it, which on a Top Tier build put the
   closing band's eyebrow and the top of its heading behind 142px of nav. One unscoped rule answers
   every lane and every lane-less site at once. The 6rem the shelf already used is kept as the
   default so nothing that renders correctly today moves; a lane whose bar is taller than that sets
   `--sl-anchor-offset` rather than restating the property, and a lane-scoped rule outranks this one
   in any case. */
:where(.sl-body) [id] { scroll-margin-top: var(--sl-anchor-offset, 6rem); }
/* THE HEADER WRAPS RATHER THAN OVERFLOWS, AND NO BREAKPOINT COULD HAVE DONE THIS.
   The drawer takes over at 900px, but a one-row bar does not fit again until far above it, and how
   far depends entirely on how many nav items the site has. Measured intrinsic widths, same build,
   nav length varied:  3 items 899px · 4 items 1032 · 5 items 1123 · 6 items 1236 · 7+ over 1240.
   So between 901px and as much as 1235px the bar was overflowing its container, and what that
   looked like on Pure IV at 1024 was not subtle: Book Online sat with its right edge at 1150px —
   entirely off screen — the phone glyph and the dropdown chevron were crushed to zero width, and
   the whole DOCUMENT scrolled sideways (scrollWidth 1150 vs 1024) on every page of the site.
   A raised breakpoint cannot fix this: a number high enough for a 7-item nav (≈1240) puts a
   hamburger on a 3-item site 400px before it needs one. The fit is a function of content, so the
   remedy has to be too — the row wraps, which costs height only at the widths that were broken and
   is self-adjusting for every nav length. `margin-left: auto` keeps the nav hard right on both the
   one-row and the two-row form; `justify-content` alone right-aligns only while they share a line. */
:where(.sl-body) .site-header .container {
  display: flex; align-items: center; justify-content: space-between;
  flex-wrap: wrap; row-gap: 0.5rem;
  padding-top: 1rem; padding-bottom: 1rem;
}
:where(.sl-body) .site-header .site-nav { margin-left: auto; }
:where(.sl-body) .site-header .logo img, :where(.sl-body) .site-header .logo svg { max-height: 44px; }
:where(.sl-body) .site-nav { display: flex; gap: 1.5rem; align-items: center; }
:where(.sl-body) .site-nav a { color: var(--c-text); font-weight: 500; }
@media (max-width: 768px) { :where(.sl-body) .site-nav .nav-links { display: none; } }

/* Footer */
:where(.sl-body) .site-footer { background: var(--c-footer-bg, var(--c-primary-dark)); color: var(--c-footer-text, var(--c-bg)); padding: 3rem 0 1.5rem; }
:where(.sl-body) .site-footer a { color: var(--c-footer-text, var(--c-bg)); }
:where(.sl-body) .site-footer .footer-grid { display: grid; grid-template-columns: 2fr minmax(0, 1fr) minmax(0, 1fr); gap: 2rem; margin-bottom: 2rem; }
@media (max-width: 768px) { :where(.sl-body) .site-footer .footer-grid { grid-template-columns: minmax(0, 1fr); } }
:where(.sl-body) .site-footer .footer-bottom { padding-top: 1.5rem; border-top: 1px solid var(--c-footer-rule, rgba(255,255,255,0.15)); font-size: 0.875rem; opacity: 0.85; }

/* Hero variants */
:where(.sl-body) .hero { position: relative; overflow: hidden; display: flex; align-items: center; padding: 4rem 0; }
/* Its height is decided by the one hero rule at the top of this file. */
/* Solid brand-dark ground UNDER the photo: if --hero-bg is unset or the image 404s (e.g. a
   stale storage URL), the hero degrades to dark-brand-with-white-text instead of the
   white-on-white that an image-bg hero would otherwise show. Robust for every brand. */
:where(.sl-body) .hero-image-bg { color: var(--c-on-dark); background: var(--c-hero-plate); }
:where(.sl-body) .hero-image-bg::before {
  content: ''; position: absolute; inset: 0;
  background-size: cover; background-position: 50% var(--sl-hero-focus-y);
  background-image: var(--hero-bg);
  z-index: 0;
}
:where(.sl-body) .hero-image-bg::after { content: ''; position: absolute; inset: 0; background: var(--hero-overlay, linear-gradient(135deg, rgba(0,0,0,0.78), rgba(0,0,0,0.45))); z-index: 1; }
:where(.sl-body) .hero-image-bg .hero-inner { position: relative; z-index: 2; max-width: 720px; }
/* ── hero.align:'center' ─────────────────────────────────────────────────────────────────────
   Type centred over the subject and pushed to the LOWER half of the frame, which is where a
   full-bleed video hero wants it — the top of the frame is the picture, the bottom is the offer.
   Scoped to .hero-align-center so no existing hero moves. */
:where(.sl-body) .hero-align-center .hero-inner { max-width: 860px; margin-left: auto; margin-right: auto; text-align: center; }
/* "Lower side of the page", not the floor: flex-end alone ran the BOOK NOW button off the bottom
   edge of the fold. The padding is what makes it the lower THIRD rather than the last pixel. */
:where(.sl-body) .hero-align-center .container {
  display: flex; flex-direction: column; justify-content: flex-end; min-height: inherit;
  padding-bottom: clamp(3.5rem, 11vh, 8rem);
}
/* THE FOLD WAS BEING PAID FOR TWICE. The container above inherits the band's whole minimum height
   (the fold, already capped to the screen), and the band then added its own vertical padding
   OUTSIDE that — 64px on top and 194px underneath at 1440x900 — so a band capped at 786px drew at
   1044px, and nothing below it could be seen at three of the five window sizes fold-fit opens.
   Measured on Top Tier's home page, 2026-09-10.

   The container already owns the inset (its own padding-bottom is what sets the copy in the lower
   third), so on a centred photographic band the band's own vertical padding does no work except to
   overflow. Taking it off leaves the copy where it was, less exactly that padding: the headline
   moved up 64px on a desktop and the button still ends at 84% of the screen, against 91% before.

   The alternative that was tried first — dropping `min-height: inherit` — fits the screen too, but
   the copy then centres in the band and rides up into the top third, which changes an approved
   hero rather than fixing one. !important because the lane layer pads `.hero` with !important. */
:where(.sl-body) section.hero.hero-align-center.hero-image-bg { padding-top: 0 !important; padding-bottom: 0 !important; }
:where(.sl-body) .hero-align-center .hero-inner .cta-row, :where(.sl-body) .hero-align-center .hero-inner .hero-rating { justify-content: center; }
:where(.sl-body) .hero-align-center .hero-inner .hero-tagline { margin-left: auto; margin-right: auto; }
/* The reading-floor gradient is anchored to the text column; centred, it must scrim both sides. */
:where(.sl-body) .hero-align-center.hero-image-bg .hero-inner::after { left: -12vw; right: -12vw; }

/* hero.ink:'primary' lives at the END of this file — see the block there. Placement is the
   point: the archetype layer forces white hero ink with !important at the same specificity, so
   only source order can settle it. */

:where(.sl-body) .hero-image-bg h1, :where(.sl-body) .hero-image-bg p { color: var(--c-on-dark); }

/* ══ THE TEXT-COLUMN SCRIM — legibility that does not cost the photograph ═════════════════════
   WHY A SECOND LAYER EXISTS AT ALL. Every art direction paints its own hero glaze on
   `.hero-image-bg::after`, and each one is a DIRECTIONAL wash (a 98deg/135deg ramp, dark at the
   leading edge, near-clear at the trailing edge) chosen to make the photo read as that brand.
   That ramp is tuned to the FRAME, not to the text: it is only reliably dark for the first ~40%
   of the width. A headline is 60-80% of the width on desktop and 100% on a phone, so its trailing
   half sits where the wash has already thinned to ~20-30% — which is exactly where the measured
   failures were (white H1 over a bright face: /iv-treatments 3.27:1 across 29.4% of the headline
   area, /iv-therapy 3.39:1, /faq 3.39:1, and on the About hero 2.79:1 laid over the founders'
   faces). Every one of those archetype washes is `!important`, so a legibility floor cannot be
   appended to them; and raising them globally would flatten the photo across the whole frame,
   which is the "flat dark wash" the art direction was built to avoid.
   So the floor is anchored to the TEXT COLUMN instead: a gradient that lives on `.hero-inner`,
   bleeds off the leading edge, and fades out just past where the copy ends. The photograph keeps
   its clean side; only the ground under the type is guaranteed.
   Why it is allowed to paint over the archetype glaze: `.hero-inner` is `position: relative;
   z-index: 2`, i.e. its own stacking context, so this ::after at z-index -1 sits above the hero's
   ::after and below the copy. No specificity fight, no !important.
   Note visual-lint R15 cannot see any of this (it reads computed background COLOURS and skips
   image bands), which is why the failures survived every gate; `npm run hero-contrast` measures
   the composited pixels. */
/* IMAGE heroes only. Video heroes are deliberately excluded: their scrim is designed around the
   footage (Top Tier overlays its trust strip on the film and takes its legibility from the video's
   own bottom fade), and the measured failures were all photo heroes. */
:where(.sl-body) .hero-image-bg .hero-inner::after {
  content: ''; position: absolute; z-index: -1; pointer-events: none;
  /* Bleed hard off the leading edge (the hero is `overflow: hidden`, so -50vw simply reaches the
     frame edge at any width) and past the trailing edge, so the fade-out never lands ON a line.
     TOP AND BOTTOM BLEED THE SAME WAY, and that is not cosmetic. This gradient runs LEFT TO RIGHT,
     so its top and bottom edges are hard cuts, not fades. Boxed to the text block (the old
     -2.75rem) those cuts landed inside the picture: on a 725px hero the wash covered 109-794px and
     left a ~20px untinted strip along the top and another along the bottom, each ending in a
     visible horizontal line across the photograph. Reported repeatedly, and correctly — an effect
     of this shape is meant to sit on the whole frame. -100vh is simply "past the edge at any
     viewport"; `.hero { overflow: hidden }` does the clipping, exactly as -50vw already relied on.
     The ramp itself is unchanged, so the measured text contrast is unchanged; only the two dead
     strips go away. Mobile keeps its own inset below — that ramp runs top-to-bottom and is already
     transparent at both ends, so it has no hard edge to expose. */
  inset: -100vh -14vw -100vh -50vw;
  background: var(--hero-text-scrim, linear-gradient(to right,
    color-mix(in srgb, var(--c-primary-dark) 68%, transparent) 0%,
    color-mix(in srgb, var(--c-primary-dark) 62%, transparent) 62%,
    color-mix(in srgb, var(--c-primary-dark) 36%, transparent) 86%,
    transparent 100%));
}
/* A phone headline is the full column, so there is no trailing edge to fade INTO: a horizontal
   ramp would starve the ends of every line (measured: the same heroes ran 2.15-3.12:1 at 390px,
   worse than desktop). Below the breakpoint the scrim goes VERTICAL — even across the line, fading
   only above and below the block, which is where there is no type to protect. */
@media (max-width: 820px) {
  :where(.sl-body) .hero-image-bg .hero-inner::after {
    inset: -2rem -14vw;
    background: var(--hero-text-scrim-mobile, linear-gradient(to bottom,
      transparent 0%,
      color-mix(in srgb, var(--c-primary-dark) 64%, transparent) 12%,
      color-mix(in srgb, var(--c-primary-dark) 64%, transparent) 88%,
      transparent 100%));
  }
}

/* ══ HERO EFFECTS — six ways to treat a photograph, not one ═══════════════════════════════════
   Every site got the same directional wash, so every hero read the same however different the
   photo was. These are the alternatives, opted into with `theme.hero.effect` (or per page with
   `content.hero.effect`); unset keeps today's look exactly, so nothing moves on its own.

   THEY ALL PAINT ON `.hero-image-bg::after`, WHICH IS `inset: 0`. That is the structural answer to
   the bug above, not a coincidence: an effect anchored to the TEXT BOX cannot help but stop short
   of the frame, and a directional ramp that stops short leaves a hard line across the picture. The
   frame layer covers the hero by construction, so a new effect cannot reintroduce that defect.
   Visual-lint R19 enforces it either way.

   `!important` because the `ad-*` art directions already override this pseudo-element with
   `!important`; an effect chosen explicitly for one site has to outrank the lane's default. Each
   sets `--hero-text-scrim` where its own treatment already guarantees the ground under the type,
   so the two layers never double-darken. */

/* Clear at the top, deep at the floor. The photograph keeps its sky; the type sits in the dark.
   The default treatment of editorial and hospitality sites, and the one that flatters a wide
   landscape or an interior. */
:where(.sl-body) .hero-fx-bottom.hero-image-bg::after {
  background: linear-gradient(to top,
    color-mix(in srgb, var(--c-primary-dark) 88%, transparent) 0%,
    color-mix(in srgb, var(--c-primary-dark) 62%, transparent) 34%,
    color-mix(in srgb, var(--c-primary-dark) 18%, transparent) 68%,
    transparent 100%) !important;
  --hero-text-scrim: transparent;
}

/* A spotlight: the subject stays lit in the middle of the frame and the corners fall away. Reads
   as a photograph rather than a coloured panel, so it suits a portrait or a single hero object.
   Keeps the text scrim, because a radial falloff guarantees nothing under a headline. */
:where(.sl-body) .hero-fx-vignette.hero-image-bg::after {
  background: radial-gradient(78% 68% at 52% 38%,
    color-mix(in srgb, var(--c-primary-dark) 0%, transparent) 0%,
    color-mix(in srgb, var(--c-primary-dark) 30%, transparent) 40%,
    color-mix(in srgb, var(--c-primary-dark) 74%, transparent) 72%,
    color-mix(in srgb, var(--c-primary-dark) 94%, transparent) 100%) !important;
}
/* The falloff has to start well inside the frame or it is not a spotlight, it is a slightly darker
   wash. The first pass used a 125%x95% ellipse, which put the whole visible hero inside the clear
   centre and read as no effect at all — worth naming, because "subtle" and "not working" look
   identical in a screenshot and only the geometry tells them apart. */

/* Film still: clear through the middle, weighted at the top and the bottom. Pairs with
   `hero.align: 'center'`, where the type sits low and the nav sits on the upper band. */
:where(.sl-body) .hero-fx-cinema.hero-image-bg::after {
  background: linear-gradient(to bottom,
    color-mix(in srgb, var(--c-primary-dark) 74%, transparent) 0%,
    color-mix(in srgb, var(--c-primary-dark) 12%, transparent) 30%,
    color-mix(in srgb, var(--c-primary-dark) 12%, transparent) 54%,
    color-mix(in srgb, var(--c-primary-dark) 88%, transparent) 100%) !important;
  --hero-text-scrim: transparent;
}

/* A solid brand column holds the type; the photograph is left completely untouched beside it. The
   one treatment where a hard edge is the POINT — and it still spans the full height, which is the
   difference between a deliberate edge and the defect. Below the breakpoint the column would eat
   the frame, so it becomes a floor instead. */
:where(.sl-body) .hero-fx-panel.hero-image-bg::after {
  background: linear-gradient(to right,
    var(--c-primary-dark) 0%,
    var(--c-primary-dark) 44%,
    color-mix(in srgb, var(--c-primary-dark) 55%, transparent) 44.5%,
    transparent 62%) !important;
  --hero-text-scrim: transparent;
}
@media (max-width: 820px) {
  :where(.sl-body) .hero-fx-panel.hero-image-bg::after {
    background: linear-gradient(to top,
      var(--c-primary-dark) 0%,
      color-mix(in srgb, var(--c-primary-dark) 82%, transparent) 46%,
      color-mix(in srgb, var(--c-primary-dark) 30%, transparent) 78%,
      transparent 100%) !important;
  }
}

/* Duotone: the photograph's LUMINOSITY carried by the brand's colour. The strongest brand signal
   available on a hero, and the one that makes stock photography stop looking like stock.
   `background-blend-mode: color` on the layer ABOVE the photo takes the gradient's hue and the
   photo's light — a real duotone, not a tint sitting on top. */
:where(.sl-body) .hero-fx-duotone.hero-image-bg::before {
  /* Shadow colour to HIGHLIGHT colour, and the highlight has to be light. Running straight to
     `--c-accent` mapped the photo's bright half onto a saturated gold, which on a teal brand came
     out a sickly yellow-green — the accent is a button colour, not a highlight colour. Mixing it
     most of the way to the surface keeps the brand's warmth in the highlights without staining
     the picture. */
  background-image:
    linear-gradient(152deg,
      var(--c-primary-dark) 0%,
      color-mix(in srgb, var(--c-primary) 55%, var(--c-primary-dark)) 48%,
      color-mix(in srgb, var(--c-light-stock, #fff) 74%, var(--c-accent)) 100%),
    var(--hero-bg) !important;
  background-size: cover, cover !important;
  background-position: 50% var(--sl-hero-focus-y), 50% var(--sl-hero-focus-y) !important;
  background-blend-mode: color !important;
}
:where(.sl-body) .hero-fx-duotone.hero-image-bg::after {
  background: linear-gradient(to top,
    color-mix(in srgb, var(--c-primary-dark) 72%, transparent) 0%,
    color-mix(in srgb, var(--c-primary-dark) 24%, transparent) 62%,
    color-mix(in srgb, var(--c-primary-dark) 10%, transparent) 100%) !important;
  --hero-text-scrim: transparent;
}

/* Flat, even, desaturated — the clinical option. No direction, no drama: the photo recedes and the
   typography carries the page. Suits a med spa or a provider page where the picture is context
   rather than the message. */
:where(.sl-body) .hero-fx-tint.hero-image-bg::before { filter: saturate(0.6) contrast(1.04) brightness(0.99); }
:where(.sl-body) .hero-fx-tint.hero-image-bg::after {
  background: color-mix(in srgb, var(--c-primary-dark) 62%, transparent) !important;
  --hero-text-scrim: transparent;
}

/* `wash` — THE TREATMENT EVERY SITE ALREADY WEARS, named. Deliberately declares nothing: it is a
   label for the existing composite (the archetype glaze on `::after` plus the brand-dark
   left-to-right scrim above), not a seventh look. It exists so "which effect is this hero using"
   always has an answer, instead of being answered by omission — calling the current treatment
   "none" describes it wrongly; it is a wash, and it should be selectable by name like the rest.
   A near-identical second ramp was drafted here and cut: shipping two effects that read the same
   is how a library stops meaning anything. */
:where(.sl-body) .hero-fx-wash.hero-image-bg { /* intentionally empty — see above */ }

:where(.sl-body) .hero-gradient { background: linear-gradient(135deg, var(--c-primary), var(--c-primary-dark)); color: var(--c-on-dark); }
:where(.sl-body) .hero-gradient h1, :where(.sl-body) .hero-gradient p { color: var(--c-on-dark); }

:where(.sl-body) .hero-split { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 2rem; align-items: center; }
@media (max-width: 768px) { :where(.sl-body) .hero-split { grid-template-columns: minmax(0, 1fr); } }
:where(.sl-body) .hero-split .hero-image { border-radius: var(--card-radius); overflow: hidden; aspect-ratio: 4/3; background: var(--c-border); }
:where(.sl-body) .hero-split .hero-image img { width: 100%; height: 100%; object-fit: cover; }
/* Bag-in-slot fallback for photo-less split heroes: transparent product PNGs must be CONTAINED
   on a quiet brand tint, never cover-cropped like a photo. */
:where(.sl-body) .hero-split .hero-image.hero-image-bag { background: var(--c-surface-alt); display: grid; place-items: center; }
:where(.sl-body) .hero-split .hero-image.hero-image-bag img { width: auto; height: 86%; object-fit: contain; }

:where(.sl-body) .hero-video { position: relative; overflow: hidden; color: var(--c-on-dark); }
:where(.sl-body) .hero-video video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: 0; }
:where(.sl-body) .hero-video::after { content: ''; position: absolute; inset: 0; background: linear-gradient(135deg, rgba(0,0,0,0.7), rgba(0,0,0,0.4)); z-index: 1; }
:where(.sl-body) .hero-video .hero-inner { position: relative; z-index: 2; max-width: 720px; }

/* Aurora spotlight: the premium no-photo hero — deep brand bg, subtle grid, ambient blobs. */
:where(.sl-body) .hero-aurora-spotlight { background: var(--c-hero-plate); color: var(--c-on-dark); }
:where(.sl-body) .hero-aurora-spotlight h1, :where(.sl-body) .hero-aurora-spotlight p { color: var(--c-on-dark); }
:where(.sl-body) .hero-aurora-spotlight::before { content: ''; position: absolute; inset: 0; background-image: linear-gradient(rgba(255,255,255,0.05) 1px, transparent 1px), linear-gradient(90deg, rgba(255,255,255,0.05) 1px, transparent 1px); background-size: 42px 42px; z-index: 0; }
:where(.sl-body) .hero-aurora-spotlight::after { content: ''; position: absolute; width: 65%; height: 130%; top: -30%; left: 8%; background: radial-gradient(circle, color-mix(in srgb, var(--c-primary) 70%, transparent), transparent 60%); filter: blur(64px); z-index: 0; pointer-events: none; }
:where(.sl-body) .hero-aurora-spotlight .hero-inner { position: relative; z-index: 2; max-width: 760px; }
:where(.sl-body) .hero-aurora-spotlight .btn-secondary { color: var(--c-on-dark); border-color: var(--c-on-dark); }
:where(.sl-body) .hero-aurora-spotlight .hero-rating { background: rgba(255,255,255,0.14); border-color: rgba(255,255,255,0.32); color: var(--c-on-dark); }

/* Minimal left: text-only, generous whitespace, left-aligned — quiet and luxe. */
:where(.sl-body) .hero-minimal-left { /* text only — no picture to show whole; see .sl-hero-nopic */ --sl-hero-want: var(--sl-hero-nopic-want); }
:where(.sl-body) .hero-minimal-left .hero-inner { max-width: 640px; }
/* .hero is a flex row, so .container shrink-wraps and auto-centers — that is HOW the classic
   heroes center their block. A LEFT hero must instead fill the container so its text aligns
   with every other section's left edge (measured drift: hero at x=260, sections at x=90). */
:where(.sl-body) .hero-minimal-left .container { width: 100%; }

/* Split diagonal: the split layout with a diagonal clip on the media side. */
:where(.sl-body) .hero-split-diagonal .hero-image { clip-path: polygon(14% 0, 100% 0, 100% 100%, 0 100%); }

:where(.sl-body) .hero .eyebrow { font-size: 0.875rem; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; margin-bottom: 0.75rem; color: var(--c-accent); }
:where(.sl-body) .hero .subhead { font-size: 1.125rem; margin-bottom: 1.5rem; max-width: 60ch; }
:where(.sl-body) .hero .cta-row { display: flex; gap: 0.75rem; flex-wrap: wrap; }

/* Authenticity badge */
:where(.sl-body) .auth-badge {
  display: inline-flex; gap: 0.75rem; align-items: center;
  padding: 0.75rem 1rem; background: var(--c-surface); border: 1px solid var(--c-border);
  border-radius: var(--card-radius); margin: 1rem 0;
  box-shadow: var(--card-shadow);
}
:where(.sl-body) .auth-badge .auth-icon {
  flex: 0 0 36px; height: 36px; border-radius: 50%; background: var(--c-accent);
  color: var(--c-primary-dark); display: grid; place-items: center; font-weight: 700;
}
:where(.sl-body) .auth-badge .auth-text { font-size: 0.875rem; }
:where(.sl-body) .auth-badge .auth-text strong { display: block; color: var(--c-text); }
:where(.sl-body) .auth-badge .auth-text .auth-meta { color: var(--c-text-muted); font-size: 0.8125rem; }
:where(.sl-body) .auth-badge a { color: var(--c-primary); }

/* Generic content sections */
:where(.sl-body) .cta-row { display: flex; gap: 0.75rem; flex-wrap: wrap; align-items: center; }
/* CENTRED is the default, and stays the default.
   A previous pass here flipped every section header to left on the strength of a survey showing
   sector leaders left-align. That was the wrong conclusion from a right observation: those sites
   left-align the header AND the content under it. Flipping only the header left a centred card
   grid sitting under a left heading — which is the incongruent case this file's own R8 already
   calls out at :3286 as reading like a bug, and it is what Ian saw immediately on the live page.
   Congruency is the rule, not an alignment. The header goes left only where the content beneath
   it is left-aligned too: see the comp-treatment and photo-band header rules further down, which
   move both together the way body.hdr-left does. */
:where(.sl-body) .section-header { text-align: center; max-width: var(--content-measure); margin: 0 auto 1.85rem; }
:where(.sl-body) .section-header .eyebrow { color: var(--c-accent-ink, var(--c-accent)); font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; font-size: 0.875rem; }
:where(.sl-body) .list-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); gap: 1.5rem; }

/* FAQ — accordion (details/summary) */
:where(.sl-body) .faq-list { max-width: var(--content-max); margin-left: auto; margin-right: auto; }
:where(.sl-body) .faq-item { border-bottom: 1px solid var(--c-border); }
:where(.sl-body) .faq-item h3 { font-family: var(--font-body); font-size: 1.0625rem; margin-bottom: 0.5rem; color: var(--c-text); }
:where(.sl-body) .faq-item > summary {
  list-style: none; cursor: pointer; display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; padding: 1.15rem 0; font-weight: 600; font-size: 1.0625rem; color: var(--c-text);
}
:where(.sl-body) .faq-item > summary::-webkit-details-marker { display: none; }
:where(.sl-body) .faq-item .faq-chevron { flex: 0 0 auto; color: var(--c-primary); transition: transform .2s ease; }
:where(.sl-body) .faq-item[open] .faq-chevron { transform: rotate(180deg); }
:where(.sl-body) .faq-item > p { color: var(--c-text-muted); margin: 0; padding: 0 0 1.15rem; max-width: 70ch; }

/* Compact trust row (icon + short label, single row under hero) */
:where(.sl-body) .trust-row { display: flex; flex-wrap: wrap; justify-content: center; align-items: flex-start; gap: 1.5rem 0; }
:where(.sl-body) .trust-row-item { display: flex; flex-direction: column; align-items: center; gap: 0.65rem; text-align: center; flex: 0 1 200px; padding: 0 1.5rem; position: relative; }
/* Thin divider before each item except the first, for visual separation between trust points. */
:where(.sl-body) .trust-row-item + .trust-row-item::before { content: ''; position: absolute; left: 0; top: 8px; bottom: 8px; width: 1px; background: var(--c-border); }
:where(.sl-body) .trust-row-item .trust-ic { color: var(--c-accent); line-height: 0; display: grid; place-items: center; width: 58px; height: 58px; border-radius: 50%; background: var(--c-surface-alt, rgba(0,0,0,0.04)); }
:where(.sl-body) .trust-row-item .trust-ic svg { width: 30px; height: 30px; }
:where(.sl-body) .trust-row-item span { font-weight: 600; font-size: 0.95rem; color: var(--c-text); line-height: 1.3; }
@media (max-width: 720px) { :where(.sl-body) .trust-row-item + .trust-row-item::before { display: none; } }
/* Below 640 the strip was a FIVE-STOREY TOWER: each item is `flex: 0 1 200px` plus 1.5rem of side
   padding = 248px, and a 390px phone has ~350px of inner width, so exactly one item fits per row.
   Measured on a real 390x844 viewport: 699px tall — 83% of the screen — for what is supposed to be
   a glanceable reassurance strip you scroll past. The old rule only hid the divider and left the
   tower.
   Rows instead of a tower: icon left, label right, hairline between. Same five facts, ~280px. */
@media (max-width: 640px) {
  :where(.sl-body) .trust-row { gap: 0; }
  :where(.sl-body) .trust-row-item {
    flex: 1 1 100%;
    flex-direction: row;
    align-items: center;
    justify-content: flex-start;
    text-align: left;
    gap: 0.8rem;
    padding: 0.72rem 0;
  }
  :where(.sl-body) .trust-row-item + .trust-row-item { border-top: 1px solid var(--c-border); }
  :where(.sl-body) .trust-row-item .trust-ic { width: 38px; height: 38px; flex: 0 0 38px; }
  :where(.sl-body) .trust-row-item .trust-ic svg { width: 19px; height: 19px; }
}
/* Trust strip sits tight under the hero, not a full padded section */
:where(.sl-body) .section-trust_bar, :where(.sl-body) .section-trust_signals { padding-top: 2.5rem; padding-bottom: 2.5rem; }

/* Trust strip */
:where(.sl-body) .trust-strip { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 1rem; }
:where(.sl-body) .trust-strip .item { text-align: center; padding: 1rem; background: var(--c-surface); border-radius: var(--card-radius); border: 1px solid var(--c-border); font-weight: 500; font-size: 0.875rem; }

/* Final CTA */
/* The CTA slab is the one band where an ACCENT eyebrow can never be safe: --c-cta-bg is a
   gradient that runs INTO the accent on many brands, so accent-on-accent lands near 1:1 at one
   end of the band. Its eyebrow takes the slab's own text colour instead (the h2/p already do). */
:where(.sl-body) .final-cta { background: var(--c-cta-bg, var(--c-hero-plate)); color: var(--c-cta-text, var(--c-on-dark)); text-align: center; --eyebrow-ink: var(--c-cta-text, var(--c-on-dark)); }
/* When the BAND carries a photograph, the CTA slab must get out of its way — a solid navy card
   painted over a photo band hides the photo and leaves a picture frame round the edges. The slab
   is drawn from --c-cta-bg (including the renderer's inline fallback), so clearing the var is
   what actually removes it; the band's own scrim keeps the type legible. */
:where(.sl-body) .sec-photo { --c-cta-bg: transparent; }
:where(.sl-body) .sec-photo .final-cta { box-shadow: none; }
:where(.sl-body) .final-cta h2, :where(.sl-body) .final-cta p { color: var(--c-on-dark); }
:where(.sl-body) .final-cta .container { max-width: 720px; }
/* Accent glow so the CTA band reads premium even when primary≈primary_dark (flat gradient). */
:where(.sl-body) .final-cta::after { content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none; background: radial-gradient(75% 90% at 92% 8%, var(--c-accent), transparent 60%); opacity: 0.26; }
:where(.sl-body) .final-cta > * { position: relative; z-index: 1; }

/* Related entities */
:where(.sl-body) .related-groups .group { margin-bottom: 1.5rem; }
:where(.sl-body) .related-groups .group-label { font-size: 0.75rem; font-weight: 600; text-transform: uppercase; letter-spacing: 0.08em; color: var(--c-text-muted); margin-bottom: 0.5rem; }
:where(.sl-body) .related-groups .chips { display: flex; gap: 0.5rem; flex-wrap: wrap; }
:where(.sl-body) .related-groups .chip { padding: 0.5rem 0.875rem; border: 1px solid var(--c-border); border-radius: 999px; background: var(--c-surface); font-size: 0.875rem; }

/* ---- Theme treatments (driven by brand.theme_json via body classes) ---- */
/* cta-accent: primary CTAs use the brand accent color (e.g. Pure IV's orange "Book" button)
   instead of the primary, matching sites whose calls-to-action pop against the primary. */
/* The ink is DERIVED, not assumed: --c-accent-on is whichever of the brand's own light and dark
   stands far enough from its accent, computed in brand.ts. On most palettes that resolves to
   primary-dark and this line renders unchanged; on one where it does not, this is the difference
   between a readable button and an invisible one. */
:where(.sl-body) .cta-accent .btn-primary { background: var(--c-accent); color: var(--c-accent-on, var(--c-primary-dark)); border-color: var(--c-accent); }
:where(.sl-body) .cta-accent .btn-primary:hover { background: var(--c-accent); color: var(--c-primary-dark); filter: brightness(0.93); text-decoration: none; }
:where(.sl-body) .cta-accent .btn-secondary { color: var(--c-primary); border-color: var(--c-primary); }

/* sections-alternate: white / tinted bands instead of hairline dividers — the rhythm most
   real marketing sites use. Tint comes from the extracted surface_alt color. */
:where(.sl-body) .sections-alternate .section + .section { border-top: none; }
/* Even sections get a clearly present, brand-tinted band (surface_alt nudged toward
   the brand primary) so the vertical rhythm reads as a designed flow, not almost-white.
   Reserved brands (muted surface_alt + low-key primary) stay subtle; bold brands pop. */
:where(.sl-body) .sections-alternate main > section.section:nth-of-type(even):not(.section-tier_comparison):not(.final-cta):not(.section-hub-cta):not(.sec-room):not(.sec-photo):not(.comp-trust-band):not(.block-route-section) {
  background:
    linear-gradient(180deg,
      color-mix(in srgb, var(--c-primary) 7%, var(--c-surface-alt)) 0%,
      color-mix(in srgb, var(--c-primary) 4%, var(--c-surface-alt)) 100%);
}
/* Variety: roughly every 4th section gets a slightly richer diagonal brand wash so the
   page isn't the same two-tone all the way down. Text stays dark on these light bands. */
:where(.sl-body) .sections-alternate main > section.section:nth-of-type(4n):not(.final-cta):not(.section-hub-cta):not(.sec-room):not(.sec-photo):not(.comp-trust-band):not(.block-route-section) {
  background:
    linear-gradient(135deg,
      color-mix(in srgb, var(--c-primary) 12%, var(--c-surface)) 0%,
      color-mix(in srgb, var(--c-accent) 7%, var(--c-surface)) 100%);
}

/* ---- Design-layer components (icons, eyebrows, image+text, carousel, hero pill) ---- */
:where(.sl-body) .eyebrow { color: var(--c-accent-ink, var(--c-accent)); font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; font-size: 0.8rem; margin-bottom: 0.5rem; }

/* Feature/step card icons (accent-colored, keyword-matched) */
:where(.sl-body) .feature-ic { color: var(--c-accent); line-height: 0; margin-bottom: 0.8rem; }
:where(.sl-body) .feature-ic svg { width: 40px; height: 40px; stroke-width: 1.6; }
/* Category/feature cards: icon in a tinted circular badge (more presence than a bare line icon) */
:where(.sl-body) .auto-card .feature-ic { display: inline-grid; place-items: center; width: 58px; height: 58px; margin: 0 0 1.1rem; border-radius: 16px; background: color-mix(in srgb, var(--c-accent) 15%, var(--c-surface)); color: var(--c-accent); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--c-accent) 24%, transparent); }
:where(.sl-body) .auto-card .feature-ic svg { width: 28px; height: 28px; }
:where(.sl-body) .feature-card { text-align: left; }
/* Generic image-item cards (services/products grid with a photo per item). */
/* --sl-basis is the LAYOUT INVARIANT: renderImageItemGrid computes it from the item count so the
   row breaks evenly. Hard-coding 250px here overrode it and let the row pack by whatever fit —
   six vials came out 4+2 with an orphan row, two services came out as narrow chips in a wide band. */
/* --sl-basis is the DESIRED card width and --sl-cols the column count chooseCols picked. Basis
   alone wraps early whenever the real container is narrower than the width the basis was computed
   against (a wide product band inside a 1200px .container stacked two cards that should sit side
   by side). Capping the basis at an exact 1/N share of the ACTUAL line means the row holds N
   across at any width and simply gets narrower — never a surprise wrap. */
:where(.sl-body) .cards-center > .img-item-card {
  flex: 0 1 min(var(--sl-basis, 250px), calc((100% - (var(--sl-cols, 1) - 1) * 1.5rem) / var(--sl-cols, 1)));
}
@media (max-width: 768px) { :where(.sl-body) .cards-center > .img-item-card { flex-basis: 100%; } }
:where(.sl-body) .img-item-card { display: flex; flex-direction: column; text-align: center; text-decoration: none; transition: box-shadow .15s, transform .15s; }
:where(.sl-body) a.img-item-card:hover { box-shadow: var(--card-hover-shadow, 0 12px 30px rgba(0,0,0,0.12)); transform: translateY(-2px); }
:where(.sl-body) .img-item-media { display: flex; align-items: center; justify-content: center; height: 150px; margin-bottom: 0.75rem; }
:where(.sl-body) .img-item-media img { max-height: 100%; max-width: 80%; object-fit: contain; filter: drop-shadow(0 10px 22px rgba(0,0,0,0.14)); }
/* Vial art is TALL (roughly 2:3) where the generic item image is square, so the shared 150px
   media box shrinks a vial to a sliver of its card. Give the product-art grids a taller box and
   let the bottle fill it — same `contain` rule, just more room to be contained in. */
/* Sizes for these two live with the other product-band rules further down; keeping a second set
   here just meant two places to change and a silent override fight. */
/* .iic-body — layout-invisible by default, exactly like .pkg-body on the bag cards, so an
   ordinary image grid renders unchanged. The hover panel below promotes it. */
:where(.sl-body) .iic-body { display: contents; }
/* ── PRODUCT-GRID HOVER REVEAL ───────────────────────────────────────────────────────────────
   The same gesture the drip menu uses (pricing.bag-hover-reveal): the card face is the object and
   its name; hovering slides a navy panel over it carrying the description. Applied to the vitamin
   grid so a shot behaves like a drip — the two menus are one shopping decision, and having only
   one of them respond to the cursor reads as a bug.
   @media(hover:hover) gates the whole thing: on touch there is no hover, so .iic-body stays
   display:contents and the description simply sits in the card where a thumb can read it. */
/* A CARD WITH NOTHING TO REVEAL DOES NOT REVEAL. Every selector below is qualified with
   `:has(.iic-body)`, because the panel and the disappearing name are two halves of one gesture and
   only the panel is conditional in the markup. On Top Tier's Our Services band the three cards
   carry a picture and a name and no description at all, so hovering any of them slid a panel that
   did not exist over a name that then vanished: the card went blank under the cursor. Reported as
   "the word Memberships disappears when I come back to the page" — coming back just leaves the
   pointer resting on the card you left from, which is when you notice. */
@media (hover: hover) {
  :where(.sl-body) .cards-center.is-product-band > .img-item-card:has(.iic-body) { position: relative; overflow: hidden; }
  :where(.sl-body) .cards-center.is-product-band > .img-item-card:has(.iic-body) h3 { transition: opacity .25s ease; }
  :where(.sl-body) .cards-center.is-product-band > .img-item-card .iic-body {
    display: flex !important; flex-direction: column; align-items: center; justify-content: center;
    position: absolute; inset: 0; padding: 1.6rem 1.5rem; z-index: 3;
    background: var(--c-primary); color: var(--c-on-primary);
    transform: translateX(-100%); transition: transform .45s cubic-bezier(.22,.61,.36,1);
  }
  :where(.sl-body) .cards-center.is-product-band > .img-item-card .iic-body p { color: rgba(255,255,255,.92) !important; margin: 0; text-align: center; }
  :where(.sl-body) .cards-center.is-product-band > .img-item-card:has(.iic-body):hover .iic-body, :where(.sl-body) .cards-center.is-product-band > .img-item-card:has(.iic-body):focus-within .iic-body { transform: translateX(0); }
  :where(.sl-body) .cards-center.is-product-band > .img-item-card:has(.iic-body):hover h3, :where(.sl-body) .cards-center.is-product-band > .img-item-card:has(.iic-body):focus-within h3 { opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  :where(.sl-body) .cards-center.is-product-band > .img-item-card .iic-body { transition: none !important; }
}
:where(.sl-body) .img-item-card h3 { margin: 0 0 0.25rem; font-size: 1.02rem; }
:where(.sl-body) .img-item-card p { margin: 0; font-size: 0.92rem; }

:where(.sl-body) .step-card { text-align: center; }
/* Steps grow to fill their row so a 3-step process spans the same width as the
   other content sections (was pinned to 250px, which made 3 steps look cramped). */
:where(.sl-body) .steps-row > .card { flex: 0 1 var(--sl-basis, 300px); }
@media (max-width: 768px) { :where(.sl-body) .steps-row > .card { flex-basis: 100%; max-width: none; } }
:where(.sl-body) .step-card .feature-ic { display: flex; justify-content: center; }
:where(.sl-body) .step-card .step-label { margin-top: 0.15rem; }
:where(.sl-body) .step-badge { width: 52px; height: 52px; margin: 0 auto 0.85rem; border-radius: 50%; background: var(--c-accent); color: var(--c-primary-dark); display: grid; place-items: center; font-family: var(--font-heading); font-weight: 700; font-size: 1.4rem; position: relative; z-index: 2; }
/* .step-ic — the ICON form of a step marker: a ringed glyph with the step number tucked into the
   corner. Replaces .step-badge whenever the step names an icon, so a step band says what each
   step IS instead of counting to three. */
/* ── ICONED STEP CARD ────────────────────────────────────────────────────────────────────────
   Built to the client's marked-up reference: a cream medallion inside a DOTTED ring, centred at
   the top of the card; a dark numbered badge on the card's left edge at the medallion's foot;
   title and body LEFT-aligned under it. The default step card centres its text, which is why the
   first attempt read as a different component even once the icons were right. */
/* The card's top padding is published as a variable because .step-n is positioned ABSOLUTELY from
   the card's top edge and has to know it. Any variant that changes this padding must change the
   variable, not the padding alone — see the note on .step-n. */
:where(.sl-body) .step-card.has-step-ic { position: relative; text-align: left; --step-pad-top: 2rem; --step-ic-size: 112px; padding-top: var(--step-pad-top); }
:where(.sl-body) .step-ic {
  /* the size lives on .step-card.has-step-ic so the numeral can position against it */
  width: var(--step-ic-size, 112px); height: var(--step-ic-size, 112px);
  margin: 0 auto 1.35rem; border-radius: 50%;
  display: grid; place-items: center; position: relative; z-index: 2;
  color: var(--c-primary);
  /* The illustration palette. Named separately from --c-* so a drawing can be recoloured for a
     band (or a brand) without touching the tokens the rest of the page reads. */
  --ic-accent: var(--c-accent);
  --ic-navy: var(--c-primary);
  --ic-gold: var(--c-accent);
  --ic-cream: var(--c-light-stock);
  --ic-cream-2: color-mix(in srgb, var(--c-surface-alt) 70%, var(--c-surface));
  background: color-mix(in srgb, var(--c-accent) 15%, var(--c-surface));
}
/* The dotted ring — a real dotted border on a pseudo-element, offset from the disc. */
:where(.sl-body) .step-ic::before {
  content: ''; position: absolute; inset: -10px; border-radius: 50%;
  border: 2px dotted color-mix(in srgb, var(--c-accent) 62%, transparent);
}
/* An illustration has to FILL its medallion the way the reference does — at 52px in a 112px disc
   it reads as a small mark floating in a large circle rather than as the picture on the card. */
:where(.sl-body) .step-ic svg { width: 74px; height: 74px; }
/* A client-supplied step mark sits in the medallion at the same optical size as a drawn one. */
:where(.sl-body) .step-ic-img { width: 74px; height: 74px; object-fit: contain; display: block; }
/* The numeral: a dark disc on the card's left edge, level with the medallion's foot.
   THE OFFSET IS DERIVED, NOT TYPED. This read `calc(2rem + 112px - 15px)` — the card's top padding
   and the medallion's diameter, both written out as literals. The photographic variant of this band
   overrides the card padding to 0.5rem and knew nothing about this rule, so the disc stayed where a
   2rem card would have put it and landed squarely on the h3: Ian saw "B(1)ok Your Experience".
   Both numbers now come from the variables that own them, so a variant that changes the padding or
   the medallion size moves the numeral with it. */
:where(.sl-body) .step-n {
  position: absolute; left: 1.5rem;
  top: calc(var(--step-pad-top, 2rem) + var(--step-ic-size, 112px) - 15px);
  width: 30px; height: 30px; border-radius: 50%;
  background: var(--c-primary); color: var(--c-on-primary);
  font-family: var(--font-heading); font-weight: 700; font-size: 0.92rem;
  line-height: 30px; text-align: center; z-index: 3;
}
:where(.sl-body) .step-card.has-step-ic h3 { margin-top: 0.9rem; }
/* ── THE ROUTE ───────────────────────────────────────────────────────────────────────────────
   A car tracing a dotted path to a pin, under the cards: the service coming to you, which is the
   detail that made the reference read as a journey rather than three boxes. */
:where(.sl-body) .steps-route { max-width: 620px; margin: 1.6rem auto 0; }
:where(.sl-body) .steps-route svg { width: 100%; height: auto; display: block; overflow: visible; }
:where(.sl-body) .sr-path {
  fill: none; stroke: color-mix(in srgb, var(--c-accent) 70%, transparent);
  stroke-width: 2; stroke-linecap: round; stroke-dasharray: 1 7;
}
/* The car's position is CSS's job now, not a hardcoded transform in the markup, so the same
   coordinates can either park it at the start of the road or drive it along one. */
:where(.sl-body) .sr-car { fill: var(--c-accent); transform: translate(4px, 36px); }
:where(.sl-body) .sr-pin { fill: var(--c-accent); }
:where(.sl-body) .sr-pin-dot { fill: var(--c-primary); }

/* ── route above the cards, and the car actually drives it ────────────────────────────────────
   Client asked for the motif to introduce the steps rather than trail them, and for the car to
   move. `offset-path` takes the SAME cubic as .sr-path, so the car is on the road by construction
   instead of by a second set of hand-tuned keyframes that would drift the moment the path changes.
   offset-rotate is pinned to 0deg: the road swings ~34px vertically inside a 60px box, and letting
   a 22px car bank into those curves reads as a vehicle tumbling, not driving. */
:where(.sl-body) .steps-route--top { margin: 1.1rem auto 0.35rem; }
@supports (offset-path: path('M0 0')) {
  :where(.sl-body) .steps-route--top .sr-car {
    offset-path: path('M18 44C110 44 120 12 210 12S320 46 410 46 540 16 600 16');
    offset-rotate: 0deg;
    /* the glyph is drawn from its own top-left, so pull it onto the line it is riding */
    offset-anchor: 10px 11px;
    transform: none;
  }
  @media (prefers-reduced-motion: no-preference) {
    :where(.sl-body) .steps-route--top .sr-car { animation: srDrive 9s cubic-bezier(.55,0,.45,1) infinite; }
  }
  /* Reduce-motion parks it at the kerb rather than hiding it — the motif still reads. */
  @media (prefers-reduced-motion: reduce) {
    :where(.sl-body) .steps-route--top .sr-car { offset-distance: 0%; }
  }
}
/* Holds at both ends so it reads as arriving somewhere, not looping frantically. Stops at 92%,
   not 100%: the path ends exactly where the pin is planted, so a full run parked the car on top
   of its own destination. 92% pulls up beside it. */
@keyframes srDrive {
  0%, 6%    { offset-distance: 0%; }
  72%, 100% { offset-distance: 92%; }
}
/* THE ROAD COMES BACK ON A PHONE - but only the version that can survive there.
   This was one bare line hiding the route on anything under 900px, and it was right for the
   original placement: the road ran UNDERNEATH the three step cards, tying them together left to
   right, and three cards stacked in a column have no left-to-right to tie. The client then asked
   for the car to drive ABOVE the cards instead (`--top`), which makes it a standalone motif -
   "we come to you" drawn once, over whatever follows - and that reads the same in a column as in
   a row. Hidden, it meant the one thing she specifically asked for was missing on the phones most
   of her customers will use. So the old placement stays hidden and the new one is shown, narrower
   so the arc keeps its shape at 390px rather than stretching into a flat line. */
@media (max-width: 900px) {
  :where(.sl-body) .steps-route { display: none; }
  :where(.sl-body) .steps-route--top { display: block; margin: 0.5rem auto 1.1rem; }
  /* The width is set through --steps-rail rather than max-width, because the rail rule that owns
     this route on a photo band is far more specific than anything a plain class can say and would
     simply win - leaving the arc stretched flat across the full column, which is the shape this
     block exists to avoid. Setting the variable it already reads gets there without a specificity
     war or an !important. */
  :where(.sl-body) main > section.section:has(.steps-route--top) { --steps-rail: min(320px, 82%); }
}
/* (.step-ic-n is gone — the numeral is .step-n, a CARD-level element, because in the reference it
   sits on the card's edge rather than hanging off the medallion.) */
/* ── ICONED STEP RAIL IN A NAVY ROOM = WHITE CARDS ─────────────────────────────────────────────
   The client's reference for this band is three WHITE cards on navy, each with a large ringed
   icon. refine-dark-luxe otherwise turns cards in a room into dark plates ruled in gold, which is
   right for a card whose content is type but wrong here: it erases the object the icon sits in
   and the band reads as three labels floating on navy. Needs (0,7,3) to beat the dark-plate rule.
   Scoped to rails that actually carry icons, so a plain step rail keeps the house treatment. */
/* ══ DESIGN LANE: dark-luxe ══════════════════════════════════════════════════════════════
   Retro-described 2026-08-27. This lane was written before lanes had descriptions and
   therefore could never be ASSIGNED to a client by anything but memory — which is exactly
   how one client was given a lane another client already wore. The tag below is what
   tools/lane-pick.mjs reads; the lane itself is unchanged.
   @lane dark-luxe | full-bleed dark rooms with a warm metal accent | suits: dark moody nightlife bold dramatic vip lounge after-hours
   ══════════════════════════════════════════════════════════════════════════════════════ */
:where(.sl-body).refine-dark-luxe main > section.section.sec-room .steps-row:has(.step-ic) > .card.step-card {
  background: var(--c-surface);
  border: 1px solid color-mix(in srgb, var(--c-accent) 30%, transparent);
  box-shadow: 0 24px 48px -30px rgba(8, 14, 26, 0.55);
  padding-top: 2.1rem; padding-bottom: 1.9rem;
  --c-text: var(--c-primary);
  --c-text-muted: var(--c-muted-on-surface, color-mix(in srgb, var(--c-primary) 72%, var(--c-surface)));
  color: var(--c-primary);
}
:where(.sl-body).refine-dark-luxe main > section.section.sec-room .steps-row:has(.step-ic) > .card.step-card h3 { color: var(--c-primary); }
/* The medallion's outer ring is drawn with the CARD colour, so on a white card it must be white
   rather than the band's stock, or a beige halo appears around every icon. */

/* The medallion sits on a WHITE card in a room, so its disc keeps the card's ground. */
:where(.sl-body) .sec-room .steps-row:has(.step-ic) .step-ic { background: color-mix(in srgb, var(--c-accent) 15%, var(--c-surface)); }
/* The connector rail runs between the cards, so on a navy room it has to read against NAVY. */
:where(.sl-body) .sec-room .steps-connected::before { background: color-mix(in srgb, var(--c-accent) 60%, transparent); opacity: 1; }

/* comp-ledger hides .step-badge because a big gold disc floating over a 30/70 ruled row is noise.
   An icon is not noise — it is the thing the row is about — so the ledger keeps it, inline and
   small, sitting to the left of the label instead of centred above it. */
:where(.sl-body) .comp-ledger .step-ic {
  width: 34px; height: 34px; margin: 0 0.7rem 0 0; float: left; border: 0; background: none;
}
:where(.sl-body) .comp-ledger .step-ic svg { width: 26px; height: 26px; }

/* An intro line can carry the same mark inline ("We Come to YOU" beside the van). */
:where(.sl-body) .section-intro-iconed { display: inline-flex; align-items: center; gap: 0.55rem; }
:where(.sl-body) .section-intro-ic { display: inline-flex; color: var(--c-accent); }
/* Connecting progress line behind the step badges (steps with 3+ items). */
:where(.sl-body) .steps-connected { position: relative; }
:where(.sl-body) .steps-connected .step-card { position: relative; }
:where(.sl-body) .steps-connected::before { content: ''; position: absolute; top: calc(1.5rem + 24px); left: 18%; right: 18%; height: 3px; border-radius: 2px; background: var(--c-accent); opacity: 0.4; z-index: 1; }
/* The rail's height is pinned to the 52px badge. A 96px icon medallion centres 22px lower, so the
   line crossed the circles off-centre and read as a stray rule rather than a connector. */
/* An iconed rail draws the dotted ROUTE under the cards instead. Two connectors — a straight rule
   through the medallions and a car path below them — is one connector too many, and the straight
   one crosses the icons it is meant to link. */
:where(.sl-body) .steps-connected:has(.step-ic)::before { display: none; }
/* The rail connects steps laid out ACROSS. Every composition that restacks them into vertical
   rows leaves it as a stray horizontal line struck through the first row's copy. This was fixed
   four times under `body.refine-luxe-noir` and once under `body.grid-rows` — all five are the same
   bug, and the lane was never what made the rail wrong. Suppress it by the composition, not the lane. */
/* THE CONNECTOR BELONGS TO THE DEFAULT LAYOUT, SO ANY TREATMENT ENDS IT.
   `.steps-connected::before` is a 3px rule pinned to `top: calc(1.5rem + 24px)` — the centre of
   the numbered discs in the default three-across rail. It only means anything while those three
   discs are sitting in a row at that exact height.
   It was hidden for the four original text treatments and for nothing added since, so every
   treatment built after them leaked it: it ran straight THROUGH the card titles on cards-numeral
   and wall, floated across the gutters on cards-accent, hung off the left edge into empty space on
   split, and left a stray gold segment beside the copy on panel. Ian, looking at the sheet: "so
   many random lines that don't make sense as far as design is concerned."
   The attribute selector is deliberate — naming treatments one by one is what produced this, since
   every future one would have to remember. A comp-* class means the layout changed; the leading
   space is safe because the wrapper's class attribute always begins `section `. */
:where(.sl-body) main > section.section[class*=" comp-"] .steps-connected::before { display: none; }
:where(.sl-body) .comp-ledger .steps-connected::before, :where(.sl-body) .comp-numbered .steps-connected::before, :where(.sl-body) .comp-quiet-prose .steps-connected::before, :where(.sl-body) .comp-statement .steps-connected::before { display: none; }

/* "Why choose us" reasons as icon-left rows. Deliberately different from the icon-top
   step/feature cards so two adjacent multi-item sections never look like clones. */
/* Full-width stacked rows (title-left / body-right), one per reason. Spans the shared
   --content-max like every other section (no narrow column), each row uses the same two
   internal columns so titles and bodies align down the page, and being stacked full-width
   rows it reads clearly different from the side-by-side step cards above. No item count can
   orphan or misalign because it is a single column of equal-width rows. */
:where(.sl-body) .why-rows { display: flex; flex-direction: column; gap: 0.9rem; margin: 0 auto; }
:where(.sl-body) .why-row { display: grid; grid-template-columns: minmax(220px, 0.9fr) 1.5fr; gap: 1rem 2.5rem; align-items: center; padding: 1.5rem 1.8rem; background: var(--c-surface); border: 1px solid var(--c-border); border-radius: 16px; box-shadow: var(--card-shadow); }
:where(.sl-body) .why-row-head { display: flex; align-items: center; gap: 0.95rem; }
:where(.sl-body) .why-row-head h3 { margin: 0; font-size: 1.18rem; letter-spacing: -0.01em; }
:where(.sl-body) .why-row-ic { flex: 0 0 auto; width: 48px; height: 48px; display: grid; place-items: center; border-radius: 13px; background: color-mix(in srgb, var(--c-primary) 12%, var(--c-surface)); color: var(--c-primary); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--c-primary) 20%, transparent); }
:where(.sl-body) .why-row-ic svg { width: 25px; height: 25px; }
:where(.sl-body) img.why-row-ic { object-fit: contain; padding: 8px; }
:where(.sl-body) .why-row-body { margin: 0; color: var(--c-text-muted); line-height: 1.6; }
@media (max-width: 720px) { :where(.sl-body) .why-row { grid-template-columns: minmax(0, 1fr); gap: 0.55rem; padding: 1.25rem 1.3rem; align-items: start; } }

/* Treatment categories: compact browsable icon tiles (icon-top + label), centered flex-wrap
   capped by gridMaxWidth per the layout invariant. Each tile links to a category/treatments page. */
:where(.sl-body) .cat-grid { display: flex; flex-wrap: wrap; justify-content: center; gap: 1.25rem; margin: 0 auto; max-width: var(--content-max); }
:where(.sl-body) .cat-card { flex: 0 1 var(--sl-basis, 240px); display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 0.7rem; min-height: 118px; padding: 1.3rem 1rem; text-align: center; text-decoration: none; color: var(--c-text); background: var(--c-surface); border: 1px solid var(--c-border); border-radius: 16px; box-shadow: var(--card-shadow); transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease; }
:where(.sl-body) .cat-card:hover { transform: translateY(-3px); box-shadow: 0 22px 44px -20px rgba(16,24,32,0.26); border-color: color-mix(in srgb, var(--c-primary) 45%, transparent); }
:where(.sl-body) .cat-ic { display: grid; place-items: center; width: 54px; height: 54px; border-radius: 50%; background: color-mix(in srgb, var(--c-primary) 12%, var(--c-surface)); color: var(--c-primary); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--c-primary) 20%, transparent); }
:where(.sl-body) .cat-ic svg { width: 27px; height: 27px; }
:where(.sl-body) img.cat-ic { object-fit: contain; padding: 12px; }
:where(.sl-body) .cat-card > span { font-weight: 600; font-size: 0.98rem; line-height: 1.25; }
:where(.sl-body) .cat-card-all { border-style: dashed; color: var(--c-primary); }
:where(.sl-body) .cat-card-all .cat-all-arrow { font-size: 1.15rem; line-height: 1; }
@media (max-width: 640px) { :where(.sl-body) .cat-card { flex-basis: 44%; min-height: 104px; padding: 1.1rem 0.75rem; } }

/* Event / group wellness: reuses .cards-center + .feature-card cards; this is just the CTA row. */
:where(.sl-body) .event-cta { display: flex; justify-content: center; margin-top: 1.75rem; }
@media (max-width: 768px) { :where(.sl-body) .steps-connected::before { display: none; } }

/* Accent CTA (e.g. Pure IV's orange "Check Your Area") */
:where(.sl-body) .btn-accent { background: var(--c-accent); color: var(--c-primary-dark); border-color: var(--c-accent); }
:where(.sl-body) .btn-accent:hover { filter: brightness(0.93); color: var(--c-primary-dark); text-decoration: none; }

/* Hero rating pill */
:where(.sl-body) .hero-rating { display: inline-flex; align-items: center; gap: 0.55rem; background: rgba(255,255,255,0.14); border: 1px solid rgba(255,255,255,0.32); -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px); padding: 0.5rem 1.05rem; border-radius: 999px; margin-bottom: 1.25rem; font-size: 0.95rem; font-weight: 600; }
:where(.sl-body) .hero-rating .stars { color: var(--c-accent); letter-spacing: 1px; }
/* Light variant for split/gradient heroes where text sits on a light background */
:where(.sl-body) .hero-rating-light { background: var(--c-surface-alt); border-color: var(--c-border); color: var(--c-text); -webkit-backdrop-filter: none; backdrop-filter: none; }

/* Image + text rows */
:where(.sl-body) .img-text { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: clamp(2rem, 5vw, 4rem); align-items: center; }
:where(.sl-body) .img-text.reverse .itr-media { order: 2; }
:where(.sl-body) .itr-media img { width: 100%; height: 100%; max-height: 520px; object-fit: cover; object-position: 50% var(--sl-focus-y, 0%); /* a crop that discards the TOP of an image discards faces — portraits were losing their heads to this cover crop (Dr. Vasquez, Solstice cold start, fold review 2026-08-10) */ border-radius: var(--card-radius); box-shadow: 0 18px 44px rgba(0,0,0,0.14); }
:where(.sl-body) .itr-body h2 { margin-top: 0.25rem; }
:where(.sl-body) .itr-body .btn { margin-top: 1.1rem; }
:where(.sl-body) .itr-checklist { list-style: none; margin: 1rem 0 0; padding: 0; display: grid; gap: 0.8rem; }
:where(.sl-body) .itr-checklist li { display: flex; gap: 0.65rem; align-items: flex-start; line-height: 1.5; }
:where(.sl-body) .itr-checklist .check { flex: 0 0 auto; color: var(--c-accent); margin-top: 2px; }
:where(.sl-body) .itr-checklist strong { color: var(--c-text); }
:where(.sl-body) .itr-checklist span { color: var(--c-text-muted); }
@media (max-width: 820px) { :where(.sl-body) .img-text { grid-template-columns: minmax(0, 1fr); gap: 1.5rem; } :where(.sl-body) .img-text.reverse .itr-media { order: 0; } }
/* Top Tier only: on a phone the value_prop band's Book button matches the full-width hero CTAs
   above it instead of a narrow left-aligned button, so the two primary CTAs read as one style. */
@media (max-width: 820px) { :where(.sl-body).bands-paper .img-text .itr-body .btn { display: block; width: 100%; text-align: center; } }

/* Package carousel */
/* Center the whole carousel within the shared content width so the price section's
   visual base aligns with the grids/FAQ/steps above and below it. The track can still
   overflow this box for its peek/scroll affordance, but its left edge and centered
   base match --content-max. */
:where(.sl-body) .pkg-carousel { position: relative; max-width: var(--content-max); margin-left: auto; margin-right: auto; }
/* R10: center the cards when they fit (few packages), start-align only when the track actually
   overflows and scrolls. `safe center` centers without clipping the first card on overflow. */
:where(.sl-body) .pkg-track { display: flex; gap: 1.5rem; justify-content: safe center; overflow-x: auto; scroll-snap-type: x mandatory; padding: 0.5rem 0.25rem 1rem; scrollbar-width: none; }
:where(.sl-body) .pkg-track::-webkit-scrollbar { display: none; }
:where(.sl-body) .pkg-card { flex: 0 0 300px; scroll-snap-align: center; display: flex; flex-direction: column; text-align: center; }
/* R9: bag placeholder must not read as a white box. Soft brand-tinted panel (no #fff), so a
   package without a real bag image still looks intentional. */
:where(.sl-body) .pkg-bag-fallback { display: flex; align-items: center; justify-content: center; height: 190px; margin-bottom: 0.75rem; border-radius: var(--card-radius); background: linear-gradient(160deg, color-mix(in srgb, var(--c-accent) 12%, var(--c-surface)), var(--c-surface-alt)); color: var(--c-accent); }
:where(.sl-body) .pkg-bag-fallback svg { height: 120px; width: auto; }
:where(.sl-body) .pkg-card .pkg-book { align-self: center; }
:where(.sl-body) .pkg-arrow { position: absolute; top: 50%; transform: translateY(-50%); z-index: 3; width: 44px; height: 44px; border-radius: 50%; border: 1px solid var(--c-border); background: var(--c-surface); color: var(--c-primary); display: grid; place-items: center; cursor: pointer; box-shadow: var(--card-shadow); transition: background .15s, color .15s; }
:where(.sl-body) .pkg-arrow:hover { background: var(--c-primary); color: var(--c-on-primary); }
/* Scroll affordance: when the track overflows and isn't scrolled to the end, fade its
   right edge so the peek card reads as "more to scroll" rather than a clipped/broken card.
   A mask fades content to transparent (not a color), so it works on any section band color.
   Classes (can-scroll / is-start / is-end) are toggled by the inline script below. */
:where(.sl-body) .pkg-style-carousel.can-scroll:not(.is-end) .pkg-track {
  -webkit-mask-image: linear-gradient(90deg, #000 84%, transparent 99%);
  mask-image: linear-gradient(90deg, #000 84%, transparent 99%);
}
:where(.sl-body) .pkg-style-carousel:not(.can-scroll) .pkg-arrow { display: none; }
:where(.sl-body) .pkg-style-carousel.is-start .pkg-prev, :where(.sl-body) .pkg-style-carousel.is-end .pkg-next { opacity: 0.35; pointer-events: none; }
:where(.sl-body) .pkg-prev { left: -12px; }
:where(.sl-body) .pkg-next { right: -12px; }
@media (max-width: 768px) { :where(.sl-body) .pkg-style-carousel .pkg-arrow { display: none; } :where(.sl-body) .pkg-style-carousel .pkg-card { flex-basis: 82%; } }
/* ── REPEATING-COMPONENT ARTISTRY: per-brand carousel arrow/frame skins (theme.variants.carousel_art) ──
   The 3-up bag carousel is LOCKED (Ian's rule), so per-brand distinctiveness rides on the arrow/frame
   chrome + hover motion. CSS-only; never touches the .pkg-track structure. Seeded per brand upstream. */
:where(.sl-body) .pkg-art-solid .pkg-arrow { background: var(--c-primary); border-color: var(--c-primary); color: var(--c-on-primary); }
:where(.sl-body) .pkg-art-solid .pkg-arrow:hover { background: var(--c-primary-dark); color: var(--c-on-primary); transform: translateY(-50%) scale(1.07); }
:where(.sl-body) .pkg-art-ring .pkg-arrow { background: transparent; border: 2px solid var(--c-primary); color: var(--c-primary); box-shadow: none; }
:where(.sl-body) .pkg-art-ring .pkg-arrow:hover { background: var(--c-primary); color: var(--c-on-primary); }
:where(.sl-body) .pkg-art-square .pkg-arrow { border-radius: 7px; background: var(--c-surface); border: 1px solid var(--c-border); color: var(--c-primary); }
:where(.sl-body) .pkg-art-square .pkg-arrow:hover { background: var(--c-primary); color: var(--c-on-primary); }
:where(.sl-body) .pkg-art-pill .pkg-arrow { width: 62px; height: 40px; border-radius: 999px; background: var(--c-surface); border: 1px solid var(--c-border); color: var(--c-primary); }
:where(.sl-body) .pkg-art-pill .pkg-prev { left: -18px; }
:where(.sl-body) .pkg-art-pill .pkg-next { right: -18px; }
:where(.sl-body) .pkg-art-pill .pkg-arrow:hover { background: var(--c-primary); color: var(--c-on-primary); }
:where(.sl-body) .pkg-art-bracket .pkg-arrow { background: transparent; border: none; box-shadow: none; color: var(--c-primary); width: 40px; }
:where(.sl-body) .pkg-art-bracket .pkg-arrow:hover { background: transparent; color: var(--c-accent); }
:where(.sl-body) .pkg-art-bracket .pkg-prev:hover { transform: translateY(-50%) translateX(-4px); }
:where(.sl-body) .pkg-art-bracket .pkg-next:hover { transform: translateY(-50%) translateX(4px); }
:where(.sl-body) .pkg-art-underline .pkg-arrow { background: transparent; border: none; border-bottom: 2px solid transparent; border-radius: 0; box-shadow: none; color: var(--c-primary); height: 40px; }
:where(.sl-body) .pkg-art-underline .pkg-arrow:hover { background: transparent; color: var(--c-primary); border-bottom-color: var(--c-accent); }
/* Variant: static grid (no scroll/arrows) */
:where(.sl-body) .pkg-style-grid .pkg-track { overflow: visible; flex-wrap: wrap; justify-content: center; scroll-snap-type: none; max-width: var(--content-max); margin: 0 auto; }
/* --sl-basis is chooseCols() speaking, and it is the ONE place a column count is decided. This
   read `flex: 0 1 300px`, so eight bags sized for 4+4 (basis 252px) wrapped to 3+3+2 instead —
   R16. Only the GRID track carries --sl-basis; the carousel never sets it and keeps 300px. */
:where(.sl-body) .pkg-style-grid .pkg-card { scroll-snap-align: none; flex: 0 1 min(var(--sl-basis, 300px), calc((100% - (var(--sl-cols, 1) - 1) * 1.5rem) / var(--sl-cols, 1))); }
/* …AND THE COLUMN COUNT IS A DESKTOP DECISION, SO A PHONE MUST NOT INHERIT IT.
   `--sl-cols` is written by the renderer from the desktop layout — 4 for an eight-bag menu — and
   the calc above then divides the PHONE's width by it as well. Measured on Top Tier at 390px:
   eight cards at 62px each, carrying bag images 9px wide, with the drip names broken to one word
   a line. `.cards-center` has collapsed on small screens for years (:529); this grid never got
   the same rule, which is why the vitamin shots read fine on a phone and the drips did not.
   Two up rather than one: the bag is a tall object with a height cap of 230px here, so a single
   column would make the eight-drip menu about 2,600px of scrolling on its own. */
/* ONE PER ROW, LIKE THE VIALS. Two-up was my call, to stop the eight-drip menu becoming 2,600px
   of scrolling. Ian's call is that the bags should stack the way the vitamin shots already do, and
   he is right: they are the same kind of object on the same page, and side by side each bag ends
   up smaller than the vial further down. The drip is the thing being sold; it gets the room. */
@media (max-width: 768px) {
  :where(.sl-body) .pkg-style-grid .pkg-card { flex: 0 0 100%; max-width: 100%; }
}
/* Variant: list rows (image left, details right) */
:where(.sl-body) .pkg-style-list .pkg-track { overflow: visible; flex-direction: column; gap: 1rem; max-width: 760px; margin: 0 auto; scroll-snap-type: none; }
:where(.sl-body) .pkg-style-list .pkg-card { flex: 1 1 auto; flex-direction: row; align-items: center; text-align: left; gap: 1.25rem; }
:where(.sl-body) .pkg-style-list .pkg-bag, :where(.sl-body) .pkg-style-list .pkg-bag-fallback { height: 84px !important; width: 84px; flex: 0 0 84px; margin: 0 !important; }
:where(.sl-body) .pkg-style-list .pkg-card h3 { margin: 0; }
:where(.sl-body) .pkg-style-list .pkg-card .pkg-book { margin-left: auto; align-self: center; white-space: nowrap; }

/* pkg-menu: a boutique price-list structure (leader dots) — a genuinely different tree from the
   bag carousel, so a brand assigned variants.packages='menu' reads structurally distinct. */
:where(.sl-body) .pkg-menu { list-style: none; margin: 2rem auto 0; padding: 0; max-width: 780px; }
:where(.sl-body) .pkg-menu-row { padding: 1.1rem 0; border-bottom: 1px solid var(--c-border); }
:where(.sl-body) .pkg-menu-row:first-child { border-top: 1px solid var(--c-border); }
:where(.sl-body) .pkg-menu-head { display: flex; align-items: center; gap: 1rem; text-decoration: none; color: var(--c-text); }
:where(.sl-body) .pkg-menu-bag { flex: 0 0 auto; object-fit: contain; filter: drop-shadow(0 6px 14px rgba(0,0,0,0.14)); }
:where(.sl-body) .pkg-menu-bag-none { width: 46px; height: 58px; border-radius: 8px; background: color-mix(in srgb, var(--c-primary) 8%, var(--c-surface)); }
:where(.sl-body) .pkg-menu-name { font-weight: 600; font-size: 1.15rem; white-space: nowrap; }
:where(.sl-body) .pkg-menu-dots { flex: 1 1 auto; border-bottom: 2px dotted var(--c-border); transform: translateY(-4px); min-width: 24px; }
:where(.sl-body) .pkg-menu-price { font-weight: 700; color: var(--c-accent-ink, var(--c-accent)); font-size: 1.15rem; white-space: nowrap; }
:where(.sl-body) .pkg-menu-desc { margin: 0.4rem 0 0 calc(46px + 1rem); color: var(--c-text-muted); font-size: 0.95rem; line-height: 1.5; }
:where(.sl-body) .pkg-menu-head:hover .pkg-menu-name { color: var(--c-primary); }
@media (max-width: 640px) { :where(.sl-body) .pkg-menu-desc { margin-left: 0; } }

/* Video testimonials */
:where(.sl-body) .video-testimonials { align-items: flex-start; }
:where(.sl-body) .video-testimonial { flex: 0 1 340px; }
:where(.sl-body) .video-testimonial video { width: 100%; aspect-ratio: 9 / 11; object-fit: cover; border-radius: var(--card-radius); background: #000; box-shadow: 0 16px 40px rgba(0,0,0,0.16); }
:where(.sl-body) .video-testimonial .vt-meta { margin-top: 0.65rem; text-align: center; font-size: 0.95rem; }
:where(.sl-body) .video-testimonial .vt-meta strong { color: var(--c-text); }
:where(.sl-body) .video-testimonial .vt-meta span { color: var(--c-text-muted); }

/* Review cards (testimonials) */
:where(.sl-body) .review-card { display: flex; flex-direction: column; text-align: left; }
/* accent-INK, not raw accent: a review card sits on the light alt surface, where a light brand
   accent is decorative-only. Pure IV's gold measured 1.75:1 here. Hero ratings keep raw accent —
   those sit on a scrimmed photograph, which is the one place the undarkened accent is correct. */
:where(.sl-body) .review-card .stars { color: var(--c-accent-ink, var(--c-accent)); letter-spacing: 1px; font-size: 1.05rem; margin-bottom: 0.6rem; }
:where(.sl-body) .review-quote { font-style: italic; color: var(--c-text); margin: 0 0 1.1rem; line-height: 1.55; }
:where(.sl-body) .review-by { display: flex; align-items: center; gap: 0.6rem; margin-top: auto; }
:where(.sl-body) .review-avatar { width: 40px; height: 40px; border-radius: 50%; object-fit: cover; flex: 0 0 auto; }
:where(.sl-body) .review-initial { display: grid; place-items: center; background: var(--c-primary); color: #fff; font-weight: 700; font-size: 0.9rem; }

/* Newsletter signup band */
:where(.sl-body) .social-feed-band { text-align: center; max-width: 600px; margin: 0 auto; }
:where(.sl-body) .social-feed-band .sf-ig { display: flex; justify-content: center; margin-bottom: 0.75rem; color: var(--c-accent); }
:where(.sl-body) .newsletter-band { text-align: center; max-width: 640px; margin: 0 auto; }
:where(.sl-body) .newsletter-form { display: flex; gap: 0.6rem; justify-content: center; flex-wrap: wrap; margin-top: 0.5rem; }
:where(.sl-body) .newsletter-form input { flex: 1 1 280px; max-width: 360px; padding: 0.85rem 1.1rem; font-size: 1rem; border: 1px solid var(--c-border); border-radius: var(--btn-radius); background: var(--c-surface); color: var(--c-text); }
:where(.sl-body) .newsletter-form input:focus { outline: 2px solid var(--c-focus); outline-offset: 2px; border-color: var(--c-primary); }

/* Service-area chips */
:where(.sl-body) .area-chips { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.6rem; }
:where(.sl-body) .area-chip { display: inline-flex; align-items: center; gap: 0.4rem; padding: 0.5rem 1rem; border-radius: 999px; background: var(--c-surface-alt); color: var(--c-text); border: 1px solid var(--c-border); font-size: 0.92rem; font-weight: 500; }
:where(.sl-body) .area-chip svg { color: var(--c-accent); }

/* Coverage map: real US state outlines; served states filled in the brand accent. */
/* ── Coverage section: full-bleed brand-lit band (research-driven; replaces the old boxed
   gray map). The whole section becomes a deep brand-dark band (primary mixed toward near-
   black) with an accent corner glow; !important overrides the decorative section-rhythm
   gradients for this one section. Map left, headline + auto stat + city chips right. ── */
:where(.sl-body) .section-service_area_map, :where(.sl-body) .section-service_areas, :where(.sl-body) .section-areas, :where(.sl-body) .section-locations, :where(.sl-body) .section-coverage_area {
  background:
    radial-gradient(125% 120% at 14% 16%, color-mix(in srgb, var(--c-accent) 26%, transparent), transparent 55%),
    linear-gradient(155deg, color-mix(in srgb, var(--c-primary) 60%, #0b0e13) 0%, color-mix(in srgb, var(--c-primary) 26%, #0b0e13) 100%) !important;
  color: #fff;
}
/* ONE COLUMN, SAID OUT LOUD.

   This used to read `grid-template-columns: 1.minmax(0, 1fr) 0.9fr`. `1.minmax(...)` is not a
   length, so the whole declaration was thrown away by every browser that ever loaded it and the
   band has ALWAYS been a single stacked column. Nobody knew: the file said two columns, the page
   drew one, and the two disagreed silently for as long as the rule existed.

   Correcting the value is NOT the repair, and was tried and reverted: two real columns leave the
   left half empty on every brand whose coverage band draws no map, which is a worse band than the
   tidy stack. So the rendering stays exactly as it has always been, and the rule now SAYS that
   instead of pretending otherwise - identical pixels, no landmine for the next person to "fix".
   The two-column case is a deliberate one and lives with the mode that wants it, on
   `.coverage-panel .coverage-inner` below. */
:where(.sl-body) .coverage-inner { max-width: var(--content-max); margin: 0 auto; display: grid; grid-template-columns: minmax(0, 1fr); gap: 2rem 3.5rem; align-items: center; }
:where(.sl-body) .coverage-map-col { min-width: 0; }
:where(.sl-body) .coverage-map-col .cm-svg { width: 100%; height: auto; display: block; filter: drop-shadow(0 26px 52px rgba(0,0,0,0.45)); }
:where(.sl-body) .coverage-map-col .cm-state { fill: rgba(255,255,255,0.07); stroke: rgba(255,255,255,0.16); stroke-width: 1; }
:where(.sl-body) .coverage-map-col .cm-state-on { fill: var(--c-accent); stroke: color-mix(in srgb, var(--c-accent) 55%, #000); stroke-width: 1; }
:where(.sl-body) .coverage-pin-halo { fill: var(--c-accent); opacity: 0.28; transform-box: fill-box; transform-origin: center; }
:where(.sl-body) .coverage-pin { fill: var(--c-accent); stroke: #fff; stroke-width: 1.4; }
@media (prefers-reduced-motion: no-preference) { :where(.sl-body) .coverage-pin-halo { animation: coveragePulse 2.6s ease-in-out infinite; } }
@keyframes coveragePulse { 0%, 100% { opacity: 0.16; transform: scale(0.8); } 50% { opacity: 0.42; transform: scale(1.3); } }
:where(.sl-body) .coverage-map-col .cg-globe { fill: none; stroke: var(--c-accent); stroke-width: 1.5; opacity: 0.85; }
:where(.sl-body) .coverage-map-col .cg-line { fill: none; stroke: rgba(255,255,255,0.35); stroke-width: 1; }
:where(.sl-body) .coverage-text-col .eyebrow { background: rgba(255,255,255,0.14); color: #fff; }
:where(.sl-body) .coverage-text-col h2 { color: #fff; margin: 0 0 0.65rem; }
:where(.sl-body) .coverage-text-col .coverage-body { color: rgba(255,255,255,0.82); margin: 0 0 1.25rem; line-height: 1.6; }
:where(.sl-body) .coverage-stat { display: inline-flex; align-items: center; gap: 0.5rem; font-weight: 600; font-size: 1.05rem; color: #fff; margin-bottom: 1.1rem; }
:where(.sl-body) .coverage-stat svg { color: var(--c-accent); flex: 0 0 auto; }
:where(.sl-body) .coverage-chips { display: flex; flex-wrap: wrap; gap: 0.5rem; margin-bottom: 1.6rem; }
:where(.sl-body) .coverage-chip { display: inline-flex; align-items: center; padding: 0.4rem 0.85rem; border-radius: 999px; font-size: 0.9rem; font-weight: 500; color: #fff; background: rgba(255,255,255,0.08); border: 1px solid rgba(255,255,255,0.2); }
:where(.sl-body) .coverage-cta { display: flex; flex-wrap: wrap; align-items: center; gap: 1rem 1.5rem; }
:where(.sl-body) .coverage-fallback { color: rgba(255,255,255,0.78); text-decoration: underline; text-underline-offset: 3px; font-size: 0.95rem; }
:where(.sl-body) .coverage-fallback:hover { color: #fff; }
/* Static form (no phone to link to): it is a policy statement, not an action, so no underline. */
:where(.sl-body) .coverage-fallback-static { text-decoration: none; max-width: 42ch; line-height: 1.55; }
@media (max-width: 860px) {
  :where(.sl-body) .coverage-inner { grid-template-columns: minmax(0, 1fr); gap: 1.5rem; text-align: center; }
  :where(.sl-body) .coverage-map-col { max-width: 440px; margin: 0 auto; }
  :where(.sl-body) .coverage-chips, :where(.sl-body) .coverage-cta, :where(.sl-body) .coverage-stat { justify-content: center; }
}
:where(.sl-body) .coverage-map .cm-state-label { fill: #fff; font-size: 13px; font-weight: 700; font-family: var(--font-heading), sans-serif; pointer-events: none; }
/* Nationwide (no specific states): light brand-tinted US outline as a coverage graphic. */
:where(.sl-body) .coverage-globe { max-width: 280px; margin: 0 auto 1.5rem; }
:where(.sl-body) .coverage-globe svg { width: 100%; height: auto; display: block; }
:where(.sl-body) .coverage-globe .cg-globe { fill: var(--c-primary); opacity: 0.12; }

/* ── Coverage COMPOSITIONS (theme.composition.map) — the service-area band was the one
   composition every brand shared regardless of geometry profile (Ian, round 1 review).
   Light modes paint the band with the brand's alt surface, NOT transparent white, so
   bands-paper's one-stock law holds. Higher specificity beats the band's own !important. ── */
:where(.sl-body).map-index .section-service_area_map, :where(.sl-body).map-index .section-service_areas, :where(.sl-body).map-index .section-areas, :where(.sl-body).map-index .section-locations, :where(.sl-body).map-index .section-coverage_area, :where(.sl-body).map-panel .section-service_area_map, :where(.sl-body).map-panel .section-service_areas, :where(.sl-body).map-panel .section-areas, :where(.sl-body).map-panel .section-locations, :where(.sl-body).map-panel .section-coverage_area {
  background: var(--c-surface-alt) !important;
  color: var(--c-text);
}
:where(.sl-body) .coverage-index { max-width: var(--content-max); margin: 0 auto; }
/* ONE PAGE, ONE EDGE - AND THIS BAND KEPT ITS OWN. Every other band on a shelf page takes its
   inset from --bk-pad; this one sits in a .container capped at 1200 and is then capped AGAIN by
   its own --content-max, so its words start twenty pixels inside everybody else’s. Measured at
   1280 and 1440 on a live client: two left edges on thirteen pages, which is the fault G1 exists
   to refuse. It was invisible for as long as the grid check could not see this site at all.
   The band keeps its own cap off the shelf, where .container IS the page grid. */
/* ...AND THE SAME BAND KEPT ITS OWN ALIGNMENT TOO. --bk-align is the page’s answer to "are the
   headings centred or ranged left" and every shelf band asks it; this one answered for itself and
   came out ranged left on a page whose other three bands are centred. That is G2, one page mixing
   both, on the same thirteen pages as the edge above. One band, two halves of the same law. */
:where(.sl-body).sl-shelf main > section.section-service_area_map > .container { max-width: none; padding-inline: var(--bk-pad); text-align: var(--bk-align, start); }
/* ...AND OFF THE SHELF TOO, which the first version of this got wrong in exactly the way the
   audit above is about: it fixed the fault for shelf brands and left it standing for everybody
   else. The double cap is not a shelf problem - .container already caps and pads the band, and
   .coverage-index then caps it AGAIN and re-centres, so its words start twenty pixels inside its
   neighbours on every brand. Measured after the narrow fix: still two left edges on six brands.
   The inner cap goes wherever the container is already doing that job. */
/* Both inners. The band has two - the ruled index and the classic split - and naming only the
   first fixed one brand and left the same twenty pixels on six others. The classic one stacks
   (see the never-parsed column rule below), so widening it to the container adds no empty half. */
:where(.sl-body) .container > .coverage-index, :where(.sl-body) .container > .coverage-inner { max-width: none; }
:where(.sl-body) .coverage-index h2 { margin: 0 0 0.6rem; }
:where(.sl-body) .coverage-index .coverage-body { color: var(--c-text-muted); max-width: 62ch; margin: 0 0 1.4rem; line-height: 1.6; }
:where(.sl-body) .coverage-index-list { list-style: none; margin: 0 0 1.9rem; padding: 0; }
/* The rule has to be derived from the INK, not --c-border. This list only ever sits on the
   alt surface (the light map compositions paint it at :587), and --c-border is tuned against
   the white page stock: on Top Tier's beige band #E3DACB on #E8DCC8 is 1.03:1, so the "ruled
   ledger" rendered with no rules at all. A low-alpha ink hairline holds on any light stock. */
:where(.sl-body) .coverage-index-list li { border-bottom: 1px solid color-mix(in srgb, var(--c-text) 20%, transparent); break-inside: avoid; }
:where(.sl-body) .coverage-index-list.is-marquee li { font-family: var(--font-heading); font-weight: var(--heading-weight, 700); font-size: clamp(1.5rem, 3.2vw, 2.3rem); padding: 1.05rem 0.15rem; }
:where(.sl-body) .coverage-index-list.is-roster { columns: 2; column-gap: 3.25rem; }
:where(.sl-body) .coverage-index-list.is-roster li { font-weight: 500; padding: 0.7rem 0.15rem; }
:where(.sl-body).map-index .coverage-stat { color: var(--c-text); }
:where(.sl-body).map-index .coverage-fallback { color: var(--c-text-muted); }
:where(.sl-body).map-index .coverage-fallback:hover { color: var(--c-text); }
/* ...AND THE LABEL ABOVE THE HEADING, which this block re-inked the stat and the fallback for and
   not the eyebrow. A design lane may bind the eyebrow ink per ground, and one of them says in so
   many words that a coverage map "keeps the paper ink" — true while that band was always dark,
   and false the moment a brand chooses the light index mode. It shipped as paper on the alt
   surface: 1.11:1, invisible, on the About page and every city page of a live client. The band
   knows which mode it is in, so the ink is bound here rather than argued lane by lane. */
:where(.sl-body).map-index .section-service_area_map, :where(.sl-body).map-index .section-service_areas, :where(.sl-body).map-index .section-areas, :where(.sl-body).map-index .section-locations, :where(.sl-body).map-index .section-coverage_area, :where(.sl-body).map-panel .section-service_area_map, :where(.sl-body).map-panel .section-service_areas, :where(.sl-body).map-panel .section-areas, :where(.sl-body).map-panel .section-locations, :where(.sl-body).map-panel .section-coverage_area {
  --eyebrow-ink: var(--c-accent-ink, var(--c-text));
}
:where(.sl-body).map-index .section-service_area_map .eyebrow, :where(.sl-body).map-panel .section-service_area_map .eyebrow {
  color: var(--eyebrow-ink, var(--c-text));
  background: none;
}
@media (max-width: 720px) { :where(.sl-body) .coverage-index-list.is-roster { columns: 1; } }

:where(.sl-body) .coverage-panel {
  max-width: var(--content-max); margin: 0 auto;
  padding: clamp(1.9rem, 4.5vw, 3.25rem);
  border-radius: calc(var(--card-radius) + 10px);
  background:
    radial-gradient(125% 120% at 86% 16%, color-mix(in srgb, var(--c-accent) 26%, transparent), transparent 55%),
    linear-gradient(155deg, color-mix(in srgb, var(--c-primary) 60%, #0b0e13) 0%, color-mix(in srgb, var(--c-primary) 26%, #0b0e13) 100%);
  color: #fff;
  box-shadow: 0 34px 70px -32px rgba(11, 14, 19, 0.55);
  /* Only rebind the ink used for headings/body on the dark panel. Do NOT rebind --c-surface:
     filled-button archetypes (bold-modern) read --c-surface as the button TEXT color, so a dark
     rebind made the CTA navy-on-navy. The panel CTA is pinned to a legible accent treatment below. */
  --c-text: #fff;
}
:where(.sl-body) .coverage-panel .coverage-inner { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
/* Panel CTA: accent fill + dark ink, forced above every archetype's !important button rule
   (bold-modern's adacc-* rules are (0,3,1)!important, so match the weight and land later in file). */
:where(.sl-body).ad-bold-modern .coverage-panel .btn-primary, :where(.sl-body).ad-editorial-luxe .coverage-panel .btn-primary, :where(.sl-body).ad-bright-clinical .coverage-panel .btn-primary, :where(.sl-body).ad-typographic-clinical .coverage-panel .btn-primary, :where(.sl-body) .coverage-panel .btn-primary { background: var(--c-accent) !important; color: var(--c-accent-on, var(--c-primary-dark)) !important; border-color: var(--c-accent) !important; box-shadow: none; }
:where(.sl-body) .coverage-panel .btn-primary:hover { background: color-mix(in srgb, var(--c-accent) 85%, #fff) !important; color: var(--c-primary-dark) !important; }

/* stack mode has no .coverage-map-col wrapper, so the map styles scoped to it never apply and
   the SVG paths default to BLACK. Restate the map skin under the stack's own wrapper. */
:where(.sl-body) .coverage-stack-map .cm-svg { width: 100%; height: auto; display: block; filter: drop-shadow(0 26px 52px rgba(0, 0, 0, 0.45)); }
:where(.sl-body) .coverage-stack-map .cm-state { fill: rgba(255, 255, 255, 0.14); stroke: rgba(255, 255, 255, 0.26); stroke-width: 1; }
:where(.sl-body) .coverage-stack-map .cm-state-on { fill: var(--c-accent); stroke: color-mix(in srgb, var(--c-accent) 55%, #000); stroke-width: 1; }

:where(.sl-body) .coverage-stack { max-width: var(--content-max); margin: 0 auto; text-align: center; }
:where(.sl-body) .coverage-stack .eyebrow { background: rgba(255, 255, 255, 0.14); color: #fff; }
:where(.sl-body) .coverage-stack h2 { color: #fff; margin: 0 0 0.65rem; }
:where(.sl-body) .coverage-stack .coverage-body { color: rgba(255, 255, 255, 0.82); margin: 0 auto 0.75rem; max-width: 62ch; line-height: 1.6; }
:where(.sl-body) .coverage-stack-map { max-width: 680px; margin: 1.5rem auto 1.35rem; }
:where(.sl-body) .coverage-stack .coverage-stat { margin-bottom: 1rem; }
:where(.sl-body) .coverage-stack .coverage-chips, :where(.sl-body) .coverage-stack .coverage-cta { justify-content: center; }
:where(.sl-body) .coverage-globe .cg-line { fill: none; stroke: var(--c-primary); stroke-width: 1.5; opacity: 0.5; }
:where(.sl-body) .coverage-map-nationwide { max-width: 560px; }
:where(.sl-body) .coverage-map-nationwide .cm-state { fill: color-mix(in srgb, var(--c-primary) 34%, #cfd6df); }
:where(.sl-body) .coverage-map .cm-count { margin-top: 0.75rem; font-size: 0.95rem; color: var(--c-text-muted); }
:where(.sl-body) .coverage-map .cm-count strong { color: var(--c-text); font-size: 1.05rem; }

/* Stats / by-the-numbers band */
:where(.sl-body) .stats-band { display: flex; flex-wrap: wrap; justify-content: center; gap: clamp(1.5rem, 5vw, 4rem); text-align: center; }
:where(.sl-body) .stats-band .stat { min-width: 140px; }
:where(.sl-body) .stat-ic { display: flex; justify-content: center; margin-bottom: 0.6rem; color: var(--c-accent); }
:where(.sl-body) .stat-ic svg { width: 30px; height: 30px; }
:where(.sl-body) .stat-value { font-family: var(--font-heading); font-weight: var(--heading-weight, 700); font-size: clamp(2.1rem, 4vw, 3rem); color: var(--c-primary); line-height: 1; }
:where(.sl-body) .stat-label { color: var(--c-text-muted); margin-top: 0.45rem; font-size: 0.95rem; }
/* Stats render as a bold full-width band — color follows the design (theme.stats), else brand-dark */
:where(.sl-body) .section-stats { background: var(--c-stats-bg, var(--c-hero-plate)) !important; }
:where(.sl-body) .section-stats .eyebrow { color: var(--c-accent); }
:where(.sl-body) .section-stats h2, :where(.sl-body) .section-stats .stat-value { color: var(--c-stats-text, #fff); }
:where(.sl-body) .section-stats .stat-label { color: var(--c-stats-text, #fff); opacity: 0.8; }

/* Inline-edit preview overlay outline */
:where(.sl-body) [data-sl-armed] { outline: 1px dashed rgba(212,175,55,0.6); }

/* Klaro micro consent banner */
:where(.sl-body) .sl-consent-banner {
  position: fixed; bottom: 1rem; left: 1rem; right: 1rem; z-index: 9999;
  background: var(--c-surface); border: 1px solid var(--c-border);
  border-radius: var(--card-radius); padding: 1rem 1.25rem;
  box-shadow: 0 16px 48px rgba(0,0,0,0.2);
  max-width: 520px;
}
:where(.sl-body) .sl-consent-banner .sl-consent-row { display: flex; gap: 0.5rem; flex-wrap: wrap; margin-top: 0.75rem; }
:where(.sl-body) .sl-consent-banner .sl-consent-row .btn { padding: 0.5rem 1rem; font-size: 0.875rem; }
:where(.sl-body) .sl-consent-banner[hidden] { display: none; }

/* ============================================================================
   MATERIAL PASS v1 — surface-finish upgrade (type, depth, grain, glass, glow).
   Pure CSS, brand-token-driven, ZERO layout/content change. Appended last so it
   sits at the top of the cascade. Graceful: color-mix is Baseline-2023, glass is
   @supports-gated, grain is a tiny inline SVG (no asset weight). This is the new
   premium default surface for every brand; pilot-rendered on Pure IV first.
   ============================================================================ */
:where(.sl-body) {
  /* Faint monochrome film grain (desaturated, low-alpha) — kills banding, adds craft. */
  --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3CfeComponentTransfer%3E%3CfeFuncA type='linear' slope='0.13'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23g)'/%3E%3C/svg%3E");
}

/* 1. DISPLAY TYPE — bigger, tighter, balanced. The single biggest "premium" lever. */
:where(.sl-body) .hero h1 { font-size: clamp(2.7rem, 6.2vw, 4.6rem); line-height: 1.03; letter-spacing: -0.03em; font-weight: 800; text-wrap: balance; }
:where(.sl-body) h2 { font-size: clamp(2rem, 3.8vw, 3rem); letter-spacing: -0.022em; text-wrap: balance; }
:where(.sl-body) .hero .subhead { font-size: clamp(1.05rem, 1.5vw, 1.22rem); line-height: 1.55; max-width: 54ch; }
:where(.sl-body) .eyebrow, :where(.sl-body) .hero .eyebrow, :where(.sl-body) .section-header .eyebrow { font-weight: 700; letter-spacing: 0.14em; }
:where(.sl-body) .section-header { max-width: var(--content-measure); }

/* 2. HERO — directional legibility scrim + brand aurora glow + fine grain, so the
      photo reads cinematic and deep instead of a flat dark wash. Text stays legible:
      the scrim is darkest on the left where the headline sits. */
:where(.sl-body) .hero-image-bg::after, :where(.sl-body) .hero-video::after {
  background:
    var(--grain),
    radial-gradient(58% 80% at 86% 16%, color-mix(in srgb, var(--c-accent) 40%, transparent), transparent 60%),
    linear-gradient(100deg, color-mix(in srgb, var(--c-primary-dark) 90%, transparent) 0%, color-mix(in srgb, var(--c-primary-dark) 60%, transparent) 44%, color-mix(in srgb, var(--c-primary-dark) 20%, transparent) 100%),
    /* Legibility floor: a dark wash for LIGHT-primary brands so white hero text passes
       contrast. Transparent (no-op) for dark brands, so they render unchanged. */
    linear-gradient(var(--hero-scrim-floor, transparent), var(--hero-scrim-floor, transparent));
  background-size: 180px 180px, cover, cover, cover;
}

/* 3. SURFACES — top-lit depth + crisp hairline + hover lift, so cards feel crafted. */
:where(.sl-body) .card {
  border: 1px solid color-mix(in srgb, var(--c-text) 9%, transparent);
  box-shadow:
    0 1px 0 rgba(255,255,255,0.7) inset,
    0 1px 2px rgba(16,24,32,0.04),
    0 14px 30px -12px rgba(16,24,32,0.18);
  transition: transform .18s ease, box-shadow .18s ease;
}
:where(.sl-body) .cards-center .card:hover, :where(.sl-body) .grid .card:hover {
  transform: translateY(-3px);
  box-shadow: 0 1px 0 rgba(255,255,255,0.7) inset, 0 22px 46px -16px rgba(16,24,32,0.26);
}

/* 4. GLASS NAV — translucent, blurred, hairline; content peeks under as you scroll. */
@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  :where(.sl-body) .site-header {
    background: color-mix(in srgb, var(--c-surface) 78%, transparent);
    -webkit-backdrop-filter: blur(14px) saturate(1.4);
    backdrop-filter: blur(14px) saturate(1.4);
    border-bottom: 1px solid color-mix(in srgb, var(--c-text) 8%, transparent);
  }
}

/* 5. BUTTONS — subtle lift + a colored glow under the primary action. */
:where(.sl-body) .btn { box-shadow: 0 1px 2px rgba(16,24,32,0.10); }
:where(.sl-body) .btn:hover { transform: translateY(-1px); }
:where(.sl-body) .btn-primary { box-shadow: 0 8px 20px -8px color-mix(in srgb, var(--c-primary) 55%, transparent); }
:where(.sl-body) .btn-accent, :where(.sl-body) .cta-accent .btn-primary { box-shadow: 0 8px 20px -7px color-mix(in srgb, var(--c-accent) 55%, transparent); }

/* 6. DARK BANDS — faint grain over big color fields (stats + final CTA) so they
      read as rich material, not flat ink. Content stays above the grain. */
:where(.sl-body) .section-stats, :where(.sl-body) .final-cta { position: relative; overflow: hidden; }
:where(.sl-body) .section-stats::before, :where(.sl-body) .final-cta::before {
  content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background-image: var(--grain); background-size: 180px 180px;
}
:where(.sl-body) .section-stats > .container { position: relative; z-index: 1; }

/* ============================================================================
   MATERIAL PASS v2 — BOLD art direction. Recomposed cinematic hero, dramatic
   oversized type, motion (entrance + scroll reveals), asymmetric bento features,
   oversized stats. Still pure CSS, static-safe, brand-token-driven. Overrides v1.
   ============================================================================ */

/* --- 1. DRAMATIC TYPE SCALE --- */
:where(.sl-body) .hero h1 { font-size: clamp(3rem, 8.4vw, 6.4rem); line-height: 0.98; letter-spacing: -0.04em; font-weight: 800; text-wrap: balance; }
:where(.sl-body) h2 { font-size: clamp(2.1rem, 4.6vw, 3.5rem); line-height: 1.04; letter-spacing: -0.028em; text-wrap: balance; }
:where(.sl-body) .section-header { max-width: var(--content-measure); margin-bottom: 3rem; }
:where(.sl-body) .hero .subhead { font-size: clamp(1.1rem, 1.6vw, 1.3rem); line-height: 1.55; max-width: 50ch; }
:where(.sl-body) .eyebrow, :where(.sl-body) .hero .eyebrow, :where(.sl-body) .section-header .eyebrow { font-weight: 700; letter-spacing: 0.18em; font-size: 0.82rem; }

/* --- 2. CINEMATIC HERO: tall, graded photo, full-bleed BRAND GLAZE, grain --- */
:where(.sl-body) .hero-image-bg::before { filter: saturate(1.08) contrast(1.05) brightness(0.96); }
/* Full-bleed brand-tinted GLAZE over the photo: a diagonal wash mixing the brand
   dark (~0.82 alpha) down into the brand primary (~0.5 alpha), plus a warm accent
   glow and fine grain. Not a flat black — the photo reads as THIS brand, and the
   glaze is strong enough that white hero text passes WCAG AA. The scrim-floor layer
   keeps light-primary brands legible (transparent no-op for dark brands). */
/* HEADS UP: this rule REPLACES the whole ::after background, which means `--hero-overlay`
   (theme_json.hero.overlay, emitted by brand.ts) is NOT painted on an image-bg hero — the glaze
   below is. Setting hero.overlay on such a site looks like it should work and does nothing; that
   cost a round on LivLong MD. The lever that DOES work is the glaze strength, parameterised here.
   Defaults are the previous literals, so every existing hero renders byte-identically.
     --hero-glaze-a/-b/-c : how much brand dark/primary is washed over the photograph
     --hero-glaze-accent  : the warm accent bloom in the top right
   A brand sets them through theme_json.hero.glaze — lower numbers let more photograph through,
   which is how a hero gets LIGHTER without swapping the picture. Hero text is white, so anything
   below roughly 45/32/20 needs visual-lint's hero contrast check to sign it off. */
:where(.sl-body) .hero-image-bg::after, :where(.sl-body) .hero-video::after {
  background:
    var(--grain),
    radial-gradient(46% 58% at 84% 18%, color-mix(in srgb, var(--c-accent) var(--hero-glaze-accent, 46%), transparent), transparent 62%),
    linear-gradient(135deg,
      color-mix(in srgb, var(--c-primary-dark) var(--hero-glaze-a, 82%), transparent) 0%,
      color-mix(in srgb, var(--c-primary-dark) var(--hero-glaze-b, 66%), transparent) 42%,
      color-mix(in srgb, var(--c-primary) var(--hero-glaze-c, 50%), transparent) 100%),
    linear-gradient(var(--hero-scrim-floor, transparent), var(--hero-scrim-floor, transparent));
  background-size: 180px 180px, cover, cover, cover;
}
:where(.sl-body) .hero-inner { max-width: 780px; }
/* Full-bleed image-bg hero: generous height, content centered vertically, capped
   ~760px so the headline + subhead + CTAs sit as one legible block over the glaze. */
:where(.sl-body) .hero-image-bg .hero-inner { max-width: 760px; }
:where(.sl-body) .hero-rating { padding: 0.7rem 1.25rem; font-size: 1rem; border-radius: 14px; background: rgba(255,255,255,0.12); border: 1px solid rgba(255,255,255,0.3); box-shadow: 0 8px 28px -10px rgba(0,0,0,0.5); }

/* --- 3. BOLDER BUTTONS --- */
:where(.sl-body) .hero .cta-row { gap: 0.9rem; margin-top: 0.5rem; }
:where(.sl-body) .hero .btn { padding: 1.05rem 1.9rem; font-size: 1.05rem; }

/* --- HERO CTA ROW: three-in-a-row on desktop, full-width stack on mobile ---
   Primary (filled) + two outline buttons must sit on ONE line at >768px, never
   orphaning a 2-then-1 wrap. Buttons shrink to fit (slightly tighter padding/size,
   min-width:0) so all three fit even under the wide full-bleed centered hero. On
   mobile they stack full-width for a clean tap target. */
@media (min-width: 769px) {
  :where(.sl-body) .hero .cta-row { flex-wrap: nowrap; align-items: stretch; }
  :where(.sl-body) .hero .cta-row .btn {
    flex: 0 1 auto;
    min-width: 0;
    padding: 1rem 1.5rem;
    font-size: 1rem;
    white-space: nowrap;
    text-align: center;
  }
}
@media (max-width: 768px) {
  :where(.sl-body) .hero .cta-row { flex-wrap: wrap; }
  :where(.sl-body) .hero .cta-row .btn { flex: 1 1 100%; width: 100%; text-align: center; }
}
:where(.sl-body) .btn-primary { box-shadow: 0 12px 30px -10px color-mix(in srgb, var(--c-primary) 65%, transparent); }
:where(.sl-body) .btn-accent, :where(.sl-body) .cta-accent .btn-primary { box-shadow: 0 14px 34px -10px color-mix(in srgb, var(--c-accent) 65%, transparent); }
:where(.sl-body) .btn:hover { transform: translateY(-2px); }

/* --- 4. MOTION: hero entrance (staggered rise) --- */
@media (prefers-reduced-motion: no-preference) {
  @keyframes slRise { from { opacity: 0; transform: translateY(26px); } to { opacity: 1; transform: none; } }
  :where(.sl-body) .hero-inner > * { animation: slRise .85s cubic-bezier(.2,.7,.2,1) both; }
  :where(.sl-body) .hero-inner > .eyebrow { animation-delay: .05s; }
  :where(.sl-body) .hero-inner > h1 { animation-delay: .14s; }
  :where(.sl-body) .hero-inner > .subhead { animation-delay: .28s; }
  :where(.sl-body) .hero-inner > .hero-rating { animation-delay: .4s; }
  :where(.sl-body) .hero-inner > .cta-row { animation-delay: .5s; }
}

/* --- 5. MOTION: section reveal on scroll — REMOVED 2026-07-30 ---------------------------
   Was: main > section:not(.hero) { animation: slReveal; animation-timeline: view(); }
   with @keyframes slReveal { from { opacity: 0; transform: translateY(38px); } }.

   Ungated, so it ran on every section of every site. Because the target is the SECTION, the
   opacity-0 start took the band's own background with it — mid-scroll you saw the white page
   through the gap where the band should be, then it slid up 38px to meet the section above.
   Reported repeatedly as looking like a glitch, not an effect. Being scroll-LINKED (view()
   timeline, not a one-shot) it also replayed on every scroll back through, so it never settled.

   The same lesson was already learned on the opt-in path — Sections.astro:440 reads "FADE ONLY
   — no translateY. The slide moved each section up ~18px as it revealed, which opened a gap."
   That fix landed on the opt-in reveal and never on this one. Do not reintroduce: if a reveal
   is ever wanted again, animate a CHILD wrapper, never the band that paints the background. */

/* --- 6. SURFACES: deeper, rounder, real lift --- */
:where(.sl-body) .card { border: 1px solid color-mix(in srgb, var(--c-text) 9%, transparent); border-radius: clamp(14px, 1.3vw, 20px);
  box-shadow: 0 1px 0 rgba(255,255,255,0.7) inset, 0 20px 40px -18px rgba(16,24,32,0.24); transition: transform .2s ease, box-shadow .2s ease; }
:where(.sl-body) .cards-center .card:hover, :where(.sl-body) .grid .card:hover { transform: translateY(-4px); box-shadow: 0 30px 56px -20px rgba(16,24,32,0.32); }
/* bigger, bolder feature icon badges */
:where(.sl-body) .feature-ic { display: inline-grid; place-items: center; width: 60px; height: 60px; border-radius: 16px; margin-bottom: 1.1rem;
  background: color-mix(in srgb, var(--c-accent) 14%, var(--c-surface)); color: var(--c-accent); }
:where(.sl-body) .feature-ic svg { width: 28px; height: 28px; }
:where(.sl-body) .feature-card h3 { font-size: 1.25rem; letter-spacing: -0.01em; }

/* --- 7. FEATURE GRIDS: even + aligned (no forced bento; equal cards win for equal content) --- */
:where(.sl-body) .cards-center:has(> .feature-card) > .feature-card { align-self: stretch; }

/* --- 8. OVERSIZED STATS --- */
:where(.sl-body) .section-stats { padding: clamp(2.5rem, 5vw, 4.5rem) 0; }
:where(.sl-body) .stat-value { font-size: clamp(3rem, 7vw, 5.25rem); letter-spacing: -0.03em; }
:where(.sl-body) .stat-label { font-size: 1.05rem; letter-spacing: 0.02em; opacity: 0.85; }

/* --- 9. BIGGER FINAL CTA --- */
:where(.sl-body) .final-cta { padding: clamp(3.5rem, 8vw, 6.5rem) 1.5rem; }
:where(.sl-body) .final-cta h2 { font-size: clamp(2.4rem, 5.5vw, 4rem); }


/* ========================================================================
   ART DIRECTION SYSTEM — per-brand archetype expression (scoped body.ad-*).
   Driven by theme.art_direction (extract-design deriveArtDirection -> brand.ts).
   Additive: a site with no recipe has no ad-* class, so these never apply to it.
   ======================================================================== */

/* ===== EDITORIAL-LUXE ===== */
/* ============================================================================
   ART DIRECTION — EDITORIAL LUXE
   For serif / warm / restrained brands (near-black + warm gold + serif display).
   Feel: a high-end print magazine / luxury concierge. The premium signal is
   RESTRAINT — immense whitespace, hairline rules, tiny gold accents, a serif
   masthead, and a treatment list styled like an elegant printed menu.
   Everything scoped under body.ad-editorial-luxe. Brand-token-driven, mobile-safe,
   gentle motion only. Overrides the bold MATERIAL v2 pass where they conflict.
   ============================================================================ */

/* ---- 1. DISPLAY TYPE — large, light-weight serif with tight tracking ---- */
:where(.sl-body).ad-editorial-luxe h1, :where(.sl-body).ad-editorial-luxe h2, :where(.sl-body).ad-editorial-luxe h3 {
  font-family: var(--font-heading);
  font-weight: var(--ad-heading-weight, 500);
  letter-spacing: var(--ad-letter-spacing, -0.012em);
}
:where(.sl-body).ad-editorial-luxe .hero h1 {
  font-size: clamp(2.6rem, calc(6.4vw * var(--ad-h1-scale, 1)), 5.4rem) !important;
  font-weight: var(--ad-heading-weight, 500) !important;
  line-height: 1.04 !important;
  letter-spacing: var(--ad-letter-spacing, -0.015em) !important;
  text-wrap: balance;
}
:where(.sl-body).ad-editorial-luxe h2 {
  font-size: clamp(1.9rem, 4vw, 3rem) !important;
  font-weight: var(--ad-heading-weight, 500) !important;
  line-height: 1.1 !important;
}
:where(.sl-body).ad-editorial-luxe .hero .subhead {
  font-family: var(--font-body);
  font-size: clamp(1.05rem, 1.4vw, 1.2rem);
  line-height: 1.7;
  max-width: 46ch;
  opacity: 0.92;
}

/* ---- 2. IMMENSE WHITESPACE — generous section + header rhythm ---- */
:where(.sl-body).ad-editorial-luxe .section {
  padding: clamp(2.5rem, 5vw, 4.25rem) 0;
}
:where(.sl-body).addens-tight.ad-editorial-luxe .section { padding: clamp(2rem, 4vw, 3.25rem) 0; }
:where(.sl-body).addens-airy.ad-editorial-luxe .section { padding: clamp(3rem, 6vw, 5rem) 0; }
:where(.sl-body).ad-editorial-luxe .section-header {
  max-width: 720px;
  margin-bottom: clamp(3rem, 6vw, 5rem);
}
/* Honours --container-max, keeping 1140 as ITS default. Hard-coding the literal here made this
   rule (0,2,1) out-specify `.container{max-width:var(--container-max,1200px)}` (0,1,0), so meas-wide
   and meas-narrow did NOTHING on every editorial-luxe brand — the composition axis was dead for
   them and would have silently scored as "no divergence".
   This is the THIRD time tonight an archetype rule has quietly beaten a per-brand rule on
   specificity (see the coverage-map band, and the alternate-band !important). ARCHETYPE RULES MUST
   NOT HARD-CODE A VALUE A BRAND TOKEN OWNS — set the token's default instead. */
:where(.sl-body).ad-editorial-luxe .container { max-width: var(--container-max, 1140px); }

/* ---- 3. HAIRLINE RULES BETWEEN SECTIONS (print-rule rhythm) ---- */
:where(.sl-body).ad-editorial-luxe .section + .section {
  border-top: 1px solid var(--c-border) !important;
}
/* If a brand routed alternating tinted bands, suppress them — luxe wants air, not fills. */
/* Same reasoning as the clinical rule below: (0,4,3) already beats the (0,3,2) wash, so no
   !important. With it, this erased any component that paints its own band. */
:where(.sl-body).ad-editorial-luxe.sections-alternate main > section.section:nth-of-type(even):not(.section-tier_comparison):not(.final-cta):not(.section-hub-cta):not(.sec-room):not(.sec-photo):not(.comp-trust-band):not(.block-route-section) {
  background: none;
}

/* ---- 4. MASTHEAD HEADER — serif logo, uppercase letter-spaced nav, hairline ---- */
:where(.sl-body).ad-editorial-luxe .site-header {
  background: var(--c-surface) !important;
  border-bottom: 1px solid var(--c-border) !important;
  -webkit-backdrop-filter: none !important;
  backdrop-filter: none !important;
}
:where(.sl-body).ad-editorial-luxe .site-header .container {
  padding-top: 1.4rem;
  padding-bottom: 1.4rem;
}
:where(.sl-body).ad-editorial-luxe .logo {
  font-family: var(--font-heading);
  font-weight: var(--ad-heading-weight, 500);
  letter-spacing: 0.02em;
}
:where(.sl-body).ad-editorial-luxe .site-nav { gap: 2.1rem; }
:where(.sl-body).ad-editorial-luxe .site-nav a {
  font-family: var(--font-body);
  text-transform: uppercase;
  letter-spacing: 0.18em;
  font-size: 0.74rem;
  font-weight: 600;
  color: var(--c-text);
}
:where(.sl-body).ad-editorial-luxe .site-nav a:hover { color: var(--c-accent); text-decoration: none; }

/* ---- 5. EYEBROWS — small caps with a leading hairline rule, gold ---- */
:where(.sl-body).ad-editorial-luxe .eyebrow, :where(.sl-body).ad-editorial-luxe .hero .eyebrow, :where(.sl-body).ad-editorial-luxe .section-header .eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  color: var(--c-accent);
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.72rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
}
:where(.sl-body).ad-editorial-luxe .eyebrow::before {
  content: '';
  width: 2.4rem;
  height: 1px;
  background: var(--c-accent);
  flex: 0 0 auto;
}
/* Centered section-header eyebrow: rule on both sides so it stays symmetric. */
:where(.sl-body).ad-editorial-luxe .section-header .eyebrow::after {
  content: '';
  width: 2.4rem;
  height: 1px;
  background: var(--c-accent);
  flex: 0 0 auto;
}

/* ---- 6. PHOTO HERO — refined gradient scrim, serif headline bottom-left ---- */
:where(.sl-body).ad-editorial-luxe .hero { align-items: flex-end; }
:where(.sl-body).ad-editorial-luxe .hero-minimal-left, :where(.sl-body).ad-editorial-luxe .hero-lead-form, :where(.sl-body).ad-editorial-luxe .hero-aurora-spotlight { align-items: center; }
:where(.sl-body).ad-editorial-luxe .hero-image-bg::before { filter: saturate(0.96) contrast(1.02) brightness(0.92); }
/* Refined single-direction scrim: deep at the bottom-left where the headline sits,
   clearing toward the top-right. No accent wash — restraint reads premium. */
:where(.sl-body).ad-editorial-luxe .hero-image-bg::after, :where(.sl-body).ad-editorial-luxe .hero-video::after {
  background:
    linear-gradient(7deg,
      color-mix(in srgb, #000 78%, transparent) 0%,
      color-mix(in srgb, #000 50%, transparent) 34%,
      color-mix(in srgb, #000 16%, transparent) 64%,
      transparent 100%) !important;
  background-size: cover !important;
}
:where(.sl-body).ad-editorial-luxe .hero-inner { max-width: 760px; }
:where(.sl-body).ad-editorial-luxe .hero-image-bg .hero-inner, :where(.sl-body).ad-editorial-luxe .hero-video .hero-inner { padding-bottom: 1.5rem; }
/* No-photo hero (gradient/aurora/minimal): a quiet thin gold rule above the
   headline keeps the editorial signature whether or not a photo is present. */
:where(.sl-body).ad-editorial-luxe .hero-gradient, :where(.sl-body).ad-editorial-luxe .hero-aurora-spotlight { background: var(--c-hero-plate) !important; }
:where(.sl-body).ad-editorial-luxe .hero-minimal-left .hero-inner > .eyebrow, :where(.sl-body).ad-editorial-luxe .hero-gradient .hero-inner > .eyebrow, :where(.sl-body).ad-editorial-luxe .hero-aurora-spotlight .hero-inner > .eyebrow { margin-bottom: 1rem; }

/* ---- 7. ACCENT AS THIN RULES / OUTLINE CTAs ONLY — never big filled blocks ---- */
/* Primary CTA: outline, serif-adjacent, letter-spaced — an invitation, not a banner. */
:where(.sl-body).ad-editorial-luxe .btn {
  border-radius: var(--ad-radius, 0px) !important;
  box-shadow: none !important;
  font-family: var(--font-body);
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-size: 0.78rem;
  padding: 0.95rem 1.9rem;
}
:where(.sl-body).ad-editorial-luxe .btn-primary {
  background: transparent !important;
  color: var(--c-text) !important;
  border: 1px solid var(--c-text) !important;
}
:where(.sl-body).ad-editorial-luxe .btn-primary:hover {
  background: var(--c-text) !important;
  color: var(--c-surface) !important;
}
/* In accent/badge accent modes, let the primary CTA carry the gold as an outline. */
:where(.sl-body).adacc-badge.ad-editorial-luxe .btn-primary, :where(.sl-body).ad-editorial-luxe.cta-accent .btn-primary {
  background: transparent !important;
  color: var(--c-accent) !important;
  border: 1px solid var(--c-accent) !important;
}
:where(.sl-body).adacc-badge.ad-editorial-luxe .btn-primary:hover, :where(.sl-body).ad-editorial-luxe.cta-accent .btn-primary:hover {
  background: var(--c-accent) !important;
  color: var(--c-primary-dark) !important;
  filter: none !important;
}
:where(.sl-body).ad-editorial-luxe .btn-secondary {
  background: transparent !important;
  color: var(--c-accent) !important;
  border: 1px solid var(--c-accent) !important;
}
:where(.sl-body).ad-editorial-luxe .btn-secondary:hover {
  background: var(--c-accent) !important;
  color: var(--c-primary-dark) !important;
}
/* CTAs sitting on a dark hero/CTA band read in warm gold outline. */
:where(.sl-body).ad-editorial-luxe .hero-image-bg .btn-primary, :where(.sl-body).ad-editorial-luxe .hero-video .btn-primary, :where(.sl-body).ad-editorial-luxe .hero-gradient .btn-primary, :where(.sl-body).ad-editorial-luxe .hero-aurora-spotlight .btn-primary, :where(.sl-body).ad-editorial-luxe .final-cta .btn-primary {
  color: var(--c-on-dark) !important;
  border-color: var(--c-accent) !important;
}
:where(.sl-body).ad-editorial-luxe .hero-image-bg .btn-primary:hover, :where(.sl-body).ad-editorial-luxe .hero-video .btn-primary:hover, :where(.sl-body).ad-editorial-luxe .hero-gradient .btn-primary:hover, :where(.sl-body).ad-editorial-luxe .hero-aurora-spotlight .btn-primary:hover, :where(.sl-body).ad-editorial-luxe .final-cta .btn-primary:hover {
  background: var(--c-accent) !important;
  color: var(--c-primary-dark) !important;
}

/* ---- 8. CARDS — flat, hairline, lots of air, NO heavy shadow ---- */
/* Refined-but-SUBSTANTIAL editorial cards (Peach-IV clean, not borderless-empty). A real surface
   with a thin border, a small radius, and restrained depth — elegant restraint, never a thin shell.
   :not([class*=" comp-"]) added 2026-08-09: these !importants outrank a composed section's card
   rules at ANY specificity, so on Halo comp-panel painted its dark container, this rule forced the
   card inside it back to WHITE, and panel's surface-white ink landed on it at 1:1 — invisible, 34
   errors, caught by CI. An art direction paints DEFAULT furniture; a section a treatment has
   claimed keeps the treatment's furniture (same precedent as the steps-connected rule at :762 and
   dark-luxe's FAQ carve-out). */
:where(.sl-body).ad-editorial-luxe main > section.section:not([class*=" comp-"]) .card, :where(.sl-body).ad-editorial-luxe main > section.section:not([class*=" comp-"]) .feature-card, :where(.sl-body).ad-editorial-luxe main > section.section:not([class*=" comp-"]) .review-card {
  background: var(--c-surface) !important;
  border: 1px solid color-mix(in srgb, var(--c-text) 11%, transparent) !important;
  border-radius: 4px !important;
  box-shadow: 0 1px 0 rgba(255,255,255,0.55) inset, 0 14px 34px -22px rgba(16,24,32,0.20) !important;
  padding: 1.9rem 1.75rem !important;
}
:where(.sl-body).ad-editorial-luxe .cards-center .card:hover, :where(.sl-body).ad-editorial-luxe .grid .card:hover {
  transform: translateY(-3px) !important;
  border-color: color-mix(in srgb, var(--c-accent) 40%, var(--c-border)) !important;
  box-shadow: 0 1px 0 rgba(255,255,255,0.55) inset, 0 22px 44px -22px rgba(16,24,32,0.28) !important;
}
:where(.sl-body).ad-editorial-luxe .feature-card h3, :where(.sl-body).ad-editorial-luxe .card h3 {
  font-family: var(--font-heading);
  font-weight: var(--ad-heading-weight, 500);
  font-size: 1.3rem;
  letter-spacing: 0;
}
/* Feature icon: a quiet outlined gold mark, not a filled chip. */
:where(.sl-body).ad-editorial-luxe .feature-ic, :where(.sl-body).ad-editorial-luxe .auto-card .feature-ic {
  background: transparent !important;
  box-shadow: none !important;
  width: auto !important;
  height: auto !important;
  border-radius: 0 !important;
  color: var(--c-accent) !important;
  margin-bottom: 1rem !important;
}
:where(.sl-body).ad-editorial-luxe .feature-ic svg { width: 30px; height: 30px; stroke-width: 1.3; }

/* ---- 9. STATS — restrained: serif numerals on the surface, hairline separators ---- */
:where(.sl-body).ad-editorial-luxe .section-stats {
  background: var(--c-surface) !important;
  border-top: 1px solid var(--c-border);
  border-bottom: 1px solid var(--c-border);
}
:where(.sl-body).ad-editorial-luxe .section-stats::before { display: none !important; }
:where(.sl-body).ad-editorial-luxe .section-stats h2 { color: var(--c-text) !important; }
:where(.sl-body).ad-editorial-luxe .stat-value {
  font-family: var(--font-heading);
  font-weight: var(--ad-heading-weight, 500);
  color: var(--c-text) !important;
  font-size: clamp(2.6rem, 6vw, 4.4rem);
  letter-spacing: -0.02em;
}
:where(.sl-body).ad-editorial-luxe .section-stats .stat-value { color: var(--c-text) !important; }
:where(.sl-body).ad-editorial-luxe .stat-label {
  color: var(--c-text-muted) !important;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  font-size: 0.74rem !important;
  opacity: 1 !important;
}
:where(.sl-body).ad-editorial-luxe .section-stats .stat-label { color: var(--c-text-muted) !important; }
:where(.sl-body).ad-editorial-luxe .stat-ic { display: none; }

/* ---- 10. PACKAGES — editorial brands use the standard bag CAROUSEL/GRID with real bag imagery,
   NOT a bagless printed-menu. The old menu-mode override (stripped bags + card chrome into thin
   text rows) was the editorial 'thinness'; the vetted catalog cut it. Elegance now comes from the
   serif type + color + the substantial card material above, with the bags fully visible. ---- */

/* ---- 11. REVIEWS — large serif pull-quote, gold rule, no card chrome ---- */
:where(.sl-body).ad-editorial-luxe .review-quote {
  font-family: var(--font-heading);
  font-style: normal;
  font-weight: var(--ad-heading-weight, 500);
  font-size: 1.3rem;
  line-height: 1.5;
  color: var(--c-text);
}
:where(.sl-body).ad-editorial-luxe .review-card .stars { color: var(--c-accent); font-size: 0.95rem; }
:where(.sl-body).ad-editorial-luxe .review-by { color: var(--c-text-muted); font-size: 0.85rem; }
:where(.sl-body).ad-editorial-luxe .review-by .review-initial { background: transparent; color: var(--c-accent); border: 1px solid var(--c-accent); }

/* ---- 12. STEPS / FAQ — quiet, outlined, hairline ---- */
:where(.sl-body).ad-editorial-luxe .step-badge {
  background: transparent !important;
  color: var(--c-accent) !important;
  border: 1px solid var(--c-accent);
  font-family: var(--font-heading);
  font-weight: var(--ad-heading-weight, 500);
}
:where(.sl-body).ad-editorial-luxe .steps-connected::before { background: var(--c-border); opacity: 1; height: 1px; }
:where(.sl-body).ad-editorial-luxe .faq-item { border-bottom: 1px solid var(--c-border); }
:where(.sl-body).ad-editorial-luxe .faq-item > summary {
  font-family: var(--font-heading);
  font-weight: var(--ad-heading-weight, 500);
  font-size: 1.15rem;
}
:where(.sl-body).ad-editorial-luxe .faq-item .faq-chevron { color: var(--c-accent); }
:where(.sl-body).ad-editorial-luxe .area-chip {
  background: transparent;
  border: 1px solid var(--c-border);
  border-radius: var(--ad-radius, 0px);
  letter-spacing: 0.04em;
}

/* ---- 13. FINAL CTA — quiet dark band, gold hairline accent (no big glow) ---- */
:where(.sl-body).ad-editorial-luxe .final-cta {
  background: var(--c-hero-plate) !important;
  border-top: 1px solid color-mix(in srgb, var(--c-accent) 50%, transparent);
  padding: clamp(4rem, 9vw, 7rem) 1.5rem;
}
:where(.sl-body).ad-editorial-luxe .final-cta::after { opacity: 0.08 !important; }
:where(.sl-body).ad-editorial-luxe .final-cta::before { display: none !important; }
:where(.sl-body).ad-editorial-luxe .final-cta h2 {
  font-family: var(--font-heading);
  font-weight: var(--ad-heading-weight, 500);
  font-size: clamp(2.2rem, 5vw, 3.6rem);
}

/* ---- 14. TRUST ROW — hairline-separated, gold outline marks ---- */
:where(.sl-body).ad-editorial-luxe .trust-row-item .trust-ic {
  background: transparent;
  border: 1px solid var(--c-accent);
  color: var(--c-accent);
}
:where(.sl-body).ad-editorial-luxe .trust-row-item span {
  text-transform: uppercase;
  letter-spacing: 0.1em;
  font-size: 0.78rem;
  font-weight: 600;
}

/* ---- 15. MOTION — gentle fades only, reduced-motion safe ---- */
@media (prefers-reduced-motion: no-preference) {
  @keyframes adLuxeFade { from { opacity: 0; transform: translateY(12px); } to { opacity: 1; transform: none; } }
  :where(.sl-body).ad-editorial-luxe .hero-inner > * { animation: adLuxeFade 1s cubic-bezier(.22,.61,.36,1) both; }
  :where(.sl-body).ad-editorial-luxe .hero-inner > .eyebrow { animation-delay: .05s; }
  :where(.sl-body).ad-editorial-luxe .hero-inner > h1 { animation-delay: .18s; }
  :where(.sl-body).ad-editorial-luxe .hero-inner > .subhead { animation-delay: .34s; }
  :where(.sl-body).ad-editorial-luxe .hero-inner > .cta-row { animation-delay: .5s; }
  @supports (animation-timeline: view()) {
    :where(.sl-body).ad-editorial-luxe main > section:not(.hero) { animation: adLuxeFade 1s linear both; animation-timeline: view(); animation-range: entry 4% cover 16%; }
  }
}
@media (prefers-reduced-motion: reduce) {
  :where(.sl-body).ad-editorial-luxe .hero-inner > *, :where(.sl-body).ad-editorial-luxe main > section:not(.hero) { animation: none !important; }
}

/* ---- 16. MOBILE SAFETY — keep the serif headline from overflowing at 390px ---- */
@media (max-width: 480px) {
  :where(.sl-body).ad-editorial-luxe .hero h1 {
    font-size: clamp(2.1rem, calc(9vw * var(--ad-h1-scale, 1)), 3rem) !important;
    line-height: 1.08 !important;
    word-break: break-word;
    hyphens: auto;
  }
  :where(.sl-body).ad-editorial-luxe .hero { align-items: center; }
  :where(.sl-body).ad-editorial-luxe .site-nav { gap: 1.1rem; }
  :where(.sl-body).ad-editorial-luxe .section { padding: clamp(2.75rem, 12vw, 4rem) 0; }
  :where(.sl-body).ad-editorial-luxe .section-header { margin-bottom: 2.25rem; }
  :where(.sl-body).ad-editorial-luxe .stat-value { font-size: clamp(2.2rem, 12vw, 3rem); }
}

/* ===== BOLD-MODERN ===== */
/* ============================================================================
   ART DIRECTION — BOLD MODERN  (scope: body.ad-bold-modern)
   A confident modern national DTC health brand: oversized 800-weight sans
   headline with tight tracking, accent used boldly (filled pill CTAs,
   primary->accent gradients, accent word-highlight), a HUGE signature
   proof-stat moment, rounded confident shapes, alternating tinted bands,
   lively scroll-reveal motion, and soft accent-tinted card shadows.
   100% brand-token-driven; mobile-safe; motion gated by reduced-motion.
   ============================================================================ */

/* ---- 0. ARCHETYPE TOKENS (read the AD vars, give bold-modern defaults) ---- */
:where(.sl-body).ad-bold-modern {
  --bm-weight: var(--ad-heading-weight, 800);
  --bm-track: var(--ad-letter-spacing, -0.03em);
  --bm-radius: var(--ad-radius, 20px);
  --bm-h1-scale: var(--ad-h1-scale, 1);
  /* a vivid signature gradient reused across CTAs, highlights and the stat band */
  --bm-grad: linear-gradient(105deg, var(--c-primary), var(--c-accent));
  --bm-shadow-accent: 0 18px 38px -14px color-mix(in srgb, var(--c-accent) 55%, transparent);
}

/* ---- 1. OVERSIZED, BOLD, TIGHT HEADLINES ---- */
:where(.sl-body).ad-bold-modern .hero h1 {
  font-weight: var(--bm-weight) !important;
  letter-spacing: var(--bm-track) !important;
  /* clamp keeps it from overflowing 390px; vw term carries the "oversized" feel,
     and --bm-h1-scale lets a brand dial it up further without breaking mobile. */
  font-size: calc(clamp(2.55rem, 9vw, 6rem) * var(--bm-h1-scale)) !important;
  line-height: 0.96 !important;
  text-wrap: balance;
}
:where(.sl-body).ad-bold-modern h2, :where(.sl-body).ad-bold-modern .section-header h2 {
  font-weight: var(--bm-weight) !important;
  letter-spacing: var(--bm-track) !important;
  line-height: 1.03;
}
:where(.sl-body).ad-bold-modern h3 { font-weight: 700; letter-spacing: -0.01em; }

/* Accent word-highlight inside the headline: a <strong>/<em>/<mark> in the H1
   gets a gradient text fill so the key promise pops in the brand accent. */
:where(.sl-body).ad-bold-modern .hero h1 strong, :where(.sl-body).ad-bold-modern .hero h1 em, :where(.sl-body).ad-bold-modern .hero h1 mark {
  font-style: normal;
  background: var(--bm-grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}

/* Eyebrows: punchy bold caps, accent-tinted pill so they read as a brand chip. */
:where(.sl-body).ad-bold-modern .eyebrow, :where(.sl-body).ad-bold-modern .hero .eyebrow, :where(.sl-body).ad-bold-modern .section-header .eyebrow {
  display: inline-block;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-size: 0.78rem;
  /* --c-accent-ink, never raw --c-accent. A brand accent is chosen to look good as a FILL; as
     0.78rem INK it has to clear AA, which is what accent-ink is derived for — and it returns the
     accent UNCHANGED when the accent already passes, so every compliant brand is byte-identical.
     Pure IV's #FF9B02 measured 1.9:1 as ink on its own 14% pill ("EFFECTIVELY INVISIBLE" per the
     gate) on the eyebrow of every section of every page. Same class of defect as the coverage-band
     lane bugs: written against one brand's dark accent, never re-checked when a light-accent brand
     adopted the archetype. */
  color: var(--c-accent-ink, var(--c-accent));
}
/* On light section headers, give the eyebrow a soft tinted pill. */
:where(.sl-body).ad-bold-modern .section-header .eyebrow {
  padding: 0.35rem 0.85rem;
  border-radius: 999px;
  background: color-mix(in srgb, var(--c-accent) 14%, transparent);
}

/* ---- 2. ACCENT, USED BOLDLY: filled pill CTAs + gradient primary ---- */
:where(.sl-body).ad-bold-modern .btn {
  border-radius: 999px !important;       /* confident full pills */
  font-weight: 700;
  letter-spacing: 0.005em;
}
:where(.sl-body).ad-bold-modern .btn-primary {
  background: var(--bm-grad) !important;
  color: #fff !important;
  border-color: transparent !important;
  box-shadow: var(--bm-shadow-accent);
}
:where(.sl-body).ad-bold-modern .btn-primary:hover {
  filter: brightness(1.05) saturate(1.05);
  box-shadow: 0 22px 46px -14px color-mix(in srgb, var(--c-accent) 62%, transparent);
}
/* badge accent-usage tier: lean even harder on the accent, flat fill */
:where(.sl-body).ad-bold-modern.adacc-badge .btn-primary {
  background: var(--c-accent) !important;
  color: var(--c-primary-dark) !important;
}
/* sparing accent-usage tier: keep CTA on primary, accent only as the glow/edge */
:where(.sl-body).ad-bold-modern.adacc-sparing .btn-primary {
  background: var(--c-primary) !important;
  color: var(--c-on-primary) !important;
  box-shadow: 0 12px 30px -12px color-mix(in srgb, var(--c-primary) 55%, transparent);
}
:where(.sl-body).ad-bold-modern .btn-accent, :where(.sl-body).ad-bold-modern .cta-accent .btn-primary {
  background: var(--c-accent) !important;
  color: var(--c-primary-dark) !important;
  border-color: transparent !important;
  box-shadow: var(--bm-shadow-accent);
}
/* Secondary: confident outline pill that picks up the accent on hover. */
:where(.sl-body).ad-bold-modern .btn-secondary {
  border-width: 2px;
  font-weight: 700;
}
:where(.sl-body).ad-bold-modern .btn-secondary:hover {
  background: var(--c-accent);
  color: var(--c-primary-dark);
  border-color: var(--c-accent);
}

/* ---- 3. HERO: works WITH or WITHOUT a photo ---- */
/* No-photo heroes (gradient/aurora/minimal-left): a vivid primary->accent wash
   so the hero is energetic even with zero imagery. */
:where(.sl-body).ad-bold-modern .hero-gradient {
  background: linear-gradient(120deg, var(--c-primary-dark), var(--c-primary) 48%, var(--c-accent) 130%) !important;
}
:where(.sl-body).ad-bold-modern .hero-aurora-spotlight::after {
  background: radial-gradient(circle, color-mix(in srgb, var(--c-accent) 60%, transparent), transparent 60%) !important;
}
/* minimal-left: keep it text-forward but warm the eyebrow rule + add an accent kicker bar */
:where(.sl-body).ad-bold-modern .hero-minimal-left .hero-inner { position: relative; }
:where(.sl-body).ad-bold-modern .hero-minimal-left .hero-inner::before {
  content: ''; display: block; width: 56px; height: 5px; border-radius: 999px;
  background: var(--bm-grad); margin-bottom: 1.25rem;
}
/* Photo heroes: warmer accent glow in the scrim so even a photo reads as THIS brand. */
:where(.sl-body).ad-bold-modern .hero-image-bg::after, :where(.sl-body).ad-bold-modern .hero-video::after {
  background:
    radial-gradient(50% 64% at 82% 18%, color-mix(in srgb, var(--c-accent) 58%, transparent), transparent 62%),
    linear-gradient(98deg, color-mix(in srgb, var(--c-primary-dark) 94%, transparent) 0%, color-mix(in srgb, var(--c-primary-dark) 64%, transparent) 42%, color-mix(in srgb, var(--c-primary-dark) 22%, transparent) 100%) !important;
}
:where(.sl-body).ad-bold-modern .hero .subhead { font-size: clamp(1.08rem, 1.6vw, 1.3rem); line-height: 1.55; }
/* Hero rating pill: rounded, bold, accent stars (base already styles stars via --c-accent). */
:where(.sl-body).ad-bold-modern .hero-rating { border-radius: 999px; font-weight: 700; }

/* ---- 4. ALTERNATING TINTED SECTION BANDS ---- */
:where(.sl-body).ad-bold-modern .section + .section { border-top: none; }
:where(.sl-body).ad-bold-modern main > section.section:nth-of-type(even):not(.section-tier_comparison):not(.final-cta):not(.section-hub-cta):not(.sec-room):not(.sec-photo):not(.comp-trust-band):not(.block-route-section) {
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--c-accent) 10%, var(--c-surface)) 0%,
    color-mix(in srgb, var(--c-accent) 3%, var(--c-surface)) 78%);
}
/* Every 4th section: a richer primary->accent diagonal wash for extra rhythm variety. */
:where(.sl-body).ad-bold-modern main > section.section:nth-of-type(4n):not(.final-cta):not(.section-hub-cta):not(.sec-room):not(.sec-photo):not(.comp-trust-band):not(.block-route-section) {
  background: linear-gradient(135deg,
    color-mix(in srgb, var(--c-primary) 14%, var(--c-surface)) 0%,
    color-mix(in srgb, var(--c-accent) 10%, var(--c-surface)) 100%);
}

/* ---- 5. ROUNDED, CONFIDENT CARDS with a soft ACCENT-TINTED shadow ---- */
:where(.sl-body).ad-bold-modern .card, :where(.sl-body).ad-bold-modern .pkg-card, :where(.sl-body).ad-bold-modern .review-card, :where(.sl-body).ad-bold-modern .step-card, :where(.sl-body).ad-bold-modern .auto-card {
  border-radius: var(--bm-radius);
}
:where(.sl-body).ad-bold-modern .card, :where(.sl-body).ad-bold-modern .review-card {
  border: 1px solid color-mix(in srgb, var(--c-accent) 12%, var(--c-border));
  box-shadow:
    0 1px 0 rgba(255,255,255,0.7) inset,
    0 20px 42px -20px color-mix(in srgb, var(--c-accent) 30%, rgba(16,24,32,0.22));
  transition: transform .2s ease, box-shadow .2s ease;
}
:where(.sl-body).ad-bold-modern .cards-center .card:hover, :where(.sl-body).ad-bold-modern .grid .card:hover, :where(.sl-body).ad-bold-modern .cards-center .review-card:hover {
  transform: translateY(-5px);
  box-shadow:
    0 1px 0 rgba(255,255,255,0.7) inset,
    0 30px 58px -22px color-mix(in srgb, var(--c-accent) 42%, rgba(16,24,32,0.3));
}
/* Bold rounded accent feature-icon badges */
:where(.sl-body).ad-bold-modern .feature-ic {
  display: inline-grid; place-items: center;
  width: 62px; height: 62px; border-radius: 18px; margin-bottom: 1.1rem;
  background: var(--bm-grad);
  color: #fff;
  box-shadow: var(--bm-shadow-accent);
}
:where(.sl-body).ad-bold-modern .feature-ic svg { width: 28px; height: 28px; }
:where(.sl-body).ad-bold-modern .step-badge { background: var(--bm-grad); color: #fff; }

/* ---- 6. THE SIGNATURE PROOF-STAT MOMENT — enormous gradient numerals ---- */
:where(.sl-body).ad-bold-modern .section-stats {
  padding: clamp(4rem, 9vw, 7rem) 0;
}
:where(.sl-body).ad-bold-modern .stats-band { gap: clamp(2rem, 6vw, 5rem); }
:where(.sl-body).ad-bold-modern .stat-value {
  font-weight: 800;
  letter-spacing: -0.04em;
  line-height: 0.92;
  font-size: clamp(3.4rem, 10vw, 6.5rem) !important;
  /* accent -> light gradient text fill against the dark stats band */
  background: linear-gradient(135deg, var(--c-accent), color-mix(in srgb, var(--c-accent) 30%, #fff));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent !important;
  -webkit-text-fill-color: transparent;
}
:where(.sl-body).ad-bold-modern .stat-label {
  font-weight: 700;
  font-size: clamp(0.95rem, 1.4vw, 1.1rem);
  letter-spacing: 0.03em;
  opacity: 0.92;
}
:where(.sl-body).ad-bold-modern .stat-ic { color: var(--c-accent); }

/* ---- 7. PRICING — accent-edged pill cards ---- */
:where(.sl-body).ad-bold-modern .pkg-card {
  border-radius: var(--bm-radius);
}
/* NOTE: arrow chrome is now owned by the per-brand carousel_art dial (.pkg-art-*), so the old
   archetype-level .pkg-arrow override was removed to keep that dial authoritative. */

/* ---- 8. FINAL CTA — gradient band, oversized ---- */
:where(.sl-body).ad-bold-modern .final-cta {
  background: var(--bm-grad) !important;
  padding: clamp(4rem, 9vw, 7rem) 1.5rem;
}
:where(.sl-body).ad-bold-modern .final-cta::after { opacity: 0; } /* the band is already a gradient */
:where(.sl-body).ad-bold-modern .final-cta h2 {
  font-size: clamp(2.5rem, 6vw, 4.2rem);
  font-weight: 800;
  letter-spacing: -0.03em;
}
/* On the gradient CTA, the primary button flips to a solid surface chip for contrast. */
:where(.sl-body).ad-bold-modern .final-cta .btn-primary {
  background: var(--c-light-stock) !important;
  color: var(--c-primary-dark) !important;
}
:where(.sl-body).ad-bold-modern .final-cta .btn-secondary {
  color: var(--c-on-dark) !important;
  border-color: var(--c-on-dark) !important;
}

/* ---- 9. FAQ + chips: rounded, accent affordances ---- */
:where(.sl-body).ad-bold-modern .faq-item .faq-chevron { color: var(--c-accent); }
:where(.sl-body).ad-bold-modern .area-chip { border-radius: 999px; font-weight: 600; }

/* ---- 10. DENSITY tiers (addens-*) — let the brand breathe or tighten ---- */
:where(.sl-body).ad-bold-modern.addens-airy .section { padding: clamp(3rem, 6vw, 5rem) 0; }
:where(.sl-body).ad-bold-modern.addens-airy .section-header { margin-bottom: 3.25rem; }
:where(.sl-body).ad-bold-modern.addens-tight .section { padding: clamp(2rem, 4vw, 3.25rem) 0; }

/* ---- 11. LIVELY MOTION — staggered hero rise + scroll reveal (gated) ---- */
@media (prefers-reduced-motion: no-preference) {
  @keyframes bmRise { from { opacity: 0; transform: translateY(30px); } to { opacity: 1; transform: none; } }
  :where(.sl-body).ad-bold-modern .hero-inner > * { animation: bmRise .8s cubic-bezier(.2,.7,.2,1) both; }
  :where(.sl-body).ad-bold-modern .hero-inner > .eyebrow { animation-delay: .04s; }
  :where(.sl-body).ad-bold-modern .hero-inner > h1 { animation-delay: .12s; }
  :where(.sl-body).ad-bold-modern .hero-inner > .subhead { animation-delay: .26s; }
  :where(.sl-body).ad-bold-modern .hero-inner > .hero-rating { animation-delay: .36s; }
  :where(.sl-body).ad-bold-modern .hero-inner > .cta-row { animation-delay: .46s; }

  @supports (animation-timeline: view()) {
    @keyframes bmReveal { from { opacity: 0; transform: translateY(40px) scale(0.985); } to { opacity: 1; transform: none; } }
    :where(.sl-body).ad-bold-modern main > section:not(.hero) {
      animation: bmReveal linear both;
      animation-timeline: view();
      animation-range: entry 3% cover 22%;
    }
    /* stat values pop in slightly faster/snappier for the signature moment */
    :where(.sl-body).ad-bold-modern .stat-value {
      animation: bmReveal linear both;
      animation-timeline: view();
      animation-range: entry 0% cover 30%;
    }
  }
}
@media (prefers-reduced-motion: reduce) {
  :where(.sl-body).ad-bold-modern .hero-inner > *, :where(.sl-body).ad-bold-modern main > section:not(.hero), :where(.sl-body).ad-bold-modern .stat-value { animation: none !important; }
}

/* ---- 12. MOBILE SAFETY (<=480px) — never let the oversized type overflow ---- */
@media (max-width: 480px) {
  :where(.sl-body).ad-bold-modern .hero h1 { font-size: calc(clamp(2.2rem, 11vw, 3.1rem) * var(--bm-h1-scale)) !important; line-height: 1.02 !important; }
  :where(.sl-body).ad-bold-modern .stat-value { font-size: clamp(3rem, 17vw, 4rem) !important; }
  :where(.sl-body).ad-bold-modern .final-cta h2 { font-size: clamp(2rem, 9vw, 2.6rem); }
  :where(.sl-body).ad-bold-modern .hero .btn, :where(.sl-body).ad-bold-modern .final-cta .btn { width: 100%; text-align: center; }
}

/* ===== TYPOGRAPHIC-CLINICAL ===== */
/* ============================================================================
   ART DIRECTION — TYPOGRAPHIC CLINICAL
   For no-photo brands with a cool/muted distinctive accent (e.g. deep teal +
   olive). Type-led, calm, precise, "expensive clinic." The hero becomes a deep
   --c-primary field with a soft aurora/mesh glow + faint grid behind a MASSIVE
   sans headline; sections below are airy, hairline-separated white. Accent is
   used sparingly as kickers/badges/underlines. All scoped under .ad-typographic-clinical.
   Brand-token-driven (works for ANY brand routed here), mobile-safe, a11y contrast.
   ============================================================================ */

/* ---- Global type tone: tighter tracking + heavier headings, calm body ---- */
:where(.sl-body).ad-typographic-clinical {
  --adtc-h1: calc(clamp(2.7rem, 8.2vw, 5.6rem) * var(--ad-h1-scale, 1.18));
  --adtc-glow-a: color-mix(in srgb, var(--c-accent) 60%, transparent);
  --adtc-glow-p: color-mix(in srgb, var(--c-primary) 72%, transparent);
}
:where(.sl-body).ad-typographic-clinical h1, :where(.sl-body).ad-typographic-clinical h2, :where(.sl-body).ad-typographic-clinical h3 {
  font-weight: var(--ad-heading-weight, 800);
  letter-spacing: var(--ad-letter-spacing, -0.03em);
}
:where(.sl-body).ad-typographic-clinical .section-header { max-width: 820px; }

/* ============================================================================
   HERO — deep primary field, aurora/mesh glow, faint grid, massive white type.
   Reads well WITH or WITHOUT a photo: any of the no-photo variants get the field;
   if a photo IS present (image-bg/video/split) we keep the photo but lay the same
   calm grid + accent kicker over it so it still reads as this archetype.
   ============================================================================ */
:where(.sl-body).ad-typographic-clinical .hero, :where(.sl-body).ad-typographic-clinical .hero-aurora-spotlight, :where(.sl-body).ad-typographic-clinical .hero-minimal-left, :where(.sl-body).ad-typographic-clinical .hero-gradient {
  background: var(--c-room) !important;
  color: var(--c-on-room);
  /* Height: the one hero rule — `.sl-hero-box` in this file. This said
     `min-height: clamp(520px, 78vh, 760px)`, and because a theme selector outranks `.hero` it
     quietly put the 760px cap back on for this one theme after every other cap was removed. A
     theme decides COLOUR and ORNAMENT here; it does not decide how tall a hero is. */
  isolation: isolate;
}

/* layer 1 — faint precision grid (kicker for "clinical" structure) */
:where(.sl-body).ad-typographic-clinical .hero::before {
  content: '';
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background-image:
    linear-gradient(rgba(255,255,255,0.045) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,0.045) 1px, transparent 1px);
  background-size: 46px 46px;
  /* fade the grid out toward the bottom-right so it stays a whisper */
  -webkit-mask-image: radial-gradient(120% 120% at 0% 0%, #000 35%, transparent 88%);
  mask-image: radial-gradient(120% 120% at 0% 0%, #000 35%, transparent 88%);
}

/* layer 2 — soft aurora/mesh glow: accent bloom + primary bloom, heavily blurred */
:where(.sl-body).ad-typographic-clinical .hero::after {
  content: '';
  position: absolute; inset: -10%; z-index: 0; pointer-events: none;
  background:
    radial-gradient(38% 46% at 78% 16%, var(--adtc-glow-a), transparent 64%),
    radial-gradient(52% 60% at 12% 92%, var(--adtc-glow-p), transparent 66%),
    radial-gradient(40% 44% at 96% 88%, color-mix(in srgb, var(--c-accent) 34%, transparent), transparent 62%);
  filter: blur(58px) saturate(1.15);
  opacity: 0.95;
}

/* If a real photo hero is routed here, keep its image but recolor the scrim to the
   deep primary field so the aurora + grid still dominate and type stays legible. */
:where(.sl-body).ad-typographic-clinical .hero-image-bg::after, :where(.sl-body).ad-typographic-clinical .hero-video::after {
  background:
    radial-gradient(40% 50% at 80% 16%, var(--adtc-glow-a), transparent 62%),
    linear-gradient(92deg,
      color-mix(in srgb, var(--c-primary) 94%, transparent) 0%,
      color-mix(in srgb, var(--c-primary) 70%, transparent) 46%,
      color-mix(in srgb, var(--c-primary) 30%, transparent) 100%) !important;
  background-size: cover, cover !important;
}

/* content above the layers */
:where(.sl-body).ad-typographic-clinical .hero-inner, :where(.sl-body).ad-typographic-clinical .hero .container > * { position: relative; z-index: 2; }
:where(.sl-body).ad-typographic-clinical .hero-inner { max-width: 940px; }

/* MASSIVE type — the whole point of the archetype */
:where(.sl-body).ad-typographic-clinical .hero h1 {
  color: var(--c-on-room) !important;
  font-size: var(--adtc-h1);
  line-height: 0.97;
  letter-spacing: clamp(-0.05em, var(--ad-letter-spacing, -0.035em), -0.025em);
  font-weight: 800;
  text-wrap: balance;
  max-width: 16ch;
  /* hairline optical refinement so huge white type reads crisp on the field */
  text-shadow: 0 1px 40px color-mix(in srgb, var(--c-primary) 60%, transparent);
}
:where(.sl-body).ad-typographic-clinical .hero .subhead, :where(.sl-body).ad-typographic-clinical .hero p {
  color: color-mix(in srgb, var(--c-surface) 86%, var(--c-primary)) !important;
  font-size: clamp(1.05rem, 1.5vw, 1.28rem);
  max-width: 56ch;
}

/* accent kicker/eyebrow — a small badge with a tasteful accent dot */
:where(.sl-body).ad-typographic-clinical .hero .eyebrow {
  display: inline-flex; align-items: center; gap: 0.55rem;
  color: color-mix(in srgb, var(--c-accent) 88%, #fff);
  font-weight: 700; letter-spacing: 0.2em; text-transform: uppercase;
  font-size: 0.78rem;
}
:where(.sl-body).ad-typographic-clinical .hero .eyebrow::before {
  content: ''; width: 7px; height: 7px; border-radius: 50%;
  background: var(--c-accent);
  box-shadow: 0 0 0 4px color-mix(in srgb, var(--c-accent) 28%, transparent);
}

/* hero rating pill — glassy, accent stars, on the dark field */
:where(.sl-body).ad-typographic-clinical .hero .hero-rating {
  background: rgba(255,255,255,0.10);
  border: 1px solid rgba(255,255,255,0.22);
  color: var(--c-on-room);
}
:where(.sl-body).ad-typographic-clinical .hero .hero-rating .stars { color: var(--c-accent); }

/* buttons on the dark hero field */
:where(.sl-body).ad-typographic-clinical .hero .btn-primary {
  background: var(--c-light-stock); color: var(--c-primary);
  border-color: var(--c-light-stock);
}
:where(.sl-body).ad-typographic-clinical .hero .btn-primary:hover {
  background: color-mix(in srgb, var(--c-surface) 90%, var(--c-accent));
  color: var(--c-primary);
}
:where(.sl-body).ad-typographic-clinical .hero .btn-secondary {
  background: transparent; color: var(--c-on-room);
  border-color: rgba(255,255,255,0.5);
}
:where(.sl-body).ad-typographic-clinical .hero .btn-secondary:hover {
  background: rgba(255,255,255,0.12); color: var(--c-on-room); border-color: var(--c-on-room);
}

/* ============================================================================
   HEADER — quiet, clinical. Hairline rule, primary text, accent only on hover.
   ============================================================================ */
:where(.sl-body).ad-typographic-clinical .site-header {
  border-bottom: 1px solid var(--c-border);
}
:where(.sl-body).ad-typographic-clinical .site-nav a {
  color: var(--c-text); font-weight: 500; letter-spacing: 0.01em;
  position: relative;
}
/* precise accent underline on hover — a clinical, type-led signature */
:where(.sl-body).ad-typographic-clinical .site-nav a::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: -4px; height: 2px;
  background: var(--c-accent); transform: scaleX(0); transform-origin: left;
  transition: transform .22s ease;
}
:where(.sl-body).ad-typographic-clinical .site-nav a:hover { text-decoration: none; }
:where(.sl-body).ad-typographic-clinical .site-nav a:hover::after { transform: scaleX(1); }

/* ============================================================================
   SECTIONS BELOW — calm white, generous, HAIRLINE-separated (override tints).
   ============================================================================ */
:where(.sl-body).ad-typographic-clinical main > section.section { background: var(--c-surface); }
:where(.sl-body).ad-typographic-clinical .section + .section { border-top: 1px solid var(--c-border) !important; }
/* Kill the alternate-band wash if it's also on — clinical wants clean hairlines.
   NO !important, ON PURPOSE. This selector is (0,4,3) and the wash it cancels
   (.sections-alternate main > section.section:nth-of-type(even)) is (0,3,2), so it already
   wins on specificity alone. The !important that used to be here ALSO beat any component
   that paints its OWN band — it silently erased the coverage map's dark navy panel while
   the map's uncontested `color:#fff` survived, leaving an entire section of white text on
   a white background at contrast 1.0. A blanket band rule must out-specify the wash, never
   out-shout a component. Enforced by R15 in scripts/visual-lint.mjs. */
:where(.sl-body).ad-typographic-clinical.sections-alternate main > section.section:nth-of-type(even):not(.section-tier_comparison):not(.final-cta):not(.section-hub-cta):not(.sec-room):not(.sec-photo):not(.comp-trust-band):not(.block-route-section) {
  background: var(--c-surface);
}
:where(.sl-body).ad-typographic-clinical .section { padding: clamp(2.5rem, 5vw, 4.25rem) 0; }

/* section eyebrows: small accent kicker, centered, with a short underline tick */
:where(.sl-body).ad-typographic-clinical .section-header .eyebrow, :where(.sl-body).ad-typographic-clinical .eyebrow {
  color: var(--c-accent); font-weight: 700; letter-spacing: 0.2em;
  text-transform: uppercase; font-size: 0.78rem;
}
:where(.sl-body).ad-typographic-clinical .section-header .eyebrow {
  display: inline-block; padding-bottom: 0.55rem; position: relative;
}
:where(.sl-body).ad-typographic-clinical .section-header .eyebrow::after {
  content: ''; position: absolute; left: 50%; bottom: 0; transform: translateX(-50%);
  width: 26px; height: 2px; background: var(--c-accent);
}
:where(.sl-body).ad-typographic-clinical .section-header h2 {
  font-size: clamp(2rem, 4.4vw, 3.2rem); line-height: 1.05;
}

/* ============================================================================
   CARDS / FEATURE GRID — flat, precise, hairline. Calm material, NOT glossy lift.
   ============================================================================ */
:where(.sl-body).ad-typographic-clinical .card, :where(.sl-body).ad-typographic-clinical .feature-card, :where(.sl-body).ad-typographic-clinical .auto-card {
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: var(--ad-radius, 10px);
  box-shadow: none;
}
:where(.sl-body).ad-typographic-clinical .cards-center .card:hover, :where(.sl-body).ad-typographic-clinical .grid .card:hover, :where(.sl-body).ad-typographic-clinical .auto-grid .auto-card:hover {
  transform: none;
  border-color: color-mix(in srgb, var(--c-accent) 45%, var(--c-border));
  box-shadow: 0 1px 0 color-mix(in srgb, var(--c-accent) 30%, transparent) inset,
              0 10px 30px -22px rgba(16,24,32,0.4);
}
/* feature icon: muted accent square tile, calm not flashy */
:where(.sl-body).ad-typographic-clinical .feature-ic, :where(.sl-body).ad-typographic-clinical .auto-card .feature-ic {
  background: color-mix(in srgb, var(--c-accent) 12%, var(--c-surface));
  color: var(--c-accent);
  border-radius: calc(var(--ad-radius, 10px) - 2px);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--c-accent) 22%, transparent);
}
:where(.sl-body).ad-typographic-clinical .feature-card h3 { letter-spacing: -0.01em; }

/* drips/menu grid: precise, even, tidy */
:where(.sl-body).ad-typographic-clinical .pkg-card, :where(.sl-body).ad-typographic-clinical .pkg-style-grid .pkg-card {
  border: 1px solid var(--c-border); border-radius: var(--ad-radius, 10px);
  background: var(--c-surface);
}

/* ============================================================================
   STATS BAND — deep primary field, crisp accent numbers (proof reads precise).
   ============================================================================ */
:where(.sl-body).ad-typographic-clinical .section-stats {
  background: var(--c-room) !important;
  position: relative; isolation: isolate;
}
/* faint matching grid so the proof band echoes the hero */
:where(.sl-body).ad-typographic-clinical .section-stats::after {
  content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background-image:
    linear-gradient(rgba(255,255,255,0.04) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,0.04) 1px, transparent 1px);
  background-size: 46px 46px;
}
:where(.sl-body).ad-typographic-clinical .section-stats > .container { position: relative; z-index: 1; }
:where(.sl-body).ad-typographic-clinical .section-stats h2, :where(.sl-body).ad-typographic-clinical .section-stats .stat-value { color: var(--c-on-room); }
:where(.sl-body).ad-typographic-clinical .section-stats .stat-value {
  font-weight: 800; letter-spacing: -0.04em;
  font-variant-numeric: tabular-nums;
}
:where(.sl-body).ad-typographic-clinical .section-stats .stat-ic { color: var(--c-accent); }
:where(.sl-body).ad-typographic-clinical .section-stats .stat-label {
  color: var(--c-on-room); opacity: 0.78; letter-spacing: 0.04em;
}

/* ============================================================================
   REVIEWS / FAQ — quiet, hairline, accent only on the small marks.
   ============================================================================ */
:where(.sl-body).ad-typographic-clinical .review-card .stars, :where(.sl-body).ad-typographic-clinical .stars { color: var(--c-accent); }
:where(.sl-body).ad-typographic-clinical .review-quote { font-style: normal; line-height: 1.6; }
:where(.sl-body).ad-typographic-clinical .review-initial { background: var(--c-primary); }
:where(.sl-body).ad-typographic-clinical .faq-item { border-bottom: 1px solid var(--c-border); }
:where(.sl-body).ad-typographic-clinical .faq-item .faq-chevron { color: var(--c-accent); }
:where(.sl-body).ad-typographic-clinical .area-chip { border-radius: 999px; }
:where(.sl-body).ad-typographic-clinical .area-chip svg { color: var(--c-accent); }

/* ============================================================================
   FINAL CTA — deep primary field with a soft accent aurora, calm and confident.
   ============================================================================ */
:where(.sl-body).ad-typographic-clinical .final-cta {
  background: var(--c-room) !important; position: relative; overflow: hidden;
}
:where(.sl-body).ad-typographic-clinical .final-cta::after {
  background: radial-gradient(60% 80% at 86% 12%, var(--adtc-glow-a), transparent 60%);
  opacity: 0.5;
}
:where(.sl-body).ad-typographic-clinical .final-cta h2 { letter-spacing: -0.03em; }
:where(.sl-body).ad-typographic-clinical .final-cta .btn-primary {
  background: var(--c-light-stock); color: var(--c-primary); border-color: var(--c-light-stock);
}
:where(.sl-body).ad-typographic-clinical .final-cta .btn-primary:hover {
  background: color-mix(in srgb, var(--c-surface) 90%, var(--c-accent)); color: var(--c-primary);
}

/* ============================================================================
   ACCENT-USAGE HELPERS (adacc-*) — lean harder into the accent only on badge mode.
   ============================================================================ */
/* sparing: keep the accent to thin marks only (already the default above) */
:where(.sl-body).ad-typographic-clinical.adacc-sparing .section-header .eyebrow::after { width: 20px; }
/* badge: kickers/numbers get an accent chip treatment for a more branded read */
:where(.sl-body).ad-typographic-clinical.adacc-badge .section-header .eyebrow {
  background: color-mix(in srgb, var(--c-accent) 14%, var(--c-surface));
  color: color-mix(in srgb, var(--c-accent) 86%, #000);
  padding: 0.4rem 0.8rem; border-radius: 999px;
  border: 1px solid color-mix(in srgb, var(--c-accent) 32%, transparent);
}
:where(.sl-body).ad-typographic-clinical.adacc-badge .section-header .eyebrow::after { display: none; }
:where(.sl-body).ad-typographic-clinical.adacc-bold .hero .eyebrow {
  color: var(--c-accent);
}

/* ============================================================================
   DENSITY HELPERS (addens-*) — tune the calm structure.
   ============================================================================ */
:where(.sl-body).ad-typographic-clinical.addens-airy .section { padding: clamp(3rem, 6vw, 5rem) 0; }
:where(.sl-body).ad-typographic-clinical.addens-airy .section-header { margin-bottom: 3.5rem; }
:where(.sl-body).ad-typographic-clinical.addens-tight .section { padding: clamp(2rem, 4vw, 3.25rem) 0; }

/* ============================================================================
   MOTION — subtle only, gated by reduced-motion. Slow aurora drift + soft type rise.
   ============================================================================ */
@media (prefers-reduced-motion: no-preference) {
  @keyframes adtcAurora {
    0%   { transform: translate3d(0, 0, 0) scale(1); }
    50%  { transform: translate3d(2%, -2%, 0) scale(1.06); }
    100% { transform: translate3d(0, 0, 0) scale(1); }
  }
  :where(.sl-body).ad-typographic-clinical .hero::after {
    animation: adtcAurora 18s ease-in-out infinite;
  }
  @keyframes adtcRise { from { opacity: 0; transform: translateY(18px); } to { opacity: 1; transform: none; } }
  :where(.sl-body).ad-typographic-clinical .hero-inner > * { animation: adtcRise .7s cubic-bezier(.2,.7,.2,1) both; }
  :where(.sl-body).ad-typographic-clinical .hero-inner > .eyebrow { animation-delay: .04s; }
  :where(.sl-body).ad-typographic-clinical .hero-inner > h1 { animation-delay: .12s; }
  :where(.sl-body).ad-typographic-clinical .hero-inner > .subhead { animation-delay: .24s; }
  :where(.sl-body).ad-typographic-clinical .hero-inner > .cta-row { animation-delay: .36s; }
}

/* ============================================================================
   MOBILE — keep the giant headline from overflowing at 390px and below.
   ============================================================================ */
@media (max-width: 600px) {
  :where(.sl-body).ad-typographic-clinical {
    --adtc-h1: calc(clamp(2.3rem, 11vw, 3.2rem) * var(--ad-h1-scale, 1));
  }
  :where(.sl-body).ad-typographic-clinical .hero h1 { max-width: 100%; letter-spacing: -0.03em; }
  :where(.sl-body).ad-typographic-clinical .hero::before { background-size: 34px 34px; }
  :where(.sl-body).ad-typographic-clinical .section-stats::after { background-size: 34px 34px; }
}

/* ===== BRIGHT-CLINICAL ===== */
/* ============================================================================
   ART DIRECTION — BRIGHT CLINICAL TRUST
   Scoped under body.ad-bright-clinical. Additive; appended after the v2 bold
   pass so it wins the cascade. Target feel: One Medical / Forward — crisp white,
   --c-primary, airy spacing, a confident (not huge) sans headline, accent as
   small badges + the primary "Book" CTA, top-lit card depth with hairlines and a
   hover lift, a clean photo hero with rating proof up top + floating trust-card
   feel, a two-column price MENU with a "most popular" accent emphasis, and
   verified-review check badges. Brand-token-driven, mobile-safe, accessible.
   ============================================================================ */

/* ---- 1. BRIGHTEN THE CANVAS — crisp white, cool surfaces ---- */
:where(.sl-body).ad-bright-clinical {
  background: var(--c-surface, #fff);
  color: var(--c-text);
}
/* Generous breathing room between content sections; hairline rule (not a band)
   keeps the page feeling clean and clinical. Tightened/loosened by density helper. */
:where(.sl-body).ad-bright-clinical .section {
  padding: clamp(2.5rem, 5vw, 4.25rem) 0;
}
:where(.sl-body).ad-bright-clinical.addens-airy .section { padding: clamp(3rem, 6vw, 5rem) 0; }
:where(.sl-body).ad-bright-clinical.addens-tight .section { padding: clamp(2rem, 4vw, 3.25rem) 0; }
:where(.sl-body).ad-bright-clinical .section + .section {
  border-top: 1px solid color-mix(in srgb, var(--c-text) 8%, transparent);
}
/* When alternating bands are on, keep them whisper-soft + cool, never heavy. */
:where(.sl-body).ad-bright-clinical.sections-alternate main > section.section:nth-of-type(even):not(.section-tier_comparison):not(.final-cta):not(.section-hub-cta):not(.sec-room):not(.sec-photo):not(.comp-trust-band):not(.block-route-section) {
  background: color-mix(in srgb, var(--c-surface-alt, #f3f6f8) 55%, var(--c-surface, #fff));
}

/* ---- 2. TYPE — confident, NOT huge. Tame the bold v2 scale. ---- */
:where(.sl-body).ad-bright-clinical h1, :where(.sl-body).ad-bright-clinical h2, :where(.sl-body).ad-bright-clinical h3 {
  font-weight: var(--ad-heading-weight, 700);
  letter-spacing: var(--ad-letter-spacing, -0.02em);
}
:where(.sl-body).ad-bright-clinical .hero h1 {
  font-size: clamp(2.4rem, 4.6vw, 3.6rem) !important;
  /* honor a per-brand scale tweak while staying mobile-safe */
  font-size: clamp(2.4rem, calc(4.6vw * var(--ad-h1-scale, 1)), 3.7rem) !important;
  line-height: 1.08 !important;
  letter-spacing: -0.025em !important;
  text-wrap: balance;
}
:where(.sl-body).ad-bright-clinical h2 {
  font-size: clamp(1.8rem, 3.1vw, 2.5rem) !important;
  line-height: 1.12 !important;
  letter-spacing: -0.02em !important;
}
:where(.sl-body).ad-bright-clinical .section-header { max-width: 680px; margin-bottom: 1.85rem; }
:where(.sl-body).ad-bright-clinical .section-header p { font-size: 1.0625rem; line-height: 1.6; color: var(--c-text-muted); }
:where(.sl-body).ad-bright-clinical .hero .subhead {
  font-size: clamp(1.05rem, 1.4vw, 1.2rem) !important;
  line-height: 1.6;
  max-width: 52ch;
  color: var(--c-text-muted);
}
/* Eyebrow reads as a small confident clinical label, accent-tinted. */
:where(.sl-body).ad-bright-clinical .eyebrow, :where(.sl-body).ad-bright-clinical .hero .eyebrow, :where(.sl-body).ad-bright-clinical .section-header .eyebrow {
  font-weight: 700;
  letter-spacing: 0.13em;
  font-size: 0.78rem;
  text-transform: uppercase;
  color: var(--c-accent);
}

/* ---- 3. HEADER — clean, bright, hairline; primary "Book" CTA pops in accent ---- */
:where(.sl-body).ad-bright-clinical .site-header {
  background: color-mix(in srgb, var(--c-surface, #fff) 88%, transparent);
  -webkit-backdrop-filter: saturate(1.3) blur(12px);
  backdrop-filter: saturate(1.3) blur(12px);
  border-bottom: 1px solid color-mix(in srgb, var(--c-text) 8%, transparent);
}
:where(.sl-body).ad-bright-clinical .site-nav a { color: var(--c-text); font-weight: 500; }
:where(.sl-body).ad-bright-clinical .site-nav a:hover { color: var(--c-primary); text-decoration: none; }
/* The nav "Book" button (a primary CTA living in the header) wears the accent. */
:where(.sl-body).ad-bright-clinical .site-nav .btn-primary, :where(.sl-body).ad-bright-clinical .site-header .btn-primary {
  background: var(--c-accent);
  color: var(--c-primary-dark);
  border-color: var(--c-accent);
}

/* ---- 4. HERO — bright, credible. Reads whether or not a photo is present. ---- */
/* Confident height, not the v2 90vh wall. */
:where(.sl-body).ad-bright-clinical .hero { padding: clamp(3rem, 6vw, 5rem) 0; }

/* SIGNATURE PHOTO HERO: the pitch lives in a SOLID deep-brand CARD anchored to the left over a
   full-bleed lifestyle photo (an editorial "brand card over photo"), NOT plain text centered on the
   image. This composition is what sets bright-clinical apart from the bold-modern full-photo hero so
   two brands never read as the same hero. The photo stays rich (only a light cohesion veil + a soft
   brand wash behind the card); the card carries the contrast, so text is light. */
:where(.sl-body).ad-bright-clinical .hero-image-bg { color: #fff !important; }
:where(.sl-body).ad-bright-clinical .hero-image-bg::before {
  filter: saturate(1.06) brightness(0.99) !important;
}
:where(.sl-body).ad-bright-clinical .hero-image-bg::after, :where(.sl-body).ad-bright-clinical .hero-video::after {
  background:
    radial-gradient(60% 70% at 92% 18%, color-mix(in srgb, var(--c-accent) 16%, transparent), transparent 62%),
    linear-gradient(90deg,
      color-mix(in srgb, var(--c-primary-dark) 34%, transparent) 0%,
      color-mix(in srgb, var(--c-primary-dark) 10%, transparent) 40%,
      transparent 66%) !important;
  background-size: cover, cover !important;
}
/* the brand card */
/* left-anchor the card within the hero so the photo subjects read on the right. width:100% stops
   the flex container from shrinking to the card (which would re-center it via its auto margins). */
:where(.sl-body).ad-bright-clinical .hero-image-bg .container, :where(.sl-body).ad-bright-clinical .hero-video .container { display: flex; justify-content: flex-start; width: 100%; max-width: 1180px; margin-left: auto; margin-right: auto; }
:where(.sl-body).ad-bright-clinical .hero-image-bg .hero-inner, :where(.sl-body).ad-bright-clinical .hero-video .hero-inner {
  max-width: 540px;
  background: linear-gradient(155deg, color-mix(in srgb, var(--c-primary) 94%, #000), var(--c-primary-dark));
  color: #fff;
  border-radius: calc(var(--card-radius, 16px) + 4px);
  padding: clamp(1.9rem, 3vw, 2.9rem);
  box-shadow: 0 34px 80px -34px rgba(20, 10, 45, 0.6);
  border: 1px solid color-mix(in srgb, #fff 15%, transparent);
}
/* keep the CTA buttons INSIDE the card (they overflowed onto the photo) */
:where(.sl-body).ad-bright-clinical .hero-image-bg .cta-row, :where(.sl-body).ad-bright-clinical .hero-video .cta-row { flex-wrap: wrap; gap: 0.7rem; }
:where(.sl-body).ad-bright-clinical .hero-image-bg .cta-row .btn, :where(.sl-body).ad-bright-clinical .hero-video .cta-row .btn { white-space: nowrap; }
:where(.sl-body).ad-bright-clinical .hero-image-bg h1, :where(.sl-body).ad-bright-clinical .hero-image-bg p, :where(.sl-body).ad-bright-clinical .hero-image-bg .subhead, :where(.sl-body).ad-bright-clinical .hero-video h1, :where(.sl-body).ad-bright-clinical .hero-video .subhead { color: #fff !important; }
:where(.sl-body).ad-bright-clinical .hero-image-bg .subhead { color: color-mix(in srgb, #fff 82%, var(--c-accent)) !important; }
:where(.sl-body).ad-bright-clinical .hero-image-bg .eyebrow { color: var(--c-accent) !important; }
/* secondary CTAs read as legible light chips on the deep card */
:where(.sl-body).ad-bright-clinical .hero-image-bg .btn-secondary {
  color: #fff !important; border-color: color-mix(in srgb, #fff 72%, transparent) !important;
  background: color-mix(in srgb, #fff 12%, transparent) !important;
}
:where(.sl-body).ad-bright-clinical .hero-image-bg .btn-secondary:hover { background: color-mix(in srgb, #fff 22%, transparent) !important; }
@media (max-width: 640px) {
  :where(.sl-body).ad-bright-clinical .hero-image-bg .hero-inner, :where(.sl-body).ad-bright-clinical .hero-video .hero-inner { max-width: 100%; }
}

/* Video hero gets the same bright veil; keep video legible by darkening text bg slightly less. */
:where(.sl-body).ad-bright-clinical .hero-video { color: var(--c-text) !important; }
:where(.sl-body).ad-bright-clinical .hero-video h1, :where(.sl-body).ad-bright-clinical .hero-video p { color: var(--c-text) !important; }

/* NO-PHOTO heroes (gradient / aurora / minimal-left): force a BRIGHT surface so the
   archetype still reads clinical-white instead of a deep brand slab. */
:where(.sl-body).ad-bright-clinical .hero-gradient, :where(.sl-body).ad-bright-clinical .hero-aurora-spotlight {
  background: radial-gradient(120% 120% at 80% 0%, color-mix(in srgb, var(--c-primary) 9%, var(--c-surface, #fff)), var(--c-surface, #fff) 70%) !important;
  color: var(--c-text) !important;
}
:where(.sl-body).ad-bright-clinical .hero-gradient h1, :where(.sl-body).ad-bright-clinical .hero-gradient p, :where(.sl-body).ad-bright-clinical .hero-aurora-spotlight h1, :where(.sl-body).ad-bright-clinical .hero-aurora-spotlight p { color: var(--c-text) !important; }
/* kill the dark-hero aurora glow/grid that fights the bright look */
:where(.sl-body).ad-bright-clinical .hero-aurora-spotlight::before { opacity: 0.4; }
:where(.sl-body).ad-bright-clinical .hero-aurora-spotlight::after {
  background: radial-gradient(circle, color-mix(in srgb, var(--c-accent) 22%, transparent), transparent 60%) !important;
  opacity: 0.7;
}
/* secondary button on the still-light gradient/aurora heroes reads as primary outline. NOTE:
   image-bg + video now use the DEEP brand card (light text), so they are intentionally excluded
   here and keep their light-outline chips from the card block above. */
:where(.sl-body).ad-bright-clinical .hero-gradient .btn-secondary, :where(.sl-body).ad-bright-clinical .hero-aurora-spotlight .btn-secondary {
  color: var(--c-primary) !important;
  border-color: var(--c-primary) !important;
  background: transparent !important;
}
:where(.sl-body).ad-bright-clinical .hero-gradient .btn-secondary:hover, :where(.sl-body).ad-bright-clinical .hero-aurora-spotlight .btn-secondary:hover {
  background: var(--c-primary) !important;
  color: var(--c-on-primary, #fff) !important;
}

/* RATING PROOF UP TOP — a clean floating trust card, light + hairline + accent stars.
   On any hero (light now), so override the dark-glass rating treatment. */
:where(.sl-body).ad-bright-clinical .hero-rating {
  background: var(--c-surface, #fff) !important;
  border: 1px solid color-mix(in srgb, var(--c-text) 10%, transparent) !important;
  color: var(--c-text) !important;
  border-radius: 999px !important;
  padding: 0.55rem 1.1rem !important;
  font-size: 0.95rem !important;
  font-weight: 600;
  -webkit-backdrop-filter: none !important;
  backdrop-filter: none !important;
  box-shadow:
    0 1px 0 rgba(255,255,255,0.9) inset,
    0 10px 26px -12px rgba(16,24,32,0.28) !important;
  margin-bottom: 1.25rem;
}
:where(.sl-body).ad-bright-clinical .hero-rating .stars { color: var(--c-accent) !important; }

/* Split-image hero: photo gets a soft top-lit card frame to feel "floating / clinical". */
:where(.sl-body).ad-bright-clinical .hero-split .hero-image {
  border-radius: var(--ad-radius, 18px);
  box-shadow:
    0 1px 0 rgba(255,255,255,0.8) inset,
    0 28px 60px -24px rgba(16,24,32,0.3);
}

/* ---- 5. BUTTONS — confident, rounded, primary CTA carries the accent ("Book") ---- */
:where(.sl-body).ad-bright-clinical .btn {
  border-radius: var(--ad-radius, 12px);
  font-weight: 600;
  box-shadow: 0 1px 2px rgba(16,24,32,0.08);
}
:where(.sl-body).ad-bright-clinical .hero .btn { padding: 0.95rem 1.7rem; font-size: 1.02rem; }
/* Primary action = accent badge color, the credible "Book now" pop. */
:where(.sl-body).ad-bright-clinical .btn-primary {
  background: var(--c-accent);
  color: var(--c-primary-dark);
  border-color: var(--c-accent);
  box-shadow: 0 10px 26px -10px color-mix(in srgb, var(--c-accent) 60%, transparent);
}
:where(.sl-body).ad-bright-clinical .btn-primary:hover {
  background: var(--c-accent);
  color: var(--c-primary-dark);
  filter: brightness(0.95);
  transform: translateY(-1px);
}
/* If a brand prefers a sparing accent (adacc-sparing), keep the primary CTA on the
   brand primary instead, reserving accent for tiny badges only. */
:where(.sl-body).ad-bright-clinical.adacc-sparing .btn-primary {
  background: var(--c-primary);
  color: var(--c-on-primary, #fff);
  border-color: var(--c-primary);
  box-shadow: 0 10px 26px -10px color-mix(in srgb, var(--c-primary) 55%, transparent);
}
:where(.sl-body).ad-bright-clinical.adacc-sparing .btn-primary:hover { background: var(--c-primary-dark); filter: none; }
:where(.sl-body).ad-bright-clinical .btn-secondary {
  background: transparent;
  color: var(--c-primary);
  border-color: color-mix(in srgb, var(--c-primary) 50%, var(--c-border));
}
:where(.sl-body).ad-bright-clinical .btn-secondary:hover { background: var(--c-primary); color: var(--c-on-primary, #fff); border-color: var(--c-primary); }

/* ---- 6. SURFACES — TOP-LIT card depth, crisp hairlines, clean hover lift ---- */
:where(.sl-body).ad-bright-clinical .card, :where(.sl-body).ad-bright-clinical .feature-card, :where(.sl-body).ad-bright-clinical .review-card {
  background: var(--c-surface, #fff);
  border: 1px solid color-mix(in srgb, var(--c-text) 8%, transparent);
  border-radius: var(--ad-radius, 16px);
  box-shadow:
    0 1px 0 rgba(255,255,255,0.9) inset,
    0 1px 2px rgba(16,24,32,0.04),
    0 16px 34px -18px rgba(16,24,32,0.16);
  transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}
:where(.sl-body).ad-bright-clinical .cards-center .card:hover, :where(.sl-body).ad-bright-clinical .grid .card:hover, :where(.sl-body).ad-bright-clinical .auto-grid .auto-card:hover {
  transform: translateY(-3px);
  border-color: color-mix(in srgb, var(--c-primary) 22%, transparent);
  box-shadow:
    0 1px 0 rgba(255,255,255,0.9) inset,
    0 24px 48px -20px rgba(16,24,32,0.24);
}
/* Feature icon = small accent badge in a soft tinted square (clinical, not flashy). */
:where(.sl-body).ad-bright-clinical .feature-ic, :where(.sl-body).ad-bright-clinical .auto-card .feature-ic {
  display: inline-grid; place-items: center;
  width: 52px; height: 52px;
  border-radius: 14px;
  margin-bottom: 1rem;
  background: color-mix(in srgb, var(--c-primary) 9%, var(--c-surface, #fff));
  color: var(--c-primary);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--c-primary) 16%, transparent);
}
:where(.sl-body).ad-bright-clinical .feature-ic svg { width: 26px; height: 26px; stroke-width: 1.7; }
:where(.sl-body).ad-bright-clinical .feature-card h3 { font-size: 1.18rem; letter-spacing: -0.01em; }

/* ---- 7. TRUST ROW — clean, accent-on-tinted badges, hairline dividers ---- */
:where(.sl-body).ad-bright-clinical .trust-row-item .trust-ic {
  background: color-mix(in srgb, var(--c-primary) 8%, var(--c-surface, #fff));
  color: var(--c-primary);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--c-primary) 14%, transparent);
}

/* ---- 8. PRICE MENU — clean two-column menu with a "most popular" accent card ---- */
/* Grid layout reads as a tidy menu; cards are crisp + top-lit. */
:where(.sl-body).ad-bright-clinical .pkg-style-grid .pkg-track { gap: 1.5rem; }
:where(.sl-body).ad-bright-clinical .pkg-card {
  background: var(--c-surface, #fff);
  border: 1px solid color-mix(in srgb, var(--c-text) 9%, transparent);
  border-radius: var(--ad-radius, 16px);
  padding: 1.75rem 1.5rem;
  box-shadow:
    0 1px 0 rgba(255,255,255,0.9) inset,
    0 16px 34px -18px rgba(16,24,32,0.16);
  transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}
:where(.sl-body).ad-bright-clinical .pkg-style-grid .pkg-card:hover {
  transform: translateY(-3px);
  box-shadow: 0 24px 48px -20px rgba(16,24,32,0.24);
}
/* "Most popular" emphasis: the middle card of a 3-up menu (or 2nd of 2) wears an
   accent ring + subtle lift, the conversion-forward focal point. Pure CSS, no markup. */
:where(.sl-body).ad-bright-clinical .pkg-style-grid .pkg-card:nth-child(2) {
  border-color: var(--c-accent);
  box-shadow:
    0 0 0 1px var(--c-accent) inset,
    0 1px 0 rgba(255,255,255,0.9) inset,
    0 22px 46px -18px color-mix(in srgb, var(--c-accent) 45%, rgba(16,24,32,0.22));
  position: relative;
}
:where(.sl-body).ad-bright-clinical .pkg-style-grid .pkg-card:nth-child(2)::before {
  content: 'Most popular';
  position: absolute;
  top: -0.7rem; left: 50%; transform: translateX(-50%);
  background: var(--c-accent);
  color: var(--c-primary-dark);
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 0.68rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 0.3rem 0.75rem;
  border-radius: 999px;
  white-space: nowrap;
  box-shadow: 0 6px 16px -6px color-mix(in srgb, var(--c-accent) 60%, transparent);
}

/* ---- 9. VERIFIED REVIEWS — check badge + clean card, accent stars ---- */
:where(.sl-body).ad-bright-clinical .review-card { padding: 1.6rem 1.5rem; }
:where(.sl-body).ad-bright-clinical .review-card .stars { color: var(--c-accent); }
:where(.sl-body).ad-bright-clinical .review-quote { font-style: normal; color: var(--c-text); line-height: 1.6; }
/* A small "verified" check chip pinned to each review's author line. */
:where(.sl-body).ad-bright-clinical .review-by { position: relative; }
:where(.sl-body).ad-bright-clinical .review-by::after {
  content: '';
  width: 18px; height: 18px;
  margin-left: 0.4rem;
  flex: 0 0 auto;
  border-radius: 50%;
  background:
    color-mix(in srgb, var(--c-primary) 12%, var(--c-surface, #fff))
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='20 6 9 17 4 12'/%3E%3C/svg%3E")
    center / 11px no-repeat;
  /* tint the check stroke to the brand primary via a mask-like layered approach */
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--c-primary) 28%, transparent);
}
:where(.sl-body).ad-bright-clinical .review-initial { background: var(--c-primary); }

/* ---- 10. STATS BAND — keep it on-brand but credible; big number in primary ---- */
:where(.sl-body).ad-bright-clinical .stat-value { font-size: clamp(2.6rem, 5vw, 4rem) !important; letter-spacing: -0.025em; }
:where(.sl-body).ad-bright-clinical .stat-label { font-size: 1rem; opacity: 0.85; }

/* ---- 11. FINAL CTA — confident, not enormous; clean accent button inside ---- */
:where(.sl-body).ad-bright-clinical .final-cta { padding: clamp(3rem, 6.5vw, 5.5rem) 1.5rem; }
:where(.sl-body).ad-bright-clinical .final-cta h2 { font-size: clamp(2.1rem, 4.5vw, 3.2rem) !important; }
:where(.sl-body).ad-bright-clinical .final-cta .btn-primary, :where(.sl-body).ad-bright-clinical .final-cta .btn-accent {
  background: var(--c-accent);
  color: var(--c-primary-dark);
  border-color: var(--c-accent);
}

/* ---- 12. FAQ — clean clinical accordion, primary chevron ---- */
:where(.sl-body).ad-bright-clinical .faq-item { border-bottom: 1px solid color-mix(in srgb, var(--c-text) 8%, transparent); }
:where(.sl-body).ad-bright-clinical .faq-item .faq-chevron { color: var(--c-primary); }

/* ---- 13. MOTION — tasteful only; calmer than the bold v2 entrance ---- */
@media (prefers-reduced-motion: no-preference) {
  :where(.sl-body).ad-bright-clinical .hero-inner > * { animation: slRiseClinical .6s cubic-bezier(.22,.7,.25,1) both; }
  :where(.sl-body).ad-bright-clinical .hero-inner > .eyebrow { animation-delay: .04s; }
  :where(.sl-body).ad-bright-clinical .hero-inner > h1 { animation-delay: .1s; }
  :where(.sl-body).ad-bright-clinical .hero-inner > .subhead { animation-delay: .2s; }
  :where(.sl-body).ad-bright-clinical .hero-inner > .cta-row { animation-delay: .3s; }
  @keyframes slRiseClinical { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
}
@media (prefers-reduced-motion: reduce) {
  :where(.sl-body).ad-bright-clinical .hero-inner > *, :where(.sl-body).ad-bright-clinical .btn, :where(.sl-body).ad-bright-clinical .card { animation: none !important; transition: none !important; }
}

/* ---- 14. MOBILE SAFETY (390px and down) ---- */
@media (max-width: 480px) {
  :where(.sl-body).ad-bright-clinical .hero h1 {
    font-size: clamp(2rem, 9vw, 2.6rem) !important;
    line-height: 1.12 !important;
    letter-spacing: -0.02em !important;
  }
  :where(.sl-body).ad-bright-clinical h2 { font-size: clamp(1.6rem, 7vw, 2.1rem) !important; }
  /* On small screens the photo-hero light veil should cover the whole width so
     dark text never lands on a bright photo area without a veil behind it. */
  :where(.sl-body).ad-bright-clinical .hero-image-bg::after, :where(.sl-body).ad-bright-clinical .hero-video::after {
    background:
      linear-gradient(180deg,
        color-mix(in srgb, var(--c-surface, #fff) 86%, transparent) 0%,
        color-mix(in srgb, var(--c-surface, #fff) 70%, transparent) 100%) !important;
  }
  /* Price menu stacks; drop the "most popular" lift so it doesn't overlap on stack. */
  :where(.sl-body).ad-bright-clinical .pkg-style-grid .pkg-card:nth-child(2) { transform: none; }
  :where(.sl-body).ad-bright-clinical .final-cta h2 { font-size: clamp(1.8rem, 8vw, 2.4rem) !important; }
}

/* Renderer-merge: moved out of SectionBlock.astro's scoped \3c style> so the pure-TS
   renderers' set:html markup (which loses Astro's scoped attribute) is still styled.
   .auto-grid/.auto-card are the balanced card grid used by event_wellness/group_services
   and the generic feature/browse grids. Placed after the .auto-card .feature-ic badge rule
   above so the flex-start override keeps its cascade order. */
:where(.sl-body) .auto-grid { display: flex; flex-wrap: wrap; justify-content: center; align-items: stretch; gap: 1.5rem; margin: 1.25rem auto 0; max-width: 1120px; }
:where(.sl-body) .auto-card { flex: 0 1 var(--sl-basis, 280px); display: flex; flex-direction: column; text-align: left; background: var(--c-surface); border: 1px solid color-mix(in srgb, var(--c-text) 9%, transparent); border-radius: 18px; padding: 1.8rem 1.6rem; box-shadow: 0 1px 0 rgba(255,255,255,0.65) inset, 0 18px 40px -18px rgba(16,24,32,0.2); transition: transform .2s ease, box-shadow .2s ease; }
:where(.sl-body) .auto-card:hover { transform: translateY(-4px); box-shadow: 0 30px 56px -20px rgba(16,24,32,0.28); }
@media (max-width: 640px) { :where(.sl-body) .auto-card { flex-basis: 100%; max-width: none; } }
:where(.sl-body) .auto-card .feature-ic { display: flex; justify-content: flex-start; }
:where(.sl-body) .auto-card h3 { margin: 0 0 0.5rem; font-size: 1.2rem; letter-spacing: -0.01em; }
:where(.sl-body) .auto-card p { margin: 0; color: var(--c-text-muted, #555); line-height: 1.6; }

/* Two-column splits (class="vp-2col": value_prop_two_col + contact_two_col) render an inline
   1fr/1fr grid via the shared renderer. Stack to one column on phones (matches .hero-split /
   .ba-row); !important beats the inline grid-template-columns:1fr 1fr. Moved here from
   SectionBlock's scoped \3c style> because set:html markup loses component-scoped styles. */
@media (max-width: 768px) { :where(.sl-body) .vp-2col { grid-template-columns: minmax(0, 1fr) !important; } }

/* moved from SectionBlock scoped \3c style> (renderer-merge: team_carousel) */
:where(.sl-body) .team-carousel { display: flex; gap: 1.25rem; margin: 1.5rem auto 0; max-width: 1100px; overflow-x: auto; scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch; padding-bottom: 0.75rem; scrollbar-width: thin; }
:where(.sl-body) .team-member-card { flex: 0 0 240px; scroll-snap-align: start; text-align: center; background: var(--c-surface); border: 1px solid var(--c-border); border-radius: var(--card-radius, 12px); padding: 1.6rem 1.3rem; box-shadow: var(--card-shadow, 0 1px 3px rgba(0,0,0,0.06)); }
:where(.sl-body) .tm-photo { width: 120px; height: 120px; border-radius: 50%; object-fit: cover; margin: 0 auto 0.85rem; display: block; }
:where(.sl-body) .tm-photo-initial { display: flex; align-items: center; justify-content: center; background: var(--c-bg); color: var(--c-accent); font-family: var(--font-heading); font-size: 2rem; font-weight: 700; border: 1px solid var(--c-border); }
:where(.sl-body) .tm-name { display: block; font-size: 1.05rem; }
:where(.sl-body) .tm-title { margin-top: 0.2rem; }
:where(.sl-body) .tm-bio { margin: 0.6rem 0 0; }
@media (max-width: 640px) { :where(.sl-body) .team-member-card { flex-basis: 78%; } }
/* Small team (2-3 people): a centered row of wider cards, not a scroll track with a dead gutter. */
:where(.sl-body) .team-carousel.tc-few { justify-content: center; overflow-x: visible; flex-wrap: wrap; }
:where(.sl-body) .team-carousel.tc-few .team-member-card { flex: 0 1 340px; }
@media (max-width: 640px) { :where(.sl-body) .team-carousel.tc-few .team-member-card { flex-basis: 100%; } }
/* MIXED ROSTER (see renderTeamCarousel): real portraits render together as captioned figures,
   and every bio renders in the same left-aligned block underneath. Never an initials medallion
   sitting beside a photograph, and never a long founder bio as a centered paragraph. */
:where(.sl-body) .team-roster { max-width: var(--content-max, 1100px); margin: 1.5rem auto 0; }
:where(.sl-body) .tr-faces { display: flex; flex-wrap: wrap; justify-content: center; gap: 1.75rem 2.5rem; margin-bottom: 2.25rem; }
:where(.sl-body) .tr-face { margin: 0; text-align: center; max-width: 240px; }
:where(.sl-body) .tr-face img { width: 200px; height: 200px; border-radius: 50%; object-fit: cover; display: block; margin: 0 auto 0.8rem; box-shadow: 0 14px 32px rgba(0,0,0,0.14); }
:where(.sl-body) .tr-faces-one .tr-face img { width: 240px; height: 240px; }
:where(.sl-body) .tr-face figcaption { display: flex; flex-direction: column; gap: 0.15rem; }
:where(.sl-body) .tr-face-name { font-family: var(--font-heading); font-weight: 600; font-size: 1.05rem; color: var(--c-text); }
:where(.sl-body) .tr-face-title { font-size: 0.875rem; color: var(--c-text-muted); }
:where(.sl-body) .tr-bios { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 1.5rem 2.75rem; text-align: left; }
:where(.sl-body) .tr-bio { text-align: left; }
:where(.sl-body) .tr-bio .tm-name { font-family: var(--font-heading); font-size: 1.2rem; margin: 0; }
:where(.sl-body) .tr-bio .tm-title { color: var(--c-text-muted); font-size: 0.9375rem; margin-top: 0.15rem; }
:where(.sl-body) .tr-bio .tm-bio { color: var(--c-text-muted); margin: 0.7rem 0 0; }
@media (max-width: 720px) {
  :where(.sl-body) .tr-bios { grid-template-columns: minmax(0, 1fr); }
  :where(.sl-body) .tr-face img, :where(.sl-body) .tr-faces-one .tr-face img { width: 168px; height: 168px; }
}
/* GROUP PORTRAIT (see renderTeamCarousel): one photograph of the team, every bio as text beside
   it. The photo column is sticky so the picture stays with the reading column instead of stranding
   a tall empty gutter next to two long founder bios. */
:where(.sl-body) .team-founders {
  max-width: var(--content-max, 1100px);
  margin: 1.75rem auto 0;
  display: grid;
  grid-template-columns: minmax(280px, 0.82fr) minmax(0, 1.18fr);
  gap: 1.75rem 3rem;
  align-items: start;
  text-align: left;
}
:where(.sl-body) .tf-photo { margin: 0; position: sticky; top: 6.5rem; }
:where(.sl-body) .tf-photo img {
  display: block; width: 100%; height: auto;
  border-radius: var(--card-radius, 16px);
  box-shadow: 0 22px 48px rgba(0, 0, 0, 0.16);
}
:where(.sl-body) .tf-cap { margin-top: 0.75rem; font-size: 0.9375rem; line-height: 1.5; color: var(--c-text-muted); }
:where(.sl-body) .tf-bios { display: flex; flex-direction: column; gap: 1.75rem; }
:where(.sl-body) .tf-bios .tr-bio .tm-bio { max-width: 62ch; }
@media (max-width: 860px) {
  :where(.sl-body) .team-founders { grid-template-columns: minmax(0, 1fr); gap: 1.5rem; }
  :where(.sl-body) .tf-photo { position: static; max-width: 520px; }
}
/* Named-but-unpictured roster (nurses, techs). Names are what make a team read as real. */
:where(.sl-body) .tr-roster {
  max-width: var(--content-max, 1100px);
  margin: 2.25rem auto 0;
  padding-top: 1.5rem;
  border-top: 1px solid var(--c-border);
  text-align: left;
}
:where(.sl-body) .tr-roster-label { font-size: 0.8rem; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; color: var(--c-text-muted); margin-bottom: 0.85rem; }
:where(.sl-body) .tr-roster-list { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: 0.6rem 0.75rem; }
:where(.sl-body) .tr-roster-list li {
  display: inline-flex; align-items: baseline; gap: 0.45rem;
  padding: 0.45rem 0.9rem;
  border: 1px solid var(--c-border);
  border-radius: 999px;
  background: var(--c-surface);
}
:where(.sl-body) .tr-roster-name { font-weight: 600; color: var(--c-text); font-size: 0.9375rem; }
:where(.sl-body) .tr-roster-title { color: var(--c-text-muted); font-size: 0.8125rem; }
:where(.sl-body) .tr-roster-note { margin: 0.9rem 0 0; color: var(--c-text-muted); font-size: 0.9375rem; max-width: 68ch; }
/* UNLABELLED team gallery: real portraits with NO per-photo caption, so no face is ever asserted to
   be a particular name. Sized well below the founders' portrait so it reads as supporting imagery. */
:where(.sl-body) .tr-gallery { display: flex; flex-wrap: wrap; gap: 0.9rem; margin: 0 0 1.1rem; }
:where(.sl-body) .tr-gallery-img {
  width: 148px; height: 148px; object-fit: cover; border-radius: 16px;
  border: 1px solid var(--c-border); background: var(--c-surface);
}
:where(.sl-body) .tr-gallery-cap { flex-basis: 100%; margin: 0.15rem 0 0; color: var(--c-text-muted); font-size: 0.9375rem; }
@media (max-width: 640px) { :where(.sl-body) .tr-gallery-img { width: 96px; height: 96px; } }

/* moved from SectionBlock scoped \3c style> (renderer-merge: logo_wall) */
:where(.sl-body) .logo-wall { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 2.5rem 3rem; margin: 1.5rem auto 0; max-width: 980px; }
  :where(.sl-body) .logo-wall-item { display: inline-flex; align-items: center; }
  :where(.sl-body) .logo-wall-item img { max-height: 56px; max-width: 160px; width: auto; height: auto; object-fit: contain; filter: grayscale(1); opacity: 0.7; transition: filter 0.2s ease, opacity 0.2s ease; }
  :where(.sl-body) .logo-wall-item:hover img, :where(.sl-body) a.logo-wall-item:focus-visible img { filter: grayscale(0); opacity: 1; }
  @media (max-width: 640px) { :where(.sl-body) .logo-wall { gap: 1.5rem 2rem; } :where(.sl-body) .logo-wall-item img { max-height: 42px; max-width: 120px; } }

/* moved from SectionBlock scoped \3c style> (renderer-merge: package_ticker) */
:where(.sl-body) .bag-ticker-viewport { overflow: hidden; width: 100%; }
  :where(.sl-body) .bag-ticker-track {
    display: flex;
    gap: 30px;
    width: max-content;
    align-items: flex-end;
    animation: slBagTicker 45s linear infinite;
  }
  :where(.sl-body) .bag-ticker-track:hover { animation-play-state: paused; }
  :where(.sl-body) .bag-ticker-item { flex: 0 0 auto; width: 120px; text-align: center; }
  :where(.sl-body) .bag-ticker-item img { width: 100%; height: 150px; object-fit: contain; filter: drop-shadow(0 10px 24px rgba(0, 0, 0, 0.35)); }
  @keyframes slBagTicker { from { transform: translateX(0); } to { transform: translateX(-50%); } }
  @media (prefers-reduced-motion: reduce) { :where(.sl-body) .bag-ticker-track { animation: none; } }

/* moved from SectionBlock scoped \3c style> (renderer-merge: pricing_tiers) */
/* Pricing tiers: centered flex so a short last row balances (mirrors .cards-center) */
  :where(.sl-body) .pricing-tiers { display: flex; flex-wrap: wrap; justify-content: center; gap: 1.5rem; margin: 1.5rem auto 0; max-width: var(--content-max); }
  /* One plan, on purpose. A practice that sells a single concierge programme (LivLong MD: one
     membership, $4,000/month) used to render nothing at all, because the component required two
     tiers. Now that one complete plan is allowed, it must not stretch across the full band like a
     card that lost its siblings — capped and centred, a lone plan reads as a deliberate offer. */
  :where(.sl-body) .pricing-tiers.tiers-single { max-width: 34rem; }
  :where(.sl-body) .pricing-tiers.tiers-single .tier-card { flex: 1 1 auto; }
  :where(.sl-body) .tier-card { flex: 0 1 var(--sl-basis, 320px); display: flex; flex-direction: column; text-align: left; position: relative; padding: 2rem 1.6rem; }
  :where(.sl-body) .tier-featured { border-color: var(--c-accent); box-shadow: 0 0 0 2px var(--c-accent), var(--card-shadow, 0 1px 3px rgba(0,0,0,0.08)); }
  :where(.sl-body) .tier-badge { position: absolute; top: -0.75rem; left: 50%; transform: translateX(-50%); background: var(--c-accent); color: var(--c-primary-dark, #fff); font-size: 0.75rem; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; padding: 0.25rem 0.75rem; border-radius: 999px; white-space: nowrap; }
  :where(.sl-body) .tier-name { margin: 0 0 0.5rem; font-size: 1.15rem; }
  :where(.sl-body) .tier-price { display: flex; align-items: baseline; gap: 0.35rem; margin-bottom: 0.75rem; }
  :where(.sl-body) .tier-amount { font-family: var(--font-heading); font-size: 2.25rem; font-weight: 700; color: var(--c-primary); line-height: 1; }
  :where(.sl-body) .tier-period { color: var(--c-text-muted); font-size: 0.9rem; }
  :where(.sl-body) .tier-desc { margin: 0 0 1rem; }
  :where(.sl-body) .tier-features { list-style: none; padding: 0; margin: 0 0 1.25rem; display: flex; flex-direction: column; gap: 0.55rem; }
  :where(.sl-body) .tier-features li { display: flex; align-items: flex-start; gap: 0.55rem; }
  :where(.sl-body) .tier-check { flex: 0 0 auto; color: var(--c-accent); margin-top: 0.15rem; }
  :where(.sl-body) .tier-cta { margin-top: auto; align-self: stretch; text-align: center; }
  @media (max-width: 640px) { :where(.sl-body) .tier-card { flex-basis: 100%; } }

/* moved from SectionBlock scoped \3c style> (renderer-merge: comparison_table) */
:where(.sl-body) .cmp-wrap { max-width: 860px; margin: 1.5rem auto 0; overflow-x: auto; -webkit-overflow-scrolling: touch; }
  /* R14 — a comparison matrix can't stack (it would lose the side-by-side comparison), so it
     scrolls horizontally on mobile instead: min-width forces readable columns + engages the
     wrapper's overflow-x so cells never squish into unreadable word-wrap on a phone. */
  :where(.sl-body) .cmp-table { width: 100%; min-width: 520px; border-collapse: separate; border-spacing: 0; }
  :where(.sl-body) .cmp-table th, :where(.sl-body) .cmp-table td { padding: 0.85rem 1rem; text-align: center; border-bottom: 1px solid var(--c-border, rgba(0,0,0,0.1)); }
  :where(.sl-body) .cmp-table thead th { font-size: 0.95rem; font-weight: 600; color: var(--c-text); }
  :where(.sl-body) .cmp-table .cmp-rowlabel { text-align: left; font-weight: 500; color: var(--c-text); }
  :where(.sl-body) .cmp-table .cmp-hl { background: color-mix(in srgb, var(--c-accent) 10%, transparent); }
  :where(.sl-body) .cmp-table thead th.cmp-hl { background: var(--c-accent); color: var(--c-primary-dark, #fff); border-top-left-radius: 10px; border-top-right-radius: 10px; }
  :where(.sl-body) .cmp-table tbody tr:last-child td.cmp-hl { border-bottom-left-radius: 10px; border-bottom-right-radius: 10px; }
  :where(.sl-body) .cmp-yes { color: var(--c-accent); display: inline-flex; }
  :where(.sl-body) .cmp-no { color: var(--c-text-muted, #999); opacity: 0.6; display: inline-flex; }

/* moved from SectionBlock scoped \3c style> (renderer-merge: insurance_hsa) */
:where(.sl-body) .ins-band { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 2rem; background: var(--c-surface); border: 1px solid var(--c-border); border-radius: var(--card-radius, 12px); padding: 2rem 2.25rem; box-shadow: var(--card-shadow, 0 1px 3px rgba(0,0,0,0.06)); }
  :where(.sl-body) .ins-copy { flex: 1 1 320px; }
  :where(.sl-body) .ins-copy h2 { margin: 0 0 0.5rem; }
  :where(.sl-body) .ins-copy .btn { margin-top: 1rem; }
  :where(.sl-body) .ins-badges { flex: 1 1 280px; display: flex; flex-wrap: wrap; gap: 1rem; justify-content: flex-end; }
  :where(.sl-body) .ins-badge { display: flex; align-items: center; gap: 0.55rem; background: var(--c-bg); border: 1px solid var(--c-border); border-radius: 999px; padding: 0.6rem 1.1rem; font-weight: 500; font-size: 0.95rem; }
  :where(.sl-body) .ins-ic { display: inline-flex; color: var(--c-accent); }
  :where(.sl-body) .ins-ic svg { width: 22px; height: 22px; }
  @media (max-width: 640px) { :where(.sl-body) .ins-band { padding: 1.5rem; } :where(.sl-body) .ins-badges { justify-content: flex-start; } }

/* moved from SectionBlock scoped \3c style> (renderer-merge: before_after) */
/* Before / after split — two labeled figures side by side, stack on mobile */
  :where(.sl-body) .ba-row { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 1.5rem; max-width: 980px; margin: 1.5rem auto 0; }
  :where(.sl-body) .ba-fig { position: relative; margin: 0; border-radius: var(--card-radius, 12px); overflow: hidden; box-shadow: var(--card-shadow, 0 1px 3px rgba(0,0,0,0.08)); border: 1px solid var(--c-border); }
  :where(.sl-body) .ba-fig img { display: block; width: 100%; height: auto; object-fit: cover; }
  :where(.sl-body) .ba-cap { position: absolute; top: 0.75rem; left: 0.75rem; font-size: 0.8125rem; font-weight: 600; letter-spacing: 0.03em; text-transform: uppercase; padding: 0.3rem 0.7rem; border-radius: 999px; }
  :where(.sl-body) .ba-cap-before { background: var(--c-bg); color: var(--c-text); border: 1px solid var(--c-border); }
  :where(.sl-body) .ba-cap-after { background: var(--c-accent); color: var(--c-primary-dark, #fff); }
  @media (max-width: 640px) { :where(.sl-body) .ba-row { grid-template-columns: minmax(0, 1fr); } }

/* moved from SectionBlock scoped \3c style> (renderer-merge: video_embed) */
/* Responsive 16:9 video embed (YouTube / Vimeo iframe or .mp4 <video>) */
  :where(.sl-body) .video-embed-wrap { max-width: 860px; margin: 1.5rem auto 0; }
  :where(.sl-body) .video-embed-frame { position: relative; width: 100%; aspect-ratio: 16 / 9; border-radius: var(--card-radius, 12px); overflow: hidden; background: #000; box-shadow: var(--card-shadow, 0 1px 3px rgba(0,0,0,0.08)); }
  :where(.sl-body) .video-embed-frame iframe, :where(.sl-body) .video-embed-frame video { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; object-fit: cover; }
  :where(.sl-body) .video-embed-cap { margin: 0.85rem 0 0; text-align: center; color: var(--c-text-muted); font-size: 0.9rem; }

/* Generic-fallback structured section (renderGenericFallback via set:html) — moved from
   SectionBlock's scoped \3c style> because set:html markup can't use component-scoped styles. */
:where(.sl-body) .auto-intro { margin: 0 0 1rem; }
:where(.sl-body) .auto-footer { margin-top: 1rem; }
/* THE FALLBACK'S PROSE HAD NO MEASURE. renderGenericFallback's intro, body and footer paragraphs
   rendered unwrapped and ran the full ~1160px container — ~190 characters a line at 1280, the
   widest text anywhere on a generated page, and the "scrolling past a wall of one-line copy"
   feel on every section without a bespoke renderer. Same cap as .sl-prose and the addons menu
   (R7: a menu is TEXT, so it takes the text edge). Left-ragged, not centered: these paragraphs
   sit under left-set section headers and usually lead into a full-width table or card grid. */
:where(.sl-body) .auto-intro, :where(.sl-body) .auto-footer, :where(.sl-body) .auto-body { max-width: var(--content-measure); }
:where(.sl-body) .auto-table { width: 100%; border-collapse: collapse; margin: 1rem 0; }
:where(.sl-body) .auto-table th, :where(.sl-body) .auto-table td { text-align: left; padding: 0.6rem 0.75rem; border-bottom: 1px solid var(--c-border, rgba(0,0,0,0.1)); vertical-align: top; }
:where(.sl-body) .auto-table th { font-size: 0.85rem; color: var(--c-text-muted, #666); font-weight: 600; }
:where(.sl-body) .auto-table tr.is-highlight { background: var(--c-surface, rgba(0,0,0,0.04)); font-weight: 600; }
/* R14 — wide tables STACK into readable labelled rows on mobile. A 3-4 column table crammed into
   a ~375px phone wraps every word onto its own line (unreadable). Below 640px each row becomes a
   card: the first cell is the bold title, the rest show "Label: value" via their data-label. */
@media (max-width: 640px) {
  :where(.sl-body) .auto-table, :where(.sl-body) .auto-table tbody, :where(.sl-body) .auto-table tr, :where(.sl-body) .auto-table td { display: block; width: 100%; }
  :where(.sl-body) .auto-table thead { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }
  :where(.sl-body) .auto-table tr { padding: 0.9rem 0; border-bottom: 1px solid var(--c-border, rgba(0,0,0,0.12)); }
  :where(.sl-body) .auto-table tr:first-child { padding-top: 0; }
  :where(.sl-body) .auto-table td { border: none; padding: 0.15rem 0; }
  :where(.sl-body) .auto-table td:first-child { font-weight: 700; font-size: 1.05rem; margin-bottom: 0.2rem; color: var(--c-text, #1a1a1a); }
  :where(.sl-body) .auto-table td[data-label]::before { content: attr(data-label) ": "; font-weight: 700; color: var(--c-text-muted, #555); }
  :where(.sl-body) .auto-table tr.is-highlight { border-radius: var(--card-radius, 10px); padding-left: 0.85rem; padding-right: 0.85rem; }
}
:where(.sl-body) .auto-items { display: flex; flex-wrap: wrap; justify-content: center; align-items: stretch; gap: 1.25rem; margin: 1.5rem auto 0; max-width: var(--content-max); }
:where(.sl-body) .auto-item { flex: 0 1 var(--sl-basis, 300px); background: var(--c-surface); border: 1px solid var(--c-border); border-radius: var(--card-radius); padding: 1.3rem 1.4rem; box-shadow: var(--card-shadow); }
:where(.sl-body) .auto-item strong { display: block; margin-bottom: 0.3rem; font-size: 1.05rem; }
:where(.sl-body) .auto-item p { margin: 0; color: var(--c-text-muted, #555); }
@media (max-width: 640px) { :where(.sl-body) .auto-item { flex-basis: 100%; max-width: none; } }
:where(.sl-body) .auto-list { margin: 1rem 0; padding-left: 1.25rem; }
:where(.sl-body) .auto-list li { margin: 0.3rem 0; }

/* ============================================================================
   Batch B (renderer-merge): rich package/ingredient-page section renderers
   ported from the SiteLaunch editor's bespoke React blocks into the shared
   renderer so the PUBLISHED SITE renders them richly (was generic fallback).
   ============================================================================ */

/* ===== renderIngredientChoice ===== */
/* moved from 03-NewArticleModal (renderer-merge: ingredient_choice) —
   full-bleed dark "choose A vs B" comparison band (e.g. NAD+ vs NAC). */
/* Rule 6: color the SECTION wrapper dark (can't be set from inner html). Both the editor's
   scoped renderer.css form (:where(.sl-body)) and the plain site form, comma-joined. */
:where(.sl-body) :where(.sl-body) .section-ingredient_choice, :where(.sl-body) .section-ingredient_choice { background: var(--c-hero-plate); color: #fff; }
:where(.sl-body) .section-ingredient_choice .section-header h2 { color: #fff; }
:where(.sl-body) .section-ingredient_choice .section-header p { color: rgba(255,255,255,0.85); }
:where(.sl-body) .ichoice-grid { max-width: 920px; margin: 0 auto; display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); border: 1px solid rgba(255,255,255,0.18); border-radius: 12px; overflow: hidden; text-align: left; }
:where(.sl-body) .ichoice-opt { padding: 20px 22px; border-right: 1px solid rgba(255,255,255,0.18); }
:where(.sl-body) .ichoice-opt:last-child { border-right: none; }
/* The option name is the only accent-coloured text on this dark plate, and a raw accent is not
   safe here: an accent picked to sit on PAPER is often dark (CHIdrate's burnt orange #D43F16
   measures 3.5:1 on the plate, an AA fail at 16px/500). Lifting it a third of the way to the
   band's own ink keeps the colour reading as the brand's accent while clearing 4.5:1 for dark
   accents; light accents (a gold, say) only get brighter, so no brand loses legibility. This was
   invisible to visual-lint until the band stopped being repainted beige — it only measures text
   whose band resolves to a real colour. */
:where(.sl-body) .ichoice-name { font-size: 1rem; font-weight: 500; color: color-mix(in srgb, var(--c-accent) 68%, #fff); margin-bottom: 10px; }
:where(.sl-body) .ichoice-desc { font-size: 0.875rem; line-height: 1.6; color: rgba(255,255,255,0.88); margin-bottom: 12px; }
/* The price sits between the option's name and its reasoning, because that is the order the
   question is asked in: which one is this, what does it cost, and why would I pick it. Set in
   surface ink rather than the accent — the NAME is the only accent-coloured text on this plate
   (see above) and a second accent line would leave neither of them leading. */
:where(.sl-body) .ichoice-price { font-size: 1.25rem; font-weight: 600; letter-spacing: -0.01em; line-height: 1.2; color: #fff; margin: -4px 0 10px; }
:where(.sl-body) .ichoice-best { font-size: 0.8125rem; color: rgba(255,255,255,0.7); }
:where(.sl-body) .ichoice-best strong { color: #fff; }
:where(.sl-body) .ichoice-tiebreaker { max-width: 720px; margin: 22px auto 0; text-align: center; font-size: 0.875rem; font-style: italic; color: rgba(255,255,255,0.75); }
/* R14 — stack the multi-column choice grid to a single column on mobile;
   swap the inter-column right borders for row-dividing bottom borders. */
@media (max-width: 640px) {
  :where(.sl-body) .ichoice-grid { grid-template-columns: minmax(0, 1fr); }
  :where(.sl-body) .ichoice-opt { border-right: none; border-bottom: 1px solid rgba(255,255,255,0.18); }
  :where(.sl-body) .ichoice-opt:last-child { border-bottom: none; }
}

/* ===== renderValueStack ===== */
/* value_stack — "if you built it yourself" cost-comparison table (ported from 03-NewArticleModal.jsx bespoke block) */
:where(.sl-body) .vstack-wrap { max-width: 720px; margin: 1.5rem auto 0; background: var(--c-surface); border: 1px solid var(--c-border, #e5e8ec); border-radius: 12px; overflow: hidden; }
  :where(.sl-body) .vstack-table { width: 100%; border-collapse: collapse; text-align: left; }
  :where(.sl-body) .vstack-table th, :where(.sl-body) .vstack-table td { padding: 0.875rem 1.125rem; font-size: 0.875rem; vertical-align: top; }
  :where(.sl-body) .vstack-table thead th { background: var(--c-room); color: #fff; font-size: 0.8125rem; font-weight: 500; padding: 0.75rem 1.125rem; }
  :where(.sl-body) .vstack-table th:last-child, :where(.sl-body) .vstack-table td:last-child { width: 240px; }
  :where(.sl-body) .vstack-table tbody tr + tr td { border-top: 1px solid var(--c-border, #eef0f3); }
  :where(.sl-body) .vstack-label { color: var(--c-text); }
  :where(.sl-body) .vstack-cost { color: var(--c-text-secondary, #5a6270); }
  :where(.sl-body) .vstack-row-hl td { background: color-mix(in srgb, var(--c-primary) 5%, var(--c-surface)); font-weight: 700; }
  :where(.sl-body) .vstack-row-hl .vstack-cost { color: var(--c-primary); }
:where(.sl-body) .vstack-footer { max-width: 720px; margin: 1rem auto 0; text-align: center; font-style: italic; font-size: 0.875rem; color: var(--c-text-secondary, #5a6270); }
  /* R14 — stack the 2-column table to one column on mobile; hide the header row and re-attach the
     "Cost" label to the value cell so the meaning survives the stack. */
  @media (max-width: 640px) {
    :where(.sl-body) .vstack-table, :where(.sl-body) .vstack-table tbody { display: block; width: 100%; }
    :where(.sl-body) .vstack-table thead { display: none; }
    :where(.sl-body) .vstack-table tr { display: block; padding: 0.875rem 1.125rem; }
    :where(.sl-body) .vstack-table tbody tr + tr { border-top: 1px solid var(--c-border, #eef0f3); }
    :where(.sl-body) .vstack-table td { display: block; width: 100%; padding: 0; }
    :where(.sl-body) .vstack-table th:last-child, :where(.sl-body) .vstack-table td:last-child { width: 100%; }
    :where(.sl-body) .vstack-label { margin-bottom: 0.25rem; }
    :where(.sl-body) .vstack-cost::before { content: "Cost: "; color: var(--c-text-secondary, #5a6270); font-weight: 500; }
    :where(.sl-body) .vstack-row-hl .vstack-cost::before { color: inherit; }
  }

/* ===== renderPersonas ===== */
/* ── personas (who-it's-for split: bullet list + optional portrait) ── */
:where(.sl-body) .personas-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 2.25rem; align-items: center; }
:where(.sl-body) .personas-grid.personas-has-img { grid-template-columns: minmax(0, 1fr) minmax(280px, 420px); }
/* Keep readable line length when there's no image column. */
:where(.sl-body) .personas-grid:not(.personas-has-img) .personas-copy { max-width: var(--content-measure); }
:where(.sl-body) .personas-headline { font-size: 2rem; font-weight: 500; letter-spacing: -0.02em; margin: 0 0 1.5rem; color: var(--c-text); }
:where(.sl-body) .personas-list { padding-left: 1.375rem; margin: 0; list-style: disc; }
:where(.sl-body) .personas-item { margin-bottom: 1rem; font-size: 0.9375rem; line-height: 1.6; color: var(--c-text-secondary, #5a6270); }
:where(.sl-body) .personas-item:last-child { margin-bottom: 0; }
:where(.sl-body) .personas-lead { color: var(--c-text); }
:where(.sl-body) .personas-media { border-radius: 12px; overflow: hidden; box-shadow: 0 8px 32px rgba(8,37,44,0.18); aspect-ratio: 4 / 5; }
:where(.sl-body) .personas-media img { width: 100%; height: 100%; object-fit: cover; display: block; }
@media (max-width: 640px) {
  :where(.sl-body) .personas-grid.personas-has-img { grid-template-columns: minmax(0, 1fr); }
  :where(.sl-body) .personas-media { max-width: 420px; margin: 0 auto; }
}

/* ===== renderIngredientsBreakdown ===== */
/* ── ingredients_breakdown: 2-col "Ingredient / What It Does in This Formula" table ── */
:where(.sl-body) .ibreak-panel { max-width: var(--content-measure); margin: 0 auto; background: var(--c-surface); border: 1px solid var(--c-border); border-radius: 12px; overflow: hidden; }
:where(.sl-body) .ibreak-table { width: 100%; border-collapse: collapse; }
:where(.sl-body) .ibreak-table thead th { background: var(--c-room); color: #fff; text-align: left; font-size: 0.8125rem; font-weight: 500; padding: 0.75rem 1.125rem; }
:where(.sl-body) .ibreak-table thead th.ibreak-col-name { width: 260px; }
:where(.sl-body) .ibreak-table td { padding: 0.875rem 1.125rem; vertical-align: top; font-size: 0.875rem; }
:where(.sl-body) .ibreak-table tbody tr + tr td { border-top: 1px solid var(--c-border); }
:where(.sl-body) .ibreak-name { width: 260px; font-weight: 500; color: var(--c-primary); }
:where(.sl-body) .ibreak-desc { color: var(--c-text-secondary, #5a6270); line-height: 1.55; }
@media (max-width: 640px) {
  /* R14 — stack the data table to a single column on narrow viewports */
  :where(.sl-body) .ibreak-table thead { display: none; }
  :where(.sl-body) .ibreak-table tr, :where(.sl-body) .ibreak-table td { display: block; width: auto; }
  :where(.sl-body) .ibreak-table tbody tr + tr td { border-top: none; }
  :where(.sl-body) .ibreak-table tbody tr + tr { border-top: 1px solid var(--c-border); }
  :where(.sl-body) .ibreak-name { padding-bottom: 0.15rem; }
  :where(.sl-body) .ibreak-desc { padding-top: 0.15rem; }
}

/* ===== renderWhyUs ===== */
/* ── why_us — client "why choose us" centered feature cards (ports the why_us block from 03-NewArticleModal.jsx) ── */
:where(.sl-body) .whyus-eyebrow { color: var(--c-primary); font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; font-size: 0.8125rem; margin-bottom: 0.5rem; }
/* Column width follows the renderer's computed --sl-basis (cardBasis, non-orphaning counts);
   a fixed 260px minmax ignored it and orphaned 4 cards as 3+1 under narrower measures. */
:where(.sl-body) .whyus-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(var(--sl-basis, 260px), 100%), minmax(0, 1fr))); gap: 1.125rem; margin-left: auto; margin-right: auto; max-width: var(--content-max); }
:where(.sl-body).meas-narrow .whyus-grid { grid-template-columns: repeat(auto-fit, minmax(min(calc(var(--sl-basis, 260px) * 0.85), 100%), minmax(0, 1fr))); }
:where(.sl-body) .whyus-card { background: var(--c-surface); border: 1px solid var(--c-border); border-radius: 12px; padding: 22px 20px; text-align: center; }
:where(.sl-body) .whyus-title { color: var(--c-primary); font-size: 1.0625rem; font-weight: 600; line-height: 1.3; margin: 0 0 0.625rem; }
:where(.sl-body) .whyus-body { color: var(--c-text-secondary, #5a6270); font-size: 0.9rem; line-height: 1.6; margin: 0; }
/* R14: stack cards to one column on mobile */
@media (max-width: 640px) { :where(.sl-body) .whyus-grid { grid-template-columns: minmax(0, 1fr); } }

/* ===== renderTierComparison ===== */
/* renderer-merge: tier_comparison (full-bleed dark package/tier comparison table) */
/* Rule 6 — color the SECTION wrapper dark (inner html can't set the band background).
   Both the :where(.sl-body) scoped form (editor renderer.css) and the plain form (site). */
:where(.sl-body) :where(.sl-body) .section-tier_comparison, :where(.sl-body) .section-tier_comparison { background: var(--c-hero-plate); color: #fff; }
/* light-on-dark header text (override the muted defaults inside this dark band) */
:where(.sl-body) .section-tier_comparison .section-header h2, :where(.sl-body) .section-tier_comparison .section-header h2 { color: #fff; }
:where(.sl-body) .section-tier_comparison .section-header p.tiercmp-intro, :where(.sl-body) .section-tier_comparison .section-header p.tiercmp-intro { color: rgba(255,255,255,0.8); }

:where(.sl-body) .tiercmp-wrap { max-width: 1000px; margin: 0 auto; }
:where(.sl-body) .tiercmp-panel { background: rgba(255,255,255,0.04); border: 1px solid rgba(255,255,255,0.18); border-radius: 12px; overflow: hidden; }
:where(.sl-body) .tiercmp-table { width: 100%; border-collapse: collapse; }
:where(.sl-body) .tiercmp-table thead th { background: var(--c-room); color: #fff; text-align: left; font-size: 0.78rem; font-weight: 600; letter-spacing: 0.02em; padding: 0.75rem 1rem; }
:where(.sl-body) .tiercmp-table thead th:nth-child(1) { width: 180px; }
:where(.sl-body) .tiercmp-table thead th:nth-child(2) { width: 90px; }
:where(.sl-body) .tiercmp-table tbody td { padding: 0.9rem 1rem; font-size: 0.85rem; color: rgba(255,255,255,0.85); line-height: 1.55; vertical-align: top; border-top: 1px solid rgba(255,255,255,0.12); }
:where(.sl-body) .tiercmp-table tbody tr:first-child td { border-top: none; }
:where(.sl-body) .tiercmp-table td.tiercmp-pkg { color: #fff; font-weight: 600; }
:where(.sl-body) .tiercmp-table td.tiercmp-price { color: var(--c-accent-ink-dark, var(--c-accent)); font-weight: 600; }
:where(.sl-body) .tiercmp-footer { max-width: 720px; margin: 1.15rem auto 0; text-align: center; font-style: italic; font-size: 0.9rem; color: rgba(255,255,255,0.75); }
/* R14 — a per-package data table STACKS to one column on mobile (label-prefixed cells) */
@media (max-width: 640px) {
  :where(.sl-body) .tiercmp-table thead { display: none; }
  :where(.sl-body) .tiercmp-table, :where(.sl-body) .tiercmp-table tbody, :where(.sl-body) .tiercmp-table tr, :where(.sl-body) .tiercmp-table td { display: block; width: 100%; }
  :where(.sl-body) .tiercmp-table tbody td { border-top: none; padding: 0.3rem 1rem; }
  :where(.sl-body) .tiercmp-table tbody tr { border-top: 1px solid rgba(255,255,255,0.12); padding: 0.85rem 0; }
  :where(.sl-body) .tiercmp-table tbody tr:first-child { border-top: none; }
  :where(.sl-body) .tiercmp-table tbody td:not(.tiercmp-pkg)::before { content: attr(data-label) ": "; font-weight: 600; color: rgba(255,255,255,0.55); }
  :where(.sl-body) .tiercmp-table td.tiercmp-pkg { font-size: 1rem; padding-top: 0.2rem; padding-bottom: 0.4rem; }
}


/* ═══ HARVESTED SIGNATURE COMPONENTS ═══ */

/* ===== renderPressLogoBar ===== */
/* press_logo_bar — Drip/Peach-style "As Featured In" credibility strip: a muted
   greyscale eyebrow over a centered, wrapping row of publication logos. A missing
   logo image falls back to a serif wordmark (.press-logo-wordmark) so no slot is
   ever blank. Emits no scoped CSS from the renderer; all styles live here. */
:where(.sl-body) .press-bar { max-width: var(--content-max); margin: 0 auto; text-align: center; }
:where(.sl-body) .press-bar-eyebrow { color: var(--c-text-muted); font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase; font-size: 0.78rem; margin-bottom: 1.5rem; opacity: 0.85; }
:where(.sl-body) .press-bar-logos { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 1.75rem 3rem; }
:where(.sl-body) .press-logo { display: inline-flex; align-items: center; justify-content: center; }
:where(.sl-body) .press-logo img { max-height: 38px; max-width: 160px; width: auto; height: auto; object-fit: contain; filter: grayscale(1); opacity: 0.65; transition: filter 0.2s ease, opacity 0.2s ease; }
:where(.sl-body) .press-logo:hover img { filter: grayscale(0); opacity: 1; }
/* Serif wordmark fallback — reads like a masthead regardless of the brand's sans body font. */
:where(.sl-body) .press-logo-wordmark span { font-family: Georgia, 'Times New Roman', 'Playfair Display', serif; font-size: 1.5rem; font-weight: 600; letter-spacing: 0.01em; line-height: 1; white-space: nowrap; color: var(--c-text-muted); opacity: 0.8; transition: color 0.2s ease, opacity 0.2s ease; }
:where(.sl-body) .press-logo-wordmark:hover span { color: var(--c-text); opacity: 1; }
@media (max-width: 640px) {
  :where(.sl-body) .press-bar-eyebrow { margin-bottom: 1.15rem; }
  :where(.sl-body) .press-bar-logos { gap: 1.25rem 2rem; }
  :where(.sl-body) .press-logo img { max-height: 28px; max-width: 120px; }
  :where(.sl-body) .press-logo-wordmark span { font-size: 1.2rem; }
}


/* Outcome stat row — bordered tiles of BIG defensible outcome numbers (renderOutcomeStatRow).
   Distinct from the .stats-band dark band: a clean, restrained proof strip that auto-fits 3-4
   tiles across on desktop and stacks safely on mobile. */
:where(.sl-body) .outcome-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 1rem;
  max-width: var(--content-max);
  margin: 0 auto;
}
:where(.sl-body) .outcome-tile {
  text-align: center;
  padding: 1.75rem 1.25rem;
  border: 1px solid var(--c-border);
  border-radius: var(--card-radius);
  background: color-mix(in srgb, var(--c-primary) 3%, var(--c-surface));
}
:where(.sl-body) .outcome-value {
  font-family: var(--font-heading);
  font-weight: var(--heading-weight, 700);
  font-size: clamp(2.25rem, 4.5vw, 3.25rem);
  line-height: 1;
  letter-spacing: -0.02em;
  color: var(--c-primary);
  font-variant-numeric: tabular-nums;
}
:where(.sl-body) .outcome-label {
  margin-top: 0.55rem;
  color: var(--c-text-muted);
  font-size: 0.98rem;
  line-height: 1.4;
}
:where(.sl-body) .outcome-detail {
  margin-top: 0.35rem;
  color: var(--c-text-muted);
  font-size: 0.82rem;
  opacity: 0.85;
}
@media (max-width: 768px) {
  :where(.sl-body) .outcome-row { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.75rem; }
  :where(.sl-body) .outcome-tile { padding: 1.35rem 1rem; }
}
@media (max-width: 420px) {
  :where(.sl-body) .outcome-row { grid-template-columns: minmax(0, 1fr); }
}


/* ── guarantee_callout: badge-forward risk-reversal panel ───────────────────── */
:where(.sl-body) .guarantee-callout {
  display: flex;
  align-items: center;
  gap: 1.75rem;
  max-width: var(--content-max);
  margin: 0 auto;
  padding: 1.9rem 2.15rem;
  border: 1px solid var(--c-border);
  border-radius: var(--card-radius);
  background: linear-gradient(180deg, color-mix(in srgb, var(--c-primary) 5%, var(--c-surface)), var(--c-surface));
  box-shadow: 0 14px 36px rgba(8, 18, 22, 0.06);
  position: relative;
  overflow: hidden;
}
/* Accent spine — reads as a certified/sealed panel, not a plain card. */
:where(.sl-body) .guarantee-callout::before {
  content: "";
  position: absolute;
  left: 0; top: 0; bottom: 0;
  width: 4px;
  background: linear-gradient(180deg, var(--c-primary), var(--c-accent));
}
:where(.sl-body) .guarantee-seal {
  flex: 0 0 auto;
  width: 78px; height: 78px;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%;
  color: var(--c-primary);
  background: color-mix(in srgb, var(--c-primary) 12%, var(--c-surface));
  box-shadow: inset 0 0 0 1.5px color-mix(in srgb, var(--c-primary) 24%, transparent),
              inset 0 1px 0 color-mix(in srgb, #fff 55%, transparent);
}
:where(.sl-body) .guarantee-seal-ic { width: 42px; height: 42px; }
:where(.sl-body) .guarantee-copy { min-width: 0; }
:where(.sl-body) .guarantee-eyebrow {
  display: inline-block;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--c-primary);
  background: color-mix(in srgb, var(--c-primary) 9%, var(--c-surface));
  border: 1px solid color-mix(in srgb, var(--c-primary) 18%, transparent);
  padding: 0.28rem 0.72rem;
  border-radius: 999px;
  margin-bottom: 0.7rem;
}
:where(.sl-body) .guarantee-headline {
  font-family: var(--font-heading);
  font-size: clamp(1.3rem, 2.4vw, 1.7rem);
  line-height: 1.15;
  letter-spacing: -0.01em;
  margin: 0;
  color: var(--c-text);
}
:where(.sl-body) .guarantee-body {
  color: var(--c-text-muted);
  line-height: 1.6;
  margin: 0.55rem 0 0;
  max-width: 62ch;
}
:where(.sl-body) .guarantee-fine {
  color: var(--c-text-muted);
  opacity: 0.82;
  font-size: 0.85rem;
  line-height: 1.5;
  margin: 0.7rem 0 0;
  max-width: 64ch;
}
/* Mobile: stack the seal above centered copy. */
@media (max-width: 640px) {
  :where(.sl-body) .guarantee-callout {
    flex-direction: column;
    text-align: center;
    gap: 1.1rem;
    padding: 1.6rem 1.25rem;
  }
  :where(.sl-body) .guarantee-callout::before { display: none; }
  :where(.sl-body) .guarantee-body, :where(.sl-body) .guarantee-fine { margin-left: auto; margin-right: auto; }
}


/* ── authority_founder_block: portrait-led Medical Director / founder authority band ── */
:where(.sl-body) .afb { display: grid; grid-template-columns: minmax(240px, 0.82fr) 1.18fr; gap: clamp(1.75rem, 4vw, 3.25rem); align-items: center; max-width: var(--content-max); margin: 0 auto; }
:where(.sl-body) .afb-portrait { padding: 10px; border-radius: 26px; background: linear-gradient(160deg, color-mix(in srgb, var(--c-primary) 16%, var(--c-surface)), var(--c-surface)); box-shadow: 0 24px 55px -24px rgba(16,24,32,0.40); }
:where(.sl-body) .afb-portrait img { display: block; width: 100%; aspect-ratio: 4 / 5; object-fit: cover; border-radius: 18px; }
:where(.sl-body) .afb-copy { min-width: 0; }
:where(.sl-body) .afb-copy .eyebrow, :where(.sl-body) .afb-card .eyebrow { color: var(--c-accent); font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase; font-size: 0.82rem; margin-bottom: 0.55rem; }
:where(.sl-body) .afb-name { font-family: var(--font-heading); font-size: clamp(1.55rem, 3vw, 2.25rem); line-height: 1.12; letter-spacing: -0.01em; margin: 0 0 0.4rem; }
:where(.sl-body) .afb-role { color: var(--c-text); font-weight: 600; font-size: 1.05rem; }
:where(.sl-body) .afb-creds { color: var(--c-text-muted); font-size: 0.95rem; margin-top: 0.15rem; }
:where(.sl-body) .afb-bio { color: var(--c-text-muted); line-height: 1.72; margin: 1.1rem 0 1.4rem; max-width: 60ch; }
:where(.sl-body) .afb-trust { display: inline-flex; align-items: center; gap: 0.55rem; padding: 0.5rem 1.05rem; border: 1px solid var(--c-border); border-radius: 999px; background: color-mix(in srgb, var(--c-primary) 5%, var(--c-surface)); font-size: 0.92rem; font-weight: 600; color: var(--c-text); }
:where(.sl-body) .afb-trust svg { flex: 0 0 auto; color: var(--c-primary); }
/* Text-only authority card (no headshot resolved): centered card + initials medallion. */
:where(.sl-body) .afb-card { max-width: var(--content-measure); margin: 0 auto; display: flex; flex-direction: column; align-items: center; text-align: center; padding: clamp(1.9rem, 4vw, 2.9rem); }
:where(.sl-body) .afb-card .afb-bio { margin-left: auto; margin-right: auto; }
:where(.sl-body) .afb-medallion { width: 84px; height: 84px; margin-bottom: 1.1rem; border-radius: 50%; display: grid; place-items: center; font-family: var(--font-heading); font-weight: 700; font-size: 1.75rem; color: var(--c-primary); background: color-mix(in srgb, var(--c-primary) 12%, var(--c-surface)); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--c-primary) 22%, transparent); }
@media (max-width: 768px) {
  :where(.sl-body) .afb { grid-template-columns: minmax(0, 1fr); gap: 1.75rem; justify-items: center; text-align: center; }
  :where(.sl-body) .afb-portrait { max-width: 300px; }
  :where(.sl-body) .afb-copy .afb-bio { margin-left: auto; margin-right: auto; }
  :where(.sl-body) .afb-trust { justify-content: center; }
}


/* ── promo_code_banner: slim full-bleed accent offer strip with a click-to-copy code chip ──
   The section itself carries the full-width accent band (edge to edge); content stays inside the
   .container. Text uses --c-primary-dark on accent, mirroring the site's own .btn-accent pairing. */
:where(.sl-body) .section-promo_code_banner {
  padding: 0 !important;
  border-top: none !important;
  background: linear-gradient(90deg, var(--c-accent) 0%, color-mix(in srgb, var(--c-accent) 85%, var(--c-primary)) 100%) !important;
}
:where(.sl-body) .section-promo_code_banner + .section { border-top: none; }
:where(.sl-body) .promo-strip {
  display: flex; align-items: center; justify-content: center; flex-wrap: wrap;
  gap: 0.5rem 1rem; padding: 0.72rem 0; text-align: center; color: var(--c-primary-dark);
}
:where(.sl-body) .promo-strip-icon { display: inline-flex; line-height: 0; opacity: 0.9; }
:where(.sl-body) .promo-strip-msg { font-weight: 600; font-size: 0.95rem; letter-spacing: 0.01em; }
:where(.sl-body) .promo-code-chip {
  display: inline-flex; align-items: center; gap: 0.5rem; font: inherit; cursor: pointer;
  padding: 0.3rem 0.5rem 0.3rem 0.85rem; color: var(--c-primary-dark);
  background: rgba(255,255,255,0.28);
  border: 1.5px dashed color-mix(in srgb, var(--c-primary-dark) 45%, transparent);
  border-radius: 999px;
  transition: background 0.15s ease, border-color 0.15s ease, transform 0.08s ease;
}
:where(.sl-body) .promo-code-chip:hover { background: rgba(255,255,255,0.46); border-color: color-mix(in srgb, var(--c-primary-dark) 60%, transparent); }
:where(.sl-body) .promo-code-chip:active { transform: translateY(1px); }
:where(.sl-body) .promo-code-chip:focus-visible { outline: 2px solid var(--c-primary-dark); outline-offset: 2px; }
:where(.sl-body) .promo-code-text { font-weight: 700; text-transform: uppercase; letter-spacing: 0.09em; font-size: 0.95rem; }
:where(.sl-body) .promo-code-copy {
  display: inline-flex; align-items: center; gap: 0.28rem; padding: 0.14rem 0.5rem;
  border-radius: 999px; background: color-mix(in srgb, var(--c-primary-dark) 14%, transparent);
  font-size: 0.7rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.06em;
}
:where(.sl-body) .promo-code-chip.is-copied { background: rgba(255,255,255,0.55); }
:where(.sl-body) .promo-code-chip.is-copied .promo-code-copy { background: color-mix(in srgb, var(--c-primary-dark) 24%, transparent); }
:where(.sl-body) .promo-strip-cta { display: inline-flex; align-items: center; gap: 0.32rem; font-weight: 700; font-size: 0.9rem; color: var(--c-primary-dark); text-decoration: underline; text-underline-offset: 3px; }
:where(.sl-body) .promo-strip-cta:hover { text-decoration: none; }
@media (max-width: 768px) {
  :where(.sl-body) .promo-strip { flex-direction: column; gap: 0.55rem; padding: 0.8rem 0; }
  :where(.sl-body) .promo-strip-msg { font-size: 0.9rem; }
}


/* ── competitor_fee_callout — us-vs-them "$0 travel fee" cost contrast ───────────── */
:where(.sl-body) .cfc-grid { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 1.5rem; max-width: var(--content-max); margin: 2rem auto 0; align-items: stretch; }
:where(.sl-body) .cfc-panel { position: relative; display: flex; flex-direction: column; padding: 2rem 1.75rem; border-radius: var(--card-radius); border: 1px solid var(--c-border); background: var(--c-surface); text-align: center; }
:where(.sl-body) .cfc-panel-them { background: color-mix(in srgb, var(--c-text) 4%, var(--c-surface)); }
:where(.sl-body) .cfc-panel-ours { border: 2px solid var(--c-accent); background: color-mix(in srgb, var(--c-accent) 7%, var(--c-surface)); box-shadow: 0 18px 44px color-mix(in srgb, var(--c-primary) 16%, transparent); }
:where(.sl-body) .cfc-panel-label { font-weight: 600; font-size: 0.8rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--c-text-muted); margin-bottom: 0.85rem; }
:where(.sl-body) .cfc-panel-ours .cfc-panel-label { color: var(--c-primary); }
:where(.sl-body) .cfc-fee { font-family: var(--font-heading); font-size: clamp(2.6rem, 6vw, 3.6rem); font-weight: 700; line-height: 1; letter-spacing: -0.02em; }
:where(.sl-body) .cfc-fee-strike { color: var(--c-text-muted); text-decoration: line-through; text-decoration-thickness: 2px; text-decoration-color: color-mix(in srgb, var(--c-text-muted) 55%, transparent); opacity: 0.9; }
:where(.sl-body) .cfc-fee-ours { color: var(--c-accent); }
:where(.sl-body) .cfc-fee-note { margin-top: 0.5rem; font-size: 0.92rem; color: var(--c-text-muted); }
:where(.sl-body) .cfc-panel-ours .cfc-fee-note { color: var(--c-text); }
:where(.sl-body) .cfc-list { list-style: none; padding: 0; margin: 1.4rem 0 0; text-align: left; display: flex; flex-direction: column; gap: 0.65rem; }
:where(.sl-body) .cfc-li { display: flex; align-items: flex-start; gap: 0.6rem; font-size: 0.95rem; line-height: 1.45; }
:where(.sl-body) .cfc-li-no { color: var(--c-text-muted); }
:where(.sl-body) .cfc-li-yes { color: var(--c-text); }
:where(.sl-body) .cfc-no, :where(.sl-body) .cfc-yes { flex: 0 0 auto; display: inline-flex; align-items: center; justify-content: center; width: 22px; height: 22px; border-radius: 999px; margin-top: 0.06rem; }
:where(.sl-body) .cfc-no { background: color-mix(in srgb, var(--c-text-muted) 16%, transparent); color: var(--c-text-muted); }
:where(.sl-body) .cfc-yes { background: var(--c-accent); color: var(--c-primary-dark); }
:where(.sl-body) .cfc-save-badge { position: absolute; top: -0.85rem; left: 50%; transform: translateX(-50%); background: var(--c-accent); color: var(--c-primary-dark); font-size: 0.72rem; font-weight: 700; letter-spacing: 0.06em; text-transform: uppercase; padding: 0.32rem 0.9rem; border-radius: 999px; white-space: nowrap; box-shadow: 0 6px 16px color-mix(in srgb, var(--c-accent) 40%, transparent); }
:where(.sl-body) .cfc-vs { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); z-index: 2; width: 48px; height: 48px; display: flex; align-items: center; justify-content: center; border-radius: 999px; background: var(--c-surface); border: 1px solid var(--c-border); color: var(--c-text-muted); font-family: var(--font-heading); font-weight: 700; font-size: 0.9rem; text-transform: uppercase; box-shadow: 0 4px 14px rgba(0, 0, 0, 0.1); }
:where(.sl-body) .cfc-foot { max-width: 56ch; margin: 1.5rem auto 0; text-align: center; color: var(--c-text-muted); font-size: 0.95rem; }
:where(.sl-body) .cfc-cta { margin-top: 1.75rem; text-align: center; }
@media (max-width: 768px) {
  :where(.sl-body) .cfc-grid { grid-template-columns: minmax(0, 1fr); gap: 2.5rem; }
  :where(.sl-body) .cfc-vs { position: static; transform: none; margin: -0.5rem auto; }
  :where(.sl-body) .cfc-panel { padding: 1.75rem 1.25rem; }
}
/* --- addons_boosters_grid --- */
/* Add-ons / boosters menu — priced upsell cards with a +$price PILL (renderAddonsBoostersGrid).
   The pill (and, for dosed boosters, the per-mg price rows) is what reads this as a MENU rather
   than a bullet list. Flexbox basis grid (like .cards-center): balances 2-3 across on desktop and
   stacks to one column on mobile. */
:where(.sl-body) .addon-grid { display: flex; flex-wrap: wrap; justify-content: center; align-items: stretch; gap: 1.25rem; max-width: var(--content-max); margin: 0 auto; }
:where(.sl-body) .addon-card { flex: 0 1 var(--sl-basis, 320px); display: flex; flex-direction: column; padding: 1.5rem 1.5rem 1.35rem; background: var(--c-surface); border: 1px solid var(--c-border); border-radius: var(--card-radius); box-shadow: var(--card-shadow); transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease; }
:where(.sl-body) .addon-card:hover { transform: translateY(-3px); border-color: color-mix(in srgb, var(--c-accent) 45%, var(--c-border)); box-shadow: 0 18px 40px -18px color-mix(in srgb, var(--c-primary) 32%, transparent); }
:where(.sl-body) .addon-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 0.85rem; }
:where(.sl-body) .addon-name { font-family: var(--font-heading); font-size: 1.12rem; line-height: 1.3; margin: 0; }
:where(.sl-body) .addon-pill { flex: none; display: inline-flex; align-items: center; padding: 0.32rem 0.8rem; border-radius: 999px; background: color-mix(in srgb, var(--c-accent) 14%, var(--c-surface)); border: 1px solid color-mix(in srgb, var(--c-accent) 42%, transparent); color: var(--c-primary-dark, var(--c-primary)); font-weight: 700; font-size: 0.98rem; font-variant-numeric: tabular-nums; white-space: nowrap; }
:where(.sl-body) .addon-desc { margin: 0.7rem 0 0; color: var(--c-text-muted); font-size: 0.95rem; line-height: 1.55; }
:where(.sl-body) .addon-tiers { list-style: none; margin: 0.95rem 0 0; padding: 0.85rem 0 0; border-top: 1px dashed var(--c-border); display: flex; flex-direction: column; gap: 0.5rem; }
:where(.sl-body) .addon-tier { display: flex; align-items: baseline; gap: 0.5rem; font-size: 0.95rem; }
:where(.sl-body) .addon-tier-label { color: var(--c-text); white-space: nowrap; }
:where(.sl-body) .addon-tier-dots { flex: 1 1 auto; align-self: center; border-bottom: 1px dotted color-mix(in srgb, var(--c-text-muted) 55%, transparent); }
:where(.sl-body) .addon-tier-price { flex: none; color: var(--c-primary); font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }
:where(.sl-body) .addon-note { display: inline-flex; align-items: center; gap: 0.45rem; margin-top: auto; padding-top: 1rem; color: var(--c-text-muted); font-size: 0.8rem; letter-spacing: 0.03em; text-transform: uppercase; font-weight: 600; }
:where(.sl-body) .addon-note-plus { display: inline-flex; align-items: center; justify-content: center; width: 1.1rem; height: 1.1rem; border-radius: 999px; background: color-mix(in srgb, var(--c-accent) 16%, var(--c-surface)); color: var(--c-accent); font-weight: 800; line-height: 1; flex: none; }
:where(.sl-body) .addon-cta { text-align: center; margin-top: 1.75rem; }
@media (max-width: 768px) {
  :where(.sl-body) .addon-grid { gap: 1rem; }
  :where(.sl-body) .addon-card { flex-basis: 100%; padding: 1.35rem 1.25rem; }
}
/* --- membership_vip_tiers (ribbon; reuses .tier-*) --- */
  /* Save-X% ribbon — featured membership/VIP tier (membership_vip_tiers). Reuses .tier-card; a
     self-contained corner flag, so it needs no overflow clip (like .tier-badge it overhangs the top). */
  :where(.sl-body) .tier-card .tier-ribbon { position: absolute; top: -0.7rem; right: 1rem; z-index: 2; background: var(--c-accent); color: var(--c-primary-dark, #fff); font-size: 0.72rem; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase; padding: 0.34rem 0.75rem 0.4rem; border-radius: 4px 4px 4px 0; white-space: nowrap; box-shadow: 0 6px 16px color-mix(in srgb, var(--c-accent) 38%, transparent); }
  :where(.sl-body) .tier-card .tier-ribbon::after { content: ''; position: absolute; top: 100%; left: 0; border: 0.32rem solid transparent; border-top-color: color-mix(in srgb, var(--c-accent) 60%, #000); border-left-width: 0; }

  /* Placement: add these two rules inside the existing pricing_tiers block in src/styles/global.css,
     right after `.tier-cta { ... }` (line ~2140) and before the `@media (max-width: 640px)` rule that
     closes the tier block. They live next to the other .tier-* rules; the base .pricing-tiers /
     .tier-card / .tier-featured / .tier-badge / .tier-name / .tier-price / .tier-period / .tier-desc /
     .tier-features / .tier-check / .tier-cta styles are ALREADY present and are reused unchanged. */
/* --- symptom_first_browse (reuses .cat-*) --- */
/* symptom_first_browse — reuses the .cat-grid/.cat-card icon tiles (defined above); this only
   adds the mapped-drip sub-label under each symptom. Must be placed AFTER the .cat-card rules. */
:where(.sl-body) .cat-card.sfb-card { gap: 0.5rem; }
/* NOT inline-flex: when the drip name wraps to two lines the flex box stretches to the card
   width and strands the arrow against the left edge, away from the centred text. Plain inline
   keeps the arrow as the first token of the centred text flow, so it wraps with it. */
:where(.sl-body) .sfb-drip { display: inline; color: var(--c-text-muted); font-size: 0.85rem; font-weight: 500; line-height: 1.3; }
:where(.sl-body) .sfb-arrow { color: var(--c-primary); font-weight: 700; margin-right: 0.3rem; }
@media (max-width: 640px) { :where(.sl-body) .sfb-drip { font-size: 0.82rem; } }
/* --- dual_pricing_packages --- */
/* Dual-pricing skin (.pkg-card--dual): a per-brand treatment on the standard .pkg-card that shows
   TWO labelled prices — in-clinic vs mobile — instead of a single figure. Activated purely by DATA
   (a package carrying BOTH an in-clinic and a mobile rate); when only one price is present the
   single-price markup renders, so this degrades cleanly with no visual gap. Rows are a flex column,
   so they already stack correctly on mobile. Uses brand tokens only. */
:where(.sl-body) .pkg-dual-prices { display: flex; flex-direction: column; gap: 0.4rem; width: 100%; max-width: 220px; margin: 0.55rem auto 0.2rem; }
:where(.sl-body) .pkg-price-row { display: flex; align-items: baseline; justify-content: space-between; gap: 0.75rem; padding: 0.42rem 0.75rem; border-radius: calc(var(--card-radius) - 4px); background: color-mix(in srgb, var(--c-primary) 6%, var(--c-surface)); border: 1px solid var(--c-border); }
:where(.sl-body) .pkg-price-row--mobile { background: color-mix(in srgb, var(--c-accent) 10%, var(--c-surface)); border-color: color-mix(in srgb, var(--c-accent) 34%, var(--c-border)); }
:where(.sl-body) .pkg-price-tier { font-size: 0.72rem; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: var(--c-text-muted); }
:where(.sl-body) .pkg-price-amt { font-size: 1.18rem; font-weight: 700; line-height: 1; color: var(--c-primary); font-variant-numeric: tabular-nums; }
:where(.sl-body) .pkg-price-row--mobile .pkg-price-amt { color: var(--c-accent-ink, var(--c-accent)); }
/* List-variant: keep the dual block compact and left-aligned inside the row card. */
:where(.sl-body) .pkg-style-list .pkg-card--dual .pkg-dual-prices { margin: 0.25rem 0; max-width: 260px; }
@media (max-width: 768px) { :where(.sl-body) .pkg-dual-prices { max-width: 240px; } }
/* --- lead_capture_hero --- */
/* ── Lead-capture hero (variant 'lead-form') ──────────────────────────────
   Light 2-col hero: pitch on the left, inline mini booking-form card on the right.
   Reuses .hero-split (which already collapses to 1-col at <=768px) for the grid. */
:where(.sl-body) .hero-lead-form .hero-inner { max-width: 560px; }
:where(.sl-body) .hero-lead-form .hero-form-col { display: flex; justify-content: flex-end; }
:where(.sl-body) .lead-form-card {
  width: 100%; max-width: 420px;
  background: var(--c-surface); border: 1px solid var(--c-border);
  border-radius: var(--card-radius); box-shadow: var(--card-shadow);
  padding: 1.6rem 1.6rem 1.4rem;
}
:where(.sl-body) .lead-form-title { font-family: var(--font-heading); font-size: 1.35rem; font-weight: 700; line-height: 1.2; color: var(--c-text); margin: 0 0 1.1rem; }
:where(.sl-body) .lead-field { display: block; margin-bottom: 0.85rem; }
:where(.sl-body) .lead-field > span { display: block; margin-bottom: 0.35rem; font-size: 0.8rem; font-weight: 600; letter-spacing: 0.02em; text-transform: uppercase; color: var(--c-text-muted); }
:where(.sl-body) .lead-field input {
  width: 100%; padding: 0.7rem 0.85rem; font: inherit; font-size: 1rem; color: var(--c-text);
  background: var(--c-bg); border: 1px solid var(--c-border); border-radius: var(--input-radius, 10px);
  transition: border-color .15s ease, box-shadow .15s ease;
}
:where(.sl-body) .lead-field input::placeholder { color: var(--c-text-muted); opacity: 0.75; }
:where(.sl-body) .lead-field input:focus { outline: none; border-color: var(--c-primary); box-shadow: 0 0 0 3px color-mix(in srgb, var(--c-primary) 22%, transparent); }
:where(.sl-body) .lead-form-btn { display: block; width: 100%; margin-top: 0.5rem; text-align: center; }
:where(.sl-body) .lead-form-note { margin: 0.85rem 0 0; font-size: 0.8rem; line-height: 1.4; color: var(--c-text-muted); text-align: center; }
@media (max-width: 768px) {
  :where(.sl-body) .hero-lead-form .hero-inner { max-width: none; }
  :where(.sl-body) .hero-lead-form .hero-form-col { justify-content: stretch; }
  :where(.sl-body) .lead-form-card { max-width: none; }
}
/* Textarea inside a lead-form card (contact_two_col message form) matches the inputs. */
:where(.sl-body) .lead-field textarea {
  width: 100%; padding: 0.7rem 0.85rem; font: inherit; font-size: 1rem; color: var(--c-text);
  background: var(--c-bg); border: 1px solid var(--c-border); border-radius: var(--input-radius, 10px);
  resize: vertical; min-height: 6.5rem;
  transition: border-color .15s ease, box-shadow .15s ease;
}
:where(.sl-body) .lead-field textarea:focus { outline: none; border-color: var(--c-primary); box-shadow: 0 0 0 3px color-mix(in srgb, var(--c-primary) 22%, transparent); }

/* ── contact_two_col / additional_contact ──────────────────────────────────
   Contact info column: tappable method cards (tel/sms/mailto), service areas, socials. */
:where(.sl-body) .contact-col-title { font-family: var(--font-heading); font-size: 1.5rem; line-height: 1.2; margin: 0 0 0.6rem; color: var(--c-text); }
:where(.sl-body) .contact-intro { color: var(--c-text-muted); margin: 0 0 1.25rem; max-width: 46ch; }
:where(.sl-body) .contact-book { margin: 0 0 1.5rem; }
:where(.sl-body) .contact-methods { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 0.85rem; margin-bottom: 1.5rem; }
:where(.sl-body) .contact-method {
  display: block; text-decoration: none; padding: 0.95rem 1.1rem;
  background: var(--c-surface); border: 1px solid var(--c-border);
  border-radius: var(--card-radius); box-shadow: var(--card-shadow);
  transition: border-color .15s ease, transform .15s ease;
}
:where(.sl-body) .contact-method:hover { border-color: var(--c-primary); transform: translateY(-2px); }
:where(.sl-body) .contact-method-label { display: block; font-size: 0.8125rem; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase; color: var(--c-text-muted); margin-bottom: 0.3rem; }
:where(.sl-body) .contact-method-value { display: block; font-size: 1.0625rem; font-weight: 600; color: var(--c-text); }
:where(.sl-body) .contact-areas { margin-bottom: 1.25rem; }
:where(.sl-body) .contact-areas p { margin: 0; color: var(--c-text-muted); }
:where(.sl-body) .contact-social { display: flex; flex-wrap: wrap; gap: 0.6rem; margin-bottom: 1rem; }
:where(.sl-body) .contact-social-link {
  display: inline-block; padding: 0.45rem 0.95rem; font-size: 0.9375rem; font-weight: 600;
  text-decoration: none; color: var(--c-text);
  border: 1px solid var(--c-border); border-radius: 999px;
}
:where(.sl-body) .contact-social-link:hover { border-color: var(--c-primary); color: var(--c-primary); }
:where(.sl-body) .contact-note { font-size: 0.875rem; color: var(--c-text-muted); margin: 0; }
/* Post-send confirmation panel inside the contact message form. Replaces the fields the moment
   Send is pressed, so the visitor always gets a visible result plus every real way to reach the
   business (the mailto hand-off can silently no-op on phones with no mail client configured). */
:where(.sl-body) .contact-sent[hidden] { display: none; }
:where(.sl-body) .contact-sent-title { font-family: var(--font-heading); font-size: 1.25rem; font-weight: 700; line-height: 1.25; color: var(--c-text); margin: 0 0 0.6rem; }
:where(.sl-body) .contact-sent-body { font-size: 0.9375rem; line-height: 1.55; color: var(--c-text-muted); margin: 0 0 1.15rem; }
:where(.sl-body) .contact-sent-actions { display: flex; flex-direction: column; gap: 0.6rem; }
:where(.sl-body) .contact-sent-actions .btn { width: 100%; text-align: center; }
:where(.sl-body) .contact-sent-copy {
  display: block; width: 100%; margin-top: 0.9rem; padding: 0.5rem 0.75rem;
  font: inherit; font-size: 0.875rem; font-weight: 600; color: var(--c-text-muted);
  background: none; border: 1px dashed var(--c-border); border-radius: 10px; cursor: pointer;
}
:where(.sl-body) .contact-sent-copy:hover { color: var(--c-text); border-color: var(--c-primary); }
:where(.sl-body) .contact-2col .contact-form-col { display: flex; justify-content: flex-end; }
:where(.sl-body) .contact-2col .contact-form-col .lead-form-card { max-width: 460px; }
@media (max-width: 768px) {
  :where(.sl-body) .contact-2col .contact-form-col { justify-content: stretch; }
  :where(.sl-body) .contact-2col .contact-form-col .lead-form-card { max-width: none; }
}
/* THE CONTACT PAGE'S INFO COLUMN IS A SPLIT TOO, and on a phone it stacks over the form like every
   other split - so it follows the same phone rule as the composed bands by the standard at the top
   of this file (760px): heading, lead, booking button, ways to reach us and socials read the page's
   alignment instead of hanging at the left edge. Measured on an invented client's /contact/,
   2026-09-11: the only band on the page whose button still sat hard left on a phone. Shelf pages
   only, like the rule it follows. */
@media (max-width: 760px) {
  :where(.sl-body).sl-shelf .contact-2col .contact-info-col { text-align: var(--bk-align, center); }
  :where(.sl-body).sl-shelf .contact-2col .contact-intro { margin-inline: var(--bk-mi, auto); }
  :where(.sl-body).sl-shelf .contact-2col .contact-social { justify-content: var(--bk-justify, center); }
}
/* auto-fit off a fixed 240px minimum decides the column count from the container alone, which is
   how a 6-item list landed 4+2 with two cards stranded (R16). The renderer now supplies
   --sl-basis from cardBasis(n), the same non-orphaning width every other card band uses, so the
   count drives the columns. Falls back to the old 240px when no basis is passed. */
:where(.sl-body) .additional-contact .ac-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(var(--sl-basis, 240px), 100%), minmax(0, 1fr))); gap: 1rem; }
:where(.sl-body) .additional-contact .ac-card { display: block; text-decoration: none; padding: 1.15rem 1.25rem; }
:where(.sl-body) .additional-contact a.ac-card:hover { border-color: var(--c-primary); }
:where(.sl-body) .additional-contact .ac-card-value { display: block; color: var(--c-text-muted); line-height: 1.5; }

/* Categorised FAQ (faq_categories): group label above each accordion stack. */
:where(.sl-body) .faq-cat + .faq-cat { margin-top: 2.25rem; }
:where(.sl-body) .faq-cat-title { font-family: var(--font-heading); font-size: 1.25rem; line-height: 1.2; margin: 0 0 0.5rem; color: var(--c-text); }
/* ── PHOTO STEPS ("How to get your IV", but with pictures) ────────────────────
   Client brief (Top Tier Wellness): she wants the how-it-works rail on the home page with real
   photos instead of numbered icons. Only applies when EVERY step carries an image (renderWhatToExpect
   adds .steps-photo), so the icon rail is untouched for every other brand. The connecting rail line is
   dropped here — it fights a photo edge — and the number becomes a badge sitting on the image corner. */
/* same contract as the photo band above: change the variable, not only the shorthand, or .step-n
   positions itself against a padding this card no longer has */
:where(.sl-body) .steps-photo .step-card { --step-pad-top: 0; padding: var(--step-pad-top) 0 1.4rem !important; overflow: hidden; text-align: left; }
:where(.sl-body) .steps-photo.steps-connected::before, :where(.sl-body) .steps-photo.steps-connected::after { display: none !important; }
:where(.sl-body) .steps-photo .step-photo { position: relative; margin: 0 0 1.1rem; line-height: 0; }
/* THE FRAME TAKES THE PICTURE'S SHAPE — the interior copy of the rule the six home houses now
   follow. It was pinned here at 200px tall with `cover`, which crops a third off the top and the
   bottom of a tall portrait of a provider and takes the head with it, at every window width.
   `aspect-ratio: auto` with `height: auto` is the browser reading the file, so an unmeasured
   picture still renders at its own shape and nothing has to know its size in advance. The renderer
   sets `--sl-step-ar` when the library could prove the shape. Bounded rather than pinned, and
   `contain` because a bound is not permission to crop; the box is already the picture's own shape,
   so there is nothing to letterbox. */
:where(.sl-body) .steps-photo .step-photo img {
  width: 100%; height: auto; aspect-ratio: var(--sl-step-ar, auto);
  max-height: 46vh; object-fit: contain; display: block;
  border-radius: var(--card-radius) var(--card-radius) 0 0;
}
:where(.sl-body) .steps-photo .step-photo .step-badge {
  position: absolute; bottom: -18px; left: 1.25rem; margin: 0;
  width: 36px; height: 36px; display: grid; place-items: center;
  border-radius: 50%; background: var(--c-primary); color: var(--c-on-primary);
  font-weight: 700; font-size: 0.95rem; font-variant-numeric: tabular-nums;
  box-shadow: 0 6px 16px -6px rgba(0,0,0,0.45); border: 2px solid var(--c-on-dark);
}
:where(.sl-body) .steps-photo .step-card h3 { margin: 1.5rem 1.25rem 0.4rem; }
:where(.sl-body) .steps-photo .step-card p { margin: 0 1.25rem; }
@media (max-width: 640px) { :where(.sl-body) .steps-photo .step-photo img { max-height: 40vh; } }

/* ── .hero-bag-float — the product bag composed onto a package-page hero ──────────────────────
   R9: the bag floats on the hero with NOTHING around it — no box, no panel. Requires transparent
   bag art (background removed in the pipeline) so the drop-shadow follows the silhouette.
   Lives HERE and not in Sections.astro's \3c style>: the img is emitted through set:html, so Astro's
   scoped [data-astro-cid-*] selector never matched it and the whole rule was inert. */
:where(.sl-body) .hero-bag-float {
  /* PINNED TO THE PAGE, NOT TO THE SCREEN. `right: 4%` and `max-width: 30%` both measured the
     SECTION, which is full-bleed, while the page column stops growing at 1200px. The overhang past
     the column is therefore 0.46W - 580: 82px at 1440, and 591px at 2560, where more than half the
     product sat outside the page with nothing beside it. --bk-pad IS the column's edge, and the
     cap becomes absolute so a wide screen cannot inflate the bag either. Guarded by G5 in
     scripts/grid-lint.mjs. */
  position: absolute; right: var(--bk-pad); bottom: 0;
  max-height: 90%; max-width: min(30%, 420px); object-fit: contain;
  /* Two shadows: a tight one hugs the silhouette so a light bag reads on a bright hero, plus a
     soft ambient one for depth. Shadows alone assume the hero is merely BRIGHT — they do nothing
     when the hero is a photo of the SAME object, which is how Top Tier's clear-liquid bag went
     invisible over the clear-bag hero video. The radial scrim behind the transparent art
     separates it from anything; closest-side plus a transparent stop means no edge to see. */
  filter: drop-shadow(0 3px 10px rgba(8, 18, 22, 0.30)) drop-shadow(0 22px 46px rgba(8, 18, 22, 0.38));
  background: radial-gradient(closest-side ellipse at 50% 55%,
    rgba(9, 13, 20, 0.52), rgba(9, 13, 20, 0.30) 60%, rgba(9, 13, 20, 0) 78%);
  pointer-events: none; z-index: 1;
}
@media (max-width: 900px) { :where(.sl-body) .hero-bag-float { display: none; } }

/* THE BAG NEEDS A LANE OF ITS OWN, AND NOTHING WAS GIVING IT ONE.
   The float is pinned to the right of the page column and painted after the words, so a headline
   long enough to reach it is drawn straight across the product - in white, over a white bag. On
   the packages listing "IV Packages and Pricing" ran the last two syllables over the bag and
   through the logo mark on its label: the headline unreadable and the product spoiled, both at
   once. It was never specific to that page. Every package page uses this float, and any drip whose
   name runs long collides in exactly the same way; the listing page was simply the first headline
   long enough to prove it.
   So a hero carrying a bag caps its text column short of the bag instead. The cap tracks the same
   expression the bag's own width uses, so the two can never disagree, plus a gap so the words stop
   clear of the silhouette rather than touching it. Below 900px the bag is not rendered at all and
   the text takes the full width, as before. */
:where(.sl-body) .hero:has(> .hero-bag-float) .hero-inner {
  max-width: calc(100% - min(30%, 420px) - 2.5rem);
}
@media (max-width: 900px) {
  :where(.sl-body) .hero:has(> .hero-bag-float) .hero-inner { max-width: none; }
}

/* ── .hero-bagstage — the photograph as shot, the words on a card, the bag standing in front ─────
   Ian, 2026-09-21, on the IV Revival drip pages: "I don't want the hero to have that green wash,
   and I want the image of the bag in the hero as well. Put the hero bag sitting on top of the hero
   image behind it. Remove the green gradient. Move around the copy on the screen so that it all
   kind of fits nice on there."

   THE WASH COMES OFF, BY NAME. The glaze and every lane's wash paint `.hero-image-bg::after`, some
   with !important, so this is the one rule that has to outrank them: the photograph is shown as
   it was taken, in its own colours.

   WHICH MEANS THE WORDS NEED A GROUND OF THEIR OWN. White type was only ever readable on this hero
   because of the wash; take the wash away and the same type sits on a bright room. So the copy goes
   on a white card on the left — the same plate the rest of this site already uses — in the page's
   own ink, and the photograph is left alone rather than dimmed to rescue it.

   AND THE BAG STANDS ON THE PICTURE, larger than the float's default, on the right, without the
   dark halo the float wears to survive a heavy wash — there is no wash here for it to survive. */
:where(.sl-body) .hero-bagstage.hero-image-bg::after { background: none !important; opacity: 0 !important; }
/* AND THE SECOND GREEN. The first pass took the wash off the section and the left half stayed
   green: `.hero-inner::after` is the text-column legibility panel, a brand-green ramp bleeding
   900px out to the left from behind the copy. It was the other half of "that green wash", and on
   a white card it has nothing left to do. */
:where(.sl-body) .hero-bagstage .hero-inner::after, :where(.sl-body) .hero-bagstage .hero-inner::before { display: none !important; content: none !important; }
/* The card starts on the page column every other band starts on, not in a narrow centred box. */
:where(.sl-body) .hero-bagstage > .container { max-width: none !important; width: 100%; padding-inline: var(--bk-pad, clamp(16px, 5.5vw, 80px)) !important; }
:where(.sl-body) .hero-bagstage .hero-inner {
  background: rgba(255,255,255,.95); border-radius: 22px; padding: clamp(24px, 2.6vw, 38px) clamp(24px, 2.8vw, 40px);
  box-shadow: 0 1px 2px rgba(8,18,22,.06), 0 24px 50px -26px rgba(8,18,22,.45);
  max-width: min(560px, calc(100% - min(34%, 440px) - 2.5rem)) !important;
  color: var(--bk-ink, #14251a); text-shadow: none !important;
}
:where(.sl-body) .hero-bagstage .hero-inner :is(h1, :where(.sl-body) h1 *, :where(.sl-body) p, :where(.sl-body) li, :where(.sl-body) span, :where(.sl-body) strong, :where(.sl-body) b, :where(.sl-body) .hero-price, :where(.sl-body) .hero-facts, :where(.sl-body) .hero-tagline):not(.btn, :where(.sl-body) .btn *) { color: var(--bk-ink, #14251a) !important; text-shadow: none !important; }
/* The filled booking button keeps its own white label; the ink rule above is for the words. */
:where(.sl-body) .hero-bagstage .hero-inner .btn-primary, :where(.sl-body) .hero-bagstage .hero-inner .btn-primary * { color: var(--bk-primary-ink, #fff) !important; }
:where(.sl-body) .hero-bagstage .hero-inner :is(.hero-subhead, :where(.sl-body) .hero-facts, :where(.sl-body) .hero-facts *) { color: var(--bk-muted, #4d5a52) !important; }
:where(.sl-body) .hero-bagstage .hero-inner h1 { font-size: clamp(34px, 4vw, 58px) !important; line-height: 1.02; margin-bottom: 14px; }
/* The outlined call button was drawn white-on-photo; on a white card it takes the brand colour. */
:where(.sl-body) .hero-bagstage .hero-inner :is(.btn-secondary, :where(.sl-body) .btn-outline, :where(.sl-body) .btn-ghost) {
  color: var(--bk-primary, #4d7d1a) !important; border-color: var(--bk-primary, #4d7d1a) !important;
  box-shadow: inset 0 0 0 1.5px var(--bk-primary, #4d7d1a) !important; background: transparent !important;
}
/* IT FITS THE SCREEN. fold-fit refused the first build at every window size, and the measurement
   said why: the hero kept the 155px of bottom padding and the 567px floor the old layout used to
   leave room for words laid over the photograph. Here the words are on a card, so the band is the
   card plus a margin and nothing else. Measured before: 741px at a 720px laptop, 952 at 864x900. */
:where(.sl-body) .hero-bagstage { min-height: 0 !important; padding-top: clamp(20px, 2.4vw, 36px) !important; padding-bottom: clamp(24px, 3vw, 44px) !important; }
:where(.sl-body) .hero-bagstage .hero-bag-float {
  /* The whole bag, tubing included, clear of the bottom edge: at bottom 0 the section clipped the
     ports off, which is the one part of the object that says "IV". */
  max-height: 82%; max-width: min(34%, 430px); bottom: 7%; right: calc(var(--bk-pad, 80px) + 2%);
  background: none;
  filter: drop-shadow(0 4px 12px rgba(8,18,22,.28)) drop-shadow(0 26px 44px rgba(8,18,22,.34));
}
/* ON A PHONE the bag still belongs in the hero — the default float hides below 900px, which is the
   one thing this layout exists not to do. It stands above the card, smaller, centred. */
@media (max-width: 900px) {
  :where(.sl-body) .hero-bagstage { display: flex; flex-direction: column; }
  :where(.sl-body) .hero-bagstage .hero-bag-float { display: block; position: relative; right: auto; order: -1; align-self: center;
    max-height: 180px; max-width: 50%; margin: 10px auto -22px; z-index: 2; }
  /* AND THE CARD MAY NOT BE SQUEEZED SMALLER THAN ITS OWN WORDS. As a column flex item it defaulted
     to `flex: 0 1 auto`, so on a short phone the band's height won its argument with the copy: the
     white plate stopped under the buttons and the price and fine print were left sitting on the
     photograph, dark ink on a sunlit wall. Measured by hero-contrast at 1.66:1 over 73% of the
     price line. The plate sizes to its content and the band grows. */
  :where(.sl-body) .hero-bagstage .hero-inner { max-width: none !important; flex: 0 0 auto; }
}
/* A SMALL PHONE CANNOT HOLD THE WHOLE CARD AND THE BAG. Measured at 360x640: the card alone was 616px
   before the bag was added. The three fact lines — the base-bag line, the ingredient list and the
   payment line — are the part of this card the page repeats in full in its own "at a glance"
   section two bands down, so on the smallest screens they are left to that section. SHORT screens
   only: a 390x844 phone has room for them and keeps them. */
@media (max-width: 420px) and (max-height: 720px) {
  :where(.sl-body) .hero-bagstage .hero-bag-float { max-height: 120px; margin: 6px auto -16px; }
  :where(.sl-body) .hero-bagstage .hero-inner { padding: 18px 18px 20px !important; }
  :where(.sl-body) .hero-bagstage .hero-inner .hero-facts { display: none !important; }
  :where(.sl-body) .hero-bagstage .hero-inner h1 { font-size: 30px !important; margin-bottom: 8px; }
}

/* .pkg-body: layout-invisible by default so the bag card renders exactly as before. Only the
   pricing.bag-hover-reveal variant promotes it into a sliding panel. */
:where(.sl-body) .pkg-body { display: contents; }
/* A grid card is ~300px wide with no neighbour crowding it, so the bag can be taller than the
   3-up carousel allows. Tall product art (near 1:2) is otherwise a thumbnail in a big white box. */
/* ── PRODUCT BANDS ARE WIDER THAN THE READING MEASURE ───────────────────────────────────────
   The bag menu and the vial grid are the shop window. Held to the 1120px copy measure, four bags
   come out 252px wide with the artwork a thumbnail inside them. The renderer sizes these bands
   against 1380 (PRODUCT_BAND_PX) so the SAME balanced column count yields ~30% wider cards; the
   frame here has to match, or the cards compute wider than the box and wrap a row early.
   Eight bags divide by four and by two, never by three — so "fewer per row" is not available
   without orphaning a row (R16). Bigger comes from a wider frame and a taller bag box. */
/* The band also has to ESCAPE .container (1200px), or the wider basis has nowhere to go and the
   row wraps — which is what stacked the two Our Services cards. Widen the container for these
   three sections only; every other band keeps the reading measure. */
:where(.sl-body) .section-popular_packages_local > .container, :where(.sl-body) .section-vitamin_shots > .container, :where(.sl-body) .section-our_offerings > .container { max-width: min(1420px, 100%); }
:where(.sl-body) .pkg-style-grid, :where(.sl-body) .cards-center.is-product-band { max-width: 100%; margin-left: auto; margin-right: auto; }
:where(.sl-body) .pkg-style-grid .pkg-track { max-width: none; }
:where(.sl-body) .pkg-style-grid { --pkg-bag-h: 330px; }
@media (max-width: 1100px) { :where(.sl-body) .pkg-style-grid { --pkg-bag-h: 260px; } }
@media (max-width: 640px) { :where(.sl-body) .pkg-style-grid { --pkg-bag-h: 230px; } }
/* Vials are ~2:3 and service-line art is a single hero object, so both want a much taller box
   than the generic 150px item image. These are the "make them big" bands. */
:where(.sl-body) .section-vitamin_shots .img-item-media { height: 340px; }
:where(.sl-body) .section-vitamin_shots .img-item-media img { max-width: 58%; }
@media (max-width: 900px) {
  :where(.sl-body) .section-vitamin_shots .img-item-media { height: 260px; }
}

/* ── our_offerings — PHOTOGRAPHS, not cut-out product art ────────────────────────────────────
   This band used the same bag and vial that appear again further down the page, which is the
   repetition Ian called out ("we're just using a bag and vial… repeating the same thing over and
   over"). The two service lines now carry photographs instead, and a photograph wants the exact
   opposite of the cut-out treatment: fill the frame rather than float inside it, and no
   drop-shadow — a shadow under a rectangular photo reads as a mistake, not depth.
   The caption was the other half of the complaint. A centred 1.02rem label stranded under a big
   image looks unfinished; set in the display face over a short gold rule it reads as a caption
   somebody chose. */
:where(.sl-body) .section-our_offerings .img-item-media {
  height: auto;
  aspect-ratio: 4 / 3;
  margin-bottom: 0;
  border-radius: var(--radius-lg, 14px);
  overflow: hidden;
  background: color-mix(in srgb, var(--c-primary) 8%, var(--c-surface-alt));
}
:where(.sl-body) .section-our_offerings .img-item-media img {
  width: 100%; height: 100%;
  max-width: none; max-height: none;
  object-fit: cover;
  filter: none;
  transition: transform .5s ease;
}
:where(.sl-body) .section-our_offerings .img-item-card { text-align: left; }
:where(.sl-body) .section-our_offerings .img-item-card:hover .img-item-media img { transform: scale(1.03); }
:where(.sl-body) .section-our_offerings .img-item-card h3 {
  font-family: var(--font-heading, inherit);
  font-size: clamp(1.25rem, 2.1vw, 1.6rem);
  line-height: 1.2;
  letter-spacing: 0.01em;
  color: var(--c-primary);
  margin: 1.15rem 0 0;
  padding-top: 1.05rem;
  position: relative;
}
:where(.sl-body) .section-our_offerings .img-item-card h3::before {
  content: ''; position: absolute; top: 0; left: 0;
  width: 46px; height: 2px; background: var(--c-accent);
}
@media (max-width: 900px) {
  :where(.sl-body) .section-our_offerings .img-item-card h3 { font-size: 1.2rem; }
}

/* ── wellness_packages: persona bundle cards, FORCED 3-up ──────────────────────
   Deliberately grid-with-3-explicit-columns, NOT the .cards-center flex/cardBasis
   path: chooseCols(6,4) yields a 4+2 orphan row, and this component exists to give
   2 clean rows of THREE. Stacks 3 -> 2 (<=900px) -> 1 (<=640px) on mobile. */
/* Centered flex-wrap + --sl-basis, like every other card band (the LAYOUT INVARIANT in
   SectionBlock.astro). This was `display:grid; repeat(3, minmax(0,1fr))` — hard-coded to dodge
   chooseCols(6,4)=4+2 back when chooseCols was broken. That workaround CREATED the very bug it
   was dodging: a rigid grid has no justify-content:center, so 4 bundles rendered 3+1 and 7
   rendered 3+3+1 with the last card hanging LEFT. chooseCols is fixed now (6 -> 3+3 on its own),
   so there is nothing left to work around. Never hard-code repeat(N) around the helper. */
:where(.sl-body) .wpkg-grid { display: flex; flex-wrap: wrap; justify-content: center; gap: 1.5rem; max-width: var(--content-max); margin: 0 auto; align-items: stretch; }
:where(.sl-body) .wpkg-grid > .wpkg-card { flex: 0 1 var(--sl-basis, 320px); }
:where(.sl-body) .wpkg-card { display: flex; flex-direction: column; text-align: left; padding: 1.9rem 1.6rem; background: var(--c-surface); border: 1px solid var(--c-border); border-radius: var(--card-radius); }
:where(.sl-body) .wpkg-ic { display: inline-flex; align-items: center; justify-content: center; width: 44px; height: 44px; margin-bottom: 1rem; border-radius: 50%; color: var(--c-accent); background: color-mix(in srgb, var(--c-accent) 12%, var(--c-surface)); border: 1px solid color-mix(in srgb, var(--c-accent) 28%, var(--c-border)); }
:where(.sl-body) .wpkg-ic svg { width: 22px; height: 22px; }
:where(.sl-body) .wpkg-name { margin: 0 0 0.4rem; font-family: var(--font-heading); font-size: 1.18rem; line-height: 1.25; color: var(--c-primary); letter-spacing: -0.01em; }
:where(.sl-body) .wpkg-for { margin: 0 0 1.1rem; color: var(--c-text-muted); font-size: 0.94rem; line-height: 1.55; }
:where(.sl-body) .wpkg-list { list-style: none; margin: 0 0 1.25rem; padding: 1.1rem 0 0; border-top: 1px solid var(--c-border); display: grid; gap: 0.6rem; }
:where(.sl-body) .wpkg-list li { display: flex; gap: 0.6rem; align-items: flex-start; line-height: 1.5; font-size: 0.93rem; color: var(--c-text); }
:where(.sl-body) .wpkg-list .wpkg-check { flex: 0 0 auto; color: var(--c-accent); margin-top: 3px; }
:where(.sl-body) .wpkg-price { margin: 0 0 1.1rem; font-size: 1.35rem; font-weight: 600; color: var(--c-primary); font-variant-numeric: tabular-nums; letter-spacing: -0.01em; }
/* margin-top:auto pins every Book button to the card floor, so a row of bundles with
   uneven checklists still lines its CTAs up. */
:where(.sl-body) .wpkg-cta { margin-top: auto; align-self: stretch; text-align: center; }
@media (max-width: 900px) { :where(.sl-body) .wpkg-grid > .wpkg-card { flex-basis: calc(50% - 0.75rem); } }
@media (max-width: 640px) { :where(.sl-body) .wpkg-grid { gap: 1.1rem; } :where(.sl-body) .wpkg-grid > .wpkg-card { flex-basis: 100%; } :where(.sl-body) .wpkg-card { padding: 1.6rem 1.35rem; } }

/* ── policy_expand — policy accordion paired with a photo that scales UP as an item opens ──────
   From the client-referenced pattern (vividesthetics.co/booking): open a policy, the photo beside
   it grows. There it's incidental (an auto-height grid row pushing a stretched image); here it's
   the point. The renderer gates the media column, so with no photo the list runs full-width at
   measure width — no empty frame, and the effect lights up on its own once a photo lands. */
:where(.sl-body) .pxp-layout {
  display: grid; grid-template-columns: minmax(0, 0.85fr) minmax(0, 1fr);
  gap: 2.75rem; align-items: start;
  max-width: var(--content-max); margin-left: auto; margin-right: auto;
}
:where(.sl-body) .pxp-layout.pxp-no-media { grid-template-columns: minmax(0, 1fr); max-width: var(--content-measure); }
:where(.sl-body) .pxp-media { position: sticky; top: 2rem; }
:where(.sl-body) .pxp-frame {
  position: relative; overflow: hidden; aspect-ratio: 4 / 5;
  border-radius: var(--card-radius, 12px); background: var(--c-surface-alt, rgba(0, 0, 0, 0.04));
  /* A PHOTO NEEDS AN EDGE. This frame sits on whatever band it lands on, and a soft warm image on a
     warm tinted band has no boundary at all — it reads as a smudge rather than a photograph. (Real
     case: beige linen photos on the beige band, no visible edge anywhere.) A hairline + a resting
     shadow give it a definite edge on ANY band without decorating it.
     Also cap it: at aspect-ratio 4/5 in a 494px column the frame runs 618px, while five COLLAPSED
     policies are ~350px — 270px of the band left dead beside it. The photo should not tower over
     the list it belongs to. */
  max-height: 30rem;
  border: 1px solid var(--c-border);
  box-shadow: 0 6px 22px rgba(0, 0, 0, 0.07);
  /* Rest state is deliberately SMALL so opening a policy visibly grows it. Scaling (not sizing)
     keeps the grid box fixed, so the list beside it never reflows — the photo grows, nothing jumps. */
  transform: scale(0.9); transform-origin: 50% 15%;
  transition: transform 0.55s cubic-bezier(0.22, 0.61, 0.36, 1), box-shadow 0.55s ease;
}
:where(.sl-body) .pxp-layout.is-expanded .pxp-frame { transform: scale(1); box-shadow: 0 18px 44px rgba(0, 0, 0, 0.16); }
:where(.sl-body) .pxp-img {
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover;
  opacity: 0; transition: opacity 0.45s ease;
}
:where(.sl-body) .pxp-img.is-active { opacity: 1; }

:where(.sl-body) .pxp-list { min-width: 0; }
:where(.sl-body) .pxp-item { border-bottom: 1px solid var(--c-border); }
:where(.sl-body) .pxp-item:first-child { border-top: 1px solid var(--c-border); }
:where(.sl-body) .pxp-summary {
  list-style: none; cursor: pointer; display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; padding: 1.25rem 0; font-family: var(--font-heading);
  font-weight: 600; font-size: 1.0625rem; color: var(--c-text);
}
:where(.sl-body) .pxp-summary::-webkit-details-marker { display: none; }
:where(.sl-body) .pxp-summary:focus-visible { outline: 2px solid var(--c-accent); outline-offset: 3px; border-radius: 3px; }
:where(.sl-body) .pxp-title { min-width: 0; }
/* CSS-drawn plus that closes to a minus — mirrors the reference's icon, no icon font/asset. */
:where(.sl-body) .pxp-plus { position: relative; flex: 0 0 auto; width: 18px; height: 18px; }
:where(.sl-body) .pxp-plus::before, :where(.sl-body) .pxp-plus::after {
  content: ''; position: absolute; left: 50%; top: 50%; background: var(--c-accent);
  transition: transform 0.3s ease, opacity 0.3s ease;
}
:where(.sl-body) .pxp-plus::before { width: 16px; height: 2px; transform: translate(-50%, -50%); }
:where(.sl-body) .pxp-plus::after { width: 2px; height: 16px; transform: translate(-50%, -50%); }
:where(.sl-body) .pxp-item[open] .pxp-plus::after { transform: translate(-50%, -50%) rotate(90deg); opacity: 0; }
:where(.sl-body) .pxp-body { padding: 0 0 1.4rem; }
/* pre-line: policy copy is authored with real line breaks ("Must be done 24 hours in advance!\n\n…").
   esc() has already escaped the text, so this only affects whitespace rendering. */
:where(.sl-body) .pxp-body p { margin: 0; color: var(--c-text-muted); max-width: 70ch; white-space: pre-line; }

/* Mobile: one column, photo above the list, and the grow still works (Ian reviews on his phone).
   The frame goes landscape so a stacked photo doesn't eat the whole viewport before the policies. */
@media (max-width: 860px) {
  :where(.sl-body) .pxp-layout { grid-template-columns: minmax(0, 1fr); gap: 1.5rem; }
  :where(.sl-body) .pxp-media { position: static; }
  :where(.sl-body) .pxp-frame { aspect-ratio: 3 / 2; transform: scale(0.94); transform-origin: 50% 50%; }
}
@media (prefers-reduced-motion: reduce) {
  :where(.sl-body) .pxp-frame, :where(.sl-body) .pxp-img, :where(.sl-body) .pxp-plus::before, :where(.sl-body) .pxp-plus::after { transition: none; }
  /* No motion means no scale animation — the photo just sits at full size, and the swap is instant. */
  :where(.sl-body) .pxp-frame, :where(.sl-body) .pxp-layout.is-expanded .pxp-frame { transform: none; }
}

/* ── group_events — occasion chip wall + headcount ladder ─────────────────────────
   The "all together" group page: every occasion in one glanceable wall (chips, not
   title-only cards) beside a ladder of headcount bands. Chips are flex-wrap and the
   ladder is its own column, so neither uses cardBasis/chooseCols (no 4-up orphan).
   Stacks to one column at 860px; the ladder rungs stack their note at 480px. */
:where(.sl-body) .ge-avail { display: flex; align-items: center; justify-content: center; gap: 0.55rem; width: fit-content; max-width: 100%; margin: 1.25rem auto 0; padding: 0.5rem 1.1rem; border-radius: 999px; border: 1px solid color-mix(in srgb, var(--c-accent) 38%, var(--c-border)); background: color-mix(in srgb, var(--c-accent) 9%, var(--c-surface)); color: var(--c-text); font-size: 0.92rem; font-weight: 600; line-height: 1.35; text-align: left; }
:where(.sl-body) .ge-avail-ic { flex: 0 0 auto; display: inline-flex; color: var(--c-accent); }
:where(.sl-body) .ge-avail-ic svg { width: 17px; height: 17px; }

:where(.sl-body) .ge-grid { display: grid; grid-template-columns: 1.15fr 0.85fr; gap: 1.5rem; align-items: start; max-width: var(--content-max); margin: 2rem auto 0; }
:where(.sl-body) .ge-grid-single { grid-template-columns: minmax(0, 1fr); max-width: 860px; }
:where(.sl-body) .ge-panel { display: flex; flex-direction: column; padding: 1.9rem 1.75rem; border-radius: var(--card-radius); border: 1px solid var(--c-border); background: var(--c-surface); }
:where(.sl-body) .ge-panel-tiers { background: color-mix(in srgb, var(--c-primary) 5%, var(--c-surface)); }
:where(.sl-body) .ge-panel-label { font-weight: 600; font-size: 0.82rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--c-text-muted); margin-bottom: 1.1rem; }

:where(.sl-body) .ge-chips { list-style: none; padding: 0; margin: 0; display: flex; flex-wrap: wrap; gap: 0.6rem; }
:where(.sl-body) .ge-chip { display: inline-flex; align-items: center; gap: 0.5rem; padding: 0.52rem 0.95rem; border-radius: 999px; border: 1px solid var(--c-border); background: color-mix(in srgb, var(--c-primary) 4%, var(--c-surface)); }
:where(.sl-body) .ge-chip-ic { flex: 0 0 auto; display: inline-flex; color: var(--c-accent); }
:where(.sl-body) .ge-chip-ic svg { width: 16px; height: 16px; }
:where(.sl-body) .ge-chip-tx { font-size: 0.92rem; font-weight: 500; line-height: 1.25; color: var(--c-text); }

:where(.sl-body) .ge-ladder { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 0.55rem; counter-reset: none; }
:where(.sl-body) .ge-rung { display: grid; grid-template-columns: auto auto minmax(0, 1fr); align-items: baseline; gap: 0.4rem 0.55rem; padding: 0.85rem 1.05rem; border-radius: calc(var(--card-radius) * 0.7); border: 1px solid color-mix(in srgb, var(--c-primary) 16%, var(--c-border)); background: var(--c-surface); }
/* Rungs escalate with group size — the ladder reads as a ladder, not three equal rows. */
:where(.sl-body) .ge-rung:nth-child(2) { background: color-mix(in srgb, var(--c-accent) 7%, var(--c-surface)); border-color: color-mix(in srgb, var(--c-accent) 30%, var(--c-border)); }
:where(.sl-body) .ge-rung:nth-child(n + 3) { background: color-mix(in srgb, var(--c-accent) 13%, var(--c-surface)); border-color: color-mix(in srgb, var(--c-accent) 46%, var(--c-border)); }
:where(.sl-body) .ge-rung-size { font-family: var(--font-heading); font-size: 1.45rem; font-weight: 700; line-height: 1; letter-spacing: -0.01em; color: var(--c-primary); font-variant-numeric: tabular-nums; }
:where(.sl-body) .ge-rung-unit { font-size: 0.85rem; font-weight: 600; color: var(--c-text-muted); }
:where(.sl-body) .ge-rung-note { grid-column: 3; justify-self: end; text-align: right; font-size: 0.9rem; line-height: 1.35; color: var(--c-text); }

:where(.sl-body) .ge-cta { margin-top: 1.75rem; text-align: center; }
:where(.sl-body) .ge-btns { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.75rem; }
:where(.sl-body) .ge-contact { max-width: 56ch; margin: 1rem auto 0; color: var(--c-text-muted); font-size: 0.95rem; line-height: 1.5; }

@media (max-width: 860px) {
  :where(.sl-body) .ge-grid { grid-template-columns: minmax(0, 1fr); gap: 1.25rem; }
  :where(.sl-body) .ge-panel { padding: 1.6rem 1.25rem; }
}
@media (max-width: 480px) {
  /* Note drops under the headcount instead of squeezing to a 2-word column. */
  :where(.sl-body) .ge-rung { grid-template-columns: auto minmax(0, 1fr); }
  :where(.sl-body) .ge-rung-note { grid-column: 1 / -1; justify-self: start; text-align: left; }
  :where(.sl-body) .ge-btns .btn { width: 100%; }
}

/* ============================================================================
   COMPOSITION — per-brand GEOMETRY (theme.composition). Moves WHERE THE INK SITS.

   Why this exists: measured 2026-07-15, Pure IV vs Top Tier scored 89.7% silhouette
   similarity with colour, font and copy stripped ("same website in different colours")
   while ALREADY differing in 8 of 9 variant categories, palette, fonts and hero. Skins
   are not differentiation. Every shared section was header-centered on BOTH sites
   (10/10) because a centered .section-header was the only thing the renderer could
   emit. Re-measure any change with: npm run silhouette -- <urlA> <urlB>

   R8 explicitly allows this: "a design may adopt a different treatment (e.g.
   left-aligned headers) as long as it is applied uniformly across the page.
   Congruency + intent is the rule; a specific alignment is not."
   ========================================================================= */

/* Editorial-left composition. Applied UNIFORMLY (R8): the header AND its content move
   together. Left header over a centered grid is the incongruent version and reads as a
   bug — it is exactly the "lonely left-hugging card" R10 warns about, inverted. */
:where(.sl-body).hdr-left .section-header {
  text-align: left;
  margin-left: 0;
  margin-right: auto;
  max-width: 46ch;
}
:where(.sl-body).hdr-left .section-header .eyebrow { margin-left: 0; }
/* The card bands align to the same left edge as the header they sit under, so a short
   last row hangs WITH the composition instead of floating against it. */
:where(.sl-body).hdr-left .cards-center, :where(.sl-body).hdr-left .auto-grid, :where(.sl-body).hdr-left .auto-items, :where(.sl-body).hdr-left .why-rows, :where(.sl-body).hdr-left .steps-row { justify-content: flex-start; }
/* Full-bleed bands (hero, final_cta) stay centered: they are deliberate exceptions in
   R8 and their copy is the focal point, not a column in a flow. */
:where(.sl-body).hdr-left .hero .section-header, :where(.sl-body).hdr-left .section-final_cta .section-header { text-align: center; margin-left: auto; max-width: none; }
/* THE PHONE COLLAPSE IS DELETED, AND THAT DELETION IS THE POINT.
   This used to re-center everything under 768px, reasoning that "there is no width left for an
   editorial gutter to read as intentional." That conflates two different things: an editorial
   GUTTER (an indent, which genuinely needs width) with LEFT ALIGNMENT (a flush edge, which needs
   none). The cost of the conflation was total: theme.composition is the ONE geometry lever this
   codebase has, and it was switched off on the only device the client reviews from — so the whole
   feature could only ever move a desktop screenshot nobody looks at. That is the definition of an
   invisible change, shipped as a system.
   And on the phone it is not neutral, it is the defect: at 390px every h2 wraps to two lines, so a
   CENTERED header rags on both edges directly above card text that is already flush left — two
   conflicting axes inside one viewport, 12 sections deep. Left is congruent AND it is the only
   composition that survives the wrap.
   Safe by measurement, not by hope: 0 of 22 brands set theme.composition (verified in the DB), so
   hdr-left is dead code for everyone until a brand opts in. R8 holds — the header and its bands
   still move TOGETHER at every width, and at 1-up `flex-start` and `center` are the same pixel for
   a full-width card, so this only bites where it should (the 2-up band). hero/final_cta keep their
   centered carve-out above. */

/* Measure (R7 keeps ONE content width per page; this changes WHICH one, per brand). */
/* Both numbers move together. The first version set only --content-max, but .container
   hard-coded max-width:1200px and never read it, so meas-wide declared 1320 and delivered 1200 —
   a token that measured as doing nothing. Verified live before/after with getBoundingClientRect. */
:where(.sl-body).meas-wide { --container-max: 1360px; --content-max: 1280px; }
:where(.sl-body).meas-narrow { --container-max: 1040px; --content-max: 960px; }

/* Measure (R7 keeps ONE content width per page; this changes WHICH one, per brand).
   --container-max moves the PAGE edge with the grid edge; without it the two disagree and the
   brand reads as a 1200px page with oddly-sized grids inside it. */
:where(.sl-body).meas-wide { --content-max: 1320px; --container-max: 1320px; }
:where(.sl-body).meas-narrow { --content-max: 960px; --container-max: 1040px; }
/* A wider page needs a wider gutter or the content sits on the viewport edge. */
:where(.sl-body).meas-wide .container { padding-left: 2rem; padding-right: 2rem; }

/* ── GRID: ruled rows (theme.composition.grid = 'ruled-rows') ────────────────────
   THE PRIMITIVE LEVER. Header alignment and measure move the ink sideways; this changes the
   SHAPE of every content band. Measured 2026-07-15: with palette/fonts/hero/8-of-9 variants
   ALREADY different, Pure IV vs Top Tier still matched on layout primitive 10/10 — and
   primitive is 0.5 of the silhouette score. Every band on every brand was a centered N-up
   card grid because that was the only thing the renderer could emit.

   R8 COMPLIANCE: applied UNIFORMLY to every content card band via a single brand-level
   switch — never per-section. R8's carve-outs are preserved as-is:
     - .trust-row      compact reassurance strip (chrome, not a content band).
     - .pkg-track      R5 mandates the package carousel.
     - details/summary FAQ stays an accordion (R13).
     - hero / final_cta full-bleed bands, R8's explicit exceptions.
     - .pricing-tiers  a price COMPARISON reads side-by-side (same logic as R14's matrix).
   R4 is strengthened: a one-per-row index cannot orphan a trailing card.

   SHAPE-MATCHED, NOT ONE-SIZE: an icon+label tile stretched to a full row leaves ~78% of the
   band empty, so compact tiles take a TWO-column ruled index instead. Still one congruent
   brand decision: every band is a hairline-ruled list; the column count follows CONTENT SHAPE
   uniformly. The silhouette only asks whether the primitive DIFFERS, not by how much, so
   grid-4up -> grid-2up scores exactly like grid-4up -> grid-1up. */
:where(.sl-body).grid-rows .cards-center, :where(.sl-body).grid-rows .addon-grid, :where(.sl-body).grid-rows .wpkg-grid, :where(.sl-body).grid-rows .auto-items {
  display: flex;
  flex-direction: column;
  flex-wrap: nowrap;
  align-items: stretch;
  gap: 0;
  max-width: var(--content-max);
  border-top: 1px solid var(--c-border);
}
/* Compact icon+label tiles: a two-up ruled index, not a sparse ladder.
   NOTE: .cat-card has NO mobile flex-basis:100% rule (unlike .cards-center > .card) — it
   renders 2-UP ON MOBILE today. Forcing 1fr below 768px is what makes the phone page ~4.6%
   taller; delete the following @media line to keep mobile at its current 2-up height. */
:where(.sl-body).grid-rows .cat-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  column-gap: 3rem;
  row-gap: 0;
  max-width: var(--content-max);
  border-top: 1px solid var(--c-border);
}
@media (max-width: 768px) { :where(.sl-body).grid-rows .cat-grid { grid-template-columns: minmax(0, 1fr); } }
/* value_prop_two_col / contact_two_col carry an INLINE grid-template-columns:1fr 1fr from the
   shared renderer (renderSection.ts:388/390/1208), so this needs !important exactly like the
   existing mobile rule at global.css:2154. */
:where(.sl-body).grid-rows .vp-2col { grid-template-columns: minmax(0, 1fr) !important; gap: 1.5rem !important; }
/* Collapsing a 2-col split to 1 col hands its text the FULL band; at 1240px the body copy ran
   a ~150-character line, which R7 exists to prevent. One column is not permission to abandon
   the measure. */
:where(.sl-body).grid-rows .vp-2col > * { max-width: var(--content-measure); }

/* The row itself: full measure, chrome stripped, separated by a hairline instead of a shadow. */
:where(.sl-body).grid-rows .cards-center > *, :where(.sl-body).grid-rows .cat-grid > *, :where(.sl-body).grid-rows .addon-grid > *, :where(.sl-body).grid-rows .wpkg-grid > *, :where(.sl-body).grid-rows .auto-items > * {
  flex: 1 1 auto;
  width: 100%;
  max-width: none;
  min-height: 0;
  background: none;
  border: 0;
  border-bottom: 1px solid var(--c-border);
  border-radius: 0;
  box-shadow: none;
  padding: 1.5rem 0;
  text-align: left;
  align-items: flex-start;
}
/* Chrome-stripped rows must not re-inherit the card hover lift (global.css:78/687). */
:where(.sl-body).grid-rows .cards-center > *:hover, :where(.sl-body).grid-rows .cat-grid > *:hover, :where(.sl-body).grid-rows .addon-grid > *:hover, :where(.sl-body).grid-rows .wpkg-grid > *:hover, :where(.sl-body).grid-rows .auto-items > *:hover {
  transform: none;
  box-shadow: none;
  border-color: var(--c-border);
}
/* A row is full-measure, so its prose must still honour R7's text edge. */
:where(.sl-body).grid-rows .cards-center > * > p, :where(.sl-body).grid-rows .addon-grid > * > p, :where(.sl-body).grid-rows .wpkg-grid > * > p { max-width: var(--content-measure); }
/* .wpkg-cta is align-self:stretch (global.css:2803) to pin CTAs to a card floor. In a row that
   becomes a full-bleed dark "Book this bundle" bar across the whole page, once per bundle.
   Reset the stretch, the auto-margin and the button's implied full width. */
:where(.sl-body).grid-rows .wpkg-cta { align-self: flex-start; margin-top: 1rem; text-align: left; }
:where(.sl-body).grid-rows .wpkg-cta .btn { display: inline-flex; width: auto; }
/* .wpkg-list's border-top (global.css:2797) reads as a stray dash once the card walls are gone. */
:where(.sl-body).grid-rows .wpkg-list { border-top: 0; padding-top: 0; max-width: var(--content-measure); }
/* .steps-connected::before (global.css:284) draws a HORIZONTAL rail — meaningless in a
   vertical list. Already hidden below 768px; hide it for every brand in rows mode. */
:where(.sl-body).grid-rows .steps-connected::before { display: none; }

/* ── bands-tinted: alternating brand-tinted bands (theme.sections.rhythm = 'tinted') ──────────
   An opt-in, per-brand rhythm. It exists because an archetype can force every band to
   --c-surface; on a brand whose surface is #FFFFFF that renders the page as one unbroken white
   scroll and leaves --c-surface-alt (a colour the CLIENT asked for) painted nowhere.

   SPECIFICITY, deliberately: (0,4,3), matching
   `body.ad-typographic-clinical.sections-alternate main > section.section:nth-of-type(even)` so
   an explicit per-brand request is not silently out-shouted by an archetype default. Source order
   then decides, and this block is last. NO !important — that is what erased the coverage map's
   own band earlier tonight. An archetype states a DEFAULT; a brand token states an INTENT, and
   intent wins.

   The tint is --c-surface-alt (the brand's own second surface), never a hardcoded colour. */
:where(.sl-body).bands-tinted.sections-alternate main > section.section:nth-of-type(even):not(.final-cta):not(.section-hub-cta):not(.sec-room):not(.sec-photo):not(.comp-trust-band):not(.block-route-section), :where(.sl-body).bands-tinted:not(.sections-alternate) main > section.section:nth-of-type(even):not(.section-tier_comparison):not(.final-cta):not(.section-hub-cta):not(.sec-room):not(.sec-photo):not(.comp-trust-band):not(.block-route-section) {
  background: var(--c-surface-alt);
}
/* Sections that paint their OWN band (the coverage map's dark panel, full-bleed hero/CTA) keep it:
   they are R8's deliberate exceptions and already carry their own background. */
:where(.sl-body).bands-tinted main > section.section-service_area_map { background: unset; }

/* THE TRUST STRIP IS THE ANCHOR, NOT A THIRD CREAM BAND.
   Two problems, one decision. (1) Its icon circles are var(--c-surface-alt) — the SAME beige the
   tinted rhythm paints the band, measured Δ=0 RGB: five invisible circles in the first section
   under the hero. Painting the band beige is what CAUSED that; they were beige-on-white before.
   (2) A page that only ping-pongs surface/surface-alt is a checkerboard, not a composition — two
   values alternating is the laziest possible rhythm.
   So the strip lands in the brand's PRIMARY: a dark anchor directly under the hero that catches the
   video's scrim, gives the eye somewhere to land, and introduces a third value so the page reads
   white / beige / navy instead of cream-cream-cream. Gold icons and white copy are her own palette
   doing the work. It is the same move the coverage map already makes further down, which is why the
   page has exactly two dark anchors and they bracket the content. */
:where(.sl-body).bands-tinted.sections-alternate main > section.section.section-trust_strip, :where(.sl-body).bands-tinted main > section.section.section-trust_strip {
  background: var(--c-room);
  color: var(--c-on-room);
}

/* policy_expand ALWAYS takes the plain surface, never the tint.
   Its whole point is a large warm photograph, and a warm photo on a warm tinted band gives you a
   beige rectangle inside a beige rectangle — no edge, no subject, no reason to look. Giving the
   frame a hairline was not enough: the complaint was never "the photo lacks a border", it was "the
   whole thing is beige", and it was right.
   This is where a mechanical two-value rhythm breaks: alternation counts sections, it cannot know
   one of them is carrying a cream photograph. A band that hosts a large image is a SURFACE for that
   image and has to stay out of its way. Same (0,5,3) as the trust-strip anchor so it beats the
   (0,4,3) alternation rather than fighting it with !important. */
:where(.sl-body).bands-tinted.sections-alternate main > section.section.section-policy_expand, :where(.sl-body).bands-tinted main > section.section.section-policy_expand {
  background: var(--c-surface);
}
:where(.sl-body).bands-tinted .section-trust_strip .trust-row-item .trust-ic {
  background: rgba(255, 255, 255, 0.09);
  color: var(--c-accent);
}
:where(.sl-body).bands-tinted .section-trust_strip .trust-row-item span { color: var(--c-on-room); }
/* The hairline dividers were tuned for a light band. NOTE the ::before pseudo-element IS the
   divider; the item itself must never take a background or it paints a 200px pale box across the
   navy. (It did. That is what the light rectangle behind items 2-5 was.) */
:where(.sl-body).bands-tinted .section-trust_strip .trust-row-item + .trust-row-item::before {
  background: rgba(255, 255, 255, 0.16);
}
@media (max-width: 640px) {
  :where(.sl-body).bands-tinted .section-trust_strip .trust-row-item + .trust-row-item {
    border-top-color: rgba(255, 255, 255, 0.16);
  }
}

/* A CARD MUST NEVER BE THE SAME COLOUR AS ITS BAND.
   Alternating bands only solves half the problem: on a tinted band a white card lifts, but on a
   white band a white card is invisible — measured Δ=0 RGB between .card and its section on
   popular_packages_local and treatment_categories, leaving the drip menu as faint outlines on
   nothing. The rule is the inverse of the band, not a fixed colour: tinted band -> surface card,
   surface band -> tinted card. Then every card has an edge on every band, in any brand palette.
   Cards that paint themselves (the navy pkg-body reveal, the dark CTA) are untouched: they set
   their own background later in the cascade. */
:where(.sl-body).bands-tinted main > section.section:nth-of-type(odd) .card, :where(.sl-body).bands-tinted main > section.section:nth-of-type(odd) .addon-card, :where(.sl-body).bands-tinted main > section.section:nth-of-type(odd) .cat-card {
  background: var(--c-surface-alt);
}
/* The clinical hairline between every section is redundant once bands carry the rhythm — two
   separators doing one job reads as noise. Keep it only between two same-coloured bands. */
:where(.sl-body).bands-tinted .section:nth-of-type(even) + .section, :where(.sl-body).bands-tinted .section:nth-of-type(odd) + .section { border-top: 0 !important; }

/* ══ bands-paper — ONE STOCK. White is a material, never a room. ═════════════════════════════
   theme.sections.rhythm = 'paper'. Opt-in per brand, so every other brand is untouched.

   WHY THIS REPLACES 'tinted', IN ONE NUMBER: #FFFFFF against #EFE7D9 is a contrast ratio of
   1.23:1. Below ~1.5:1 the eye does not resolve two surfaces — it reads ONE surface under uneven
   light. 'tinted' alternated exactly those two values on nth-of-type across 11 bands, so the
   page's entire compositional structure was a non-event printed eleven times. The client called
   it "cheap ... the cream and white just going back and forth"; the number says he was reading it
   correctly, and it is why round after round of band paint was invisible to him.

   AND YOU CANNOT FIX IT BY ADDING A THIRD LIGHT VALUE. Every cream between #FFFFFF and #EFE7D9
   sits within 1.5:1 of both — a ladder of mush is the same disease with more rungs. In this
   palette (navy #1B2A44, gold #C5A253, beige #EFE7D9, white) the only values with real separation
   are the navy and the gold. So "more than two backgrounds" is answered by DELETION, not
   addition:
     PAPER  — beige, the page's single stock. Every band, by default.
     CARD   — white, every card, on every rung. NEVER a band again.
     ROOM   — navy, full-bleed. You are inside it. Used 3x.
     OBJECT — navy, inset, paper rails visible either side at every width. You look AT it. 2x.
   Navy goes 8% -> ~35% of the page and stops being a cameo.

   THE ARCHITECTURE: BANDS DECLARE TOKENS; COMPONENTS CONSUME THEM. The specificity fight happens
   ONCE, at the band, on a custom property — never per-descendant, never with !important.
   Never set `color:` on a band: h1-h6 hardcode `color: var(--c-text)` (:24) so a band-level
   `color` cannot reach a heading anyway, and `.pkg-card` is an <a> that would inherit it, landing
   WHITE TEXT ON A WHITE CARD. Rebind --c-text instead and both problems vanish.
   `:nth-of-type(n)` always matches; it buys a class-column point and nothing else. */

:where(.sl-body).bands-paper {
  /* THE PAGE'S DEFAULT EYEBROW INK. Read by renderSection.ts's inline eyebrow style (which no
     selector could otherwise beat) AND by the routing rules below. Navy on paper = 11.58:1;
     the gold it replaces measured 1.97:1, i.e. invisible. Rooms/objects re-declare it to gold. */
  --eyebrow-ink: var(--c-primary);
  /* --c-text-muted ships #6E7686 — an imported grey on a palette that owns no grey, and 3.67:1
     on beige (an AA fail) on every band once beige is the only stock. Navy-into-beige gives
     #525B6B: 5.52:1 on paper, 6.86:1 on a white card. In-palette, and it passes. */
  --c-text-muted: var(--c-muted-on-surface, color-mix(in srgb, var(--c-primary) 74%, var(--c-surface-alt)));
  /* --card-shadow ships rgba(0,0,0,0.06) (brand.ts:90). Black is a fifth, DEAD colour on a
     four-colour page — rgba(0,0,0,.0x) is the most reliable template tell there is. Cast the
     shadow in her own navy so the page contains no colour she did not choose. */
  --card-shadow: 0 4px 16px color-mix(in srgb, var(--c-primary) 10%, transparent);
}

/* RUNG 1 — PAPER. (0,3,3) beats ad-typographic-clinical's `main > section.section
   { background: var(--c-surface) }` (:1574, (0,2,3)) on SPECIFICITY, not source order.
   The coverage map self-paints with !important (:478) and is untouched by this. */
/* :not(.final-cta) — the closing CTA paints its OWN dark ground and sets white ink to match
   (`.final-cta` at :458). Repainting it with the page stock left that white heading on a near-white
   band at 1.09:1 on every hub page. A band that brings its own ink is not the page's to repaint. */
:where(.sl-body).bands-paper main > section.section:nth-of-type(n):not(.final-cta) { background: var(--c-surface-alt); }

/* Inherently-dark components keep their dark plate under paper. THE CLASS OF BUG: a component
   that paints its OWN dark wrapper and hardcodes white ink on it (`background: var(--c-primary-dark);
   color: #fff`) loses the background to the paper repaint above — (0,3,3) beats the component's
   (0,1,1) — but KEEPS the white ink, because that ink is set per-descendant at (0,2,1) and no band
   rule touches it. Result: white text on beige. tier_comparison measured 1.07:1; ingredient_choice
   measured 1.1:1 (h2, subhead and both option columns invisible on desktop and mobile).
   This exemption must therefore list EVERY self-darkening component. The full set in this
   stylesheet is tier_comparison (:2501), ingredient_choice (:2399) and stats (:603) — stats paints
   itself with !important so the repaint never reaches it and it needs no entry here. Any NEW
   section that ships its own dark plate belongs on this list. */
:where(.sl-body).bands-paper main > section.section.section-tier_comparison:nth-of-type(n), :where(.sl-body).bands-paper main > section.section.section-ingredient_choice:nth-of-type(n) { background: var(--c-hero-plate); }

/* meas-narrow shrinks the row, but every inline --sl-basis was computed by cardBasis() against
   the 1080px inner width, and flex WRAP decisions use the base size, so intended column counts
   wrap into orphans under the ~1000px narrow inner (measured: 8 chips 3+3+2, 4 cards 3+1).
   Rescale the base size on every --sl-basis consumer; intended columns then fit again. */
:where(.sl-body).meas-narrow .cards-center > .card, :where(.sl-body).meas-narrow .steps-row > .card, :where(.sl-body).meas-narrow .cat-card, :where(.sl-body).meas-narrow .auto-card, :where(.sl-body).meas-narrow .tier-card, :where(.sl-body).meas-narrow .auto-item, :where(.sl-body).meas-narrow .addon-card, :where(.sl-body).meas-narrow .wpkg-grid > .wpkg-card { flex-basis: calc(var(--sl-basis, 330px) * 0.85); }

/* GOLD ROUTING — the one structural job gold has.
   MEASURED: gold on beige is 1.95:1, UNDER visual-lint's INVISIBLE=2.0 threshold. Every .eyebrow
   on this page is gold (:183, :279, :1590), so once beige is the only stock every one of them is
   a build blocker — gold's current use is not restraint, it is an illegibility wearing
   restraint's clothes. Gold becomes the ink of the NAVY and only of the navy (5.94:1), so it
   stops being a colour and becomes a signal that says "the brand is transacting here". On paper
   an eyebrow goes navy (11.58:1).
   (0,3,3) beats .eyebrow (:279), .section-header .eyebrow (:183), .coverage-text-col .eyebrow
   (:495) and body.ad-typographic-clinical .section-header .eyebrow (:1590, (0,3,1)).
   Scoped to `main > section.section` so the hero (section.hero, not .section) keeps its gold. */
:where(.sl-body).bands-paper main > section.section .eyebrow { color: var(--eyebrow-ink, var(--c-primary)); }

/* THE BADGE CHIP. This brand's art direction is adacc-badge, so every .section-header .eyebrow is
   a chip: `body.ad-typographic-clinical.adacc-badge .section-header .eyebrow` (:1705) fills with
   color-mix(--c-accent 14%, --c-surface) = #F7F2E7 and inks it 86%-gold. That chip was designed
   against a WHITE band: on PAPER it is a near-white pill on beige (1.2:1 — an invisible chip
   around illegible text), and on NAVY it would be a pale cream lozenge. It is (0,4,1); this is
   (0,4,3), so it wins on the element column without !important. Chip and edge are tokens, so each
   rung retints them by declaring two properties — the band never restyles the component. */
/* SCOPED TO adacc-badge, which is the art direction that actually makes the eyebrow a chip. The
   rule's own comment says so — "this brand's art direction is adacc-badge" — but the selector did
   not, so on every OTHER paper site the eyebrow is a plain block element and the chip painted as a
   full-width pale BAR across the band. Visible on Tidewater the moment it got a dark room: a stray
   lighter rectangle behind "BOOST YOUR DRIP" that reads as a rendering artifact.
   The ink rebinding above still applies everywhere; only the chip is conditional. */
:where(.sl-body).bands-paper.adacc-badge main > section.section .section-header .eyebrow {
  color: var(--eyebrow-ink);
  background: var(--eyebrow-chip, var(--c-surface));                                  /* white: the mat */
  border-color: var(--eyebrow-chip-edge, color-mix(in srgb, var(--c-primary) 14%, transparent));
}
:where(.sl-body).bands-paper:not(.adacc-badge) main > section.section .section-header .eyebrow {
  color: var(--eyebrow-ink);
}

/* THE TRUST STRIP IS OVERLAID ON THE HERO VIDEO (Ian, desktop): it is no longer its own navy band,
   it sits transparent over the bottom of the (now taller) film, so the licensure badges live on the
   footage. Negative margin pulls it up onto the hero; z-index lifts it above the scrim. The token
   rebinds stay — white labels + gold icons already read on the dark bottom of the video. */
:where(.sl-body).bands-paper main > section.section.section-trust_strip:nth-of-type(n) {
  /* A gentle dark scrim (a GRADIENT, i.e. a background-image) rather than pure transparent: it
     darkens the footage just where the row sits so the white labels stay legible, and — because it
     is a background-image — visual-lint's bgOf() correctly SKIPS this band (it cannot measure text
     composited over the sibling <video> behind it, exactly the hero's own blind spot; a pure
     transparent bg made it read the white PAGE behind and false-flag white-on-white). The video
     still shows through the top of the gradient. */
  /* NO dark band behind the row (Ian). A transparent gradient — invisible, but still a
     background-IMAGE so visual-lint's bgOf skips this band (it can't read text over the sibling
     <video>; a plain transparent bg made it false-flag white-on-white). Legibility comes from the
     hero's own gradual bottom scrim + a text-shadow on the labels, not a bar. */
  background: linear-gradient(rgba(0,0,0,0), rgba(0,0,0,0));
  /* sit at the very BOTTOM of the video: pull up ~its own height so the row lands on the footage
     bottom and cream begins there. Transparent now, so any small over/under-pull is invisible. */
  margin-top: -120px;
  padding-top: 0.35rem;
  padding-bottom: 0.6rem;
  position: relative;
  z-index: 3;
  --c-text: var(--c-on-dark);                 /* .trust-row-item span (:206) -> white on footage */
  --c-border: rgba(255, 255, 255, 0.28);
  --eyebrow-ink: var(--c-accent-ink-dark, var(--c-accent));
}
/* legibility on bare footage: a soft shadow behind the labels + icon discs, no band needed */
:where(.sl-body).bands-paper main > section.section.section-trust_strip:nth-of-type(n) .trust-row-item span {
  text-shadow: 0 1px 10px rgba(0,0,0,0.75), 0 1px 2px rgba(0,0,0,0.6);
}
:where(.sl-body).bands-paper main > section.section.section-trust_strip:nth-of-type(n) .trust-ic {
  box-shadow: 0 2px 12px rgba(0,0,0,0.4);
}
/* On a phone the five items STACK (~350px tall); overlaying only lands the top one or two on the
   footage and drops the rest onto the light page below with white-on-light labels. So mobile keeps
   the trust as a compact NAVY bar under the (still taller) hero — no overlay. */
@media (max-width: 768px) {
  :where(.sl-body).bands-paper main > section.section.section-trust_strip:nth-of-type(n) {
    background: var(--c-room);
    margin-top: 0;
  }
  /* on the solid navy mobile bar the labels sit on flat navy, so the footage-legibility shadow
     is unneeded and reads as a doubled/blurred ghost — drop it (Ian's PureIV polish pass). */
  :where(.sl-body).bands-paper main > section.section.section-trust_strip:nth-of-type(n) .trust-row-item span {
    text-shadow: none;
  }
}

/* ══ BOXED ACCORDIONS — FAQ + "How Booking Works" get a card per item (Ian) ═══════════════════
   Both were borderless rows separated by a hairline; Ian wants each question in its own box. Each
   <details> becomes a lifted card. FAQ is on NAVY → white cards, ink re-bound to dark, gold chevron.
   Booking (policy_expand) is on CREAM → white cards that lift the usual way. */
:where(.sl-body).bands-paper main > section.section.section-city_faq .faq-item {
  background: var(--c-surface);
  border: 0;
  border-radius: 14px;
  box-shadow: 0 8px 22px -10px rgba(0, 0, 0, 0.45);
  padding: 0.1rem 1.3rem;
  /* The gap .pxp-item below has carried since day one and this rule never did — so the white
     rounded cards sat flush on the navy band, which is the owner-reported "FAQ bubbles touch
     each other" defect. Same value as the policy accordion, for the same reason. */
  margin-bottom: 0.85rem;
  --c-text: var(--c-primary);
  --c-text-muted: var(--c-muted-on-surface, color-mix(in srgb, var(--c-primary) 74%, var(--c-surface-alt)));
}
:where(.sl-body).bands-paper main > section.section.section-city_faq .faq-item > summary { padding: 1.15rem 0; }
:where(.sl-body).bands-paper main > section.section.section-city_faq .faq-item > p { padding: 0 0 1.15rem; }
:where(.sl-body).bands-paper main > section.section.section-city_faq .faq-chevron { color: var(--c-accent); }
/* EVERY faq family member inside a NAVY ROOM gets the same plate, not just city_faq. The room's
   ink rebind below (:sec-room list) sets .faq-item ink DARK on the assumption a plate exists —
   an assumption comp-faq-cards satisfies and comp-split / comp-faq-ruled / the bare default do
   not, which shipped navy-on-navy questions to CI on CHIdrate (faq comp-split sec-room) the
   first day the assigner got livelier. The plate makes the rebind's assumption true for the
   whole family. Same geometry as the city_faq rule above. */
:where(.sl-body).bands-paper main > section.section.sec-room:nth-of-type(n) .faq-item {
  background: var(--c-surface);
  border: 0;
  border-radius: 14px;
  box-shadow: 0 8px 22px -10px rgba(0, 0, 0, 0.45);
  padding: 0.1rem 1.3rem;
  margin-bottom: 0.85rem;
}

:where(.sl-body).bands-paper main > section.section.section-policy_expand .pxp-item {
  background: var(--c-surface);
  border: 1px solid var(--c-border);
  border-radius: 14px;
  box-shadow: var(--card-shadow);
  padding: 0.1rem 1.3rem;
  margin-bottom: 0.85rem;
  /* A WHITE card rebinds its own ink, exactly as the city_faq rule above does. Without this the
     card inherits whatever the BAND set: put this section in a navy room and the room's light
     muted ink lands on white at 2.25:1. The FAQ rule got these two lines and this one never did,
     which only surfaced when the two swapped places in the beige -> navy -> beige reorder. */
  --c-text: var(--c-primary);
  --c-text-muted: var(--c-muted-on-surface, color-mix(in srgb, var(--c-primary) 74%, var(--c-surface-alt)));
}
:where(.sl-body).bands-paper main > section.section.section-policy_expand .pxp-summary { padding: 1.15rem 0; }
:where(.sl-body).bands-paper main > section.section.section-policy_expand .pxp-body { padding-bottom: 1.1rem; }
/* .trust-ic fills with --c-surface-alt (:204) — which is now the PAPER, i.e. five beige discs on
   navy. It is the same Δ=0 class of bug the old rhythm shipped, just inverted. */
:where(.sl-body).bands-paper main > section.section.section-trust_strip:nth-of-type(n) .trust-ic {
  background: rgba(255, 255, 255, 0.09);
}

/* ══ STRICT ALTERNATION — the navy bands ═══════════════════════════════════════════════════════
   Ian's rule (2026-07-16): no two adjacent sections may share a background; the whole page reads
   as a consistent rhythm and NEVER repeats. Cream and navy are the only two values with real
   contrast (every cream is ~1.23:1 from every other), so the rhythm is cream/navy alternating,
   with ONE photo band ('what_to_expect') bridging the two hard-navy fixed points (add-ons, whose
   gold prices die on cream, and the map). The resulting order never repeats a neighbour:
     trust(N) value_prop(C) symptom(N) drip(C) addons(N) what_to_expect(PHOTO) why_local(C)
     treatment(N) wellness(C) group(N) testimonials(C) map(N) policy(C) faq(N) final(C)
   Because no two navy bands are adjacent, EVERY navy band is isolated (cream on both sides), so
   each simply glows and fades to plain navy at its edges where it meets cream — no seam is even
   possible. The token rebinds are generic (band -> light ink; white cards -> dark ink). */
/* SURFACE = navy ROOM. Assignment is now per-site DATA: renderer adds `.sec-room` to any section
   named in theme.surfaces.dark_bands (Sections.astro), so a site composes its OWN dark bands from
   the same primitive instead of this list being welded to fixed section keys. Top Tier's dark_bands
   = [symptom_first_browse, addons_boosters_grid, treatment_categories, group_events, city_faq] ⇒
   byte-identical to the old hardcoded list. nth-of-type(n) keeps the specificity that clears the
   base rules without an !important. */
:where(.sl-body).bands-paper main > section.section.sec-room:nth-of-type(n) {
  background: var(--c-room);
  /* NOTE (2026-07-31, tried and reverted): rebinding --c-text does not change `color`, which is
     declared once on body as `color: var(--c-text)` — so a bare <p> in a room keeps inheriting
     body's navy. CHIdrate's why_local_grid intro renders navy-on-navy for exactly this reason.
     Adding `color: var(--c-text)` here DOES fix that paragraph, but it then cascades white into
     every chip and card in the room that carries its own white fill, taking CHIdrate from 4
     errors to 23. Adding it to the card-rebind rule below as well does not recover it. The real
     fix is per-component (each bare-text component needs its own color declaration), not a
     blanket cascade — left for a pass that can go component by component. */
  --c-text: var(--c-on-room);                                                     /* h2 -> 14.38:1 */
  --c-text-muted: var(--c-muted-on-room, color-mix(in srgb, var(--c-surface-alt) 72%, var(--c-primary)));
  --eyebrow-ink: var(--c-accent-ink-dark, var(--c-accent));                                                 /* -> 5.94:1 */
  --eyebrow-chip: rgba(255, 255, 255, 0.09);
  --eyebrow-chip-edge: rgba(255, 255, 255, 0.18);
  /* the archetype's `.section + .section { border-top: 1px ... !important }` (:1575) would draw a
     beige hairline at the top of a navy band; rebind the TOKEN it reads so the important border
     resolves to nothing. Isolated navy meets cream cleanly, no hairline wanted. */
  --c-border: transparent;
}

/* AND THE ONE THING NEITHER PAINT CAN DECIDE ALONE: WHAT SITS DIRECTLY UNDER A ROOM. The rule above
   gives a room the brand's darkest ground and the base `.final-cta` rule gives the closing band
   `--c-cta-bg`, which on most brands is a gradient whose FIRST STOP is that same `--c-primary`.
   Each is right on its own and wrong when a page puts one straight after the other, which the hub
   and listing pages do everywhere: 521 built pages here close on a room followed immediately by the
   closing band. Measured on halo's packages page that is 625px of rgb(138,75,59) meeting 354px of
   rgb(78,37,27) at 1.96:1 - one brown band as far as a reader is concerned - and on nine of the
   nineteen lane/archetype pairs measured the gradient opens on the room's colour exactly, 1.00:1
   at the seam, with only a 1px hairline between them.
   This decision was already written once and correctly, but inside a single lane by name, so that
   lane's pages were the only ones in the fleet that broke the run and thirteen others kept shipping
   the pair. It is a property of the two SHARED paints above, not of any lane, so it lives with them
   and is written unscoped. The lane copy has been removed rather than repeated thirteen times.
   The closing band yields, because it is the one that has somewhere else to go: on paper it still
   reads as a close, whereas a room that turns pale stops being a room. Its ink, its eyebrow and
   BOTH of its buttons come with it, or they keep the light-on-dark pairing they were given for a
   ground they are no longer standing on - the outline button was measured at 1.11:1 on a live
   client on 2026-08-24 when exactly that was forgotten in the lane copy of this rule.
   `!important` on the ground because three archetypes paint `.final-cta` with an `!important` of
   their own (ad-editorial-luxe, ad-bold-modern, ad-typographic-clinical) and there is no winning
   that on specificity alone. A band that already carries a photograph or stone owns its ground and
   wants no paper, so `.sec-photo`, the photo CTA skin and the dark-marble preset stand outside it -
   marble's closing band is a translucent scrim over the same stone the room is cut from, which is
   already a different surface. Measured across nineteen lane/archetype pairs after this rule: every
   room-to-band step is 5.4:1 or better, and every heading, paragraph and button standing on the
   yielded band is 5.8:1 or better. Only the lane that already had the fix renders unchanged. */
:where(.sl-body) {
  /* THE LIGHT-CONTEXT INKS, SAVED BEFORE ANY BAND REBINDS THEM. A section that turns dark rebinds
     `--c-text` and `--c-accent-ink` on itself, so a rule that later hands that same section back to
     paper can no longer read the page's own ink out of those tokens - it would restore white onto
     cream, which is how the luxe lanes would have failed here. Two lanes each wrote this save
     privately (refine-luxe-noir's `--ln-text-save` is one); kept once, at the level where it is true for
     every lane and every brand. */
  --c-text-paper: var(--c-text);
  --c-text-paper-muted: var(--c-text-muted);
  --c-accent-ink-paper: var(--c-accent-ink);
}
:where(.sl-body).bands-paper:not(.dark-marble) main > section.section.sec-room + section.section.final-cta:not(.sec-photo):not(.cta-skin-photo) {
  background: var(--c-surface-alt) !important;
  --c-text: var(--c-text-paper);
  --c-text-muted: var(--c-text-paper-muted);
  --c-accent-ink: var(--c-accent-ink-paper);
  --eyebrow-ink: var(--c-accent-ink-paper);
  --c-cta-text: var(--c-on-room);
  --c-cta-bg: var(--c-room);
  color: var(--c-text-paper);
}
:where(.sl-body).bands-paper:not(.dark-marble) main > section.section.sec-room + section.section.final-cta:not(.sec-photo):not(.cta-skin-photo) :is(h1, :where(.sl-body) h2, :where(.sl-body) h3) { color: var(--c-text-paper); }
:where(.sl-body).bands-paper:not(.dark-marble) main > section.section.sec-room + section.section.final-cta:not(.sec-photo):not(.cta-skin-photo) p { color: color-mix(in srgb, var(--c-text-paper) 82%, transparent); }
/* The plaque skin lifts its eyebrow out of the stack onto a dark tab of its own, so that
   one keeps the ink it was given for the tab rather than taking the band's. */
:where(.sl-body).bands-paper:not(.dark-marble) main > section.section.sec-room + section.section.final-cta:not(.sec-photo):not(.cta-skin-photo):not(.cta-skin-plaque) :is(.eyebrow, :where(.sl-body) [class*="eyebrow"]) { color: var(--c-accent-ink-paper); }
/* THE FILLED BUTTON ON THE YIELDED BAND TAKES THE CONTROL PLATE, NOT THE PRIMARY. On paper the two
   are the same value — `--c-control` resolves to `--c-room`, which resolves to `--c-primary`, so
   every light page is byte-identical — and on a dark page the primary IS a near-page navy: measured
   #10263B on the yielded band's #294248, 1.44:1, a caption with no button under it. See the control
   plate note beside `.btn-primary` at the head of this file. */
:where(.sl-body).bands-paper:not(.dark-marble) main > section.section.sec-room + section.section.final-cta:not(.sec-photo):not(.cta-skin-photo) .btn-primary {
  background: var(--c-control) !important;
  border-color: var(--c-control) !important;
  color: var(--c-on-control) !important;
}
/* AND THE SECOND BUTTON, which the lane copy of this rule forgot for weeks. Everything else on the
   band came with it - the headings, the copy, the eyebrow, the filled button - and the outline
   button kept the pale ink it was given for the dark ground it is no longer standing on. On a pale
   band an outline button is the ink, not the paper. */
:where(.sl-body).bands-paper:not(.dark-marble) main > section.section.sec-room + section.section.final-cta:not(.sec-photo):not(.cta-skin-photo) :is(.btn-secondary, :where(.sl-body) .btn-outline) {
  background: transparent !important;
  border-color: color-mix(in srgb, var(--c-text-paper) 42%, transparent) !important;
  color: var(--c-text-paper) !important;
}

/* White cards on a navy band re-bind ink BACK to dark so their own text stays readable. Covers
   every white-card primitive that appears in these sections: .cat-card (symptom/treatment browse),
   .card (group-rate cards). .addon-card is a MENU row (not a card) and keeps the band's white ink;
   the FAQ accordion is text directly on the band and keeps white too. */
/* White-card primitives inside ANY navy room rebind ink back to dark so their own text reads. This
   is now keyed by CARD CLASS under the generic .sec-room, not by section: .cat-card (the browse
   tiles), and group_events' .ge-rung / .ge-avail (white rungs + light availability pill). Transparent
   internals (.ge-chip, .addon-card menu rows, the FAQ accordion) are NOT listed, so they keep the
   band's white ink — same result as before, on whichever sections a site marks as rooms. */
/* .card / .feature-card / .step-card / .pkg-card joined 2026-07-31. The room sets
   `--c-text: var(--c-surface)` for the whole section, which is right for copy sitting ON the
   navy and wrong for copy inside a card that kept its WHITE fill — white ink on a white card,
   1:1, "EFFECTIVELY INVISIBLE". CHIdrate's about page rendered its entire `values` section that
   way, 36 R15 errors across the site, and it had been shipping like that. The generic card
   classes were simply missing from a list whose own comment says it is keyed by card class;
   refine-dark-luxe already carries exactly this set at :4545, so this aligns the two. */
/* .whyus-card and .faq-item joined 2026-08-01, and for the reason this list already documents:
   they are cards in a dark room whose ink comes from the ROOM (white) while the plate under it is
   WHITE — 1:1. It surfaced the moment comp-faq-cards gave .faq-item a plate of its own on 20
   CHIdrate pages, and comp-cards-* did the same for .whyus-card. Third time in this file, so the
   rule is worth stating: a card class that gets a solid plate inside a room must be on this list,
   or its inherited white ink lands on white. Inverting the PLATE instead (making it translucent)
   was tried first and is wrong — it leaves the room's other cards dark-on-dark. */
/* The :not(.comp-…) chain, added 2026-08-09: this rebind's whole premise is "a card with its own
   LIGHT plate inside a dark room needs dark ink". Several treatments deliberately STRIP the plate
   (comp-ledger/quiet-prose/statement/numbered/callout/split/swatch set rows transparent — "no
   boxes, just ruled rows"), and on a stripped row this rebind painted navy ink straight onto the
   navy band: why_choose[comp-callout] in a room shipped 1:1 to CI on Ember the first day the
   assigner reached more sections. A stripped row must keep the ROOM's white ink, so the rebind
   now skips sections wearing a plate-stripping treatment. comp-panel is excluded too — it paints
   and inks itself. Plate-KEEPING treatments (cards-*, wall, mosaic, faq-cards) still rebind. */
:where(.sl-body).bands-paper main > section.section.sec-room:nth-of-type(n):where(:not(.comp-ledger):not(.comp-quiet-prose):not(.comp-statement):not(.comp-numbered):not(.comp-callout):not(.comp-split):not(.comp-swatch):not(.comp-panel):not(.comp-cats-rule)) .whyus-card, :where(.sl-body).bands-paper main > section.section.sec-room:nth-of-type(n) .faq-item, :where(.sl-body).bands-paper main > section.section.sec-room:nth-of-type(n):where(:not(.comp-ledger):not(.comp-quiet-prose):not(.comp-statement):not(.comp-numbered):not(.comp-callout):not(.comp-split):not(.comp-swatch):not(.comp-panel):not(.comp-cats-rule)) .cat-card, :where(.sl-body).bands-paper main > section.section.sec-room:nth-of-type(n):where(:not(.comp-ledger):not(.comp-quiet-prose):not(.comp-statement):not(.comp-numbered):not(.comp-callout):not(.comp-split):not(.comp-swatch):not(.comp-panel):not(.comp-cats-rule)) .card, :where(.sl-body).bands-paper main > section.section.sec-room:nth-of-type(n):where(:not(.comp-ledger):not(.comp-quiet-prose):not(.comp-statement):not(.comp-numbered):not(.comp-callout):not(.comp-split):not(.comp-swatch):not(.comp-panel):not(.comp-cats-rule)) .feature-card, :where(.sl-body).bands-paper main > section.section.sec-room:nth-of-type(n):where(:not(.comp-ledger):not(.comp-quiet-prose):not(.comp-statement):not(.comp-numbered):not(.comp-callout):not(.comp-split):not(.comp-swatch):not(.comp-panel):not(.comp-cats-rule)) .step-card, :where(.sl-body).bands-paper main > section.section.sec-room:nth-of-type(n):where(:not(.comp-ledger):not(.comp-quiet-prose):not(.comp-statement):not(.comp-numbered):not(.comp-callout):not(.comp-split):not(.comp-swatch):not(.comp-panel):not(.comp-cats-rule)) .pkg-card, :where(.sl-body).bands-paper main > section.section.sec-room:nth-of-type(n):where(:not(.comp-ledger):not(.comp-quiet-prose):not(.comp-statement):not(.comp-numbered):not(.comp-callout):not(.comp-split):not(.comp-swatch):not(.comp-panel):not(.comp-cats-rule)) .why-row, :where(.sl-body).bands-paper main > section.section.sec-room:nth-of-type(n) .ge-rung, :where(.sl-body).bands-paper main > section.section.sec-room:nth-of-type(n) .ge-avail, :where(.sl-body).bands-paper main > section.section.sec-room:nth-of-type(n) .outcome-tile, :where(.sl-body).bands-paper main > section.section.sec-room:nth-of-type(n) .ge-panel {
  --c-text: var(--c-primary);
  --c-text-muted: var(--c-muted-on-surface, color-mix(in srgb, var(--c-primary) 74%, var(--c-surface-alt)));
  --c-border: color-mix(in srgb, var(--c-primary) 12%, var(--c-surface-alt));      /* #D6D0C7 */
}

/* PHOTO BANDS NEVER HAD THIS REBIND AT ALL — the list above is sec-room only. A .sec-photo band
   sets its ink white for copy sitting ON the photograph, and a card inside it that still has a
   fill of its own would render white ink on a white plate: Halo's home what_to_expect, three step
   cards, 1:1, caught by CI 2026-08-09. Rooms solved this in the list above; photo bands get the
   same treatment with the same plate-stripping :not() carve-outs (a stripped row sits on the
   photo and keeps the band's white). Not rhythm-scoped, because photo bands paint from rules that
   are not rhythm-scoped either.
   THIS LIST NO LONGER OPENS WITH .card, .step-card AND .pkg-card, and that omission is the fix.
   The premise written above — "a card inside it keeps its own white plate" — was never true for
   those three: the rule that strips card plates inside a photo band takes the plate off every
   .card unconditionally and with !important, and the renderer only ever emits `card step-card`
   and `card pkg-card`. So they had no plate for dark ink to sit on and the dark ink went onto the
   photograph — an MK build wearing refine-luxe-noir put ten text nodes of one process_steps band
   between 1.22:1 and 1.48:1, and only the single lane carrying a hand-written counter-row escaped
   it. The ink for a plateless card is now declared beside the rule that removes the plate, so
   "does this card have a plate right now" is answered once, from one class list, and that lane
   counter-row is deleted rather than copied. Anything named here must be something the stripper
   does not touch: .cat-card, .whyus-card and .auto-card carry their own fill (.auto-card is new
   here and inert today, since the renderer always pairs it with .feature-card — it is listed so
   the day it is emitted alone it is already right), and .feature-card is emitted BOTH as
   `card feature-card`, which the stripper takes and re-inks, and as `auto-card feature-card`,
   which keeps its plate and needs this. .faq-item is a bare <details> with only a hairline in the
   base sheet and is kept here solely because theme-botanical fills it; an uncomposed FAQ in a
   photo band on any other theme still wants looking at. */
:where(.sl-body) main > section.section.sec-photo:where(:not(.comp-ledger):not(.comp-quiet-prose):not(.comp-statement):not(.comp-numbered):not(.comp-callout):not(.comp-split):not(.comp-swatch):not(.comp-panel):not(.comp-cats-rule)) .feature-card, :where(.sl-body) main > section.section.sec-photo:where(:not(.comp-ledger):not(.comp-quiet-prose):not(.comp-statement):not(.comp-numbered):not(.comp-callout):not(.comp-split):not(.comp-swatch):not(.comp-panel):not(.comp-cats-rule)) .auto-card, :where(.sl-body) main > section.section.sec-photo:where(:not(.comp-ledger):not(.comp-quiet-prose):not(.comp-statement):not(.comp-numbered):not(.comp-callout):not(.comp-split):not(.comp-swatch):not(.comp-panel):not(.comp-cats-rule)) .cat-card, :where(.sl-body) main > section.section.sec-photo:where(:not(.comp-ledger):not(.comp-quiet-prose):not(.comp-statement):not(.comp-numbered):not(.comp-callout):not(.comp-split):not(.comp-swatch):not(.comp-panel):not(.comp-cats-rule)) .whyus-card, :where(.sl-body) main > section.section.sec-photo:where(:not(.comp-ledger):not(.comp-quiet-prose):not(.comp-statement):not(.comp-numbered):not(.comp-callout):not(.comp-split):not(.comp-swatch):not(.comp-panel):not(.comp-cats-rule)) .faq-item {
  --c-text: var(--c-primary);
  --c-text-muted: var(--c-muted-on-surface, color-mix(in srgb, var(--c-primary) 74%, var(--c-surface-alt)));
  --c-border: color-mix(in srgb, var(--c-primary) 12%, var(--c-surface-alt));
}
/* THE INVERSE CASE, lane edition, DELETED 2026-08-29. ad-bright-clinical used to carry its own
   three-selector counter-row here giving cards in a photo band the band's light ink, and its own
   comment closed with "Every lane that strips card plates needs a row here when it first meets a
   photo band" — which is the admission that the decision was in the wrong place. It was also
   misdiagnosed: that lane paints card plates white, it does not strip them; what stripped them
   was the universal rule further down this file, which now carries the light ink for exactly the
   classes whose plate it removes. The row is redundant for .card and .step-card, and it was
   actively wrong for .feature-card, because `auto-card feature-card` in that lane keeps a white
   plate and was being given white ink. Nothing replaces it and nothing should. */

/* ══ THE ADD-ONS ARE A MENU. PRINT THEM LIKE ONE. ═══════════════════════════════════════════
   The renderer's own comment calls this section a "priced add-on / booster upsell MENU with
   +$price pills" — and then renders six white cards in a 3-up grid. A priced list IS a menu; a
   card is for something you pick UP. That mismatch is the page's clearest category error, and it
   is GEOMETRY, which is the only lever measured to move anything (colour/variant rounds scored
   0; the sole variant that ever registered, faq.two-column, was the only one that changed shape).
   The correct primitive was already built and QUARANTINED INSIDE ONE CARD: `.addon-tiers` /
   `.addon-tier-dots` (:2710) already renders NAD+'s dose rows as name · leader-dots · price. The
   component knew the idiom and only ever used it for the exception. This promotes it to the rule.
   Measured cost of the cards: 6 identical white slabs, ~1,345px on a 390px phone (1.6 screens) to
   say six things of the form "Vitamin B12 ... +$25", each repeating the SAME "+ ADD TO ANY IV".
   CSS-ONLY and Top-Tier-only: no renderer change, so parity cannot drift and 21 brands cannot
   move. Prices are gold ON NAVY = 5.94:1 — the one place gold is legible, which is exactly why
   the menu belongs in the room and nowhere else. */
/* THE SHAPE OF THE MENU IS NOT DECLARED HERE ANY MORE, THE INK STILL IS. What a menu row IS — the
   grid collapses to a block, the row is one baseline flex line, the name holds that line — was
   written out twice, once against this section key and once against `comp-menu-list` further down,
   and only the second copy ever learned to unwrap on a phone. Measured on a built 425px page: the
   add-on "Anti-Nausea (anti-nausea medication)" rendered 304px of un-wrappable name inside a 326px
   row, so the row ran 67px wider than its own container and shoved its +$30 flush against the
   window edge, and at 390 or 375px it goes further off. Those three declarations now live once, on
   a selector list carrying both shapes, beside the single narrow-viewport unwrap — see the
   `comp-menu-list` block. What stays here is what actually differs: the ink, which this block mixes
   from `--addon-rule` so it follows the room. */
/* The card is deleted, not restyled. What remains is a ruled row. */
:where(.sl-body).bands-paper main > section.section.section-addons_boosters_grid:nth-of-type(n) .addon-card {
  display: block;
  flex: none;
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  padding: 0.95rem 0;
  border-bottom: 1px solid var(--addon-rule, rgba(255, 255, 255, 0.14));
}
:where(.sl-body).bands-paper main > section.section.section-addons_boosters_grid:nth-of-type(n) .addon-card:first-child {
  border-top: 1px solid var(--addon-rule, rgba(255, 255, 255, 0.14));
}
/* No lift: a menu line is printed, not picked up. */
:where(.sl-body).bands-paper main > section.section.section-addons_boosters_grid:nth-of-type(n) .addon-card:hover {
  transform: none;
  box-shadow: none;
  border-color: var(--addon-rule, rgba(255, 255, 255, 0.14));
}
/* name ·············· +$25 — the leader dots ARE the menu, and they cost one pseudo-element. The
   row and the name are declared with `comp-menu-list`, for the reason given above; only the dots
   are written here, because only the dots are ink. */
/* The dots must sit BETWEEN the name and the price, but ::after is last in DOM order — which
   printed "Vitamin B12 +$25 ·········" (price glued to the name, dots trailing into nothing).
   A menu is name ········· price, with the price flush RIGHT: that alignment is the whole point,
   because it lets the eye scan one column of numbers. `order` re-sequences the flex line without
   the renderer emitting a single extra element. */
:where(.sl-body).bands-paper main > section.section.section-addons_boosters_grid:nth-of-type(n) .addon-head::after {
  content: '';
  order: 2;
  flex: 1 1 auto;
  align-self: center;
  border-bottom: 1px dotted var(--addon-rule-strong, rgba(255, 255, 255, 0.3));
  min-width: 1.5rem;
}
/* The pill was the card's way of shouting the price. On a menu line the POSITION says it. */
:where(.sl-body).bands-paper main > section.section.section-addons_boosters_grid:nth-of-type(n) .addon-pill {
  order: 3;
  background: transparent;
  border: 0;
  padding: 0;
  border-radius: 0;
  color: var(--addon-price-ink, var(--c-accent-ink, var(--c-accent))); /* surface-aware, see below */
  font-weight: 700;
  font-variant-numeric: tabular-nums;           /* so the price column scans as a column */
}
:where(.sl-body).bands-paper main > section.section.section-addons_boosters_grid:nth-of-type(n) .addon-desc {
  margin-top: 0.3rem;
  max-width: 46ch;
}
/* "+ ADD TO ANY IV" printed six times under six rows in a section headed "Stack any of these onto
   your IV at booking" is the same sentence three ways. The heading already said it. */
:where(.sl-body).bands-paper main > section.section.section-addons_boosters_grid:nth-of-type(n) .addon-note {
  display: none;
}
/* NAD+'s dose rows: the idiom this section is now built from. Keep them, re-inked for navy. */
/* NO max-width here. The dose rows carry prices too, and capping them at 24rem parked +$99/+$199
   mid-band while every price above ran flush right — two gold columns where the entire argument
   for a menu is ONE column your eye can scan down. Full width, same rail. */
:where(.sl-body).bands-paper main > section.section.section-addons_boosters_grid:nth-of-type(n) .addon-tiers {
  border-top: 0;
  margin-top: 0.45rem;
  padding-top: 0;
}
:where(.sl-body).bands-paper main > section.section.section-addons_boosters_grid:nth-of-type(n) .addon-tier-dots {
  border-bottom-color: var(--addon-rule-strong, rgba(255, 255, 255, 0.22));
}
:where(.sl-body).bands-paper main > section.section.section-addons_boosters_grid:nth-of-type(n) .addon-tier-price {
  color: var(--addon-price-ink, var(--c-accent-ink, var(--c-accent)));
}
/* This block was written for the add-ons menu AS A NAVY ROOM (Top Tier pins it there). A site
   whose add-ons band stays light inherits the same rules on cream, so the price ink has to follow
   the SURFACE, not the section key: the light-on-dark ink only where the room actually is. */
:where(.sl-body).bands-paper main > section.section.section-addons_boosters_grid:nth-of-type(n) {
  --addon-rule: color-mix(in srgb, var(--c-text) 16%, transparent);
  --addon-rule-strong: color-mix(in srgb, var(--c-text) 32%, transparent);
}
:where(.sl-body).bands-paper main > section.section.section-addons_boosters_grid.sec-room:nth-of-type(n) {
  --addon-price-ink: var(--c-accent-ink-dark, var(--c-accent));
  --addon-rule: rgba(255, 255, 255, 0.14);
  --addon-rule-strong: rgba(255, 255, 255, 0.3);
}

/* RUNG 4 — OBJECT. wellness_packages is the largest section and the largest commitment, so it
   earns weight — but it is not the entry product, so it gets an object, not a room. Same navy;
   THE GEOMETRY IS THE ARGUMENT. A second full-bleed 1,200px room would teach the eye the first
   one was not special. `width: min()` guarantees paper rails at EVERY width, including 390px, so
   it can never read as a room on the device this gets reviewed from.
   Layout safety: inner width lands ~1128px and .wpkg-grid caps at --content-max (1120), with
   3 x 320 basis + 2 x 24 gap = 1008 <= 1120. 3-up holds, so R4 (no orphan row) is not at risk. */
:where(.sl-body).bands-paper main > section.section.section-wellness_packages:nth-of-type(n) > .container {
  width: min(var(--container-max, 1200px), calc(100% - 2.5rem));
  padding: clamp(2.25rem, 3.5vw, 3.25rem) clamp(1.25rem, 2.5vw, 2.5rem);
  border-radius: clamp(16px, 1.6vw, 24px);
  background: var(--c-room);
  box-shadow: 0 30px 70px -30px color-mix(in srgb, var(--c-primary) 45%, transparent);
  --c-text: var(--c-on-room);
  --c-text-muted: var(--c-muted-on-room, color-mix(in srgb, var(--c-surface-alt) 72%, var(--c-primary)));
  --eyebrow-ink: var(--c-accent-ink-dark, var(--c-accent));
  --eyebrow-chip: rgba(255, 255, 255, 0.09);
  --eyebrow-chip-edge: rgba(255, 255, 255, 0.18);
}
:where(.sl-body).bands-paper main > section.section.section-wellness_packages:nth-of-type(n) .wpkg-card {
  --c-text: var(--c-primary);
  --c-text-muted: var(--c-muted-on-surface, color-mix(in srgb, var(--c-primary) 74%, var(--c-surface-alt)));
  --c-border: color-mix(in srgb, var(--c-primary) 12%, var(--c-surface-alt));
}

/* The map paints itself with !important (:478) and handles its own text (.coverage-text-col h2
   { color:#fff }, :496). Only its eyebrow needs re-declaring, because the gold-routing rule
   above out-specifies :495. Two navy siblings now sit above it, so it reads as the third room
   rather than a dark widget someone dropped into a sea of cream. */
/* ...WHICH IS TRUE OF THE DARK MAP AND OF NO OTHER. The comment above is right about the classic
   band; it was written when that was the only band this section could be. A brand may now choose
   the light index or panel mode, and then this line hands the label the paper colour on a paper
   ground: 1.11:1, invisible, on nine pages of a live client. The two light modes are excluded the
   same way five design lanes already exclude them a few hundred lines down. */
:where(.sl-body).bands-paper:not(.map-index):not(.map-panel) main > section.section.section-service_area_map:nth-of-type(n) {
  --eyebrow-ink: var(--c-on-dark);
  --eyebrow-chip: rgba(255, 255, 255, 0.14);          /* its own value, from :495 */
  --eyebrow-chip-edge: rgba(255, 255, 255, 0.18);
}

/* THE PHOTOGRAPH (policy_expand). The old rhythm gave this band its own WHITE special-case to
   give the warm photo an edge — but white on beige is 1.23:1, so by this file's own law that
   band bought nothing, and the complaint it was answering ("the whole thing is beige") was
   right. The edge problem is real; it is solved AT THE PHOTO, which is where it lives.
   .pxp-frame fills with --c-surface-alt and borders with --c-border (:2851) — on paper that is a
   beige rectangle inside a beige rectangle with no boundary at all. So give it the page's own
   material: white is a MAT, matting a print on warm board. That is what white is for now.
   Safe: *{box-sizing:border-box} (:1) is global, so aspect-ratio applies to the border box and
   the grid does not reflow. Do NOT use padding — .pxp-img is absolute and inset:0 resolves
   against the padding box. */
:where(.sl-body).bands-paper .pxp-frame {
  border: 8px solid var(--c-surface);
  box-shadow: 0 14px 36px -14px color-mix(in srgb, var(--c-primary) 32%, transparent);
}
:where(.sl-body).bands-paper .pxp-layout.is-expanded .pxp-frame {
  box-shadow: 0 24px 54px -18px color-mix(in srgb, var(--c-primary) 42%, transparent);
}

/* THE BUNDLE CTA. Every element in a .wpkg-card sits on one left axis — icon, name, "for" line,
   checklist — and then the card ends in a full-width navy bar whose label is the only centred
   thing on the card. Measured on a 390px phone: the bar is 260 CSS px of the darkest ink in the
   card, printed 6x down the stack, so the repeated CHROME outshouts the unique copy and the
   1.18rem name (:2827) stops leading. Releasing the stretch shrinks it to ~177px (label 127 +
   48 padding + 2 border), which is ~67% of the 265px card content box: a proportioned button,
   not a slab.
   MECHANISM (the non-obvious part): .wpkg-cta IS the <a class="btn btn-primary wpkg-cta"> — not
   a wrapper around one — and it is a flex ITEM of the column-flex .wpkg-card. So .btn's
   display:inline-block (:43) is BLOCKIFIED and irrelevant here; what makes it full-width is
   purely align-self:stretch (:2835) on the cross axis. flex-start swaps stretch for fit-content
   sizing, which is the whole fix. text-align:center is then a no-op (the box is exactly its
   label wide), so it is left alone rather than re-declared for show.
   margin-top:auto is deliberately NOT touched, so CTAs stay pinned to the card floor and the
   desktop 3-up baseline still lines up. All 6 labels are identical => all 6 shrink to the same
   width, no raggedness. No colour change: the button stays navy, filled, and keeps its per-
   bundle UTM. This is the same call the codebase already made for rows mode at :3116-3120, for
   the same reason; grid mode never got it. Scoped to bands-paper (Top Tier only) — the other 21
   brands keep the stretch.

   FINISHING THE MOVE: un-stretching left a 179x56 FILLED navy slab, still the heaviest, darkest
   mass on the card — the eye lands on three words of boilerplate before it reaches the unique
   bundle name. Six of them stack down a phone. So demote the button to a typographic link.
   THE GLOW IS LEAKAGE, NOT A DECISION: .btn-primary picks up a navy drop shadow at :686
   (`0 12px 30px -10px`), inside the block commented "MATERIAL PASS v2 — BOLD art direction"
   (:624). Top Tier is art-directed ad-typographic-clinical, which restyles .btn-primary in
   exactly two places — .hero (:1536) and .final-cta (:1692) — and BOTH flip it to white-on-navy,
   where a navy glow cannot render. That is why nobody ever saw it: the six navy-on-white
   .wpkg-cta are the ONLY surface on this brand where a BOLD-pass glow actually shows. It also
   inverts the material logic — the small button floats while the .wpkg-card sheet holding it is
   dead flat (border, no shadow, :2824). box-shadow:none drops it.
   Setting `color` here is legal under BANDS DECLARE / COMPONENTS CONSUME: .wpkg-cta is a
   component consuming --c-primary, not a band declaring ink for its children.
   Specificity: this selector is (0,5,3); .btn/.btn-primary/.btn:hover are (0,1,0)-(0,2,0), so
   every declaration below wins outright and NO !important is needed — including on :hover, where
   .btn-primary:hover's background (:56) loses to the transparent set here.
   TAP TARGET: .btn is font-size:1rem with no line-height (:43), so at 0.95rem the label box is
   ~18.6px; 0.8rem of vertical padding puts the box at ~44px. Do NOT drop to 0.7rem — that lands
   at ~41px and this brand is adacc-badge (it makes an accessibility claim on the page).
   The arrow is DECORATIVE, not text: gold on white is 2.42:1, which is fine for a mark and is
   already the exact treatment of the gold checkmarks and gold icon disc on this same white card.
   Booking is untouched — per-bundle UTM/href stays, and the sticky header keeps "Book Online".
   NOT DONE: making the whole card the link. .wpkg-card is an <article> (renderSection.ts:2417);
   retagging it would hit all 21 other brands. */
:where(.sl-body).bands-paper main > section.section.section-wellness_packages:nth-of-type(n) .wpkg-cta {
  align-self: flex-start;
  padding: 0.8rem 0;
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  color: var(--c-primary);
  font-size: 0.95rem;
}
:where(.sl-body).bands-paper main > section.section.section-wellness_packages:nth-of-type(n) .wpkg-cta::after {
  content: ' \2192';
  /* inherit, not --c-accent. This arrow lives INSIDE the CTA, whose own colour is already chosen
     to clear its fill; painting it with the raw accent assumed an accent that contrasts with that
     fill. CHIdrate's accent and primary are near-identical, so the arrow rendered navy on navy at
     1:1. An affordance glyph belongs to its label — inheriting is correct for every brand, not
     just the ones whose palette happens to differ. */
  color: inherit;
}
:where(.sl-body).bands-paper main > section.section.section-wellness_packages:nth-of-type(n) .wpkg-cta:hover {
  transform: none;
  color: var(--c-primary-dark);
}

/* THE BUNDLE NAME. .wpkg-name is 1.18rem = 18.9px (:2827) against a 14.9px checklist and a 15px
   "for" line — the product name, the ONE thing that differs card to card, is only 1.27x the copy
   around it. It gets no weight advantage either: brand.ts:113 emits --ad-heading-weight:500, so
   the var(--ad-heading-weight, 800) fallback at :1431 never applies and the name renders at 500
   Jost against 400 Inter. Nothing else overrides .wpkg-name on this brand (variant-extra.ts:8
   does, at 1.05rem !important, but that variant is not active here — measured 1.18rem live), so
   this is the shared default landing unexamined on the section that most needs the name to lead.
   One full step up the scale. Paired with the CTA demotion above it flips the card's hierarchy:
   name leads, checklist supports, link closes. No colour touched.
   Verified live at 390px: all six names still fit on ONE line (the longest, "Back From the
   Airport", measures 210px in a 265px box), so this costs ~22px total, not a wrap. */
:where(.sl-body).bands-paper main > section.section.section-wellness_packages:nth-of-type(n) .wpkg-name {
  font-size: 1.45rem;
  line-height: 1.18;
}

/* THE CARD'S INK IS INVERTED. Measured live on all six cards: .wpkg-for — the promise, the ONE
   line that differs card to card ("You landed at Dulles or Reagan and the week starts tomorrow")
   — consumes --c-text-muted at 15.04px (#525B6B, 6.85:1), while .wpkg-list li — the ingredients
   — consumes --c-text at 14.88px (#1B2A44, 14.37:1). Same size, 2.1x the ink, and the heavy one
   is the SHARED content: "B-complex" appears verbatim in 4/6 lists (5/6 counting "B-complex and
   B12"), "1L hydration" in 5/6, "Vitamin C" in 4/6; Saturday and Monday share 3 of 4 IDENTICAL
   strings, the 4th differing only "B-complex and B12" vs "B12". So the six cards read as one
   card printed six times BECAUSE their identical content is set at max ink and their unique
   content at min ink. The best copy on the page is currently its faintest text.
   THE FIX IS A TOKEN SWAP, not a new colour: the two selectors trade which token they consume.
   Both are already re-bound on .wpkg-card (:3469) — --c-text is navy, and --c-text-muted is
   color-mix(--c-primary 74%, --c-surface-alt), which resolves to exactly the #525B6B .wpkg-for
   reads today. Consuming the TOKEN rather than hardcoding that hex is the point: a future
   re-bind then carries both selectors. Legal under BANDS DECLARE / COMPONENTS CONSUME — these
   are components taking ink, not a band declaring it for its children (same precedent as
   .wpkg-cta at :3547).
   The gold checkmarks are unaffected: .wpkg-check declares color:var(--c-accent) directly
   (:2831), which beats inheriting from the li.
   14px clears this project's 13px floor for muted text and lands at 6.85:1, well past AA.
   This is how a premium menu sets type: name, evocative line in ink, ingredients small and
   quiet. Today the card is a spec sheet with the sales line as a caption.
   COST, DISCLOSED: the promise wraps at 17px, so each card grows ~24px. Accepted — the standing
   rule is never to chase the metric, and the section's real mass is taken by the head collapse
   below, which more than pays for it. */
:where(.sl-body).bands-paper main > section.section.section-wellness_packages:nth-of-type(n) .wpkg-for {
  font-size: 1.0625rem;
  line-height: 1.5;
  color: var(--c-text);
}
:where(.sl-body).bands-paper main > section.section.section-wellness_packages:nth-of-type(n) .wpkg-list li {
  font-size: 0.875rem;
  color: var(--c-text-muted);
}

/* THE CARD HEAD IS TWO ROWS FOR NO REASON. renderSection.ts:2417 emits <div class="wpkg-ic"> as
   a SIBLING before <h3 class="wpkg-name">, and both are items of the column-flex .wpkg-card, so
   the disc gets a dedicated row: measured on a true iPhone 13, the head burns 89px (25.6 pad +
   44 disc + 16 gap + 29 name) before one word of the bundle's own copy — x6, ~360px of the
   section's 3,078px, and the cards are 83% of the section, so the head is the only real geometry
   lever left. Worse, round 2 bought each bundle a distinct icon and this layout parks that mark
   as far from the name it identifies as a card can, so the disc reads as generic decoration
   rather than as the bundle's mark.
   Lift ONLY the disc out of the flow and indent the name past it. The head becomes one row.
   DO NOT instead convert .wpkg-card to grid/align-content:start: that kills .wpkg-cta's
   margin-top:auto (:2835) and desktop CTAs go ragged (measured 5978/5978/6001 against a clean
   6061 baseline) — the exact floor pin :2833 exists to protect. Keeping the card as column flex
   and taking only the disc out of flow preserves it (verified: desktop 1440 CTA tops land
   6007/6007/6007, still aligned in threes).
   34px, not 44: a 44px disc beside the 23.2px name (:3577) reads clumsy, and at 44 the indent
   (55.2px) wraps "Back From the Airport" at 390px — the device this page gets reviewed from.
   The 641px breakpoint mirrors the component's own 640px padding switch (:2837), so the disc
   tracks the card's padding box exactly rather than drifting at one width.
   Specificity: (0,5,3), this block's established idiom, so no !important is needed anywhere.
   KNOWN AND ACCEPTED: at <=375px (iPhone SE, most Android) the indent takes the longest name to
   two lines. It is geometrically unavoidable — the 360px baseline leaves the name only ~25px of
   slack and ANY inline disc eats more than that. It costs back ~21px of the 54px/card win, there
   is no overlap (the disc aligns to line 1), and a wrapped long name beats printing a stranded
   60px chrome row six times down a phone. */
:where(.sl-body).bands-paper main > section.section.section-wellness_packages:nth-of-type(n) .wpkg-card {
  position: relative;
}
:where(.sl-body).bands-paper main > section.section.section-wellness_packages:nth-of-type(n) .wpkg-ic {
  position: absolute;
  top: 1.6rem;
  left: 1.35rem;
  width: 34px;
  height: 34px;
  margin: 0;
}
:where(.sl-body).bands-paper main > section.section.section-wellness_packages:nth-of-type(n) .wpkg-ic svg {
  width: 19px;
  height: 19px;
}
/* min-height + centring optically hangs the name off the disc rather than off its own cap line. */
:where(.sl-body).bands-paper main > section.section.section-wellness_packages:nth-of-type(n) .wpkg-name {
  margin-left: calc(34px + 0.7rem);
  min-height: 34px;
  display: flex;
  align-items: center;
}
@media (min-width: 641px) {
  :where(.sl-body).bands-paper main > section.section.section-wellness_packages:nth-of-type(n) .wpkg-ic {
    top: 1.9rem;
    left: 1.6rem;
  }
}

/* THE ONE PER-CARD DIFFERENTIATOR IS DRAWN IN THE ONE PAIRING THIS BRAND FORBIDS. .wpkg-ic fills
   with color-mix(--c-accent 12%, --c-surface) = #F8F4EA and strokes its glyph in gold (:2825),
   which measures 2.21:1: at true 1x the refresh/cup/clock/dumbbell/pin/sparkle marks are pale
   watermarks, not icons. Gold is legible on navy (5.94:1) and nowhere else — that is the brief's
   own rule and the reason the eyebrow pill is gold-on-navy. So rebind the GROUND and keep the
   glyph, the stroke and the geometry: gold lands on its one legal surface.
   This matters more than a normal contrast miss. Round 2 spent itself replacing one shared bolt
   with six semantically-matched icons, and at 2.21:1 that purchase is unrealized — the disc is
   the only thing distinguishing the six cards at a glance, and it is invisible.
   THE 1.23:1 LAW DOES NOT REACH HERE. Its carve-out — a small shape with an edge and corners is
   carried by its border — governs DISC vs CARD, which measures 1.1:1 and IS fine: the tan ring
   carries it, do not "fix" it. A 1.75px stroke INSIDE the disc has no edge to be carried by.
   Different object. Verified on pixels rather than on the number: at true 1x the before is a
   smudge and the after is crisp, and it holds downscaled to 50%.
   BACKGROUND ONLY, deliberately. border-color is left alone: at 34px the tan ring is
   pixel-indistinguishable against navy, so re-declaring it would be a change that does nothing.
   Six small navy discs on white cards also echo the navy panel holding them — navy as objects,
   which is the system this page already ships. */
:where(.sl-body).bands-paper main > section.section.section-wellness_packages:nth-of-type(n) .wpkg-ic {
  background: var(--c-primary);
}

/* ══ ONE ICON LANGUAGE — navy disc, gold mark, on every white card ═══════════════════════════
   The bundle discs above became navy+gold; but the other 14 icon discs on the page (.cat-ic in
   the two browse grids, .why-row-ic in the Difference rows) were still the stock treatment:
   a #E4E5E9 disc — a COLD GREY that is not in her palette at all (it is color-mix(navy 12%,
   white), which reads as grey, not navy) — at 1.26:1 on a white card, i.e. a barely-there puck
   with a navy mark. Fine in isolation; but a screen below the crisp navy/gold bundle discs it
   reads as unfinished, and it put a fifth, off-palette value on a four-colour page.
   So every disc that sits on a WHITE CARD now speaks the same language the bundles set: a solid
   navy disc with a gold mark. Geometry is untouched (cat-ic stays a circle, why-row-ic a rounded
   square) — only the MATERIAL changes, which is the whole point: consistency of material, variety
   of shape. gold-on-navy = 5.94:1 (passes). The trust-strip discs are deliberately NOT included:
   they sit on a NAVY band, where a navy disc would vanish, so their white-disc/gold-mark stays. */
:where(.sl-body).bands-paper main > section.section .cat-ic, :where(.sl-body).bands-paper main > section.section .why-row-ic {
  background: var(--c-primary);
  color: var(--c-accent);            /* the mark is currentColor -> gold */
  box-shadow: none;                  /* drop the pale inset ring; navy needs no edge on white */
}

/* (The navy bands are defined once, up in the STRICT ALTERNATION block. drip + why_local are now
   CREAM — they were navy in an earlier round; the strict rhythm reverts them.) */

/* ══ PHOTO BAND — the third surface in the rotation (what_to_expect) ═══════════════════════════
   The strict cream/navy rhythm has one hard parity clash: add-ons must be navy (gold prices die on
   cream) and the map is navy, and they fall on opposite beats, so a THIRD surface between them is
   required to close the alternation without a repeat. A photo band is that third surface (Ian is
   trying it out). "How To Get Your IV" is the natural spot — it already carries lifestyle images.
   The steps' OWN inner photos are HIDDEN (a photo behind photos is clutter); instead one lifestyle
   shot becomes the full-bleed band under a navy scrim, and the three steps read as white text with
   numbered badges over it — a process shown ON a moment, not in three little boxes. */
/* :nth-of-type(n) is the same specificity bump .sec-room carries, and for the same reason: the
   archetype layer paints alternating bands with `main > section.section:nth-of-type(2n):not(...)`,
   which outranks a plain `.sec-photo`. Without the bump the band lost its photo AND its scrim while
   KEEPING the white ink this rule binds — white text on a pale wash, i.e. an invisible section.
   (Latent until a photo band met the bold-modern archetype; CHIdrate is the first.) */
/* ── PHOTO BAND — BASE LAYER (lane-agnostic) ────────────────────────────────────────────────
   Every .sec-photo rule below is scoped to body.bands-paper, so the full-bleed photographic band
   — the single most structural thing in the surface library — only ever painted on sites carrying
   that one class. A section marked as a photo band anywhere else got the class, no image and no
   scrim, and just looked like an ordinary band.
   This gives it to all 25 sites. The bands-paper rules keep their prefix and still out-specify
   this (0,4,x over 0,2,x), so every site that already had photo bands renders unchanged.
   Deliberately the same shape as the composition base layer above: base grants, lane refines. */
/* :nth-of-type(n) is a specificity bump, not a filter — it matches every element. The archetype
   and lane layers paint alternating bands with `main > section.section:nth-of-type(2n)` at (0,4,x),
   which outranks a plain `.sec-photo` at (0,2,2): the band kept its brand tint and took this rule's
   WHITE ink, i.e. white text on blush at 1.46:1 across 90 of MK's pages. The bands-paper rule below
   carries the same bump for the same reason, and its comment says so. */
:where(.sl-body) main > section.section.sec-photo:nth-of-type(n) {
  position: relative;
  /* !important, deliberately. The lane and archetype layers paint alternating bands with selectors
     that chain half a dozen :not() classes -- `body.refine-luxe-noir.sections-alternate main >
     section.section:nth-of-type(even):not(.section-tier_comparison):not(...)...` -- and no
     reasonable selector here outranks them. Losing that race is not cosmetic: this rule binds WHITE
     ink, so a band that keeps the brand tint renders white text on blush at 1.46:1 (90 of MK's
     pages did exactly that). The background and the ink have to move together or not at all. */
  background:
    /* Scrim strength is a var so a band whose photograph IS the point (a closing CTA over a room
       shot) can lift it, while a text-heavy band over a busy image keeps the heavier default. */
    /* Scrim COLOUR follows the brand (--c-scrim-rgb, set in brand.ts from primary_dark and
       guarded so a light primary_dark keeps this cold default). It was hardcoded, so a warm or
       green brand got a blue-black wash over its own warm photography and the band read as a
       colder, different site. Strength is unchanged — that part is contrast-critical. */
    linear-gradient(180deg,
      rgba(var(--c-scrim-rgb, 16,20,28),var(--sec-photo-scrim-top, 0.78)) 0%,
      rgba(var(--c-scrim-rgb, 16,20,28),var(--sec-photo-scrim-mid, 0.70)) 45%,
      rgba(var(--c-scrim-rgb, 16,20,28),var(--sec-photo-scrim-bot, 0.88)) 100%),
    var(--sec-photo-img) center/cover no-repeat,
    var(--c-primary-dark, #16202c) !important;
  --c-text: var(--c-on-dark);
  --c-text-muted: rgba(255, 255, 255, 0.9);
  --eyebrow-ink: var(--c-accent-ink-dark, var(--c-accent));
  /* `color` as well as the token: a bare <p> inherits color from body and would keep the page's
     dark ink over the photograph. (The same trap that made a navy paragraph invisible in a navy
     room — here it is safe to declare, because a photo band has no white cards inside it.) */
  color: var(--c-on-dark);
}
/* Content sits directly on the photograph: no card fills, no shadows, nothing clipped. */
/* !important for the same reason the band's own background carries it: the band above binds WHITE
   ink, and a card that keeps its opaque fill under white ink is invisible by construction (Halo's
   spa-luxe lane paints .step-card white at a specificity no selector here reaches — 12 errors at
   1:1). In a photo band a card is never a surface; the photograph is the surface. Transparent is
   not a preference here, it is a correctness condition.
   THE INK IS DECLARED HERE TOO, on the same three classes, because the two halves of one decision
   had been written 465 lines apart and had drifted. The dark-ink rebind up the file listed seven
   classes on the premise that a card in a photo band keeps its own white plate; this rule was
   already taking that plate off three of them, unconditionally, so on every lane except the one
   that had been given a hand-written counter-row those cards got the page's dark ink with nothing
   underneath it. Measured on an MK build wearing refine-luxe-noir, the process_steps band over a
   photograph: step headings at 1.22:1 and body copy at 1.48:1, ten text nodes under the 4.5:1
   floor on a single band. A card whose plate this rule has just removed IS the band, so it takes
   the band's own ink. Ink and plate now live in one block on one class list, which is the only
   thing that stops the next class added to either half from repeating this; the per-lane
   counter-rows that used to carry it (ad-bright-clinical had one, refine-dark-luxe still writes
   its own beside its own stripper) are the shape to stop copying. */
:where(.sl-body) main > section.section.sec-photo:nth-of-type(n) .card, :where(.sl-body) main > section.section.sec-photo:nth-of-type(n) .step-card, :where(.sl-body) main > section.section.sec-photo:nth-of-type(n) .why-row {
  background: transparent !important;
  box-shadow: none !important;
  border: 0 !important;
  overflow: visible;
  --c-text: var(--c-on-dark);
  --c-text-muted: rgba(255, 255, 255, 0.9);
  --c-border: color-mix(in srgb, var(--c-on-dark) 25%, transparent);
  color: var(--c-on-dark);
}
:where(.sl-body) main > section.section.sec-photo:nth-of-type(n) .step-photo img { display: none; }
:where(.sl-body) main > section.section.sec-photo:nth-of-type(n) .step-photo {
  position: static; height: auto; min-height: 0; line-height: normal;
  background: none; box-shadow: none; margin: 0 0 0.9rem;
}
/* Steps read LEFT, like the heading above them. global.css already calls a centred header over a
   hard-left grid an incongruence; the inverse — centred step copy under a left header — is the
   same defect, and it is what the band shipped with once headers moved left. */
:where(.sl-body) main > section.section.sec-photo:nth-of-type(n) .step-card, :where(.sl-body) main > section.section.sec-photo:nth-of-type(n) .steps-row > .card { text-align: left; }

:where(.sl-body).bands-paper main > section.section.sec-photo:nth-of-type(n) {
  position: relative;
  /* the image is DATA now: the renderer sets --sec-photo-img from theme.surfaces.photo_bands[].image,
     so any site drops any section onto any lifestyle shot without editing this stylesheet. */
  background:
    linear-gradient(180deg, rgba(20,28,44,0.80) 0%, rgba(20,28,44,0.72) 45%, rgba(20,28,44,0.88) 100%),
    var(--sec-photo-img) center/cover no-repeat,
    #1B2A44;
  --c-text: var(--c-on-dark);
  /* step BODY copy is the muted token; over the brightest photo regions (a lit face/window) the old
     off-white washed out on mobile. Near-solid white + the stronger scrim above clears it. (PureIV pass) */
  --c-text-muted: rgba(255, 255, 255, 0.9);
  --eyebrow-ink: var(--c-accent-ink-dark, var(--c-accent));
  --eyebrow-chip: rgba(255, 255, 255, 0.10);
  --eyebrow-chip-edge: rgba(255, 255, 255, 0.22);
}
/* The .why-row ink rebind above assumes the row KEEPS its white fill — true for an uncomposed
   room, false the moment a composition treatment strips that fill to sit the copy on the room
   itself. Then the rebound dark ink lands on the dark room: CHIdrate's why_local_grid rendered
   navy on navy at 1:1 the moment the rotation moved. When the section carries a treatment, the
   row is transparent, so it takes the ROOM's ink, not the card's. */
:where(.sl-body).bands-paper main > section.section.sec-room:nth-of-type(n).comp-numbered .why-row, :where(.sl-body).bands-paper main > section.section.sec-room:nth-of-type(n).comp-ledger .why-row, :where(.sl-body).bands-paper main > section.section.sec-room:nth-of-type(n).comp-quiet-prose .why-row, :where(.sl-body).bands-paper main > section.section.sec-room:nth-of-type(n).comp-split .why-row, :where(.sl-body).bands-paper main > section.section.sec-room:nth-of-type(n).comp-wall .why-row {
  --c-text: var(--c-on-room);
  --c-text-muted: rgba(255, 255, 255, 0.9);
}

/* An .img-text body inside a dark room sits DIRECTLY on the room — no card, no fill of its own —
   so it must take the room's ink. It did not, because `color` is declared once on body as
   `color: var(--c-text)` and rebinding the token further down does not re-run that declaration;
   a bare <p> kept inheriting the page's dark ink and rendered navy on navy at 1:1. Declaring color
   on the ROOM fixes this but cascades white into every white chip in it (tried: 4 errors becomes
   23). Scoping it to .itr-body is the per-component fix that earlier note asked for: this element
   is never a white card, so there is nothing for the white ink to break. */
/* …AND THE TOKEN IT READS HAS TO BE THE ROOM'S. This set `color: var(--c-text)` and relied on
   `--c-text` having been rebound to the surface ink further up — which happens only for the five
   `comp-*` treatments listed above. A room with no treatment on it therefore got the PAGE's ink
   through a rule written to prevent exactly that, and rendered ink on ink at 1:1. Found on five
   listing pages at once the day lane-gate first built a lane on a design it had not been authored
   for. The rebind is made here, on the same element the note above already argues is safe for it:
   `.itr-body` is never a white card, so there is nothing for the light ink to break. */
:where(.sl-body) main > section.section.sec-room .img-text .itr-body, :where(.sl-body) main > section.section.sec-photo .img-text .itr-body {
  --c-text: var(--c-on-dark);
  --c-text-muted: rgba(255, 255, 255, 0.9);
}
:where(.sl-body) main > section.section.sec-room .img-text .itr-body, :where(.sl-body) main > section.section.sec-room .img-text .itr-body p, :where(.sl-body) main > section.section.sec-photo .img-text .itr-body, :where(.sl-body) main > section.section.sec-photo .img-text .itr-body p { color: var(--c-text); }

/* the section's own step photos are hidden; the badge stays, re-styled as a gold-ringed disc */
:where(.sl-body).bands-paper main > section.section.sec-photo .step-photo img { display: none; }
/* the .step-photo wrapper is now just the badge's home; make it STATIC so the badge flows above the
   title instead of hanging absolutely off a hidden image (that + .step-card overflow:hidden clipped
   the badges to a sliver — Ian caught it on desktop). */
:where(.sl-body).bands-paper main > section.section.sec-photo .step-photo {
  position: static; height: auto; min-height: 0; line-height: normal;
  background: none; box-shadow: none; margin: 0 0 0.9rem;
}
/* the step cards become transparent — content sits directly on the photo; overflow VISIBLE so the
   badge is never clipped, and the card's own left padding restored (the .steps-photo default is 0). */
:where(.sl-body).bands-paper main > section.section.sec-photo .step-card {
  background: transparent; box-shadow: none; border: 0; overflow: visible;
  /* declare the variable, not just the shorthand: .step-n is absolutely positioned from the card's
     top edge and reads --step-pad-top. Setting only the padding left the numeral where a 2rem card
     would have put it, i.e. on top of the heading. */
  --step-pad-top: 0.5rem;
  padding: var(--step-pad-top) 1.25rem 1.4rem !important;
}
/* badge flows normally now: a gold-ringed navy disc with a gold number, left-aligned above the step */
:where(.sl-body).bands-paper main > section.section.sec-photo .step-badge {
  position: static; bottom: auto; left: auto; margin: 0 0 0.9rem;
  width: 46px; height: 46px; font-size: 1.15rem;
  /* the numeral is small text on a navy disc, so it takes the dark-room accent ink, not the raw
     accent (raw accent on primary measured 2.61:1). The ring keeps the raw accent: it is a rule,
     not text, so the contrast floor does not apply to it. */
  background: var(--c-primary); color: var(--c-accent-ink-dark, var(--c-accent));
  border: 1.5px solid color-mix(in srgb, var(--c-accent) 55%, transparent);
  box-shadow: 0 8px 20px -6px rgba(0,0,0,0.5);
}
:where(.sl-body).bands-paper main > section.section.sec-photo .step-card h3 { margin: 0 0 0.4rem; }
:where(.sl-body).bands-paper main > section.section.sec-photo .step-card p { margin: 0; }
/* the connector rail between steps, tinted for the dark photo */
:where(.sl-body).bands-paper main > section.section.sec-photo .steps-connected::before {
  background: rgba(255, 255, 255, 0.22);
}
/* ONE RAIL: THE HEADING, THE CARDS AND THE ROAD ALL SPAN IT.
   Measured at 1440/1920/2560, the three disagreed. The heading sat on the container's grid line;
   the card row was inset 20px and then centred, leaving the first card 40px further in again; and
   the road was a 620px graphic centred inside a 1080px rail, so it began and ended over nothing —
   a dotted line and a car floating between the title and the cards, which is what Ian kept seeing.
   The row now starts on the line and fills the container, the cards share that width evenly, and
   the road spans exactly the same rail so the car sets off above the first card and arrives at
   the pin above the last. */
/* The cards fill the rail evenly so the three boxes are equal and the row has no dead slack at
   its right end. The row itself stays CENTRED — the band's content is a centred grid like every
   other card band on the page, and the header above now centres with it. */
:where(.sl-body).bands-paper main > section.section.sec-photo .steps-row > .step-card { flex: 1 1 0; }
/* The road spans the same rail as the cards — same max-width, same centring — so the car sets off
   above the first card and the pin lands above the last, instead of being a 620px graphic adrift
   in the middle of a wider row. Both positions: a road under the cards floats just as badly. */
:where(.sl-body).bands-paper main > section.section.sec-photo .steps-route {
  max-width: var(--steps-rail, 1120px); margin-left: auto; margin-right: auto;
}
/* ROOM FOR THE RING. The medallion carries a dotted ring drawn at `inset: -10px`, i.e. 10px
   OUTSIDE the disc, and the card's top padding was 8px — so the ring crossed the card's own
   border and came out visibly clipped. Measured: card top 5695, medallion top 5704, gap 9px
   against a 10px ring. The padding is now bigger than the ring it has to clear. */
:where(.sl-body).bands-paper main > section.section.sec-photo .step-card { --step-pad-top: 1.5rem; }

/* ══ HERO — taller video + the trust row OVERLAID on it (Ian, desktop) ═════════════════════════
   The video was capped at 660px and read as trimmed; give it real vertical room. And the trust
   strip is no longer its own navy band — it sits OVER the bottom of the video (transparent), so the
   licensure badges live on the footage instead of in a separate dark bar under it. */
/* TALLER so the video reads full (it is object-fit:cover, so height = how much shows) and so the
   centered content sits well ABOVE the bottom, leaving real space between the CTAs and the trust
   row. Ian: the gap was 9px. */
/* the diagonal legibility scrim + a GENTLE bottom darkening (a soft gradient, deliberately not a
   hard band) so the trust labels read on the footage without a visible bar behind them. */
:where(.sl-body).bands-paper .hero-video::after {
  background:
    linear-gradient(135deg, rgba(0,0,0,0.66), rgba(0,0,0,0.32) 55%),
    linear-gradient(to bottom, transparent 62%, rgba(10,15,26,0.62) 100%);
}
/* push the centered content UP a little so the bottom of the film breathes under the CTAs */
:where(.sl-body).bands-paper .hero-video .hero-inner { margin-bottom: 3.5rem; }
/* The overlaid trust strip (pulled up ~120px, below) was authored against the TALLER video hero.
   On an image-bg hero the same pull landed the badge row ON TOP of the hero CTA buttons, so the
   photo hero reserves that strip of itself: the extra bottom padding both lifts the centered
   hero content clear and leaves a clean band of photograph for the badges to sit on. Mobile keeps
   the solid bar under the hero (see the 768px rule), so the reservation is desktop-only. */
@media (min-width: 769px) {
  :where(.sl-body).bands-paper .hero-image-bg { padding-bottom: calc(4rem + 130px); }
}
/* trust strip: transparent, pulled up over the video's lower edge. Negative margin overlaps it onto
   the hero (siblings, so the hero's overflow:hidden does not clip it); z-index lifts it above the
   scrim. Its own icon discs (rgba white) + gold marks + white labels already read on dark footage. */
:where(.sl-body).bands-paper main > section.section.section-trust_strip {
  background: transparent;
  margin-top: -118px;
  padding-top: 0.5rem;
  position: relative;
  z-index: 3;
  --c-border: transparent;
}
/* the divider ticks between trust items, tuned for footage rather than a flat navy band */
:where(.sl-body).bands-paper .section-trust_strip .trust-row-item + .trust-row-item::before {
  background: rgba(255, 255, 255, 0.22);
}

/* ══════════════════════════════════════════════════════════════════════════════════════════════
   SURFACE TREATMENTS — the reusable "background material" library
   theme.surfaces.dark = 'glow'  · theme.surfaces.light = 'texture' | 'sunlit' | 'texture-sunlit'
   Each is an independent, opt-in, alternatable modifier. Flat fills read cheap; these add DEPTH
   (a light source, a material grain) WITHOUT a cheap gradient, all inside the brand's four colours.

   MECHANISM, and why it is a ::before overlay and not a background-image on the band:
   visual-lint's bgOf() bails to null the moment a text node's ancestor carries a background-image
   (scripts/visual-lint.mjs:113), because an image makes the painted colour unknowable. Painting the
   treatment straight onto the section would therefore SILENTLY SWITCH OFF the contrast guardrail for
   every band it touches — the exact way a gate dies. So the section keeps its opaque background
   COLOUR (bgOf still resolves it, R15 stays live) and the treatment rides on a separate ::before
   layer that is NOT in any text node's ancestor chain. Depth added, guardrail intact. ═════════ */

/* the overlay sits between the band's colour and its content */
:where(.sl-body).dark-glow main > section.section, :where(.sl-body).paper-texture main > section.section, :where(.sl-body).paper-sunlit main > section.section { position: relative; }
:where(.sl-body).dark-glow main > section.section > .container, :where(.sl-body).paper-texture main > section.section > .container, :where(.sl-body).paper-sunlit main > section.section > .container { position: relative; z-index: 1; }

/* ── dark-glow: a light source in every navy band ─────────────────────────────────────────────
   A warm gold wash from the top-left, so white cards read as lit objects in a case. Under STRICT
   ALTERNATION no two navy bands are adjacent, so each is isolated (cream on both sides) and simply
   glows; the wash is a SINGLE top-left radial fading to PLAIN NAVY at every edge (no bottom
   "deepening" radial — that once darkened a bottom edge below plain navy and reseamed a navy pair).
   Plain-navy edges meeting cream = a clean colour change, never a seam. */
:where(.sl-body).bands-paper.dark-glow main > section.section.sec-room::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(115% 105% at 12% 2%, color-mix(in srgb, var(--c-accent) 20%, transparent), transparent 50%);
}

/* ── paper-texture: a fine grain, like premium matte cardstock. Noise is the OPPOSITE of a
   gradient, so it carries zero banding risk on low-chroma beige. Excludes the always-navy sections
   so grain never lands on ink (the navy rooms get the glow above instead).
   Grain rides ::after (the topmost overlay) so it sits OVER the sunlit wash below it, never the
   reverse — a texture is the last material layer, light falls under it. ──────────────────────── */
:where(.sl-body).bands-paper.paper-texture:not(.ground-dark) main > section.section:not(.sec-room):not(.sec-photo):not(.comp-trust-band):not(.block-route-section):not(.section-trust_strip):not(.section-service_area_map)::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0.45;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='170' height='170'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size: 170px 170px;
  mix-blend-mode: multiply;
}

/* ── paper-alt: alternate the paper bands with a distinct warm STONE ───────────────────────────
   THE FIX for "two back-to-back beige sections look like a weird split." Root cause was the sunlit
   wash restarting a top-light at every section (dim bottom of A meets bright top of B = a seam);
   with 'alt' the neighbouring bands are DIFFERENT TONES, so each boundary is an intentional step,
   not an accidental seam. This is the alternation the original white/beige checkerboard could never
   be: #FFF vs #EFE7D9 is 1.23:1 (invisible), but a real warm stone is a second paper stock the eye
   actually resolves. The stone is navy+a touch of gold mixed into the beige, kept WARM (a cool grey
   greige would read as dirty, not designed). It is a token so a site can retune it in one place.
   nth-of-type(even) paints the stone; the four always-navy sections are excluded so the room/glow
   rules are never overridden (only addons is an even navy section, but exclude all four for safety
   and to future-proof against re-ordering). Specificity (0,8,3) via the four :not() clears every
   base rule without an !important. Texture (::after) and content (z-index:1) ride on top unchanged. */
:where(.sl-body).bands-paper.paper-alt {
  --c-paper-alt: color-mix(in srgb, color-mix(in srgb, var(--c-primary) 72%, var(--c-accent)) 17%, var(--c-surface-alt));
}
:where(.sl-body).bands-paper.paper-alt main > section.section:nth-of-type(even):not(.sec-room):not(.sec-photo):not(.comp-trust-band):not(.block-route-section):not(.section-trust_strip):not(.section-service_area_map):not(.section-tier_comparison) {
  background: var(--c-paper-alt);
}
/* A card must never match its band (the rule that has held all along). On a stone band the white
   card lifts fine; but the stone-tinted icon discs / any element that read --c-surface-alt would
   now match the stone. Cards stay white (they set their own surface), so nothing to do here — the
   stone only ever sits BEHIND white cards, which keep their edge. Kept as a note, not a rule. */

/* ── paper-sunlit: a warm top-light. Combine with texture for the richest paper. A radial wash
   tinted with a whisper of her gold, so it reads as sunlight on warm stock, not a grey gradient.
   Rides ::before so it sits UNDER any grain. NOTE: on its own it seams a run of same-tone bands
   (see paper-alt above); pair it with 'alt' or use on isolated bands only. ────────────────────── */
:where(.sl-body).bands-paper.paper-sunlit:not(.ground-dark) main > section.section:not(.sec-room):not(.sec-photo):not(.comp-trust-band):not(.block-route-section):not(.section-trust_strip):not(.section-service_area_map)::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: radial-gradient(140% 92% at 50% -10%, color-mix(in srgb, var(--c-accent) 10%, #FFFFFF), transparent 58%);
}

/* ══ Trust strip vs LIGHT heroes ═══════════════════════════════════════════════════════════
   The overlay treatment above (negative pull-up + white ink + text shadows) exists for dark
   full-bleed media heroes (video / image-bg), where the badges sit on footage. Any LIGHT hero
   mode (minimal-left, lead-form, split-*, gradient, aurora) has no footage to land on: the
   strip climbed onto the hero's CTA row with white-on-light labels (Ian, round 1 review).
   Higher specificity (3 body classes) beats both overlay blocks at any source position. */
:where(.sl-body).bands-paper.heromode-minimal-left main > section.section.section-trust_strip:nth-of-type(n), :where(.sl-body).bands-paper.heromode-lead-form main > section.section.section-trust_strip:nth-of-type(n), :where(.sl-body).bands-paper.heromode-split-diagonal main > section.section.section-trust_strip:nth-of-type(n), :where(.sl-body).bands-paper.heromode-split-image-text main > section.section.section-trust_strip:nth-of-type(n), :where(.sl-body).bands-paper.heromode-gradient main > section.section.section-trust_strip:nth-of-type(n), :where(.sl-body).bands-paper.heromode-aurora-spotlight main > section.section.section-trust_strip:nth-of-type(n) {
  margin-top: 0;
  background: var(--c-surface-alt);
  --c-text: inherit;
  --c-border: inherit;
}
:where(.sl-body).bands-paper.heromode-minimal-left main > section.section.section-trust_strip:nth-of-type(n) .trust-row-item span, :where(.sl-body).bands-paper.heromode-lead-form main > section.section.section-trust_strip:nth-of-type(n) .trust-row-item span, :where(.sl-body).bands-paper.heromode-split-diagonal main > section.section.section-trust_strip:nth-of-type(n) .trust-row-item span, :where(.sl-body).bands-paper.heromode-split-image-text main > section.section.section-trust_strip:nth-of-type(n) .trust-row-item span, :where(.sl-body).bands-paper.heromode-gradient main > section.section.section-trust_strip:nth-of-type(n) .trust-row-item span, :where(.sl-body).bands-paper.heromode-aurora-spotlight main > section.section.section-trust_strip:nth-of-type(n) .trust-row-item span {
  text-shadow: none;
  color: var(--c-text);
}
:where(.sl-body).bands-paper.heromode-minimal-left main > section.section.section-trust_strip:nth-of-type(n) .trust-ic, :where(.sl-body).bands-paper.heromode-lead-form main > section.section.section-trust_strip:nth-of-type(n) .trust-ic, :where(.sl-body).bands-paper.heromode-split-diagonal main > section.section.section-trust_strip:nth-of-type(n) .trust-ic, :where(.sl-body).bands-paper.heromode-split-image-text main > section.section.section-trust_strip:nth-of-type(n) .trust-ic, :where(.sl-body).bands-paper.heromode-gradient main > section.section.section-trust_strip:nth-of-type(n) .trust-ic, :where(.sl-body).bands-paper.heromode-aurora-spotlight main > section.section.section-trust_strip:nth-of-type(n) .trust-ic {
  box-shadow: none;
}

/* Coverage 'index' WITH a compact supporting map (Ian: a service business should not lose the
   map; it is trust, not decoration). When the section resolves a map, the ledger and a small
   token-inked map sit side by side; no map data degrades to the pure ledger. */
:where(.sl-body) .coverage-index.has-map { display: grid; grid-template-columns: 1.15fr 0.85fr; gap: 1.5rem 3.5rem; align-items: center; }
:where(.sl-body) .coverage-index.has-map > * { grid-column: 1; }
:where(.sl-body) .coverage-index.has-map .coverage-index-map { grid-column: 2; grid-row: 1 / span 6; align-self: center; }
:where(.sl-body) .coverage-index-map .cm-svg { width: 100%; height: auto; display: block; }
:where(.sl-body) .coverage-index-map .cm-state { fill: color-mix(in srgb, var(--c-text) 7%, transparent); stroke: color-mix(in srgb, var(--c-text) 16%, transparent); stroke-width: 1; }
:where(.sl-body) .coverage-index-map .cm-state-on { fill: var(--c-accent); stroke: color-mix(in srgb, var(--c-accent) 55%, #000); stroke-width: 1; }
/* The AREA PHOTOGRAPH takes the same column the map held. A metro brand has no national map
   worth drawing, but it does have a place worth showing, and without it this band is a list of
   words on empty stock. Stretches the full row so it reads as a plate, not a thumbnail. */
:where(.sl-body) .coverage-index-photo { margin: 0; position: relative; }
/* 4/5 plate, matching .pxp-frame — NOT stretched to the ledger's height. Stretching made it
   940px tall against a 1200x1172 source, and since cover scales to the taller side that showed
   the frame's full height: the arch filled with ~235px of empty sky. A fixed plate keeps the
   subject's share of the frame constant however long the town list gets. */
:where(.sl-body) .coverage-index-photo img {
  display: block; width: 100%; height: auto; aspect-ratio: 4 / 5;
  /* the plate's own bias, kept as the FALLBACK so the picture's answer (lib/photoFocus) wins when
     the library knows one. A town photo says nothing and lands at 65% exactly as before. */
  object-fit: cover; object-position: 50% var(--sl-focus-y, 65%);
  border-radius: var(--card-radius, 12px);
}
:where(.sl-body) .coverage-index.has-map .coverage-index-photo { grid-column: 2; grid-row: 1 / span 6; align-self: center; }
@media (max-width: 860px) { :where(.sl-body) .coverage-index.has-map { display: block; } :where(.sl-body) .coverage-index-map { max-width: 440px; margin: 1.25rem auto 0; } }
@media (max-width: 860px) {
  :where(.sl-body) .coverage-index-photo { max-width: 440px; margin: 1.75rem auto 0; }
  :where(.sl-body) .coverage-index-photo img { min-height: 0; aspect-ratio: 4 / 5; }
}

/* tier_comparison is an inherently DARK component (its white ink is baked in at the component
   rules near :2422). Every band-rhythm stock repaint (alternate even-bands, tinted, paper)
   outguns the component's low-specificity paint and leaves white text on a light band; the
   round-1 fix only covered bands-paper. State the dark plate at rhythm specificity, at end of
   file so equal-specificity ties resolve to the component. */
:where(.sl-body) main > section.section.section-tier_comparison:nth-of-type(n) { background: var(--c-hero-plate); }

/* ══ Round-2 SIGNATURE components ═══════════════════════════════════════════════════════════ */

/* standards_ledger (Ember): editorial numbered manifesto. Oversized serif numerals, one claim
   per ruled row. Inherits the brand's heading font, so it only sings on serif brands. */
:where(.sl-body) .stdl-list { list-style: none; margin: 0 auto; padding: 0; }
:where(.sl-body) .stdl-row { display: grid; grid-template-columns: minmax(72px, 110px) minmax(0, 1fr); gap: 1rem 2.25rem; align-items: start; padding: 1.9rem 0.25rem; border-bottom: 1px solid var(--c-border); }
:where(.sl-body) .stdl-row:first-child { border-top: 1px solid var(--c-border); }
:where(.sl-body) .stdl-num { font-family: var(--font-heading); font-weight: var(--heading-weight, 700); font-size: clamp(2.4rem, 5vw, 3.6rem); line-height: 0.9; color: var(--c-accent); font-variant-numeric: tabular-nums; }
:where(.sl-body) .stdl-copy h3 { margin: 0 0 0.45rem; font-size: 1.35rem; }
:where(.sl-body) .stdl-copy p { margin: 0; max-width: 58ch; line-height: 1.65; }
@media (max-width: 640px) { :where(.sl-body) .stdl-row { grid-template-columns: 56px minmax(0, 1fr); gap: 0.75rem 1.1rem; padding: 1.4rem 0; } :where(.sl-body) .stdl-num { font-size: 2rem; } }

/* visit_timeline (Halo): concierge itinerary. Hairline rail, accent dots, serif time markers. */
:where(.sl-body) .vtl { margin: 0 auto; position: relative; }
:where(.sl-body) .vtl-item { display: grid; grid-template-columns: minmax(120px, 150px) minmax(0, 1fr); gap: 0.5rem 2rem; position: relative; padding: 0 0 2.2rem; }
:where(.sl-body) .vtl-item:last-child { padding-bottom: 0; }
:where(.sl-body) .vtl-marker { text-align: right; position: relative; }
:where(.sl-body) .vtl-time { display: block; font-family: var(--font-heading); font-size: 1.02rem; color: var(--c-accent); letter-spacing: 0.02em; padding-right: 1.6rem; }
:where(.sl-body) .vtl-dot { position: absolute; right: -5px; top: 0.42em; width: 11px; height: 11px; border-radius: 50%; background: var(--c-accent); box-shadow: 0 0 0 4px color-mix(in srgb, var(--c-accent) 18%, transparent); }
/* the rail: a hairline dropping from each dot to the next (skipped after the last stop) */
:where(.sl-body) .vtl-item:not(:last-child) .vtl-marker::after { content: ''; position: absolute; right: 0; top: 1.5em; height: calc(100% + 1.6rem); width: 1px; background: var(--c-border); }
:where(.sl-body) .vtl-copy h3 { margin: 0 0 0.4rem; font-size: 1.3rem; }
:where(.sl-body) .vtl-copy p { margin: 0; line-height: 1.65; }
@media (max-width: 640px) {
  :where(.sl-body) .vtl-item { grid-template-columns: minmax(0, 1fr); gap: 0.3rem; padding-left: 1.4rem; }
  :where(.sl-body) .vtl-marker { text-align: left; }
  :where(.sl-body) .vtl-time { padding-right: 0; }
  :where(.sl-body) .vtl-dot { right: auto; left: -1.4rem; }
  :where(.sl-body) .vtl-item:not(:last-child) .vtl-marker::after { display: none; }
}

/* bag_builder (Voltage): build-your-drip configurator. Real inputs; chips + summary card. */
:where(.sl-body) .bb { display: grid; grid-template-columns: 1.05fr minmax(0, 1fr) 0.85fr; gap: 1.75rem; max-width: var(--content-max); margin: 0 auto; align-items: start; }
:where(.sl-body) .bb-col-label { font-weight: 700; font-size: 0.85rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--c-text-muted); margin-bottom: 0.9rem; }
:where(.sl-body) .bb-base { display: block; cursor: pointer; margin-bottom: 0.8rem; }
:where(.sl-body) .bb-base input, :where(.sl-body) .bb-boost input { position: absolute; opacity: 0; pointer-events: none; }
:where(.sl-body) .bb-base-card { display: block; padding: 1rem 1.1rem; background: var(--c-surface); border: 1.5px solid var(--c-border); border-radius: var(--card-radius); transition: border-color .15s ease, box-shadow .15s ease; }
:where(.sl-body) .bb-base input:checked + .bb-base-card { border-color: var(--c-primary); box-shadow: 0 0 0 3px color-mix(in srgb, var(--c-primary) 16%, transparent); }
:where(.sl-body) .bb-base input:focus-visible + .bb-base-card { outline: 2px solid var(--c-focus); outline-offset: 2px; }
:where(.sl-body) .bb-base-head { display: flex; justify-content: space-between; align-items: baseline; gap: 0.75rem; font-weight: 700; }
:where(.sl-body) .bb-base-price { color: var(--c-primary); white-space: nowrap; }
:where(.sl-body) .bb-base-desc { display: block; margin-top: 0.35rem; font-size: 0.92rem; line-height: 1.5; }
:where(.sl-body) .bb-boosts { display: flex; flex-wrap: wrap; gap: 0.6rem; }
:where(.sl-body) .bb-boost { cursor: pointer; }
:where(.sl-body) .bb-boost-chip { display: inline-flex; align-items: center; gap: 0.55rem; padding: 0.55rem 0.95rem; border: 1.5px solid var(--c-border); border-radius: 999px; background: var(--c-surface); font-size: 0.95rem; font-weight: 600; transition: border-color .15s ease, background .15s ease; }
:where(.sl-body) .bb-boost-price { color: var(--c-text-muted); font-weight: 700; font-size: 0.88rem; }
:where(.sl-body) .bb-boost input:checked + .bb-boost-chip { border-color: var(--c-primary); background: color-mix(in srgb, var(--c-primary) 9%, var(--c-surface)); }
:where(.sl-body) .bb-boost input:checked + .bb-boost-chip .bb-boost-price { color: var(--c-primary); }
:where(.sl-body) .bb-boost input:focus-visible + .bb-boost-chip { outline: 2px solid var(--c-focus); outline-offset: 2px; }
:where(.sl-body) .bb-summary { background: var(--c-surface); border: 1px solid var(--c-border); border-radius: var(--card-radius); box-shadow: var(--card-shadow); padding: 1.4rem 1.4rem 1.5rem; position: sticky; top: 90px; }
:where(.sl-body) .bb-total { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; padding-bottom: 0.9rem; border-bottom: 1px solid var(--c-border); }
:where(.sl-body) .bb-total-label { font-size: 0.95rem; color: var(--c-text-muted); }
:where(.sl-body) .bb-total-amt { font-family: var(--font-heading); font-weight: var(--heading-weight, 700); font-size: 2rem; color: var(--c-text); }
:where(.sl-body) .bb-picked { list-style: none; margin: 0.9rem 0 1.1rem; padding: 0; font-size: 0.95rem; }
:where(.sl-body) .bb-picked li { padding: 0.28rem 0; color: var(--c-text-muted); }
:where(.sl-body) .bb-picked li:first-child { color: var(--c-text); font-weight: 600; }
:where(.sl-body) .bb-cta { width: 100%; text-align: center; }
:where(.sl-body) .bb-note { margin: 0.8rem 0 0; font-size: 0.85rem; line-height: 1.5; }
@media (max-width: 980px) { :where(.sl-body) .bb { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } :where(.sl-body) .bb-summary { grid-column: 1 / -1; position: static; } }
@media (max-width: 640px) { :where(.sl-body) .bb { grid-template-columns: minmax(0, 1fr); } }

/* ══ REFINE: spa-luxe ═══════════════════════════════════════════════════════════════════════
   Opt-in via theme.refinement='spa-luxe' (currently Halo only). A quiet-luxury layer over the
   editorial-luxe archetype, from the theivspa/myivspa/zenivspa study: a dark espresso anchor,
   big light-weight serif, gold tracked-caps eyebrows, near-sharp hairline geometry. Every rule
   is gated on the flag, so no brand that has not opted in is touched. Appended last so equal-
   specificity rules resolve here. ═══════════════════════════════════════════════════════════ */
/* ══ DESIGN LANE: spa-luxe ══════════════════════════════════════════════════════════════
   Retro-described 2026-08-27. This lane was written before lanes had descriptions and
   therefore could never be ASSIGNED to a client by anything but memory — which is exactly
   how one client was given a lane another client already wore. The tag below is what
   tools/lane-pick.mjs reads; the lane itself is unchanged.
   @lane spa-luxe | soft, light, unhurried; type-led with almost no chrome | suits: spa calm serene restorative gentle wellness quiet soothing
   ══════════════════════════════════════════════════════════════════════════════════════ */
:where(.sl-body).refine-spa-luxe {
  --spa-deep: color-mix(in srgb, var(--c-primary-dark) 74%, #000);    /* warm espresso anchor */
  --spa-line: color-mix(in srgb, var(--c-accent) 34%, transparent);   /* gold hairline */
}

/* 1. Big LIGHT serif headings (Canela move: couture, not bold-generic) */
:where(.sl-body).refine-spa-luxe h1, :where(.sl-body).refine-spa-luxe h2 { font-weight: 400; letter-spacing: -0.01em; }
:where(.sl-body).refine-spa-luxe .hero-inner h1 { font-size: clamp(2.75rem, 5.2vw, 4.6rem); line-height: 1.03; }
:where(.sl-body).refine-spa-luxe .section-header h2 { font-size: clamp(2rem, 3.6vw, 2.85rem); line-height: 1.08; }

/* 2. Gold tracked-caps eyebrows; strip the editorial em-rule flourishes */
/* NO COLOUR HERE. The base rules are ground-aware — `.section-header .eyebrow` reads
   `--c-accent-ink` on paper, and every dark ground rebinds that token to the light
   version — and a lane rule at (0,2,1) outranks them and takes the paper ink back onto
   exactly the grounds that needed it changed. The lane keeps the typography. */
:where(.sl-body).refine-spa-luxe .eyebrow, :where(.sl-body).refine-spa-luxe .hero .eyebrow, :where(.sl-body).refine-spa-luxe .section-header .eyebrow {
  font-family: var(--font-body); font-weight: 600; text-transform: uppercase;
  letter-spacing: 0.2em; font-size: 0.72rem; background: none; padding: 0;
}
:where(.sl-body).refine-spa-luxe .eyebrow::before, :where(.sl-body).refine-spa-luxe .eyebrow::after, :where(.sl-body).refine-spa-luxe .section-header .eyebrow::before, :where(.sl-body).refine-spa-luxe .section-header .eyebrow::after { content: none !important; }

/* 3. Near-sharp hairline geometry: gallery feel, no soft app-shadows */
:where(.sl-body).refine-spa-luxe .card, :where(.sl-body).refine-spa-luxe .feature-card, :where(.sl-body).refine-spa-luxe .pkg-card, :where(.sl-body).refine-spa-luxe .cat-card, :where(.sl-body).refine-spa-luxe .whyus-card, :where(.sl-body).refine-spa-luxe .addon-card, :where(.sl-body).refine-spa-luxe .tier-card:not(.tier-featured), :where(.sl-body).refine-spa-luxe .vtl-item {
  border-radius: 3px; box-shadow: none; border: 1px solid var(--spa-line);
}
:where(.sl-body).refine-spa-luxe .vtl-item { border: none; }  /* the timeline keeps its rail, not a card box */

/* 4. DARK ANCHOR HERO: espresso ground, light serif pitch left, framed cream form right */
:where(.sl-body).refine-spa-luxe .hero-lead-form { background: var(--spa-deep); color: var(--c-bg); }
/* Only the PITCH column goes light; the cream form card keeps its own dark ink (scoping to
   .hero-inner avoids painting the form's fine-print cream-on-white). */
:where(.sl-body).refine-spa-luxe .hero-lead-form .hero-inner, :where(.sl-body).refine-spa-luxe .hero-lead-form .hero-inner h1, :where(.sl-body).refine-spa-luxe .hero-lead-form .hero-inner p, :where(.sl-body).refine-spa-luxe .hero-lead-form .hero-inner .subhead { color: var(--c-bg) !important; }
:where(.sl-body).refine-spa-luxe .hero-lead-form .eyebrow { color: var(--c-accent) !important; }
:where(.sl-body).refine-spa-luxe .lead-form-card { background: var(--c-surface); border: 1px solid var(--spa-line); border-radius: 4px; box-shadow: 0 34px 68px -30px rgba(0,0,0,0.55); }
:where(.sl-body).refine-spa-luxe .lead-form-card .lead-form-title { color: var(--c-text); }
:where(.sl-body).refine-spa-luxe .lead-field input { border-radius: 3px; }

/* 5. A single hairline gold rule under each section eyebrow group reads as couture structure */
:where(.sl-body).refine-spa-luxe .section-header { position: relative; }

/* ============================================================================
   REFINEMENT: dark-luxe  (theme.refinement = 'dark-luxe')
   ----------------------------------------------------------------------------
   Opt-in per brand, scoped entirely under body.refine-dark-luxe, so a brand that
   has not set theme.refinement renders byte-identical. Built for Top Tier from
   client reference boards whose shared vocabulary is: a DARK ground, sparse
   cream inset panels, and a thin GOLD HAIRLINE drawn around images and cards.

   The references also share what they do NOT have: no grain, no texture, no
   gradient. Flat fields of colour only. So this layer adds line, not shading —
   every rule here is a 1px border or an inset ring, never a fill or a blur.
   ============================================================================ */

/* 1. IMAGES CARRY A GOLD HAIRLINE, offset slightly so the rule reads as a frame
      the photo sits inside rather than a border stuck to its edge. */
:where(.sl-body).refine-dark-luxe .itr-media, :where(.sl-body).refine-dark-luxe .step-photo, :where(.sl-body).refine-dark-luxe .pxp-figure {
  position: relative;
}
:where(.sl-body).refine-dark-luxe .itr-media::after, :where(.sl-body).refine-dark-luxe .step-photo::after, :where(.sl-body).refine-dark-luxe .pxp-figure::after {
  content: '';
  position: absolute;
  inset: 10px;
  border: 1px solid color-mix(in srgb, var(--c-accent) 72%, transparent);
  pointer-events: none;
  z-index: 2;
}
/* On a navy room the same rule needs a touch more presence to survive the dark. */
:where(.sl-body).refine-dark-luxe .sec-room .step-photo::after {
  inset: 8px;
  border-color: color-mix(in srgb, var(--c-accent) 88%, transparent);
}

/* 2. CARDS ARE RULED, NOT SHADED. Drop the soft drop-shadow (a blur is the
      opposite of the flat, printed look the references share) and replace it
      with a single hairline. */
:where(.sl-body).refine-dark-luxe .card, :where(.sl-body).refine-dark-luxe .cat-card, :where(.sl-body).refine-dark-luxe .pkg-card, :where(.sl-body).refine-dark-luxe .feature-card, :where(.sl-body).refine-dark-luxe .step-card {
  box-shadow: none !important;
  border: 1px solid color-mix(in srgb, var(--c-primary) 14%, transparent);
}
/* Inside a navy room a white card gets the gold hairline instead of a grey one. */
:where(.sl-body).refine-dark-luxe .sec-room .card, :where(.sl-body).refine-dark-luxe .sec-room .cat-card, :where(.sl-body).refine-dark-luxe .sec-room .pkg-card, :where(.sl-body).refine-dark-luxe .sec-room .feature-card, :where(.sl-body).refine-dark-luxe .sec-room .step-card {
  border: 1px solid color-mix(in srgb, var(--c-accent) 55%, transparent);
}

/* 3. THE CREAM PANELS ARE INSET OBJECTS, not full-bleed bands: a gold rule
      inside the band edge turns each relief panel into a framed plate, which is
      how the reference boards use their light sections. */
:where(.sl-body).refine-dark-luxe main > section.section:not(.sec-room):not(.section-trust_strip):not(.section-service_area_map):not(.section-marquee_band):not(.hero) {
  position: relative;
}
:where(.sl-body).refine-dark-luxe main > section.section:not(.sec-room):not(.section-trust_strip):not(.section-service_area_map):not(.section-marquee_band):not(.hero)::after {
  content: '';
  position: absolute;
  inset: 18px;
  border: 1px solid color-mix(in srgb, var(--c-accent) 42%, transparent);
  pointer-events: none;
  z-index: 0;
}
@media (max-width: 720px) {
  :where(.sl-body).refine-dark-luxe main > section.section:not(.sec-room):not(.section-trust_strip):not(.section-service_area_map):not(.section-marquee_band):not(.hero)::after { inset: 10px; }
  :where(.sl-body).refine-dark-luxe .itr-media::after, :where(.sl-body).refine-dark-luxe .step-photo::after, :where(.sl-body).refine-dark-luxe .pxp-figure::after { inset: 7px; }
}

/* 4. FLAT GROUND, ENFORCED. Any inherited scrim/wash/grain is removed so the
      colour fields stay flat even if a surface treatment is left on.
      `.sec-bg-photo` is exempt for the same reason `.sec-photo` is exempt from the ::after rule
      below: it is not an inherited treatment left on by accident, it is a photograph the site
      ASKED for by name in theme.surfaces.bg_photos. Without the exemption this rule silently ate
      the layer — class and custom properties both present in the markup, nothing painted. */
:where(.sl-body).refine-dark-luxe main > section.section:not(.sec-bg-photo)::before { background: none !important; }
:where(.sl-body).refine-dark-luxe main > section.section:not(.sec-photo)::after { background-image: none; }

/* ---- dark-luxe, pass 2: CARDS IN A ROOM ARE DARK PLATES, NOT WHITE TILES ----
   The reference boards put their card content straight onto the dark ground and
   separate it with a gold hairline. A white tile on navy is the opposite move:
   it reads as a UI component, not as printed matter. So inside a navy room the
   card loses its fill and keeps only the rule.

   Specificity note: the room's own card rule (`body.bands-paper main > section
   .sec-room:nth-of-type(n) .cat-card`, (0,5,3)) rebinds ink back to navy for the
   white tile it assumes. These selectors deliberately carry (0,6,3) so the ink
   follows the plate instead. */
:where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-room:nth-of-type(n) .card:not(:has(.step-ic)), :where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-room:nth-of-type(n) .cat-card, :where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-room:nth-of-type(n) .pkg-card, :where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-room:nth-of-type(n) .feature-card, :where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-room:nth-of-type(n) .step-card:not(:has(.step-ic)) {
  background: transparent !important;
  border: 1px solid color-mix(in srgb, var(--c-accent) 62%, transparent) !important;
  box-shadow: none !important;
  --c-text: var(--c-on-room);
  --c-text-muted: color-mix(in srgb, var(--c-on-room) 76%, var(--c-primary));
  --c-border: color-mix(in srgb, var(--c-accent) 45%, transparent);
  color: var(--c-on-room);
}
/* Headings and body inside those plates follow the plate's ink. */
:where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-room:nth-of-type(n) .card:not(:has(.step-ic)) h3, :where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-room:nth-of-type(n) .cat-card h3, :where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-room:nth-of-type(n) .pkg-card h3, :where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-room:nth-of-type(n) .feature-card h3, :where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-room:nth-of-type(n) .step-card:not(:has(.step-ic)) h3 {
  color: var(--c-on-room);
}
:where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-room:nth-of-type(n) .card:not(:has(.step-ic)) p, :where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-room:nth-of-type(n) .cat-card p, :where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-room:nth-of-type(n) .pkg-card p, :where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-room:nth-of-type(n) .feature-card p, :where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-room:nth-of-type(n) .step-card:not(:has(.step-ic)) p {
  color: color-mix(in srgb, var(--c-surface) 78%, var(--c-primary));
}
/* A solid navy CTA inside a navy plate is a rectangle you cannot see. Outline it. */
:where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-room:nth-of-type(n) .pkg-card .btn-primary, :where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-room:nth-of-type(n) .card .btn-primary {
  background: transparent !important;
  border: 1px solid color-mix(in srgb, var(--c-accent) 70%, transparent) !important;
  color: var(--c-accent) !important;
  box-shadow: none !important;
}
/* The step icons are transparent PNGs now, so the white tile behind them is gone
   and the disc floats on the plate the way the reference's ringed icons do. */
:where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-room:nth-of-type(n) .step-photo::after { border-color: transparent; }
:where(.sl-body).refine-dark-luxe .steps-photo .step-photo img { background: transparent; }

/* ---- FLAT, ENFORCED: no blur anywhere in the composition ---- */
:where(.sl-body).refine-dark-luxe .itr-media img, :where(.sl-body).refine-dark-luxe .pxp-img, :where(.sl-body).refine-dark-luxe .step-photo img { box-shadow: none !important; }

/* ---- The gold rules carry more presence than the first pass allowed ---- */
:where(.sl-body).refine-dark-luxe main > section.section:not(.sec-room):not(.section-trust_strip):not(.section-service_area_map):not(.section-marquee_band):not(.hero)::after {
  border-color: color-mix(in srgb, var(--c-accent) 62%, transparent);
}
:where(.sl-body).refine-dark-luxe .itr-media::after { border-color: color-mix(in srgb, var(--c-accent) 88%, transparent); }

/* why_local_grid renders `.why-row`, not `.card`, so it needs the plate treatment
   spelled out or it keeps a white fill and inherits the room's white ink. */
:where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-room:nth-of-type(n) .why-row {
  background: transparent !important;
  border: 1px solid color-mix(in srgb, var(--c-accent) 62%, transparent) !important;
  box-shadow: none !important;
  --c-text: var(--c-on-room);
  --c-text-muted: color-mix(in srgb, var(--c-on-room) 76%, var(--c-primary));
}
:where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-room:nth-of-type(n) .why-row h3 { color: var(--c-on-room); }
:where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-room:nth-of-type(n) .why-row .why-row-body, :where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-room:nth-of-type(n) .why-row p {
  color: color-mix(in srgb, var(--c-surface) 78%, var(--c-primary));
}

/* .sfb-arrow is hardcoded to --c-primary, which is the plate's own colour once the
   card loses its white fill. Gold is both legible here and the right register:
   the reference boards use gold for exactly these small directional marks. */
:where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-room:nth-of-type(n) .sfb-arrow { color: var(--c-accent); }
:where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-room:nth-of-type(n) .cat-all-arrow { color: var(--c-accent); }

/* The coverage band ships a radial + linear gradient stack (:545, !important). It is the
   last gradient on the page, and the reference boards have none. Flatten it to the deep
   navy so the band still steps tonally away from the rooms without any shading.

   Only for brands that keep the DARK band. The light map compositions (:587) paint their
   own alt surface and set navy ink to match; this rule outspecifies them (0,3,3) vs (0,2,1)
   and both carry !important, so without the guard it repaints the band navy underneath navy
   text — 1.27:1, invisible, which is exactly what the R15 gate caught on Top Tier. */
:where(.sl-body).refine-dark-luxe:not(.map-index):not(.map-panel) main > section.section.section-service_area_map {
  background: var(--c-hero-plate) !important;
}

/* ---- dark-luxe, pass 3: THE ARCH ----------------------------------------
   The single most recognisable shape in the reference boards: photographs
   finished with a半 round top. Applied to the two editorial photos (the
   value-prop plate and the policy photo), never to product or icon art,
   which must stay square to read as objects.

   The gold frame has to carry the same curve or you get a rectangle drawn
   around an arch, so the radius is a variable both share. */
:where(.sl-body).refine-dark-luxe { --arch: 50% 50% 3px 3px / 38% 38% 3px 3px; }

:where(.sl-body).refine-dark-luxe .itr-media img { border-radius: var(--arch) !important; }
:where(.sl-body).refine-dark-luxe .itr-media::after { border-radius: var(--arch); }

/* policy_expand's photo: the wrapper is .pxp-frame (an earlier pass named
   .pxp-figure, which does not exist and never applied). */
:where(.sl-body).refine-dark-luxe .pxp-frame {
  position: relative;
  border: none !important;
  box-shadow: none !important;
  border-radius: var(--arch) !important;
  overflow: hidden;
}
:where(.sl-body).refine-dark-luxe .pxp-img { border-radius: var(--arch); }
:where(.sl-body).refine-dark-luxe .pxp-layout.is-expanded .pxp-frame { box-shadow: none !important; }
/* Its gold frame sits on the .pxp-media wrapper so it is not clipped by the
   photo's own overflow:hidden. */
:where(.sl-body).refine-dark-luxe .pxp-media { position: relative; }
:where(.sl-body).refine-dark-luxe .pxp-media::after {
  content: '';
  position: absolute;
  inset: -10px;
  border: 1px solid color-mix(in srgb, var(--c-accent) 78%, transparent);
  border-radius: var(--arch);
  pointer-events: none;
  z-index: 2;
}
/* The coverage photograph gets the same arch + gold frame as the other two editorial photos.
   The frame lives on the <figure>, which is position:relative and NOT overflow:hidden — the
   img carries the arch itself, so the inset ring is not clipped by the photo's own rounding. */
:where(.sl-body).refine-dark-luxe .coverage-index-photo img { border-radius: var(--arch) !important; }
:where(.sl-body).refine-dark-luxe .coverage-index-photo::after {
  content: '';
  position: absolute;
  inset: -10px;
  border: 1px solid color-mix(in srgb, var(--c-accent) 78%, transparent);
  border-radius: var(--arch);
  pointer-events: none;
  z-index: 2;
}
@media (max-width: 720px) {
  :where(.sl-body).refine-dark-luxe { --arch: 50% 50% 3px 3px / 26% 26% 3px 3px; }
  :where(.sl-body).refine-dark-luxe .pxp-media::after { inset: -6px; }
  :where(.sl-body).refine-dark-luxe .coverage-index-photo::after { inset: -6px; }
}

/* The cream bands are PLATES, so the gold rule sits well inside the band edge
   and the content gets room to breathe inside it. 18px read as a border stuck
   to the section; 30px reads as a framed page. */
:where(.sl-body).refine-dark-luxe main > section.section:not(.sec-room):not(.section-trust_strip):not(.section-service_area_map):not(.section-marquee_band):not(.hero)::after {
  inset: 30px;
}
:where(.sl-body).refine-dark-luxe main > section.section:not(.sec-room):not(.section-trust_strip):not(.section-service_area_map):not(.section-marquee_band):not(.hero) {
  padding-left: 30px;
  padding-right: 30px;
}
@media (max-width: 720px) {
  :where(.sl-body).refine-dark-luxe main > section.section:not(.sec-room):not(.section-trust_strip):not(.section-service_area_map):not(.section-marquee_band):not(.hero)::after { inset: 12px; }
  :where(.sl-body).refine-dark-luxe main > section.section:not(.sec-room):not(.section-trust_strip):not(.section-service_area_map):not(.section-marquee_band):not(.hero) { padding-left: 12px; padding-right: 12px; }
}

/* ---- dark-luxe, pass 4: THE PHOTO BAND IS SCRIMMED FLAT ------------------
   The band ships a three-stop scrim (0.80 / 0.72 / 0.88). Over a photograph
   that reads as a vignette, and this brand's whole premise is flat fields.
   One even value instead, dark enough to hold white type over any part of the
   image. */
:where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) {
  background:
    linear-gradient(rgba(20,28,44,0.70), rgba(20,28,44,0.70)),
    var(--sec-photo-img) center/cover no-repeat,
    var(--c-primary);
}

/* A photo band is a dark ground too, so its cards are plates for the same reason
   the rooms' are - a white tile over a photograph is the least expensive-looking
   thing on the page. Same treatment, keyed to .sec-photo. */
:where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) .card, :where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) .cat-card, :where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) .pkg-card, :where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) .feature-card, :where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) .why-row {
  background: transparent !important;
  border: 1px solid color-mix(in srgb, var(--c-accent) 62%, transparent) !important;
  box-shadow: none !important;
  --c-text: var(--c-on-dark);
  --c-text-muted: rgba(255, 255, 255, 0.9);
  color: var(--c-on-dark);
}
:where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) .cat-card h3, :where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) .card h3, :where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) .cat-card span, :where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) .cat-card div {
  color: var(--c-on-dark);
}
:where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) .sfb-arrow, :where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) .cat-all-arrow { color: var(--c-accent); }

/* group_events builds its ledger from LIGHT objects with baked-in near-white
   fills (.ge-chip, .ge-rung, .ge-avail, and the labelled groups around them).
   The room CSS already rebinds ink for two of them; on a photo band none of
   them are covered, so the band's white ink lands on white chips. Ink follows
   the OBJECT here, not the band. */
:where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) .ge-chip, :where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) .ge-chip *, :where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) .ge-rung, :where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) .ge-rung *, :where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) .ge-avail, :where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) .ge-avail *{
  color: var(--c-primary) !important;
  --c-text: var(--c-primary);
  --c-text-muted: var(--c-muted-on-surface, color-mix(in srgb, var(--c-primary) 74%, #ffffff));
}

/* .ge-panel-label ("Perfect for", "Group rates") sits inside the light panel, so
   it belongs to the object, not the band. Same for the panel itself. */
:where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) .ge-panel, :where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) .ge-panel *, :where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) .ge-panel-label, :where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) .ge-ladder, :where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) .ge-ladder *, :where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) .ge-chips, :where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) .ge-chips * {
  color: var(--c-primary) !important;
  --c-text: var(--c-primary);
  --c-text-muted: var(--c-muted-on-surface, color-mix(in srgb, var(--c-primary) 74%, #ffffff)) !important;
}

/* ── PHOTO-TOPPED FEATURE CARDS (.feature-card--photo) ─────────────────────────
   Emitted only when every item in the band carries its own image, so a brand
   with no item images never sees this. The photo bleeds to the card edges and
   the copy sits under it - the image-led service grid the reference boards use. */
:where(.sl-body) .feature-card--photo { padding-top: 0 !important; overflow: hidden; }
:where(.sl-body) .feature-card > .fc-photo {
  display: block;
  /* the global img{max-width:100%} clamps this calc, which shifts the photo left and
     leaves a gap on the right, so the cap has to be lifted for the bleed to work. */
  width: calc(100% + 3rem);
  max-width: none;
  margin: 0 -1.5rem 1.15rem;
  height: 200px;
  object-fit: cover;
}
@media (max-width: 640px) { :where(.sl-body) .feature-card > .fc-photo { height: 172px; } }
/* dark-luxe: flat, and ruled in gold like every other object on the page. */
:where(.sl-body).refine-dark-luxe .feature-card--photo { border: 1px solid color-mix(in srgb, var(--c-primary) 14%, transparent); }
:where(.sl-body).refine-dark-luxe .feature-card > .fc-photo { border-bottom: 1px solid color-mix(in srgb, var(--c-accent) 62%, transparent); }
:where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-room:nth-of-type(n) .feature-card--photo, :where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) .feature-card--photo {
  border: 1px solid color-mix(in srgb, var(--c-accent) 62%, transparent) !important;
}

/* ---- dark-luxe, pass 5: GOLD BUTTONS, FLAT ------------------------------
   Every card in the reference boards carries a SOLID gold button - it is the
   loudest gold on those pages and the main thing that reads as "expensive".
   An earlier pass outlined the in-card CTAs instead, which is quieter than the
   reference. Gold fill with navy ink measures 7.5:1, so it is also the safe
   choice. `.cta-accent` ships a gold glow shadow; this page has no shadows. */
:where(.sl-body).refine-dark-luxe.cta-accent .btn-primary{
  box-shadow: none !important;
}
:where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-room:nth-of-type(n) .pkg-card .btn-primary, :where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-room:nth-of-type(n) .card .btn-primary, :where(.sl-body).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) .card .btn-primary {
  background: var(--c-accent) !important;
  border: 1px solid var(--c-accent) !important;
  color: var(--c-primary-dark) !important;
  box-shadow: none !important;
}

/* The header CTA is a .btn-primary but the header's own scope forces white ink on
   it. With cta-accent that white now sits on gold (1.75:1). Ink follows the gold
   fill: navy on gold is 7.5:1. Same for the sticky bar's book button. */
:where(.sl-body).refine-dark-luxe.cta-accent .header-book, :where(.sl-body).refine-dark-luxe.cta-accent .site-header .btn-primary, :where(.sl-body).refine-dark-luxe.cta-accent .site-header--dark .btn-primary, :where(.sl-body).refine-dark-luxe.cta-accent .sl-sb-book {
  background: var(--c-accent) !important;
  border-color: var(--c-accent) !important;
  color: var(--c-primary-dark) !important;
  box-shadow: none !important;
}

/* ══ DESIGN LANE: luxe-noir ═══════════════════════════════════════════════════════════════
   First med spa lane (DESIGN-LANES.md, build order #1). Quiet luxury: big LIGHT serif
   display, wide-tracked caps eyebrows, hairline accent rules, restrained radius, and the
   signature axis — FULL-BLEED DARK BANDS (primary_dark) alternating with light. Everything
   derives from the brand's own palette tokens, so any brand's palette works; contrast on
   the dark bands rides --c-accent-ink-dark, which brand.ts guarantees >=4.8:1 against
   primary_dark. Opt-in via theme.refinement='luxe-noir'; every rule is scoped under the
   body class, so all other brands render byte-identical.

   Dark-band set is KEYED, not nth-counted, so the rhythm is deterministic per page type
   and every dark band's interior is a known quantity: trust_strip (extends the dark hero),
   pricing_starting_at + consult_deliverable (mid-page statement bands), final_cta
   (full-bleed close), service_area_map (already dark; flattened here), + the hero itself.
   Contrast math (MK seed palette, computed 2026-07-30):
     surface on primary_dark 15.79:1 · mix(surface 80%, primary_dark) on primary_dark
     10.55:1 · accent-ink-dark on primary_dark 7.76:1 · accent on primary_dark 6.59:1 ·
     primary_dark on accent (buttons) 6.59:1 · accent-ink on white 6.69:1 / on
     surface_alt 5.75:1 · white on primary (buttons) 12.43:1. All >= 4.5.  ══════════════ 
   @lane luxe-noir | quiet luxury, evening palette energy, hairline gold rules | suits: luxury luxe premium elite evening concierge dark opulent exclusive discreet
   */
:where(.sl-body).refine-luxe-noir {
  /* save the light-context inks BEFORE any section rebinds them, so objects inside a
     dark band can restore them without hardcoding a hex (the dark-luxe save/restore trick) */
  --ln-text-save: var(--c-text);
  --ln-muted-save: var(--c-text-muted);
  --ln-dark-muted: color-mix(in srgb, var(--c-on-dark) 80%, var(--c-primary-dark));
  --ln-hairline: color-mix(in srgb, var(--c-accent) 42%, transparent);
  --ln-hairline-strong: color-mix(in srgb, var(--c-accent) 70%, transparent);
  --card-radius: 4px;   /* restrained radius, everywhere the token reaches */
  --btn-radius: 2px;
  /* the final CTA flattens to the same dark as its band -> full-bleed close, no inner card */
  --c-cta-bg: var(--c-primary-dark);
}

/* 1. TYPE — the brand serif at higher contrast: bigger, LIGHTER display. */
:where(.sl-body).refine-luxe-noir h1, :where(.sl-body).refine-luxe-noir h2 { font-weight: 400; letter-spacing: 0; }
:where(.sl-body).refine-luxe-noir .hero-inner h1 { font-size: clamp(2.9rem, 5.6vw, 4.8rem); line-height: 1.05; }
:where(.sl-body).refine-luxe-noir .section-header h2 { font-size: clamp(2.5rem, 4.4vw, 3.6rem); line-height: 1.07; }
:where(.sl-body).refine-luxe-noir .final-cta h2 { font-weight: 400; }
/* pricing_starting_at renders a full SENTENCE as its h2; at display scale that is a wall.
   Statement scale instead — still large text (>=24px at desktop), white on dark 15.79:1. */
:where(.sl-body).refine-luxe-noir .section-pricing_starting_at h2 { font-size: clamp(1.55rem, 2.7vw, 2.2rem); line-height: 1.32; }

/* Wide-tracked caps eyebrows. TYPOGRAPHY ONLY — no color property here, so every existing
   surface-aware eyebrow color rule (light bands: accent-ink; coverage/stats/CTA darks:
   their own inks) keeps winning. !important reaches the inline-styled eyebrows
   (pricing/final_cta emit letter-spacing inline); their color rides --eyebrow-ink. */
:where(.sl-body).refine-luxe-noir .eyebrow {
  font-family: var(--font-body);
  font-weight: 600 !important;
  font-size: 0.76rem !important;
  letter-spacing: 0.22em !important;
  text-transform: uppercase;
}

/* NORTH-STAR: the structure mark moves ABOVE the headline and OFF-CENTER — a short accent
   rule hanging at the left edge, not a centered underline. A centered underline is the single
   strongest "template" tell; this is the first symmetry kill. */
:where(.sl-body).refine-luxe-noir .section-header h2::before {
  content: '';
  display: block;
  width: 56px;
  height: 2px;
  background: var(--c-accent);
  margin: 0 0 1.15rem;
}

/* 2. SHAPE — hairline accent rules instead of app shadows; near-sharp corners. */
:where(.sl-body).refine-luxe-noir .card, :where(.sl-body).refine-luxe-noir .auto-item, :where(.sl-body).refine-luxe-noir .why-row, :where(.sl-body).refine-luxe-noir .cat-card, :where(.sl-body).refine-luxe-noir .prepaft-col, :where(.sl-body).refine-luxe-noir .contact-method, :where(.sl-body).refine-luxe-noir .lead-form-card {
  border-radius: 4px;
  border: 1px solid var(--ln-hairline);
  box-shadow: none;
}
:where(.sl-body).refine-luxe-noir.cards-elevated .card:hover { box-shadow: none; transform: none; border-color: var(--ln-hairline-strong); }
:where(.sl-body).refine-luxe-noir .cat-card:hover, :where(.sl-body).refine-luxe-noir .contact-method:hover { transform: none; box-shadow: none; border-color: var(--ln-hairline-strong); }
/* The bag/art plate in the services carousel reads as a framed object, not a tinted blob. */
:where(.sl-body).refine-luxe-noir .pkg-bag-fallback { border: 1px solid var(--ln-hairline); border-radius: 4px; }
/* Framed imagery, wherever the fan-out drops a photo (image+text bands, step photos). */
:where(.sl-body).refine-luxe-noir .itr-media { position: relative; }
:where(.sl-body).refine-luxe-noir .itr-media::after {
  content: '';
  position: absolute;
  inset: 10px;
  border: 1px solid var(--ln-hairline-strong);
  pointer-events: none;
  z-index: 2;
}
:where(.sl-body).refine-luxe-noir .itr-media img { box-shadow: none; border-radius: 4px; }
@media (max-width: 720px) { :where(.sl-body).refine-luxe-noir .itr-media::after { inset: 7px; } }
:where(.sl-body).refine-luxe-noir .faq-item .faq-chevron { color: var(--c-accent-ink); }

/* 3. BUTTONS — slim, letter-spaced, near-sharp. Label pairs measured: white on primary
   12.43:1; accent fill with primary_dark ink 6.59:1 (the final CTA emits that inline). */
:where(.sl-body).refine-luxe-noir .btn {
  border-radius: 2px;
  padding: 0.78rem 1.7rem;
  font-size: 0.83rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  box-shadow: none;
}
:where(.sl-body).refine-luxe-noir .hero .btn { padding: 0.92rem 2rem; font-size: 0.86rem; }

/* 4. BAND ARCHITECTURE — the signature axis. Light bands flatten to a single quiet
   surface_alt stock (the default even/4n gradient washes are the opposite of unhurried).
   The :not() chain keeps this off the keyed dark bands below and off sections that are
   dark by construction. Contrast on surface_alt: text 11.99:1, muted 5.24:1, accent-ink
   5.75:1 — all measured, all >= 4.5. */
/* BOTH BEATS, NOT ONE. This lane declared the even band and left the odd one to fall through to
   the page default — so a brand whose default ground IS a tint alternates tint with tint, and the
   page-rules P3 check refuses the build. Five listing pages at once, and the fault has been paid
   for twice in this file already. The odd beat and the bands-paper rhythm are both named here. */
:where(.sl-body).refine-luxe-noir.sections-alternate main > section.section:nth-of-type(odd):not(.section-tier_comparison):not(.section-ingredient_choice):not(.section-trust_strip):not(.section-pricing_starting_at):not(.section-consult_deliverable):not(.section-final_cta):not(.section-hub-cta):not(.final-cta):not(.section-service_area_map):not(.section-stats):not(.section-skin_type_suitability):not(.sec-room):not(.sec-photo), :where(.sl-body).refine-luxe-noir.bands-paper main > section.section:nth-of-type(odd):not(.section-tier_comparison):not(.section-ingredient_choice):not(.section-trust_strip):not(.section-pricing_starting_at):not(.section-consult_deliverable):not(.section-final_cta):not(.section-hub-cta):not(.final-cta):not(.section-service_area_map):not(.section-stats):not(.section-skin_type_suitability):not(.sec-room):not(.sec-photo) {
  background: var(--c-surface);
}
:where(.sl-body).refine-luxe-noir.sections-alternate main > section.section:nth-of-type(even):not(.section-tier_comparison):not(.section-ingredient_choice):not(.section-trust_strip):not(.section-pricing_starting_at):not(.section-consult_deliverable):not(.section-final_cta):not(.section-hub-cta):not(.final-cta):not(.section-service_area_map):not(.section-stats):not(.section-skin_type_suitability), :where(.sl-body).refine-luxe-noir.bands-paper main > section.section:nth-of-type(even):not(.section-tier_comparison):not(.section-ingredient_choice):not(.section-trust_strip):not(.section-pricing_starting_at):not(.section-consult_deliverable):not(.section-final_cta):not(.section-hub-cta):not(.final-cta):not(.section-service_area_map):not(.section-stats):not(.section-skin_type_suitability):not(.sec-room):not(.sec-photo) {
  background: var(--c-surface-alt);
}
:where(.sl-body).refine-luxe-noir.sections-alternate main > section.section:nth-of-type(4n):not(.section-tier_comparison):not(.section-ingredient_choice):not(.section-trust_strip):not(.section-pricing_starting_at):not(.section-consult_deliverable):not(.section-final_cta):not(.section-hub-cta):not(.final-cta):not(.section-service_area_map):not(.section-stats):not(.section-skin_type_suitability) {
  background: var(--c-surface-alt);
}

/* The keyed DARK bands. Ink is rebound via the custom properties every component already
   reads, so h2/p/eyebrow inside flip to the dark-band inks without per-element chasing:
   text -> surface (15.79:1), muted -> 80% surface mix (10.55:1), accent ink ->
   accent-ink-dark (7.76:1, machine-guaranteed per brand). */
:where(.sl-body).refine-luxe-noir main > section.section.section-trust_strip:nth-of-type(n), :where(.sl-body).refine-luxe-noir main > section.section.section-pricing_starting_at:nth-of-type(n), :where(.sl-body).refine-luxe-noir main > section.section.section-consult_deliverable:nth-of-type(n), :where(.sl-body).refine-luxe-noir main > section.section.section-final_cta:nth-of-type(n), :where(.sl-body).refine-luxe-noir main > section.section.section-skin_type_suitability:nth-of-type(n), :where(.sl-body).refine-luxe-noir main > section.section.section-hub-cta:nth-of-type(n) {
  background: var(--c-hero-plate);
  --c-text: var(--c-on-dark);
  --c-text-muted: var(--ln-dark-muted);
  --c-accent-ink: var(--c-accent-ink-dark);
  --eyebrow-ink: var(--c-accent-ink-dark);
  color: var(--c-on-dark);
  border-top: 1px solid var(--ln-hairline);
  border-bottom: 1px solid var(--ln-hairline);
}
/* Any card-like object the fan-out ever drops INTO a dark band stays a light plate with
   its own light-context inks (restored from the body-level saves, never hardcoded). */
:where(.sl-body).refine-luxe-noir .section-pricing_starting_at .card, :where(.sl-body).refine-luxe-noir .section-consult_deliverable .card, :where(.sl-body).refine-luxe-noir .section-pricing_starting_at .auto-item, :where(.sl-body).refine-luxe-noir .section-consult_deliverable .auto-item {
  background: var(--c-surface);
  --c-text: var(--ln-text-save);
  --c-text-muted: var(--ln-muted-save);
  color: var(--ln-text-save);
}

/* NORTH-STAR trust strip: DE-ICONED. The icon parade is the second-strongest template tell.
   On the dark band the strip becomes ONE masthead credit line — tracked small caps separated
   by small gold diamonds, like the credits line of a fashion editorial. The icon discs are
   hidden entirely; the base absolute hairline divider is recast as an inline diamond glyph
   (static position turns the ::before into a flex child that flows in line). */
:where(.sl-body).refine-luxe-noir .section-trust_strip .trust-row { gap: 0.55rem 0; justify-content: center; }
:where(.sl-body).refine-luxe-noir .section-trust_strip .trust-row-item {
  flex: 0 0 auto;
  flex-direction: row;
  align-items: center;
  gap: 0;
  padding: 0.3rem 0;
  text-align: left;
}
:where(.sl-body).refine-luxe-noir .section-trust_strip .trust-row-item .trust-ic { display: none; }
:where(.sl-body).refine-luxe-noir .section-trust_strip .trust-row-item span {
  font-weight: 500;
  font-size: 0.78rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--c-on-dark);
  line-height: 1.7;
}
:where(.sl-body).refine-luxe-noir .section-trust_strip .trust-row-item + .trust-row-item::before {
  content: '◆';
  position: static;
  display: inline-block;
  width: auto;
  height: auto;
  top: auto;
  bottom: auto;
  background: none;
  color: var(--c-accent);
  font-size: 0.5rem;
  line-height: 1;
  margin: 0 1.6rem;
  transform: translateY(-1px);
}
/* The base mobile rules stack the items as icon rows with hairline tops; the masthead line
   instead wraps as centered caps lines, so kill the borrowed border and keep the diamonds. */
@media (max-width: 640px) {
  :where(.sl-body).refine-luxe-noir .section-trust_strip .trust-row-item + .trust-row-item { border-top: 0; }
  /* flex: 0 0 auto sizes the item at max-content, so the longest credit ran past the phone
     viewport (seen clipped in the 390px screenshot). Let the item shrink so its caps WRAP. */
  :where(.sl-body).refine-luxe-noir .section-trust_strip .trust-row-item { justify-content: center; padding: 0.18rem 0; flex-shrink: 1; min-width: 0; max-width: 100%; }
  :where(.sl-body).refine-luxe-noir .section-trust_strip .trust-row-item span { text-align: center; }
  :where(.sl-body).refine-luxe-noir .section-trust_strip .trust-row-item + .trust-row-item::before { margin: 0 0.9rem; }
}

/* Final CTA: the inner card dissolves into its band (same token = same paint), the accent
   glow drops to a whisper, and the close reads as one full-bleed evening block. */
:where(.sl-body).refine-luxe-noir .final-cta::after { opacity: 0.1; }
/* CTA buttons on the dark close. The standard final_cta emits accent fill + primary_dark
   ink INLINE, but the hub CTA emits bare .btn classes — and .btn-secondary's default
   primary ink on a dark band measured 1.27:1 (caught by visual-lint the moment the lane
   flattened the gradient into a measurable color; the defect predates the lane, hidden
   behind the gradient bail-out). Pin both buttons to the dark-band pairs: accent fill /
   primary_dark ink 6.59:1, surface outline ink 15.79:1. */
:where(.sl-body).refine-luxe-noir .final-cta .btn-primary {
  background: var(--c-accent);
  border-color: var(--c-accent);
  color: var(--c-primary-dark);
}
:where(.sl-body).refine-luxe-noir .final-cta .btn-primary:hover { background: color-mix(in srgb, var(--c-accent) 85%, var(--c-surface)); color: var(--c-primary-dark); }
/* The secondary's ink and outline were pinned here too, as `color`/`border-color: var(--c-surface)`.
   That was one of five copies of the same sentence — a secondary button on a dark ground takes the
   surface ink — and it was a DEAD copy: the shared dark-ground guard a thousand lines below states
   it at exactly the same (0,3,1) and later in the file, so this line never once won. It named the
   paper colour where the guard reads `--c-cta-text`, the token brand.ts derives from the band the
   button actually lands on, so keeping it could only ever have been the wrong answer arriving too
   late to be used. Deleted. The hover below stays: nothing else states it at this weight. */
:where(.sl-body).refine-luxe-noir .final-cta .btn-secondary:hover { background: var(--c-light-stock); color: var(--c-primary-dark); }

/* ── Primary CTA on DARK bands: light pill, not accent fill ──────────────────────────────
   The accent fill above clears AA (rose on plum_dark, 6.6:1) but reads MUTED against a
   plum band or a plum-scrimmed hero photo — the fill and the band are neighbours on the
   same hue, so the button stops looking like the thing to press. Measured against the
   hand-built reference (../mk-aesthetics-site), the primary action there is a light pill
   on dark and it is the single loudest element on the hero. Surface fill on primary_dark
   ink is also the higher contrast pair (15.8:1 vs 6.6:1), so this is a legibility win as
   well as a hierarchy one. Accent survives as the HOVER state, which keeps the lane's
   rose in play on the element it was tuned for. */
:where(.sl-body).refine-luxe-noir .final-cta .btn-primary, :where(.sl-body).refine-luxe-noir .hero .btn-primary {
  background: var(--c-light-stock);
  border-color: var(--c-light-stock);
  color: var(--c-primary-dark);
}
:where(.sl-body).refine-luxe-noir .final-cta .btn-primary:hover, :where(.sl-body).refine-luxe-noir .hero .btn-primary:hover {
  background: var(--c-accent);
  border-color: var(--c-accent);
  color: var(--c-primary-dark);
}

/* Coverage band: flatten the radial+linear stack to the same flat primary_dark as the
   other dark bands (base rule is !important, so this must be too), kill the app-y svg
   drop shadow, and swap the white chip eyebrow for the lane's tracked gold caps. */
/* Guarded exactly as dark-luxe is at :4660, and for the identical reason. This rule is (0,3,3)
   with !important and the light map compositions at :587 are (0,2,1) with !important, so an
   unguarded lane repaints the band plum UNDERNEATH the plum ink those compositions set. MK
   Wellness is the first luxe-noir site to ask for composition.map = 'index' and it rendered at
   1.1:1 — the same R15 failure dark-luxe already took on Top Tier, latent here the whole time. */
:where(.sl-body).refine-luxe-noir:not(.map-index):not(.map-panel) main > section.section.section-service_area_map {
  background: var(--c-hero-plate) !important;
}
:where(.sl-body).refine-luxe-noir .coverage-map-col .cm-svg { filter: none; }
:where(.sl-body).refine-luxe-noir .coverage-text-col .eyebrow, :where(.sl-body).refine-luxe-noir .coverage-stack .eyebrow {
  background: none;
  padding: 0;
  color: var(--c-accent-ink-dark);
}

/* Hub hero (gradient variant): one flat evening field, matching the band system. */
:where(.sl-body).refine-luxe-noir .hero-gradient { background: var(--c-hero-plate); }

/* ── luxe-noir NORTH-STAR round — structural anti-template ────────────────────────────────
   Ian's verdict on the first round: "still just looks like a template." The diagnosis is the
   SKELETON, not the paint: centered symmetric headers, icon-card grids, uniform band rhythm.
   This round breaks the skeleton. Six moves, all scoped, all riding the DOM the renderers
   already emit: (1) editorial left-set headers, (2) icon grids -> numbered editorial rows
   [since PROMOTED to `.comp-numbered` — see the COMPOSITION VOCABULARY block below], (3)
   trust strip as a masthead line (above), (4) the Fitzpatrick spectrum band — the
   signature, (5) a massive type-led minimal-left hero, (6) an asymmetric FAQ split [since
   PROMOTED to `.comp-split`, same block]. */

/* (1) EDITORIAL HEADERS — left-set, oversized (scale set at the v1 rule above), the offset
   accent rule above the headline via h2::before. The header block spans the same content-max
   column as the card bands below it, so left edges align down the page; the h2/p get their
   own ragged measures so lines never run the full band. */
:where(.sl-body).refine-luxe-noir .section-header {
  text-align: left;
  max-width: var(--content-max);
  margin: 0 auto 2.5rem;
}
:where(.sl-body).refine-luxe-noir .section-header .eyebrow { margin-bottom: 0.85rem; }
:where(.sl-body).refine-luxe-noir .section-header h2 { max-width: 24ch; }
:where(.sl-body).refine-luxe-noir .section-header p { max-width: 62ch; }

/* (2) REMOVED HERE, PROMOTED BELOW. The numbered-editorial rows this round invented were
   keyed to bare .why-rows/.steps-row, which dressed EVERY same-type section identically —
   the monotony Ian rejected. They now live in the COMPOSITION VOCABULARY block at the end
   of this lane as `.comp-numbered`, applied per section INSTANCE via content_json's
   _composition map. Deliberate consequence: an un-composed section renders the lane's
   base SKIN (hairline cards, badge discs, connector rail) until its page gets a
   _composition map — structure now comes from composition, never from section type. */

/* (4) THE SPECTRUM BAND — the signature. skin_type_suitability is keyed into the dark band
   set above; its six auto-items become a continuous edge-to-edge bar of the six Fitzpatrick
   tones (fixed hexes — this IS the Fitzpatrick scale, not a brand token). Labels sit ON the
   swatches with measured inks: #2E1A0E on tones I–IV = 13.25 / 11.45 / 8.36 / 4.96,
   #F6EDE2 on tones V–VI = 5.04 / 9.47 — every pair >= 4.5:1. (The naive light-on-dark-half
   split fails: tone IV #B5825A tops out at 3.05:1 against ANY light ink, so the ink flips at
   V, not IV. Computed 2026-07-30.) One row at every width — six narrow columns on a phone. */
:where(.sl-body).refine-luxe-noir .section-skin_type_suitability { padding-top: clamp(3rem, 6vw, 4.75rem); padding-bottom: clamp(3rem, 6vw, 4.75rem); }
:where(.sl-body).refine-luxe-noir .section-skin_type_suitability .section-header {
  max-width: none;
  margin-left: 0;
  margin-bottom: 1.4rem;
}
:where(.sl-body).refine-luxe-noir .section-skin_type_suitability .section-header h2 {
  font-size: clamp(2.7rem, 5.4vw, 4.3rem);
  max-width: 18ch;
}
/* the renderer emits the intro as a bare <p> between header and bar */
:where(.sl-body).refine-luxe-noir .section-skin_type_suitability .container > p {
  max-width: 58ch;
  margin: 0 0 0.5rem;
  color: var(--ln-dark-muted);
}
:where(.sl-body).refine-luxe-noir .section-skin_type_suitability .auto-items {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 0;
  max-width: none;
  margin: 2.75rem 0 0;
  border: 1px solid var(--ln-hairline-strong); /* frames the bar so tone VI reads against the espresso band */
}
:where(.sl-body).refine-luxe-noir .section-skin_type_suitability .auto-item {
  border: 0;
  border-radius: 0;
  box-shadow: none;
  padding: 0;
  min-height: clamp(190px, 26vw, 320px);
  display: flex;
  align-items: flex-end;
  justify-content: center;
}
:where(.sl-body).refine-luxe-noir .section-skin_type_suitability .auto-item:nth-child(1) { background: #F2E4D5; }
:where(.sl-body).refine-luxe-noir .section-skin_type_suitability .auto-item:nth-child(2) { background: #EBD3B8; }
:where(.sl-body).refine-luxe-noir .section-skin_type_suitability .auto-item:nth-child(3) { background: #D9B18C; }
:where(.sl-body).refine-luxe-noir .section-skin_type_suitability .auto-item:nth-child(4) { background: #B5825A; }
:where(.sl-body).refine-luxe-noir .section-skin_type_suitability .auto-item:nth-child(5) { background: #8A5A38; }
:where(.sl-body).refine-luxe-noir .section-skin_type_suitability .auto-item:nth-child(6) { background: #55351F; }
:where(.sl-body).refine-luxe-noir .section-skin_type_suitability .auto-item strong {
  display: block;
  margin: 0 0.25rem 1.2rem;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: clamp(0.58rem, 0.9vw, 0.78rem);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-align: center;
  line-height: 1.6;
}
:where(.sl-body).refine-luxe-noir .section-skin_type_suitability .auto-item:nth-child(-n+4) strong { color: #2E1A0E; }
:where(.sl-body).refine-luxe-noir .section-skin_type_suitability .auto-item:nth-child(n+5) strong { color: #F6EDE2; }

/* (5) MINIMAL-LEFT HERO — type-led. The display headline goes MASSIVE at tight leading on a
   quiet paper tint (no photo, no gradient theatre); eyebrow carries the offset accent rule;
   subhead / rating / CTA row step right of the headline's left edge on wide screens (the
   indent collapses to 0 on a phone). The accent-ink swap on eyebrow + stars also clears the
   two 2.4:1 accent-on-white lint warnings the v1 hero carried. */

/* ══ COMPOSITION VOCABULARY (design-lanes PART II, items 2 + 4) ═══════════════════════════
   STRUCTURE COMES FROM COMPOSITION, SKIN FROM THE LANE. Every structural treatment below
   keys off a `comp-*` class that Sections.astro emits on a section WRAPPER from the page's
   content_json._composition map — per INSTANCE, never per section type. Two step-lists on
   one page can wear two different treatments; that is the anti-monotony mechanism, and
   scripts/monotony-lint.mjs polices adjacency (M1) and overuse (M2).

   Every treatment dresses BOTH dominant DOM shapes — .why-rows row lists and .steps-row
   card lists — and degrades gracefully anywhere else: a comp class over a shape a
   treatment does not know simply matches nothing and the lane's skin carries the section.
   Photo-topped step rails (.steps-photo) are deliberately untouched by every text
   treatment — a photograph has nowhere to live in a text row.

   The five treatments:
     comp-numbered    — numbered editorial (PROMOTED from this file's north-star round)
     comp-split       — 38/62 sticky-header split (PROMOTED from the same round's FAQ)
     comp-quiet-prose — the calm one: indented prose, bold lead-ins, one opening hairline
     comp-ledger      — the precise one: 30/70 ruled rows, small-caps labels, no air
     comp-statement   — the loud one: hero-scale headline, small right-set flowing line
                        (the gate caps every treatment at twice a page; taste caps this
                        one at once or twice)

   CONTRAST LAW: no treatment introduces a literal color. Everything rides the lane inks
   already measured for the MK seed palette — text 13.76:1 on white / 11.99:1 on
   surface_alt; muted 5.98 / 5.24; accent-ink 6.69 / 5.75 — and inside the keyed dark
   bands the same variables rebind to surface 15.79 / dark-muted 10.55 / accent-ink-dark
   7.76. The numerals, em-dash lead-ins, and diamond separators all use those INK
   variables (never raw --c-accent, which is 2.4:1 on white). All pairs >= 4.5:1. ═══════ */

/* ╔══════════════════════════════════════════════════════════════════════════════════════╗
   ║  COMPOSITION VOCABULARY — BASE LAYER (lane-agnostic)                                 ║
   ╚══════════════════════════════════════════════════════════════════════════════════════╝
   WHY THIS LAYER EXISTS. Every one of the 80 comp-* rules below this block is scoped to
   `body.refine-luxe-noir`. Exactly one client carries that lane. So the shape vocabulary —
   the whole anti-monotony mechanism — has only ever worked on ONE site out of 25: assigning
   a treatment anywhere else emitted the class and matched no CSS at all, which is why
   monotony-lint passes vacuously (118 of 134 pages on the flagship IV site are "uncomposed")
   and why every non-MK page renders the same default shape 8-12 times down the page.

   This layer gives the vocabulary to EVERY site. The lane rules below keep their
   `body.refine-luxe-noir` prefix and therefore keep out-specifying this base (0,3,x beats
   0,2,x), so MK renders byte-identically to before — verified by the visual gate. Lanes
   refine; they no longer gatekeep.

   CONTRAST LAW (inherited from the lane block below): no treatment introduces a literal
   color. Everything rides --c-text / --c-text-muted / --c-accent-ink, which are the pairs
   already measured against every brand's surfaces. Raw --c-accent is never used for ink.

   Nine treatments. The five that existed, plus four the 2026-07-30 survey of 19 sector
   leaders (Skin Pharm, Peachy, Alchemy 43, Formula Fig, Heyday, Glowbar, Upkeep, Milk +
   Honey, Silver Mirror, Drip Hydration, Restore and others) showed on nearly every one and
   SiteLaunch had no equivalent of: a mixed-size proof wall, a facts strip, an
   alternating-side showcase, and a full-bleed photographic rest. */

/* CONGRUENT HEADERS. These four treatments render their content hard-left — a numeral column, a
   ruled ledger, a prose measure, a sticky split — so their header goes left with it, and only
   theirs. Everything else keeps the centred default because its content is a centred grid. This
   is R8 (:3286) applied per section instead of per site: the alternative, flipping every header
   left, leaves centred card rows under left headings and reads as a bug.
   A full-bleed photo band gets the same treatment: copy over a photograph is editorial by nature,
   and centring it fights the image's own composition. */
/* …EXCEPT WHEN THE PHOTO BAND'S CONTENT IS A CENTRED GRID, which is the case the paragraph above
   already rules out and this selector did not. `.sec-photo` was added to this list by SURFACE — it
   has a photograph, so it was called editorial — while every other entry earns its place by
   CONTENT SHAPE: a ledger, a prose measure, a sticky split, all of them left-aligned layouts.
   The steps band is a photo band holding three centred cards, so it took the left header and
   produced precisely what the note above calls a bug: a centred card row under a left heading.
   On Top Tier's home page that made it the only left-aligned heading among six centred ones —
   which grid-lint had been reporting as "G2 6 centred vs 1 left-aligned" the whole time.
   :has() asks the question the rule always meant to ask: is this band's content left-shaped? */
:where(.sl-body) .comp-numbered > .container > .section-header, :where(.sl-body) .comp-ledger > .container > .section-header, :where(.sl-body) .comp-facts > .container > .section-header, :where(.sl-body) .comp-quiet-prose > .container > .section-header, :where(.sl-body) main > section.section.sec-photo:nth-of-type(n):not(:has(.steps-row)) > .container > .section-header {
  text-align: left;
  margin-left: 0;
  margin-right: auto;
}

/* comp-numbered (base) — oversized numeral hanging left of each row.
   display:block is load-bearing, not tidiness. .steps-row ships as a horizontal 3-column
   grid; leaving it gridded put each numeral in its own narrow column where it collided with
   that card's heading and read as "01 Book Your Appointment 02 Real-Time Medical". Every
   vertical treatment (numbered, ledger, quiet-prose) has to unwind the grid first. */
:where(.sl-body) .comp-numbered .why-rows, :where(.sl-body) .comp-numbered .steps-row:not(.steps-photo) { display: block; counter-reset: cb-row; gap: 0; }
/* The numeral is a real GRID ITEM, not an absolutely-positioned ::before. Absolute positioning
   pinned it to the row's padding box, but .why-row is itself a grid whose heading can start lower
   than the box does — so "01" floated above "Real-Time Medical Approval" instead of sharing its
   baseline. As a grid item in column 1 it aligns with the title by construction, at any type size. */
:where(.sl-body) .comp-numbered .why-row, :where(.sl-body) .comp-numbered .steps-row:not(.steps-photo) > .card.step-card {
  counter-increment: cb-row;
  display: grid;
  grid-template-columns: clamp(2.6rem, 5vw, 3.8rem) minmax(0, 1fr);
  column-gap: clamp(1rem, 2.2vw, 1.8rem);
  align-items: start;
  background: transparent; border: 0; border-radius: 0; box-shadow: none;
  padding: clamp(1.4rem, 2.8vw, 2.2rem) 0;
  border-bottom: 1px solid color-mix(in srgb, var(--c-text) 14%, transparent);
  text-align: left;
}
:where(.sl-body) .comp-numbered .why-row:last-child, :where(.sl-body) .comp-numbered .steps-row:not(.steps-photo) > .card.step-card:last-child { border-bottom: 0; }
/* top matches the row's own padding-top so the numeral sits on the TITLE's first baseline, not
   floating above it — the row is a grid whose head can start lower than the box does. */
:where(.sl-body) .comp-numbered .why-row::before, :where(.sl-body) .comp-numbered .steps-row:not(.steps-photo) > .card.step-card::before {
  content: counter(cb-row, decimal-leading-zero);
  grid-column: 1; grid-row: 1 / -1; align-self: start;
  font-family: var(--font-heading);
  font-size: clamp(1.5rem, 3vw, 2.1rem);
  line-height: 1.15; color: var(--c-accent-ink); opacity: 0.85;
}
/* Every real child sits in column 2; the ::before owns column 1. `> *` matches elements only, so
   it never selects the pseudo-element — which is why this must NOT be written as :not(::before),
   a selector that is invalid inside :not() and silently drops the whole rule (it did: the body
   copy fell into the 3rem numeral column and wrapped one word per line). */
:where(.sl-body) .comp-numbered .why-row > *, :where(.sl-body) .comp-numbered .steps-row:not(.steps-photo) > .card.step-card > * { grid-column: 2; min-width: 0; }
:where(.sl-body) .comp-numbered .why-row-ic, :where(.sl-body) .comp-numbered .step-badge { display: none; }

/* comp-ledger (base) — 30/70 ruled rows, label left, body right, no boxes. */
:where(.sl-body) .comp-ledger .why-rows, :where(.sl-body) .comp-ledger .steps-row:not(.steps-photo) { display: block; gap: 0; }
:where(.sl-body) .comp-ledger .why-row, :where(.sl-body) .comp-ledger .steps-row:not(.steps-photo) > .card.step-card {
  display: grid; grid-template-columns: minmax(0, 30fr) minmax(0, 70fr);
  column-gap: clamp(1.5rem, 4vw, 3.5rem);
  align-items: start; text-align: left;
  background: transparent; border: 0; border-radius: 0; box-shadow: none;
  padding: clamp(1.1rem, 2.2vw, 1.7rem) 0;
  border-bottom: 1px solid color-mix(in srgb, var(--c-text) 14%, transparent);
}
:where(.sl-body) .comp-ledger .why-row:last-child, :where(.sl-body) .comp-ledger .steps-row:not(.steps-photo) > .card.step-card:last-child { border-bottom: 0; }
:where(.sl-body) .comp-ledger .why-row-ic, :where(.sl-body) .comp-ledger .step-badge { display: none; }
@media (max-width: 700px) {
  :where(.sl-body) .comp-ledger .why-row, :where(.sl-body) .comp-ledger .steps-row:not(.steps-photo) > .card.step-card {
    grid-template-columns: minmax(0, 1fr); row-gap: 0.35rem;
  }
}

/* comp-quiet-prose (base) — a measure, not a band. The section narrows to the copy. */
/* 74ch was a book measure on a page that is not a book: beside full-width bands it read as a
   column stranded in the middle of the screen — Ian: "my only concern is how narrow it is".
   Wider, and capped against the shared content width so it still narrows relative to its
   neighbours, which is the entire point of the treatment. */
@media (min-width: 901px) { :where(.sl-body) .comp-quiet-prose .container { max-width: min(var(--content-max), 92ch); } }
:where(.sl-body) .comp-quiet-prose .why-rows, :where(.sl-body) .comp-quiet-prose .steps-row:not(.steps-photo) {
  display: block; gap: 0;
  border-top: 1px solid color-mix(in srgb, var(--c-text) 14%, transparent);
  padding-top: clamp(1.4rem, 2.6vw, 2.2rem);
}
:where(.sl-body) .comp-quiet-prose .why-row, :where(.sl-body) .comp-quiet-prose .steps-row:not(.steps-photo) > .card.step-card {
  display: block; background: transparent; border: 0; border-radius: 0; box-shadow: none;
  padding: 0.85rem 0; text-align: left; line-height: 1.85;
}
:where(.sl-body) .comp-quiet-prose .why-row-ic, :where(.sl-body) .comp-quiet-prose .step-badge { display: none; }

/* comp-split (base) — 38/62 sticky header column, content right. */
@media (min-width: 901px) {
  :where(.sl-body) .comp-split .container {
    display: grid; grid-template-columns: minmax(0, 38fr) minmax(0, 62fr);
    column-gap: clamp(2.5rem, 5vw, 5rem); align-items: start;
  }
  :where(.sl-body) .comp-split .container > * { grid-column: 2; }
  :where(.sl-body) .comp-split .container > .section-header {
    grid-column: 1; position: sticky; top: 108px; margin: 0; max-width: none; text-align: left;
  }
  :where(.sl-body) .comp-split .container > .faq-list, :where(.sl-body) .comp-split .container > .why-rows, :where(.sl-body) .comp-split .container > .cards-center { max-width: none; margin-left: 0; margin-right: 0; }
}

/* comp-statement (base) — one hero-scale line. Used once a page; the gate caps it at twice. */
/* 20ch AT 4.4rem IS A CHIMNEY, NOT A STATEMENT. A five-word headline broke over five lines,
   one word per line, straight down the middle of the page — Ian: "super skinny down the middle,
   doesn't look right at all." The measure was written for a two-word headline and nothing checked
   it against a real one. A statement is loud because the TYPE is big, not because the column is
   narrow; the measure now scales with the viewport so the line count stays sane at any width. */
/* The measure is in REM, not ch, and the unit was the actual bug. `ch` resolves against the element
   it is set on — .section-header inherits ~16px — so "30ch" was about 240px while the h2 inside it
   rendered at 3.6rem, and every word wrapped. Widening the ch value would never have fixed it. */
:where(.sl-body) .comp-statement .section-header { max-width: min(100%, 44rem); text-align: left; }
:where(.sl-body) .comp-statement .section-header h2 { font-size: clamp(2rem, 4.6vw, 3.6rem); line-height: 1.06; text-wrap: balance; }
:where(.sl-body) .comp-statement .section-header p { font-size: clamp(1rem, 1.4vw, 1.12rem); max-width: 46ch; }

/* ── comp-wall (NEW) — MIXED-SIZE PROOF WALL ────────────────────────────────────────────
   Peachy's review section is the single best component in the survey: text reviews,
   customer video stills and press clippings in one masonry at deliberately unequal sizes.
   The unevenness is the point — a proof grid of identical tiles reads as a template, and a
   wall of real artifacts reads as a business people actually go to. CSS columns rather than
   grid so tiles keep their natural height and the wall packs itself. */
:where(.sl-body) .comp-wall .cards-center, :where(.sl-body) .comp-wall .why-rows, :where(.sl-body) .comp-wall .steps-row:not(.steps-photo) {
  display: block; columns: 3 260px; column-gap: clamp(0.9rem, 1.8vw, 1.4rem); max-width: none;
}
:where(.sl-body) .comp-wall .card, :where(.sl-body) .comp-wall .why-row, :where(.sl-body) .comp-wall .step-card {
  break-inside: avoid; -webkit-column-break-inside: avoid; page-break-inside: avoid;
  display: block; width: 100%; margin: 0 0 clamp(0.9rem, 1.8vw, 1.4rem); text-align: left;
}
/* Cadence: every third and fifth tile carries more weight, so the eye never finds a grid. */
:where(.sl-body) .comp-wall .card:nth-child(3n+1) { font-size: 1.06em; }
:where(.sl-body) .comp-wall .card:nth-child(5n+3) { background: var(--c-surface-alt); }
:where(.sl-body) .comp-wall .why-row-ic, :where(.sl-body) .comp-wall .step-badge { display: none; }
@media (max-width: 700px) { :where(.sl-body) .comp-wall .cards-center, :where(.sl-body) .comp-wall .why-rows { columns: 1; } }

/* ── comp-facts (NEW) — THE FACTS STRIP ─────────────────────────────────────────────────
   The hand-built MK concept and Skin Pharm both put a compact label/value ledger directly
   under the hero — WHERE, PHONE, HOURS, RATING. It answers the four questions a local
   visitor actually arrived with, in less vertical space than one card row, and it is the
   cheapest credibility on a page. Label small-caps left, value beside it, hairline between. */
:where(.sl-body) .comp-facts .why-rows, :where(.sl-body) .comp-facts .steps-row:not(.steps-photo), :where(.sl-body) .comp-facts .cards-center {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(clamp(200px, 22vw, 280px), minmax(0, 1fr)));
  gap: 0 clamp(1.5rem, 4vw, 3rem); max-width: none;
}
:where(.sl-body) .comp-facts .why-row, :where(.sl-body) .comp-facts .steps-row:not(.steps-photo) > .card.step-card, :where(.sl-body) .comp-facts .card {
  display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: baseline;
  column-gap: clamp(0.9rem, 2vw, 1.6rem);
  background: transparent; border: 0; border-radius: 0; box-shadow: none;
  padding: clamp(0.85rem, 1.6vw, 1.15rem) 0; text-align: left;
  border-bottom: 1px solid color-mix(in srgb, var(--c-text) 14%, transparent);
}
:where(.sl-body) .comp-facts .why-row-head h3, :where(.sl-body) .comp-facts .step-card h3, :where(.sl-body) .comp-facts .card h3 {
  font-family: var(--font-heading); font-size: 0.72rem; font-weight: 700;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--c-text-muted); margin: 0;
}
:where(.sl-body) .comp-facts .why-row p, :where(.sl-body) .comp-facts .step-card p, :where(.sl-body) .comp-facts .card p { margin: 0; color: var(--c-text); }
:where(.sl-body) .comp-facts .why-row-ic, :where(.sl-body) .comp-facts .step-badge { display: none; }

/* additional_contact IS this shape and always was. It renders .ac-grid of .ac-card, each a
   .contact-method-label over an .ac-card-value — a label/value ledger wearing card chrome. The
   treatment existed for weeks and rendered on zero sites because it only knew the three generic
   shapes and nothing generic carries label/value pairs. Naming the one component that does is
   what makes it real: WHERE / PHONE / HOURS / EMAIL, under the hero, as a ledger instead of a
   row of boxes. */
:where(.sl-body) .comp-facts .ac-grid {
  /* TWO FAULTS, BOTH INVISIBLE UNTIL SOMEBODY MEASURED THE PAGE.
     1. This read `minmax(clamp(180px, 20vw, 250px), minmax(0, 1fr))`. minmax() does not accept
        another minmax() as its maximum, so the whole declaration was invalid and the browser threw
        it away - leaving `display: grid` with one implicit column. The ledger has rendered as a
        single 1160px-wide column on every client carrying this treatment since it was written, and
        no check can see it: the CSS parses, the page renders, nothing overflows.
     2. The minimum it asked for was 180-250px, which suits two-word facts (WHERE / PHONE / HOURS)
        and not the sentences clients actually put here - "Wellness gatherings, corporate events,
        bridal parties, athletic teams..." in a 250px column is a tall ragged stack. So the minimum
        is a readable measure instead: wide enough that a sentence gets a couple of lines, and
        `min(100%, …)` so a narrow container still collapses to one column instead of overflowing. */
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 30rem), 1fr));
  gap: 0 clamp(1.5rem, 4vw, 3rem);
}
:where(.sl-body) .comp-facts .ac-card {
  /* BACK TO ONE COLUMN. `.ac-card` also carries the generic `.card` class, so `.comp-facts .card`
     above grids it into label-left / value-right - which is the right ledger for the three generic
     shapes and the wrong one here. Each row is its own grid, so no two label columns agree on a
     width and the values come out ragged, every value starting wherever its own label happened to
     end. The block below was already written for label-over-value (see `display: block` on the
     label) and just never said so to the grid. */
  display: block; grid-template-columns: none;
  background: transparent; border: 0; border-radius: 0; box-shadow: none;
  padding: clamp(0.8rem, 1.5vw, 1.1rem) 0; text-align: left;
  border-bottom: 1px solid color-mix(in srgb, var(--c-text) 14%, transparent);
}
:where(.sl-body) .comp-facts .ac-card .contact-method-label {
  font-family: var(--font-heading); font-size: 0.72rem; font-weight: 700;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--c-text-muted);
  display: block; margin-bottom: 0.2rem;
}
:where(.sl-body) .comp-facts .ac-card .ac-card-value { color: var(--c-text); font-size: 1rem; }

/* ── comp-showcase (NEW) — ALTERNATING-SIDE SPLIT ───────────────────────────────────────
   Skin Pharm runs text-left/photo-right, then mirrors it photo-left/text-right on the very
   next section. That single alternation is most of why its page never reads as a stack of
   bands. `.is-mirrored` flips it; the assigner alternates the flag down the page so no two
   adjacent showcases lean the same way. */
@media (min-width: 861px) {
  :where(.sl-body) .comp-showcase .container {
    display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    column-gap: clamp(2rem, 5vw, 4.5rem); align-items: center;
  }
  :where(.sl-body) .comp-showcase .container > .section-header { grid-column: 1; margin: 0; max-width: 46ch; text-align: left; }
  :where(.sl-body) .comp-showcase .container > * { grid-column: 2; }
  :where(.sl-body) .comp-showcase.is-mirrored .container > .section-header { grid-column: 2; }
  :where(.sl-body) .comp-showcase.is-mirrored .container > *:not(.section-header) { grid-column: 1; }
}
:where(.sl-body) .comp-showcase img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ── comp-bleed (NEW) — THE FULL-BLEED REST ─────────────────────────────────────────────
   Every leader in the survey puts at least one edge-to-edge photograph with little or no
   copy between two dense sections. It is not decoration; it is the pause that makes the
   dense sections readable. SiteLaunch pages never rest — every band is packed, which is a
   large part of why they feel relentless. Breaks the container to the viewport edge. */
:where(.sl-body) .comp-bleed > .container { max-width: none; width: 100%; padding-left: 0; padding-right: 0; }
/* ONLY WHEN THERE IS ACTUALLY A PHOTOGRAPH. This lifts the header out of flow and hangs it over
   the image — correct for a full-bleed rest, and nonsense without one: on a section with no img
   the headline landed on top of the cards, which is exactly what Ian saw ("the H1 is sitting on
   top of the card"). `:has(img)` makes the treatment degrade to an ordinary header instead of
   overlapping content it was never meant to cover. */
:where(.sl-body) .comp-bleed:has(img) .section-header {
  position: absolute; left: 50%; transform: translateX(-50%); bottom: clamp(1.5rem, 4vw, 3rem);
  z-index: 2; width: min(100% - 3rem, var(--content-max)); text-align: left; margin: 0;
}
:where(.sl-body) .comp-bleed:not(:has(img)) .section-header h2, :where(.sl-body) .comp-bleed:not(:has(img)) .section-header p { color: inherit; text-shadow: none; }
:where(.sl-body) .comp-bleed:not(:has(img))::after { display: none; }
:where(.sl-body) .comp-bleed { position: relative; padding-top: 0; padding-bottom: 0; overflow: hidden; }
:where(.sl-body) .comp-bleed img { width: 100%; height: clamp(280px, 46vh, 560px); object-fit: cover; display: block; }
/* Copy over a photograph needs its own floor — the band's ink is tuned for the band, not
   for whatever the photograph happens to be doing behind the words. */
:where(.sl-body) .comp-bleed .section-header h2, :where(.sl-body) .comp-bleed .section-header p { color: #fff; text-shadow: 0 1px 24px rgba(0,0,0,0.55); }
:where(.sl-body) .comp-bleed::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(to top, rgba(0,0,0,0.55), rgba(0,0,0,0.12) 45%, transparent 70%);
}

/* ── comp-numbered — NUMBERED EDITORIAL ROWS ─────────────────────────────────────────────
   Icon squares and badge discs vanish; an oversized serif numeral (01 02 03…) in the
   darkened accent hangs left of the text. No boxes — hairline separators BETWEEN rows
   only; alternate rows take a modest left indent so the column edge is not one line. */
:where(.sl-body).refine-luxe-noir .comp-numbered .why-rows { counter-reset: ln-row; gap: 0; }
:where(.sl-body).refine-luxe-noir .comp-numbered .why-row {
  counter-increment: ln-row;
  grid-template-columns: clamp(3.4rem, 5.4vw, 4.8rem) minmax(0, 1fr);
  grid-template-rows: auto auto;
  column-gap: clamp(1.1rem, 2.4vw, 2rem);
  row-gap: 0.45rem;
  align-items: start;
  padding: clamp(1.6rem, 3vw, 2.4rem) 0;
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
}
:where(.sl-body).refine-luxe-noir .comp-numbered .why-row::before {
  content: counter(ln-row, decimal-leading-zero);
  grid-row: 1 / span 2;
  grid-column: 1;
  font-family: var(--font-heading);
  font-weight: 400;
  font-size: clamp(2.6rem, 4.4vw, 3.8rem);
  line-height: 0.95;
  color: var(--c-accent-ink, var(--c-accent));
}
:where(.sl-body).refine-luxe-noir .comp-numbered .why-row + .why-row { border-top: 1px solid var(--ln-hairline); }
:where(.sl-body).refine-luxe-noir .comp-numbered .why-row:nth-child(even) { padding-left: clamp(1.25rem, 4vw, 3.75rem); }
:where(.sl-body).refine-luxe-noir .comp-numbered .why-row-ic { display: none; }
:where(.sl-body).refine-luxe-noir .comp-numbered .why-row-head { grid-column: 2; }
:where(.sl-body).refine-luxe-noir .comp-numbered .why-row-head h3 { font-size: clamp(1.25rem, 2vw, 1.55rem); }
:where(.sl-body).refine-luxe-noir .comp-numbered .why-row-body { grid-column: 2; margin: 0; max-width: 62ch; }
/* …and the same rows when the instance is a step rail. */
:where(.sl-body).refine-luxe-noir .comp-numbered .steps-row:not(.steps-photo) {
  display: block;
  counter-reset: ln-step;
  max-width: var(--content-max);
  margin-left: auto;
  margin-right: auto;
}
:where(.sl-body).refine-luxe-noir .comp-numbered .steps-row:not(.steps-photo) > .card.step-card {
  counter-increment: ln-step;
  display: grid;
  grid-template-columns: clamp(3.4rem, 5.4vw, 4.8rem) minmax(0, 1fr);
  column-gap: clamp(1.1rem, 2.4vw, 2rem);
  row-gap: 0.45rem;
  align-items: start;
  text-align: left;
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  padding: clamp(1.6rem, 3vw, 2.4rem) 0;
  max-width: none;
}
:where(.sl-body).refine-luxe-noir .comp-numbered .steps-row:not(.steps-photo) > .card.step-card::before {
  content: counter(ln-step, decimal-leading-zero);
  grid-row: 1 / span 2;
  grid-column: 1;
  font-family: var(--font-heading);
  font-weight: 400;
  font-size: clamp(2.6rem, 4.4vw, 3.8rem);
  line-height: 0.95;
  color: var(--c-accent-ink, var(--c-accent));
}
:where(.sl-body).refine-luxe-noir .comp-numbered .steps-row:not(.steps-photo) > .step-card + .step-card { border-top: 1px solid var(--ln-hairline); }
:where(.sl-body).refine-luxe-noir .comp-numbered .steps-row:not(.steps-photo) > .step-card:nth-child(even) { padding-left: clamp(1.25rem, 4vw, 3.75rem); }
:where(.sl-body).refine-luxe-noir .comp-numbered .steps-row:not(.steps-photo) .step-badge { display: none; }
:where(.sl-body).refine-luxe-noir .comp-numbered .steps-row:not(.steps-photo) .step-card h3 { grid-column: 2; margin: 0; font-size: clamp(1.25rem, 2vw, 1.55rem); }
:where(.sl-body).refine-luxe-noir .comp-numbered .steps-row:not(.steps-photo) .step-card p { grid-column: 2; margin: 0; max-width: 62ch; }
:where(.sl-body).refine-luxe-noir .comp-numbered .steps-connected::before { display: none; }

/* ── comp-split — 38/62 STICKY-HEADER SPLIT ──────────────────────────────────────────────
   One section that is structurally two-column: header column left (~38%), content right;
   the header stays put (sticky under the site header) while the content scrolls. Shape-
   agnostic: any direct child of the container that is not the header goes to the right
   column, so it fits FAQ accordions, why-rows, and step rails alike. Collapses to the
   normal single column below 901px. */
@media (min-width: 901px) {
  :where(.sl-body).refine-luxe-noir .comp-split .container {
    display: grid;
    grid-template-columns: minmax(0, 38fr) minmax(0, 62fr);
    column-gap: clamp(2.5rem, 5vw, 5rem);
    align-items: start;
  }
  :where(.sl-body).refine-luxe-noir .comp-split .container > * { grid-column: 2; }
  :where(.sl-body).refine-luxe-noir .comp-split .container > .section-header {
    grid-column: 1;
    position: sticky;
    top: 108px;
    margin: 0;
    max-width: none;
  }
  /* the right column IS the measure now — content blocks fill it edge to edge
     (.why-rows carries an inline max-width of --content-max, wider than this column,
     so it needs no override) */
  :where(.sl-body).refine-luxe-noir .comp-split .container > .faq-list, :where(.sl-body).refine-luxe-noir .comp-split .container > .why-rows, :where(.sl-body).refine-luxe-noir .comp-split .container > .cards-center {
    max-width: none;
    margin-left: 0;
    margin-right: 0;
  }
}

/* comp-split INTERIOR (2026-07-30, first squint pass): the split arranged the columns but
   left its rows wearing the default card skin — icon tiles in hairline boxes, the exact
   icon-parade DNA the north-star round killed. Inside a split, rows read editorial: no
   boxes, no icon tiles, hairline separators only. Applies at every viewport (the interior
   should not regain icons on phones when the columns stack). */
:where(.sl-body).refine-luxe-noir .comp-split .why-row {
  border: 0;
  background: transparent;
  border-radius: 0;
  padding: 1.35rem 0;
  border-bottom: 1px solid color-mix(in srgb, var(--c-border) 70%, transparent);
  grid-template-columns: minmax(0, 1fr);
}
:where(.sl-body).refine-luxe-noir .comp-split .why-rows .why-row:last-child { border-bottom: 0; }
:where(.sl-body).refine-luxe-noir .comp-split .why-row-ic { display: none; }
:where(.sl-body).refine-luxe-noir .comp-split .why-row-head { margin-bottom: 0.4rem; }

/* ── comp-quiet-prose — THE CALM TREATMENT ───────────────────────────────────────────────
   No numerals, no boxes, no separators. Each item becomes an indented prose paragraph
   whose title is a bolded lead-in flowing straight into the body copy on an em dash,
   generous leading throughout, and a single hairline where the prose begins — nothing
   after it. */
:where(.sl-body).refine-luxe-noir .comp-quiet-prose .why-rows, :where(.sl-body).refine-luxe-noir .comp-quiet-prose .steps-row:not(.steps-photo) {
  display: block;
  gap: 0;
  max-width: var(--content-max);
  margin-left: auto;
  margin-right: auto;
  border-top: 1px solid var(--ln-hairline);
  padding-top: clamp(1.4rem, 2.6vw, 2.2rem);
}
:where(.sl-body).refine-luxe-noir .comp-quiet-prose .why-row, :where(.sl-body).refine-luxe-noir .comp-quiet-prose .steps-row:not(.steps-photo) > .card.step-card {
  display: block;
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  padding: 0.85rem 0 0.85rem clamp(1.5rem, 4.5vw, 4rem);
  max-width: 66ch;
  text-align: left;
  line-height: 1.85;
}
/* The band has to be as narrow as the prose inside it. The rules above cap each item at 66ch
   (~560px) and indent it, but left the SECTION at --content-max (1120px), so the copy hugged
   the left edge with the right half of the band empty — the single ugliest thing on MK's home
   page at 1280. Surveyed against how the sector actually sets long-form (Skin Pharm, Peachy,
   Alchemy 43 all run policy / how-it-works copy in a measure, never a half-filled band), the fix
   is to narrow the container, not to widen the prose: a calm treatment that fills 1120px stops
   being calm. Header and prose then share one left edge and the emptiness reads as margin. */
@media (min-width: 901px) {
  :where(.sl-body).refine-luxe-noir .comp-quiet-prose .container { max-width: 74ch; }
  :where(.sl-body).refine-luxe-noir .comp-quiet-prose .why-rows, :where(.sl-body).refine-luxe-noir .comp-quiet-prose .steps-row:not(.steps-photo) { max-width: none; }
  /* the indent existed to offset the prose from a wide band; inside a measure it just eats it */
  :where(.sl-body).refine-luxe-noir .comp-quiet-prose .why-row, :where(.sl-body).refine-luxe-noir .comp-quiet-prose .steps-row:not(.steps-photo) > .card.step-card {
    padding-left: 0;
    max-width: none;
  }
}
:where(.sl-body).refine-luxe-noir .comp-quiet-prose .why-row-ic, :where(.sl-body).refine-luxe-noir .comp-quiet-prose .steps-row:not(.steps-photo) .step-badge { display: none; }
:where(.sl-body).refine-luxe-noir .comp-quiet-prose .why-row-head { display: inline; }
:where(.sl-body).refine-luxe-noir .comp-quiet-prose .why-row-head h3, :where(.sl-body).refine-luxe-noir .comp-quiet-prose .steps-row:not(.steps-photo) .step-card h3 {
  display: inline;
  margin: 0;
  font-family: var(--font-body);
  font-size: 1.02rem;
  font-weight: 600;
  letter-spacing: 0;
  line-height: inherit;
}
/* the renderer emits </h3><p …> with no whitespace between; the em dash is the seam */
:where(.sl-body).refine-luxe-noir .comp-quiet-prose .why-row-head h3::after, :where(.sl-body).refine-luxe-noir .comp-quiet-prose .steps-row:not(.steps-photo) .step-card h3::after {
  content: ' — ';
  font-weight: 400;
  color: var(--c-text-muted);
}
:where(.sl-body).refine-luxe-noir .comp-quiet-prose .why-row-body, :where(.sl-body).refine-luxe-noir .comp-quiet-prose .steps-row:not(.steps-photo) .step-card p {
  display: inline;
  margin: 0;
  line-height: inherit;
}
:where(.sl-body).refine-luxe-noir .comp-quiet-prose .steps-connected::before { display: none; }

/* ── comp-ledger — THE PRECISE TREATMENT ─────────────────────────────────────────────────
   Dense: tight rows on a 30/70 grid, tracked small-caps label left, text right, a
   hairline on every row, no air. Holds its two columns at every viewport — the density
   IS the identity. */
:where(.sl-body).refine-luxe-noir .comp-ledger .why-rows, :where(.sl-body).refine-luxe-noir .comp-ledger .steps-row:not(.steps-photo) {
  display: block;
  gap: 0;
  max-width: var(--content-max);
  margin-left: auto;
  margin-right: auto;
  border-top: 1px solid var(--ln-hairline);
}
:where(.sl-body).refine-luxe-noir .comp-ledger .why-row, :where(.sl-body).refine-luxe-noir .comp-ledger .steps-row:not(.steps-photo) > .card.step-card {
  display: grid;
  grid-template-columns: minmax(0, 30fr) minmax(0, 70fr);
  gap: 0.25rem clamp(1.1rem, 3vw, 2.75rem);
  align-items: start;
  text-align: left;
  padding: 0.8rem 0;
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  border-bottom: 1px solid var(--ln-hairline);
  max-width: none;
}
:where(.sl-body).refine-luxe-noir .comp-ledger .why-row-ic, :where(.sl-body).refine-luxe-noir .comp-ledger .steps-row:not(.steps-photo) .step-badge { display: none; }
:where(.sl-body).refine-luxe-noir .comp-ledger .why-row-head { display: block; grid-column: 1; }
:where(.sl-body).refine-luxe-noir .comp-ledger .why-row-head h3, :where(.sl-body).refine-luxe-noir .comp-ledger .steps-row:not(.steps-photo) .step-card h3 {
  margin: 0;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.76rem;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  line-height: 1.7;
  color: var(--c-text);
}
:where(.sl-body).refine-luxe-noir .comp-ledger .steps-row:not(.steps-photo) .step-card h3 { grid-column: 1; }
:where(.sl-body).refine-luxe-noir .comp-ledger .why-row-body, :where(.sl-body).refine-luxe-noir .comp-ledger .steps-row:not(.steps-photo) .step-card p {
  grid-column: 2;
  grid-row: 1;
  margin: 0;
  font-size: 0.95rem;
  line-height: 1.55;
  max-width: 70ch;
}
:where(.sl-body).refine-luxe-noir .comp-ledger .steps-connected::before { display: none; }

/* ── comp-statement — THE LOUD TREATMENT ─────────────────────────────────────────────────
   The section headline goes hero-scale; the support copy drops small and steps RIGHT; the
   items flatten into one flowing line — bold lead-ins on em dashes, small diamonds
   between items — set in the same right-hand column. The header spans the full container
   (not --content-max) so the headline's left edge and the indent both measure from the
   same rail. The indent variable collapses to ~0 below ~520px viewports. */
:where(.sl-body).refine-luxe-noir .comp-statement { --ln-stmt-indent: clamp(0rem, 34vw - 8rem, 22rem); }
:where(.sl-body).refine-luxe-noir .comp-statement .section-header {
  max-width: none;
  margin-bottom: clamp(1.5rem, 3vw, 2.5rem);
}
:where(.sl-body).refine-luxe-noir .comp-statement .section-header h2 {
  font-size: clamp(2.9rem, 6.6vw, 5.4rem);
  line-height: 0.98;
  letter-spacing: -0.015em;
  max-width: 15ch;
}
:where(.sl-body).refine-luxe-noir .comp-statement .section-header p {
  font-size: 0.98rem;
  max-width: 46ch;
  margin-top: 1.1rem;
  margin-left: var(--ln-stmt-indent);
}
:where(.sl-body).refine-luxe-noir .comp-statement .why-rows, :where(.sl-body).refine-luxe-noir .comp-statement .steps-row:not(.steps-photo) {
  display: block;
  margin: 0 0 0 var(--ln-stmt-indent);
  /* width, not max-width: .why-rows carries an inline max-width that would win a
     max-width fight, and width beats it without !important */
  width: min(58ch, calc(100% - var(--ln-stmt-indent)));
  font-size: 0.98rem;
  line-height: 1.9;
  text-align: left;
}
:where(.sl-body).refine-luxe-noir .comp-statement .why-row, :where(.sl-body).refine-luxe-noir .comp-statement .steps-row:not(.steps-photo) > .card.step-card {
  display: inline;
  margin: 0;
  padding: 0;
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  max-width: none;
  text-align: left;
}
:where(.sl-body).refine-luxe-noir .comp-statement .why-row-ic, :where(.sl-body).refine-luxe-noir .comp-statement .steps-row:not(.steps-photo) .step-badge { display: none; }
:where(.sl-body).refine-luxe-noir .comp-statement .why-row-head { display: inline; }
:where(.sl-body).refine-luxe-noir .comp-statement .why-row-head h3, :where(.sl-body).refine-luxe-noir .comp-statement .steps-row:not(.steps-photo) .step-card h3 {
  display: inline;
  margin: 0;
  font-family: var(--font-body);
  font-size: inherit;
  font-weight: 600;
  letter-spacing: 0;
  line-height: inherit;
}
:where(.sl-body).refine-luxe-noir .comp-statement .why-row-head h3::after, :where(.sl-body).refine-luxe-noir .comp-statement .steps-row:not(.steps-photo) .step-card h3::after {
  content: ' — ';
  font-weight: 400;
  color: var(--c-text-muted);
}
:where(.sl-body).refine-luxe-noir .comp-statement .why-row-body, :where(.sl-body).refine-luxe-noir .comp-statement .steps-row:not(.steps-photo) .step-card p {
  display: inline;
  margin: 0;
  font-size: inherit;
  line-height: inherit;
}
/* the diamond between items — accent-INK, same reasoning as the numerals */
:where(.sl-body).refine-luxe-noir .comp-statement .why-row + .why-row::before, :where(.sl-body).refine-luxe-noir .comp-statement .steps-row:not(.steps-photo) > .step-card + .step-card::before {
  content: '◆';
  display: inline-block;
  color: var(--c-accent-ink, var(--c-accent));
  font-size: 0.5rem;
  line-height: 1;
  margin: 0 0.95rem;
  transform: translateY(-2px);
}
:where(.sl-body).refine-luxe-noir .comp-statement .steps-connected::before { display: none; }

/* ══ DESIGN LANE: clinical-porcelain ══════════════════════════════════════════════════════
   Second med spa lane (DESIGN-LANES.md, build order #2). Bright precision: geometric sans
   from the brand's body family at a tight compact scale, square corners, flat white
   surfaces, hairline neutral dividers, dense grids — and NO alternating tints: sections
   sit on continuous white separated by hairline rules. Opt-in via
   theme.refinement='clinical-porcelain'; fully scoped, palette-token-driven.
   Contrast math (MK seed palette, computed 2026-07-30): text on white 13.76:1 · muted on
   white 5.98:1 (eyebrows/labels) · white on primary buttons 12.43:1 · white on flat
   primary_dark CTA 15.79:1 · primary_dark on accent 6.59:1. All >= 4.5.  ═══════════════ 
   @lane clinical-porcelain | bright precision: geometric sans, flat white, hairline dividers | suits: clinical precise medical trust sterile technical accurate professional
   */
:where(.sl-body).refine-clinical-porcelain {
  --card-radius: 14px;
  --btn-radius: 999px;
  --card-shadow: none;
  --card-hover-shadow: none;
  /* the CTA block flattens from a gradient to one exact dark — trust, not theatre */
  --c-cta-bg: var(--c-primary-dark);
  /* inline-styled eyebrows (pricing etc.) read this: small neutral tracked-caps labels.
     .final-cta re-declares its own --eyebrow-ink for its dark ground, and wins there. */
  --eyebrow-ink: var(--c-text-muted);
}

/* 1. BANDS — continuous white. The page is painted ONCE (body -> surface) and the
   sections go transparent, which beats the even/4n tint washes on specificity; the :not()
   chain leaves alone everything that is dark by construction (map band, stats, CTA).
   Transparent-over-one-stock rather than white-painted-per-section on purpose: the lane's
   claim is that sections are NOT bands, and the silhouette fingerprint reads a painted
   section as banded no matter its colour. Visually identical; structurally honest. */
:where(.sl-body).refine-clinical-porcelain { background: var(--c-surface); }
/* …AND NOT THE TRUST BAND. `.comp-trust-band` is a PLATE — it paints the brand dark and sets
   white ink on itself in the same rule — so repainting its ground with the page stock leaves
   the white ink on paper. The house rules exclude it from every band beat for this reason;
   this one did not. `.block-route-section` is excluded on the same grounds. */
:where(.sl-body).refine-clinical-porcelain.sections-alternate main > section.section:nth-of-type(n):not(.section-service_area_map):not(.section-stats):not(.section-tier_comparison):not(.section-ingredient_choice):not(.final-cta):not(.section-hub-cta):not(.comp-trust-band):not(.block-route-section):not(.sec-room):not(.sec-photo) {
  background: transparent;
}
/* Hairline rules do the separating (the divider the tint rhythm removed). */
:where(.sl-body).refine-clinical-porcelain .section + .section, :where(.sl-body).refine-clinical-porcelain.sections-alternate .section + .section {
  border-top: 1px solid var(--c-border);
}

/* 2. TYPE — geometric sans everywhere, compact scale, sentence-case headlines (the copy
   is already sentence case; nothing here transforms it). */
:where(.sl-body).refine-clinical-porcelain h1, :where(.sl-body).refine-clinical-porcelain h2, :where(.sl-body).refine-clinical-porcelain h3, :where(.sl-body).refine-clinical-porcelain h4, :where(.sl-body).refine-clinical-porcelain h5, :where(.sl-body).refine-clinical-porcelain h6 { font-family: var(--font-body); letter-spacing: -0.01em; }
:where(.sl-body).refine-clinical-porcelain .lead-form-title, :where(.sl-body).refine-clinical-porcelain .contact-col-title, :where(.sl-body).refine-clinical-porcelain .step-badge, :where(.sl-body).refine-clinical-porcelain .stat-value, :where(.sl-body).refine-clinical-porcelain .coverage-index-list.is-marquee li { font-family: var(--font-body); }
:where(.sl-body).refine-clinical-porcelain h1 { font-size: clamp(2rem, 4vw, 2.9rem); }
:where(.sl-body).refine-clinical-porcelain .hero-inner h1 { font-size: clamp(2.1rem, 4.2vw, 3.1rem); line-height: 1.12; }
:where(.sl-body).refine-clinical-porcelain h2 { font-size: clamp(1.5rem, 2.5vw, 1.95rem); }
:where(.sl-body).refine-clinical-porcelain .section-header h2 { font-size: clamp(1.5rem, 2.5vw, 1.95rem); }
:where(.sl-body).refine-clinical-porcelain h3 { font-size: 1.05rem; }
:where(.sl-body).refine-clinical-porcelain .section-header p { font-size: 0.98rem; }
:where(.sl-body).refine-clinical-porcelain .final-cta h2 { font-size: clamp(1.7rem, 3vw, 2.3rem); }

/* Small tracked-caps labels. Typography via !important to reach inline-styled eyebrows;
   color only where the ground is known light — dark grounds keep their own rules. */
:where(.sl-body).refine-clinical-porcelain .eyebrow {
  font-family: var(--font-body);
  font-weight: 600 !important;
  font-size: 0.7rem !important;
  letter-spacing: 0.14em !important;
  text-transform: uppercase;
}
:where(.sl-body).refine-clinical-porcelain .section-header .eyebrow { color: var(--c-text-muted); }
/* Dark-ground guards for the label recolor above (stats band renders its eyebrow inside
   a .section-header; ingredient/tier are IV dark bands a med spa page could inherit). */
:where(.sl-body).refine-clinical-porcelain .section-stats .eyebrow, :where(.sl-body).refine-clinical-porcelain .section-ingredient_choice .eyebrow, :where(.sl-body).refine-clinical-porcelain .section-tier_comparison .eyebrow { color: var(--c-accent-ink-dark); }

/* 3. COMPOSITION — left-set headers over left-set grids, applied uniformly (mirrors the
   proven body.hdr-left composition; R8's carve-outs for hero/final CTA kept verbatim). */
:where(.sl-body).refine-clinical-porcelain .section-header {
  text-align: left;
  margin-left: 0;
  margin-right: auto;
  max-width: 52ch;
  margin-bottom: 1.4rem;
}
:where(.sl-body).refine-clinical-porcelain .section-header .eyebrow { margin-left: 0; }
:where(.sl-body).refine-clinical-porcelain .cards-center, :where(.sl-body).refine-clinical-porcelain .auto-items, :where(.sl-body).refine-clinical-porcelain .why-rows, :where(.sl-body).refine-clinical-porcelain .steps-row, :where(.sl-body).refine-clinical-porcelain .cat-grid { justify-content: flex-start; }
:where(.sl-body).refine-clinical-porcelain .hero .section-header, :where(.sl-body).refine-clinical-porcelain .section-final_cta .section-header {
  text-align: center;
  margin-left: auto;
  max-width: none;
}

/* 4. DENSITY — the clinical rhythm is compact. */
:where(.sl-body).refine-clinical-porcelain .section { padding: clamp(1.8rem, 3.4vw, 2.75rem) 0; }
:where(.sl-body).refine-clinical-porcelain .section-trust_strip { padding-top: 1.35rem; padding-bottom: 1.35rem; }
:where(.sl-body).refine-clinical-porcelain .cards-center, :where(.sl-body).refine-clinical-porcelain .auto-items, :where(.sl-body).refine-clinical-porcelain .cat-grid, :where(.sl-body).refine-clinical-porcelain .grid { gap: 1rem; }
:where(.sl-body).refine-clinical-porcelain .why-rows { gap: 0.6rem; }
/* THE FEATURED TIER IS A PLATE THIS LANE MUST NOT ERASE. `.tier-card.tier-featured` (interior
   route) and `.bk-tier.bk-feat` (block library) are both a DARK PLATE with WHITE type set in their
   own component. A generic card rule reaches them, strips the plate and leaves the ink, which is
   white on pale. Two lanes shipped exactly that this week and one was caught only by the contrast
   gate. Excluded here rather than restated, because this lane has nothing of its own to say about
   a featured tier. */
:where(.sl-body).refine-clinical-porcelain .card:not(.tier-featured) { padding: 1.2rem 1.3rem; }
:where(.sl-body).refine-clinical-porcelain .auto-item { padding: 1.05rem 1.15rem; }
:where(.sl-body).refine-clinical-porcelain .why-row { padding: 1.05rem 1.3rem; }
:where(.sl-body).refine-clinical-porcelain .hero { padding: 3rem 0; }
/* This family's hero is a band, not a stage — deliberately shorter than the house. One lever,
   not another height: it takes three quarters of what the fold allows. */
:where(.sl-body).refine-clinical-porcelain .hero-image-bg { --sl-hero-fill: 0.76; }

/* 5. SHAPE — flat white cells ruled by neutral hairlines; every disc becomes a square. */
:where(.sl-body).refine-clinical-porcelain .card, :where(.sl-body).refine-clinical-porcelain .auto-item, :where(.sl-body).refine-clinical-porcelain .why-row, :where(.sl-body).refine-clinical-porcelain .cat-card, :where(.sl-body).refine-clinical-porcelain .prepaft-col, :where(.sl-body).refine-clinical-porcelain .contact-method, :where(.sl-body).refine-clinical-porcelain .lead-form-card {
  border-radius: 0;
  border: 1px solid var(--c-border);
  box-shadow: none;
}
:where(.sl-body).refine-clinical-porcelain.cards-elevated .card:hover { box-shadow: none; transform: none; border-color: var(--c-text-muted); }
:where(.sl-body).refine-clinical-porcelain .cat-card:hover, :where(.sl-body).refine-clinical-porcelain .contact-method:hover { transform: none; box-shadow: none; border-color: var(--c-text-muted); }
:where(.sl-body).refine-clinical-porcelain .cat-ic, :where(.sl-body).refine-clinical-porcelain .trust-row-item .trust-ic, :where(.sl-body).refine-clinical-porcelain .why-row-ic, :where(.sl-body).refine-clinical-porcelain .auto-card .feature-ic, :where(.sl-body).refine-clinical-porcelain .step-badge { border-radius: 0; }
:where(.sl-body).refine-clinical-porcelain .lead-field input, :where(.sl-body).refine-clinical-porcelain .lead-field textarea { border-radius: 0; }

/* 6. BUTTONS — solid, square, exact. White on primary 12.43:1. */
:where(.sl-body).refine-clinical-porcelain .btn {
  border-radius: 0;
  padding: 0.68rem 1.3rem;
  font-size: 0.92rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  box-shadow: none;
}
:where(.sl-body).refine-clinical-porcelain .hero .btn { padding: 0.8rem 1.5rem; font-size: 0.95rem; }

/* 7. FLAT DARKS — the two functional dark moments stay, but as exact fields, not washes:
   the CTA loses its radial accent glow (flat primary_dark via --c-cta-bg above), the
   coverage band loses the radial+linear stack and svg drop shadow, the hub hero gradient
   becomes one field. White on flat primary_dark: 15.79:1. */
:where(.sl-body).refine-clinical-porcelain .final-cta::after { display: none; }
/* Same hub-CTA fix as luxe-noir: bare .btn-secondary on the (now flat, now measurable)
   dark block defaults to primary ink at 1.27:1. Solid accent primary / surface outline. */
:where(.sl-body).refine-clinical-porcelain .final-cta .btn-primary {
  background: var(--c-accent);
  border-color: var(--c-accent);
  color: var(--c-primary-dark);
}
:where(.sl-body).refine-clinical-porcelain .final-cta .btn-primary:hover { background: color-mix(in srgb, var(--c-accent) 85%, var(--c-surface)); color: var(--c-primary-dark); }
/* The secondary outline was pinned here too, and the comment above says out loud where it came
   from — "same hub-CTA fix as luxe-noir". It was the third writing of one sentence, and dead for
   the same reason luxe-noir's was: the shared dark-ground guard below restates it at the same
   specificity, later, reading `--c-cta-text` instead of naming the paper colour. Deleted; the
   hover stays. */
:where(.sl-body).refine-clinical-porcelain .final-cta .btn-secondary:hover { background: var(--c-light-stock); color: var(--c-primary-dark); }
/* Same guard, same reason as dark-luxe (:4660) and luxe-noir above: without it this (0,3,3)
   !important rule outspecifies the light map compositions at :587 and buries their ink. No
   porcelain site sets map-index today, so this is a latent fix, not a visual change. */
:where(.sl-body).refine-clinical-porcelain:not(.map-index):not(.map-panel) main > section.section.section-service_area_map {
  background: var(--c-hero-plate) !important;
}
:where(.sl-body).refine-clinical-porcelain .coverage-map-col .cm-svg { filter: none; }
:where(.sl-body).refine-clinical-porcelain .hero-gradient { background: var(--c-hero-plate); }

/* ══ pill-porcelain ═══════════════════════════════════════════════════════════════════════════
   THE DEVICE IS THE SPEECH BUBBLE, LIFTED OUT OF THE LOGO. Mobile IV Near Me's mark is a
   wordmark sitting on a solid pink bar with a wedge off its bottom-left, and their brand book
   (Vol 1 2026, p12) explicitly licenses that bar to be reused on its own as "a pink pill holding
   a short line ... tail on the bottom-left, Poppins Bold in white, never more than four words".
   So every eyebrow on the site becomes that bubble. Nothing else in the fleet has it, and it is
   the one shape a viewer already associates with this brand before reading a word.

   Authored rather than assigned: clinical-porcelain was the only unused stock lane, and it sets
   --card-radius:0, --btn-radius:0, --card-shadow:none and pushes h1-h6 onto the BODY font. All
   four are direct contradictions of written rules in this brand book ("999px for actions, 16px
   for cards", "One shadow: 0 2px 10px rgba(38,34,48,.05)", "Poppins is the voice of the brand:
   display, headlines, buttons, labels"). The two dark lanes contradict the book's stated 60%
   white-and-Mist ratio, and spa-luxe is worn by Halo IV Wellness in this same vertical and
   contradicts "Never a wellness gimmick".

   CONTRAST, MEASURED 2026-08-09, and this is the one place the lane deliberately departs from
   the book. The book's own pairings panel prints "White on Pink 4.1:1 - large text & UI only";
   the real figure is 3.77:1, and either way it is below the 4.5:1 needed for normal-size text.
   The brand's signature is a pink button, so rather than abandon it this lane makes it legal:
     - PRIMARY BUTTONS keep IV Pink and their label is set at 1.2rem/700. Bold >= 18.66px is
       WCAG "large text", where the threshold is 3.0, so 3.77:1 passes. One big confident pink
       button also happens to be exactly what the book asks for ("One pink button per view").
     - SMALL PINK LABELS (the eyebrow pills) use Raspberry #C81657 instead, which is an in-palette
       brand colour and lands at 5.66:1 white-on-fill. Reading as the same pink family, legal at
       label size. IV Pink is never asked to carry text below 18.66px anywhere in this lane.
   Verified safe and used freely: Ink on white 15.51:1, white on Ink 15.51:1, Ink on Mist 13.83:1,
   Ink on Blush 12.99:1.  ═══════════════════════════════════════════════════════════════════ 
   @lane pill-porcelain | a pink speech-bubble eyebrow on a mostly-white page | suits: friendly approachable bubbly modern franchise national playful chatty
   */
:where(.sl-body).refine-pill-porcelain {
  --card-radius: 16px;
  --btn-radius: 999px;
  --input-radius: 12px;
  /* The book allows exactly one shadow, and this is it. Everything else separates by spacing. */
  --card-shadow: 0 2px 10px rgba(38, 34, 48, .05);
  --card-hover-shadow: 0 6px 18px rgba(38, 34, 48, .09);
  --pp-bubble: #C81657;
  --pp-ease: 160ms ease-out;
  /* The bubble has to be set as TOKENS, not just as a .eyebrow rule. accent_mode:badge emits
     `body.bands-paper.adacc-badge main > section.section .section-header .eyebrow`, specificity
     (0,5,2) against a lane's (0,2,1), and paints a white chip. It reads --eyebrow-chip and
     --eyebrow-ink, so setting those turns the device on THROUGH that rule instead of fighting it,
     and the inline-styled eyebrows (final_cta) that read the same vars come along for free. */
  --eyebrow-chip: var(--pp-bubble);
  --eyebrow-ink: #fff;
}

/* 1. SURFACES, the 60/22/15 ratio is a stated brand rule, so the page is mostly white and Mist
      and pink is rationed. Bands alternate white and Mist with no rules and no shadows between
      them; the change of stock is the divider. */
:where(.sl-body).refine-pill-porcelain { background: var(--c-surface); }
/* BOTH BEATS, NOT ONE. This lane declared only the even band. A brand whose default ground IS a
   tint then alternates tint with tint, and the page-rules P3 check refuses the build — the fault
   costs five listing pages at once and has been paid for twice in this file. The odd beat and the
   bands-paper rhythm are named explicitly here so neither can fall through to the page default. */
:where(.sl-body).refine-pill-porcelain.sections-alternate main > section.section:nth-of-type(odd):not(.section-service_area_map):not(.section-stats):not(.final-cta):not(.section-hub-cta):not(.sec-room):not(.sec-photo), :where(.sl-body).refine-pill-porcelain.bands-paper main > section.section:nth-of-type(odd):not(.section-service_area_map):not(.section-stats):not(.final-cta):not(.section-hub-cta):not(.sec-room):not(.sec-photo) {
  background: var(--c-surface);
}
:where(.sl-body).refine-pill-porcelain.sections-alternate main > section.section:nth-of-type(even):not(.section-service_area_map):not(.section-stats):not(.final-cta):not(.section-hub-cta), :where(.sl-body).refine-pill-porcelain.bands-paper main > section.section:nth-of-type(even):not(.section-service_area_map):not(.section-stats):not(.final-cta):not(.section-hub-cta):not(.sec-room):not(.sec-photo) {
  background: var(--c-surface-alt);
}
:where(.sl-body).refine-pill-porcelain .section + .section { border-top: 0; }

/* 2. TYPE, Poppins carries every heading (the book's rule, and the lane exists partly because
      the stock porcelain lane broke it). Sentence case is already how the copy is written, so
      nothing here transforms it. The 68-character measure is also the book's number. */
:where(.sl-body).refine-pill-porcelain h1, :where(.sl-body).refine-pill-porcelain h2, :where(.sl-body).refine-pill-porcelain h3, :where(.sl-body).refine-pill-porcelain h4 {
  font-family: var(--font-headline, var(--font-heading));
  font-weight: 800;
  letter-spacing: -0.015em;
  text-transform: none;
}
:where(.sl-body).refine-pill-porcelain .section-header p, :where(.sl-body).refine-pill-porcelain .hero-inner p { max-width: 68ch; }

/* 3. THE BUBBLE. Every eyebrow becomes the logo's bar: a pink pill with the wedge tucked one
      radius in from the left edge, pointing down and left, exactly as the anatomy page draws it.
      Raspberry rather than IV Pink for the contrast reason in the header note. */
:where(.sl-body).refine-pill-porcelain .eyebrow {
  display: inline-block;
  position: relative;
  background: var(--pp-bubble);
  color: #fff;
  font-family: var(--font-headline, var(--font-heading));
  font-weight: 700;
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 0.42rem 0.95rem 0.44rem;
  border-radius: 999px;
  border: 0;
  margin-bottom: 1.15rem;
  line-height: 1;
}
/* THE TAIL. Two things were wrong in the first cut and both showed:
   1. It was clipped `polygon(100% 0, 100% 100%, 0 100%)`, which puts the vertical edge on the
      RIGHT and slopes away to the left, so the wedge read as pointing down-right. The logo does
      the opposite: the left edge continues straight down off the bar and the hypotenuse runs back
      up to the right, so the point lands at the bottom LEFT.
   2. It was offset with `bottom: -0.33rem`, which parks it BELOW the pill. The pill is a 999px
      radius, so its bottom-left corner is already curving away at that x, and the result was a
      visible gap: a detached floating triangle rather than a tail.
   Fixed by flipping the polygon and starting the wedge INSIDE the pill (top: calc(100% - 4px)),
   so the two shapes always share fill no matter the font size. Colour comes from the same token
   the pill uses, so the dark-band inversion carries automatically and needs no separate rule. */
:where(.sl-body).refine-pill-porcelain .eyebrow::after {
  content: '';
  position: absolute;
  left: 0.95rem;
  top: calc(100% - 4px);
  width: 0.7rem;
  height: 0.52rem;
  background: var(--eyebrow-chip, var(--pp-bubble));
  clip-path: polygon(0 0, 100% 0, 0 100%);
}
/* On a dark band a raspberry chip only reaches 2.74:1 against Ink and reads muddy, so the bubble
   inverts to white with Ink text (15.51:1). Done by overriding the TOKENS on the container rather
   than restyling .eyebrow: CSS variables resolve from the element's own cascade, so this reaches
   the inline-styled eyebrows too, which a .eyebrow rule cannot (they would stay white-on-white).
   The selector has to outweigh the dark-band token block at :4253, which rebinds --eyebrow-chip
   to a 9% white wash from `body.bands-paper main > section.section.sec-room`. A plain
   `.lane .sec-room` loses to that silently. */
:where(.sl-body).refine-pill-porcelain.bands-paper main > section.section.sec-room, :where(.sl-body).refine-pill-porcelain.bands-paper main > section.section.sec-bg-photo, :where(.sl-body).refine-pill-porcelain .final-cta {
  --eyebrow-chip: #fff;
  --eyebrow-chip-edge: #fff;
  --eyebrow-ink: var(--c-primary-dark);
}
:where(.sl-body).refine-pill-porcelain .sec-room .eyebrow, :where(.sl-body).refine-pill-porcelain .final-cta .eyebrow, :where(.sl-body).refine-pill-porcelain .sec-bg-photo .eyebrow {
  background: #fff;
  color: var(--c-primary-dark);
}
/* No ::after override needed here: the tail paints from --eyebrow-chip, which these containers
   already rebind, so it inverts with the pill. One source of truth, so they cannot drift apart. */

/* 4. ACTIONS, fully round, one pink button per view. The primary label is deliberately large
      (see header note: that is what makes white-on-pink legal). Secondary is an Ink outline so a
      second pink never appears beside it. */
:where(.sl-body).refine-pill-porcelain .btn {
  border-radius: 999px;
  font-family: var(--font-headline, var(--font-heading));
  font-weight: 700;
  min-height: 48px;
  padding: 0.8rem 1.7rem;
  transition: background var(--pp-ease), box-shadow var(--pp-ease), color var(--pp-ease);
  box-shadow: none;
}
/* The size here is an ACCESSIBILITY FLOOR, not taste. White on IV Pink is 3.77:1, which is under
   the 4.5:1 AA needs for normal text but over the 3.0 AA needs for large text, and WCAG counts
   bold >= 18.66px as large. 1.2rem/700 = 19.2px clears it, so the brand keeps its signature pink
   button legally. !important because responsive `.hero .btn` rules inside media queries reset the
   size and silently drop it back to 16px, which is the failing case. If this ever gets loosened,
   the button has to go Raspberry (5.66:1) instead. */
:where(.sl-body).refine-pill-porcelain .btn-primary{
  background: var(--c-accent);
  /* NOT #fff. The note above is true of the accent this lane was DRAWN for and of nothing else:
     white clears large-text AA on that deep pink at 3.77:1, and lands at 1.86:1 on the amber accent
     of the first other brand to wear the lane — the header booking button on every page of the
     site, unreadable. `--c-accent-on` is the site's own answer to "what ink reads on my accent",
     computed from its palette in brand.ts, so a pink brand still gets white here and an amber one
     gets its own near-black. The size floor below stays: it is what makes white-on-pink legal
     where white is what the brand's own accent asks for. */
  color: var(--c-accent-on, #fff);
  font-size: 1.2rem !important;
  font-weight: 700 !important;
  border: 0;
}
:where(.sl-body).refine-pill-porcelain .btn-primary:hover{ background: var(--pp-bubble); }
/* ONE PINK BUTTON PER VIEW (book, p14), and the header's is sticky, so if IT is pink then
   every in-page CTA makes two. The page's own action keeps the pink; the persistent chrome
   goes Ink (15.51:1 with white). At every scroll position exactly one pink button is visible. */
:where(.sl-body).refine-pill-porcelain .site-header .btn, :where(.sl-body).refine-pill-porcelain .header-book {
  background: var(--c-primary);
  color: #fff;
  font-size: 1rem;
  border: 0;
}
:where(.sl-body).refine-pill-porcelain .site-header .btn:hover, :where(.sl-body).refine-pill-porcelain .header-book:hover { background: var(--c-primary-dark); }
/* ── A LANE MAY SHAPE A CONTROL. IT MAY NOT COLOUR ONE WHOSE GROUND IT DOES NOT OWN. ───────────
   `.btn-secondary` inks itself `--c-primary`, and the shared rules above rebind it to the surface
   ink wherever it lands on a dark ground — a photographic hero, a gradient hero, a closing band.
   A lane rule written as `body.refine-x .btn-secondary` is (0,2,1) and beats `.hero-image-bg
   .btn-secondary` at (0,2,0), so the lane silently takes the ink back on exactly the grounds that
   needed it changed.
   Measured on a cold-start client whose palette is a deep green: "Call Us" in the hero of all five
   listing pages came out at 1.1:1 — the brand green on the brand-dark hero, invisible — on desktop
   and phone, caught by two gates at once. The same shape is already on record as CHIdrate's navy
   label on navy.
   So the dark grounds are named back, once, ahead of every lane. This is the ground-aware rule
   restated at a specificity a lane cannot outrank; the lanes keep their shape, their border and
   their hover, and lose only the right to be unreadable.
   NAMED BACK AS A HAND-TYPED LIST OF TEN LANES, WHICH MADE THE GUARD THE THING THAT DRIFTS. Four
   lanes on the shelf were authored after this line and never added to it, so a third of the
   fourteen stood outside the rule that exists to protect them, and every lane written from here
   on would have stood outside it too. Nothing was wrong on a built page: those four ink their
   outline in currentColor and set no colour of their own, so they already resolved to exactly
   this pairing. What was wrong was the guard, which would not have fired for the next lane author
   who wrote a bare `color:` on a secondary button — which four of the ten listed lanes did, and
   which is how the 1.1:1 above came to be measured. The form its own neighbour twenty lines below
   already uses needs no list, so it is used here: the class name is MATCHED, not enumerated, and
   the specificity is unchanged at (0,3,1) because an attribute selector weighs the same as a
   class. Every lane present and future is covered, and there is nothing left to keep in step. */
:where(.sl-body)[class*="refine-"]
  :is(.hero-image-bg, :where(.sl-body) .hero-video, :where(.sl-body) .hero-gradient, :where(.sl-body) .final-cta, :where(.sl-body) .section-hub-cta) .btn-secondary {
  color: var(--c-cta-text, var(--c-surface));
  border-color: var(--c-cta-text, var(--c-on-dark));
}

/* ── THE SAME RULE, POINTING AT A PLATE INSTEAD OF AN INK ──────────────────────────────────────
   The membership band's featured tier is a DARK PLATE carrying WHITE TEXT, and the two are set in
   the block, in two separate declarations, at the specificity Astro's scoping gives them (0,2,0).
   Every lane in this file writes a generic card rule - `body.refine-x .bk-tier { background: ... }`
   - which is (0,2,1). So a lane repaints the plate, the white ink stays, and the tier ships white
   text on the lane's pale card. Two lanes did it: warm-studio was caught by the contrast check on
   its first build (1.07:1, "EFFECTIVELY INVISIBLE"), and editorial-ivory has been doing it on a
   live page since it was written, because the rules it wrote to handle the featured tier name
   `[data-featured]` and `.is-featured` - two selectors the block does not emit. Dead CSS reads
   exactly like handled CSS.

   So the plate is restated here, once, ahead of every lane, at a specificity a lane's generic card
   rule cannot reach. A lane that genuinely means to restyle the featured tier still can: name it
   the way the block does, as `.bk-tier.bk-feat`, and the pairing clears this guard. Naming the
   thing you are changing is the price of changing it. */
:where(.sl-body)[class*="refine-"] .bk-tier.bk-feat {
  background: var(--bk-dark, #16232c);
  color: #fff;
}

:where(.sl-body).refine-pill-porcelain .btn-secondary {
  background: transparent;
  color: var(--c-primary);
  border: 1.5px solid var(--c-primary);
  font-size: 1rem;
}
:where(.sl-body).refine-pill-porcelain .btn-secondary:hover {
  background: var(--c-primary);
  color: #fff;
}
:where(.sl-body).refine-pill-porcelain input, :where(.sl-body).refine-pill-porcelain select, :where(.sl-body).refine-pill-porcelain textarea { border-radius: 12px; }
/* A row of drip cards ships one pink button EACH, which is six pink pills in one band and the
   loudest possible breach of "one pink button per view". The card is already a link, so these
   only need to read as affordances: Ink outline. The pink in this band is the price. */
:where(.sl-body).refine-pill-porcelain .pkg-book {
  background: transparent;
  color: var(--c-primary);
  border: 1.5px solid var(--c-primary);
  font-size: 0.95rem;
}
:where(.sl-body).refine-pill-porcelain .pkg-book:hover { background: var(--c-primary); color: #fff; }
/* The price is where the accent lives in this band. Raspberry, not IV Pink: it is small text. */
:where(.sl-body).refine-pill-porcelain .pkg-price-amt, :where(.sl-body).refine-pill-porcelain .pkg-price { color: var(--pp-bubble); }

/* 4b. LOCKUP MINIMUM SIZE. The book sets a hard floor for the primary lockup: 120px wide on
   digital, below which "near me" fills in and you are supposed to switch to the circle mark.
   The stock header caps the logo at 44px tall, and this lockup is 2.14:1, so it was landing at
   81px wide, a third under the floor. 60px tall puts it at ~128px. */
/* The header <img> is emitted with width="180" height="44" as generic layout-shift hints, but this
   lockup is 848x397 (2.14:1), not 4.09:1. With the global `img { height: auto }` the browser sizes
   from those ATTRIBUTES, then `object-fit: contain` letterboxes the real artwork inside the wrong
   shaped box, so the visible mark was far smaller than its own element and a min-width only ever
   grew the empty box around it. `aspect-ratio: auto` tells it to use the image's real proportions,
   after which one explicit height gives an exact, undistorted size. Ian: the logo was too small.
   Never reach for min-width here: that stretches, and stretching the lockup is misuse rule 01. */
:where(.sl-body).refine-pill-porcelain .site-header .logo, :where(.sl-body).refine-pill-porcelain .site-header .logo img{
  max-width: none;
}
:where(.sl-body).refine-pill-porcelain .site-header .logo img{
  /* Both axes pinned, at the artwork's real 2.135:1, because leaving either to `auto` let the
     element fall back to the width="180" height="44" attributes and collapse to 81x38. Stating
     both is also the only way to guarantee the ratio, and a stretched lockup is misuse rule 01. */
  aspect-ratio: auto !important;
  height: 66px !important;
  width: 141px !important;
  max-height: none !important;
  max-width: none !important;
  min-width: 0;
  object-fit: contain;
}
@media (max-width: 640px) {
  :where(.sl-body).refine-pill-porcelain .site-header .logo img {
    height: 44px !important;
    width: 94px !important;
  }
}
/* Same floor in the footer. That img carries an inline max-height:40px (Footer.astro sets the
   style so it can drop the invert filter for an authored dark lockup), so beating it needs
   !important. Scoped to this lane, so no other client's footer moves. */
:where(.sl-body).refine-pill-porcelain .site-footer .footer-brand img {
  max-height: 58px !important;
  min-width: 120px;
  width: auto;
}

/* 5. CARDS, 16px, one shadow, no borders competing with it. */
:where(.sl-body).refine-pill-porcelain .card, :where(.sl-body).refine-pill-porcelain .whyus-card, :where(.sl-body).refine-pill-porcelain .cat-card, :where(.sl-body).refine-pill-porcelain .addon-card, :where(.sl-body).refine-pill-porcelain .wpkg-card, :where(.sl-body).refine-pill-porcelain .tier-card:not(.tier-featured), :where(.sl-body).refine-pill-porcelain .faq-item, :where(.sl-body).refine-pill-porcelain .team-member-card, :where(.sl-body).refine-pill-porcelain .pkg-card {
  border-radius: 16px;
  box-shadow: 0 2px 10px rgba(38, 34, 48, .05);
  border: 0;
  background: var(--c-surface);
  transition: box-shadow var(--pp-ease);
}
/* A PLATE OWNS ITS PADDING AND ITS NEIGHBOURS' AIR. Every card in the list above pads itself
   except .faq-item — the base accordion pads 1.15rem VERTICALLY ONLY because its rows sit bare on
   the page. Porcelain-plating them without an inset put the question flush against a 16px-radius
   plate, and without a margin the plates stacked touching — the owner-reported bubble defect. The
   :7279 city_faq grid handles its own spacing, hence the :not(); margins inside that grid would
   double its 0.65rem gap. */
:where(.sl-body).refine-pill-porcelain main > section.section:not(.section-city_faq) .faq-item {
  padding: 0.1rem clamp(1.05rem, 2vw, 1.4rem);
}
:where(.sl-body).refine-pill-porcelain main > section.section:not(.section-city_faq) .faq-item + .faq-item {
  margin-top: 0.65rem;
}
:where(.sl-body).refine-pill-porcelain.sections-alternate main > section.section:nth-of-type(even) .card, :where(.sl-body).refine-pill-porcelain.sections-alternate main > section.section:nth-of-type(even) .whyus-card, :where(.sl-body).refine-pill-porcelain.sections-alternate main > section.section:nth-of-type(even) .cat-card, :where(.sl-body).refine-pill-porcelain.sections-alternate main > section.section:nth-of-type(even) .addon-card {
  background: #fff;
}
/* 6. MOTION, the book allows 160ms ease-out and forbids bounce and parallax, so hover lifts are
      shadow-only. No card in this lane translates, scales or rotates. */
:where(.sl-body).refine-pill-porcelain .card:hover, :where(.sl-body).refine-pill-porcelain .cat-card:hover, :where(.sl-body).refine-pill-porcelain .addon-card:hover, :where(.sl-body).refine-pill-porcelain .wpkg-card:hover, :where(.sl-body).refine-pill-porcelain .pkg-card:hover {
  transform: none;
  box-shadow: 0 6px 18px rgba(38, 34, 48, .09);
}

/* 6b. THE ADD IN LIST. This brand publishes all 21 add ins, which is the point ("published so you
      can read it before you book"), but the stock treatment resolves .addon-grid to display:block
      with full width cards, so 21 items became a 2255px wall of identical rows and the page read
      as one endless scroll. Same information, three columns: about seven rows instead of 21.
      Nothing is hidden or truncated, which matters because the whole claim is that the list is
      complete. Ian, staging review round 1. */
:where(.sl-body).refine-pill-porcelain .section-addons_boosters_grid .addon-grid {
  display: grid !important;
  grid-template-columns: repeat(auto-fit, minmax(252px, 1fr));
  gap: 0.55rem 1.1rem;
  align-items: stretch;
}
:where(.sl-body).refine-pill-porcelain .section-addons_boosters_grid .addon-card {
  width: auto !important;
  flex: initial !important;
  padding: 0.7rem 0.9rem;
  border-radius: 12px;
}
/* Three columns makes the cards narrow, and the long names in this list ("Dexamethasone
   (Decadron)", "Reglan (Metoclopramide)") then collide with the price: a flex item defaults to
   min-width:auto, so the name refuses to shrink below its content width and shoves the +$30 out
   of the card. min-width:0 lets it wrap; the price is pinned no-shrink so it always stays inside
   its column and on one line. */
:where(.sl-body).refine-pill-porcelain .section-addons_boosters_grid .addon-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 0.55rem;
  flex-wrap: nowrap;
}
:where(.sl-body).refine-pill-porcelain .section-addons_boosters_grid .addon-name {
  font-size: 0.92rem;
  line-height: 1.25;
  flex: 1 1 auto;
  min-width: 0;
  overflow-wrap: anywhere;
}
:where(.sl-body).refine-pill-porcelain .section-addons_boosters_grid .addon-pill {
  flex: 0 0 auto;
  white-space: nowrap;
}
/* The stock dark-band treatment for this section is a leader-dot menu: `name ······· price`, with
   `.addon-name { white-space: nowrap }` so the name holds one line and the dots stretch. That is
   the right look full width and impossible at a third of it, and because it is specificity (0,5,3)
   it beat the wrap rules above and let the long names run under their own price. Matching its
   selector shape to outweigh it, then dropping the dots: a 250px column has no room for a dotted
   run, and name-left / price-right is legible without it. This is NOT made redundant by the shared
   unwrap the menu now carries: that one only fires below 560px, and this lane needs the name to
   wrap at every width, because its columns are 252px wide on a desktop. */
:where(.sl-body).refine-pill-porcelain.bands-paper main > section.section.section-addons_boosters_grid:nth-of-type(n) .addon-name {
  white-space: normal;
  overflow-wrap: anywhere;
  font-size: 0.92rem;
  order: 0;
}
:where(.sl-body).refine-pill-porcelain.bands-paper main > section.section.section-addons_boosters_grid:nth-of-type(n) .addon-head {
  justify-content: space-between;
  align-items: baseline;
  gap: 0.55rem;
}
:where(.sl-body).refine-pill-porcelain.bands-paper main > section.section.section-addons_boosters_grid:nth-of-type(n) .addon-head::after {
  display: none;
}
:where(.sl-body).refine-pill-porcelain .section-addons_boosters_grid .addon-desc {
  font-size: 0.8rem;
  line-height: 1.4;
  margin-top: 0.2rem;
}

/* 7. NUMBERED STEPS, the step badge is the bubble again, at its smallest, so the five-step
      "How it works" rail reads as the same device rather than a generic numbered circle. */
:where(.sl-body).refine-pill-porcelain .step-badge {
  background: var(--pp-bubble);
  color: #fff;
  border-radius: 999px;
  border: 0;
  font-family: var(--font-headline, var(--font-heading));
  font-weight: 700;
}

/* 8. TINT PANELS, Blush is the book's callout stock, and Ink on it is 12.99:1. */
:where(.sl-body).refine-pill-porcelain .callout{
  background: var(--c-surface-alt-2, #FFE4EE);
  color: var(--c-primary-dark);
  border-radius: 16px;
  border: 0;
}

/* ── pill-porcelain, pass 2: five bands Ian called out on staging ─────────────────────────────
   All five are the same complaint in different clothes: a band that renders correctly, holds real
   content, and still reads as unfinished because the content sits in one strip and the rest of the
   width is empty. None of them would ever fail a gate.  ───────────────────────────────────── */

/* A. HOW IT WORKS, put the bubble back. comp-panel lays each step out as a two column grid
      (title | body) and hides .step-badge outright (:7860), which leaves a wide empty gutter on
      the left of every row: "it just looks kind of plain". The badge is already in the DOM with
      the step number in it, so this only has to un-hide it, give it a leading column, and dress it
      as the brand's bubble. Ian asked for "some sort of pink icon" there, and the numbered pink
      pill is the device this whole lane is built on. */
/* process_timeline.vertical-rail caps the row at `max-width:540px!important` and centres it. Inside
   a full width panel that leaves a wide empty gutter on BOTH sides and squeezes the body copy into
   about 190px, which is the other half of why this band read as unfinished. Let it use the panel. */
:where(.sl-body).refine-pill-porcelain .comp-panel .steps-row:not(.steps-photo) {
  max-width: 100% !important;
}
:where(.sl-body).refine-pill-porcelain .comp-panel .steps-row:not(.steps-photo) > .card.step-card {
  grid-template-columns: auto minmax(0, 24%) minmax(0, 1fr);
  column-gap: clamp(1rem, 2.4vw, 2rem);
  align-items: start;
}
:where(.sl-body).refine-pill-porcelain .comp-panel .step-badge {
  display: grid !important;
  place-items: center;
  grid-column: 1;
  width: 46px;
  height: 46px;
  margin: 0;
  border-radius: 999px;
  background: var(--c-accent);
  color: var(--c-accent-on, #fff);
  font-family: var(--font-headline, var(--font-heading));
  font-weight: 800;
  /* 1.2rem = 19.2px, NOT 1.15rem. Same rule as the buttons: white on IV Pink is 3.77:1, legal only
     as WCAG large text, and bold has to clear 18.66px to count. 1.15rem is 18.4px and misses it by
     a quarter of a pixel, which visual-lint R15 caught on all five badges. */
  font-size: 1.2rem;
  position: relative;
}
/* the tail again, so the step markers read as the same object as every eyebrow on the page */
:where(.sl-body).refine-pill-porcelain .comp-panel .step-badge::after {
  content: '';
  position: absolute;
  left: 7px;
  top: calc(100% - 5px);
  width: 0.62rem;
  height: 0.46rem;
  background: var(--c-accent);
  clip-path: polygon(0 0, 100% 0, 0 100%);
}
@media (max-width: 720px) {
  :where(.sl-body).refine-pill-porcelain .comp-panel .steps-row:not(.steps-photo) > .card.step-card {
    grid-template-columns: auto minmax(0, 1fr);
    row-gap: 0.5rem;
  }
  :where(.sl-body).refine-pill-porcelain .comp-panel .step-card p { grid-column: 1 / -1; }
}

/* B. THE ADD IN LIST, give every entry a box. Three columns of borderless rows separated only by
      a hairline ran together left to right with nothing to say where one item stopped and the next
      began. Ian: "the way they run into each other from left to right just doesn't look right."
      A real card each, and the hairline underline that was doing the separating comes off. */
:where(.sl-body).refine-pill-porcelain.bands-paper main > section.section.section-addons_boosters_grid:nth-of-type(n) .addon-card {
  background: rgba(255, 255, 255, 0.055);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 14px;
  padding: 0.85rem 1rem 0.9rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.14);
}
:where(.sl-body).refine-pill-porcelain.bands-paper main > section.section.section-addons_boosters_grid:nth-of-type(n) .addon-card:hover {
  background: rgba(255, 255, 255, 0.09);
  border-color: rgba(255, 255, 255, 0.24);
}

/* C. LICENSING AND OVERSIGHT, stop it being a wall of words. The band already carries a photograph
      (surfaces.bg_photos) but at wash strength it was invisible, so the section read as three
      centred paragraphs and a lot of nothing. Hold the prose to the left half and let the
      photograph own the right, which is the "push it to the side and put an image" Ian asked for.
      The image itself stays data (theme_json.surfaces.bg_photos), never a URL in shared CSS. */
/* The stock .sec-bg-photo treatment paints the photograph full bleed at ~16% behind the copy and
   lays a scrim over it. Turning the strength up does not make it "an image beside the text", it
   makes muddy text sitting ON a picture. So the same photograph gets confined to the right hand
   column at full opacity, softened on its inner edge so it does not end on a line, and the scrim
   is dropped because the copy no longer sits over anything. The URL still comes from data: the
   section already carries it as --sec-bg-img, so nothing is hardcoded here. */
:where(.sl-body).refine-pill-porcelain main > section.section.section-safety_oversight.sec-bg-photo::before {
  left: auto;
  /* Stop at the page's own gutter. Running it to `right: 0` bled the photograph past the margin
     every other band on the page respects, and it blew out that edge. This is the container's
     maths: half the leftover width, plus the container's own 1.25rem padding. */
  right: calc(max(0px, (100% - var(--container-max, 1200px)) / 2) + 1.25rem);
  width: min(42%, 560px);
  top: clamp(0.75rem, 2vw, 2rem);
  bottom: clamp(0.75rem, 2vw, 2rem);
  opacity: 1;
  border-radius: 16px;
  -webkit-mask-image: none;
  mask-image: none;
}
:where(.sl-body).refine-pill-porcelain main > section.section.section-safety_oversight.sec-bg-photo::after {
  background: none;
}
:where(.sl-body).refine-pill-porcelain .section-safety_oversight .section-header, :where(.sl-body).refine-pill-porcelain .section-safety_oversight .sl-prose {
  max-width: 52%;
  margin-left: 0;
  margin-right: auto;
  text-align: left;
}
:where(.sl-body).refine-pill-porcelain .section-safety_oversight .section-header .eyebrow { margin-left: 0; }
/* Narrow: no room for two columns, so the photograph goes back to being a faint full bleed wash
   behind the copy, which is what the stock treatment is for. */
@media (max-width: 900px) {
  :where(.sl-body).refine-pill-porcelain main > section.section.section-safety_oversight.sec-bg-photo::before {
    left: 0;
    right: 0;
    width: auto;
    opacity: 0.26;
    -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 14%, #000 86%, transparent 100%);
    mask-image: linear-gradient(to bottom, transparent 0%, #000 14%, #000 86%, transparent 100%);
  }
  :where(.sl-body).refine-pill-porcelain main > section.section.section-safety_oversight.sec-bg-photo::after {
    background: linear-gradient(to bottom,
      color-mix(in srgb, var(--c-surface) 62%, transparent) 0%,
      color-mix(in srgb, var(--c-surface) 38%, transparent) 45%,
      color-mix(in srgb, var(--c-surface) 62%, transparent) 100%);
  }
  :where(.sl-body).refine-pill-porcelain .section-safety_oversight .section-header, :where(.sl-body).refine-pill-porcelain .section-safety_oversight .sl-prose { max-width: 100%; }
}

/* D. WHY BOOK WITH US, two columns. Nine numbered rows stacked in a single left hand strip left
      the entire right half of the band empty ("it's a line to the left, so it just feels empty on
      the right") and made the section 1739px tall on its own. Two columns fills the measure and
      halves the height. Numbers stay in document order down column one then column two. */
/* has to outweigh `main > section.section.comp-stdl-rule .stdl-list { display: block }`, which is
   (0,3,2) against a plain lane selector's (0,3,1) and quietly kept the list one column wide even
   with grid-template-columns set. Flow is row-wise, so it reads 01 02 / 03 04 across then down. */
:where(.sl-body).refine-pill-porcelain main > section.section.comp-stdl-rule .stdl-list {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  column-gap: clamp(1.5rem, 3.5vw, 3.25rem);
  row-gap: 0;
  align-items: start;
}
/* .stdl-row draws its rule as a border-bottom with a border-top on the first child only. In two
   columns the SECOND item starts a column too, so it needs the same top rule or the right hand
   column opens with a missing line. */
/* In one column the first row correctly drops its top rule and top padding so the list starts
   flush under the header (:10394). In two columns that makes row 01 sit 38px higher than row 02
   beside it, and row 02 opens with a rule that 01 does not have. Both rows start a column here, so
   both get the same treatment: same rule, same padding, tops aligned. */
:where(.sl-body).refine-pill-porcelain main > section.section.comp-stdl-rule .stdl-row:first-child, :where(.sl-body).refine-pill-porcelain main > section.section.comp-stdl-rule .stdl-row:nth-child(2) {
  border-top: 1px solid color-mix(in srgb, var(--c-text) 14%, transparent);
  padding-top: clamp(1.5rem, 3vw, 2.4rem);
}
@media (max-width: 860px) {
  :where(.sl-body).refine-pill-porcelain main > section.section.comp-stdl-rule .stdl-list { grid-template-columns: minmax(0, 1fr); }
  :where(.sl-body).refine-pill-porcelain main > section.section.comp-stdl-rule .stdl-row:first-child { border-top: 0; padding-top: 0; }
  :where(.sl-body).refine-pill-porcelain main > section.section.comp-stdl-rule .stdl-row:nth-child(2) { border-top: 1px solid color-mix(in srgb, var(--c-text) 14%, transparent); }
}

/* E. THE FAQ. Two faults, both Ian's words. "Underneath Common questions you just have a big blank
      space": comp-split parks the header in a left column that is 120px of content against a 430px
      accordion, so most of that column is empty. And "the FAQ bubbles touch each other": the items
      are stacked with margin 0 and a 14px radius, so consecutive rounded corners meet flush, which
      is exactly the thing a radius is supposed to prevent. Single centred column, and real space
      between every bubble. */
:where(.sl-body).refine-pill-porcelain .section-city_faq.comp-split .container, :where(.sl-body).refine-pill-porcelain .section-city_faq .container {
  display: block;
}
/* comp-split makes this header `position: sticky; top: 108px` so it can hold station beside a
   scrolling accordion in its own column. Once the band is ONE centred column that stickiness has
   nothing to sit beside: the header detaches on scroll and rides down over the question bubbles.
   Static, since it is now a normal centred heading. */
:where(.sl-body).refine-pill-porcelain .section-city_faq .section-header {
  text-align: center;
  max-width: 40rem;
  margin-left: auto;
  margin-right: auto;
  position: static;
  top: auto;
}
:where(.sl-body).refine-pill-porcelain .section-city_faq .section-header .eyebrow { margin-left: auto; margin-right: auto; }
/* Ten questions in one tall stack is a long scroll for the least important band on the page, so
   they run two up: five rows of two, five on the left and five on the right. Row flow rather than
   column flow on purpose. These are accordions, and with `grid-auto-flow: column` opening one
   would resize its whole column and shove its neighbours; row flow keeps each pair independent.
   align-items:start so an open answer grows only its own cell. */
:where(.sl-body).refine-pill-porcelain .section-city_faq .faq-list, :where(.sl-body).refine-pill-porcelain .section-city_faq .cards-center {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  align-items: start;
  gap: 0.65rem 0.9rem;
  max-width: 68rem;
  margin: 0 auto;
}
:where(.sl-body).refine-pill-porcelain .section-city_faq .faq-item {
  margin: 0;
  border-radius: 14px;
}
@media (max-width: 820px) {
  :where(.sl-body).refine-pill-porcelain .section-city_faq .faq-list, :where(.sl-body).refine-pill-porcelain .section-city_faq .cards-center { grid-template-columns: minmax(0, 1fr); }
}

/* ══ dark-luxe, pass 4: four defects Ian called out on staging v51 ══════════════════════════
   All four are "it renders, and it looks cheap" — none would ever fail a gate. */

/* 1. THE BAND ORDER. service_area_map and policy_expand were both --c-surface-alt and ran
      together as one endless beige expanse. Three attempts went at the COLOUR of the coverage
      band — a mixed-down sand, then the brief's unused light_blue, then navy — when the actual
      problem was the ORDER. Ian's call, and it is the right one: leave the coverage band on the
      page's own beige and flip the band AFTER it instead, so the run reads beige -> navy -> beige
      (see theme.surfaces.dark_bands). Nothing new is invented, the alternation is restored, and
      no navy band ends up touching a section that already carries blue imagery.
      Kept here as a note because the wrong instinct was persistent: when two bands collide, fix
      the rhythm, do not tint one of them. */

/* 2. THE WHITE BOXES BEHIND THE BAGS. .pkg-card inherited the stark #FFF card fill, so six
      hard white rectangles sat on the warm band — the "cheap" read. The bag PNGs are genuinely
      transparent, so the white was never in the artwork and nothing has to be re-cut. Inside a
      navy room these same cards are ALREADY transparent with a gold hairline (:4567); this just
      gives the light bands the same treatment, so the object floats on the page stock and the
      rule is one system instead of two. */
/* Ian, v62: white back behind the bags. The earlier transparent treatment removed the "cheap"
   hard-edged box, but it also removed the plate the product was standing on, and a cut-out bag
   floating on the band reads as unfinished. Keep the surface, keep the gold hairline that
   replaced the grey one, and let the frame do the refining instead of deleting the card. */
:where(.sl-body).refine-dark-luxe main > section.section:not(.sec-room):not(.sec-photo):not(.comp-trust-band):not(.block-route-section) .pkg-card {
  background: var(--c-surface) !important;
  border: 1px solid color-mix(in srgb, var(--c-accent) 42%, transparent) !important;
  box-shadow: 0 14px 32px -22px color-mix(in srgb, var(--c-primary) 60%, transparent) !important;
}

/* 3. THE GRADIENT BLAST ON THE CLOSING CARD. .final-cta::after is a 60%x80% gold radial at
      86% 12% — a literal blast of colour in the top right, and a gradient, which this brand
      asked to have none of. The plate under it was also OPAQUE navy over the marble backdrop,
      so the marble Ian asked for survived only as a frame around the edge. Kill the gradient
      and make the plate a flat scrim so the stone actually reads through it. */
:where(.sl-body).refine-dark-luxe .final-cta::after { display: none !important; }
/* NOT ON A HUB PAGE. `.final-cta` is two different things: an interior page's closing plate, which
   this translucent fill was tuned for, and a LISTING page's closing band, which lands directly
   beneath an ink room. Painting the second one the same dark colour as the room above it is one
   colour twice with no seam, which the page-rules P3 check refuses — and it refuses every listing
   page on the site at once. The interior shape keeps the plate; the band form is left to the
   system, which is what the two lanes written this week both do. */
:where(.sl-body).refine-dark-luxe .final-cta:not(.section-hub-cta) {
  background: color-mix(in srgb, var(--c-primary-dark) 74%, transparent) !important;
}
/* 74% was tuned against a marble TEXTURE, where a strong plate still reads as depth. Over a real
   photograph it is a navy rectangle with a picture peeking out around the frame — the same defect
   the note above describes, one step milder. On a photo band the plate goes entirely and the
   band's own scrim carries legibility; the plate stays wherever there is no photograph. */
:where(.sl-body).refine-dark-luxe .sec-photo .final-cta { background: transparent !important; }
/* The closing CTA is three short lines over a room shot the client asked to SEE. With no plate
   in the way the default scrim is doing all the darkening on its own, so it can come up — enough
   contrast for white type, enough photograph to be worth having. */
:where(.sl-body) .section-final_cta.sec-photo { --sec-photo-scrim-top: 0.62; --sec-photo-scrim-mid: 0.50; --sec-photo-scrim-bot: 0.72; }

/* 4. THE "HOW ARE YOU FEELING?" CARDS. A 150px-tall card holding a 15.7px label, and an icon
      disc painted rgb(34,50,66) — the exact navy of the band behind it, so the disc was
      invisible and the glyph floated. Hence "plain and tiny inside": the box was sized for
      content that was never scaled to match. Give the disc a gold ring so it reads as an
      object, and let the symptom carry the display serif at a size worth the box. */
:where(.sl-body).refine-dark-luxe .sec-room .sfb-card .cat-ic {
  background: transparent;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--c-accent) 48%, transparent);
  color: var(--c-accent);
  width: 60px; height: 60px;
}
:where(.sl-body).refine-dark-luxe .sec-room .sfb-card .cat-ic svg { width: 30px; height: 30px; }
:where(.sl-body).refine-dark-luxe .sec-room .sfb-card {
  min-height: 176px;
  padding: 1.7rem 1.15rem;
  gap: 0.85rem;
}
:where(.sl-body).refine-dark-luxe .sec-room .sfb-card > span {
  font-family: var(--font-heading);
  font-size: 1.28rem;
  font-weight: 500;
  line-height: 1.2;
}
:where(.sl-body).refine-dark-luxe .sec-room .sfb-card .sfb-drip {
  font-size: 0.74rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  font-weight: 600;
}
@media (max-width: 640px) {
  :where(.sl-body).refine-dark-luxe .sec-room .sfb-card { min-height: 150px; padding: 1.3rem 0.8rem; }
  :where(.sl-body).refine-dark-luxe .sec-room .sfb-card > span { font-size: 1.08rem; }
}

/* ══ dark-luxe, pass 5: the toolbar and the bag carousel ═══════════════════════════════════ */

/* THE HEADER. A white bar with default-weight sentence-case links — none of the vocabulary the
   rest of the page speaks. Every other label on this site is a letterspaced uppercase eyebrow
   over a hairline rule, so the toolbar adopts the same: small caps, generous tracking, a gold
   hairline closing the bar, and a gold underline that grows on hover instead of a grey tint. */
:where(.sl-body).refine-dark-luxe .site-header {
  border-bottom: 1px solid color-mix(in srgb, var(--c-accent) 42%, transparent);
  box-shadow: none;
}
:where(.sl-body).refine-dark-luxe .site-header > .container { padding-top: 0.55rem; padding-bottom: 0.55rem; }
:where(.sl-body).refine-dark-luxe .nav-links { gap: 0.35rem; }
:where(.sl-body).refine-dark-luxe .nav-item > a {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 0.65rem 0.85rem;
  border-radius: 0;
  position: relative;
  color: var(--c-text);
}
/* The default hover paints a grey tint block behind the link, which on a white bar reads as a
   button that is not one. A rule that grows from the centre is quieter and matches the gold
   hairlines used everywhere else. */
:where(.sl-body).refine-dark-luxe .nav-item > a:hover, :where(.sl-body).refine-dark-luxe .nav-item > a:focus-visible { background: transparent; }
:where(.sl-body).refine-dark-luxe .nav-item > a::after {
  content: '';
  position: absolute;
  left: 50%; right: 50%; bottom: 0.32rem;
  height: 1px;
  background: var(--c-accent);
  transition: left .22s ease, right .22s ease;
}
:where(.sl-body).refine-dark-luxe .nav-item > a:hover::after, :where(.sl-body).refine-dark-luxe .nav-item > a:focus-visible::after, :where(.sl-body).refine-dark-luxe .nav-item > a.active::after { left: 0.85rem; right: 0.85rem; }
:where(.sl-body).refine-dark-luxe .nav-actions .btn {
  font-size: 0.72rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 0.9rem 1.6rem;
} :where(.sl-body).refine-dark-luxe .site-header .logo img { max-height: 62px; }

/* THE BAG CAROUSEL. Rewritten in pass 6 — see the block at the end of this file. */

/* ══ pass 6: THE CAROUSEL, properly ════════════════════════════════════════════════════════
   Requirements, from Ian: three bags visible, the centre one enlarged, one bag per step, moving
   on its own, slowly, and looping forever in both directions. The previous version failed every
   one of those — it scrolled ~3 cards per click and dead-ended at each extreme, because it was a
   scroll container and a scroll container has ends. It now translates a track and rotates the DOM
   (see CAROUSEL_JS), which is what makes the loop endless AND makes the centre a fixed position:
   after every step the leftmost visible card is child 1, so the middle is always child 2. */

/* Arrows OUTSIDE the cards. They were absolutely positioned over the track, so they sat on top of
   the first and third bag — hard to hit, and a click landed on the card's link as often as the
   button. The carousel now reserves a gutter for them. */
:where(.sl-body).refine-dark-luxe .pkg-carousel { padding: 0 4.5rem; }
/* ...but ONLY the carousel has arrows. In grid mode the gutter reserved space for buttons that
   are never rendered, costing the track 144px — enough that eight cards sized by chooseCols for
   4+4 could only fit 3 per row (R16). No arrows, no gutter. */
:where(.sl-body).refine-dark-luxe .pkg-carousel.pkg-style-grid{ padding-left: 0; padding-right: 0; }
:where(.sl-body).refine-dark-luxe .pkg-prev { left: 0; }
:where(.sl-body).refine-dark-luxe .pkg-next { right: 0; }
:where(.sl-body).refine-dark-luxe .pkg-arrow {
  width: 46px; height: 46px;
  border: 1px solid color-mix(in srgb, var(--c-accent) 55%, transparent);
  background: transparent;
  color: var(--c-text);
  box-shadow: none;
}
:where(.sl-body).refine-dark-luxe .pkg-arrow:hover {
  background: var(--c-accent);
  color: var(--c-primary-dark);
  border-color: var(--c-accent);
}
/* The loop never runs out of cards, so the "you can still scroll" affordances are lies now. */

/* The viewport clips; the track slides. Vertical padding is what gives the raised centre room —
   overflow:hidden clips at the PADDING box, so a card lifted into that padding still shows. */
:where(.sl-body) .pkg-viewport { overflow: hidden; padding: 2.75rem 0 3rem; }
:where(.sl-body) .pkg-carousel.pkg-loop .pkg-track {
  overflow: visible;
  scroll-snap-type: none;
  transform: translateX(0);
  transition: transform .62s cubic-bezier(.4, 0, .2, 1);
  justify-content: flex-start;
  will-change: transform;
}
:where(.sl-body) .pkg-carousel.pkg-loop .pkg-card { scroll-snap-align: none; }
/* THE CENTRE — child 2, always, because the DOM rotates. The scale change is what Ian asked for:
   the bag arriving in the middle grows into the highlight as the slide settles. */
:where(.sl-body).refine-dark-luxe .pkg-carousel.pkg-loop .pkg-card:nth-child(2) {
  transform: translateY(-16px) scale(1.06);
  border-color: color-mix(in srgb, var(--c-accent) 85%, transparent) !important;
  background: var(--c-surface) !important;
  box-shadow: 0 26px 54px -26px color-mix(in srgb, var(--c-primary) 66%, transparent) !important;
}
:where(.sl-body).refine-dark-luxe .pkg-carousel.pkg-loop .pkg-card:nth-child(2) .pkg-bag { height: 232px !important; }
:where(.sl-body).refine-dark-luxe .pkg-carousel.pkg-loop .pkg-card:nth-child(2) h3 { font-size: 1.32rem; }
@media (prefers-reduced-motion: reduce) {
  :where(.sl-body) .pkg-carousel.pkg-loop .pkg-track { transition: none; }
}
@media (max-width: 900px) {
  :where(.sl-body).refine-dark-luxe .pkg-carousel { padding: 0 2.5rem; }
  :where(.sl-body).refine-dark-luxe .pkg-carousel.pkg-loop .pkg-card:nth-child(2) { transform: none; }
  :where(.sl-body).refine-dark-luxe .pkg-carousel.pkg-loop .pkg-card:nth-child(2) .pkg-bag { height: 190px !important; }
  :where(.sl-body) .pkg-viewport { padding: 1.5rem 0 2rem; }
}

/* city_faq on the page stock. The first pass made these transparent, reasoning from the white
   boxes behind the bags — wrong read. That defect was a large white RECTANGLE behind a product
   object; a thin accordion bar is not the same thing, and policy_expand carried exactly this
   treatment on beige for weeks without complaint. Transparent bars on a beige band gave the
   section nothing but hairlines and it washed out completely. The card keeps its own surface so
   the rows read as objects; the gold hairline replaces the grey one for warmth. */
/* :not(.comp-faq-cards):not(.comp-faq-ruled) added 2026-08-09: these !importants outrank a
   composed FAQ design at ANY specificity, so comp-faq-cards lost its [open] tint and border here
   and comp-faq-ruled lost its whole premise. The lane cannot be out-specified, so the lane steps
   aside — a section a design has claimed keeps the design. */
:where(.sl-body).refine-dark-luxe main > section.section:not(.sec-room):not(.sec-photo):not(.comp-trust-band):not(.block-route-section):not(.comp-faq-cards):not(.comp-faq-ruled) .faq-item {
  background: var(--c-surface) !important;
  border: 1px solid color-mix(in srgb, var(--c-accent) 38%, transparent) !important;
  box-shadow: 0 10px 26px -18px color-mix(in srgb, var(--c-primary) 55%, transparent) !important;
}
/* A PLATE OWNS ITS NEIGHBOURS' AIR: the bordered cards above stacked with 0 margin, so adjacent
   1px gold borders doubled into a seam and the accordion read as one striped slab — the same
   owner-reported defect as bands-paper's city_faq, from a different lane. Padding for the inset
   the base accordion deliberately lacks, margin for the air. Applies to the un-composed case
   only; composed FAQs are excluded above and carry their own geometry. */
:where(.sl-body).refine-dark-luxe main > section.section:not(.sec-room):not(.sec-photo):not(.comp-trust-band):not(.block-route-section):not(.comp-faq-cards):not(.comp-faq-ruled) .faq-item {
  padding: 0.1rem clamp(1.05rem, 2vw, 1.4rem);
}
:where(.sl-body).refine-dark-luxe main > section.section:not(.sec-room):not(.sec-photo):not(.comp-trust-band):not(.block-route-section):not(.comp-faq-cards):not(.comp-faq-ruled) .faq-item + .faq-item {
  margin-top: 0.7rem;
}

/* THE TOOLBAR, pass 7. Letterspaced caps alone did not carry it — the bar was still a stark white
   rail, the single plainest surface on the page, sitting above a navy hero. Two changes: give the
   brand's colour a place to live at the top (the utility strip), and warm the bar itself off pure
   #FFF onto the page's own stock so it belongs to the site rather than to the browser. */
:where(.sl-body) .header-utility {
  background: var(--c-hero-plate);
  color: color-mix(in srgb, var(--c-surface) 82%, var(--c-primary));
}
:where(.sl-body) .header-utility .container {
  display: flex;
  justify-content: center;
  gap: 2.25rem;
  padding-top: 0.5rem;
  padding-bottom: 0.5rem;
  font-size: 0.66rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  font-weight: 600;
}
:where(.sl-body) .header-utility span, :where(.sl-body) .header-utility .header-utility-link { white-space: nowrap; }
:where(.sl-body) .header-utility .header-utility-link { color: inherit; text-decoration: none; transition: color .15s; }
:where(.sl-body) .header-utility .header-utility-link:hover { color: var(--c-accent); }
/* The separator dot is drawn by the SECOND item onward, whichever element type it is. Keyed to
   span+span only, an <a> in the strip lost its dot and the run read as one long phrase. */
:where(.sl-body) .header-utility span + span, :where(.sl-body) .header-utility span + .header-utility-link, :where(.sl-body) .header-utility .header-utility-link + span, :where(.sl-body) .header-utility .header-utility-link + .header-utility-link { position: relative; }
:where(.sl-body) .header-utility span + span::before, :where(.sl-body) .header-utility span + .header-utility-link::before, :where(.sl-body) .header-utility .header-utility-link + span::before, :where(.sl-body) .header-utility .header-utility-link + .header-utility-link::before {
  content: '';
  position: absolute; left: -1.15rem; top: 50%;
  width: 3px; height: 3px; border-radius: 50%;
  background: var(--c-accent);
  transform: translateY(-50%);
}
/* This strip is the one element that overflowed the mobile viewport: three nowrap items measured
   416px inside a 390px screen, which widened the DOCUMENT to 417 and clipped every band at the
   right edge — the hero read as broken when the hero was fine. Drop items as space runs out, and
   allow wrapping so no future string can push the page wide again. */
:where(.sl-body) .header-utility .container { flex-wrap: wrap; row-gap: 0.15rem; }
@media (max-width: 720px) {
  :where(.sl-body) .header-utility .container { gap: 1.1rem; font-size: 0.58rem; letter-spacing: 0.14em; }
  :where(.sl-body) .header-utility span + span::before { left: -0.65rem; }
  :where(.sl-body) .header-utility span:nth-child(3) { display: none; }
}
@media (max-width: 560px) {
  :where(.sl-body) .header-utility span:nth-child(2) { display: none; }
}
/* THE SEPARATOR HAS TO BE IN THE FLOW, AND THE GAP HAS TO SURVIVE.
   Two faults, one rail, both visible on Top Tier's phone header:
     · `gap: 0` above made the items touch — measured "SERVING NORTHERN VIRGINIA" ending at 238px
       and "(703) 357-6511" starting at 238px, so the page read "…VIRGINIA(703) 357-6511". The gap
       was zeroed to stop the rail overflowing, but the rail wraps now (row-gap, :8360), so the
       overflow that justified it cannot happen any more.
     · the dot is an absolutely-positioned ::before at left:-1.15rem on the item that FOLLOWS it,
       so the first item on a wrapped line drew a dot 18px to its left — an orphan bullet hanging
       at the start of line two, which is what the email line showed.
   A trailing ::after, in the flow, fixes both: it cannot orphan (a wrapped line never starts with
   one), and it carries its own margin so the items can never touch. Scoped to the wrapping widths;
   the desktop rail keeps the leading dot it was designed with. */
@media (max-width: 720px) {
  :where(.sl-body) .header-utility .container { column-gap: 0; row-gap: 0.15rem; }
  :where(.sl-body) .header-utility span + span::before, :where(.sl-body) .header-utility span + .header-utility-link::before, :where(.sl-body) .header-utility .header-utility-link + span::before, :where(.sl-body) .header-utility .header-utility-link + .header-utility-link::before { content: none; }
  /* A 15px-TALL PHONE NUMBER IS NOT A TAP TARGET. Measured on the rail: the number 108x15 and the
     email 194x15 — the two links a phone user is most likely to reach for, both a third of the
     44px floor. The number gets a real target; the email comes off, because on a phone it is the
     third copy (the header already carries a Call button, and the footer carries both) and it is
     the longest string on the rail — dropping it is what lets the rail stay one line. */
  :where(.sl-body) .header-utility .header-utility-link[href^="tel:"] {
    display: inline-flex; align-items: center; min-height: 40px;
  }
  :where(.sl-body) .header-utility .container { padding-top: 0; padding-bottom: 0; }
  :where(.sl-body) .header-utility .header-utility-link[href^="mailto:"] { display: none; }
  /* A DOT MUST BELONG TO THE ITEM THAT FOLLOWS IT, NOT THE ONE BEFORE.
     Written as "a dot AFTER everything except the last item", which is the obvious way round and
     is wrong here: two items on this rail are hidden at narrow widths (the hours below 560, the
     email below 720) and a hidden element is still a child, so the phone number was never the
     last child and kept painting a separator with nothing after it - a dot floating at the end of
     the rail on every phone. Hanging the dot on the FOLLOWING item instead fixes it for good,
     because a hidden item does not paint its own ::before: whatever is hidden takes its separator
     with it, at any width, for any number of items. */
  :where(.sl-body) .header-utility .container > *:not(:first-child)::before {
    content: '';
    /* The rail's ORIGINAL dot (:8346) is position:absolute at left:-1.15rem, and this
       selector overlaps it. Without putting the dot back in the flow it would hang 18px
       to the left of its item and orphan at the start of a wrapped line - the exact
       fault described above. Stated here rather than inherited by luck. */
    position: static; left: auto;
    display: inline-block; vertical-align: middle;
    width: 3px; height: 3px; border-radius: 50%;
    background: var(--c-accent);
    margin: 0 0.6rem 0.15em 0.6rem;
  }
}
/* LIGHT bar: WHITE, not the page stock (Ian: "header wants to be white"). It was cream so the bar
   would melt into a cream page, but that also means the header stops reading as a separate plane —
   and on this archetype the utility strip directly above it is already cream, so cream-on-cream
   collapsed the two rails into one block. White separates them, and the hairline below keeps the
   bar defined where the section under it is also white. */
:where(.sl-body).refine-dark-luxe .site-header:not(.site-header--dark) {
  background: var(--c-surface);
  border-bottom: 1px solid color-mix(in srgb, var(--c-primary) 12%, transparent);
}
:where(.sl-body).refine-dark-luxe .site-header .container { background: transparent; }

/* FLIPPED (theme.header.variant = 'dark'): the thick bar carries the brand colour and the thin
   strip above it goes to the page stock. The main bar is --c-primary, NOT --c-primary-dark, so it
   still reads as a distinct plane against the near-black hero scrim directly beneath it rather
   than merging into one dark mass. Needs theme.header.logo_light or the lockup disappears. */
:where(.sl-body).refine-dark-luxe .site-header--dark { background: var(--c-room); }
:where(.sl-body).refine-dark-luxe .site-header--dark .header-utility {
  background: var(--c-surface-alt);
  color: var(--c-primary);
}
:where(.sl-body).refine-dark-luxe .site-header--dark .header-utility span + span::before { background: var(--c-primary); }
:where(.sl-body).refine-dark-luxe .site-header--dark .nav-item > a { color: var(--c-on-room); }
:where(.sl-body).refine-dark-luxe .site-header--dark .nav-item > a::after { background: var(--c-accent); }
:where(.sl-body).refine-dark-luxe .site-header--dark { border-bottom-color: color-mix(in srgb, var(--c-accent) 55%, transparent); }

/* ── PHOTOGRAPHY (2026-07-30, round 3): the lane finally carries images ──────────────────
   Ian's verdict on the composed page was that it still looked like shit, and he was right
   for a reason no amount of arrangement fixes: the page had NO PHOTOGRAPHS on it. The
   treatment tiles rendered a 30px line icon each and the service carousel fell back to
   shared IV-bag art (on a med spa). Both are now data-driven images; these rules give them
   editorial shape. Scoped to the lane, so no other brand changes. */

/* Category tiles become full-bleed image cards. The renderer emits
   <a class="cat-card"><img class="cat-ic" width="30" height="30"><span>label</span></a>,
   so the width/height ATTRIBUTES must be overridden in CSS, not respected. */
:where(.sl-body).refine-luxe-noir .cat-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 230px), minmax(0, 1fr)));
  gap: clamp(1rem, 2vw, 1.75rem);
  max-width: none;
}
:where(.sl-body).refine-luxe-noir .cat-card {
  display: block;
  padding: 0;
  border: 0;
  background: transparent;
  border-radius: 0;
  text-align: left;
  box-shadow: none;
  overflow: hidden;
}
/* THE ROOM PUTS THIS TILE'S INK BACK. `.cat-card` is a WHITE tile, and the shared room rule at
   :4676 rebinds its ink to the dark page colour precisely BECAUSE it is white and sits on a dark
   band. This lane strips the white plate — which is the lane's own identity and right — but the
   rebind above is written at a specificity the lane cannot reach, so the dark ink stayed on the
   dark room. Where the plate is gone, the ink follows it. */
:where(.sl-body).refine-luxe-noir main > section.section.sec-room .cat-card, :where(.sl-body).refine-luxe-noir main > section.section.sec-photo .cat-card {
  --c-text: var(--c-on-dark);
  color: var(--c-on-dark);
}
:where(.sl-body).refine-luxe-noir .cat-card img.cat-ic {
  display: block;
  width: 100%;
  height: clamp(190px, 21vw, 250px);
  object-fit: cover;
  border-radius: 0;
  margin: 0 0 0.85rem;
  background: var(--c-surface-alt);
  transition: transform 420ms cubic-bezier(.2,.6,.2,1);
}
:where(.sl-body).refine-luxe-noir .cat-card:hover img.cat-ic { transform: scale(1.03); }
:where(.sl-body).refine-luxe-noir .cat-card > span {
  font-family: var(--font-display, Georgia, serif);
  font-size: clamp(1.02rem, 1.5vw, 1.18rem);
  font-weight: 400;
  line-height: 1.25;
  color: var(--c-text);
  letter-spacing: 0.005em;
}
/* the imageless fallback tile keeps a quiet framed shape so a mixed row still reads */
:where(.sl-body).refine-luxe-noir .cat-card > .cat-ic:not(img) {
  height: clamp(190px, 21vw, 250px);
  display: grid;
  place-items: center;
  background: var(--c-surface-alt);
  border-radius: 0;
  margin: 0 0 0.85rem;
}

/* IV-BAG ART IS NOT MED SPA FURNITURE. With per-item art suppressed the pkg renderer falls
   back to a line-drawn IV bag — the same vertical leak as "After your drip". A lane that is
   not IV hides it outright and lets the card read as type. */
:where(.sl-body).refine-luxe-noir .pkg-bag-fallback { display: none; }
:where(.sl-body).refine-luxe-noir .pkg-card { padding-top: 1.6rem; }

/* ══ ROOM INK, generalised ═════════════════════════════════════════════════════════════════
   Third time this exact bug has shipped: a section moves onto a navy room and something inside
   it keeps ink that was chosen against a LIGHT band. It happened to policy_expand's .pxp-item,
   to city_faq, and now to why_us and the hub cards, because the per-page rhythm can now put ANY
   section in a room — so "which sections are dark" is no longer knowable when writing a
   component. Two rules, stated once, covering both directions.

   1. Anything painted with --c-primary DIRECTLY on the band is navy-on-navy. */
:where(.sl-body).bands-paper main > section.section.sec-room .whyus-eyebrow, :where(.sl-body).bands-paper main > section.section.sec-photo .whyus-eyebrow {
  color: var(--c-accent);
}
/* 2. A card that keeps its own LIGHT surface inside a room must rebind its own ink, or it
      inherits the room's light-on-dark values and prints pale text on white. */
:where(.sl-body).bands-paper main > section.section.sec-room .whyus-card, :where(.sl-body).bands-paper main > section.section.sec-room .hub-card, :where(.sl-body).bands-paper main > section.section.sec-photo .whyus-card, :where(.sl-body).bands-paper main > section.section.sec-photo .hub-card {
  --c-text: var(--c-primary);
  --c-text-muted: var(--c-muted-on-surface, color-mix(in srgb, var(--c-primary) 74%, var(--c-surface-alt)));
  color: var(--c-primary);
}
:where(.sl-body).bands-paper main > section.section.sec-room .hub-card-desc, :where(.sl-body).bands-paper main > section.section.sec-photo .hub-card-desc {
  color: var(--c-muted-on-surface, color-mix(in srgb, var(--c-primary) 74%, var(--c-surface-alt)));
}
/* 2b. …EXCEPT A CARD THAT IS A PHOTOGRAPH. The rule above says so in its own first line - "a card
       that keeps its own LIGHT surface" - and the tile arrangement does not: its card IS the
       picture, with the words on a dark gradient over the bottom of it, already white by design.
       Re-inking those to the dark navy put 30 lines of near-black type on a photograph at 1.0:1,
       measured over the real pixels, on every listing page at both widths.
       It only appeared when the dark bands came back, which is the trap: this rule and the tile
       rule had never been on the same band before, so neither was wrong on its own. */
:where(.sl-body).bands-paper main > section.section.sec-room .hub-cards-tile .hub-card, :where(.sl-body).bands-paper main > section.section.sec-photo .hub-cards-tile .hub-card {
  --c-text: #fff;
  --c-text-muted: rgba(255, 255, 255, 0.86);
  color: #fff;
}
:where(.sl-body).bands-paper main > section.section.sec-room .hub-cards-tile :is(.hub-card-title, :where(.sl-body) .hub-card-desc, :where(.sl-body) .hub-card-count, :where(.sl-body) .hub-card-more), :where(.sl-body).bands-paper main > section.section.sec-photo .hub-cards-tile :is(.hub-card-title, :where(.sl-body) .hub-card-desc, :where(.sl-body) .hub-card-count, :where(.sl-body) .hub-card-more) {
  color: #fff;
}
/* AND THE RAIL, which is the same case and was written for neither. The deck gives every card its
   own pale plate, so a card on a dark band still reads; the tile got the rule above when the dark
   bands came back. The rail draws no plate at all - `background: transparent`, a hairline between
   rows - so on a room its title inherits the brand primary and sits on the brand primary: 1:1,
   twenty-four lines of it, invisible. It had never shipped in 616 built listing pages, so nobody
   had seen it; the moment the ground rotation could reach it, it did. */
:where(.sl-body).bands-paper main > section.section.sec-room .hub-cards-rail :is(.hub-card, :where(.sl-body) .hub-card-title, :where(.sl-body) .hub-card-desc, :where(.sl-body) .hub-card-count, :where(.sl-body) .hub-card-more), :where(.sl-body).bands-paper main > section.section.sec-photo .hub-cards-rail :is(.hub-card, :where(.sl-body) .hub-card-title, :where(.sl-body) .hub-card-desc, :where(.sl-body) .hub-card-count, :where(.sl-body) .hub-card-more) {
  color: var(--c-on-dark, #fff);
}
:where(.sl-body).bands-paper main > section.section.sec-room .hub-cards-rail .hub-card-desc, :where(.sl-body).bands-paper main > section.section.sec-photo .hub-cards-rail .hub-card-desc {
  color: color-mix(in srgb, var(--c-surface, #fff) 86%, transparent);
}
/* 3. And the inverse: a TRANSPARENT element in a room sits on the navy itself, so it needs the
      LIGHT ink, not the dark rebinding above. The hub FAQ is rules-and-text with no surface. */
:where(.sl-body).bands-paper main > section.section.sec-room .hub-faq-item, :where(.sl-body).bands-paper main > section.section.sec-room .hub-faq-item summary, :where(.sl-body).bands-paper main > section.section.sec-photo .hub-faq-item, :where(.sl-body).bands-paper main > section.section.sec-photo .hub-faq-item summary {
  color: var(--c-on-dark);
}
:where(.sl-body).bands-paper main > section.section.sec-room .hub-faq-item p, :where(.sl-body).bands-paper main > section.section.sec-photo .hub-faq-item p {
  color: color-mix(in srgb, var(--c-surface) 80%, var(--c-primary));
}
:where(.sl-body).bands-paper main > section.section.sec-room .hub-faq-item summary::after, :where(.sl-body).bands-paper main > section.section.sec-photo .hub-faq-item summary::after { color: var(--c-accent); }
:where(.sl-body).bands-paper main > section.section.sec-room .hub-faq, :where(.sl-body).bands-paper main > section.section.sec-room .hub-faq-item, :where(.sl-body).bands-paper main > section.section.sec-photo .hub-faq, :where(.sl-body).bands-paper main > section.section.sec-photo .hub-faq-item {
  border-color: color-mix(in srgb, var(--c-on-dark) 26%, transparent);
}

/* THE GOLD BLAST, everywhere it lives. Ian rejected it on the closing card — "the gradient blast
   of color on the top right... it doesn't look good" — and it was removed there and nowhere else.
   The identical layer, same 0.6 alpha, sits on EVERY hero on EVERY page via the archetype's scrim
   (:1621). Same defect, same brand, one instance fixed and one left: the pattern this session has
   repeated more than any other. The navy scrim underneath STAYS — that one is load-bearing, it is
   what keeps white headline type legible over the hero video — only the decorative wash goes. */
/* THE SWEEP. Removing the gold blast left the archetype's 92deg ramp behind — 94% navy on the
   left, 30% on the right — which over a real photograph reads as a diagonal wash smeared across
   the picture and stopping partway, not as a treatment. A scrim's whole job is to be unnoticed.
   Even coverage instead: one flat tone across the frame, dark enough to hold white display type
   (verified by R15) and consistent enough that the photograph underneath reads as a photograph. */
/* HOW DARK, THOUGH, IS A PER-BRAND QUESTION. 58% was measured for a hero whose picture is a
   room — a dim interior that the wash barely changes. Top Tier's client asked for a wide golden
   landscape and got a navy rectangle: at 58% a sunrise is gone. The number is the same literal it
   always was, so every site that does not set the key renders byte-identically; a brand that has
   a picture worth seeing can now say so. Below roughly 40% the hero's white display type needs
   the photo-text check to sign it off, which is what that check is for. */
:where(.sl-body).refine-dark-luxe .hero-image-bg::after{
  background: color-mix(in srgb, var(--c-primary) var(--hero-wash, 58%), transparent) !important;
  background-size: auto !important;
}
/* ...but an even 58% navy over a VIDEO is a blue tint across the whole picture, and the video is
   the one asset here that was art-directed shot by shot — Ian: "I want the hero video to look
   exactly how it's supposed to look, as it was generated." So the wash comes off the footage and
   becomes a floor: clear through the top two-thirds where the infusion actually happens, ramping
   only under the type. Legibility is unchanged (R15 verifies it); the picture is not. */
:where(.sl-body).refine-dark-luxe .hero-gradient::after { background-image: none !important; }

/* THE PHOTO HERO WAS NEVER PAINTED. The base rule puts the hero image on .hero-image-bg::before
   (background-image: var(--hero-bg)), but the archetype claims the SAME pseudo-element for its
   grid texture at higher specificity (body.ad-typographic-clinical .hero::before, :1590), so the
   photograph was silently replaced by a 46px grid on every image hero this brand has ever
   rendered. Home never showed the symptom because its hero is a <video> ELEMENT, not a
   background — which is exactly why home looked finished and no other page did.
   Give the photo its layer back. The grid is a whisper and the photograph is the point. */
:where(.sl-body).refine-dark-luxe .hero-image-bg::before {
  background-image: var(--hero-bg) !important;
  background-size: cover !important;
  background-position: 50% var(--sl-hero-focus-y) !important;
  -webkit-mask-image: none !important;
  mask-image: none !important;
  filter: none;
  opacity: 1;
}

/* ── image_stack — the layout from the client's reference boards ───────────────────────────────
   One tall plate with a second, smaller plate overlapping its lower corner, copy set beside it.
   Built as a real section rather than a one-off so any page can use it. Both plates take the
   brand's gold hairline; the overlap is what makes it read as composed rather than as two
   pictures that happen to be near each other. */
/* THE BAND'S CONTENT STARTS WHERE THE PAGE'S COLUMN STARTS. `--content-max` is 1120px while the
   container hands down 1160px of content (1200 cap less 20px of padding a side), so an inner
   element that takes the token and centres itself lands 20px inside the page column. Measured on
   About: every other band's content began at 140 and this one at 160, which is the two-left-edges
   defect grid-lint names as G1.
   Scoped to this band deliberately. The same 20px gap is available to all 46 rules that read
   `--content-max`, and closing it at the token would move content on every site in the fleet —
   that is a fleet-wide design decision, not a fix for one misaligned band. */
:where(.sl-body) .istack { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: clamp(2rem, 5vw, 4.5rem); align-items: center; max-width: none; margin: 0 auto; }
:where(.sl-body) .istack.is-reverse .istack-plates { order: 2; }
:where(.sl-body) .istack.is-textonly { grid-template-columns: minmax(0, var(--content-measure)); justify-content: center; }
:where(.sl-body) .istack-plates { position: relative; }
:where(.sl-body) .istack-a img, :where(.sl-body) .istack-b img { display: block; width: 100%; height: 100%; object-fit: cover; }
:where(.sl-body) .istack-a { margin: 0; position: relative; aspect-ratio: 4 / 5; }
/* The second plate hangs off the lower-right corner and sits ON the first. Its own margin-bottom
   reserves the overhang so the section never collides with what follows. */
:where(.sl-body) .istack-b { margin: 0; position: absolute; right: -10%; bottom: -14%; width: 54%; aspect-ratio: 4 / 5; z-index: 2; }
/* THE OVERHANG MIRRORS WITH THE ORDER. The plate hangs 10% off the right of its column so it
   overlaps its sibling - which lands in the harmless gap between the two columns when the plates
   are the LEFT column, and lands out in the page margin when `.is-reverse` moves them to the
   RIGHT. Written for one of the two orders the renderer emits; comp-imgtext-frame already carries
   the same flip. Guarded by G5. */
:where(.sl-body) .istack.is-reverse .istack-plates > .istack-b { right: auto; left: -10%; }
:where(.sl-body) .istack-plates.is-pair { margin-bottom: 9%; }
:where(.sl-body) .istack-body h2 { margin-bottom: 1rem; }
:where(.sl-body) .istack-body p { color: var(--c-text-muted); line-height: 1.7; margin-bottom: 1rem; max-width: 52ch; }
:where(.sl-body) .istack-body .btn { margin-top: 0.5rem; }
@media (max-width: 860px) {
  :where(.sl-body) .istack { grid-template-columns: minmax(0, 1fr); gap: 2rem; }
  :where(.sl-body) .istack.is-reverse .istack-plates { order: 0; }
  :where(.sl-body) .istack-b { right: 0; bottom: -10%; width: 46%; }
  :where(.sl-body) .istack-plates.is-pair { margin-bottom: 12%; }
}
/* Brand finish: the same gold hairline the other editorial photos carry. */
:where(.sl-body).refine-dark-luxe .istack-a img, :where(.sl-body).refine-dark-luxe .istack-b img { border-radius: var(--card-radius, 2px); }
:where(.sl-body).refine-dark-luxe .istack-a::after, :where(.sl-body).refine-dark-luxe .istack-b::after {
  content: ''; position: absolute; inset: -10px; pointer-events: none; z-index: 3;
  border: 1px solid color-mix(in srgb, var(--c-accent) 70%, transparent);
  border-radius: var(--card-radius, 2px);
}
:where(.sl-body).refine-dark-luxe .istack-b { box-shadow: 0 30px 60px -28px color-mix(in srgb, var(--c-primary) 80%, transparent); }
@media (max-width: 720px) {
  :where(.sl-body).refine-dark-luxe .istack-a::after, :where(.sl-body).refine-dark-luxe .istack-b::after { inset: -6px; }
}

/* hero.tagline — the brand line that belongs WITH the button, not with the headline. Set apart
   from the subhead so the two never read as one paragraph: smaller, letterspaced, gold. */
/* THE HERO PRICE LINE — the fixed-price fork of menu_pricing (docs/teardowns/package.md §g).
   A drip with ONE number states it here and builds no pricing band anywhere on the page; a drip
   whose price depends on dose leaves this empty and builds the table instead.

   Scale is from the reference: cap height 25px, i.e. roughly 36px set — deliberately well below
   the headline and unmistakably above the subhead, which is what makes it read as a fact rather
   than as more copy. The word sits in ink and the figure in the accent, so the number is the thing
   the eye lands on. */
:where(.sl-body) .hero-price {
  margin: 0 0 1.15rem;
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.15em 0.5em;
  line-height: 1.1;
}
:where(.sl-body) .hero-price-label {
  font-family: var(--font-heading);
  font-size: clamp(1rem, 1.3vw, 1.15rem);
  font-weight: 600;
  letter-spacing: 0.02em;
}
:where(.sl-body) .hero-price-figure {
  font-family: var(--font-heading);
  font-size: clamp(1.6rem, 2.6vw, 2.25rem);
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--c-accent-ink, var(--c-accent));
}
/* A note ("HSA/FSA accepted", "travel included") rides the same baseline, small and quiet. */
:where(.sl-body) .hero-price-note {
  font-size: clamp(0.9rem, 1.1vw, 1rem);
  opacity: 0.82;
}
/* On a photo or gradient hero the accent can fall out of contrast against the scrim, and the
   whole point of this line is that the number is readable. Dark heroes take surface ink for the
   word and let the accent carry the figure only where it stays legible. */
:where(.sl-body) .hero-image-bg .hero-price-label, :where(.sl-body) .hero-video .hero-price-label, :where(.sl-body) .hero-gradient .hero-price-label { color: var(--c-on-dark); }

/* THE FIGURE TOO, NOT ONLY THE LABEL AND THE NOTE.
   The price line was given a dark-hero treatment when it was built this morning — for its LABEL and
   its NOTE. The figure itself kept `var(--c-accent-ink)`, which is a deep green on Bolt and sits on
   a purple hero: 1.38:1, reported by the contrast check as EFFECTIVELY INVISIBLE on all four of its
   package pages. The number is the whole point of the line.
   One of a pair fixed and the other missed, which is the same shape as the logo that shipped black
   on a black bar. */
:where(.sl-body) .hero-image-bg .hero-price-figure, :where(.sl-body) .hero-video .hero-price-figure, :where(.sl-body) .hero-gradient .hero-price-figure { color: var(--c-on-dark); }
:where(.sl-body) .hero-image-bg .hero-price-note, :where(.sl-body) .hero-video .hero-price-note, :where(.sl-body) .hero-gradient .hero-price-note { color: var(--c-on-dark); opacity: 0.86; }
:where(.sl-body) .hero-align-center .hero-inner .hero-price { justify-content: center; }

:where(.sl-body) .hero-tagline {
  margin: 0 0 1.15rem;
  font-family: var(--font-heading);
  font-size: clamp(1.05rem, 1.7vw, 1.35rem);
  font-style: italic;
  letter-spacing: 0.01em;
  color: var(--c-accent);
}

/* ── coverage state map ────────────────────────────────────────────────────────────────────── */
:where(.sl-body) .coverage-index.has-map .coverage-state { grid-column: 2; grid-row: 1 / span 6; align-self: center; }
:where(.sl-body) .coverage-state { position: relative; }
:where(.sl-body) .sm-svg { width: 100%; height: auto; display: block; overflow: visible; }
:where(.sl-body) .sm-state {
  fill: color-mix(in srgb, var(--c-primary) 10%, transparent);
  stroke: color-mix(in srgb, var(--c-primary) 42%, transparent);
  stroke-width: 1.1;
  stroke-linejoin: round;
}
:where(.sl-body) .sm-halo { fill: color-mix(in srgb, var(--c-accent) 34%, transparent); }
:where(.sl-body) .sm-pin  { fill: var(--c-accent); }
/* ── Zoomed service-area callout ─────────────────────────────────────────────────────────────
   Six towns inside four map units cannot be labelled in place, so the names sit in an evenly
   spaced column joined to their pins by hairlines. The locator underneath shows the framed
   region on the whole state, which is what keeps the zoom legible as a place. */
/* ── REGION MAP — county view ────────────────────────────────────────────────────────────────
   Real jurisdiction outlines, each named inside itself, served ones carrying the accent at three
   strengths so neighbouring counties separate without inventing a second palette. Cities sit on
   top as small pins with their names beside them — no leader lines needed, because at county
   zoom the towns are genuinely far apart. */
:where(.sl-body) .coverage-state.is-region { display: grid; gap: 0.85rem; }
:where(.sl-body) .rm-svg { width: 100%; height: auto; display: block; overflow: visible; }
:where(.sl-body) .rm-area {
  fill: color-mix(in srgb, var(--c-primary) 7%, var(--c-surface));
  stroke: color-mix(in srgb, var(--c-primary) 34%, transparent);
  stroke-width: 1.2; vector-effect: non-scaling-stroke; stroke-linejoin: round;
}
/* Three strengths, far enough apart that adjacent served counties are obviously different
   jurisdictions — the first pass sat at 30/46/62% of a pale gold and read as one wash. */
:where(.sl-body) .rm-served-0 { fill: color-mix(in srgb, var(--c-accent) 78%, var(--c-surface)); }
:where(.sl-body) .rm-served-1 { fill: color-mix(in srgb, var(--c-accent) 48%, var(--c-surface)); }
:where(.sl-body) .rm-served-2 { fill: color-mix(in srgb, var(--c-accent) 100%, var(--c-surface)); }
:where(.sl-body) .rm-served { stroke: color-mix(in srgb, var(--c-primary) 55%, transparent); stroke-width: 1.6; }
:where(.sl-body) .rm-label {
  fill: color-mix(in srgb, var(--c-primary) 62%, var(--c-surface-alt));
  font-family: var(--font-heading), serif; font-weight: 600; letter-spacing: 0.02em;
  text-anchor: middle; dominant-baseline: middle; pointer-events: none;
}
:where(.sl-body) .rm-label.is-served { fill: var(--c-primary); }
:where(.sl-body) .rm-city { fill: var(--c-primary); stroke: var(--c-surface); stroke-width: 1.6; vector-effect: non-scaling-stroke; }
:where(.sl-body) .rm-city-label {
  fill: var(--c-primary); font-family: var(--font-body), sans-serif; font-weight: 500;
  dominant-baseline: middle; paint-order: stroke;
  stroke: color-mix(in srgb, var(--c-surface) 88%, transparent); stroke-width: 3px;
}
/* THE CALLOUT: a pin keeps its place on the map, its NAME sits in the margin, and this line
   carries the identity across the gap. Drawn at 42% of the ink so it reads as a tether rather
   than as a border - at full strength six of them look like a second set of county lines. */
:where(.sl-body) .rm-lead {
  fill: none; stroke: color-mix(in srgb, var(--c-text) 30%, transparent);
  stroke-width: 1; vector-effect: non-scaling-stroke;
  stroke-linecap: round; stroke-linejoin: round; pointer-events: none;
}
:where(.sl-body) .rm-pin-label {
  /* --c-text, not --c-primary: the census beside this file records that the primary used as an
     ink measures about 1.04:1 on a dark ground, and every rule filed under that debt is to be
     rewritten to the role when its section is next opened. This rule is new, so it starts right. */
  fill: var(--c-text); font-family: var(--font-body), sans-serif; font-weight: 500;
  dominant-baseline: middle; pointer-events: none;
}
:where(.sl-body) .rm-legend {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.4rem 1.25rem;
  font-size: 0.78rem; color: var(--c-text-muted); letter-spacing: 0.04em;
}
:where(.sl-body) .rm-key { width: 13px; height: 13px; border-radius: 3px; display: inline-block; margin-right: 0.35rem; vertical-align: -2px; }
:where(.sl-body) .rm-key-served { background: color-mix(in srgb, var(--c-accent) 78%, var(--c-surface)); border: 1px solid color-mix(in srgb, var(--c-primary) 45%, transparent); }
/* The map IS the content of this band — the copy beside it is four short blocks. Give the region
   layout the wider frame and the larger share of it, or the counties render at half the size the
   reference implies. */
:where(.sl-body) .section-service_area_map > .container { max-width: min(1340px, 100%); }
:where(.sl-body) .coverage-index.has-region { grid-template-columns: minmax(0, 0.92fr) minmax(0, 1.08fr); }
:where(.sl-body) .rm-key-city { background: var(--c-primary); border-radius: 50%; width: 11px; height: 11px; }
/* In a navy room the whole plane inverts: unserved land goes dark, labels and pins go light. */
:where(.sl-body) .sec-room .rm-area { fill: color-mix(in srgb, var(--c-on-room) 9%, var(--c-room)); stroke: color-mix(in srgb, var(--c-on-room) 30%, transparent); }
:where(.sl-body) .sec-room .rm-served-0 { fill: color-mix(in srgb, var(--c-accent) 40%, var(--c-primary)); }
:where(.sl-body) .sec-room .rm-served-1 { fill: color-mix(in srgb, var(--c-accent) 26%, var(--c-primary)); }
:where(.sl-body) .sec-room .rm-served-2 { fill: color-mix(in srgb, var(--c-accent) 56%, var(--c-primary)); }
:where(.sl-body) .sec-room .rm-label { fill: color-mix(in srgb, var(--c-on-room) 72%, var(--c-room)); }
:where(.sl-body) .sec-room .rm-label.is-served { fill: var(--c-on-room); }
:where(.sl-body) .sec-room .rm-city { fill: var(--c-on-room); stroke: var(--c-room); }
:where(.sl-body) .sec-room .rm-city-label { fill: var(--c-on-room); stroke: color-mix(in srgb, var(--c-room) 80%, transparent); }
:where(.sl-body) .sec-room .rm-lead { stroke: color-mix(in srgb, var(--c-on-room) 50%, transparent); }
:where(.sl-body) .sec-room .rm-pin-label { fill: var(--c-on-room); }

:where(.sl-body) .coverage-state.is-zoom { display: grid; gap: 0.9rem; }
/* CLIP. The shared .sm-svg sets overflow:visible so a whole-state map can bleed its stroke; at a
   zoom the path continues far outside the viewBox and painted straight across the copy column.
   And the state stroke has to stop scaling with the frame — 1.1 units is a hairline on a 136-unit
   state and a 20px grey band on a 24-unit crop. */
:where(.sl-body) .coverage-state.is-zoom .sm-svg {
  overflow: hidden; aspect-ratio: 1; border-radius: var(--card-radius, 4px);
  background: color-mix(in srgb, var(--c-primary) 4%, transparent);
}
:where(.sl-body) .coverage-state.is-zoom .sm-state { vector-effect: non-scaling-stroke; stroke-width: 1.4; }
/* Map plane, all from the brand palette: water-toned ground outside the state, a soft inland
   gradient on the land, a faint graticule for scale, and a warm wash over the served cluster.
   The gradient stops are vars so a room (navy band) can restate them without new geometry. */
/* Land must read WARM and LIGHT against COOL and DEEP water, or the coastline disappears and the
   panel is one flat grey rectangle with a line through it. The first pass had the land gradient
   ending darker than the water, which is exactly backwards. */
:where(.sl-body) .coverage-state.is-zoom {
  --sm-land-a: color-mix(in srgb, var(--c-surface) 94%, var(--c-accent));
  --sm-land-b: color-mix(in srgb, var(--c-surface-alt) 88%, var(--c-accent));
  --sm-glow: var(--c-accent);
}
/* Navy mixed into a warm beige just makes grey — land and water came out the same value with a
   line between them. Water is mixed toward a cool tint so it reads as water; the tint is derived
   from the brand's own primary (desaturated up, not an arbitrary blue), so it stays on-palette. */
:where(.sl-body) .sm-water { fill: color-mix(in srgb, var(--c-primary) 26%, color-mix(in srgb, var(--c-primary) 8%, #eef2f7)); }
:where(.sl-body) .sm-grat { stroke: color-mix(in srgb, var(--c-primary) 10%, transparent); stroke-width: 1; vector-effect: non-scaling-stroke; }
:where(.sl-body) .sm-wash { pointer-events: none; }
/* The coastline gets a soft drop so the land sits ON the water rather than beside it. */
:where(.sl-body) .coverage-state.is-zoom .sm-state {
  stroke: color-mix(in srgb, var(--c-primary) 52%, transparent);
  filter: drop-shadow(0 2px 5px rgba(16, 24, 40, 0.22));
}
/* Pins are the point of the map: ring them in the card colour so they hold against land or wash. */
:where(.sl-body) .coverage-state.is-zoom .sm-pin { stroke: var(--c-surface); stroke-width: 1.5; vector-effect: non-scaling-stroke; }
:where(.sl-body) .sec-room .coverage-state.is-zoom {
  --sm-land-a: color-mix(in srgb, var(--c-on-room) 16%, var(--c-room));
  --sm-land-b: color-mix(in srgb, var(--c-primary) 88%, #000);
}
:where(.sl-body) .sec-room .sm-water { fill: color-mix(in srgb, var(--c-primary) 92%, #000); }
:where(.sl-body) .sec-room .sm-grat { stroke: color-mix(in srgb, var(--c-on-room) 10%, transparent); }
:where(.sl-body) .sm-leader { stroke: color-mix(in srgb, var(--c-primary) 34%, transparent); stroke-width: 1; vector-effect: non-scaling-stroke; fill: none; }
:where(.sl-body) .sm-label {
  fill: var(--c-text); font-family: var(--font-body), sans-serif; font-weight: 500;
  letter-spacing: 0.01em; dominant-baseline: middle;
}
:where(.sl-body) .sm-locator-wrap { display: flex; align-items: center; gap: 0.6rem; justify-content: flex-start; }
:where(.sl-body) .sm-locator { width: 96px; height: auto; display: block; flex: 0 0 auto; overflow: visible; }
:where(.sl-body) .sm-frame {
  fill: color-mix(in srgb, var(--c-accent) 22%, transparent);
  stroke: var(--c-accent); stroke-width: 1.2; vector-effect: non-scaling-stroke;
}
:where(.sl-body) .sm-locator-cap {
  font-size: 0.72rem; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--c-text-muted); font-weight: 600;
}
/* On a navy band the outline and labels have to invert with the room, same as any other ink. */
:where(.sl-body) .sec-room .sm-label { fill: var(--c-on-room); }
:where(.sl-body) .sec-room .sm-leader { stroke: color-mix(in srgb, var(--c-on-room) 40%, transparent); }
:where(.sl-body) .sec-room .sm-state { fill: color-mix(in srgb, var(--c-on-room) 10%, transparent); stroke: color-mix(in srgb, var(--c-on-room) 38%, transparent); }
:where(.sl-body).refine-dark-luxe .sm-state {
  fill: color-mix(in srgb, var(--c-primary) 14%, transparent);
  stroke: color-mix(in srgb, var(--c-primary) 55%, transparent);
}
@media (max-width: 860px) {
  :where(.sl-body) .coverage-state { max-width: 420px; margin: 1.75rem auto 0; }
}

/* ── marquee_band ──────────────────────────────────────────────────────────────────────────────
   Oversized OUTLINED type tracking across a band, from the client's reference. Two rows moving
   opposite ways so the band reads as motion rather than as a sign.

   overflow:hidden here is not decoration — it is the whole safety of this component. The track is
   deliberately WIDER than the viewport, and an unclipped element that wide is exactly what widened
   the document and clipped every band on mobile once before (the header utility strip). Clip it at
   the section, and it can never reach the page scroll width. */
/* FULL BLEED. The lanes are the band — inside `.container` they render as two stripes floating on
   page stock with beige margins either side, which is not the effect. Kill the container's width
   and padding for this section only, and suppress the framed-plate rule that draws a gold inset
   border around every non-room band in this lane. */
/* The marquee joins .section-trust_strip and .section-service_area_map in the framed-plate rule's
   :not() list up at :4780 — those are the bands that go edge to edge, and that rule (six classes
   deep) is what was holding 30px of page stock down each side of this one. Excluded there rather
   than fought with !important here, so the inset border, the ::after frame and the responsive
   step-down all agree that this band has no margins. */
:where(.sl-body) .section-marquee_band { overflow: hidden; padding: 0; }
/* A marquee IS its two lanes — it must have NO vertical padding. The lanes measure identically
   (125px each), but the section's own 77px of padding is the same cream as the light lane, so it
   read as a light lane twice the height of the dark one AND as a gap before the next section.
   Every art-direction lane sets `.section` padding at its own specificity (addens-airy is (0,3,1)),
   so a class selector here always loses. This band's geometry is not a per-lane choice, which is
   what makes !important the honest answer rather than a specificity race. */
:where(.sl-body) main > section.section.section-marquee_band { padding-top: 0 !important; padding-bottom: 0 !important; }
:where(.sl-body) .section-marquee_band > .container { max-width: none; padding-left: 0; padding-right: 0; }
:where(.sl-body).refine-dark-luxe main > section.section.section-marquee_band::before, :where(.sl-body).refine-dark-luxe main > section.section.section-marquee_band::after { display: none !important; }
/* gap:0 — the two lanes BUTT together. The reference is one dark band sitting directly on one
   light band with no seam of page stock between them. */
:where(.sl-body) .marquee-band { display: grid; gap: 0; }
:where(.sl-body) .mq-lane { overflow: hidden; width: 100%; }
/* ── surfaces.dark = 'marble' ────────────────────────────────────────────────────────────────
   The dark bands take real stone. A scrim in the brand's own navy rides over it so white type is
   guaranteed regardless of where the veining falls, and `background-attachment: fixed` is
   deliberately NOT used — it costs a repaint on every scroll and janks on mobile. One asset,
   one request, every dark band on the site. */
/* :nth-of-type(n) is the specificity bump the band rules themselves carry — `body.bands-paper main
   > section.section.sec-room` paints with the `background` SHORTHAND, which resets
   background-image, so a rule at equal weight declared earlier in the file loses the stone. */
:where(.sl-body).dark-marble main > section.section.sec-room:nth-of-type(n), :where(.sl-body).dark-marble .mq-lane-dark, :where(.sl-body).dark-marble main > section.section.section-hub-cta:nth-of-type(n), :where(.sl-body).dark-marble main > section.section.section-final_cta:nth-of-type(n) {
  background-image:
    linear-gradient(color-mix(in srgb, var(--c-primary) 78%, transparent), color-mix(in srgb, var(--c-primary) 78%, transparent)),
    var(--room-texture);
  background-size: cover, cover;
  background-position: center, center;
}
/* A photo band already carries a photograph — stone on top of it is two textures fighting. */
:where(.sl-body).dark-marble main > section.section.sec-photo { background-image: none; }
/* The closing CTA's inner plate is drawn with `background: … !important`, which resets
   background-image — so the STONE goes on the section and the plate stays what it was always
   meant to be, a scrim over it. 74% was tuned to sit on a texture; over real veining it buries
   the gold, so on a marble site the plate lightens and the stone reads through the whole band. */
/* …and the plate must NOT be drawn when `.final-cta` IS the section. On interior pages the plate
   is an inner element sitting on a stone-painted section, which is what the 46% was tuned for. On
   a hub the same class lands on the <section> itself, so this shorthand — `background`, with
   !important — reset the very background-image the rule above had just given it, and the plate
   composited onto the white body instead of onto stone. Excluding the hub variant lets the stone
   stand as that band's ground. */
:where(.sl-body).dark-marble .final-cta:not(.section-hub-cta) { background: color-mix(in srgb, var(--c-primary-dark) 46%, transparent) !important; }

:where(.sl-body) .mq-lane-dark { background: var(--c-room); }
/* The light lane is the PAGE STOCK, not white. On a paper-rhythm site --c-surface is card white,
   so a white lane read as a foreign stripe cutting through the cream. --c-surface-alt is whatever
   the site's own ground is, which is what makes the dark lane the only thing that interrupts. */
:where(.sl-body) .mq-lane-light { background: var(--c-surface-alt); }
:where(.sl-body) .mq-row { display: flex; width: max-content; will-change: transform; }
:where(.sl-body) .mq-track { display: flex; flex: 0 0 auto; }
:where(.sl-body) .mq-item {
  display: block;
  padding-right: 0.5em;
  font-family: var(--font-heading);
  font-weight: var(--heading-weight, 600);
  font-size: clamp(2.6rem, 9vw, 7rem);
  line-height: 1.12;
  white-space: nowrap;
  /* Outlined, not filled: the reference is stroke-only type. */
  color: transparent;
  -webkit-text-stroke: 1.5px color-mix(in srgb, var(--c-surface) 78%, transparent);
}
/* Lane defaults for brands outside refine-dark-luxe: light ink on the dark lane, dark on the light. */
:where(.sl-body) .mq-lane-dark .mq-item { -webkit-text-stroke-color: color-mix(in srgb, var(--c-on-room) 82%, transparent); }
:where(.sl-body) .mq-lane-light .mq-item { -webkit-text-stroke-color: color-mix(in srgb, var(--c-primary) 78%, transparent); }
/* Translating by exactly -50% moves the row by one full track, so the second track lands where the
   first began and the loop has no seam at any viewport width. */
@keyframes mqLeft  { from { transform: translateX(0); }      to { transform: translateX(-50%); } }
@keyframes mqRight { from { transform: translateX(-50%); }   to { transform: translateX(0); } }
/* 38s moved the track at ~125px/s, which the client called "way too fast" — at that speed a word
   crosses a 1440px screen in eleven seconds and the band reads as a news ticker rather than the
   slow drift in the reference. 120s puts it near 53px/s: legible, ambient, and still clearly moving.

   SPEED HAS TO BE RE-DERIVED PER BREAKPOINT, because the animation moves the row by -50% of ITS
   OWN WIDTH over a FIXED duration — so the apparent px/s falls with the viewport. Measured on the
   live page: 12787px row at 1440 = 53px/s, but 4750px row on an iPhone = 20px/s over the same
   120s. Ian saw it drifting on desktop while everyone he sent the link to, on phones, saw a band
   that looked frozen: 20px/s is under the threshold you notice while scrolling past.
   The durations below hold ~50-53px/s — the speed the client already signed off — at every width,
   by shortening the run in proportion to the row that has to travel. */
:where(.sl-body) .mq-ltr { animation: mqLeft var(--mq-dur, 120s) linear infinite; }
:where(.sl-body) .mq-rtl { animation: mqRight var(--mq-dur, 120s) linear infinite; }
/* Five steps, not two: the item font is `clamp(2.6rem, 9vw, 7rem)`, so the row keeps shrinking
   through the mid widths and a coarse ladder overshoots. Two steps left 640px running at 71px/s —
   faster than the desktop the client tuned. Each duration below is measured, not estimated. */
@media (max-width: 1200px) { :where(.sl-body) .marquee-band { --mq-dur: 100s; } }
@media (max-width:  900px) { :where(.sl-body) .marquee-band { --mq-dur:  84s; } }
@media (max-width:  700px) { :where(.sl-body) .marquee-band { --mq-dur:  62s; } }
@media (max-width:  500px) { :where(.sl-body) .marquee-band { --mq-dur:  46s; } }
@media (prefers-reduced-motion: reduce) {
  :where(.sl-body) .mq-ltr, :where(.sl-body) .mq-rtl { animation: none; transform: translateX(-12%); }
}
/* The LANES paint now, not the section — a section-level fill would show through the light lane. */
/* Stroke colours must come from the BAND's own ink, not from a fixed light value. The second row
   was --c-surface at 55%, i.e. white-on-beige, which measured as good as invisible once the band
   rhythm put this section on the page stock instead of the navy I had assumed. --c-text is
   rebound per band (navy on paper, surface in a room), so both rows stay legible wherever the
   rhythm places this section. */
/* Ink is keyed to the LANE it sits on, not to row order. Keying it to `.mq-row + .mq-row` assumed
   both rows shared one background; now that the lanes are opposite, the second row's stroke has to
   be dark or it is white-on-cream. Gold on the navy lane, navy on the light lane. */

/* ══ COMPOSITION — four more treatments ═══════════════════════════════════════════════════════
   The library had nine, and the auto-assigner only ever reaches for four of them (numbered,
   ledger, split, quiet-prose). The other five are shaped for the content they were designed
   against — a proof wall, a label/value strip, an alternating photo showcase, a full-bleed rest —
   and shredded a reason-list when pointed at one (measured: `statement` and `showcase` broke the
   headline over five lines, `bleed` printed it on top of the cards, `facts` cut the body into
   one-word columns). So a page of reason-lists and step-lists was drawing from a pool of FOUR,
   and that is most of why the middle of a page reads the same however different the copy is.

   These four are structurally different from those four and from each other, not restyled
   versions of them: a dark inset panel, an asymmetric mosaic, a promoted lead statement, and
   colour-blocked swatches. Same content, four genuinely different page rhythms.

   All ride --c-text / --c-text-muted / --c-accent-ink / --c-primary-dark / --c-surface, the pairs
   already measured against every brand's surfaces, so none of them can invent an unmeasured
   contrast — R15 covers them for free. */

/* comp-panel — the whole section becomes ONE dark inset block, reasons as ruled rows inside it.
   The point is the rhythm of the PAGE, not the section: a solid dark panel between two light
   bands is the strongest way to break a run of pale card grids without touching a word of copy. */
/* DESCENDANT, NOT A DIRECT-CHILD CHAIN. `> .container > .section-header` assumed the header is a
   direct child of the container. Several renderers wrap their content in an unnamed measure div
   first, so the chain missed the header entirely — and because this treatment paints the panel
   dark and reverses its ink, missing the header meant a dark heading on a dark panel, measured at
   1:1 contrast and completely invisible. The gate caught it on Vela's vitamin C page. Depth is not
   something a page-level rule should have to know; the same lesson as the eyebrow selector. */
:where(.sl-body) .comp-panel .section-header { text-align: left; margin-left: 0; margin-right: auto; }
:where(.sl-body) .comp-panel > .container {
  background: var(--c-hero-plate);
  color: var(--c-on-dark);
  border-radius: clamp(12px, 1.4vw, 20px);
  padding: clamp(1.9rem, 4vw, 3.4rem);
  max-width: var(--content-max);
}
:where(.sl-body) .comp-panel .section-header h2, :where(.sl-body) .comp-panel .section-header .eyebrow { color: var(--c-on-dark); }
:where(.sl-body) .comp-panel .section-header p { color: color-mix(in srgb, var(--c-surface) 76%, transparent); }
:where(.sl-body) .comp-panel .why-rows, :where(.sl-body) .comp-panel .steps-row:not(.steps-photo) { display: block; gap: 0; }
:where(.sl-body) .comp-panel .why-row, :where(.sl-body) .comp-panel .steps-row:not(.steps-photo) > .card.step-card {
  display: grid;
  grid-template-columns: minmax(0, 32%) minmax(0, 1fr);
  column-gap: clamp(1.2rem, 3vw, 2.4rem);
  align-items: start;
  background: transparent; border: 0; border-radius: 0; box-shadow: none;
  padding: clamp(1.15rem, 2.4vw, 1.8rem) 0;
  border-bottom: 1px solid color-mix(in srgb, var(--c-on-dark) 20%, transparent);
  text-align: left;
}
:where(.sl-body) .comp-panel .why-row:last-child, :where(.sl-body) .comp-panel .steps-row:not(.steps-photo) > .card.step-card:last-child { border-bottom: 0; }
:where(.sl-body) .comp-panel .why-row-head { grid-column: 1; margin: 0; }
:where(.sl-body) .comp-panel .why-row-body { grid-column: 2; margin: 0; }
:where(.sl-body) .comp-panel .why-row-ic, :where(.sl-body) .comp-panel .step-badge, :where(.sl-body) .comp-panel .step-ic { display: none; }
:where(.sl-body) .comp-panel h3, :where(.sl-body) .comp-panel .card h3 { color: var(--c-on-dark); margin: 0; }
:where(.sl-body) .comp-panel .why-row-body, :where(.sl-body) .comp-panel .step-card p {
  color: color-mix(in srgb, var(--c-surface) 78%, transparent) !important;
}
@media (max-width: 720px) {
  :where(.sl-body) .comp-panel .why-row, :where(.sl-body) .comp-panel .steps-row:not(.steps-photo) > .card.step-card {
    grid-template-columns: minmax(0, 1fr); row-gap: 0.55rem;
  }
  :where(.sl-body) .comp-panel .why-row-body { grid-column: 1; }
}

/* comp-mosaic — the first reason is the big one. Three equal boxes is the shape that reads as a
   template; promoting the lead item to full width with display-scale type says which reason
   actually matters, and makes the row a composition instead of a list. */
:where(.sl-body) .comp-mosaic .why-rows, :where(.sl-body) .comp-mosaic .steps-row:not(.steps-photo) {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(0.9rem, 1.9vw, 1.5rem);
  align-items: stretch;
}
:where(.sl-body) .comp-mosaic .why-row, :where(.sl-body) .comp-mosaic .steps-row:not(.steps-photo) > .card.step-card {
  /* .why-row ships as its own two-column grid (head | body). Every treatment that re-grids the
     CONTAINER has to unwind the ROW first, or head and body stay side by side inside a column that
     is now half as wide, and the title wraps one word per line. Cost three of these four on the
     first pass; comp-panel only survived because it assigns those two columns explicitly. */
  display: block;
  text-align: left;
  padding: clamp(1.25rem, 2.6vw, 1.9rem);
  border-radius: clamp(10px, 1.2vw, 16px);
  border: 1px solid color-mix(in srgb, var(--c-text) 12%, transparent);
  background: var(--c-surface);
  box-shadow: none;
}
:where(.sl-body) .comp-mosaic .why-rows > .why-row:first-child, :where(.sl-body) .comp-mosaic .steps-row:not(.steps-photo) > .card.step-card:first-child {
  grid-column: 1 / -1;
  background: color-mix(in srgb, var(--c-primary-dark) 6%, var(--c-surface));
  border-color: color-mix(in srgb, var(--c-primary-dark) 18%, transparent);
  padding: clamp(1.7rem, 3.4vw, 2.6rem);
}
/* The lead card is CENTRED. Left-set, its title took a third of a full-width card and left the
   rest empty — Ian: "every time there's just a ton of blank space in it". Centring gives the
   promoted item the presence the promotion was for. */
:where(.sl-body) .comp-mosaic .why-rows > .why-row:first-child, :where(.sl-body) .comp-mosaic .steps-row:not(.steps-photo) > .card.step-card:first-child { text-align: center; }
:where(.sl-body) .comp-mosaic .why-rows > .why-row:first-child .why-row-head { justify-content: center; }
:where(.sl-body) .comp-mosaic .why-rows > .why-row:first-child h3, :where(.sl-body) .comp-mosaic .steps-row:not(.steps-photo) > .card.step-card:first-child h3 {
  font-size: clamp(1.35rem, 2.9vw, 2rem); line-height: 1.15; text-wrap: balance;
}
:where(.sl-body) .comp-mosaic .why-rows > .why-row:first-child .why-row-body { max-width: 62ch; margin-inline: auto; }
:where(.sl-body) .comp-mosaic .why-row-ic { margin-bottom: 0.5rem; }
@media (max-width: 640px) {
  :where(.sl-body) .comp-mosaic .why-rows, :where(.sl-body) .comp-mosaic .steps-row:not(.steps-photo) { grid-template-columns: minmax(0, 1fr); }
}

/* comp-callout — the lead reason promoted OUT of the grid entirely, set as a centred statement at
   reading measure, with the remainder as quiet ruled supports underneath. Where mosaic makes the
   first item bigger, this makes it a different KIND of thing: an argument, then its evidence. */
:where(.sl-body) .comp-callout .why-rows, :where(.sl-body) .comp-callout .steps-row:not(.steps-photo) {
  /* FLEX, not auto-fit grid. `repeat(auto-fit, minmax(220px, 1fr))` sizes tracks to the CONTAINER,
     so a wide band made four tracks and the two supporting reasons filled the leftmost two —
     half the row empty. Flex distributes across however many items there actually are, which is
     what a support row needs when the count is 2 on one page and 5 on the next. */
  display: flex;
  /* `.why-rows` ships as flex-direction: column, so a flex-basis set here sized HEIGHT and every
     support ran full width on its own line. Direction has to be stated, not assumed. */
  flex-direction: row;
  flex-wrap: wrap;
  gap: clamp(1rem, 2.2vw, 1.8rem);
}
:where(.sl-body) .comp-callout .why-rows > .why-row, :where(.sl-body) .comp-callout .steps-row:not(.steps-photo) > .card.step-card { flex: 1 1 clamp(200px, 22%, 300px); }
:where(.sl-body) .comp-callout .why-row, :where(.sl-body) .comp-callout .steps-row:not(.steps-photo) > .card.step-card {
  display: block;   /* unwind the row's own head|body grid — see comp-mosaic */
  background: transparent; border: 0; box-shadow: none; border-radius: 0;
  padding: clamp(1rem, 2vw, 1.4rem) 0 0;
  border-top: 2px solid color-mix(in srgb, var(--c-accent-ink) 34%, transparent);
  text-align: left;
}
:where(.sl-body) .comp-callout .why-rows > .why-row:first-child, :where(.sl-body) .comp-callout .steps-row:not(.steps-photo) > .card.step-card:first-child {
  flex: 0 0 100%;
  border-top: 0;
  text-align: center;
  /* The reading measure belongs to the TEXT, not to the flex item. Capping the item at 62ch left
     it only half the band wide, so the two supports slid up beside it and the lead stopped being
     a lead. The item takes the full row; its h3 and body carry the measure. */
  max-width: none;
  margin: 0 0 clamp(0.6rem, 1.6vw, 1.2rem);
  padding-bottom: clamp(1.2rem, 2.6vw, 2rem);
}
:where(.sl-body) .comp-callout .why-rows > .why-row:first-child > * { max-width: 62ch; margin-inline: auto; }
:where(.sl-body) .comp-callout .why-rows > .why-row:first-child h3, :where(.sl-body) .comp-callout .steps-row:not(.steps-photo) > .card.step-card:first-child h3 {
  font-size: clamp(1.45rem, 3.2vw, 2.3rem); line-height: 1.16; margin-bottom: 0.6rem;
}
:where(.sl-body) .comp-callout .why-rows > .why-row:first-child .why-row-body {
  font-size: clamp(1rem, 1.25vw, 1.12rem);
}
:where(.sl-body) .comp-callout .why-rows > .why-row:first-child .why-row-head { justify-content: center; }
:where(.sl-body) .comp-callout .why-row-ic, :where(.sl-body) .comp-callout .step-badge { display: none; }
:where(.sl-body) .comp-callout .why-row h3 { margin-bottom: 0.4rem; }

/* comp-swatch — colour-blocked. Each reason's title is reversed out of a solid brand block and its
   body sits on the page below, so the row reads as colour first and copy second. The blocks step
   through three mixes of the brand pair rather than repeating one navy, because three identical
   coloured boxes is the same monotony as three identical white ones. */
:where(.sl-body) .comp-swatch .why-rows, :where(.sl-body) .comp-swatch .steps-row:not(.steps-photo) {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), minmax(0, 1fr)));
  gap: clamp(1rem, 2.1vw, 1.7rem);
  align-items: start;
}
:where(.sl-body) .comp-swatch .why-row, :where(.sl-body) .comp-swatch .steps-row:not(.steps-photo) > .card.step-card {
  display: block;   /* unwind the row's own head|body grid — see comp-mosaic */
  background: transparent; border: 0; box-shadow: none; padding: 0;
  border-radius: clamp(10px, 1.2vw, 16px);
  overflow: hidden; text-align: left;
}
/* Title CENTRED in the block, not hung off its bottom-left corner. Bottom-left is a poster
   convention and it read as misalignment at card scale — Ian: "the location just looks odd". */
:where(.sl-body) .comp-swatch .why-row-head {
  background: var(--c-hero-plate);
  padding: clamp(1.2rem, 2.5vw, 1.9rem);
  min-height: clamp(6.5rem, 11vw, 9rem);
  display: flex; align-items: center; justify-content: center; text-align: center; margin: 0;
  border-radius: clamp(10px, 1.2vw, 16px);
}
:where(.sl-body) .comp-swatch .why-row:nth-child(3n + 2) .why-row-head {
  background: color-mix(in srgb, var(--c-primary-dark) 72%, var(--c-accent));
}
:where(.sl-body) .comp-swatch .why-row:nth-child(3n) .why-row-head {
  background: color-mix(in srgb, var(--c-primary-dark) 84%, var(--c-surface));
}
:where(.sl-body) .comp-swatch .why-row-head h3 { color: var(--c-on-dark); margin: 0; }
:where(.sl-body) .comp-swatch .why-row-ic { display: none; }
:where(.sl-body) .comp-swatch .why-row-body { padding: clamp(0.85rem, 1.7vw, 1.15rem) 0.15rem 0; margin: 0; }
/* A STEP CARD HAS NO `.why-row-head`, so every colour block above missed it and the treatment
   delivered nothing on `.steps-row` but the removal of the card — three columns of plain text with
   the numbered discs still floating over them. Worse than a no-op, because it looks deliberate.
   The step card's own `h3` is the equivalent element, so it takes the same block, the same
   three-way cadence and the same reversed ink. The badge goes: a gradient disc hovering above a
   solid colour block is the default's furniture left on top of a new design. */
:where(.sl-body) .comp-swatch .steps-row:not(.steps-photo) > .card.step-card > h3 {
  background: var(--c-hero-plate);
  color: var(--c-on-dark);
  margin: 0;
  padding: clamp(1.2rem, 2.5vw, 1.9rem);
  min-height: clamp(6.5rem, 11vw, 9rem);
  display: flex; align-items: center; justify-content: center; text-align: center;
  border-radius: clamp(10px, 1.2vw, 16px);
}
:where(.sl-body) .comp-swatch .steps-row:not(.steps-photo) > .card.step-card:nth-child(3n + 2) > h3 {
  background: color-mix(in srgb, var(--c-primary-dark) 72%, var(--c-accent));
}
:where(.sl-body) .comp-swatch .steps-row:not(.steps-photo) > .card.step-card:nth-child(3n) > h3 {
  background: color-mix(in srgb, var(--c-primary-dark) 84%, var(--c-surface));
}
:where(.sl-body) .comp-swatch .steps-row:not(.steps-photo) > .card.step-card > p {
  padding: clamp(0.85rem, 1.7vw, 1.15rem) 0.15rem 0; margin: 0; text-align: left;
}
:where(.sl-body) .comp-swatch .step-badge, :where(.sl-body) .comp-swatch .step-ic { display: none; }

/* ══ SECTION BACKGROUND IMAGERY — a photograph behind the band, not another flat colour ═══════
   Ian, reviewing the treatment library: "it's not being imaginative or creative… instead of
   creating imagery and making new visual elements, it's thinking about how to FORMAT the section."
   He is right, and this is the correction. Every treatment before this one differentiates by
   moving type around; that is how you end up with a chimney-width headline and call it a design.
   This adds something to look at instead.
   "It really brings life to a website when you use an image as a background in some sections,
   rather than just colors all the time."

   NOT the same thing as .sec-photo. That is a dark full-bleed band that inverts the ink to white
   and takes the section over. This is a GHOST: the photograph sits at low opacity behind ordinary
   copy in ordinary colours, so the band gains depth and texture and nothing about its contrast
   changes. That matters practically — R15 measures painted ink against painted ground, and a
   treatment that leaves both alone cannot fail it.

   The image never touches the ink:
     • it lives on a ::before at z-index 0 with the container lifted above it
     • it is capped at --sec-bg-strength (default 0.16) — a texture, not a picture
     • it is masked to fade out top and bottom, so the band still reads as a band and there is no
       hard horizontal edge across the page (the same defect R19 catches on heroes; this cannot
       reintroduce it because the mask ends transparent by construction)
     • a scrim of the section's own surface colour sits between photo and copy, so the ground
       under the type stays the ground the type was measured against

   Turn on per section with theme.surfaces.bg_photos:
     [{ "section": "why_local_grid", "image": "https://…", "strength": 0.2 }]
   Absent => no class => byte-identical output. */
:where(.sl-body) main > section.section.sec-bg-photo {
  position: relative;
  isolation: isolate;
  overflow: hidden;
}
:where(.sl-body) main > section.section.sec-bg-photo::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image: var(--sec-bg-img);
  background-size: cover;
  background-position: var(--sec-bg-pos, center);
  background-repeat: no-repeat;
  opacity: var(--sec-bg-strength, 0.16);
  /* Fades to nothing at both edges, so the photograph never ends on a line. */
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 14%, #000 86%, transparent 100%);
  mask-image: linear-gradient(to bottom, transparent 0%, #000 14%, #000 86%, transparent 100%);
}
/* The scrim: the band's own surface, thinned, between the photograph and the copy. Without it a
   busy image reads THROUGH body text even at 16% — legibility must not depend on which photo a
   client happened to upload. */
:where(.sl-body) main > section.section.sec-bg-photo::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: linear-gradient(to bottom,
    color-mix(in srgb, var(--c-surface) 62%, transparent) 0%,
    color-mix(in srgb, var(--c-surface) 38%, transparent) 45%,
    color-mix(in srgb, var(--c-surface) 62%, transparent) 100%);
}
:where(.sl-body) main > section.section.sec-bg-photo > .container { position: relative; z-index: 1; }

/* On a DARK band the ghost works the same way, but the scrim has to be the dark surface or the
   photograph washes the room out to grey. */
:where(.sl-body) main > section.section.sec-bg-photo.sec-room::after {
  background: linear-gradient(to bottom,
    color-mix(in srgb, var(--c-primary-dark) 66%, transparent) 0%,
    color-mix(in srgb, var(--c-primary-dark) 44%, transparent) 45%,
    color-mix(in srgb, var(--c-primary-dark) 66%, transparent) 100%);
}
/* AND SO DOES A BAND THAT PAINTS ITS OWN DARK GROUND FROM THIS FILE.

   `.sec-room` above is the marker for a dark band, and the coverage band does not carry it: its
   darkness comes from the gradient rule near the top of this file, which is !important and
   therefore invisible to everything that reasons about grounds. So when a background photograph
   landed on it, the scrim above chose the LIGHT stock, laid 38-62% of near-white over a dark band,
   and the white type it was protecting fell to 2.1:1 against it - measured by photo-text on a real
   build, seven lines unreadable on one page. The picture was legible; the words were not.

   The scrim has to follow the ground the band ACTUALLY paints, not the ground the planner recorded
   for it. These five keys are the same list the gradient rule paints, and the two must stay
   together - a band added to one and not the other gets a white veil over a dark ground again.
   The light map modes are excluded because in those modes the band really is light, and they
   already restate their own colours below. */
:where(.sl-body) main > section.section.sec-bg-photo:is(.section-service_area_map, :where(.sl-body) .section-service_areas, :where(.sl-body) .section-areas, :where(.sl-body) .section-locations, :where(.sl-body) .section-coverage_area)::after {
  background: linear-gradient(to bottom,
    color-mix(in srgb, var(--c-primary-dark) 66%, transparent) 0%,
    color-mix(in srgb, var(--c-primary-dark) 44%, transparent) 45%,
    color-mix(in srgb, var(--c-primary-dark) 66%, transparent) 100%);
}
:where(.sl-body):is(.map-index, :where(.sl-body) .map-panel) main > section.section.sec-bg-photo:is(.section-service_area_map, :where(.sl-body) .section-service_areas, :where(.sl-body) .section-areas, :where(.sl-body) .section-locations, :where(.sl-body) .section-coverage_area)::after {
  background: linear-gradient(to bottom,
    color-mix(in srgb, var(--c-surface) 62%, transparent) 0%,
    color-mix(in srgb, var(--c-surface) 38%, transparent) 45%,
    color-mix(in srgb, var(--c-surface) 62%, transparent) 100%);
}
/* comp-panel paints its own dark container, so the ghost belongs OUTSIDE it — behind the band,
   around the panel, which is where it reads as depth rather than as noise under the type. */
:where(.sl-body) main > section.section.sec-bg-photo.comp-panel::after {
  background: linear-gradient(to bottom,
    color-mix(in srgb, var(--c-surface) 70%, transparent) 0%,
    color-mix(in srgb, var(--c-surface) 50%, transparent) 45%,
    color-mix(in srgb, var(--c-surface) 70%, transparent) 100%);
}
@media (prefers-reduced-motion: no-preference) {
  /* No parallax, deliberately: a background that moves at a different rate to the copy is the
     single most dated effect available, and it costs a repaint on every scroll frame. */
  :where(.sl-body) main > section.section.sec-bg-photo::before { background-attachment: scroll; }
}

/* ══ CARD TREATMENTS — the card as a visual object, not a rearranged one ══════════════════════
   Ian: "we need different cards, different-looking cards. All the different visual elements in
   here need to look different. Rather than just formatting them and arranging them in a different
   way." Everything before this differentiated by moving type; these change what the card IS.

   AND THEY CLOSE A REAL HOLE. `why_us` renders `.whyus-grid > .whyus-card` and NO treatment in the
   library had ever styled it — every comp-* landing there was a silent no-op, until comp-panel
   painted a dark container under white cards and produced white-on-white at 1:1 on 38 pages. These
   four are the first treatments that actually dress it, so the most common "reasons" section on
   every site finally has something to wear.

   Each dresses all three card shapes — .whyus-card, .cards-center > .card, .steps-row > .step-card
   — so one treatment covers the reasons block, the feature grid and the step rail.

   Ink rides the measured pairs (--c-text / --c-text-muted / --c-accent-ink / --c-surface /
   --c-primary-dark) throughout. None of these invents a colour, so R15 covers all four for free —
   which is exactly what comp-panel failed to do on a shape it did not know about. */

/* ── comp-cards-numeral — a ghosted numeral behind each card ─────────────────────────────────
   The counter sits BEHIND the copy as a watermark rather than beside it: it reads as depth and
   sequence at a glance, and it costs no horizontal space, so the copy measure is unchanged. This
   is the difference from comp-numbered, which hangs a numeral in its own column and turns the row
   into a list. */
:where(.sl-body) .comp-cards-numeral .whyus-grid, :where(.sl-body) .comp-cards-numeral .cards-center, :where(.sl-body) .comp-cards-numeral .steps-row:not(.steps-photo) { counter-reset: cnum; }
:where(.sl-body) .comp-cards-numeral .whyus-card, :where(.sl-body) .comp-cards-numeral .cards-center > .card, :where(.sl-body) .comp-cards-numeral .steps-row:not(.steps-photo) > .card.step-card {
  counter-increment: cnum;
  position: relative;
  overflow: hidden;
  isolation: isolate;
  text-align: left;
  padding: clamp(1.5rem, 3vw, 2.2rem);
  border: 1px solid color-mix(in srgb, var(--c-text) 12%, transparent);
  border-radius: clamp(10px, 1.2vw, 16px);
  background: var(--c-surface);
}
:where(.sl-body) .comp-cards-numeral .whyus-card::before, :where(.sl-body) .comp-cards-numeral .cards-center > .card::before, :where(.sl-body) .comp-cards-numeral .steps-row:not(.steps-photo) > .card.step-card::before {
  content: counter(cnum, decimal-leading-zero);
  position: absolute;
  /* FULLY INSIDE THE CARD. The first pass hung it off the bottom-right corner at -0.3em and
     `overflow: hidden` sliced every numeral in half — which reads as a rendering bug, not as a
     watermark. A bleed has to look deliberate or not happen at all. */
  right: clamp(0.6rem, 1.4vw, 1.1rem);
  bottom: clamp(0.2rem, 0.8vw, 0.6rem);
  z-index: -1;
  font-family: var(--font-heading);
  font-size: clamp(3.4rem, 6.5vw, 5.4rem);
  line-height: 0.86;
  font-weight: 700;
  /* 10% of the brand dark — present, never competing with the copy sitting over it. */
  color: color-mix(in srgb, var(--c-primary-dark) 10%, transparent);
  pointer-events: none;
}
:where(.sl-body) .comp-cards-numeral .why-row-ic, :where(.sl-body) .comp-cards-numeral .step-badge, :where(.sl-body) .comp-cards-numeral .step-ic { display: none; }

/* ── comp-cards-accent — a colour edge, stepping through the brand pair ───────────────────────
   A weighted rule across the top of each card, each one a different mix of the brand's two
   colours. The cheapest way to make a row of cards read as a designed set rather than three
   repetitions, and it survives any card content because it touches only the edge. */
:where(.sl-body) .comp-cards-accent .whyus-card, :where(.sl-body) .comp-cards-accent .cards-center > .card, :where(.sl-body) .comp-cards-accent .steps-row:not(.steps-photo) > .card.step-card {
  position: relative;
  text-align: left;
  padding: clamp(1.5rem, 3vw, 2.1rem);
  border: 1px solid color-mix(in srgb, var(--c-text) 10%, transparent);
  border-radius: clamp(10px, 1.2vw, 16px);
  background: var(--c-surface);
  box-shadow: 0 1px 2px color-mix(in srgb, var(--c-primary-dark) 6%, transparent);
  overflow: hidden;
}
:where(.sl-body) .comp-cards-accent .whyus-card::before, :where(.sl-body) .comp-cards-accent .cards-center > .card::before, :where(.sl-body) .comp-cards-accent .steps-row:not(.steps-photo) > .card.step-card::before {
  content: '';
  position: absolute; inset: 0 0 auto 0; height: 5px;
  background: var(--c-primary-dark);
}
:where(.sl-body) .comp-cards-accent .whyus-card:nth-child(3n + 2)::before, :where(.sl-body) .comp-cards-accent .cards-center > .card:nth-child(3n + 2)::before, :where(.sl-body) .comp-cards-accent .steps-row:not(.steps-photo) > .card.step-card:nth-child(3n + 2)::before {
  background: color-mix(in srgb, var(--c-primary-dark) 55%, var(--c-accent));
}
:where(.sl-body) .comp-cards-accent .whyus-card:nth-child(3n)::before, :where(.sl-body) .comp-cards-accent .cards-center > .card:nth-child(3n)::before, :where(.sl-body) .comp-cards-accent .steps-row:not(.steps-photo) > .card.step-card:nth-child(3n)::before {
  background: color-mix(in srgb, var(--c-accent) 78%, var(--c-primary-dark));
}

/* ── comp-cards-stagger — the row stops being a straight line ─────────────────────────────────
   Alternate cards drop by a step and take a tint. Three cards on one baseline is the single most
   template-looking arrangement there is; breaking the baseline is what makes a row look composed.
   Only above the breakpoint — stacked on a phone there is no row to break, and the offset would
   just be uneven gaps. */
/* Prefixed 2026-08-09 per rule 3: the .whyus-card selector sat at (0,2,0) and lost its plate to
   lane .whyus-card rules at (0,2,1) — the same treatment applied on cards-center and
   half-applied on whyus-grid, which is the split the shape contract exists to prevent. */
:where(.sl-body) main > section.section.comp-cards-stagger .whyus-card, :where(.sl-body) main > section.section.comp-cards-stagger .cards-center > .card, :where(.sl-body) main > section.section.comp-cards-stagger .steps-row:not(.steps-photo) > .card.step-card {
  text-align: left;
  padding: clamp(1.5rem, 3vw, 2.1rem);
  border: 0;
  border-radius: clamp(10px, 1.2vw, 16px);
  background: color-mix(in srgb, var(--c-primary-dark) 5%, var(--c-surface));
}
@media (min-width: 861px) {
  :where(.sl-body) main > section.section.comp-cards-stagger .whyus-grid, :where(.sl-body) main > section.section.comp-cards-stagger .cards-center, :where(.sl-body) main > section.section.comp-cards-stagger .steps-row:not(.steps-photo) { align-items: start; }
  :where(.sl-body) main > section.section.comp-cards-stagger .whyus-card:nth-child(even), :where(.sl-body) main > section.section.comp-cards-stagger .cards-center > .card:nth-child(even), :where(.sl-body) main > section.section.comp-cards-stagger .steps-row:not(.steps-photo) > .card.step-card:nth-child(even) {
    transform: translateY(clamp(1rem, 2.6vw, 2.4rem));
    background: color-mix(in srgb, var(--c-accent) 9%, var(--c-surface));
  }
}

/* ── comp-cards-glass — translucent cards, ONLY on a band with a photograph behind it ─────────
   REQUIRES `sec-bg-photo` on the same section, and the assigner enforces it. Frosted cards over a
   flat colour are just cards with a slightly different white — measured side by side against the
   default they were indistinguishable, which makes it a treatment that costs a rotation slot and
   changes nothing. Over a photograph it is the one card style that lets the image read THROUGH the
   row instead of being walled off behind it.
   Built to pair with `theme.surfaces.bg_photos`: frosted cards let the background photograph read
   THROUGH the row instead of being hidden behind a wall of solid boxes, which is what makes the
   image feel like part of the design rather than wallpaper.
   The ground under the type is still ~78% surface, so the measured contrast pair is intact — a
   glass card over a bright photo is exactly where a naive implementation goes unreadable. */
:where(.sl-body) .comp-cards-glass .whyus-card, :where(.sl-body) .comp-cards-glass .cards-center > .card, :where(.sl-body) .comp-cards-glass .steps-row:not(.steps-photo) > .card.step-card {
  text-align: left;
  padding: clamp(1.5rem, 3vw, 2.1rem);
  border: 1px solid color-mix(in srgb, var(--c-on-dark) 70%, transparent);
  border-radius: clamp(12px, 1.4vw, 18px);
  background: color-mix(in srgb, var(--c-surface) 78%, transparent);
  -webkit-backdrop-filter: blur(9px) saturate(1.15);
  backdrop-filter: blur(9px) saturate(1.15);
  box-shadow: 0 12px 30px -22px color-mix(in srgb, var(--c-primary-dark) 55%, transparent);
}
/* No backdrop-filter (older Safari, Firefox with it disabled) means the translucency would be the
   only thing separating copy from a photograph. Fall back to an opaque card: less pretty, still
   legible, and legibility is not the part we gamble. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  :where(.sl-body) .comp-cards-glass .whyus-card, :where(.sl-body) .comp-cards-glass .cards-center > .card, :where(.sl-body) .comp-cards-glass .steps-row:not(.steps-photo) > .card.step-card {
    background: color-mix(in srgb, var(--c-surface) 94%, transparent);
  }
}

/* Shared: these four all set their card text hard-left, so a centred title inside would fight it. */
:where(.sl-body) .comp-cards-numeral .whyus-title, :where(.sl-body) .comp-cards-accent .whyus-title, :where(.sl-body) .comp-cards-stagger .whyus-title, :where(.sl-body) .comp-cards-glass .whyus-title { text-align: left; }

/* ══ CATEGORY-TILE TREATMENTS — the highest-volume shape with no coverage ═════════════════════
   `.cat-grid` is rendered by treatment_categories, browse_categories, common_symptoms,
   when_to_get and symptom_first_browse — the "pick your thing" grid, on nearly every page of
   every site — and NO treatment in the library dressed it. The audit put common_symptoms and
   when_to_get at six untreated occurrences each on one site alone.

   The default is a centred icon disc over a label in a bordered box. Fine, and the same on every
   site, on every page, for every one of those five sections. These two change what the tile IS. */

/* ── comp-cats-portrait — the tile becomes a panel ────────────────────────────────────────────
   Taller, hard-left, with the icon lifted into a large soft square and the label set at heading
   scale. The centred-disc-over-caption arrangement reads as a button; this reads as a card you
   are meant to look at, which is what a "browse the menu" grid actually wants. */
/* No gap override: the base gap is part of what cardBasis balanced against. See comp-cats-rule. */
:where(.sl-body) .comp-cats-portrait .cat-card {
  flex-direction: column;
  align-items: flex-start;
  justify-content: flex-start;
  text-align: left;
  gap: clamp(0.7rem, 1.6vw, 1.1rem);
  min-height: clamp(150px, 17vw, 200px);
  padding: clamp(1.25rem, 2.6vw, 1.8rem);
  border-radius: clamp(12px, 1.4vw, 18px);
  background: color-mix(in srgb, var(--c-primary-dark) 4%, var(--c-surface));
  border-color: color-mix(in srgb, var(--c-primary-dark) 12%, transparent);
  box-shadow: none;
}
:where(.sl-body) .comp-cats-portrait .cat-ic {
  width: clamp(44px, 5vw, 58px);
  height: clamp(44px, 5vw, 58px);
  border-radius: clamp(10px, 1.1vw, 14px);   /* square, not a disc — the tell that it is a panel */
  background: var(--c-primary-dark);
  color: var(--c-on-dark);
  box-shadow: none;
}
:where(.sl-body) .comp-cats-portrait .cat-card > span { font-size: clamp(1rem, 1.35vw, 1.12rem); font-weight: 600; line-height: 1.25; }
:where(.sl-body) .comp-cats-portrait .cat-card:hover {
  transform: none;
  border-color: color-mix(in srgb, var(--c-primary-dark) 34%, transparent);
  background: color-mix(in srgb, var(--c-primary-dark) 7%, var(--c-surface));
}

/* ── comp-cats-rule — no boxes at all ─────────────────────────────────────────────────────────
   Hairline-separated rows with the icon inline before the label. Where portrait adds weight, this
   removes it: a page that already carries two card grids does not need a third, and the same
   content as a ruled index is the quiet beat the composition rhythm was always reaching for.
   The icon keeps its accent so the row is still scannable at a glance. */
/* KEEPS THE BASE FLEX LAYOUT. `.cat-grid` is a flex row whose `--sl-basis` is computed per section
   by cardBasis(n) precisely so N cards land in balanced rows. Re-gridding it to auto-fit threw that
   away and produced 8 cards as 3+3+2 and 10 as 3+3+3+1 — a lone orphan, which visual-lint R16
   exists to catch and did. The treatment changes what a card LOOKS like; the row maths is not its
   business. */
:where(.sl-body) .comp-cats-rule .cat-grid {
  justify-content: flex-start;
  /* COLUMN gap must match the base 1.25rem exactly. Widening it to 3rem fitted one fewer card per
     row, which turned a balanced 4+4 into 3+3+2 — the same orphan R16 caught on the grid rewrite.
     cardBasis() balanced the row against the base gutter, so any treatment that changes the gutter
     is silently changing the row count. Row gap goes to 0 because the hairline IS the separation. */
  column-gap: 1.25rem;
  row-gap: 0;
}
:where(.sl-body) .comp-cats-rule .cat-card {
  flex: 0 1 var(--sl-basis, 240px);
  flex-direction: row;
  align-items: center;
  justify-content: flex-start;
  gap: clamp(0.75rem, 1.6vw, 1.1rem);
  min-height: 0;
  text-align: left;
  padding: clamp(0.9rem, 1.9vw, 1.25rem) 0;
  background: transparent;
  border: 0;
  border-bottom: 1px solid color-mix(in srgb, var(--c-text) 14%, transparent);
  border-radius: 0;
  box-shadow: none;
}
:where(.sl-body) .comp-cats-rule .cat-card:hover {
  transform: none;
  box-shadow: none;
  border-bottom-color: color-mix(in srgb, var(--c-accent-ink) 55%, transparent);
}
:where(.sl-body) .comp-cats-rule .cat-ic {
  width: clamp(30px, 3.4vw, 38px);
  height: clamp(30px, 3.4vw, 38px);
  flex: 0 0 auto;
  background: transparent;
  color: var(--c-accent-ink);
  box-shadow: none;
}
:where(.sl-body) .comp-cats-rule .cat-ic svg { width: 21px; height: 21px; }
:where(.sl-body) .comp-cats-rule .cat-card > span { font-size: 1rem; font-weight: 600; }
/* The "view all" tile is a call to action, not another row — it keeps its chrome so it does not
   vanish into the index it sits at the end of. */
:where(.sl-body) .comp-cats-rule .cat-card.cat-card-all {
  border-bottom: 0;
  color: var(--c-accent-ink);
  font-weight: 700;
}

/* ══ FAQ TREATMENTS — the accordion had exactly one ═══════════════════════════════════════════
   `.faq-list` is on nearly every page (the audit counted ten untreated `faq` occurrences on one
   site alone) and `comp-split` was the only treatment in the library that selected it. One option
   is not a rotation, so in practice every FAQ on every site rendered identically: hairline rows,
   17px question, chevron right.

   Both of these keep `<details>` semantics untouched — the disclosure widget is doing real work
   and no treatment gets to break it. */

/* ── comp-faq-ruled — the question set as a heading ───────────────────────────────────────────
   Question at heading scale with generous air between rows, answer at reading measure, and a rule
   only under an OPEN item so the closed list reads as a clean index rather than a ledger. This is
   the treatment for a page whose FAQ is the main event — a condition page, a pricing page. */
/* Selectors prefixed `main > section.section` 2026-08-09 per this library's own rule 3
   (docs/SECTION-LIBRARY.md): unprefixed, the whole block sat at (0,2,0) and every lane .faq-item
   rule at (0,2,1) beat it — refine-pill-porcelain's `border: 0` erased the ruled hairlines while
   its plate stayed, leaving plates with no separators, no gap and no design. Half-applied is
   worse than not applied. */
:where(.sl-body) main > section.section.comp-faq-ruled .faq-list { max-width: min(var(--content-max), 60rem); }
:where(.sl-body) main > section.section.comp-faq-ruled .faq-item {
  border-bottom: 1px solid color-mix(in srgb, var(--c-text) 10%, transparent);
}
:where(.sl-body) main > section.section.comp-faq-ruled .faq-item > summary {
  padding: clamp(1.15rem, 2.4vw, 1.75rem) 0;
  font-size: clamp(1.05rem, 1.55vw, 1.3rem);
  font-weight: 600;
  line-height: 1.32;
  gap: clamp(1rem, 2.5vw, 2rem);
}
:where(.sl-body) main > section.section.comp-faq-ruled .faq-item[open] > summary { padding-bottom: clamp(0.5rem, 1.1vw, 0.85rem); }
:where(.sl-body) main > section.section.comp-faq-ruled .faq-item > p {
  font-size: 1rem;
  line-height: 1.72;
  padding-bottom: clamp(1.2rem, 2.4vw, 1.8rem);
  max-width: 68ch;
}
/* The chevron becomes a hairline circle — at this type size a bare glyph reads as debris. */
:where(.sl-body) main > section.section.comp-faq-ruled .faq-item .faq-chevron {
  width: clamp(28px, 3vw, 34px); height: clamp(28px, 3vw, 34px);
  display: grid; place-items: center; border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--c-text) 18%, transparent);
  color: var(--c-accent-ink);
}

/* ── comp-faq-cards — each question its own panel ─────────────────────────────────────────────
   Boxed, spaced, with the open panel lifting onto the brand's own tint. Where ruled is quiet, this
   gives an FAQ presence on a page that is otherwise all prose — and the gaps between panels stop a
   twelve-question list reading as a wall of hairlines. */
/* Prefixed 2026-08-09, same reason as comp-faq-ruled above: at (0,2,0) this block lost its
   border and radius to any lane's (0,2,1) .faq-item plate and shipped half-applied. */
:where(.sl-body) main > section.section.comp-faq-cards .faq-list {
  display: flex; flex-direction: column;
  gap: clamp(0.6rem, 1.3vw, 0.95rem);
  max-width: min(var(--content-max), 62rem);
}
:where(.sl-body) main > section.section.comp-faq-cards .faq-item {
  border: 1px solid color-mix(in srgb, var(--c-text) 11%, transparent);
  border-radius: clamp(10px, 1.2vw, 15px);
  background: var(--c-surface);
  overflow: hidden;
  transition: background .18s ease, border-color .18s ease;
}
:where(.sl-body) main > section.section.comp-faq-cards .faq-item > summary {
  padding: clamp(0.95rem, 2vw, 1.35rem) clamp(1.1rem, 2.2vw, 1.6rem);
  font-weight: 600;
}
:where(.sl-body) main > section.section.comp-faq-cards .faq-item > p {
  padding: 0 clamp(1.1rem, 2.2vw, 1.6rem) clamp(1.1rem, 2.2vw, 1.5rem);
  max-width: 70ch;
}
:where(.sl-body) main > section.section.comp-faq-cards .faq-item[open] {
  background: color-mix(in srgb, var(--c-primary-dark) 4%, var(--c-surface));
  border-color: color-mix(in srgb, var(--c-primary-dark) 20%, transparent);
}
/* faq_categories groups its items under `.faq-cat` headings; the group label needs to sit OUTSIDE
   the panels or it looks like a question with no answer. */
:where(.sl-body) main > section.section.comp-faq-cards .faq-cat { display: contents; }
:where(.sl-body) main > section.section.comp-faq-cards .faq-cat-title {
  margin: clamp(1rem, 2vw, 1.5rem) 0 0.2rem;
  font-size: 0.78rem; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--c-text-muted);
}


/* ══ EDUCATION-LIST TREATMENTS — the shape that had no class at all ══════════════════════════
   `renderEducationBlock` emits a bare `<ul>` when its items are plain strings, and that is where
   safety_oversight, ingredient_synergies and remedies_compared land. All three were declared
   composable while rendering something no treatment could see, so every assignment was a no-op.
   The list now carries `.edu-list`; these are the first two treatments that can reach it. */

/* ── comp-edu-checks — each point gets a mark ─────────────────────────────────────────────────
   Bullets become accent check marks in their own gutter, with air between items. On a safety or
   standards list the mark is doing real work: it says "we do this", which a disc bullet does not. */
:where(.sl-body) .comp-edu-checks .edu-list {
  list-style: none;
  padding-left: 0 !important;
  columns: auto !important;
  display: grid;
  gap: clamp(0.6rem, 1.3vw, 0.95rem);
}
:where(.sl-body) .comp-edu-checks .edu-list > li {
  display: grid;
  grid-template-columns: clamp(1.4rem, 2.4vw, 1.9rem) minmax(0, 1fr);
  gap: clamp(0.6rem, 1.2vw, 0.9rem);
  align-items: start;
  line-height: 1.62;
}
:where(.sl-body) .comp-edu-checks .edu-list > li::before {
  content: '';
  width: clamp(1.05rem, 1.8vw, 1.3rem);
  height: clamp(1.05rem, 1.8vw, 1.3rem);
  margin-top: 0.28em;
  border-radius: 50%;
  background:
    /* a check, drawn in the mask so it takes the accent colour and needs no SVG asset */
    linear-gradient(currentColor, currentColor) no-repeat center/58% 58%;
  -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 6 9 17l-5-5' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 6 9 17l-5-5' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  -webkit-mask-size: contain; mask-size: contain;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-position: center; mask-position: center;
  color: var(--c-accent-ink);
  background-color: currentColor;
}

/* ── comp-edu-chips — the list becomes a set of objects ───────────────────────────────────────
   Short points read better as chips than as a column of bullets: the eye takes the set in at once
   instead of reading down. Wraps naturally, so a list of four and a list of eleven both look
   deliberate. `<strong>`-led items keep their lead-in as the chip's own emphasis. */
:where(.sl-body) .comp-edu-chips .edu-list {
  list-style: none;
  padding-left: 0 !important;
  columns: auto !important;
  display: flex;
  flex-wrap: wrap;
  gap: clamp(0.5rem, 1.1vw, 0.8rem);
}
:where(.sl-body) .comp-edu-chips .edu-list > li {
  padding: clamp(0.5rem, 1.1vw, 0.72rem) clamp(0.85rem, 1.8vw, 1.15rem);
  border-radius: 999px;
  background: color-mix(in srgb, var(--c-primary-dark) 6%, var(--c-surface));
  border: 1px solid color-mix(in srgb, var(--c-primary-dark) 14%, transparent);
  font-size: 0.95rem;
  line-height: 1.4;
}
:where(.sl-body) .comp-edu-chips .edu-list > li strong { color: var(--c-text); }
/* A long point is a paragraph wearing a pill — at that length the chip stops being scannable and
   becomes a lozenge of prose. Above the wrap width they degrade to plain ruled rows. */
:where(.sl-body) .comp-edu-chips .edu-list > li:not(:last-child) { margin-bottom: 0; }
@media (max-width: 620px) {
  :where(.sl-body) .comp-edu-chips .edu-list { display: grid; gap: 0.4rem; }
  :where(.sl-body) .comp-edu-chips .edu-list > li { border-radius: clamp(9px, 1.1vw, 13px); }
}
/* Inside a dark room the chip is a solid plate, so it goes on the white-plate list's terms:
   light ground, dark ink. */
:where(.sl-body) main > section.section.sec-room .comp-edu-chips .edu-list > li, :where(.sl-body) main > section.section.sec-room.comp-edu-chips .edu-list > li {
  background: color-mix(in srgb, var(--c-surface) 92%, transparent);
  border-color: color-mix(in srgb, var(--c-on-room) 40%, transparent);
  color: var(--c-text);
}

/* ══ TABLE + LEDGER TREATMENTS — the shapes the library could never reach ═════════════════════
   The composition vocabulary dresses eight DOM shapes. Everything else on a page — and on a
   PACKAGE page that is most of the page — renders exactly one way on every site, forever. The
   census that motivated this block, run over the whole roster rather than over one site:

     value_stack             40 pages / 9 sites   .vstack-table    no treatment
     ingredients_breakdown   35 pages / 8 sites   .ibreak-table    no treatment
     tier_comparison         34 pages / 8 sites   .tiercmp-table   no treatment
     prep_aftercare           7 pages / 1 site    .prepaft-grid    no treatment
     comparison_table         4 pages / 1 site    .cmp-table       no treatment
     standards_ledger         3 pages / 3 sites   .stdl-list       no treatment
     visit_timeline           1 page  / 1 site    .vtl             no treatment

   The first three are the point. They are ADJACENT on every package page in the build: a filled
   header bar over white rows, three times running, with only the column headings differing. It is
   the single most repeated arrangement in the system and no gate could see it, because M3 only
   asks whether a section carries a comp-* class and these sections were never even candidates.

   Each treatment below changes what the thing IS — a plate, a ladder, a card stack, a receipt —
   not where the type sits. Ian, on the last round: "instead of creating imagery and making new
   visual elements, it is thinking about how to FORMAT the section."

   THE THREE RULES, restated because each has already cost a round here:
   1. A treatment that cannot dress the shape it lands on is a SILENT no-op that still reports as
      composed. Every treatment here is bound to exactly one shape in COMP_SHAPE_CONTRACT
      (Sections.astro) and COMP_CONTRACT (monotony-lint), and M4 fails the build otherwise.
   2. A treatment that changes a background OWNS THE INK ON IT. comp-prep-duo, comp-stdl-plaque and
      comp-matrix-plate all invert a surface, and each rebinds its ink where it does.
   3. A treatment changes how a card LOOKS; the row maths is not its business. Nothing here touches
      a --sl-basis flex row's display, columns or gutter. .prepaft-grid's two columns come from the
      DATA (--prepaft-cols), not from cardBasis, and are left exactly as the renderer set them.

   WHY EVERY SELECTOR CARRIES `main > section.section`. It is not decoration and it is not the
   :nth-of-type(n) trick used further up — it is the minimum that beats a LANE. Lane rules are
   written `body.refine-luxe-noir .prepaft-col`, which is (0,2,1): one type selector more than a
   plain `.comp-prep-duo .prepaft-col` at (0,2,0). So the first draft of comp-prep-duo painted its
   dark plate and then had the lane hand back a 4px radius and a hairline border — a treatment
   half-applied, which is worse than not applied because it looks intentional. Measured on MK by
   reading the computed style off the built page; the CSS file said 18px. The prefix takes every
   rule here to (0,3,2), which clears the lanes without reaching for !important.
   The one !important that remains is on `.vtl`, and it is unavoidable: the renderer emits that
   element with an inline `style="max-width:..."`, which no selector can outrank.

   Ink rides the measured pairs (--c-text / --c-text-muted / --c-accent-ink / --c-accent-ink-dark /
   --c-surface / --c-primary-dark) throughout, so R15 covers all seven for free. One property worth
   naming because two of these rely on it: --c-accent-ink is the accent DARKENED until it measures
   as ink on --c-surface, so using it as a GROUND under --c-surface ink is the same ratio inverted
   and is legible by construction. Raw --c-accent (2.4:1 on white) is never used for either. ══ */

/* ── comp-matrix-plate — the winning column becomes an object ─────────────────────────────────
   `.cmp-table` ships as a flat grid of hairlines with one tinted column and a solid accent cap.
   It reads as a spreadsheet, and the column that is meant to WIN is distinguished only by being
   slightly beige. Every comparison table worth looking at makes that column a raised plate the
   others sit beside, and that is what this does: the other columns lose all chrome, the marks stop
   being two coloured glyphs and become a filled disc against an empty ring, and the highlighted
   column gets a dark cap, its own ground and a real shadow.
   The filled/empty pair is the substantive change. A check in one hue beside a cross in another is
   two colours to decode; a filled dot beside an empty one is legible at a glance and survives
   being printed, screenshotted, or read by someone who cannot separate those two hues. */
:where(.sl-body) main > section.section.comp-matrix-plate .cmp-wrap { padding: clamp(0.9rem, 2vw, 1.5rem) 0 clamp(1rem, 2.2vw, 1.7rem); }
:where(.sl-body) main > section.section.comp-matrix-plate .cmp-table { border-spacing: 0; }
/* Chrome off everywhere first, then given back only to the plate. */
:where(.sl-body) main > section.section.comp-matrix-plate .cmp-table th, :where(.sl-body) main > section.section.comp-matrix-plate .cmp-table td { border-bottom: 0; padding: clamp(0.75rem, 1.6vw, 1.05rem) clamp(0.6rem, 1.4vw, 1rem); }
:where(.sl-body) main > section.section.comp-matrix-plate .cmp-table tbody tr:not(:last-child) .cmp-rowlabel, :where(.sl-body) main > section.section.comp-matrix-plate .cmp-table tbody tr:not(:last-child) td:not(.cmp-hl) {
  border-bottom: 1px solid color-mix(in srgb, var(--c-text) 12%, transparent);
}
:where(.sl-body) main > section.section.comp-matrix-plate .cmp-table thead th {
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--c-text-muted); padding-bottom: clamp(0.7rem, 1.5vw, 1rem);
}
:where(.sl-body) main > section.section.comp-matrix-plate .cmp-table .cmp-rowlabel {
  font-weight: 500; font-size: 1rem; color: var(--c-text); padding-left: 0;
}
/* THE PLATE. A table cell cannot carry a plate on its own, so the column is assembled from three
   parts: the cap rounds and colours the top, every body cell shares one ground, and the last row
   rounds the bottom and casts the shadow for the whole column. */
:where(.sl-body) main > section.section.comp-matrix-plate .cmp-table thead th.cmp-hl {
  background: var(--c-hero-plate);
  color: var(--c-on-dark);                 /* rule 2: this treatment repainted the ground */
  font-size: 0.76rem; letter-spacing: 0.11em;
  border-radius: clamp(10px, 1.2vw, 14px) clamp(10px, 1.2vw, 14px) 0 0;
  padding-top: clamp(0.85rem, 1.8vw, 1.15rem); padding-bottom: clamp(0.85rem, 1.8vw, 1.15rem);
}
:where(.sl-body) main > section.section.comp-matrix-plate .cmp-table .cmp-hl {
  background: var(--c-surface);
  box-shadow: inset 1px 0 0 color-mix(in srgb, var(--c-primary-dark) 12%, transparent),
              inset -1px 0 0 color-mix(in srgb, var(--c-primary-dark) 12%, transparent);
}
:where(.sl-body) main > section.section.comp-matrix-plate .cmp-table tbody tr:last-child td.cmp-hl {
  border-radius: 0 0 clamp(10px, 1.2vw, 14px) clamp(10px, 1.2vw, 14px);
  box-shadow: inset 1px 0 0 color-mix(in srgb, var(--c-primary-dark) 12%, transparent),
              inset -1px 0 0 color-mix(in srgb, var(--c-primary-dark) 12%, transparent),
              inset 0 -1px 0 color-mix(in srgb, var(--c-primary-dark) 12%, transparent),
              0 26px 44px -30px color-mix(in srgb, var(--c-primary-dark) 62%, transparent);
}
/* FILLED vs EMPTY. The svg keeps its stroke and inherits the disc's ink; the "no" mark drops its
   glyph entirely for a single hairline dash, which is what an empty slot should look like. */
:where(.sl-body) main > section.section.comp-matrix-plate .cmp-yes {
  width: clamp(1.5rem, 2.4vw, 1.85rem); height: clamp(1.5rem, 2.4vw, 1.85rem);
  border-radius: 50%; align-items: center; justify-content: center;
  background: var(--c-accent-ink); color: var(--c-surface);
}
:where(.sl-body) main > section.section.comp-matrix-plate .cmp-yes svg { width: 62%; height: 62%; }
:where(.sl-body) main > section.section.comp-matrix-plate .cmp-no {
  width: clamp(1.5rem, 2.4vw, 1.85rem); height: clamp(1.5rem, 2.4vw, 1.85rem);
  border-radius: 50%; align-items: center; justify-content: center; opacity: 1;
  border: 1px solid color-mix(in srgb, var(--c-text) 20%, transparent);
  color: color-mix(in srgb, var(--c-text) 34%, transparent);
}
:where(.sl-body) main > section.section.comp-matrix-plate .cmp-no svg { display: none; }
:where(.sl-body) main > section.section.comp-matrix-plate .cmp-no::before {
  content: ''; width: 38%; height: 1.5px; border-radius: 2px; background: currentColor;
}
/* In a dark room the plate inverts: the cap goes light so it still reads as the promoted column. */
:where(.sl-body) main > section.section.sec-room.comp-matrix-plate .cmp-table thead th.cmp-hl {
  background: var(--c-light-stock); color: var(--c-primary-dark);
}
:where(.sl-body) main > section.section.sec-room.comp-matrix-plate .cmp-table .cmp-hl {
  background: color-mix(in srgb, var(--c-surface) 12%, transparent);
}
:where(.sl-body) main > section.section.sec-room.comp-matrix-plate .cmp-yes {
  background: var(--c-accent-ink-dark, var(--c-accent)); color: var(--c-primary-dark);
}

/* ── comp-tier-ladder — you can SEE the tier climb ────────────────────────────────────────────
   `.tiercmp-table` is a dark panel with a filled header bar and four hairline rows: the cheapest
   drip and the most expensive one look identical, which is the one thing a tier table must not do.
   Here each row becomes its own floating plate and the plates STEP — a left bar that lengthens and
   a ground that deepens with each tier — so the ladder is visible before a word is read.
   border-spacing on a separate-collapse table is what makes rows float apart WITHOUT breaking the
   column alignment; going display:block would have re-laid the four columns out by hand and taken
   the existing mobile stacking rules with it.
   This section is force-dark site-wide (`.section-tier_comparison { background: --c-primary-dark }`
   at :4826), so every ground here is a wash of --c-surface OVER that band and every ink is the
   light pair the component already used. */
:where(.sl-body) main > section.section.comp-tier-ladder .tiercmp-panel { background: transparent; border: 0; border-radius: 0; overflow: visible; }
:where(.sl-body) main > section.section.comp-tier-ladder .tiercmp-table { border-collapse: separate; border-spacing: 0 clamp(0.5rem, 1.1vw, 0.85rem); }
:where(.sl-body) main > section.section.comp-tier-ladder .tiercmp-table thead th {
  background: transparent; color: color-mix(in srgb, var(--c-surface) 62%, transparent);
  font-size: 0.68rem; letter-spacing: 0.12em; text-transform: uppercase;
  padding: 0 1rem 0.35rem; font-weight: 600;
}
:where(.sl-body) main > section.section.comp-tier-ladder .tiercmp-table tbody td {
  border-top: 0; background: color-mix(in srgb, var(--c-surface) 7%, transparent);
  padding: clamp(0.95rem, 2vw, 1.35rem) 1rem;
}
:where(.sl-body) main > section.section.comp-tier-ladder .tiercmp-table tbody td:first-child { border-radius: 12px 0 0 12px; }
:where(.sl-body) main > section.section.comp-tier-ladder .tiercmp-table tbody td:last-child { border-radius: 0 12px 12px 0; }
/* THE STEP. Four rungs; a fifth row and beyond reuse the top rung rather than running off the
   scale, because a ladder with an invisible sixth step is worse than a ladder of four. */
:where(.sl-body) main > section.section.comp-tier-ladder .tiercmp-row:nth-child(1) td:first-child { box-shadow: inset 3px 0 0 color-mix(in srgb, var(--c-accent) 45%, transparent); }
:where(.sl-body) main > section.section.comp-tier-ladder .tiercmp-row:nth-child(2) td:first-child { box-shadow: inset 6px 0 0 color-mix(in srgb, var(--c-accent) 62%, transparent); }
:where(.sl-body) main > section.section.comp-tier-ladder .tiercmp-row:nth-child(3) td:first-child { box-shadow: inset 9px 0 0 color-mix(in srgb, var(--c-accent) 80%, transparent); }
:where(.sl-body) main > section.section.comp-tier-ladder .tiercmp-row:nth-child(n+4) td:first-child { box-shadow: inset 12px 0 0 var(--c-accent); }
:where(.sl-body) main > section.section.comp-tier-ladder .tiercmp-row:nth-child(2) td { background: color-mix(in srgb, var(--c-surface) 9%, transparent); }
:where(.sl-body) main > section.section.comp-tier-ladder .tiercmp-row:nth-child(3) td { background: color-mix(in srgb, var(--c-surface) 11%, transparent); }
:where(.sl-body) main > section.section.comp-tier-ladder .tiercmp-row:nth-child(n+4) td { background: color-mix(in srgb, var(--c-surface) 14%, transparent); }
:where(.sl-body) main > section.section.comp-tier-ladder .tiercmp-table td.tiercmp-pkg {
  padding-left: clamp(1.3rem, 2.4vw, 1.75rem);
  font-family: var(--font-heading); font-size: clamp(1rem, 1.4vw, 1.15rem); font-weight: 600;
}
:where(.sl-body) main > section.section.comp-tier-ladder .tiercmp-table td.tiercmp-price {
  white-space: nowrap; font-variant-numeric: tabular-nums;
  font-size: clamp(1.05rem, 1.5vw, 1.25rem);
  color: var(--c-accent-ink-dark, var(--c-accent));
}
:where(.sl-body) main > section.section.comp-tier-ladder .tiercmp-footer { font-style: normal; }
@media (max-width: 760px) {
  /* The stacked mode already exists below 760px; it only needs the plate to survive it. */
  :where(.sl-body) main > section.section.comp-tier-ladder .tiercmp-table tbody tr { background: color-mix(in srgb, var(--c-surface) 8%, transparent); border-radius: 12px; padding: 0.9rem 1rem; }
  :where(.sl-body) main > section.section.comp-tier-ladder .tiercmp-table tbody td, :where(.sl-body) main > section.section.comp-tier-ladder .tiercmp-table tbody td:first-child, :where(.sl-body) main > section.section.comp-tier-ladder .tiercmp-table tbody td:last-child { background: transparent; border-radius: 0; box-shadow: none; padding: 0.25rem 0; }
  :where(.sl-body) main > section.section.comp-tier-ladder .tiercmp-table td.tiercmp-pkg { padding-left: 0; }
}

/* ── comp-ing-cards — a formula is a set of things, not a spreadsheet ─────────────────────────
   `.ibreak-table` puts a 60-word paragraph in the right cell of a two-column table, which is a
   table being used as a layout. Each ingredient becomes its own plate with an indexed label, so
   the formula reads as a list of components you could point at. The head row stays — the phrase
   "What it does in this formula" is doing work — but loses its filled bar for a ruled caption.
   The grid is declared on BOTH the head row and the body rows from one custom property, so the
   caption can never drift out of line with the column it names. */
:where(.sl-body) main > section.section.comp-ing-cards { --ing-cols: minmax(0, 30fr) minmax(0, 70fr); }
:where(.sl-body) main > section.section.comp-ing-cards .ibreak-panel { background: transparent; border: 0; border-radius: 0; overflow: visible; max-width: var(--content-max); }
:where(.sl-body) main > section.section.comp-ing-cards .ibreak-table, :where(.sl-body) main > section.section.comp-ing-cards .ibreak-table thead, :where(.sl-body) main > section.section.comp-ing-cards .ibreak-table tbody { display: block; width: 100%; }
:where(.sl-body) main > section.section.comp-ing-cards .ibreak-table tbody { counter-reset: ing; }
:where(.sl-body) main > section.section.comp-ing-cards .ibreak-table tr {
  display: grid; grid-template-columns: var(--ing-cols);
  gap: 0 clamp(1.2rem, 3vw, 2.75rem); align-items: start;
}
:where(.sl-body) main > section.section.comp-ing-cards .ibreak-table thead tr { padding: 0 clamp(1.2rem, 2.4vw, 1.8rem) 0.55rem; }
:where(.sl-body) main > section.section.comp-ing-cards .ibreak-table thead th {
  background: transparent; width: auto; padding: 0;
  font-size: 0.68rem; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--c-text-muted);
}
:where(.sl-body) main > section.section.comp-ing-cards .ibreak-table tbody tr {
  counter-increment: ing;
  background: var(--c-surface);
  border: 1px solid color-mix(in srgb, var(--c-text) 10%, transparent);
  border-radius: clamp(10px, 1.2vw, 15px);
  padding: clamp(1.1rem, 2.2vw, 1.5rem) clamp(1.2rem, 2.4vw, 1.8rem);
  margin-bottom: clamp(0.55rem, 1.2vw, 0.85rem);
}
:where(.sl-body) main > section.section.comp-ing-cards .ibreak-table tbody tr + tr td { border-top: 0; }
:where(.sl-body) main > section.section.comp-ing-cards .ibreak-table td { display: block; width: auto; padding: 0; font-size: 1rem; }
/* The index. Small, tracked and set above the name, so a five-ingredient formula reads as an
   ordered thing rather than as five interchangeable rows. */
:where(.sl-body) main > section.section.comp-ing-cards .ibreak-table td.ibreak-name {
  width: auto; font-family: var(--font-heading);
  font-size: clamp(1.05rem, 1.5vw, 1.22rem); font-weight: 600; line-height: 1.28;
  color: var(--c-text);
}
:where(.sl-body) main > section.section.comp-ing-cards .ibreak-table td.ibreak-name::before {
  content: counter(ing, decimal-leading-zero);
  display: block; margin-bottom: 0.3rem;
  font-size: 0.7rem; font-weight: 700; letter-spacing: 0.14em;
  color: var(--c-accent-ink); font-variant-numeric: tabular-nums;
}
:where(.sl-body) main > section.section.comp-ing-cards .ibreak-table td.ibreak-desc { color: var(--c-text-muted); line-height: 1.68; }
@media (max-width: 760px) {
  :where(.sl-body) main > section.section.comp-ing-cards { --ing-cols: minmax(0, 1fr); }
  :where(.sl-body) main > section.section.comp-ing-cards .ibreak-table thead { display: none; }
  :where(.sl-body) main > section.section.comp-ing-cards .ibreak-table tbody tr { gap: 0.35rem 0; }
}
/* A plate in a room needs dark ink on it — the fourth instance of this in the file. */
:where(.sl-body) main > section.section.sec-room.comp-ing-cards .ibreak-table tbody tr {
  --c-text: var(--c-primary);
  --c-text-muted: var(--c-muted-on-surface, color-mix(in srgb, var(--c-primary) 74%, var(--c-surface-alt)));
  color: var(--c-primary);
}

/* ── comp-value-receipt — an itemised bill, printed like one ──────────────────────────────────
   value_stack answers "what would this cost if you bought the pieces separately", and the renderer
   prints it as the same bordered table as everything else on the page. The content already IS a
   receipt, so this makes it look like one: leader dots running from each item to its price,
   tabular figures, no cell chrome, a double rule above the total, and a perforated tear along the
   bottom edge of the plate.
   The tear is a mask, so a browser without mask support gets a plain rectangle and loses nothing
   but the flourish. The leader dots are the `.addon-tier-dots` idiom this codebase already uses
   for dosed boosters, done in CSS because a table cell cannot carry a spacer element. */
:where(.sl-body) main > section.section.comp-value-receipt .vstack-wrap {
  max-width: 640px;
  background: var(--c-surface);
  border: 0; border-radius: 0; overflow: visible;
  padding: clamp(1.3rem, 2.8vw, 2rem) clamp(1.3rem, 3vw, 2.2rem) clamp(1.9rem, 3.6vw, 2.7rem);
  box-shadow: 0 22px 44px -34px color-mix(in srgb, var(--c-primary-dark) 68%, transparent);
  /* the tear: half-discs punched out of the bottom edge, one every 18px */
  -webkit-mask-image: radial-gradient(circle at 9px 100%, transparent 8.5px, #000 9px);
  mask-image: radial-gradient(circle at 9px 100%, transparent 8.5px, #000 9px);
  -webkit-mask-size: 18px 100%; mask-size: 18px 100%;
  -webkit-mask-repeat: repeat-x; mask-repeat: repeat-x;
}
/* THE ROWS LEAVE THE TABLE LAYOUT, and they have to. The leader dots need the label cell to be a
   FLEX line so a trailing rule can eat the slack — and `display: flex` on a <td> takes that cell
   out of the table formatting context, so the browser can no longer size the column from its
   content. Measured on Halo before this: the label column collapsed to 132px and every item
   wrapped one word per line while the cost column sat at 437px of empty space.
   So the table becomes a two-column grid, declared once on the row and shared by the head. Same
   move as comp-ing-cards, and the same reason: a two-column table used as a layout is a grid that
   has not admitted it yet. */
:where(.sl-body) main > section.section.comp-value-receipt .vstack-table, :where(.sl-body) main > section.section.comp-value-receipt .vstack-table thead, :where(.sl-body) main > section.section.comp-value-receipt .vstack-table tbody { display: block; width: 100%; }
:where(.sl-body) main > section.section.comp-value-receipt .vstack-table tr {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  align-items: baseline; column-gap: clamp(0.8rem, 2vw, 1.4rem);
}
:where(.sl-body) main > section.section.comp-value-receipt .vstack-table thead th {
  background: transparent; color: var(--c-text-muted); width: auto;
  font-size: 0.68rem; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase;
  padding: 0 0 0.5rem; text-align: left;
}
:where(.sl-body) main > section.section.comp-value-receipt .vstack-table thead tr {
  border-bottom: 1px solid color-mix(in srgb, var(--c-text) 20%, transparent);
}
:where(.sl-body) main > section.section.comp-value-receipt .vstack-table th:last-child, :where(.sl-body) main > section.section.comp-value-receipt .vstack-table td:last-child { width: auto; text-align: right; }
:where(.sl-body) main > section.section.comp-value-receipt .vstack-table td { display: block; padding: clamp(0.5rem, 1.1vw, 0.72rem) 0; font-size: 0.97rem; }
:where(.sl-body) main > section.section.comp-value-receipt .vstack-table tbody tr + tr td { border-top: 0; }
/* LEADER DOTS. The label cell becomes a flex line whose trailing rule eats the slack, which is
   what carries the eye to a price sitting in a different grid column.
   `td.vstack-label`, not `.vstack-label`: the rule four lines up sets `display: block` on every
   `td` in this table and carries one more element selector, so a bare class here loses the
   cascade and the flex line silently reverts to a block. It did, and the dots never drew. */
:where(.sl-body) main > section.section.comp-value-receipt .vstack-table td.vstack-label {
  display: flex; align-items: baseline; gap: 0.6rem;
  color: var(--c-text); padding-right: clamp(0.8rem, 2vw, 1.4rem);
}
:where(.sl-body) main > section.section.comp-value-receipt .vstack-table td.vstack-label::after {
  content: ''; flex: 1 1 auto; align-self: center; min-width: 1.5rem;
  border-bottom: 1px dotted color-mix(in srgb, var(--c-text) 40%, transparent);
}
:where(.sl-body) main > section.section.comp-value-receipt .vstack-table td.vstack-cost { color: var(--c-text); font-variant-numeric: tabular-nums; }
/* THE TOTAL. A double rule and a promotion in size, which is the whole reason the row is
   highlighted in the data. No fill — a tinted band inside a receipt reads as a table again. */
:where(.sl-body) main > section.section.comp-value-receipt .vstack-row-hl td {
  background: transparent;
  border-top: 1px solid color-mix(in srgb, var(--c-text) 26%, transparent);
  box-shadow: inset 0 3px 0 -2px color-mix(in srgb, var(--c-text) 26%, transparent);
  padding-top: clamp(0.85rem, 1.8vw, 1.15rem);
}
:where(.sl-body) main > section.section.comp-value-receipt .vstack-table .vstack-row-hl td.vstack-label {
  font-size: 0.72rem; letter-spacing: 0.12em; text-transform: uppercase; font-weight: 700;
}
:where(.sl-body) main > section.section.comp-value-receipt .vstack-table .vstack-row-hl td.vstack-label::after { border-bottom-style: none; }
:where(.sl-body) main > section.section.comp-value-receipt .vstack-table .vstack-row-hl td.vstack-cost {
  font-family: var(--font-heading);
  font-size: clamp(1.05rem, 1.7vw, 1.3rem); line-height: 1.25;
  color: var(--c-accent-ink); white-space: normal; max-width: 22ch;
}
:where(.sl-body) main > section.section.comp-value-receipt .vstack-footer { max-width: 640px; }
:where(.sl-body) main > section.section.sec-room.comp-value-receipt .vstack-wrap {
  --c-text: var(--c-primary);
  --c-text-muted: var(--c-muted-on-surface, color-mix(in srgb, var(--c-primary) 74%, var(--c-surface-alt)));
  color: var(--c-primary);
}

/* ── comp-prep-duo — two boxes that are not the same box ──────────────────────────────────────
   prep_aftercare renders BEFORE and AFTER as two identical white cards side by side, which is the
   purest form of the monotony this whole layer exists for: the section's own content is a
   contrast, and the design states it as a repetition. So the two halves are made opposite. Before
   is a dark plate; after is a light one under an accent cap. The icon disc becomes a square badge
   in both, because a disc beside a disc is the same tell as a box beside a box.
   RULE 2 IS THE ENTIRE RISK HERE. Inverting one column puts the renderer's own inline
   `.prepaft-list span { color: var(--c-text-muted) }` on a dark ground, so the column rebinds
   --c-text / --c-text-muted rather than recolouring each element — which is also what keeps any
   element added to that column later from arriving invisible.
   :not(:only-child) so a section with only a BEFORE list does not render as one lone dark slab. */
:where(.sl-body) main > section.section.comp-prep-duo .prepaft-col {
  border: 0; border-radius: clamp(12px, 1.5vw, 18px);
  padding: clamp(1.5rem, 3vw, 2.1rem) clamp(1.4rem, 2.8vw, 1.9rem);
  background: var(--c-surface);
  box-shadow: inset 0 4px 0 var(--c-accent-ink),
              0 18px 38px -32px color-mix(in srgb, var(--c-primary-dark) 60%, transparent);
}
:where(.sl-body) main > section.section.comp-prep-duo .prepaft-col-head { gap: 0.85rem; }
:where(.sl-body) main > section.section.comp-prep-duo .prepaft-ic {
  width: clamp(38px, 4.4vw, 46px); height: clamp(38px, 4.4vw, 46px);
  border-radius: clamp(9px, 1.1vw, 12px);        /* square badge — the tell that this is not the default */
  background: color-mix(in srgb, var(--c-accent-ink) 14%, var(--c-surface));
  color: var(--c-accent-ink);
}
:where(.sl-body) main > section.section.comp-prep-duo .prepaft-col-head h3 { font-size: clamp(1.05rem, 1.5vw, 1.25rem); }
/* BEFORE: the dark half. Ink rebinds with the ground. */
:where(.sl-body) main > section.section.comp-prep-duo .prepaft-col:first-child:not(:only-child) {
  background: var(--c-hero-plate);
  box-shadow: 0 22px 44px -32px color-mix(in srgb, var(--c-primary-dark) 75%, transparent);
  --c-text: var(--c-on-dark);
  --c-text-muted: color-mix(in srgb, var(--c-on-dark) 80%, var(--c-primary-dark));
  --c-border: color-mix(in srgb, var(--c-on-dark) 22%, transparent);
  color: var(--c-on-dark);
}
:where(.sl-body) main > section.section.comp-prep-duo .prepaft-col:first-child:not(:only-child) .prepaft-col-head {
  border-bottom-color: color-mix(in srgb, var(--c-on-dark) 24%, transparent);
}
:where(.sl-body) main > section.section.comp-prep-duo .prepaft-col:first-child:not(:only-child) .prepaft-col-head h3 { color: var(--c-on-dark); }
:where(.sl-body) main > section.section.comp-prep-duo .prepaft-col:first-child:not(:only-child) .prepaft-ic {
  background: color-mix(in srgb, var(--c-surface) 15%, transparent);
  color: var(--c-on-dark);
}
:where(.sl-body) main > section.section.comp-prep-duo .prepaft-col:first-child:not(:only-child) .prepaft-list .check {
  color: var(--c-accent-ink-dark, var(--c-accent));
}

/* ── comp-stdl-plaque — the manifesto stops being a list of rules ─────────────────────────────
   standards_ledger is already the best-looking untreated shape in the build: big numerals, one
   claim per hairline row. What it cannot do is look like anything else, and it is a HOME-page
   section on every site that carries it, so it is a first impression that repeats.
   The plaque inverts the emphasis. The numeral leaves the text flow for a solid block set beside
   the claim — a physical marker rather than a figure in a margin — and the hairline rows become
   plates with air between them. Same content, and it now reads as a set of commitments rather
   than as an index. The numeral block owns its ink (rule 2). */
:where(.sl-body) main > section.section.comp-stdl-plaque .stdl-list { display: grid; gap: clamp(0.6rem, 1.3vw, 1rem); }
:where(.sl-body) main > section.section.comp-stdl-plaque .stdl-row {
  border: 0; border-radius: clamp(12px, 1.4vw, 16px);
  background: color-mix(in srgb, var(--c-primary-dark) 4%, var(--c-surface));
  padding: clamp(1.15rem, 2.4vw, 1.7rem) clamp(1.3rem, 2.6vw, 1.9rem);
  grid-template-columns: clamp(3.1rem, 5vw, 4.1rem) minmax(0, 1fr);
  gap: 0 clamp(1.1rem, 2.4vw, 1.8rem);
  align-items: start;
}
:where(.sl-body) main > section.section.comp-stdl-plaque .stdl-row:first-child { border-top: 0; }
:where(.sl-body) main > section.section.comp-stdl-plaque .stdl-num {
  display: grid; place-items: center;
  width: clamp(3.1rem, 5vw, 4.1rem); height: clamp(3.1rem, 5vw, 4.1rem);
  border-radius: clamp(9px, 1.1vw, 12px);
  background: var(--c-hero-plate);
  color: var(--c-on-dark);                 /* rule 2 */
  font-size: clamp(1.05rem, 1.7vw, 1.35rem); line-height: 1;
}
/* Every third plaque takes the accent block, so a five-item manifesto is not five identical
   markers — the same cadence device the card treatments use, at plaque scale. */
:where(.sl-body) main > section.section.comp-stdl-plaque .stdl-row:nth-child(3n + 2) .stdl-num { background: var(--c-accent-ink); }
:where(.sl-body) main > section.section.comp-stdl-plaque .stdl-copy h3 { font-size: clamp(1.08rem, 1.5vw, 1.28rem); margin-bottom: 0.3rem; }
:where(.sl-body) main > section.section.comp-stdl-plaque .stdl-copy p { font-size: 0.97rem; color: var(--c-text-muted); }
@media (max-width: 640px) {
  :where(.sl-body) main > section.section.comp-stdl-plaque .stdl-row { grid-template-columns: 2.6rem minmax(0, 1fr); gap: 0 0.9rem; padding: 1.1rem 1.1rem; }
  :where(.sl-body) main > section.section.comp-stdl-plaque .stdl-num { width: 2.6rem; height: 2.6rem; font-size: 0.95rem; }
}

/* ── comp-vtl-rail — the itinerary gets a spine ───────────────────────────────────────────────
   visit_timeline draws a hairline rail with small dots and hangs the time markers off the right
   of a 150px column. At a distance the rail disappears and the section reads as a plain
   two-column list. This gives it a real spine: a continuous accent rail behind ringed stop
   markers, the time promoted into a small plate, and each stop's copy on its own ground so the
   sequence is visible rather than implied.
   The rail is drawn on the .vtl CONTAINER, so it is continuous — the per-item hairline it replaces
   restarted at every stop and left a break at each gap.
   THE MEASURE, not the band. The renderer caps .vtl at --content-measure (~64ch) with an inline
   style, and the first pass overrode that to --content-max — which on Halo resolved to the full
   1216px container and put itinerary copy on a 1020px line. A treatment may widen a component to
   make room for what it adds; it may not throw the measure away. The !important is the one in this
   block, and it is unavoidable: an inline style attribute outranks every selector. */
:where(.sl-body) main > section.section.comp-vtl-rail .vtl {
  --vtl-gut: clamp(120px, 15vw, 158px);
  position: relative;
  max-width: calc(var(--vtl-gut) + 46rem) !important;
  margin-inline: auto;
}
:where(.sl-body) main > section.section.comp-vtl-rail .vtl::before {
  content: ''; position: absolute; top: 0.9rem; bottom: 1.6rem;
  left: var(--vtl-gut); width: 2px; border-radius: 2px;
  background: color-mix(in srgb, var(--c-accent) 26%, transparent);
}
:where(.sl-body) main > section.section.comp-vtl-rail .vtl-item {
  grid-template-columns: var(--vtl-gut) minmax(0, 1fr);
  gap: 0 clamp(1.4rem, 3vw, 2.4rem);
  padding-bottom: clamp(0.6rem, 1.3vw, 1rem);
}
:where(.sl-body) main > section.section.comp-vtl-rail .vtl-marker { text-align: right; padding-right: clamp(1.1rem, 2.2vw, 1.6rem); }
:where(.sl-body) main > section.section.comp-vtl-rail .vtl-time {
  display: inline-block; padding: 0.32rem 0.7rem; border-radius: 999px;
  background: color-mix(in srgb, var(--c-accent-ink) 12%, var(--c-surface));
  color: var(--c-accent-ink);
  font-size: 0.82rem; letter-spacing: 0.03em; font-weight: 600;
}
/* The stop marker sits ON the rail: a filled disc ringed in the section's own ground so the rail
   appears to pass behind it. left, not right, because it is pinned to the container's rail. */
:where(.sl-body) main > section.section.comp-vtl-rail .vtl-dot {
  right: auto; left: calc(var(--vtl-gut) - 7px); top: 0.55rem;
  width: 14px; height: 14px;
  background: var(--c-accent-ink);
  box-shadow: 0 0 0 4px var(--c-surface-alt);
}
:where(.sl-body) main > section.section.comp-vtl-rail .vtl-item:not(:last-child) .vtl-marker::after { display: none; }  /* the container owns the rail now */
:where(.sl-body) main > section.section.comp-vtl-rail .vtl-copy {
  background: var(--c-surface);
  border-radius: clamp(10px, 1.2vw, 15px);
  padding: clamp(1rem, 2vw, 1.4rem) clamp(1.1rem, 2.2vw, 1.6rem);
  margin-bottom: clamp(0.5rem, 1.1vw, 0.8rem);
}
:where(.sl-body) main > section.section.comp-vtl-rail .vtl-copy h3 { font-size: clamp(1.05rem, 1.5vw, 1.24rem); }
:where(.sl-body) main > section.section.comp-vtl-rail .vtl-copy p { color: var(--c-text-muted); }
@media (max-width: 640px) {
  :where(.sl-body) main > section.section.comp-vtl-rail .vtl { --vtl-gut: 0px; }
  :where(.sl-body) main > section.section.comp-vtl-rail .vtl::before { left: 6px; }
  :where(.sl-body) main > section.section.comp-vtl-rail .vtl-item { grid-template-columns: minmax(0, 1fr); padding-left: 1.9rem; }
  :where(.sl-body) main > section.section.comp-vtl-rail .vtl-marker { text-align: left; padding-right: 0; margin-bottom: 0.4rem; }
  :where(.sl-body) main > section.section.comp-vtl-rail .vtl-dot { left: -1.9rem; top: 0.45rem; }
}
:where(.sl-body) main > section.section.sec-room.comp-vtl-rail .vtl-copy, :where(.sl-body) main > section.section.sec-room.comp-stdl-plaque .stdl-row {
  --c-text: var(--c-primary);
  --c-text-muted: var(--c-muted-on-surface, color-mix(in srgb, var(--c-primary) 74%, var(--c-surface-alt)));
  color: var(--c-primary);
  background: var(--c-surface);
}
:where(.sl-body) main > section.section.sec-room.comp-vtl-rail .vtl-dot { box-shadow: 0 0 0 4px var(--c-primary-dark); }

/* ══ CLOSING-CTA SKINS — the most repeated object in the entire build ═════════════════════════
   `final_cta` is on 190 pages across 17 sites: every page in the system ends with it. And it is
   one object everywhere — a floating rounded slab, eyebrow over headline over subhead over three
   centred pills. The lanes recolour it and restyle its type; not one of them changes its
   SILHOUETTE, so at a squint the last screen of every SiteLaunch page is identical.

   Four members, and the fourth is the one that already exists. `cta-skin-` (not `comp-`) because
   this is a SITE-wide choice, not a per-instance one: a closing CTA that changed between a site's
   own pages would read as a mistake, and the monotony rules — which cap a treatment at twice a
   page — are the wrong instrument for something that appears exactly once. Selection lives in
   Sections.astro next to the auto-composer; an authored `theme.cta.style` always wins.

     (default)   the floating slab. Still in the rotation, still drawn on a quarter of the roster.
     bleed       edge to edge, square, hairline rules. The silhouette change, and the cheapest.
     plaque      the slab keeps its ground and gains an inset frame; the eyebrow becomes a tab
                 sitting ON the frame's top edge.
     photo       the page's own hero photograph behind the slab under a heavy scrim. Gated on
                 there BEING one — see the note on the assigner.

   !important IS REQUIRED HERE and is not laziness. renderFinalCta emits the div with
   `style="text-align:center; padding:...; border-radius:...; background:...; overflow:hidden"` —
   an inline style attribute, which outranks every selector that has ever been written. Only the
   properties the renderer sets inline carry it; everything else rides ordinary specificity.

   CONTRAST. The default ground is `--c-cta-bg`, falling back to a --c-primary/--c-primary-dark
   gradient, with `--c-cta-text` (→ --c-surface) on top; the renderer also sets the buttons'
   ink inline. Every skin below keeps that same ink pair, so no measured contrast changes hands:
   `bleed` and `plaque` reuse the ground verbatim, and `photo` puts the photograph BEHIND it at
   an opacity capped low enough that the scrim over it is still the ground the ink was measured
   against. That is the same argument sec-bg-photo makes, and the same reason R15 covers it. ══ */

/* ── cta-skin-bleed — a band, not a card ──────────────────────────────────────────────────────
   The container's gutter and the slab's radius both go, so the ground runs to both edges of the
   viewport. It is the largest change available for the least risk: no ink moves, no measured pair
   changes, and the last thing on the page stops being a rectangle floating on stock. */
:where(.sl-body) main > section.section.cta-skin-bleed { padding-left: 0 !important; padding-right: 0 !important; }
:where(.sl-body) main > section.section.cta-skin-bleed > .container { max-width: none !important; padding-left: 0 !important; padding-right: 0 !important; }
/* A LANE THAT FRAMES ITS BANDS WILL FRAME THIS ONE, and a frame around a full-bleed band is a
   contradiction that renders as a defect. Measured on Top Tier: refine-dark-luxe draws an inset
   gold plate on every non-room section via ::before/::after, so the bleed skin came out as two
   gold rules a few pixels apart with a strip of page stock still showing down each side.
   `.section-marquee_band` hit this first and was excluded by name inside the lane's own :not()
   list. That does not generalise — there are five lanes and this skin can land on any of them —
   so the suppression lives with the skin instead, and any lane that frames is covered by
   construction. !important because the lane rule already carries it. */
:where(.sl-body) main > section.section.cta-skin-bleed::before, :where(.sl-body) main > section.section.cta-skin-bleed::after { display: none !important; }
:where(.sl-body) main > section.section.cta-skin-bleed .final-cta {
  border-radius: 0 !important;
  padding: clamp(3.5rem, 8vw, 6.5rem) clamp(1.5rem, 5vw, 3rem) !important;
}
/* The hairlines are what stop a full-bleed band reading as an accident of layout. */
:where(.sl-body) main > section.section.cta-skin-bleed .final-cta {
  box-shadow: inset 0 3px 0 var(--c-accent), inset 0 -3px 0 var(--c-accent);
}
/* The copy still takes a measure — a headline running the full width of a 1440px screen is not a
   band, it is a line of text with nothing holding it. */
:where(.sl-body) main > section.section.cta-skin-bleed .final-cta > * { max-width: var(--content-max); margin-left: auto; margin-right: auto; }

/* ── cta-skin-plaque — the slab becomes an object with an edge ────────────────────────────────
   An inset hairline frame in the accent, held off the slab's own edge, and the eyebrow lifted out
   of the stack onto the frame's top rule as a tab. Two real objects added; nothing rearranged. */
:where(.sl-body) main > section.section.cta-skin-plaque .final-cta {
  padding: clamp(4rem, 8.5vw, 7rem) clamp(2rem, 5vw, 3.5rem) clamp(3.5rem, 8vw, 6rem) !important;
}
/* NO PSEUDO-ELEMENT. Two drafts of this frame lived on `.final-cta::before` and neither painted a
   pixel: the computed style reported inset 25.6px, a 1px accent border, display block, visibility
   visible, opacity 1 — and an 8px SOLID RED override with !important was still invisible at 3x.
   That pseudo is already claimed by the grain rule at :999 (`inset: 0; z-index: 0`) and by two
   lanes, and its used width came back as 696px inside a 1143px box, so something in that stack is
   resizing it out of view. Chasing which is not worth a frame.
   `box-shadow` on the element itself draws the same ring with no pseudo, no stacking context and
   no cascade argument, and it clips to the slab's own radius for free. The ring sits ON the edge
   rather than inset, which is what makes the straddling tab below read as a plaque label. */
:where(.sl-body) main > section.section.cta-skin-plaque .final-cta {
  box-shadow:
    inset 0 0 0 1px color-mix(in srgb, var(--c-accent) 68%, transparent),
    inset 0 0 0 7px color-mix(in srgb, var(--c-primary-dark) 34%, transparent) !important;
}
/* The tab. Lifted out of the stack onto the frame's top rule, on its own ground so it reads as a
   label fixed to the plaque rather than as the first line of the copy. */
:where(.sl-body) main > section.section.cta-skin-plaque .final-cta .eyebrow {
  position: absolute;
  z-index: 2;
  top: clamp(0.9rem, 2vw, 1.6rem);
  left: 50%;
  transform: translate(-50%, -50%);
  display: inline-block;
  margin: 0;
  padding: 0.4rem 1.1rem;
  border: 1px solid color-mix(in srgb, var(--c-accent) 72%, transparent);
  border-radius: 999px;
  background: var(--c-hero-plate);
  color: var(--c-accent-ink-dark, var(--c-accent));
  white-space: nowrap;
}

/* ── cta-skin-photo — the closing pitch gets a picture ────────────────────────────────────────
   Ian, on what the library was missing: "it really brings life to a website when you use an image
   as a background in some sections, rather than just colors all the time." The closing CTA is the
   best place left to do it — it is the one band on every page whose ink is ALREADY white on a dark
   ground, so a photograph behind a scrim costs nothing in measured contrast.
   The image is the PAGE'S OWN HERO, passed in as --cta-photo. That is deliberate: it is already
   downloaded and decoded by the time a visitor reaches the foot of the page, so the band costs
   zero extra bytes (asset-weight-lint has caught 59MB of PNGs here before), and reusing the
   opening picture to close the page reads as a bookend rather than as stock.
   The ground stays ON TOP of the photograph at 82%, so the ink pair is unchanged. */
:where(.sl-body) main > section.section.cta-skin-photo .final-cta {
  background:
    linear-gradient(color-mix(in srgb, var(--c-primary-dark) 82%, transparent),
                    color-mix(in srgb, var(--c-primary-dark) 82%, transparent)),
    var(--cta-photo) center / cover no-repeat,
    var(--c-primary-dark) !important;
}
/* The house radial accent wash reads as a smear over a photograph; the picture is the interest
   now. Same call the dark-luxe lane made when it took the gold blast off its hero. */
:where(.sl-body) main > section.section.cta-skin-photo .final-cta::after { opacity: 0.1; }
:where(.sl-body) main > section.section.cta-skin-photo .final-cta::before { display: none; }
/* A pale photograph under an 82% scrim is still lighter than a flat slab, so the type gets the
   floor the hero effects give theirs. Cheap, and it is what keeps this legible on a white sky. */
:where(.sl-body) main > section.section.cta-skin-photo .final-cta h2, :where(.sl-body) main > section.section.cta-skin-photo .final-cta p, :where(.sl-body) main > section.section.cta-skin-photo .final-cta .eyebrow { text-shadow: 0 1px 18px rgba(0, 0, 0, 0.45); }

/* ══ FIVE MORE DESIGNS — the rest of the shapes with a single look ════════════════════════════
   Same contract as the block above: one shape each, ink on the measured pairs, and every selector
   prefixed `main > section.section` so a lane at (0,2,1) cannot half-eat it.

   These are LIBRARY ENTRIES. Nothing assigns them — a page opts in through its own `_composition`
   map, which is the existing "someone chose this" path. Review them on the library sheet
   (`node tools/library-sheet.mjs`), not on a client site. ══════════════════════════════════════ */

/* ── comp-stats-medallion — the number becomes the object ─────────────────────────────────────
   `.stats-band` puts a small accent icon over a big figure over a caption, centred, four across.
   The icon is the weakest element on the band: it is generic (a users glyph over "5,000+ visits"
   says nothing the number does not) and it is the only thing distinguishing one stat from the
   next. Drop it, and ring the figure instead — a medallion reads as a claim being presented
   rather than as a caption with a picture, and it gives the band a repeating shape at a distance,
   which four bare numerals do not.
   The ring rides --c-accent-ink-dark because this band is force-dark (`.section-stats` at :912). */
:where(.sl-body) main > section.section.comp-stats-medallion .stats-band { align-items: start; }
:where(.sl-body) main > section.section.comp-stats-medallion .stat-ic { display: none; }
:where(.sl-body) main > section.section.comp-stats-medallion .stat {
  display: grid; justify-items: center; gap: 0.85rem; min-width: clamp(140px, 15vw, 180px);
}
/* NO `background` ON THE FIGURE, and no colour either. `body.ad-bold-modern .stat-value` fills the
   number with a gradient via `background-clip: text` + `color: transparent !important`, and the
   first draft of this ring set its own background — which replaced that gradient and left the
   figure filled with nothing. Four rings, no numbers, and the computed colour read back as
   `rgba(0,0,0,0)`. So the ring is a BORDER only: on a gradient-text lane the number keeps its fill
   and gains a ring, and on every other lane it keeps `--c-primary` from the base rule.
   font-size is the one property that has to be taken back — that lane sets 6.5rem !important,
   which is a figure far larger than any circle it could sit in. */
:where(.sl-body) main > section.section.comp-stats-medallion .stat-value {
  display: grid; place-items: center;
  /* Wide enough that "5,000+" sets on one line. The first pass at 6.2rem broke it after the comma
     and left the "+" alone on a second line, which reads as a wrapping bug rather than a figure. */
  width: clamp(7.2rem, 10.5vw, 9.2rem); height: clamp(7.2rem, 10.5vw, 9.2rem);
  border-radius: 50%;
  border: 2px solid color-mix(in srgb, var(--c-accent-ink-dark, var(--c-accent)) 70%, transparent);
  font-size: clamp(1.35rem, 2.2vw, 1.8rem) !important;
  line-height: 1;
  padding: 0.4rem;
  text-align: center;
  /* A figure like "5,000+" must not overflow its ring at any width — the ring is the constraint,
     so the type gives way, not the circle. */
  overflow-wrap: anywhere;
}
:where(.sl-body) main > section.section.comp-stats-medallion .stat-label {
  margin: 0; max-width: 16ch; font-size: 0.88rem;
  letter-spacing: 0.06em; text-transform: uppercase;
}

/* ── comp-tiers-cap — the price stops being a line of text ────────────────────────────────────
   `.pricing-tiers` renders three bordered cards, each a stack of name, price, description,
   checklist and button, distinguished only by a "Most popular" pill on one of them. The price —
   the single thing a visitor is comparing — is set as the third line of a paragraph column.
   Here every card gains a solid CAP carrying the name and the price reversed out of the brand
   dark, and the body below is white with the checklist on it. The featured card's cap takes the
   accent instead, which is a stronger promotion than a 2px ring and does not need the badge to
   overhang the card (that badge is the reason .tier-card cannot use overflow:hidden).
   The cap owns its ink — rule 2 — and is the reason this treatment is safe on any lane. */
:where(.sl-body) main > section.section.comp-tiers-cap .tier-card {
  padding: 0;
  overflow: hidden;
  border: 1px solid color-mix(in srgb, var(--c-primary-dark) 14%, transparent);
  border-radius: clamp(12px, 1.4vw, 16px);
  background: var(--c-surface);
  box-shadow: 0 18px 40px -34px color-mix(in srgb, var(--c-primary-dark) 60%, transparent);
}
/* THE CAP. .tier-name and .tier-price are siblings, so the band is drawn on the NAME and the price
   is pulled up into it — no wrapper element exists and the renderer is not being changed for a
   skin. Padding on both halves keeps them on one ground with no seam. */
:where(.sl-body) main > section.section.comp-tiers-cap .tier-name {
  margin: 0;
  padding: clamp(1.2rem, 2.4vw, 1.6rem) clamp(1.3rem, 2.6vw, 1.8rem) 0.35rem;
  background: var(--c-hero-plate);
  color: var(--c-on-dark);
  font-size: 0.76rem; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase;
}
:where(.sl-body) main > section.section.comp-tiers-cap .tier-price {
  margin: 0;
  padding: 0 clamp(1.3rem, 2.6vw, 1.8rem) clamp(1.15rem, 2.4vw, 1.6rem);
  background: var(--c-hero-plate);
  align-items: baseline;
}
:where(.sl-body) main > section.section.comp-tiers-cap .tier-amount { color: var(--c-on-dark); font-size: clamp(2rem, 3.4vw, 2.7rem); }
:where(.sl-body) main > section.section.comp-tiers-cap .tier-period { color: color-mix(in srgb, var(--c-surface) 74%, transparent); }
/* The featured tier is promoted by its CAP, so the ring and the overhanging pill both go. */
:where(.sl-body) main > section.section.comp-tiers-cap .tier-featured { box-shadow: 0 24px 50px -30px color-mix(in srgb, var(--c-primary-dark) 70%, transparent); }
:where(.sl-body) main > section.section.comp-tiers-cap .tier-featured .tier-name, :where(.sl-body) main > section.section.comp-tiers-cap .tier-featured .tier-price { background: var(--c-accent-ink); }
/* The badge stays ABSOLUTE, in the cap's corner. Laying it out as a full-width strip added a row
   to the featured card that the other two do not have, so its name sat 33px lower than theirs and
   the three caps no longer lined up — a row of price cards is read by scanning across, and that
   scan breaks the moment one card's baseline moves. */
:where(.sl-body) main > section.section.comp-tiers-cap .tier-badge {
  top: clamp(0.75rem, 1.6vw, 1.1rem);
  left: auto;
  right: clamp(0.9rem, 1.8vw, 1.3rem);
  transform: none;
  padding: 0.22rem 0.6rem;
  background: color-mix(in srgb, var(--c-surface) 88%, transparent);
  color: var(--c-accent-ink);
  font-size: 0.62rem;
}
/* The body. Everything after the cap sits on the card's own white, inset from the edge. */
:where(.sl-body) main > section.section.comp-tiers-cap .tier-desc, :where(.sl-body) main > section.section.comp-tiers-cap .tier-features, :where(.sl-body) main > section.section.comp-tiers-cap .tier-cta { margin-left: clamp(1.3rem, 2.6vw, 1.8rem); margin-right: clamp(1.3rem, 2.6vw, 1.8rem); }
:where(.sl-body) main > section.section.comp-tiers-cap .tier-desc { margin-top: clamp(1.1rem, 2.2vw, 1.5rem); }
:where(.sl-body) main > section.section.comp-tiers-cap .tier-cta { margin-bottom: clamp(1.3rem, 2.6vw, 1.8rem); align-self: auto; }

/* ── comp-team-portrait — a roster of people, not a row of chips ──────────────────────────────
   `.team-member-card` is a 240px centred card with a 120px round photo, or a monogram disc when
   there is no photo. On a roster with no photography — which is most of them, because client
   headshots arrive late or never — it renders as four grey initials in circles, which looks like
   a placeholder that was shipped.
   This makes the imageless case deliberate: a tall portrait tile whose top two-thirds is a solid
   brand panel carrying the monogram at display scale, with the name and title on a plate below.
   A real photograph, when one exists, fills the same panel edge to edge instead. Either way the
   tile has the same silhouette, so a MIXED roster no longer reads as half-finished. */
:where(.sl-body) main > section.section.comp-team-portrait .team-member-card {
  padding: 0;
  overflow: hidden;
  text-align: left;
  border: 0;
  border-radius: clamp(12px, 1.4vw, 16px);
  background: var(--c-surface);
  box-shadow: 0 16px 34px -30px color-mix(in srgb, var(--c-primary-dark) 60%, transparent);
}
:where(.sl-body) main > section.section.comp-team-portrait .tm-photo {
  display: block; width: 100%; height: auto;
  aspect-ratio: 4 / 5; object-fit: cover;
  border-radius: 0; margin: 0;
}
/* The monogram panel. Same box as a photograph, so the two never disagree about height. */
:where(.sl-body) main > section.section.comp-team-portrait .tm-photo-initial {
  display: grid; place-items: center;
  background: var(--c-hero-plate);
  color: var(--c-on-dark);                     /* rule 2 */
  font-family: var(--font-heading);
  font-size: clamp(2.4rem, 4.5vw, 3.4rem);
  letter-spacing: 0.04em;
}
/* Every third tile takes the accent panel, so a roster of monograms is not one repeated square. */
:where(.sl-body) main > section.section.comp-team-portrait .team-member-card:nth-child(3n + 2) .tm-photo-initial { background: var(--c-accent-ink); }
:where(.sl-body) main > section.section.comp-team-portrait .tm-name {
  display: block;
  padding: clamp(1rem, 2vw, 1.35rem) clamp(1.1rem, 2.2vw, 1.5rem) 0;
  font-family: var(--font-heading); font-size: clamp(1.02rem, 1.4vw, 1.16rem); line-height: 1.25;
}
:where(.sl-body) main > section.section.comp-team-portrait .tm-title {
  padding: 0.2rem clamp(1.1rem, 2.2vw, 1.5rem) 0;
  font-size: 0.72rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--c-accent-ink);
}
:where(.sl-body) main > section.section.comp-team-portrait .tm-bio {
  padding: 0.6rem clamp(1.1rem, 2.2vw, 1.5rem) clamp(1.1rem, 2.2vw, 1.5rem);
  margin: 0; font-size: 0.92rem; line-height: 1.6;
}

/* ── comp-wpkg-ribbon — the bundle is named for a person, so lead with the person ─────────────
   wellness_packages is the one card family whose content is a PERSONA: every bundle carries a
   "for" line ("For anyone coming off a hard week") and the renderer sets it as muted body copy
   under the name, where it reads as a subtitle nobody finishes.
   Promoted to a ribbon across the head of the card it becomes the thing you scan the row by,
   which is how a visitor actually picks one. The icon disc goes — it was a second, weaker
   identifier competing with the persona for the same job. */
:where(.sl-body) main > section.section.comp-wpkg-ribbon .wpkg-card {
  padding: 0;
  overflow: hidden;
  border: 1px solid color-mix(in srgb, var(--c-primary-dark) 12%, transparent);
  border-radius: clamp(12px, 1.4vw, 16px);
}
:where(.sl-body) main > section.section.comp-wpkg-ribbon .wpkg-ic { display: none; }
:where(.sl-body) main > section.section.comp-wpkg-ribbon .wpkg-for {
  order: -1;                                   /* .wpkg-card is a flex column, so the ribbon leads */
  margin: 0 0 clamp(1rem, 2vw, 1.4rem);
  padding: clamp(0.7rem, 1.5vw, 0.95rem) clamp(1.2rem, 2.4vw, 1.6rem);
  background: var(--c-hero-plate);
  color: var(--c-on-dark);                     /* rule 2 */
  font-size: 0.74rem; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase;
  line-height: 1.4;
}
:where(.sl-body) main > section.section.comp-wpkg-ribbon .wpkg-card:nth-child(3n + 2) .wpkg-for { background: var(--c-accent-ink); }
:where(.sl-body) main > section.section.comp-wpkg-ribbon .wpkg-name, :where(.sl-body) main > section.section.comp-wpkg-ribbon .wpkg-list, :where(.sl-body) main > section.section.comp-wpkg-ribbon .wpkg-price, :where(.sl-body) main > section.section.comp-wpkg-ribbon .wpkg-cta { margin-left: clamp(1.2rem, 2.4vw, 1.6rem); margin-right: clamp(1.2rem, 2.4vw, 1.6rem); }
:where(.sl-body) main > section.section.comp-wpkg-ribbon .wpkg-name { font-size: clamp(1.25rem, 1.9vw, 1.5rem); margin-bottom: 0.85rem; }
:where(.sl-body) main > section.section.comp-wpkg-ribbon .wpkg-price {
  font-size: clamp(1.5rem, 2.3vw, 1.9rem); color: var(--c-accent-ink);
}
:where(.sl-body) main > section.section.comp-wpkg-ribbon .wpkg-cta { margin-bottom: clamp(1.2rem, 2.4vw, 1.6rem); }

/* ── comp-policy-index — a policy list you can read without opening it ────────────────────────
   `.pxp-list` is a hairline accordion: every row is a title and a plus, and the answer only exists
   once you click. For a booking-policy block that is the wrong default — the whole point of the
   section is that a visitor can check the cancellation window in two seconds — and the closed
   state gives them four identical grey rows to choose between.
   Numbering the rows and turning the plus into a ringed control makes the closed list read as an
   index; the open row lifts onto its own plate so the answer is clearly attached to its question.
   `<details>` semantics are untouched: the disclosure widget is doing real work here. */
:where(.sl-body) main > section.section.comp-policy-index .pxp-list { counter-reset: pxp; }
:where(.sl-body) main > section.section.comp-policy-index .pxp-item {
  counter-increment: pxp;
  border: 0;
  border-bottom: 1px solid color-mix(in srgb, var(--c-text) 12%, transparent);
  border-radius: clamp(9px, 1.1vw, 12px);
  transition: background .18s ease;
}
:where(.sl-body) main > section.section.comp-policy-index .pxp-item:first-child { border-top: 0; }
:where(.sl-body) main > section.section.comp-policy-index .pxp-summary {
  gap: clamp(0.9rem, 2vw, 1.4rem);
  padding: clamp(1rem, 2.1vw, 1.45rem) clamp(0.9rem, 1.8vw, 1.2rem);
  font-size: clamp(1rem, 1.35vw, 1.12rem);
}
:where(.sl-body) main > section.section.comp-policy-index .pxp-title::before {
  content: counter(pxp, decimal-leading-zero);
  margin-right: clamp(0.7rem, 1.6vw, 1.1rem);
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.12em;
  color: var(--c-accent-ink); font-variant-numeric: tabular-nums;
}
/* The plus becomes a control rather than two floating bars. */
:where(.sl-body) main > section.section.comp-policy-index .pxp-plus {
  width: clamp(28px, 3vw, 34px); height: clamp(28px, 3vw, 34px);
  border-radius: 50%;
  border: 1px solid color-mix(in srgb, var(--c-text) 18%, transparent);
}
:where(.sl-body) main > section.section.comp-policy-index .pxp-item[open] {
  background: color-mix(in srgb, var(--c-primary-dark) 4%, var(--c-surface));
  border-bottom-color: transparent;
}
:where(.sl-body) main > section.section.comp-policy-index .pxp-item[open] .pxp-plus {
  background: var(--c-accent-ink);
  border-color: var(--c-accent-ink);
}
:where(.sl-body) main > section.section.comp-policy-index .pxp-item[open] .pxp-plus::before, :where(.sl-body) main > section.section.comp-policy-index .pxp-item[open] .pxp-plus::after { background: var(--c-surface); }
:where(.sl-body) main > section.section.comp-policy-index .pxp-body { padding: 0 clamp(0.9rem, 1.8vw, 1.2rem) clamp(1.2rem, 2.4vw, 1.6rem); }
:where(.sl-body) main > section.section.comp-policy-index .pxp-body p { padding-left: clamp(2rem, 4vw, 3rem); }

/* ══ THREE MORE — the highest-volume shapes left on one look ══════════════════════════════════
     popular_packages_local + recommended_packages   99 pages / 14 sites   .pkg-card
     personas                                        41 pages /  9 sites   .personas-list
     trust_strip                                     26 pages / 13 sites   .trust-row

   The package card is the biggest single component in the build after the closing CTA, and it has
   rendered as the same centred stack — bag, name, price, sentence, duration, pill — on every IV
   site since the renderer was written. personas is a bulleted list. trust_strip is four discs.
   Library entries: nothing assigns these. See the note at the head of the previous block. ══════ */

/* ── comp-pkg-price-first — the menu card ─────────────────────────────────────────────────────
   The default centres everything and gives the bag a rounded tinted square floating inside the
   card, which is the arrangement every template uses because it is the one that needs no
   decisions. Three changes, all of them objects rather than positions: the bag panel goes
   FULL-BLEED to the card's edges so the card reads as a product tile, the price is promoted to
   display scale (it is the thing being compared and it currently sets at body size), and the
   Book button becomes a bar across the card floor instead of a pill floating above it.
   The row maths is untouched — `.pkg-card` keeps `flex: 0 0 300px` and the track keeps its
   scroll-snap, because a carousel that loses its step is a broken carousel, not a restyled one.
   `.pkg-body` is `display: contents`, so the price/desc/duration are laid out as direct children
   of the card and are addressed through it; they carry no classes of their own, only inline
   styles from the renderer, which is why font-size and layout are used here and colour is not. */
:where(.sl-body) main > section.section.comp-pkg-price-first .pkg-card {
  padding: 0;
  overflow: hidden;
  text-align: left;
  border: 1px solid color-mix(in srgb, var(--c-primary-dark) 12%, transparent);
  border-radius: clamp(12px, 1.4vw, 16px);
  background: var(--c-surface);
  box-shadow: 0 18px 38px -32px color-mix(in srgb, var(--c-primary-dark) 62%, transparent);
}
/* The bag panel: edge to edge, its own ground, one fixed ratio so a row of cards agrees. */
:where(.sl-body) main > section.section.comp-pkg-price-first .pkg-bag, :where(.sl-body) main > section.section.comp-pkg-price-first .pkg-bag-fallback {
  display: block; width: 100%; height: auto;
  aspect-ratio: 4 / 3; object-fit: contain;
  margin: 0 0 clamp(0.9rem, 1.9vw, 1.25rem);
  border-radius: 0;
  padding: clamp(0.8rem, 1.7vw, 1.15rem);
  background: linear-gradient(165deg,
    color-mix(in srgb, var(--c-accent) 14%, var(--c-surface)),
    color-mix(in srgb, var(--c-primary-dark) 6%, var(--c-surface-alt)));
  border-bottom: 1px solid color-mix(in srgb, var(--c-primary-dark) 10%, transparent);
}
:where(.sl-body) main > section.section.comp-pkg-price-first .pkg-bag-fallback { height: auto; }
:where(.sl-body) main > section.section.comp-pkg-price-first .pkg-bag-fallback svg { height: 100%; width: auto; max-height: 150px; }
:where(.sl-body) main > section.section.comp-pkg-price-first .pkg-card > h3 {
  margin: 0 clamp(1rem, 2.1vw, 1.4rem) 0.3rem;
  font-family: var(--font-heading);
  font-size: clamp(1.08rem, 1.5vw, 1.24rem); line-height: 1.25;
}
/* The price. A bare <div> with an inline accent-ink colour and no class of its own, so this takes
   the size and leaves the colour exactly where the renderer put it. `.pkg-dual-prices` keeps its
   own two-row layout — a card showing an in-clinic and a mobile rate is comparing two figures and
   must not have one of them blown up. */
:where(.sl-body) main > section.section.comp-pkg-price-first .pkg-body > div:not(.pkg-dual-prices):last-of-type {
  margin: 0 clamp(1rem, 2.1vw, 1.4rem);
  font-family: var(--font-heading);
  font-size: clamp(1.5rem, 2.3vw, 1.95rem);
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
:where(.sl-body) main > section.section.comp-pkg-price-first .pkg-dual-prices { margin: 0 clamp(1rem, 2.1vw, 1.4rem); }
/* `price_label` ("from", "starting at") is an OPTIONAL bare div emitted before the price, so the
   rule above uses :last-of-type to find the figure. The label itself drops to a caption — at
   display scale it added a whole line and made the one card that has it taller than its row. */
:where(.sl-body) main > section.section.comp-pkg-price-first .pkg-body > div:not(.pkg-dual-prices):not(:last-of-type) {
  margin: 0 clamp(1rem, 2.1vw, 1.4rem);
  font-size: 0.7rem; letter-spacing: 0.1em; text-transform: uppercase;
}
:where(.sl-body) main > section.section.comp-pkg-price-first .pkg-body > p {
  margin: 0.55rem clamp(1rem, 2.1vw, 1.4rem) 0;
  font-size: 0.93rem; line-height: 1.6;
}
/* The duration stops being a stray line of grey text and becomes a tag. */
:where(.sl-body) main > section.section.comp-pkg-price-first .pkg-body > small {
  display: inline-block;
  margin: 0.85rem clamp(1rem, 2.1vw, 1.4rem) 0;
  padding: 0.24rem 0.6rem;
  border: 1px solid color-mix(in srgb, var(--c-text) 16%, transparent);
  border-radius: 999px;
  font-size: 0.72rem; letter-spacing: 0.06em; text-transform: uppercase; font-weight: 600;
}
/* The floor bar. `align-self` and `margin` are inline on the element, so both need !important —
   they are the renderer's, not a lane's, and there is no other way to reach them. */
:where(.sl-body) main > section.section.comp-pkg-price-first .pkg-book {
  align-self: stretch !important;
  margin: clamp(1.1rem, 2.2vw, 1.5rem) 0 0 !important;
  border-radius: 0;
  text-align: center;
}

/* ── comp-personas-tiles — four situations, not four bullets ──────────────────────────────────
   personas is on 41 pages and renders as a disc-bulleted list: the section that tells a visitor
   "this is you" is the most generic object on the page. Each item becomes a tile with the lead
   promoted out of the sentence into a heading, so the four situations can be scanned instead of
   read. `auto-fit` rather than a fixed column count, because this block also renders in a narrow
   column beside a portrait (`.personas-has-img`) where two tiles across would be 130px each. */
:where(.sl-body) main > section.section.comp-personas-tiles .personas-list {
  list-style: none;
  padding-left: 0;
  display: grid;
  /* TWO columns, not auto-fit. `auto-fit` with a 250px minimum fitted THREE across the measure-
     width container this block renders in, so a four-item list came out 3 + 1 with the fourth tile
     stranded beside dead space — the orphan R16 exists to catch on card rows. Four is the common
     count here, and an odd count leaves a half-width last tile, which reads as a list ending
     rather than as a layout failing. */
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(0.7rem, 1.5vw, 1.1rem);
}
@media (max-width: 700px) {
  :where(.sl-body) main > section.section.comp-personas-tiles .personas-list { grid-template-columns: minmax(0, 1fr); }
}
/* Beside a portrait the copy column is already narrow; two tiles across would be ~130px each. */
:where(.sl-body) main > section.section.comp-personas-tiles .personas-has-img .personas-list { grid-template-columns: minmax(0, 1fr); }
:where(.sl-body) main > section.section.comp-personas-tiles .personas-item {
  margin: 0;
  padding: clamp(1.1rem, 2.2vw, 1.5rem) clamp(1.15rem, 2.4vw, 1.6rem);
  border-radius: clamp(11px, 1.3vw, 15px);
  background: color-mix(in srgb, var(--c-primary-dark) 4%, var(--c-surface));
  border: 1px solid color-mix(in srgb, var(--c-primary-dark) 10%, transparent);
  font-size: 0.95rem;
}
/* The lead is an inline <strong> inside the sentence; as a block it becomes the tile's title and
   the rest of the sentence reads as its body. A hairline under it keeps the two apart without
   adding an element the renderer does not emit. */
:where(.sl-body) main > section.section.comp-personas-tiles .personas-lead {
  display: block;
  margin-bottom: 0.55rem;
  padding-bottom: 0.5rem;
  border-bottom: 1px solid color-mix(in srgb, var(--c-primary-dark) 12%, transparent);
  font-family: var(--font-heading);
  font-size: clamp(1rem, 1.35vw, 1.14rem);
  line-height: 1.25;
  color: var(--c-text);
}
/* Every third tile takes the accent edge, so four tiles are not one tile repeated. */
:where(.sl-body) main > section.section.comp-personas-tiles .personas-item:nth-child(3n + 2) {
  border-color: color-mix(in srgb, var(--c-accent-ink) 34%, transparent);
  background: color-mix(in srgb, var(--c-accent-ink) 5%, var(--c-surface));
}

/* ── comp-trust-plinth — badges, not floating discs ───────────────────────────────────────────
   `.trust-row` is four accent discs over four labels, separated by hairlines. It is the most
   repeated small component after the CTA and it reads as a row of icons with captions rather than
   as a set of claims. Each item becomes a horizontal badge: the icon inline at reading size, the
   claim beside it, the whole thing on a plate with an edge.
   THE ROW IS NOT TOUCHED — and that is deliberate history, not caution. This strip is the section
   that broke the last time a treatment reached it: comp-split put its five badges into a 62%
   column and wrapped them 3+2, which Ian caught on a live page. `.trust-row` keeps its flex, its
   wrap, its gap and its `flex: 0 1 200px` basis; only what an item LOOKS like changes. */
:where(.sl-body) main > section.section.comp-trust-plinth .trust-row-item {
  /* Sized to the claim, not to the 200px basis the stacked disc layout needed — at 200px every
     label wrapped to two lines and the pills came out uneven. The ROW is still untouched: its
     flex, wrap and gap are the base rule's, and the horizontal spacing here is the item's own
     margin, so nothing about how many badges fit on a line is being recomputed. */
  flex: 0 0 auto;
  margin: 0 clamp(0.28rem, 0.7vw, 0.45rem);
  flex-direction: row;
  align-items: center;
  justify-content: flex-start;
  text-align: left;
  gap: clamp(0.6rem, 1.3vw, 0.85rem);
  padding: clamp(0.7rem, 1.5vw, 0.95rem) clamp(0.9rem, 1.9vw, 1.2rem);
  border-radius: 999px;
  background: color-mix(in srgb, var(--c-primary-dark) 4%, var(--c-surface));
  border: 1px solid color-mix(in srgb, var(--c-primary-dark) 11%, transparent);
}
/* The hairline separator was doing the work of an edge; the badge has its own now. */
:where(.sl-body) main > section.section.comp-trust-plinth .trust-row-item + .trust-row-item::before { display: none; }
:where(.sl-body) main > section.section.comp-trust-plinth .trust-row-item .trust-ic {
  width: clamp(26px, 3vw, 32px); height: clamp(26px, 3vw, 32px);
  flex: 0 0 auto;
  background: transparent;
  color: var(--c-accent-ink);
}
:where(.sl-body) main > section.section.comp-trust-plinth .trust-row-item .trust-ic svg { width: 20px; height: 20px; }
:where(.sl-body) main > section.section.comp-trust-plinth .trust-row-item span { font-size: 0.9rem; line-height: 1.25; white-space: nowrap; }
/* In a dark room the badge is a solid light plate, so it goes on the white-plate list's terms. */
:where(.sl-body) main > section.section.sec-room.comp-trust-plinth .trust-row-item {
  background: color-mix(in srgb, var(--c-surface) 92%, transparent);
  border-color: color-mix(in srgb, var(--c-surface) 40%, transparent);
  --c-text: var(--c-primary);
  color: var(--c-primary);
}

/* ══ SECOND DESIGNS — turning "an alternative" into a choice ══════════════════════════════════
   One alternative per shape is not variance: two sites either both take it or both do not. These
   six give the highest-volume shapes a THIRD option each, and every one is built to differ from
   both of the others in silhouette, not only in finish:

     .pkg-card        tile (default) / product panel (price-first) / editorial index (here)
     .vstack-table    table / receipt / ledger with a reversed total
     .ibreak-table    table / plates / glossary with no boxes at all
     .tiercmp-table   table / stepped plates / a rail of stops
     .personas-list   bullets / tiles / numbered editorial rows
     .trust-row       discs / badges / a solid band

   The pattern worth naming: for each shape one option has BOXES, one has PLATES and one has
   NONE. That is the axis a visitor actually reads at a glance, and it is what stops three
   different treatments from looking like three versions of the same idea. ═════════════════════ */

/* ── comp-pkg-index — the drip menu as an editorial index ─────────────────────────────────────
   Where comp-pkg-price-first makes the card a product tile, this removes the card entirely. A big
   index numeral, the name at display scale, the price under it, hairline rules between entries and
   no fill anywhere. It is the option for a brand whose bag art is weak or absent — which is most
   of them at launch, and the reason `.pkg-bag-fallback` (a line-drawn IV bag) exists at all. One
   lane already hides that fallback outright for exactly this reason; this makes it a choice
   instead of a lane's private decision. */
:where(.sl-body) main > section.section.comp-pkg-index .pkg-track { counter-reset: pkgi; }
:where(.sl-body) main > section.section.comp-pkg-index .pkg-card {
  counter-increment: pkgi;
  padding: clamp(1.3rem, 2.6vw, 1.9rem) clamp(0.9rem, 1.9vw, 1.3rem);
  text-align: left;
  background: transparent;
  border: 0;
  border-top: 2px solid color-mix(in srgb, var(--c-text) 20%, transparent);
  border-radius: 0;
  box-shadow: none;
  /* The entry is a COLUMN — numeral, then name, then price, then the line of copy — which is
     what the note above describes and what the numbered rule between entries implies. It was
     inheriting the product card's `row` + `space-between`, so the name became the MIDDLE item
     of a space-between row and its left edge moved with its own length. Measured on LivLong's
     eight-drip menu at 1440: name left edges landed at 341/348/352/356/368px, so no two rows
     in a priced menu started at the same place and the price column read ragged. Column start
     puts all eight at one x. Only `.comp-pkg-index` is touched; the carousel and every other
     package design keep the row. */
  flex-direction: column;
  align-items: flex-start;
  justify-content: flex-start;
}
:where(.sl-body) main > section.section.comp-pkg-index .pkg-card::before {
  content: counter(pkgi, decimal-leading-zero);
  display: block;
  margin-bottom: 0.75rem;
  font-family: var(--font-heading);
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.16em;
  color: var(--c-accent-ink); font-variant-numeric: tabular-nums;
}
:where(.sl-body) main > section.section.comp-pkg-index .pkg-bag, :where(.sl-body) main > section.section.comp-pkg-index .pkg-bag-fallback { display: none; }
:where(.sl-body) main > section.section.comp-pkg-index .pkg-card > h3 {
  margin: 0 0 0.4rem;
  font-family: var(--font-heading);
  font-size: clamp(1.3rem, 2vw, 1.6rem); line-height: 1.18;
}
:where(.sl-body) main > section.section.comp-pkg-index .pkg-body > div:not(.pkg-dual-prices):last-of-type {
  font-family: var(--font-heading);
  font-size: clamp(1.15rem, 1.7vw, 1.4rem); line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
:where(.sl-body) main > section.section.comp-pkg-index .pkg-body > div:not(.pkg-dual-prices):not(:last-of-type) {
  font-size: 0.68rem; letter-spacing: 0.12em; text-transform: uppercase;
}
:where(.sl-body) main > section.section.comp-pkg-index .pkg-body > p { margin-top: 0.7rem; font-size: 0.92rem; line-height: 1.62; }
:where(.sl-body) main > section.section.comp-pkg-index .pkg-body > small { display: block; margin-top: 0.7rem; letter-spacing: 0.08em; text-transform: uppercase; font-size: 0.7rem; }
/* A text link, not a pill — a bordered button on a chrome-less entry is the one thing that would
   put the card back. */
:where(.sl-body) main > section.section.comp-pkg-index .pkg-book {
  align-self: flex-start !important;
  margin: clamp(1rem, 2vw, 1.4rem) 0 0 !important;
  padding: 0 0 0.2rem;
  background: none !important;
  border: 0;
  border-bottom: 1px solid currentColor;
  border-radius: 0;
  color: var(--c-accent-ink) !important;
  box-shadow: none;
  font-size: 0.8rem; letter-spacing: 0.1em; text-transform: uppercase;
}

/* ── comp-value-ledger — the total is the object ──────────────────────────────────────────────
   The receipt sets everything at one weight and lets the leader dots carry the eye. This does the
   opposite: the line items go quiet on hairlines and the TOTAL is reversed out of a dark plate at
   the foot, which is the number the section exists to land. Rule 2 — the plate owns its ink. */
:where(.sl-body) main > section.section.comp-value-ledger .vstack-wrap {
  max-width: 660px; background: transparent; border: 0; border-radius: 0; overflow: visible;
}
:where(.sl-body) main > section.section.comp-value-ledger .vstack-table, :where(.sl-body) main > section.section.comp-value-ledger .vstack-table thead, :where(.sl-body) main > section.section.comp-value-ledger .vstack-table tbody { display: block; width: 100%; }
:where(.sl-body) main > section.section.comp-value-ledger .vstack-table tr {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  align-items: baseline; column-gap: clamp(0.9rem, 2vw, 1.6rem);
}
:where(.sl-body) main > section.section.comp-value-ledger .vstack-table thead th {
  background: transparent; width: auto; text-align: left; padding: 0 0 0.55rem;
  font-size: 0.66rem; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--c-text-muted);
}
:where(.sl-body) main > section.section.comp-value-ledger .vstack-table thead tr { border-bottom: 2px solid color-mix(in srgb, var(--c-text) 24%, transparent); }
:where(.sl-body) main > section.section.comp-value-ledger .vstack-table td {
  display: block; width: auto; padding: clamp(0.7rem, 1.5vw, 1rem) 0; font-size: 0.97rem;
}
:where(.sl-body) main > section.section.comp-value-ledger .vstack-table tbody tr { border-bottom: 1px solid color-mix(in srgb, var(--c-text) 10%, transparent); }
:where(.sl-body) main > section.section.comp-value-ledger .vstack-table tbody tr + tr td { border-top: 0; }
:where(.sl-body) main > section.section.comp-value-ledger .vstack-table td:last-child { text-align: right; font-variant-numeric: tabular-nums; }
/* THE PLATE. Two cells, one ground: the row is a grid, so each td paints its own half and the
   rounding is split between them. */
/* `.vstack-table tr.vstack-row-hl`, not `.vstack-row-hl`: the row rule above sets the grid gutter
   and carries one more element selector, so a bare class here loses and the page colour ran
   straight through the middle of what is meant to be ONE plate. Third time this session that a
   later rule lost to an earlier, longer one — element count is the tiebreak, not source order. */
:where(.sl-body) main > section.section.comp-value-ledger .vstack-table tr.vstack-row-hl {
  border-bottom: 0 !important;
  margin-top: clamp(0.8rem, 1.7vw, 1.2rem);
  column-gap: 0;
  /* STRETCH, not baseline. The row inherits `align-items: baseline` from the line items, which is
     right for a figure sitting on a label's baseline and wrong for a plate: the two cells sized to
     their own content, so the taller one (the price, which wraps) stepped past the shorter one and
     the plate came out notched down its right-hand edge. */
  align-items: stretch;
}
:where(.sl-body) main > section.section.comp-value-ledger .vstack-table tr.vstack-row-hl td { display: grid; align-content: center; }
:where(.sl-body) main > section.section.comp-value-ledger .vstack-row-hl td {
  background: var(--c-hero-plate);
  color: var(--c-on-dark);                 /* rule 2 */
  padding: clamp(1rem, 2.1vw, 1.4rem) clamp(1rem, 2.1vw, 1.4rem);
  font-weight: 700;
}
:where(.sl-body) main > section.section.comp-value-ledger .vstack-row-hl td:first-child {
  border-radius: clamp(10px, 1.2vw, 14px) 0 0 clamp(10px, 1.2vw, 14px);
  font-size: 0.72rem; letter-spacing: 0.12em; text-transform: uppercase;
}
:where(.sl-body) main > section.section.comp-value-ledger .vstack-row-hl td:last-child {
  border-radius: 0 clamp(10px, 1.2vw, 14px) clamp(10px, 1.2vw, 14px) 0;
  font-family: var(--font-heading); font-size: clamp(1rem, 1.5vw, 1.2rem); max-width: 20ch;
}
:where(.sl-body) main > section.section.comp-value-ledger .vstack-footer { max-width: 660px; }

/* MOBILE: the base rule at :3840 stacks every row to `display: block` below 640px, but the total
   row carries a (0,4,3) selector here and stayed a two-column grid — so its two halves sized
   independently, the label wrapped to three lines against the price's two, and the plate came out
   with a notch bitten from its bottom-left corner. The plate stacks with everything else.
   The base rule also prefixes the cost with "Cost: " on mobile, which reads as nonsense inside the
   total ("Cost: $235, best value for this combination"), so it comes off in the plate only. */
@media (max-width: 640px) {
  :where(.sl-body) main > section.section.comp-value-ledger .vstack-table tr.vstack-row-hl {
    display: block;
    background: var(--c-hero-plate);
    border-radius: clamp(10px, 1.2vw, 14px);
    padding: clamp(0.9rem, 3vw, 1.2rem) clamp(1rem, 3.5vw, 1.3rem);
  }
  :where(.sl-body) main > section.section.comp-value-ledger .vstack-table tr.vstack-row-hl td, :where(.sl-body) main > section.section.comp-value-ledger .vstack-table tr.vstack-row-hl td:first-child, :where(.sl-body) main > section.section.comp-value-ledger .vstack-table tr.vstack-row-hl td:last-child {
    display: block; background: transparent; border-radius: 0; padding: 0; text-align: left;
  }
  :where(.sl-body) main > section.section.comp-value-ledger .vstack-table tr.vstack-row-hl td:last-child { margin-top: 0.35rem; max-width: none; }
  :where(.sl-body) main > section.section.comp-value-ledger .vstack-table tr.vstack-row-hl .vstack-cost::before { content: none; }
}

/* ── comp-ing-split — a glossary, no boxes ────────────────────────────────────────────────────
   comp-ing-cards gives every ingredient a plate. This gives none of them one: tracked small-caps
   names in a narrow left column, descriptions at a reading measure on the right, one hairline
   between entries and a lot of air. It is the quiet option, and a package page that already
   carries two card grids does not need a third. */
:where(.sl-body) main > section.section.comp-ing-split { --ings-cols: minmax(0, 26fr) minmax(0, 74fr); }
:where(.sl-body) main > section.section.comp-ing-split .ibreak-panel {
  background: transparent; border: 0; border-radius: 0; overflow: visible;
  max-width: min(var(--content-max), 62rem);
}
:where(.sl-body) main > section.section.comp-ing-split .ibreak-table, :where(.sl-body) main > section.section.comp-ing-split .ibreak-table thead, :where(.sl-body) main > section.section.comp-ing-split .ibreak-table tbody { display: block; width: 100%; }
:where(.sl-body) main > section.section.comp-ing-split .ibreak-table tr {
  display: grid; grid-template-columns: var(--ings-cols);
  gap: 0 clamp(1.4rem, 3.5vw, 3.25rem); align-items: start;
  padding: clamp(1.15rem, 2.4vw, 1.75rem) 0;
}
:where(.sl-body) main > section.section.comp-ing-split .ibreak-table thead tr { padding-top: 0; padding-bottom: 0.5rem; }
:where(.sl-body) main > section.section.comp-ing-split .ibreak-table thead th {
  background: transparent; width: auto; padding: 0;
  font-size: 0.66rem; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--c-text-muted);
}
:where(.sl-body) main > section.section.comp-ing-split .ibreak-table tbody tr { border-top: 1px solid color-mix(in srgb, var(--c-text) 12%, transparent); }
:where(.sl-body) main > section.section.comp-ing-split .ibreak-table td { display: block; width: auto; padding: 0; border-top: 0; }
:where(.sl-body) main > section.section.comp-ing-split .ibreak-table td.ibreak-name {
  width: auto;
  font-size: 0.78rem; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase;
  line-height: 1.6; color: var(--c-text);
}
:where(.sl-body) main > section.section.comp-ing-split .ibreak-table td.ibreak-desc {
  color: var(--c-text-muted); line-height: 1.72; font-size: 1rem; max-width: 68ch;
}
@media (max-width: 760px) {
  :where(.sl-body) main > section.section.comp-ing-split { --ings-cols: minmax(0, 1fr); }
  :where(.sl-body) main > section.section.comp-ing-split .ibreak-table thead { display: none; }
  :where(.sl-body) main > section.section.comp-ing-split .ibreak-table tbody tr { gap: 0.45rem 0; }
}

/* ── comp-tier-rail — the lineup as a set of stops ────────────────────────────────────────────
   The ladder gives every tier a plate. This gives none of them one and runs a rail down the left
   instead, with a ringed stop per tier — the same reading (a sequence you move along) with the
   opposite weight. On the force-dark tier band the rail and stops ride the light accent pair the
   component already uses. */
:where(.sl-body) main > section.section.comp-tier-rail .tiercmp-panel { background: transparent; border: 0; border-radius: 0; overflow: visible; }
:where(.sl-body) main > section.section.comp-tier-rail .tiercmp-table { border-collapse: separate; border-spacing: 0; }
:where(.sl-body) main > section.section.comp-tier-rail .tiercmp-table thead th {
  background: transparent; color: color-mix(in srgb, var(--c-on-dark) 58%, transparent);
  font-size: 0.66rem; letter-spacing: 0.14em; text-transform: uppercase; font-weight: 600;
  padding: 0 1rem 0.6rem;
}
:where(.sl-body) main > section.section.comp-tier-rail .tiercmp-table thead th:first-child { padding-left: clamp(2.2rem, 4vw, 3rem); }
:where(.sl-body) main > section.section.comp-tier-rail .tiercmp-table tbody td {
  background: transparent;
  border-top: 1px solid color-mix(in srgb, var(--c-on-dark) 14%, transparent);
  padding: clamp(1.15rem, 2.4vw, 1.7rem) 1rem;
  vertical-align: top;
}
/* THE RAIL. Drawn on the first cell so it runs the full height of every row and joins up between
   them; the stop is a ringed disc sitting on it. */
:where(.sl-body) main > section.section.comp-tier-rail .tiercmp-table td.tiercmp-pkg {
  position: relative;
  padding-left: clamp(2.2rem, 4vw, 3rem);
  font-family: var(--font-heading); font-size: clamp(1rem, 1.4vw, 1.15rem); font-weight: 600;
}
:where(.sl-body) main > section.section.comp-tier-rail .tiercmp-table td.tiercmp-pkg::before {
  content: ''; position: absolute; left: clamp(0.75rem, 1.5vw, 1.1rem); top: 0; bottom: 0;
  width: 2px; background: color-mix(in srgb, var(--c-accent) 28%, transparent);
}
:where(.sl-body) main > section.section.comp-tier-rail .tiercmp-row:last-child td.tiercmp-pkg::before { bottom: 50%; }
:where(.sl-body) main > section.section.comp-tier-rail .tiercmp-table td.tiercmp-pkg::after {
  content: ''; position: absolute;
  left: calc(clamp(0.75rem, 1.5vw, 1.1rem) - 5px);
  top: clamp(1.35rem, 2.7vw, 1.95rem);
  width: 12px; height: 12px; border-radius: 50%;
  background: var(--c-accent-ink-dark, var(--c-accent));
  box-shadow: 0 0 0 4px var(--c-primary-dark);
}
:where(.sl-body) main > section.section.comp-tier-rail .tiercmp-price {
  font-variant-numeric: tabular-nums; font-size: clamp(1.05rem, 1.5vw, 1.25rem);
  color: var(--c-accent-ink-dark, var(--c-accent));
}
@media (max-width: 760px) {
  :where(.sl-body) main > section.section.comp-tier-rail .tiercmp-table td.tiercmp-pkg::before, :where(.sl-body) main > section.section.comp-tier-rail .tiercmp-table td.tiercmp-pkg::after { display: none; }
  :where(.sl-body) main > section.section.comp-tier-rail .tiercmp-table td.tiercmp-pkg { padding-left: 0; }
}

/* ── comp-personas-rules — numbered editorial rows ────────────────────────────────────────────
   The tiles put four boxes on the page. This puts none: an oversized numeral in its own column,
   the lead as a heading beside it, a hairline between. Same content, and where the tiles are a
   set you scan, this is a list you read down. */
:where(.sl-body) main > section.section.comp-personas-rules .personas-list {
  list-style: none; padding-left: 0; counter-reset: pr;
  border-top: 1px solid color-mix(in srgb, var(--c-text) 14%, transparent);
}
:where(.sl-body) main > section.section.comp-personas-rules .personas-item {
  counter-increment: pr;
  display: grid; grid-template-columns: clamp(2.4rem, 4.5vw, 3.4rem) minmax(0, 1fr);
  column-gap: clamp(1rem, 2.2vw, 1.7rem);
  align-items: start;
  margin: 0;
  padding: clamp(1.15rem, 2.4vw, 1.75rem) 0;
  border-bottom: 1px solid color-mix(in srgb, var(--c-text) 14%, transparent);
  font-size: 0.97rem; line-height: 1.68;
}
:where(.sl-body) main > section.section.comp-personas-rules .personas-item::before {
  content: counter(pr, decimal-leading-zero);
  grid-column: 1; grid-row: 1 / span 2;
  font-family: var(--font-heading);
  font-size: clamp(1.4rem, 2.6vw, 2rem); line-height: 1.05;
  color: var(--c-accent-ink); font-variant-numeric: tabular-nums;
}
:where(.sl-body) main > section.section.comp-personas-rules .personas-lead {
  display: block; grid-column: 2; margin-bottom: 0.3rem;
  font-family: var(--font-heading); font-size: clamp(1.05rem, 1.45vw, 1.22rem); line-height: 1.25;
  color: var(--c-text);
}
:where(.sl-body) main > section.section.comp-personas-rules .personas-item > span { grid-column: 2; }

/* ── comp-trust-band — one solid claim bar ────────────────────────────────────────────────────
   Discs are the default and badges are the second option; both are a row of separate objects. This
   is the opposite: one dark band across the section with the claims set in it, icons dropped and a
   small accent diamond between. It is the strongest possible reading of a trust strip — a single
   statement rather than four decorations — and the treatment that most changes what the top of a
   page feels like.
   Painting the SECTION (not the row) is what makes it a band, and rule 2 applies in full: the
   section rebinds its ink, so anything inside it lands light-on-dark by construction. */
:where(.sl-body) main > section.section.comp-trust-band {
  background: var(--c-hero-plate);
  --c-text: var(--c-on-dark);
  --c-text-muted: color-mix(in srgb, var(--c-on-dark) 78%, var(--c-primary-dark));
  --c-border: color-mix(in srgb, var(--c-on-dark) 22%, transparent);
  color: var(--c-on-dark);
  padding-top: clamp(1.1rem, 2.4vw, 1.7rem);
  padding-bottom: clamp(1.1rem, 2.4vw, 1.7rem);
}
:where(.sl-body) main > section.section.comp-trust-band .trust-row-item {
  /* Sized to the claim, like the badge option and for the same reason: at the base 200px basis
     every label broke over two lines, and a band of small caps set two-deep reads as a paragraph
     rather than as one line of proof. The ROW keeps its own flex, wrap and gap. */
  flex: 0 0 auto;
  flex-direction: row; align-items: center; justify-content: center;
  padding: 0 clamp(1rem, 2.4vw, 1.9rem);
  background: transparent; border: 0;
}
:where(.sl-body) main > section.section.comp-trust-band .trust-row-item span { white-space: nowrap; }
:where(.sl-body) main > section.section.comp-trust-band .trust-row-item .trust-ic { display: none; }
:where(.sl-body) main > section.section.comp-trust-band .trust-row-item span {
  color: var(--c-on-dark);
  font-size: 0.86rem; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase;
  line-height: 1.3;
}
/* The hairline separator becomes a diamond — a rule between two lines of small caps reads as a
   table border, and this band is one sentence made of four parts. */
:where(.sl-body) main > section.section.comp-trust-band .trust-row-item + .trust-row-item::before {
  content: '';
  top: 50%; bottom: auto; left: -3px;
  width: 5px; height: 5px;
  transform: translateY(-50%) rotate(45deg);
  background: var(--c-accent-ink-dark, var(--c-accent));
}

/* ══ FOUR MORE — the two highest-volume shapes with only two options, plus two with none ═══════
     .cat-grid   72 pages / 13 sites   had two (cats-portrait, cats-rule)
     .edu-list   44 pages /  9 sites   had two (edu-checks, edu-chips)
     .ac-grid     8 pages /  8 sites   had one (facts)
     .auto-grid   5 pages /  4 sites   had none

   `.cat-grid` is the highest-volume shape in the whole build — five section keys render it — and
   two options across thirteen sites still means most of them share one. It gets the COLOUR option:
   the axis its existing two do not use. ═══════════════════════════════════════════════════════ */

/* ── comp-cats-swatch — the tile IS the colour ────────────────────────────────────────────────
   The default is a white card with a pale disc; cats-portrait makes it a panel; cats-rule removes
   the box. All three are light, and on a page that already carries two card grids a browse row
   reads as more of the same. This one is solid: each tile takes a block of brand colour, the label
   reverses out of it, and the icon goes large and ghosted behind the type so the tile has
   something in it besides a word.
   Three mixes stepping through the brand pair, because six identical coloured blocks is the same
   monotony as six identical white ones — the cadence device the card treatments already use.
   ROW MATHS UNTOUCHED: `.cat-grid` is a flex row whose `--sl-basis` cardBasis() computed for this
   count, and re-gridding it is what produced a 3+3+2 orphan the last time (visual-lint R16). */
:where(.sl-body) main > section.section.comp-cats-swatch .cat-card {
  position: relative;
  overflow: hidden;
  flex-direction: column;
  align-items: flex-start;
  justify-content: flex-end;
  min-height: clamp(130px, 15vw, 168px);
  padding: clamp(1.1rem, 2.3vw, 1.55rem);
  border: 0;
  border-radius: clamp(12px, 1.4vw, 16px);
  box-shadow: none;
  background: var(--c-hero-plate);
  color: var(--c-on-dark);                 /* rule 2 — the tile repainted its own ground */
}
:where(.sl-body) main > section.section.comp-cats-swatch .cat-card:nth-child(3n + 2) { background: color-mix(in srgb, var(--c-primary-dark) 68%, var(--c-accent)); }
:where(.sl-body) main > section.section.comp-cats-swatch .cat-card:nth-child(3n) { background: var(--c-accent-ink); }
:where(.sl-body) main > section.section.comp-cats-swatch .cat-card > span {
  position: relative; z-index: 1;
  color: var(--c-on-dark);
  font-family: var(--font-heading);
  font-size: clamp(1.02rem, 1.4vw, 1.18rem); font-weight: 600; line-height: 1.22;
  text-align: left;
}
/* The icon becomes the tile's texture: oversized, top-right, at low opacity behind the label. */
:where(.sl-body) main > section.section.comp-cats-swatch .cat-ic {
  position: absolute;
  top: clamp(-0.6rem, -1vw, -0.4rem); right: clamp(-0.8rem, -1.4vw, -0.5rem);
  width: clamp(84px, 11vw, 116px); height: clamp(84px, 11vw, 116px);
  margin: 0;
  background: transparent;
  border: 0;
  box-shadow: none;
  color: color-mix(in srgb, var(--c-surface) 26%, transparent);
  opacity: 1;
}
:where(.sl-body) main > section.section.comp-cats-swatch .cat-ic svg { width: 100%; height: 100%; }
:where(.sl-body) main > section.section.comp-cats-swatch .cat-card:hover {
  transform: none;
  box-shadow: 0 20px 40px -28px color-mix(in srgb, var(--c-primary-dark) 70%, transparent);
}
:where(.sl-body) main > section.section.comp-cats-swatch .cat-card:hover .cat-ic { color: color-mix(in srgb, var(--c-surface) 38%, transparent); }
/* The "view all" tile is a call to action, not a category, so it stays light and reads as the
   way OUT of the grid rather than as a seventh thing to pick. */
:where(.sl-body) main > section.section.comp-cats-swatch .cat-card.cat-card-all {
  background: transparent;
  border: 1px solid color-mix(in srgb, var(--c-primary-dark) 24%, transparent);
  color: var(--c-accent-ink);
  justify-content: center;
}
:where(.sl-body) main > section.section.comp-cats-swatch .cat-card.cat-card-all > span { color: var(--c-accent-ink); }

/* ── comp-edu-rules — an index, not a list ────────────────────────────────────────────────────
   edu-checks gives every point a mark and edu-chips makes each one an object. This removes both:
   a small tracked index number in its own column, the point beside it, a hairline between and real
   air. On a safety or standards list that reads as a numbered register — the register being the
   point of the section — where a column of ticks reads as marketing. */
:where(.sl-body) main > section.section.comp-edu-rules .edu-list {
  list-style: none;
  padding-left: 0 !important;
  columns: auto !important;
  counter-reset: edur;
  border-top: 1px solid color-mix(in srgb, var(--c-text) 14%, transparent);
}
:where(.sl-body) main > section.section.comp-edu-rules .edu-list > li {
  counter-increment: edur;
  display: grid;
  grid-template-columns: clamp(2rem, 3.6vw, 2.9rem) minmax(0, 1fr);
  gap: 0 clamp(0.8rem, 1.8vw, 1.3rem);
  align-items: baseline;
  padding: clamp(0.8rem, 1.7vw, 1.15rem) 0;
  border-bottom: 1px solid color-mix(in srgb, var(--c-text) 14%, transparent);
  line-height: 1.62;
}
:where(.sl-body) main > section.section.comp-edu-rules .edu-list > li::before {
  content: counter(edur, decimal-leading-zero);
  font-size: 0.7rem; font-weight: 700; letter-spacing: 0.14em;
  color: var(--c-accent-ink); font-variant-numeric: tabular-nums;
}
:where(.sl-body) main > section.section.comp-edu-rules .edu-list > li strong { color: var(--c-text); }

/* ── comp-contact-plates — the four facts as objects ──────────────────────────────────────────
   `.ac-grid` had exactly one treatment (`facts`, a hairline label/value ledger) and its default is
   four small white cards. Both are quiet, which is wrong for the band that answers where, when and
   how to reach someone: it is the last thing a visitor needs and it should be the easiest thing to
   find. Each fact becomes a plate with its label reversed out of a solid cap, so the four read as
   a set of tickets rather than as a row of notes. */
:where(.sl-body) main > section.section.comp-contact-plates .ac-card {
  padding: 0;
  overflow: hidden;
  border: 0;
  border-radius: clamp(11px, 1.3vw, 15px);
  background: var(--c-surface);
  box-shadow: 0 16px 34px -30px color-mix(in srgb, var(--c-primary-dark) 62%, transparent);
  text-align: left;
}
:where(.sl-body) main > section.section.comp-contact-plates .ac-card .contact-method-label {
  display: block;
  margin: 0;
  padding: clamp(0.55rem, 1.2vw, 0.8rem) clamp(0.9rem, 1.9vw, 1.25rem);
  background: var(--c-hero-plate);
  color: var(--c-on-dark);                 /* rule 2 */
  font-size: 0.66rem; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase;
}
:where(.sl-body) main > section.section.comp-contact-plates .ac-card:nth-child(3n + 2) .contact-method-label { background: var(--c-accent-ink); }
:where(.sl-body) main > section.section.comp-contact-plates .ac-card .ac-card-value {
  display: block;
  padding: clamp(0.85rem, 1.8vw, 1.2rem) clamp(0.9rem, 1.9vw, 1.25rem);
  font-family: var(--font-heading);
  font-size: clamp(0.98rem, 1.3vw, 1.1rem); line-height: 1.4;
  color: var(--c-text);
}

/* ── comp-events-panel — one offer, not three cards ───────────────────────────────────────────
   event_wellness renders three white cards with gradient icon tiles, which is the house card row
   again on a section that is making a single pitch: we will bring this to your event. As one dark
   panel with the three uses as ruled rows inside it, the section reads as an offer with examples
   rather than as three unrelated products, and it breaks a run of pale card grids the way a solid
   band does. Rule 2 in full — the panel rebinds its ink so anything added inside it later lands
   light-on-dark by construction. */
:where(.sl-body) main > section.section.comp-events-panel .auto-grid {
  display: block;
  max-width: var(--content-max);
  margin: 0 auto;
  padding: clamp(1.5rem, 3.2vw, 2.4rem) clamp(1.5rem, 3.4vw, 2.6rem);
  border-radius: clamp(14px, 1.6vw, 20px);
  background: var(--c-hero-plate);
  --c-text: var(--c-on-dark);
  --c-text-muted: color-mix(in srgb, var(--c-on-dark) 78%, var(--c-primary-dark));
  --c-border: color-mix(in srgb, var(--c-on-dark) 20%, transparent);
  color: var(--c-on-dark);
}
:where(.sl-body) main > section.section.comp-events-panel .auto-card {
  display: grid;
  grid-template-columns: minmax(0, 34fr) minmax(0, 66fr);
  gap: 0 clamp(1.2rem, 3vw, 2.5rem);
  align-items: baseline;
  padding: clamp(1rem, 2.1vw, 1.45rem) 0;
  background: transparent;
  border: 0;
  border-bottom: 1px solid color-mix(in srgb, var(--c-on-dark) 18%, transparent);
  border-radius: 0;
  box-shadow: none;
  text-align: left;
}
:where(.sl-body) main > section.section.comp-events-panel .auto-card:last-of-type { border-bottom: 0; }
:where(.sl-body) main > section.section.comp-events-panel .auto-card:hover { transform: none; box-shadow: none; }
/* The gradient icon tile goes: three of them stacked down a dark panel is the loudest thing on the
   band and it is decorating a list of examples. */
:where(.sl-body) main > section.section.comp-events-panel .feature-ic { display: none; }
:where(.sl-body) main > section.section.comp-events-panel .auto-card h3 {
  margin: 0;
  color: var(--c-on-dark);
  font-size: clamp(1.02rem, 1.4vw, 1.18rem); line-height: 1.3;
}
:where(.sl-body) main > section.section.comp-events-panel .auto-card p {
  margin: 0;
  color: color-mix(in srgb, var(--c-surface) 80%, var(--c-primary-dark));
  font-size: 0.95rem; line-height: 1.6;
}
:where(.sl-body) main > section.section.comp-events-panel .event-cta { margin-top: clamp(1.4rem, 2.8vw, 2rem); }
@media (max-width: 700px) {
  :where(.sl-body) main > section.section.comp-events-panel .auto-card { grid-template-columns: minmax(0, 1fr); gap: 0.35rem 0; }
}

/* ── hero.ink:'primary' — BRAND-COLOURED display type ────────────────────────────────────────
   White hero type only works because a scrim is buried under it, and on a pale subject that scrim
   is what kills the picture. Navy on the same frame needs none. Everything in the hero flips
   together — headline, tagline, button — or the button becomes the odd one out. */
/* `.hero-video` sets white ink at (0,1,0), and the archetype restates it as
   `body.ad-typographic-clinical .hero h1 { color: var(--c-surface) !important }` — so !important
   is the only thing that reaches it. Justified: which ink an opted-in hero uses is the hero
   variant's decision, not the archetype's. Its navy text-shadow goes too; behind navy letters it
   is a smudge rather than a lift. */
/* The FALLBACK ground has to change with the ink. The archetype paints the hero section navy and
   the video covers it — but if the video never loads, navy type on navy is an invisible hero, and
   R15 measures exactly that (1:1). Cream is the page's own stock and the same value range as the
   pale footage, so the fallback looks deliberate rather than broken. */
:where(.sl-body) .hero.hero-ink-primary { color: var(--c-primary) !important; background: var(--c-surface-alt) !important; }
:where(.sl-body) .hero.hero-ink-primary h1, :where(.sl-body) .hero.hero-ink-primary .hero-tagline, :where(.sl-body) .hero.hero-ink-primary .subhead { color: var(--c-primary) !important; }
:where(.sl-body) .hero.hero-ink-primary h1 { text-shadow: 0 1px 26px color-mix(in srgb, var(--c-light-stock) 70%, transparent) !important; }
/* An AUTHORED line break only holds if the line is allowed to fit. The archetype caps the hero h1
   at 16ch and the centred column at 860px, which broke "Without Compromise." across two lines and
   turned a deliberate two-line headline into a ragged three. Give the centred hero room for the
   longest line it was written with; the clamp still shrinks the type on narrow screens. */
:where(.sl-body) .hero.hero-align-center .hero-inner { max-width: 1040px; }
:where(.sl-body) .hero.hero-ink-primary h1, :where(.sl-body) .hero.hero-align-center h1 { max-width: none !important; }
:where(.sl-body) .hero.hero-ink-primary .btn-primary {
  background: var(--c-primary); border-color: var(--c-primary); color: var(--c-on-primary);
}
:where(.sl-body) .hero.hero-ink-primary .btn-primary:hover {
  background: var(--c-primary-dark); border-color: var(--c-primary-dark);
}
:where(.sl-body) .hero.hero-ink-primary .btn-secondary { color: var(--c-primary); border-color: var(--c-primary); }
/* The floor gradient exists to darken the frame for white type. With navy type it does the
   opposite — lift the frame, so the letterforms sit on light rather than fighting a shadow. */
:where(.sl-body) .hero-ink-primary.hero-video::after {
  background: linear-gradient(180deg,
    rgba(255,255,255,0) 0%,
    rgba(255,255,255,0) 34%,
    color-mix(in srgb, var(--c-surface-alt) 42%, transparent) 60%,
    color-mix(in srgb, var(--c-surface-alt) 72%, transparent) 82%,
    color-mix(in srgb, var(--c-surface-alt) 86%, transparent) 100%) !important;
}
:where(.sl-body) .hero-ink-primary .hero-inner::after { display: none; }

/* ── hero.ink:'gilt' — cream headline, gold second line ──────────────────────────────────────
   Navy display type on a pale frame reads heavy and flat: the letterforms are the darkest thing
   on screen and the video stops being the subject. Cream puts the type back on the same side as
   the light, and setting only the SECOND authored line in gold gives the two-tone Ian asked for
   without a colour change mid-sentence.
   The reason this is not just `hero-video`'s default white: white needs the frame scrim that Ian
   had removed ("I want the Hero video to look exactly how it's supposed to look"). Instead the
   contrast comes from a shadow cast by the LETTERS — it darkens ~1.5rem around the glyph edges
   and leaves the rest of the picture untouched. */
:where(.sl-body) .hero.hero-ink-gilt { color: var(--c-surface-alt) !important; }
:where(.sl-body) .hero.hero-ink-gilt h1, :where(.sl-body) .hero.hero-ink-gilt .hero-tagline, :where(.sl-body) .hero.hero-ink-gilt .subhead { color: var(--c-surface-alt) !important; }
:where(.sl-body) .hero.hero-ink-gilt h1 .h1-l2 { color: var(--c-accent) !important; }
:where(.sl-body) .hero.hero-ink-gilt h1 {
  text-shadow:
    0 1px 2px color-mix(in srgb, var(--c-primary-dark) 55%, transparent),
    0 2px 24px color-mix(in srgb, var(--c-primary-dark) 62%, transparent) !important;
}
:where(.sl-body) .hero.hero-ink-gilt .hero-tagline, :where(.sl-body) .hero.hero-ink-gilt .subhead {
  text-shadow: 0 1px 16px color-mix(in srgb, var(--c-primary-dark) 70%, transparent) !important;
}
/* Same fallback argument as ink:'primary', inverted. If the video never loads the hero falls back
   to the archetype's navy, which cream type is measured against — so R15 sees a real pair either
   way rather than cream on cream. */
:where(.sl-body) .hero.hero-ink-gilt { background: var(--c-hero-plate) !important; }
/* The button stays navy: Ian asked for the blue in the button and only reversed on the headline.
   On a pale frame a solid navy block is the highest-contrast thing available. */
:where(.sl-body) .hero.hero-ink-gilt .btn-primary {
  background: var(--c-primary); border-color: var(--c-primary); color: var(--c-on-primary);
}
:where(.sl-body) .hero.hero-ink-gilt .btn-primary:hover {
  background: var(--c-primary-dark); border-color: var(--c-primary-dark);
}
:where(.sl-body) .hero.hero-ink-gilt .btn-secondary {
  color: var(--c-surface-alt); border-color: color-mix(in srgb, var(--c-surface-alt) 70%, transparent);
}
/* Keep the floor gradient's default (darkening) direction — with cream type it is working WITH
   the ink again, unlike under ink:'primary' where it had to be inverted. */
:where(.sl-body) .hero.hero-ink-gilt.hero-align-center .hero-inner { max-width: 1040px; }
:where(.sl-body) .hero.hero-ink-gilt h1 { max-width: none !important; }

/* ══ THE COVERAGE LIST, AND THREE SECOND OPTIONS ══════════════════════════════════════════════
   `.coverage-chips` is on 25 pages across 13 SITES — the widest site coverage of anything still
   untreated — and it is a wrapping cloud of identical pale pills. The map beside it is bespoke
   geometry and is not touched here; only the list of place names is.
   The other three give a second option to shapes that had exactly one. ═══════════════════════ */

/* ── comp-areas-chips — a directory, not a cloud of pills ─────────────────────────────────────
   Every served town gets the same pale pill, so a three-city area and a twenty-city area look
   like the same component with more of it, and at twenty the block is a wrapping mass with no
   order to it. Columns of ruled rows instead, each with a small pin: it reads as a directory you
   could look your own town up in, which is the only question this section is asked.
   CSS columns rather than a grid, so the list packs itself to whatever count a brand has — the
   count is `brand.service_areas.length` and varies from 3 to 20+ across the roster. */
:where(.sl-body) main > section.section.comp-areas-chips .coverage-chips {
  display: block;
  columns: 2 150px;
  column-gap: clamp(1.2rem, 3vw, 2.25rem);
  margin-bottom: 1.6rem;
}
:where(.sl-body) main > section.section.comp-areas-chips .coverage-chip {
  display: flex;
  align-items: baseline;
  gap: 0.55rem;
  break-inside: avoid;
  padding: 0.5rem 0;
  border: 0;
  border-bottom: 1px solid color-mix(in srgb, var(--c-on-dark) 20%, transparent);
  border-radius: 0;
  background: transparent;
  font-weight: 500;
}
/* The pin is drawn in the mask so it takes the accent and needs no SVG asset — the same device
   comp-edu-checks uses for its check mark. */
:where(.sl-body) main > section.section.comp-areas-chips .coverage-chip::before {
  content: '';
  flex: 0 0 auto;
  width: 0.72rem; height: 0.72rem;
  background-color: var(--c-accent-ink-dark, var(--c-accent));
  -webkit-mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M12 22s7-7.6 7-13a7 7 0 1 0-14 0c0 5.4 7 13 7 13z' fill='none' stroke='black' stroke-width='2.4'/><circle cx='12' cy='9' r='2.6' fill='none' stroke='black' stroke-width='2.4'/></svg>");
  mask-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M12 22s7-7.6 7-13a7 7 0 1 0-14 0c0 5.4 7 13 7 13z' fill='none' stroke='black' stroke-width='2.4'/><circle cx='12' cy='9' r='2.6' fill='none' stroke='black' stroke-width='2.4'/></svg>");
  -webkit-mask-size: contain; mask-size: contain;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
}
/* The coverage band is dark by default (the chips ship white-on-translucent), but this component
   also renders on a light stock in the stacked layout, so the rule below restates the hairline and
   the ink for that case rather than assuming either one. */
:where(.sl-body) main > section.section.comp-areas-chips .coverage-stack .coverage-chip {
  border-bottom-color: color-mix(in srgb, var(--c-text) 14%, transparent);
  color: var(--c-text);
}

/* ── comp-stdl-rule — the manifesto as a running rule ─────────────────────────────────────────
   comp-stdl-plaque gives every standard a plate and a solid numeral block. This gives none: the
   numeral goes outboard in the margin at display scale, the claim runs at a measure beside it, and
   a single hairline separates the entries. Where the plaque is a set of commitments you look at,
   this is a manifesto you read — and it is the option for a serif brand, where an oversized figure
   in the heading face is the whole design. */
:where(.sl-body) main > section.section.comp-stdl-rule .stdl-list { display: block; }
:where(.sl-body) main > section.section.comp-stdl-rule .stdl-row {
  border: 0;
  border-top: 1px solid color-mix(in srgb, var(--c-text) 14%, transparent);
  border-radius: 0;
  background: transparent;
  padding: clamp(1.5rem, 3vw, 2.4rem) 0;
  grid-template-columns: clamp(3.6rem, 7vw, 6rem) minmax(0, 1fr);
  gap: 0 clamp(1.4rem, 3.5vw, 3rem);
  align-items: start;
}
:where(.sl-body) main > section.section.comp-stdl-rule .stdl-row:first-child { border-top: 0; padding-top: 0; }
:where(.sl-body) main > section.section.comp-stdl-rule .stdl-num {
  display: block;
  width: auto; height: auto;
  background: transparent;
  border-radius: 0;
  color: color-mix(in srgb, var(--c-accent-ink) 55%, transparent);
  font-size: clamp(2.6rem, 5.5vw, 4.4rem);
  line-height: 0.85;
}
:where(.sl-body) main > section.section.comp-stdl-rule .stdl-copy h3 {
  font-size: clamp(1.2rem, 1.9vw, 1.55rem);
  margin-bottom: 0.5rem;
}
:where(.sl-body) main > section.section.comp-stdl-rule .stdl-copy p { max-width: 62ch; line-height: 1.7; }

/* ── comp-prep-checklist — one list, two headings ─────────────────────────────────────────────
   comp-prep-duo opposes the two columns, dark against light. This does the opposite: it removes
   the boxes entirely so BEFORE and AFTER read as two halves of one checklist, separated by a
   single vertical rule. The icon becomes a small inline mark rather than a badge, and the check
   marks carry the only colour. It is the quiet option for a page that already carries card grids
   above and below — which on a treatment page it always does. */
:where(.sl-body) main > section.section.comp-prep-checklist .prepaft-col {
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  padding: 0 clamp(1.2rem, 3vw, 2.5rem);
}
:where(.sl-body) main > section.section.comp-prep-checklist .prepaft-col:first-child:not(:only-child) {
  border-right: 1px solid color-mix(in srgb, var(--c-text) 14%, transparent);
  padding-left: 0;
}
:where(.sl-body) main > section.section.comp-prep-checklist .prepaft-col:last-child:not(:only-child) { padding-right: 0; }
:where(.sl-body) main > section.section.comp-prep-checklist .prepaft-col-head {
  gap: 0.6rem;
  padding-bottom: 0.75rem;
  border-bottom: 0;
  margin-bottom: 0.9rem;
}
:where(.sl-body) main > section.section.comp-prep-checklist .prepaft-ic {
  width: 24px; height: 24px;
  background: transparent;
  color: var(--c-accent-ink);
  border-radius: 0;
}
:where(.sl-body) main > section.section.comp-prep-checklist .prepaft-ic svg { width: 20px; height: 20px; }
:where(.sl-body) main > section.section.comp-prep-checklist .prepaft-col-head h3 {
  font-size: 0.74rem; font-weight: 700; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--c-text-muted);
}
:where(.sl-body) main > section.section.comp-prep-checklist .prepaft-list { gap: 0.75rem; }
:where(.sl-body) main > section.section.comp-prep-checklist .prepaft-list li { line-height: 1.65; }
@media (max-width: 768px) {
  /* The renderer's own inline CSS stacks the grid here, so the divider becomes a horizontal rule
     between the two halves rather than a stray vertical line down a single column. */
  :where(.sl-body) main > section.section.comp-prep-checklist .prepaft-col { padding: 0; }
  :where(.sl-body) main > section.section.comp-prep-checklist .prepaft-col:first-child:not(:only-child) {
    border-right: 0;
    border-bottom: 1px solid color-mix(in srgb, var(--c-text) 14%, transparent);
    padding-bottom: clamp(1.2rem, 3vw, 1.8rem);
  }
}

/* ── comp-policy-cards — the accordion as a set of panels ─────────────────────────────────────
   comp-policy-index keeps the accordion as a single ruled column and numbers it. This breaks it
   into a grid of boxed panels, so four short booking policies read as four things rather than as
   one list, and a long terms page stops being a hundred hairlines deep.
   THE FIRST DRAFT TRIED TO FORCE THEM OPEN and rendered four empty boxes. A closed `<details>`
   hides its content through the UA's own mechanism — in current Chrome a `::details-content`
   pseudo carrying `content-visibility: hidden` — which `display: block !important` on the child
   cannot reach. It is not a cascade problem, so no amount of specificity fixes it, and the
   `::details-content` override that would work is too new to rely on across the roster. The
   disclosure stays, the plus stays with it (it is the affordance for a thing that opens), and the
   treatment changes what the panel LOOKS like — which was the brief. */
:where(.sl-body) main > section.section.comp-policy-cards .pxp-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), minmax(0, 1fr)));
  gap: clamp(0.7rem, 1.5vw, 1.1rem);
  align-items: start;
}
:where(.sl-body) main > section.section.comp-policy-cards .pxp-item {
  border: 1px solid color-mix(in srgb, var(--c-primary-dark) 11%, transparent);
  border-radius: clamp(11px, 1.3vw, 15px);
  background: color-mix(in srgb, var(--c-primary-dark) 3%, var(--c-surface));
  transition: background .18s ease, border-color .18s ease;
}
:where(.sl-body) main > section.section.comp-policy-cards .pxp-item:first-child { border-top: 1px solid color-mix(in srgb, var(--c-primary-dark) 11%, transparent); }
:where(.sl-body) main > section.section.comp-policy-cards .pxp-summary {
  padding: clamp(1rem, 2.1vw, 1.4rem) clamp(1.1rem, 2.3vw, 1.55rem);
  gap: clamp(0.8rem, 1.8vw, 1.2rem);
  font-family: var(--font-heading);
  font-size: clamp(1rem, 1.35vw, 1.12rem);
  line-height: 1.28;
}
:where(.sl-body) main > section.section.comp-policy-cards .pxp-item[open] {
  background: var(--c-surface);
  border-color: color-mix(in srgb, var(--c-accent-ink) 34%, transparent);
}
:where(.sl-body) main > section.section.comp-policy-cards .pxp-item[open] .pxp-summary { padding-bottom: 0.5rem; }
:where(.sl-body) main > section.section.comp-policy-cards .pxp-body {
  padding: 0 clamp(1.1rem, 2.3vw, 1.55rem) clamp(1.1rem, 2.3vw, 1.5rem);
}
:where(.sl-body) main > section.section.comp-policy-cards .pxp-body p { font-size: 0.94rem; line-height: 1.65; }
:where(.sl-body) main > section.section.comp-policy-cards .pxp-plus { color: var(--c-accent-ink); }

/* ══ THE PROSE SHAPES — ~150 pages that nothing could ever dress ══════════════════════════════
   Nine section keys route through `renderProseParagraphs` (PROSE_KEYS: condition_lead,
   how_iv_treats, pathophysiology, when_to_get, how_iv_works, why_this_helps,
   how_it_works_with_brand, about_intro, city_intro) and it emitted an unclassed `<div>` of `<p>`.
   Add up their instances and it is roughly 150 pages — the single most common thing on a condition
   or city page — and not one treatment in the library could select it, because there was nothing
   to select. Same hole `.edu-list` had, same fix: name the shape.

   AND THEN THE MEASUREMENT SAID OTHERWISE. `.prose-block` renders on ZERO pages across six builds:
   the string branch of renderProseParagraphs almost never fires, because the generator emits an
   OBJECT and RESCUE_OBJ_KEYS reroutes those keys to the education block or to the generic
   media+text band. The ~150-page figure came from counting content_json KEYS, which is not the
   same question as what the renderer emits — the census has to be run on built HTML, which is what
   every other shape in this file was measured from.
   So one treatment stays here, documented as dormant, for the branch that does exist; the three
   others built alongside it were deleted rather than shipped as silent no-ops. `.vp-solo` was
   dropped from the renderer for the same reason. The shape those sections ACTUALLY become is
   `.img-text` — see the block below it, which is where the volume turned out to be.

   THE RISK THESE CARRY THAT A CARD TREATMENT DOES NOT: prose has no items, so there is no grid to
   balance and no card to recolour — the only levers are measure, rhythm and one piece of
   furniture. Which is exactly how the chimney-width headline happened. Every measure below is in
   rem or ch against the element it is set on, and every one was read back off a rendered page. ══ */

/* ── comp-prose-lead — the first paragraph does the work ──────────────────────────────────────
   The default sets every paragraph at one size down a 64ch measure, so a four-paragraph condition
   explainer opens with no more emphasis than it ends with. This promotes the FIRST paragraph to a
   lead — larger, looser, in the heading face — and leaves the rest alone. It is the oldest trick
   in editorial layout and it costs nothing structurally, which on a shape with no structure is
   the point. */
:where(.sl-body) main > section.section.comp-prose-lead .prose-block { max-width: min(var(--content-measure), 68ch); }
:where(.sl-body) main > section.section.comp-prose-lead .prose-block > p:first-child {
  font-family: var(--font-heading);
  font-size: clamp(1.15rem, 1.7vw, 1.42rem);
  line-height: 1.55;
  color: var(--c-text);
  margin-bottom: clamp(1rem, 2.1vw, 1.5rem);
}
:where(.sl-body) main > section.section.comp-prose-lead .prose-block > p + p {
  margin-top: 0;
  margin-bottom: clamp(0.85rem, 1.8vw, 1.2rem);
  line-height: 1.75;
}
:where(.sl-body) main > section.section.comp-prose-lead .prose-block > p:last-child { margin-bottom: 0; }

/* ── comp-psa-plate — the price stops being a heading ─────────────────────────────────────────
   pricing_starting_at is on 49 pages and renders as a centred eyebrow, an h2 and a line of grey
   text — the same silhouette as every other centred header on the page, for the one band whose
   whole job is to state a number. The block becomes a plate with the figure at display scale and
   the range beneath it, so it reads as a price and not as a section title. */
:where(.sl-body) main > section.section.comp-psa-plate .psa-block {
  display: inline-grid;
  justify-items: center;
  gap: 0.3rem;
  padding: clamp(1.4rem, 3vw, 2.2rem) clamp(2rem, 5vw, 3.5rem);
  border-radius: clamp(12px, 1.4vw, 18px);
  background: color-mix(in srgb, var(--c-primary-dark) 5%, var(--c-surface));
  border: 1px solid color-mix(in srgb, var(--c-primary-dark) 12%, transparent);
}
/* The block is inline-grid, so the CONTAINER has to centre it — the element can no longer do that
   for itself with `margin: 0 auto` because it is now shrink-to-fit inside a full-width parent. */
:where(.sl-body) main > section.section.comp-psa-plate > .container { text-align: center; }
:where(.sl-body) main > section.section.comp-psa-plate .psa-block h2 {
  margin: 0;
  font-size: clamp(2.2rem, 4.6vw, 3.4rem);
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
:where(.sl-body) main > section.section.comp-psa-plate .psa-block p {
  margin: 0;
  font-size: 0.94rem;
  color: var(--c-text-muted);
}


/* ══ .img-text — THE BAND THE PROSE SECTIONS ACTUALLY BECOME ══════════════════════════════════
   Measured on built HTML across six sites: 46 bands, nine different section keys, and every one
   of the six builds has at least one. condition_lead, concern_router, mechanism_explainer,
   value_prop_two_col, about_intro, why_this_helps, how_iv_treats, authority_founder_block and
   city_intro all land here — any section whose value carries a real image is diverted by
   Sections.astro into this generic two-column media+text band, whatever its own renderer would
   have done.

   It is the widest untreated shape left in the build, and it renders one way: photo one side, copy
   the other, alternating sides down the page, `border-radius` on the image and nothing else. The
   alternation is already doing the work a treatment usually has to invent, so these two change
   what the PICTURE is rather than where it sits — which is also the only lever that does not fight
   `_imgRow`, the counter in Sections.astro that decides which side each band leans.

   Shape: `.img-text` / `.img-text.reverse` > `.itr-media` > img, and `.itr-body` carrying an
   eyebrow, an h2, paragraphs, an optional `.itr-checklist` and a button. ═══════════════════════ */

/* ── comp-imgtext-bleed — the photograph stops being a card ───────────────────────────────────
   The image sits in a rounded box with the copy beside it, so the band reads as a card next to
   some text. Here the picture runs to the full height of the band and squares off against the
   copy column: no radius, no gap on its own side, and a tall crop. It is the difference between
   an illustration and a photograph the page is built around, and it costs nothing but geometry
   the band already has.
   The gap is closed on ONE side only, and which side depends on `.reverse` — the renderer
   alternates it, so a rule that assumed left would square the wrong edge on every second band. */
:where(.sl-body) main > section.section.comp-imgtext-bleed .img-text {
  gap: 0;
  align-items: stretch;
}
:where(.sl-body) main > section.section.comp-imgtext-bleed .itr-media {
  align-self: stretch;
  display: grid;
  border-radius: 0;
  overflow: hidden;
}
/* `max-height: none` is the whole fix, and it cost three attempts to find because I kept treating
   a 43px shortfall as a stretch problem. The base rule at :710 caps every img-text photograph at
   `max-height: 520px` — sensible for a band whose picture floats in a rounded box, and exactly
   wrong for one that runs the full height of the band. The column WAS stretching correctly the
   whole time (measured: media box 558px, body 558px); the image was simply capped.
   Read the base rule for the property you are fighting, not the one you assume is fighting you. */
:where(.sl-body) main > section.section.comp-imgtext-bleed .itr-media img {
  width: 100%; height: 100%;
  max-height: none;
  min-height: clamp(300px, 34vw, 460px);
  object-fit: cover;
  border-radius: 0;
  box-shadow: none;
  display: block;
}
:where(.sl-body) main > section.section.comp-imgtext-bleed .itr-body {
  align-self: center;
  padding: clamp(1.5rem, 4vw, 3.25rem);
  background: color-mix(in srgb, var(--c-primary-dark) 4%, var(--c-surface));
}
:where(.sl-body) main > section.section.comp-imgtext-bleed .itr-body > *:last-child { margin-bottom: 0; }

/* ── comp-imgtext-frame — the picture gets an edge and the copy gets a rail ───────────────────
   The other direction: keep the two columns as objects, but make the photograph a framed plate
   (an offset accent rule behind it, the way the istack plates are framed on the dark-luxe lane)
   and give the copy a hairline rail so the column has a left edge to sit against. Where bleed
   removes the frame, this commits to it.
   The offset frame is a ::after on the media, not a border on the image — a border would eat into
   the picture, and the whole point is that the rule sits OUTSIDE it. `.itr-media` needs
   `position: relative` for that, which the base rule does not set. */
:where(.sl-body) main > section.section.comp-imgtext-frame .img-text { align-items: center; }
:where(.sl-body) main > section.section.comp-imgtext-frame .itr-media { position: relative; }
:where(.sl-body) main > section.section.comp-imgtext-frame .itr-media img {
  position: relative; z-index: 1;
  border-radius: 0;
  display: block; width: 100%; height: auto;
}
:where(.sl-body) main > section.section.comp-imgtext-frame .itr-media::after {
  content: '';
  position: absolute;
  z-index: 0;
  inset: clamp(0.8rem, 1.8vw, 1.4rem) calc(-1 * clamp(0.8rem, 1.8vw, 1.4rem)) calc(-1 * clamp(0.8rem, 1.8vw, 1.4rem)) clamp(0.8rem, 1.8vw, 1.4rem);
  border: 2px solid color-mix(in srgb, var(--c-accent-ink) 55%, transparent);
  pointer-events: none;
}
/* Mirrored bands offset the frame the other way, or it points off the page. */
:where(.sl-body) main > section.section.comp-imgtext-frame .img-text.reverse .itr-media::after {
  inset: clamp(0.8rem, 1.8vw, 1.4rem) clamp(0.8rem, 1.8vw, 1.4rem) calc(-1 * clamp(0.8rem, 1.8vw, 1.4rem)) calc(-1 * clamp(0.8rem, 1.8vw, 1.4rem));
}
:where(.sl-body) main > section.section.comp-imgtext-frame .itr-body {
  padding-left: clamp(1.1rem, 2.4vw, 1.8rem);
  border-left: 2px solid color-mix(in srgb, var(--c-text) 16%, transparent);
}
:where(.sl-body) main > section.section.comp-imgtext-frame .img-text.reverse .itr-body {
  padding-left: 0;
  padding-right: clamp(1.1rem, 2.4vw, 1.8rem);
  border-left: 0;
  border-right: 2px solid color-mix(in srgb, var(--c-text) 16%, transparent);
}
:where(.sl-body) main > section.section.comp-imgtext-frame .itr-body h2 { margin-top: 0; }
@media (max-width: 860px) {
  /* Stacked, an offset frame hanging off the side just overflows, and a rail down a full-width
     column is a stray line. Both come off and the band reverts to photo-over-copy. */
  :where(.sl-body) main > section.section.comp-imgtext-frame .itr-media::after { display: none; }
  :where(.sl-body) main > section.section.comp-imgtext-frame .itr-body, :where(.sl-body) main > section.section.comp-imgtext-frame .img-text.reverse .itr-body {
    padding-left: 0; padding-right: 0; border-left: 0; border-right: 0;
  }
}

/* ── comp-menu-list — the add-ons as a printed menu, on any site ──────────────────────────────
   `.addon-grid` was the one shape on the original list that got skipped, and the reason was a
   specificity fight: `body.bands-paper … .section-addons_boosters_grid:nth-of-type(n) .addon-card`
   is (0,5,3) and already converts the grid to a leader-dot menu, so any ordinary treatment landed
   under it and did nothing.
   Fighting that rule would have been the wrong move, because that rule is RIGHT — its own comment
   makes the argument better than a new design would: a priced list IS a menu, a card is for
   something you pick up, and six identical white slabs cost 1,345px on a 390px phone to say six
   things of the form "Vitamin B12 … +$25". The problem was never the idea. The problem is that the
   idea is welded to one lane, so exactly one client out of twenty-six can have it.
   So this promotes it instead of competing with it: the same menu, lane-agnostic, opt-in per
   section. On a paper site the existing rule already produces this and the class is a harmless
   no-op; everywhere else it is the second design `.addon-grid` never had.
   THE ONE SUBSTANTIVE DIFFERENCE is the ink. The lane version hard-codes white rules
   (`rgba(255,255,255,0.14)`), which is correct on the navy room it was written for and invisible
   on page stock. Every rule here is mixed from `--c-text`, so it lands on any band. */
/* ONE MENU, TWO SELECTORS, ONE SET OF DECLARATIONS. `bands-paper` + the section key is the original
   menu and this is the lane-agnostic promotion of it, and while both spelled the shape out the
   older copy missed the phone unwrap at the foot of this block — 67px of overflow on a 425px page,
   with the price flush to the window edge. Everything that is the same in both is declared once,
   here, with both selectors on it, so the unwrap below cannot reach one shape and miss the other.
   Everything that is ink stays where its ink is derived. The section-keyed selector is the more
   specific of the two, so on a paper site that also wears the class the result is unchanged. */
:where(.sl-body).bands-paper main > section.section.section-addons_boosters_grid:nth-of-type(n) .addon-grid, :where(.sl-body) main > section.section.comp-menu-list .addon-grid {
  display: block;                      /* --sl-basis goes inert, by design: a menu has no columns */
  max-width: var(--content-measure);   /* R7: a menu is TEXT, so it takes the text edge */
  margin: 0 auto;
}
:where(.sl-body) main > section.section.comp-menu-list .addon-card {
  display: block;
  flex: none;
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  padding: 0.95rem 0;
  border-bottom: 1px solid color-mix(in srgb, var(--c-text) 14%, transparent);
}
:where(.sl-body) main > section.section.comp-menu-list .addon-card:first-child {
  border-top: 1px solid color-mix(in srgb, var(--c-text) 14%, transparent);
}
/* No lift: a menu line is printed, not picked up. */
:where(.sl-body) main > section.section.comp-menu-list .addon-card:hover {
  transform: none;
  box-shadow: none;
  border-color: color-mix(in srgb, var(--c-text) 14%, transparent);
}
/* name ·············· +$25. The dots have to sit BETWEEN the name and the price, and ::after is
   last in DOM order — so `order` re-sequences the flex line rather than the renderer emitting an
   extra element. Without it the line reads "Vitamin B12 +$25 ·········", price glued to the name
   and dots trailing into nothing. */
:where(.sl-body).bands-paper main > section.section.section-addons_boosters_grid:nth-of-type(n) .addon-head, :where(.sl-body) main > section.section.comp-menu-list .addon-head {
  align-items: baseline;
  justify-content: flex-start;
  gap: 0.75rem;
}
:where(.sl-body).bands-paper main > section.section.section-addons_boosters_grid:nth-of-type(n) .addon-name, :where(.sl-body) main > section.section.comp-menu-list .addon-name { white-space: nowrap; font-size: 1.08rem; order: 1; }
:where(.sl-body) main > section.section.comp-menu-list .addon-head::after {
  content: '';
  order: 2;
  flex: 1 1 auto;
  align-self: center;
  min-width: 1.5rem;
  border-bottom: 1px dotted color-mix(in srgb, var(--c-text) 34%, transparent);
}
/* The pill becomes a figure. A bordered chip on a menu line is a button on a price list. */
:where(.sl-body) main > section.section.comp-menu-list .addon-pill {
  order: 3;
  padding: 0;
  background: transparent;
  border: 0;
  border-radius: 0;
  color: var(--c-accent-ink);
  font-size: 1.02rem;
}
:where(.sl-body) main > section.section.comp-menu-list .addon-desc {
  margin-top: 0.3rem;
  font-size: 0.92rem;
  max-width: 62ch;
}
/* The dosed-booster sub-rows are already this idiom; they only need their ink re-derived. */
:where(.sl-body) main > section.section.comp-menu-list .addon-tiers { border-top-color: color-mix(in srgb, var(--c-text) 14%, transparent); }
:where(.sl-body) main > section.section.comp-menu-list .addon-tier-dots { border-bottom-color: color-mix(in srgb, var(--c-text) 34%, transparent); }
:where(.sl-body) main > section.section.comp-menu-list .addon-tier-price { color: var(--c-accent-ink); }
/* "+ ADD TO ANY IV" repeated on every line is the same sentence six times. It says something once
   at the foot of the menu, or it says nothing. */
:where(.sl-body) main > section.section.comp-menu-list .addon-note { display: none; }
:where(.sl-body) main > section.section.comp-menu-list .addon-card:last-child .addon-note {
  display: inline-flex;
  margin-top: 0.9rem;
  padding-top: 0;
}
/* On a long name the nowrap above would push the price off the line, so below the wrap width the
   row stacks: name and price on one line, description under it. This is the rule the section-keyed
   copy never had, which is why it is written here against both selectors rather than twice. */
@media (max-width: 560px) {
  :where(.sl-body).bands-paper main > section.section.section-addons_boosters_grid:nth-of-type(n) .addon-name, :where(.sl-body) main > section.section.comp-menu-list .addon-name { white-space: normal; }
  :where(.sl-body).bands-paper main > section.section.section-addons_boosters_grid:nth-of-type(n) .addon-head, :where(.sl-body) main > section.section.comp-menu-list .addon-head { flex-wrap: wrap; }
  :where(.sl-body).bands-paper main > section.section.section-addons_boosters_grid:nth-of-type(n) .addon-head::after, :where(.sl-body) main > section.section.comp-menu-list .addon-head::after { min-width: 0.75rem; }
}
/* In a dark room the rules and the price ink both come off the band's own light pair — the same
   correction the lane version hard-codes, expressed so it works on either ground. */
:where(.sl-body) main > section.section.sec-room.comp-menu-list .addon-card, :where(.sl-body) main > section.section.sec-room.comp-menu-list .addon-card:first-child, :where(.sl-body) main > section.section.sec-room.comp-menu-list .addon-card:hover {
  border-color: color-mix(in srgb, var(--c-on-room) 16%, transparent);
}
:where(.sl-body) main > section.section.sec-room.comp-menu-list .addon-head::after {
  border-bottom-color: color-mix(in srgb, var(--c-on-room) 32%, transparent);
}
:where(.sl-body) main > section.section.sec-room.comp-menu-list .addon-pill, :where(.sl-body) main > section.section.sec-room.comp-menu-list .addon-tier-price {
  color: var(--c-accent-ink-dark, var(--c-accent));
}

/* ══ THEMES — a signature device carried across every component ═══════════════════════════════
   WHAT WAS MISSING, measured rather than felt. The eight existing "art directions" touch
   background, colour, font-weight, letter-spacing, box-shadow, font-size and border-radius —
   nothing else. That is a SKIN: paint and type sizes. None of them introduces a shape language,
   an imagery treatment or a texture, which is why Pure IV and Ember, both wearing
   `ad-bold-modern`, read as the same site in different hex codes, and why eight of twenty-six
   clients wear no art direction at all.

   No number of per-section treatments fixes that. A section treatment changes one band; a theme
   is the thing that makes twelve bands look like one designed page. The difference is a SIGNATURE
   DEVICE — one graphic idea repeated everywhere the eye lands, so the page has a memory of itself.

   Each theme below is opt-in via a body class and changes nothing until a brand asks for it.
   They ride the same measured ink pairs as everything else, so R15 covers them. ═══════════════ */

/* ── theme-apothecary ─────────────────────────────────────────────────────────────────────────
   THE DEVICE IS THE ARCH. Every piece of media in the page — the hero, a card's photograph, an
   ingredient tile, a team portrait, an icon well — is capped with the same arch, and the same
   curve is echoed in the section frames and the buttons. It is the most recognisable shape in
   modern wellness branding for a reason: it reads as apothecary, spa and clinic at once, and it
   costs one border-radius.
   Around it: a warm paper ground with a real grain, a display serif doing the headline work,
   tracked small-caps for every label, and hairline rules with a diamond at their centre. */
:where(.sl-body).theme-apothecary {
  --arch: 999px 999px 0 0 / 42% 42% 0 0;
  --ap-rule: color-mix(in srgb, var(--c-text) 16%, transparent);
  --ap-paper: color-mix(in srgb, var(--c-accent) 5%, var(--c-surface-alt));
  background: var(--ap-paper);
  /* THE THEME REPAINTED THE PAGE, SO THE THEME OWNS THE INK ON IT. Rule 2 of this file, at page
     scale rather than at band scale, and it took the gate to catch it: wiring a themed build so
     visual-lint could read one put R15 at 73 warnings against a baseline of 20 — 53 new failures,
     none of which I had seen by eye.
     The cause is that every ink token was measured against the ORIGINAL surface. On this tinted
     paper (~rgb(228,231,223)) the inherited muted text lands at 4.1:1 and accent links at 3.07:1,
     both under the 4.5 floor. Darkening both here fixes nav, footer and body copy in one place,
     because everything downstream inherits these two variables. Mixing the accent toward --c-text
     rather than toward black keeps the brand hue while buying the ratio. */
  --c-text-muted: color-mix(in srgb, var(--c-text) 82%, var(--ap-paper));
  --c-accent-ink: color-mix(in srgb, var(--c-accent) 42%, var(--c-text));
}
/* THE GRAIN. A page-wide texture at 3% — enough to stop a flat colour field reading as a browser
   default, far too little to touch any measured contrast pair. Fixed attachment so it belongs to
   the page rather than scrolling with any one band. */
:where(.sl-body).theme-apothecary::before {
  content: '';
  position: fixed; inset: 0; z-index: 0; pointer-events: none; opacity: 0.035;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/></filter><rect width='140' height='140' filter='url(%23n)'/></svg>");
}
:where(.sl-body).theme-apothecary main, :where(.sl-body).theme-apothecary header, :where(.sl-body).theme-apothecary footer { position: relative; z-index: 1; }

/* EVERY PIECE OF MEDIA TAKES THE ARCH. This is the whole theme in one selector list — the device
   has to appear on the hero AND the cards AND the portraits, or it is a one-off flourish rather
   than a language. */
:where(.sl-body).theme-apothecary .itr-media, :where(.sl-body).theme-apothecary .itr-media img, :where(.sl-body).theme-apothecary .istack-a img, :where(.sl-body).theme-apothecary .istack-b img, :where(.sl-body).theme-apothecary .pxp-frame, :where(.sl-body).theme-apothecary .coverage-index-photo img, :where(.sl-body).theme-apothecary .personas-media img, :where(.sl-body).theme-apothecary .tm-photo, :where(.sl-body).theme-apothecary .cat-card img.cat-ic, :where(.sl-body).theme-apothecary .img-item-media img {
  border-radius: var(--arch);
  overflow: hidden;
}
/* The hero is the first arch a visitor sees, so it sets the expectation the rest repeats. */
:where(.sl-body).theme-apothecary .hero-image-bg, :where(.sl-body).theme-apothecary .hero-video { border-radius: 0 0 var(--arch); }

/* TYPE. A display serif carries every heading and the labels go tracked small-caps — the two
   moves that separate an apothecary from a SaaS landing page.
   THE BRIEF WINS. This stack used to end in `var(--font-heading)` with a comment claiming a brand
   that had set its own serif was "unchanged". It was not: a font stack takes the FIRST face that
   loads, and Cormorant always loads, so the brand's face sat fourth and never rendered once. Every
   client who specified a typeface silently lost it the moment they wore this theme — which is the
   whole objection to themes, and it was real. `--font-heading-authored` is emitted by brand.ts ONLY
   when the client actually chose a face (see the note there); it is absent for the brands that
   chose none, so they still get Cormorant and the theme keeps its identity. */
:where(.sl-body).theme-apothecary h1, :where(.sl-body).theme-apothecary h2, :where(.sl-body).theme-apothecary .hero h1 {
  font-family: var(--font-heading-authored, 'Cormorant Garamond'), 'Playfair Display', Georgia, serif;
  font-weight: 500;
  letter-spacing: -0.005em;
  line-height: 1.08;
}
:where(.sl-body).theme-apothecary h2 { font-size: clamp(2rem, 4.2vw, 3.2rem); }
:where(.sl-body).theme-apothecary .eyebrow, :where(.sl-body).theme-apothecary .stat-label, :where(.sl-body).theme-apothecary .tm-title {
  font-family: var(--font-body);
  font-size: 0.66rem; font-weight: 600; letter-spacing: 0.22em; text-transform: uppercase;
  background: none; padding: 0; border-radius: 0;
}

/* THE RULE WITH A DIAMOND. A section header is separated from its content by a hairline broken at
   the centre by a small rotated square — the repeated punctuation mark of the theme, and the
   cheapest way to make twelve bands feel like chapters of one document. */
:where(.sl-body).theme-apothecary .section-header { position: relative; padding-bottom: clamp(1.6rem, 3vw, 2.4rem); }
:where(.sl-body).theme-apothecary .section-header::after {
  content: '';
  position: absolute; left: 50%; bottom: clamp(0.7rem, 1.5vw, 1.1rem);
  width: 7px; height: 7px; margin-left: -3.5px;
  transform: rotate(45deg);
  background: var(--c-accent-ink);
}
:where(.sl-body).theme-apothecary .section-header::before {
  content: '';
  position: absolute; left: 50%; bottom: clamp(1.05rem, 1.9vw, 1.45rem);
  width: min(340px, 60%); height: 1px; margin-left: min(-170px, -30%);
  background: linear-gradient(to right, transparent, var(--ap-rule) 22%, var(--ap-rule) 78%, transparent);
}
/* A left-set header (the ledger and prose treatments) gets the same punctuation, hung left. */
:where(.sl-body).theme-apothecary .comp-numbered .section-header::before, :where(.sl-body).theme-apothecary .comp-ledger .section-header::before, :where(.sl-body).theme-apothecary .comp-quiet-prose .section-header::before { left: 0; margin-left: 0; width: min(240px, 40%); }
:where(.sl-body).theme-apothecary .comp-numbered .section-header::after, :where(.sl-body).theme-apothecary .comp-ledger .section-header::after, :where(.sl-body).theme-apothecary .comp-quiet-prose .section-header::after { left: 0; margin-left: 0; }

/* CARDS LOSE THEIR SHADOW AND GAIN AN EDGE. A drop shadow is the SaaS default; an apothecary card
   is a printed label — flat, warm, hairline-edged, square-cornered so the arch is the only curve
   in the system and therefore reads as deliberate. */
:where(.sl-body).theme-apothecary .card, :where(.sl-body).theme-apothecary .whyus-card, :where(.sl-body).theme-apothecary .cat-card, :where(.sl-body).theme-apothecary .addon-card, :where(.sl-body).theme-apothecary .wpkg-card, :where(.sl-body).theme-apothecary .tier-card, :where(.sl-body).theme-apothecary .faq-item, :where(.sl-body).theme-apothecary .team-member-card {
  border-radius: 2px;
  border: 1px solid var(--ap-rule);
  box-shadow: none;
  background: color-mix(in srgb, var(--c-surface) 94%, var(--c-accent));
}
:where(.sl-body).theme-apothecary .card:hover, :where(.sl-body).theme-apothecary .cat-card:hover, :where(.sl-body).theme-apothecary .addon-card:hover { transform: none; box-shadow: none; border-color: var(--c-accent-ink); }
/* A PLATE OWNS ITS PADDING AND ITS NEIGHBOURS' AIR — the ink rule (sec-room list at :4283)
   applied to geometry. Every card in the list above carries its own interior padding EXCEPT
   .faq-item: the base accordion is a ruled list whose summary/answer pad 1.15rem vertically and
   ZERO horizontally, because the row sits directly on the page. The label plate above converts
   each row into a bounded object, and a bounded object whose question starts at pixel 0 of its
   own edge reads as broken — LivLong's FAQ shipped exactly that on 2026-08-09, questions flush
   against the plate and six plates fused into one slab by their adjacent 1px borders. Padding on
   the ITEM so summary and answer inherit one inset; margin, not gap, because .faq-list is a
   plain block. */
:where(.sl-body).theme-apothecary .faq-item { padding: 0.15rem clamp(1.1rem, 2.2vw, 1.5rem); }
:where(.sl-body).theme-apothecary .faq-item + .faq-item { margin-top: clamp(0.55rem, 1.2vw, 0.85rem); }
/* THE PLATE OWNER OWNS THE INK, IN ROOMS TOO. The generic room rebind (:4283) excuses
   plate-STRIPPING treatments so a bare row keeps the room's white ink — but apothecary
   re-plates these cards at its own precedence, so a section wearing an excused treatment
   (Ember's symptom browse, comp-cats-rule, sec-room) rendered WHITE room ink on the theme's
   CREAM label plates at 1.05:1. The theme painted the plate; the theme sets its ink, on
   every card class it plates, whatever the section wears. */
/* The same strip-comp carve-outs as the generic rebind (:4283) apply HERE too — comp-menu-list
   proved it: it strips the addon plates entirely, so the dark ink this rule set landed on the
   naked navy room at 1:1 (Ember addons, caught next build). comp-cats-rule deliberately stays
   COVERED (not carved out): apothecary re-plates .cat-card at its own precedence, which is the
   exact case this rule exists for. */
:where(.sl-body).theme-apothecary main > section.section.sec-room:where(:not(.comp-menu-list):not(.comp-ledger):not(.comp-quiet-prose):not(.comp-statement):not(.comp-numbered):not(.comp-callout):not(.comp-split):not(.comp-swatch):not(.comp-panel)) .card, :where(.sl-body).theme-apothecary main > section.section.sec-room:where(:not(.comp-menu-list):not(.comp-ledger):not(.comp-quiet-prose):not(.comp-statement):not(.comp-numbered):not(.comp-callout):not(.comp-split):not(.comp-swatch):not(.comp-panel)) .whyus-card, :where(.sl-body).theme-apothecary main > section.section.sec-room .cat-card, :where(.sl-body).theme-apothecary main > section.section.sec-room:where(:not(.comp-menu-list):not(.comp-ledger):not(.comp-quiet-prose):not(.comp-statement):not(.comp-numbered):not(.comp-callout):not(.comp-split):not(.comp-swatch):not(.comp-panel)) .addon-card, :where(.sl-body).theme-apothecary main > section.section.sec-room:where(:not(.comp-menu-list):not(.comp-ledger):not(.comp-quiet-prose):not(.comp-statement):not(.comp-numbered):not(.comp-callout):not(.comp-split):not(.comp-swatch):not(.comp-panel)) .wpkg-card, :where(.sl-body).theme-apothecary main > section.section.sec-room:where(:not(.comp-menu-list):not(.comp-ledger):not(.comp-quiet-prose):not(.comp-statement):not(.comp-numbered):not(.comp-callout):not(.comp-split):not(.comp-swatch):not(.comp-panel)) .tier-card, :where(.sl-body).theme-apothecary main > section.section.sec-room .faq-item, :where(.sl-body).theme-apothecary main > section.section.sec-room:where(:not(.comp-menu-list):not(.comp-ledger):not(.comp-quiet-prose):not(.comp-statement):not(.comp-numbered):not(.comp-callout):not(.comp-split):not(.comp-swatch):not(.comp-panel)) .team-member-card {
  --c-text: var(--c-primary);
  --c-text-muted: var(--c-muted-on-surface, color-mix(in srgb, var(--c-primary) 74%, var(--c-surface-alt)));
  --c-border: color-mix(in srgb, var(--c-primary) 12%, var(--c-surface-alt));
}

/* BUTTONS. Squared, hairline, tracked — a label on a bottle, not a call to action in a dashboard.
   The primary keeps its fill so the conversion path is unchanged; only its shape and type move. */
:where(.sl-body).theme-apothecary .btn {
  border-radius: 2px;
  font-size: 0.72rem; font-weight: 600; letter-spacing: 0.18em; text-transform: uppercase;
  padding: 0.95rem 1.9rem;
  box-shadow: none;
}
:where(.sl-body).theme-apothecary .btn-secondary { border-width: 1px; background: transparent; }

/* The numbered disc becomes an outlined arch-topped marker, so even the step rail speaks the
   same language as the photographs.
   IT IS FILLED, NOT OUTLINED, AND THAT IS NOT A STYLE PREFERENCE. Transparent, the numeral sits
   directly on whatever is behind the band — and a third of the step rails on this platform run over
   a photograph, where a dark-gold glyph on a dark room is simply not there. R15 cannot catch it
   either: it reads the computed background, finds `rgba(0,0,0,0)`, and has nothing to measure a
   ratio against. A solid ground is the only version of this that is legible on both. */
:where(.sl-body).theme-apothecary .step-badge {
  background: var(--ap-paper);
  color: var(--c-accent-ink);
  border: 1px solid var(--c-accent-ink);
  border-radius: 999px 999px 4px 4px;
  font-family: 'Cormorant Garamond', Georgia, serif;
  font-size: 1.15rem;
}
:where(.sl-body).theme-apothecary .steps-connected::before { display: none; }

/* ── theme-clinic ─────────────────────────────────────────────────────────────────────────────
   THE DEVICE IS THE GRID, MADE VISIBLE. Nothing floats and nothing is round: cards share their
   borders instead of sitting in gutters, every band is numbered like a page of a spec sheet, and
   figures are set in a monospace with tabular digits. Where apothecary is warm and curved, this is
   the opposite reading of the same sector — the clinic rather than the apothecary — so no two
   clients wearing them could be mistaken for each other.
   The shared-border grid is the part that reads as designed. Cards butt together and their 1px
   edges collapse into one continuous rule, which is what makes it look like a drawn grid rather
   than a row of boxes with a border each. */
:where(.sl-body).theme-clinic {
  --cl-rule: color-mix(in srgb, var(--c-text) 20%, transparent);
  --cl-mono: ui-monospace, 'SFMono-Regular', 'Roboto Mono', Menlo, monospace;
  background: color-mix(in srgb, var(--c-surface) 97%, var(--c-text));
}
/* NOTHING IS ROUND. One declaration, and it is the loudest thing in the theme. */
:where(.sl-body).theme-clinic .card, :where(.sl-body).theme-clinic .whyus-card, :where(.sl-body).theme-clinic .cat-card, :where(.sl-body).theme-clinic .addon-card, :where(.sl-body).theme-clinic .wpkg-card, :where(.sl-body).theme-clinic .tier-card, :where(.sl-body).theme-clinic .faq-item, :where(.sl-body).theme-clinic .team-member-card, :where(.sl-body).theme-clinic .btn, :where(.sl-body).theme-clinic .itr-media img, :where(.sl-body).theme-clinic .step-badge, :where(.sl-body).theme-clinic .eyebrow, :where(.sl-body).theme-clinic .pkg-bag, :where(.sl-body).theme-clinic .tm-photo, :where(.sl-body).theme-clinic .cat-ic, :where(.sl-body).theme-clinic .trust-row-item .trust-ic {
  border-radius: 0;
}
/* THE SHARED-BORDER GRID. A -1px margin pulls each card onto its neighbour so the two 1px edges
   become one line. `background-clip: padding-box` keeps a card's fill off that shared rule. */
:where(.sl-body).theme-clinic .cards-center, :where(.sl-body).theme-clinic .whyus-grid, :where(.sl-body).theme-clinic .cat-grid, :where(.sl-body).theme-clinic .addon-grid, :where(.sl-body).theme-clinic .wpkg-grid {
  gap: 0;
}
:where(.sl-body).theme-clinic .card, :where(.sl-body).theme-clinic .whyus-card, :where(.sl-body).theme-clinic .cat-card, :where(.sl-body).theme-clinic .addon-card, :where(.sl-body).theme-clinic .wpkg-card, :where(.sl-body).theme-clinic .team-member-card {
  margin: -0.5px;
  border: 1px solid var(--cl-rule);
  box-shadow: none;
  background: var(--c-surface);
  background-clip: padding-box;
}
:where(.sl-body).theme-clinic .card:hover, :where(.sl-body).theme-clinic .cat-card:hover, :where(.sl-body).theme-clinic .addon-card:hover {
  transform: none; box-shadow: none;
  background: color-mix(in srgb, var(--c-accent) 6%, var(--c-surface));
}
/* NO BAND INDEX HERE EITHER. Numbering sections was removed house-wide 2026-09-07 (see the note
   in the clinical-ledger lane). This theme numbered every interior section '01 / ' in the margin;
   the section header keeps its own type and rule without it. */

/* --c-accent-ink is the accent darkened for a LIGHT ground; on a dark band it is close to
   invisible, which is where the index was landing on the photo bands. */
:where(.sl-body).theme-clinic main > section.section.sec-room > .container > .section-header::before, :where(.sl-body).theme-clinic main > section.section.sec-photo > .container > .section-header::before {
  color: var(--c-accent-ink-dark, var(--c-accent));
}
/* Bands are separated by a full-bleed hairline instead of a colour change — the grid continues
   through the whole page rather than stopping at each section. */
:where(.sl-body).theme-clinic main > section.section { border-top: 1px solid var(--cl-rule); }
/* TYPE. Tight sans headings, monospace for every label and every figure. Tabular digits
   everywhere, because a price list that jitters between rows is the thing this theme is against. */
:where(.sl-body).theme-clinic h1, :where(.sl-body).theme-clinic h2 {
  letter-spacing: -0.03em; line-height: 1.04; font-weight: 700;
}
:where(.sl-body).theme-clinic .eyebrow, :where(.sl-body).theme-clinic .stat-label, :where(.sl-body).theme-clinic .tm-title, :where(.sl-body).theme-clinic .addon-pill, :where(.sl-body).theme-clinic .pkg-price-tier {
  font-family: var(--cl-mono);
  font-size: 0.66rem; font-weight: 500; letter-spacing: 0.14em; text-transform: uppercase;
  background: none; border: 0; padding: 0;
}
:where(.sl-body).theme-clinic .stat-value, :where(.sl-body).theme-clinic .tier-amount, :where(.sl-body).theme-clinic .addon-pill, :where(.sl-body).theme-clinic .pkg-price-amt, :where(.sl-body).theme-clinic .wpkg-price, :where(.sl-body).theme-clinic .tiercmp-price {
  font-family: var(--cl-mono);
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}
/* Buttons are square, hairline, monospace. The primary keeps its fill; the conversion path is not
   the place to be clever. */
:where(.sl-body).theme-clinic .btn {
  font-family: var(--cl-mono);
  font-size: 0.7rem; font-weight: 500; letter-spacing: 0.14em; text-transform: uppercase;
  padding: 1rem 1.8rem; box-shadow: none;
}
:where(.sl-body).theme-clinic .btn-secondary { background: transparent; border: 1px solid var(--cl-rule); }
/* The step disc becomes a square index cell, consistent with the band numbering.
   AN EXPLICIT PAIR, NOT TWO VARIABLES THAT CAN COLLAPSE. The first version used
   `background: var(--c-text); color: var(--c-surface)`, which is fine on page stock and white-on-
   white inside a dark band: a room rebinds --c-text to --c-surface, so both sides of the pair
   became the same white and the badges rendered as blank squares. That is rule 2 of this file,
   broken in the theme layer by the person who wrote rule 2 down. --c-primary-dark and --c-surface
   are fixed tokens that never swap places, and the room case is stated separately below. */
:where(.sl-body).theme-clinic .step-badge {
  background: var(--c-primary-dark); color: var(--c-on-dark);
  font-family: var(--cl-mono); font-size: 0.95rem; font-weight: 500;
  border-radius: 0;
}
:where(.sl-body) main > section.section.sec-room body.theme-clinic .step-badge, :where(.sl-body).theme-clinic main > section.section.sec-room .step-badge, :where(.sl-body).theme-clinic main > section.section.sec-photo .step-badge {
  background: var(--c-light-stock); color: var(--c-primary-dark);
}
:where(.sl-body).theme-clinic .steps-connected::before { display: none; }

/* ── theme-botanical ─────────────────────────────────────────────────────────────────────────
   THE DEVICE IS THE ORGANIC MASK AND A REAL DUOTONE. Every photograph is cut to an asymmetric
   soft shape and printed in two brand inks rather than in full colour — the single strongest way
   to make stock photography look art-directed, and the thing this platform has never done to a
   body image (only the hero has a duotone effect). Around it: nothing straight, generous leading,
   and lowercase labels.
   The duotone is a real one: the image goes greyscale and a brand gradient is composited over it
   in `color` blend mode, so highlights and shadows keep their structure and only the hue is
   replaced. A flat overlay would just tint it. */
:where(.sl-body).theme-botanical {
  --bo-blob: 62% 38% 54% 46% / 46% 54% 38% 62%;
  --bo-blob-alt: 38% 62% 46% 54% / 54% 46% 62% 38%;
  background:
    radial-gradient(60% 50% at 12% 8%, color-mix(in srgb, var(--c-accent) 16%, transparent), transparent 70%),
    radial-gradient(55% 45% at 92% 62%, color-mix(in srgb, var(--c-primary) 13%, transparent), transparent 72%),
    var(--c-surface-alt);
  background-attachment: fixed;
}
/* THE MASK. Alternating shapes so a page of photographs never repeats one silhouette. */
:where(.sl-body).theme-botanical .itr-media, :where(.sl-body).theme-botanical .personas-media, :where(.sl-body).theme-botanical .coverage-index-photo, :where(.sl-body).theme-botanical .istack-a, :where(.sl-body).theme-botanical .istack-b {
  position: relative;
  isolation: isolate;
  border-radius: var(--bo-blob);
  overflow: hidden;
}
:where(.sl-body).theme-botanical .img-text.reverse .itr-media { border-radius: var(--bo-blob-alt); }
/* THE DUOTONE IS OPT-IN, THE MASKS ARE NOT. Botanical carries two devices: the organic blob
   masks above (shape only, harmless to any photograph) and the duotone below (it desaturates the
   image and repaints its hue). The second one silently destroys the thing a client most often
   sends deliberately — her own photography, colour-graded, sometimes shot for the brand. Ian
   raised exactly this on 2026-08-04: a theme must not overrule what the brief specified. Fonts
   got the same treatment via --font-heading-authored.
   `--bo-duotone` is emitted by brand.ts ONLY when a brand sets theme_json.photo_duotone = true,
   so it defaults to 0 and every value below degrades to a no-op: grayscale(0), contrast(1),
   brightness(1), and a fully transparent wash. Botanical still reads as botanical — blob-masked
   photography is the unusual, recognisable half — but a client's colour survives unless someone
   deliberately asks for the duotone. */
:where(.sl-body).theme-botanical .itr-media img, :where(.sl-body).theme-botanical .personas-media img, :where(.sl-body).theme-botanical .coverage-index-photo img, :where(.sl-body).theme-botanical .istack-a img, :where(.sl-body).theme-botanical .istack-b img {
  border-radius: inherit;
  filter: grayscale(var(--bo-duotone, 0))
          contrast(calc(1 + (0.06 * var(--bo-duotone, 0))))
          brightness(calc(1 + (0.02 * var(--bo-duotone, 0))));
}
/* THE DUOTONE. `color` blend takes the hue and saturation of the gradient and keeps the luminance
   of the photograph underneath, which is what a duotone IS. pointer-events off so it never eats a
   click on a linked image. Opacity gates the whole effect off by default (see above). */
:where(.sl-body).theme-botanical .itr-media::after, :where(.sl-body).theme-botanical .personas-media::after, :where(.sl-body).theme-botanical .coverage-index-photo::after {
  content: '';
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  mix-blend-mode: color;
  opacity: var(--bo-duotone, 0);
  background: linear-gradient(150deg, var(--c-primary), var(--c-accent));
}
/* Round portraits and tiles too, so the language is not only on the big photographs. */
:where(.sl-body).theme-botanical .tm-photo, :where(.sl-body).theme-botanical .cat-ic, :where(.sl-body).theme-botanical .wpkg-ic, :where(.sl-body).theme-botanical .prepaft-ic, :where(.sl-body).theme-botanical .trust-row-item .trust-ic {
  border-radius: var(--bo-blob);
}
/* CARDS ARE SOFT AND BORDERLESS, sitting on the mesh rather than boxed against it. */
:where(.sl-body).theme-botanical .card, :where(.sl-body).theme-botanical .whyus-card, :where(.sl-body).theme-botanical .cat-card, :where(.sl-body).theme-botanical .addon-card, :where(.sl-body).theme-botanical .wpkg-card, :where(.sl-body).theme-botanical .tier-card, :where(.sl-body).theme-botanical .faq-item, :where(.sl-body).theme-botanical .team-member-card {
  border: 0;
  border-radius: clamp(18px, 2.4vw, 30px);
  background: color-mix(in srgb, var(--c-surface) 82%, transparent);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  box-shadow: 0 20px 50px -34px color-mix(in srgb, var(--c-primary) 45%, transparent);
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  :where(.sl-body).theme-botanical .card, :where(.sl-body).theme-botanical .whyus-card, :where(.sl-body).theme-botanical .cat-card, :where(.sl-body).theme-botanical .faq-item { background: color-mix(in srgb, var(--c-surface) 95%, transparent); }
}
/* TYPE. Generous leading, lowercase tracked labels — the opposite of clinic's uppercase monospace
   and of apothecary's small caps, so the three are distinguishable on type alone. */
:where(.sl-body).theme-botanical h1, :where(.sl-body).theme-botanical h2 { line-height: 1.12; letter-spacing: -0.02em; }
:where(.sl-body).theme-botanical p { line-height: 1.8; }
:where(.sl-body).theme-botanical .eyebrow, :where(.sl-body).theme-botanical .tm-title, :where(.sl-body).theme-botanical .stat-label {
  text-transform: lowercase; letter-spacing: 0.04em; font-weight: 600; font-size: 0.9rem;
  background: none; padding: 0;
}
/* Fully round buttons and step markers, to finish the argument that nothing here has a corner. */
:where(.sl-body).theme-botanical .btn { border-radius: 999px; box-shadow: none; padding: 0.95rem 2rem; }
:where(.sl-body).theme-botanical .step-badge { border-radius: var(--bo-blob); }
:where(.sl-body).theme-botanical .steps-connected::before { display: none; }

/* ── THE HEADER IS A FIXED BUDGET, AND A THEME MUST NOT SPEND IT ─────────────────────────────────
   Every theme restyles `.btn`, and all three of them broke the header doing it. Uppercase plus
   0.18em tracking plus 1.9rem of horizontal padding took the Call link from 54px to 105px and the
   Book button from 145 to 165 — 36px more than `.site-header .container` has at 1280px AND at
   1440px. Nothing overflowed visibly. Instead the flex row paid for it out of the only items that
   could shrink: the phone glyph and the dropdown chevron, both `<svg>` carrying `max-width: 100%`
   from the reset, went to ZERO width. Two icons silently deleted from every page of the site, on
   all three themes, and the gallery panel looked plausible enough that it took a pixel-level crop
   to notice.
   RULE 3, ONE LAYER UP: a theme changes how things look; the header's row maths is not its
   business. So the header keeps base metrics and only borrows the theme's voice — and the icons are
   pulled out of the shrink pool for good, because an element that vanishes rather than clips gives
   no visual warning that anything is wrong.
   The un-themed header does the same thing at 1024px on its own, which is how a crushed icon can be
   a platform bug and a theme bug at once. This fixes only the themed side of it. */
:where(.sl-body).theme-apothecary .site-header .btn, :where(.sl-body).theme-clinic .site-header .btn, :where(.sl-body).theme-botanical .site-header .btn {
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  padding: 0.7rem 1.1rem;
}
/* `.header-call` is a `.btn-text`: base gives it zero horizontal padding, and the themes were
   handing it 30px a side — over half the deficit came from this one element. */
:where(.sl-body).theme-apothecary .site-header .btn-text, :where(.sl-body).theme-clinic .site-header .btn-text, :where(.sl-body).theme-botanical .site-header .btn-text { padding-left: 0; padding-right: 0; }
/* Icons never shrink. `flex: none` is the whole fix for the disappearing act. */
:where(.sl-body).theme-apothecary .site-header svg, :where(.sl-body).theme-clinic .site-header svg, :where(.sl-body).theme-botanical .site-header svg { flex: none; }

/* ══ CATALOGUE FILL — shapes that had one design, which is the same as having none ═══════════════
   A shape with a single treatment gives the assigner nothing to choose between, so the section
   looks the same on every page that renders it. These four cover the two highest-volume shapes in
   that state: `.psa-block` (98 instances across the roster, one design) and `.cmp-table` (8, one
   design, and that one lost to the untreated table on review).
   Both follow the axis the catalogue recommends — one design has BOXES, one has PLATES, one has
   NONE — because three treatments that all fill something read as three versions of one idea. */

/* ── comp-psa-rule — the statement between two rules ──────────────────────────────────────────
   `.psa-block` is an eyebrow and an h2, centred, and the existing plate sets that h2 at 3.4rem on
   the assumption it is a figure like "$150". It is not always: on a med spa the same key carries a
   forty-word sentence about consultations, which at display scale fills the viewport. This one
   scales modestly and balances the wrap, so it holds both a number and a paragraph.
   `.psa-block` carries INLINE `text-align:center` from the renderer, and the eyebrow carries inline
   colour, weight, tracking, transform and size — inline beats every selector, so exactly those
   properties need !important here and nothing else does. */
:where(.sl-body) main > section.section.comp-psa-rule .psa-block {
  text-align: left !important;
  max-width: min(760px, 100%);
  margin-inline: auto;
  padding: clamp(1.4rem, 3vw, 2rem) 0;
  border-top: 2px solid var(--c-text);
  border-bottom: 1px solid color-mix(in srgb, var(--c-text) 18%, transparent);
}
:where(.sl-body) main > section.section.comp-psa-rule .psa-block .eyebrow {
  display: block;
  margin-bottom: 0.7rem;
  font-size: 0.72rem !important;
  letter-spacing: 0.18em !important;
  color: var(--c-text-muted) !important;
}
:where(.sl-body) main > section.section.comp-psa-rule .psa-block h2 {
  margin: 0;
  font-size: clamp(1.35rem, 2.6vw, 2rem);
  line-height: 1.28;
  font-weight: 500;
  text-wrap: balance;
}

/* ── comp-psa-side — the label hung beside the statement ──────────────────────────────────────
   The complaint this answers is that a centred eyebrow over a centred heading is the silhouette of
   every other band on the page. Moving the label into its own column breaks that at a glance
   without touching type scale at all. Collapses to one column on a phone, where two columns of
   this would leave the statement about eleven characters wide. */
:where(.sl-body) main > section.section.comp-psa-side .psa-block {
  text-align: left !important;
  display: grid;
  grid-template-columns: minmax(110px, 18%) minmax(0, 1fr);
  gap: clamp(1rem, 3vw, 2.4rem);
  align-items: start;
  max-width: min(900px, 100%);
  margin-inline: auto;
}
:where(.sl-body) main > section.section.comp-psa-side .psa-block .eyebrow {
  padding-top: 0.55rem;
  border-top: 2px solid var(--c-accent);
  font-size: 0.7rem !important;
  letter-spacing: 0.16em !important;
  color: var(--c-text-muted) !important;
}
:where(.sl-body) main > section.section.comp-psa-side .psa-block h2 {
  margin: 0;
  font-size: clamp(1.3rem, 2.4vw, 1.9rem);
  line-height: 1.32;
  font-weight: 500;
}
/* The block has THREE children and this grid has two columns, so the price range wrapped back to
   column 1 and sat under the eyebrow at eleven characters wide. Pin it beneath the heading. */
:where(.sl-body) main > section.section.comp-psa-side .psa-block p {
  grid-column: 2;
  margin: 0.5rem 0 0;
  color: var(--c-text-muted);
}
@media (max-width: 640px) {
  :where(.sl-body) main > section.section.comp-psa-side .psa-block { grid-template-columns: minmax(0, 1fr); gap: 0.8rem; }
}

/* ── comp-cmp-quiet — the matrix with nothing filled in ───────────────────────────────────────
   The DEFAULT comparison table already fills the winning header with the accent and tints its
   column, so a treatment that fills something differently is the same idea in another colour —
   which is exactly why `matrix-plate` did not earn its place. This is the other end of the axis:
   no fills at all. Small-caps heads, hairlines, and the winner carried by an accent rule under its
   heading plus weight on its own cells. */
:where(.sl-body) main > section.section.comp-cmp-quiet .cmp-table thead th {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--c-text-muted);
  padding-bottom: 0.7rem;
}
:where(.sl-body) main > section.section.comp-cmp-quiet .cmp-table thead th.cmp-hl {
  background: none;
  border-radius: 0;
  color: var(--c-text);
  border-bottom: 2px solid var(--c-accent);
}
:where(.sl-body) main > section.section.comp-cmp-quiet .cmp-table td.cmp-hl { background: none; }
:where(.sl-body) main > section.section.comp-cmp-quiet .cmp-table th, :where(.sl-body) main > section.section.comp-cmp-quiet .cmp-table td {
  border-bottom: 1px solid color-mix(in srgb, var(--c-text) 10%, transparent);
}
:where(.sl-body) main > section.section.comp-cmp-quiet .cmp-table .cmp-rowlabel { font-weight: 500; }
/* THE WINNING TICKS KEEP THE ACCENT THE DEFAULT GIVES THEM. The first cut recoloured them to
   --c-accent-ink to match the quieter palette, and on screen the winning column became
   indistinguishable from the losing ones — a comparison table that no longer answers the only
   question it is asked. Quiet is about the fills and the type, not about the answer. */
:where(.sl-body) main > section.section.comp-cmp-quiet .cmp-table td:not(.cmp-hl) .cmp-yes, :where(.sl-body) main > section.section.comp-cmp-quiet .cmp-table .cmp-no { color: color-mix(in srgb, var(--c-text) 38%, transparent); }

/* ── comp-cmp-rows — read across, not down ────────────────────────────────────────────────────
   A comparison table is read one ROW at a time — "does this option do the thing I care about" —
   but a grid of equal cells invites reading down the columns. Banding the rows and hanging the
   label off the left makes the row the unit. Fills the band, not the column, so it sits opposite
   both the default and cmp-quiet on the boxes/plates/none axis. */
:where(.sl-body) main > section.section.comp-cmp-rows .cmp-table { border-collapse: separate; border-spacing: 0; }
:where(.sl-body) main > section.section.comp-cmp-rows .cmp-table th, :where(.sl-body) main > section.section.comp-cmp-rows .cmp-table td { border-bottom: 0; }
:where(.sl-body) main > section.section.comp-cmp-rows .cmp-table tbody tr:nth-child(odd) th, :where(.sl-body) main > section.section.comp-cmp-rows .cmp-table tbody tr:nth-child(odd) td {
  background: color-mix(in srgb, var(--c-text) 4%, transparent);
}
/* The BAND is the only fill. The base tints the winning column, and left on it that tint sat over
   the banding as a chequerboard — two fills arguing about which axis matters. The orange header cap
   still says which column wins, and the row is now unambiguously the unit. */
:where(.sl-body) main > section.section.comp-cmp-rows .cmp-table td.cmp-hl { background: transparent; }
:where(.sl-body) main > section.section.comp-cmp-rows .cmp-table tbody tr:nth-child(odd) td.cmp-hl {
  background: color-mix(in srgb, var(--c-text) 4%, transparent);
}
:where(.sl-body) main > section.section.comp-cmp-rows .cmp-table tbody tr th:first-child { border-radius: 8px 0 0 8px; }
:where(.sl-body) main > section.section.comp-cmp-rows .cmp-table tbody tr td:last-child { border-radius: 0 8px 8px 0; }
:where(.sl-body) main > section.section.comp-cmp-rows .cmp-table .cmp-rowlabel {
  font-weight: 600;
  padding-left: clamp(0.75rem, 1.6vw, 1.1rem);
}
:where(.sl-body) main > section.section.comp-cmp-rows .cmp-table thead th {
  font-size: 0.74rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding-bottom: 0.55rem;
}
/* The header keeps its accent cap, but squared off so it reads as a label for the column rather
   than as the lid of a plate — the banding is doing the emphasis now. */
:where(.sl-body) main > section.section.comp-cmp-rows .cmp-table thead th.cmp-hl {
  border-radius: 6px 6px 0 0;
  padding-inline: clamp(0.6rem, 1.4vw, 1rem);
}

/* ══ CATALOGUE FILL, ROUND 2 — the last nine shapes stuck on a single design ═════════════════════
   One design per shape means the assigner has no choice and the section renders identically
   wherever it appears. Two more for each, on the boxes/plates/none axis.
   Where a design wants ONE PER ROW it sets the CARD's flex-basis to 100%, never the container's
   columns or gutter: `--sl-basis` is written inline on the container by cardBasis(), and a
   treatment that edits the row maths is rule 3. Changing the card is the card's business. */

/* ── .coverage-chips ─────────────────────────────────────────────────────────────────────────── */
/* areas-rows — the pills become a set ruled list. A service area list is reference material. */
:where(.sl-body) main > section.section.comp-areas-rows .coverage-chips {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(min(190px, 100%), minmax(0, 1fr))); gap: 0;
}
:where(.sl-body) main > section.section.comp-areas-rows .coverage-chip {
  background: none; border: 0; border-radius: 0; padding: 0.62rem 0.2rem;
  /* INHERIT the ink, never name it. This band is always dark and `.coverage-chip` is `color:#fff`
     for that reason; naming --c-text here painted dark-on-dark and the town names disappeared
     completely. The rule follows currentColor for the same reason. */
  border-bottom: 1px solid color-mix(in srgb, currentColor 22%, transparent);
  font-size: 0.95rem; color: inherit;
}
/* areas-solid — the opposite end: filled chips, bigger, unmistakably a list of places. */
:where(.sl-body) main > section.section.comp-areas-solid .coverage-chip {
  background: color-mix(in srgb, var(--c-primary) 10%, var(--c-surface));
  border: 1px solid color-mix(in srgb, var(--c-primary) 22%, transparent);
  color: var(--c-primary-dark);
  padding: 0.5rem 0.95rem; border-radius: 999px; font-weight: 600;
}

/* ── .vtl (visit timeline) ───────────────────────────────────────────────────────────────────── */
/* vtl-ledger — no dots and no rail. The time becomes a set column and the rows are ruled. */
:where(.sl-body) main > section.section.comp-vtl-ledger .vtl-item {
  display: grid; grid-template-columns: minmax(104px, 15%) minmax(0, 1fr); gap: clamp(0.9rem, 2.4vw, 2rem);
  padding: 0.95rem 0; border-bottom: 1px solid color-mix(in srgb, var(--c-text) 12%, transparent);
}
:where(.sl-body) main > section.section.comp-vtl-ledger .vtl-dot { display: none; }
:where(.sl-body) main > section.section.comp-vtl-ledger .vtl-time {
  font-variant-numeric: tabular-nums; font-weight: 700; color: var(--c-accent-ink);
  font-size: 0.95rem;
}
:where(.sl-body) main > section.section.comp-vtl-ledger .vtl-copy h3 { margin: 0 0 0.25rem; font-size: 1.05rem; }
/* vtl-cards — each step on its own card, the time as a badge. Boxes, where the rail has none. */
:where(.sl-body) main > section.section.comp-vtl-cards .vtl-item {
  background: var(--c-surface); border: 1px solid var(--c-border, rgba(0,0,0,0.1));
  border-radius: 14px; padding: clamp(1rem, 2.2vw, 1.4rem); margin-bottom: 0.85rem;
  box-shadow: 0 10px 26px -22px rgba(8,37,44,0.5);
}
:where(.sl-body) main > section.section.comp-vtl-cards .vtl-dot { display: none; }
:where(.sl-body) main > section.section.comp-vtl-cards .vtl-time {
  display: inline-block; background: color-mix(in srgb, var(--c-accent) 16%, var(--c-surface));
  color: var(--c-accent-ink); border-radius: 999px; padding: 0.18rem 0.7rem;
  font-size: 0.78rem; font-weight: 700; margin-bottom: 0.5rem;
}

/* ── .stats-band ─────────────────────────────────────────────────────────────────────────────── */
/* stats-rule — figures only, separated by hairlines. The medallion has a disc; this has nothing. */
:where(.sl-body) main > section.section.comp-stats-rule .stat-ic { display: none; }
:where(.sl-body) main > section.section.comp-stats-rule .stat {
  border-left: 1px solid color-mix(in srgb, var(--c-text) 14%, transparent);
  padding: 0.2rem 0 0.2rem clamp(0.9rem, 2vw, 1.6rem);
}
:where(.sl-body) main > section.section.comp-stats-rule .stat:first-child { border-left: 0; padding-left: 0; }
:where(.sl-body) main > section.section.comp-stats-rule .stat-value {
  font-size: clamp(2rem, 4vw, 3rem); line-height: 1; font-variant-numeric: tabular-nums;
}
:where(.sl-body) main > section.section.comp-stats-rule .stat-label {
  font-size: 0.74rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--c-text-muted);
}
/* stats-tiles — each figure boxed, icon hung top-left rather than centred over it. */
:where(.sl-body) main > section.section.comp-stats-tiles .stat {
  background: var(--c-surface); border: 1px solid var(--c-border, rgba(0,0,0,0.1));
  border-radius: 14px; padding: clamp(1rem, 2.2vw, 1.5rem); text-align: left;
}
:where(.sl-body) main > section.section.comp-stats-tiles .stat-ic {
  margin: 0 0 0.6rem; width: 34px; height: 34px;
  background: color-mix(in srgb, var(--c-accent) 14%, transparent); color: var(--c-accent-ink);
}
:where(.sl-body) main > section.section.comp-stats-tiles .stat-value { font-size: clamp(1.7rem, 3vw, 2.3rem); }

/* ── .pricing-tiers ──────────────────────────────────────────────────────────────────────────── */
/* tiers-rows — one tier per row, price set right. Comparing three prices down a column is easier
   than across three cards, and it is the opposite silhouette to the capped columns. */
:where(.sl-body) main > section.section.comp-tiers-rows .tier-card {
  flex: 0 1 100%;
  display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: start;
  gap: 0.4rem clamp(1rem, 3vw, 2.5rem);
  border-radius: 0; box-shadow: none; border: 0;
  border-bottom: 1px solid color-mix(in srgb, var(--c-text) 14%, transparent);
  padding: clamp(1rem, 2.4vw, 1.5rem) 0;
}
:where(.sl-body) main > section.section.comp-tiers-rows .tier-name { grid-column: 1; margin: 0; }
:where(.sl-body) main > section.section.comp-tiers-rows .tier-price { grid-column: 2; grid-row: 1 / span 2; text-align: right; }
:where(.sl-body) main > section.section.comp-tiers-rows .tier-desc { grid-column: 1; margin: 0; color: var(--c-text-muted); }
:where(.sl-body) main > section.section.comp-tiers-rows .tier-features { grid-column: 1 / -1; margin-top: 0.6rem; }
/* tiers-plate — the middle tier lifted onto a plate; the others sit flat beside it. */
:where(.sl-body) main > section.section.comp-tiers-plate .tier-card {
  border: 0; box-shadow: none; background: none; padding-inline: clamp(0.6rem, 1.6vw, 1.1rem);
}
:where(.sl-body) main > section.section.comp-tiers-plate .tier-card:nth-child(2) {
  background: var(--c-surface); border: 1px solid color-mix(in srgb, var(--c-primary) 24%, transparent);
  border-radius: 16px; box-shadow: 0 22px 48px -30px rgba(8,37,44,0.45);
  padding: clamp(1.1rem, 2.4vw, 1.7rem);
}
:where(.sl-body) main > section.section.comp-tiers-plate .tier-amount { font-variant-numeric: tabular-nums; }

/* ── .team-carousel ──────────────────────────────────────────────────────────────────────────── */
/* team-roster — a staff list, not a gallery. Small round photo, name and title on one line. */
/* The carousel does not wrap, so cards at basis 100% shrink to a quarter each rather than stack —
   which is what this produced first time: four cramped columns, not a roster. Wrapping the
   container is safe HERE specifically because `.team-carousel` is a scroll carousel that never
   carries `--sl-basis`; there is no balanced-row calculation for rule 3 to protect. */
:where(.sl-body) main > section.section.comp-team-roster .team-carousel {
  flex-wrap: wrap; overflow-x: visible; scroll-snap-type: none; gap: 0;
}
:where(.sl-body) main > section.section.comp-team-roster .team-member-card {
  flex: 0 0 100%;
  display: grid; grid-template-columns: 54px minmax(0, 1fr); align-items: center;
  gap: 0.25rem clamp(0.8rem, 2vw, 1.2rem);
  border: 0; border-radius: 0; box-shadow: none; background: none;
  padding: 0.85rem 0; border-bottom: 1px solid color-mix(in srgb, var(--c-text) 12%, transparent);
  text-align: left;
}
:where(.sl-body) main > section.section.comp-team-roster .tm-photo {
  grid-row: 1 / span 2; width: 54px; height: 54px; border-radius: 999px;
}
:where(.sl-body) main > section.section.comp-team-roster .tm-name { align-self: end; }
:where(.sl-body) main > section.section.comp-team-roster .tm-title { align-self: start; color: var(--c-text-muted); font-size: 0.85rem; }
:where(.sl-body) main > section.section.comp-team-roster .tm-bio { display: none; }
/* team-plaque — squared cards, name in small caps over a hairline. */
:where(.sl-body) main > section.section.comp-team-plaque .team-member-card {
  border-radius: 2px; box-shadow: none;
  border: 1px solid color-mix(in srgb, var(--c-text) 16%, transparent);
  padding: clamp(1rem, 2.2vw, 1.5rem);
}
:where(.sl-body) main > section.section.comp-team-plaque .tm-photo { border-radius: 2px; }
:where(.sl-body) main > section.section.comp-team-plaque .tm-name {
  display: block; font-size: 0.9rem; letter-spacing: 0.1em; text-transform: uppercase;
  padding-bottom: 0.45rem; border-bottom: 1px solid color-mix(in srgb, var(--c-text) 16%, transparent);
  margin-bottom: 0.45rem;
}

/* ── .wpkg-grid ──────────────────────────────────────────────────────────────────────────────── */
/* wpkg-index — numbered, no icons, hairline rows. A package list read as a contents page. */
:where(.sl-body) main > section.section.comp-wpkg-index .wpkg-grid { counter-reset: wpkg; }
:where(.sl-body) main > section.section.comp-wpkg-index .wpkg-card {
  counter-increment: wpkg; position: relative;
  border: 0; border-radius: 0; box-shadow: none; background: none;
  border-top: 1px solid color-mix(in srgb, var(--c-text) 14%, transparent);
  padding: clamp(1rem, 2.2vw, 1.4rem) 0 clamp(1rem, 2.2vw, 1.4rem) 3rem;
}
:where(.sl-body) main > section.section.comp-wpkg-index .wpkg-card::before {
  content: counter(wpkg, decimal-leading-zero);
  position: absolute; left: 0; top: clamp(1rem, 2.2vw, 1.4rem);
  font-variant-numeric: tabular-nums; font-weight: 700; font-size: 0.95rem;
  color: var(--c-accent-ink);
}
:where(.sl-body) main > section.section.comp-wpkg-index .wpkg-ic { display: none; }
/* wpkg-panel — the opposite: a filled panel per package, icon kept and enlarged. */
:where(.sl-body) main > section.section.comp-wpkg-panel .wpkg-card {
  background: color-mix(in srgb, var(--c-primary) 6%, var(--c-surface));
  border: 1px solid color-mix(in srgb, var(--c-primary) 16%, transparent);
  border-radius: 16px; box-shadow: none;
}
:where(.sl-body) main > section.section.comp-wpkg-panel .wpkg-ic {
  width: 46px; height: 46px; background: var(--c-surface); border-radius: 12px;
  color: var(--c-primary-dark);
}
:where(.sl-body) main > section.section.comp-wpkg-panel .wpkg-name { color: var(--c-primary-dark); }

/* ── .auto-grid (event wellness) ─────────────────────────────────────────────────────────────── */
/* events-rows — one per row, icon inline with the heading. */
:where(.sl-body) main > section.section.comp-events-rows .auto-card {
  flex: 0 1 100%;
  display: grid; grid-template-columns: auto minmax(0, 1fr); align-items: start;
  gap: 0.3rem clamp(0.8rem, 2vw, 1.2rem);
  border: 0; border-radius: 0; box-shadow: none; background: none;
  padding: 0.95rem 0; border-bottom: 1px solid color-mix(in srgb, var(--c-text) 12%, transparent);
  text-align: left;
}
:where(.sl-body) main > section.section.comp-events-rows .feature-ic { grid-row: 1 / span 2; margin: 0; }
:where(.sl-body) main > section.section.comp-events-rows .auto-card h3 { margin: 0; }
/* events-ghost — the icon becomes a large ghosted mark behind the copy. */
:where(.sl-body) main > section.section.comp-events-ghost .auto-card {
  position: relative; overflow: hidden;
  background: var(--c-surface-alt); border: 0; border-radius: 16px;
  padding: clamp(1.2rem, 2.6vw, 1.8rem);
}
:where(.sl-body) main > section.section.comp-events-ghost .feature-ic {
  position: absolute; right: -0.4rem; top: -0.4rem; margin: 0;
  width: 92px; height: 92px; background: none;
  color: color-mix(in srgb, var(--c-primary) 12%, transparent);
}
:where(.sl-body) main > section.section.comp-events-ghost .auto-card h3, :where(.sl-body) main > section.section.comp-events-ghost .auto-card p { position: relative; z-index: 1; }

/* ── .addon-grid ─────────────────────────────────────────────────────────────────────────────── */
/* addons-cards — a proper card with the price as a badge, where menu-list is a leader-dot list. */
:where(.sl-body) main > section.section.comp-addons-cards .addon-card {
  background: var(--c-surface); border: 1px solid var(--c-border, rgba(0,0,0,0.1));
  border-radius: 14px; padding: clamp(0.95rem, 2vw, 1.35rem);
  box-shadow: 0 10px 26px -22px rgba(8,37,44,0.5);
}
:where(.sl-body) main > section.section.comp-addons-cards .addon-head { align-items: flex-start; gap: 0.6rem; }
:where(.sl-body) main > section.section.comp-addons-cards .addon-pill {
  background: var(--c-primary); color: var(--c-on-primary);
  border-radius: 999px; padding: 0.2rem 0.62rem; font-weight: 700; font-size: 0.8rem;
  font-variant-numeric: tabular-nums;
}
/* addons-index — numbered hairline rows, price set hard right. */
:where(.sl-body) main > section.section.comp-addons-index .addon-grid { counter-reset: adx; }
:where(.sl-body) main > section.section.comp-addons-index .addon-card {
  counter-increment: adx;
  background: none; border: 0; border-radius: 0; box-shadow: none;
  border-bottom: 1px solid color-mix(in srgb, var(--c-text) 12%, transparent);
  padding: 0.8rem 0 0.8rem 2.4rem; position: relative;
}
:where(.sl-body) main > section.section.comp-addons-index .addon-card::before {
  content: counter(adx, decimal-leading-zero);
  position: absolute; left: 0; top: 0.95rem;
  font-size: 0.78rem; font-weight: 700; color: var(--c-text-muted);
  font-variant-numeric: tabular-nums;
}
:where(.sl-body) main > section.section.comp-addons-index .addon-pill {
  background: none; padding: 0; font-weight: 700; color: var(--c-accent-ink);
  font-variant-numeric: tabular-nums;
}

/* ── .prose-block ────────────────────────────────────────────────────────────────────────────── */
/* prose-columns — two columns, which is what a long unbroken run of paragraphs wants. */
:where(.sl-body) main > section.section.comp-prose-columns .prose-block {
  columns: 2; column-gap: clamp(1.5rem, 4vw, 3rem);
  max-width: min(1000px, 100%); margin-inline: auto;
}
:where(.sl-body) main > section.section.comp-prose-columns .prose-block p { break-inside: avoid; margin-top: 0; }
@media (max-width: 760px) {
  :where(.sl-body) main > section.section.comp-prose-columns .prose-block { columns: 1; }
}
/* prose-margin — the first paragraph hung as a lead, with a rule down the side. */
:where(.sl-body) main > section.section.comp-prose-margin .prose-block {
  border-left: 2px solid var(--c-accent);
  padding-left: clamp(1rem, 3vw, 2.2rem);
  max-width: min(820px, 100%); margin-inline: auto;
}
:where(.sl-body) main > section.section.comp-prose-margin .prose-block p:first-child {
  font-size: clamp(1.05rem, 1.9vw, 1.3rem); line-height: 1.5; color: var(--c-text);
}



/* ══ MED SPA SHAPES ══════════════════════════════════════════════════════════════════════════════
   Base styling for the five sections that had no renderer until now. Each is a DEFAULT design in
   the catalogue sense: the shape as it looks with no comp-* class on it. */

/* ── .cdel-list — what the consultation actually gives you ─────────────────────────────────── */
:where(.sl-body) .cdel-list { list-style: none; margin: 1.4rem auto 0; padding: 0; display: grid; gap: 0.7rem; }
:where(.sl-body) .cdel-row {
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 0.7rem; align-items: start;
  padding-bottom: 0.7rem;
  border-bottom: 1px solid color-mix(in srgb, var(--c-text) 10%, transparent);
  line-height: 1.55;
}
:where(.sl-body) .cdel-row:last-child { border-bottom: 0; padding-bottom: 0; }
:where(.sl-body) .cdel-tick { color: var(--c-accent-ink, var(--c-accent)); margin-top: 0.22rem; flex: none; }
:where(.sl-body) .cdel-cta { margin-top: 1.6rem; text-align: center; }

/* ── .dtl-table — downtime, side by side ──────────────────────────────────────────────────────
   A table, because it is one: the same three questions asked of each treatment. `dtl-wrap` scrolls
   on a phone rather than letting four columns crush to unreadable widths. */
:where(.sl-body) .dtl-wrap { overflow-x: auto; margin: 1.5rem auto 0; max-width: var(--content-max); -webkit-overflow-scrolling: touch; }
:where(.sl-body) .dtl-table { width: 100%; border-collapse: collapse; min-width: 620px; text-align: left; }
:where(.sl-body) .dtl-table thead th {
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--c-text-muted); padding: 0 0.9rem 0.7rem; white-space: nowrap;
  border-bottom: 2px solid color-mix(in srgb, var(--c-text) 18%, transparent);
}
:where(.sl-body) .dtl-table td, :where(.sl-body) .dtl-table th.dtl-name {
  padding: 0.95rem 0.9rem; vertical-align: top; line-height: 1.5;
  border-bottom: 1px solid color-mix(in srgb, var(--c-text) 10%, transparent);
}
:where(.sl-body) .dtl-name { font-weight: 700; color: var(--c-text); white-space: normal; min-width: 140px; }
:where(.sl-body) .dtl-sense, :where(.sl-body) .dtl-back { color: var(--c-text-muted); font-size: 0.94rem; }
:where(.sl-body) .dtl-down { color: var(--c-text); font-size: 0.94rem; }

/* ── .dspec-bay — the platform, stated plainly ────────────────────────────────────────────── */
:where(.sl-body) .dspec-bay { display: flex; flex-wrap: wrap; justify-content: center; gap: 1.25rem; margin: 1.5rem auto 0; max-width: var(--content-max); }
:where(.sl-body) .dspec-card {
  flex: 0 1 var(--sl-basis, 420px);
  background: var(--c-surface); border: 1px solid var(--c-border, rgba(0,0,0,0.1));
  border-radius: var(--card-radius, 14px); padding: 1.4rem 1.5rem;
  box-shadow: var(--card-shadow, 0 1px 3px rgba(0,0,0,0.06));
  text-align: left;
}
:where(.sl-body) .dspec-name { margin: 0 0 0.9rem; font-size: 1.05rem; line-height: 1.35; }
:where(.sl-body) .dspec-specs { margin: 0; display: grid; gap: 0.6rem; }
:where(.sl-body) .dspec-row { display: grid; grid-template-columns: minmax(84px, 22%) minmax(0, 1fr); gap: 0.8rem; align-items: start; }
:where(.sl-body) .dspec-label {
  font-size: 0.68rem; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--c-text-muted); padding-top: 0.15rem;
}
:where(.sl-body) .dspec-value { margin: 0; font-size: 0.93rem; line-height: 1.5; color: var(--c-text); }
:where(.sl-body) .dspec-note {
  margin: 1rem 0 0; padding-top: 0.85rem; font-size: 0.86rem; line-height: 1.55;
  color: var(--c-text-muted);
  border-top: 1px solid color-mix(in srgb, var(--c-text) 10%, transparent);
}

/* ── .stsuit-list — who this suits, and who it does not ───────────────────────────────────────
   The `suitable: false` row is the reason this section exists, so it is the one row that must not
   look like the others: a different mark, in a different colour, on a tinted ground. A page of
   ticks with one cross styled identically is a contraindication nobody reads. */
:where(.sl-body) .stsuit-list { list-style: none; margin: 1.5rem auto 0; padding: 0; display: grid; gap: 0.55rem; }
:where(.sl-body) .stsuit-row {
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 0.8rem; align-items: start;
  padding: 0.85rem 1rem; border-radius: 12px;
  background: color-mix(in srgb, var(--c-text) 3%, transparent);
}
:where(.sl-body) .stsuit-mark { display: inline-flex; margin-top: 0.12rem; }
:where(.sl-body) .stsuit-yes .stsuit-mark { color: var(--c-accent-ink, var(--c-accent)); }
:where(.sl-body) .stsuit-no {
  background: color-mix(in srgb, #b4432f 8%, transparent);
  border: 1px solid color-mix(in srgb, #b4432f 22%, transparent);
}
:where(.sl-body) .stsuit-no .stsuit-mark { color: #a03a28; }
:where(.sl-body) .stsuit-copy { display: grid; gap: 0.2rem; }
:where(.sl-body) .stsuit-label { font-size: 0.98rem; line-height: 1.4; }
:where(.sl-body) .stsuit-note { font-size: 0.9rem; line-height: 1.55; color: var(--c-text-muted); }
:where(.sl-body) .stsuit-disclaimer {
  margin: 1.1rem auto 0; max-width: var(--content-max);
  font-size: 0.85rem; font-style: italic; color: var(--c-text-muted);
}

/* ── .tlad-rungs — one primary recommendation and an honest alternative ───────────────────── */
:where(.sl-body) .tlad-rungs { list-style: none; margin: 1.5rem auto 0; padding: 0; display: grid; gap: 1.1rem; counter-reset: none; }
:where(.sl-body) .tlad-rung {
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 0.4rem 1.1rem; align-items: start;
  padding-bottom: 1.1rem;
  border-bottom: 1px solid color-mix(in srgb, var(--c-text) 10%, transparent);
}
:where(.sl-body) .tlad-rung:last-child { border-bottom: 0; padding-bottom: 0; }
:where(.sl-body) .tlad-num {
  font-variant-numeric: tabular-nums; font-weight: 700; font-size: 0.9rem;
  color: var(--c-accent-ink, var(--c-accent)); padding-top: 0.28rem;
}
:where(.sl-body) .tlad-copy { display: grid; gap: 0.35rem; }
:where(.sl-body) .tlad-label { margin: 0; font-size: 1.08rem; line-height: 1.35; }
:where(.sl-body) .tlad-copy p { margin: 0; line-height: 1.6; }
:where(.sl-body) .tlad-commit {
  font-size: 0.88rem; color: var(--c-text-muted);
  padding-left: 0.8rem; border-left: 2px solid color-mix(in srgb, var(--c-accent) 45%, transparent);
}
@media (max-width: 640px) {
  :where(.sl-body) .tlad-rung { grid-template-columns: minmax(0, 1fr); }
  :where(.sl-body) .tlad-num { padding-top: 0; }
  :where(.sl-body) .dspec-row { grid-template-columns: minmax(0, 1fr); gap: 0.15rem; }
}

/* ── .bke-frame — a third-party scheduler, in the page ────────────────────────────────────────
   The height is a CUSTOM PROPERTY set inline per section, because the right number depends on the
   client's calendar: a shop with one appointment type needs far less than one with fifteen. Acuity's
   own embed script resizes the frame when it recognises the host; the declared height is what the
   page uses until then, and what it keeps if that script is blocked.
   Bespoke geometry owned by a third party — no comp-* treatment dresses it, and monotony-lint's M4
   treats any that lands here as an error. */
:where(.sl-body) .bke-frame {
  width: 100%;
  max-width: var(--content-max);
  margin: 1.5rem auto 0;
  border: 1px solid var(--c-border, rgba(0,0,0,0.1));
  border-radius: var(--card-radius, 14px);
  overflow: hidden;
  background: var(--c-surface);
  box-shadow: var(--card-shadow, 0 1px 3px rgba(0,0,0,0.06));
}
:where(.sl-body) .bke-frame iframe {
  display: block;
  width: 100%;
  height: var(--bke-h, 900px);
  border: 0;
}
/* Always visible, never a fallback in the CSS sense: tracking blockers and corporate networks kill
   third-party frames, and a booking section that fails closed is a lost customer. */
:where(.sl-body) .bke-fallback {
  max-width: var(--content-max);
  margin: 0.85rem auto 0;
  text-align: center;
  font-size: 0.9rem;
  color: var(--c-text-muted);
}
:where(.sl-body) .bke-fallback a { color: var(--c-accent-ink, var(--c-primary)); font-weight: 600; }
:where(.sl-body) .bke-note {
  max-width: var(--content-max);
  margin: 0.6rem auto 0;
  text-align: center;
  font-size: 0.86rem;
  color: var(--c-text-muted);
}
/* A phone is where most bookings happen, and 900px of calendar on a 640px-tall screen is a scroll
   trap inside a scroll. Give it the viewport and let the scheduler handle its own overflow. */
@media (max-width: 640px) {
  :where(.sl-body) .bke-frame iframe { height: min(var(--bke-h, 900px), 78vh); }
}

/* ══════════════════════════════════════════════════════════════════════════════════════════════
   REFINE-ESTATE — the flagship lane, built to the agency's own best work.
   Source of truth: docs/REFERENCE-TEARDOWN-2026-08-09.md (pureiv.com + resetiv.com, measured).
   The formula, in the references' own numbers: display type at 65–72px, body up to 24px/300,
   ONE ritual per band (eyebrow → huge centered headline → content → compact CTA pair), TRUE-dark
   bands with photographic depth, compact tracked-uppercase buttons, the product presented like
   perfume. Brand-token-agnostic: the SCALE and the RITUAL are the lane; the colors and faces are
   the brand's own. Appended at the END of this file deliberately — same-specificity ties resolve
   to the lane. ═══════════════════════════════════════════════════════════════════════════════ */

/* 1. TYPE SCALE COURAGE. The single measured gap: their H1 65–72px, ours ~40–52. */
/* ══ DESIGN LANE: estate ══════════════════════════════════════════════════════════════
   Retro-described 2026-08-27. This lane was written before lanes had descriptions and
   therefore could never be ASSIGNED to a client by anything but memory — which is exactly
   how one client was given a lane another client already wore. The tag below is what
   tools/lane-pick.mjs reads; the lane itself is unchanged.
   @lane estate | big serif display over deep photographic rooms | suits: estate heritage established grand classic serious stately
   ══════════════════════════════════════════════════════════════════════════════════════ */
:where(.sl-body).refine-estate h1 { font-size: clamp(3rem, 5.6vw, 4.5rem); line-height: 1.08; letter-spacing: -0.01em; }
:where(.sl-body).refine-estate main h2 { font-size: clamp(2.3rem, 4vw, 3.4rem); line-height: 1.14; font-weight: 500; }
:where(.sl-body).refine-estate .section-header p { font-size: clamp(1.1rem, 1.5vw, 1.3rem); font-weight: 300; line-height: 1.7; }
:where(.sl-body).refine-estate main p { font-weight: 300; }
:where(.sl-body).refine-estate main strong, :where(.sl-body).refine-estate main h3 { font-weight: 600; }

/* 2. THE RITUAL. Centered header, small-caps tracked eyebrow above EVERY headline, generous air.
   Reset repeats this on every single band; the repetition is what reads as intent. */
:where(.sl-body).refine-estate .section-header { text-align: center; margin-left: auto; margin-right: auto; margin-bottom: clamp(2rem, 4vw, 3rem); }
:where(.sl-body).refine-estate .section-header .eyebrow {
  display: block; background: none; padding: 0; margin-bottom: 0.9rem;
  font-size: 0.78rem; font-weight: 600; letter-spacing: 0.3em; text-transform: uppercase;
  color: var(--eyebrow-ink, var(--c-accent-ink, var(--c-accent)));
}
:where(.sl-body).refine-estate main > section.section { padding: clamp(3.25rem, 6.5vw, 5.5rem) 0; }

/* 3. CONFIDENCE IS SMALL BUTTONS. Compact, tracked, uppercase, near-square — the references'
   5×15px gold buttons against our fat pills. Secondary goes hairline-outlined. */
:where(.sl-body).refine-estate .btn {
  border-radius: 3px; padding: 0.78rem 1.7rem;
  font-size: 0.8rem; font-weight: 600; letter-spacing: 0.16em; text-transform: uppercase;
  box-shadow: none;
}
:where(.sl-body).refine-estate .btn-secondary {
  background: transparent;
  border: 1px solid color-mix(in srgb, var(--c-accent) 55%, transparent);
  color: var(--c-accent-ink, var(--c-accent));
}
:where(.sl-body).refine-estate .btn-secondary:hover { background: color-mix(in srgb, var(--c-accent) 12%, transparent); }

/* 4. TRUE DARKNESS WITH DEPTH. Reset's dark bands are photographed silk, not flat paint. Until a
   brand carries its own texture photograph, layered radial light does the depth: a cool key from
   the top corner, a whisper of the brand accent from the low corner, on a base pulled darker than
   primary-dark. Background only — the room's ink rebinds at :4240 still govern, deliberately. */
:where(.sl-body).refine-estate.bands-paper main > section.section.sec-room:nth-of-type(n) {
  background:
    radial-gradient(120% 90% at 12% -10%, color-mix(in srgb, var(--c-primary) 50%, transparent), transparent 55%),
    radial-gradient(90% 70% at 92% 108%, color-mix(in srgb, var(--c-accent) 16%, transparent), transparent 58%),
    linear-gradient(160deg, var(--c-primary-dark), color-mix(in srgb, var(--c-primary-dark) 80%, #000));
}

/* 5. STEP CARDS ON DARK GO HAIRLINE. Reset's "How It Works": transparent cards, thin gold edges,
   light ink — the inverse of white plates. The room rebind at :4283 assumes plates and inks these
   cards DARK; this later same-tie rule re-inks them for the transparent treatment it creates. */
:where(.sl-body).refine-estate.bands-paper main > section.section.sec-room:nth-of-type(n) .step-card, :where(.sl-body).refine-estate.bands-paper main > section.section.sec-room:nth-of-type(n) .card:not(.review-card) {
  background: color-mix(in srgb, #fff 4%, transparent);
  border: 1px solid color-mix(in srgb, var(--c-accent) 32%, transparent);
  border-radius: 4px;
  box-shadow: none;
  --c-text: var(--c-on-room);
  --c-text-muted: color-mix(in srgb, var(--c-on-room) 76%, transparent);
}

/* 6. THE PRODUCT IS PERFUME. White card, hairline edge, the name set in the display face with
   room to breathe, the price in the accent ink — the references' menu ritual. */
:where(.sl-body).refine-estate .pkg-card {
  background: var(--c-surface);
  border: 1px solid color-mix(in srgb, var(--c-text) 10%, transparent);
  border-radius: 4px;
  box-shadow: none;
}
:where(.sl-body).refine-estate .pkg-card h3 {
  font-family: var(--font-headline, inherit);
  font-size: 1.25rem; letter-spacing: 0.05em; font-weight: 500;
}
:where(.sl-body).refine-estate .pkg-price { color: var(--c-accent-ink, var(--c-accent)); font-weight: 600; letter-spacing: 0.06em; }

/* 7. QUESTIONS IN THE DISPLAY FACE. Reset sets its FAQ in the serif; the accordion reads as an
   index of chapters rather than a support widget. */
:where(.sl-body).refine-estate .faq-item > summary { font-family: var(--font-headline, inherit); font-weight: 500; }

/* 8. TRUST WHISPERS. Tiny tracked caps for the strip under the hero — signal, not shout. */
:where(.sl-body).refine-estate .trust-row-item, :where(.sl-body).refine-estate .trust-strip .label {
  font-size: 0.75rem; letter-spacing: 0.18em; text-transform: uppercase; font-weight: 600;
}

/* 9. MOBILE KEEPS THE RITUAL, LOSES NOTHING. Scale floors are set by the clamps above; the only
   extra care is the header air tightening so a phone is not 60% margin. */
@media (max-width: 640px) {
  :where(.sl-body).refine-estate .section-header { margin-bottom: 1.5rem; }
  :where(.sl-body).refine-estate main > section.section { padding: 2.6rem 0; }
}

/* ── ESTATE, THE ARCHITECTURE PASS. Ian's verdict on v1: "subtle." He was right — v1 changed the
   paint; the references' excellence is structural. Three architectural moves, measured off
   resetiv.com: the CINEMATIC HERO (full-height, centered, eyebrow ritual), TEXTURED darkness
   (a real photograph under the dark bands via --room-texture, the dark-marble mechanism), and
   the PRODUCT AT SCALE. Density is the fourth move and lives in DATA (section_visibility cut
   the canary home from 20 bands to 10 — fewer, bigger moments). ─────────────────────────────── */

/* THE CINEMATIC HERO. Reset's first impression: near-full-viewport dark photograph, everything
   centered, the headline enormous, the CTAs compact in a row beneath. */
:where(.sl-body).refine-estate .hero.hero-image-bg { display: grid; align-items: center; }
:where(.sl-body).refine-estate .hero.hero-image-bg .hero-inner {
  max-width: 62rem; margin-inline: auto; text-align: center;
  display: flex; flex-direction: column; align-items: center;
}
:where(.sl-body).refine-estate .hero.hero-image-bg h1 { font-size: clamp(3.2rem, 6.2vw, 5rem); line-height: 1.06; }
:where(.sl-body).refine-estate .hero.hero-image-bg .subhead { max-width: 46rem; font-size: clamp(1.05rem, 1.4vw, 1.25rem); font-weight: 300; line-height: 1.75; }
:where(.sl-body).refine-estate .hero.hero-image-bg .cta-row{ justify-content: center; }

/* TEXTURED DARKNESS. When the brand carries a texture photograph (surfaces.dark='marble' +
   dark_image → --room-texture, the mechanism Top Tier pioneered), the estate rooms lay it under
   a deep scrim: scrims first, the photograph beneath them, the flat base at the bottom. The
   78% scrim is the ink guarantee — R15 measures the result, as always. Brands without a texture
   keep the layered-gradient depth (the var falls back to a transparent layer). */
:where(.sl-body).refine-estate.bands-paper main > section.section.sec-room:nth-of-type(n) {
  background:
    radial-gradient(120% 90% at 12% -10%, color-mix(in srgb, var(--c-primary) 42%, transparent), transparent 55%),
    linear-gradient(160deg, color-mix(in srgb, var(--c-primary-dark) 78%, transparent), color-mix(in srgb, var(--c-primary-dark) 86%, #000)),
    var(--room-texture, linear-gradient(0deg, transparent, transparent)) center / cover no-repeat,
    linear-gradient(160deg, var(--c-primary-dark), color-mix(in srgb, var(--c-primary-dark) 80%, #000));
}

/* THE PRODUCT AT SCALE. Reset's bags are the size of perfume bottles on a counter; ours were
   thumbnails. The card gives the render room and the name the display face. */
:where(.sl-body).refine-estate .pkg-card { padding-top: 1.4rem; }
:where(.sl-body).refine-estate .pkg-card .pkg-bag { height: clamp(210px, 24vw, 300px); object-fit: contain; margin-inline: auto; }
:where(.sl-body).refine-estate .pkg-card h3 { font-size: 1.45rem; margin-top: 0.9rem; }

/* AIR AT THE REFERENCES' SCALE on the bands that remain. Ten sections can afford it; twenty
   could not — which is why density is a data decision, not a padding value. */
:where(.sl-body).refine-estate main > section.section { padding: clamp(3.75rem, 7.5vw, 6.5rem) 0; }
@media (max-width: 640px) {
  :where(.sl-body).refine-estate main > section.section { padding: 2.8rem 0; }
}

/* Estate polish, from the first full look: the trust whisper set its tracked caps in the brand
   ACCENT — Ember's gold at 0.72rem on cream reads as a wash. The whisper takes deep ink; gold
   stays on the icons where it has the size to carry. And step titles over the photo band take
   full surface ink — the scrim is dark, the title must not be the dimmest thing on it. */
:where(.sl-body).refine-estate .trust-row-item span, :where(.sl-body).refine-estate .trust-row-item .label {
  color: color-mix(in srgb, var(--c-primary-dark) 80%, var(--c-surface-alt));
}
:where(.sl-body).refine-estate main > section.section.sec-photo .step-card h3{
  color: var(--c-on-dark);
}

/* Estate secondary buttons on DARK closing bands take surface ink — the accent hairline that
   reads as luxury on cream is invisible on the band (bronze on warm dark measured 1.02:1 on
   every Solstice hub CTA, first cold-start build). The references do exactly this: white
   outline on the dark band, accent outline on the light page. */
/* This one is NOT deleted by the shared dark-ground guard the way luxe-noir's and clinical-
   porcelain's copies were, and the reason is worth writing down: it says something the guard does
   not, a hairline at 55% rather than a solid edge, and it reaches a ground the guard deliberately
   does not name — bare `.hero`, where the guard names only the three dark hero variants because a
   pale hero must keep the brand ink. What it must not do is restate the ANSWER. It named
   `--c-surface`, the brand's paper, where the guard reads `--c-cta-text`; those agree on a dark
   closing band and part company on a light one, which is the 1.92:1 cream-on-gold this file
   already records. Same value on every site standing today, right on the first site whose closing
   band is pale. */
:where(.sl-body).refine-estate .final-cta .btn-secondary, :where(.sl-body).refine-estate .section-hub-cta .btn-secondary, :where(.sl-body).refine-estate .hero .btn-secondary {
  color: var(--c-cta-text, var(--c-surface));
  border-color: color-mix(in srgb, var(--c-cta-text, var(--c-on-dark)) 55%, transparent);
}

/* ad-editorial-luxe forces accent secondary buttons with !important (:1476) — correct on the
   cream page, invisible on photo heroes and dark closing bands (bronze on Solstice's hub hero
   measured 1.02:1, five pages, first cold-start build). Only an !important later in the file
   can win this fight, scoped to exactly the dark contexts. Fourth instance of the lane-!important
   disease today; the pattern note lives in the room-rebind comment at :4283. */
/* The shared dark-ground guard cannot subsume this one either, and for a plainer reason than
   estate's: `ad-editorial-luxe` is an AD family, not a refine lane, so a selector that matches on
   the word "refine" will never see it, and an `!important` here can only be answered by another
   `!important`. It still reads the token rather than restating the answer, for the reason written
   over the estate rule above. */
:where(.sl-body).ad-editorial-luxe .hero .btn-secondary, :where(.sl-body).ad-editorial-luxe .final-cta .btn-secondary, :where(.sl-body).ad-editorial-luxe .section-hub-cta .btn-secondary {
  color: var(--c-cta-text, var(--c-surface)) !important;
  border-color: color-mix(in srgb, var(--c-cta-text, var(--c-on-dark)) 60%, transparent) !important;
}
:where(.sl-body).ad-editorial-luxe .hero .btn-secondary:hover, :where(.sl-body).ad-editorial-luxe .final-cta .btn-secondary:hover, :where(.sl-body).ad-editorial-luxe .section-hub-cta .btn-secondary:hover {
  background: color-mix(in srgb, var(--c-cta-text, var(--c-surface)) 16%, transparent) !important;
  color: var(--c-cta-text, var(--c-surface)) !important;
}

/* ══ ESTATE, THE FOLD-REVIEW PASS (2026-08-10). Ian: "open a browser and visually look."
   tools/fold-review.mjs now exists for exactly that, and its first run on the Solstice cold
   start found seven things every gate had passed. Each fix is a LANE or SYSTEM rule — the page
   was never the point. ══════════════════════════════════════════════════════════════════════ */

/* F1 — THE HERO GUARANTEES GROUND UNDER ITS TEXT. 'vignette' darkens CORNERS; centered text sits
   in the bright middle, and the headline landed on the subjects' faces. The estate hero carries
   its own center-weighted scrim, always, and the primary CTA is SOLID — three ghost outlines in
   a row is no hierarchy at all. */
:where(.sl-body).refine-estate .hero.hero-image-bg::after {
  content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: radial-gradient(90% 75% at 50% 48%, rgba(10, 6, 3, 0.52), rgba(10, 6, 3, 0.18) 70%, transparent 100%), linear-gradient(to top, rgba(10, 6, 3, 0.6), transparent 24%); /* the bottom band grounds the hero's own trust-badge overlay row — it was washing out on the bright pool edge */
}
:where(.sl-body).refine-estate .hero.hero-image-bg { position: relative; }
:where(.sl-body).refine-estate .hero.hero-image-bg .container { position: relative; z-index: 1; }
:where(.sl-body).refine-estate .hero .btn-primary {
  background: var(--c-accent) !important;
  color: var(--c-primary-dark) !important;
  border: 1px solid var(--c-accent) !important;
}

/* F2 — TRUST WHISPERS SIT ON STOCK, NEVER ON A PHOTOGRAPH. The strip rendered over the hero's
   bottom edge and turned to mush. Explicit ground + breathing room. */
:where(.sl-body).refine-estate .section-trust_strip {
  background: var(--c-surface-alt);
  padding-top: 2.2rem; padding-bottom: 2.2rem;
}

/* F3 — THE MENU CAROUSEL: arrows live in the gutter, not on the buttons; every card's CTA sits
   on one baseline (flex column + auto margin — the rag came from uneven copy lengths). */
:where(.sl-body).refine-estate .pkg-carousel { padding-inline: 3.2rem; }
:where(.sl-body).refine-estate .pkg-carousel .pkg-prev, :where(.sl-body).refine-estate .pkg-carousel .pkg-next, :where(.sl-body).refine-estate .pkg-carousel [class*="arrow"] { z-index: 2; }
:where(.sl-body).refine-estate .pkg-card { display: flex; flex-direction: column; }
:where(.sl-body).refine-estate .pkg-card .btn, :where(.sl-body).refine-estate .pkg-card a[class*="btn"] { margin-top: auto; align-self: flex-start; }

/* F4 — PROSE NEVER SITS RAW ON A PHOTOGRAPH. A six-line paragraph straight onto the pool scene
   read as a caption slab. In estate, photo-band prose gets a plate: dark, measured, breathing.
   And the band gets height so the photograph is a scene, not a strip. */
:where(.sl-body).refine-estate main > section.section.sec-photo { min-height: 460px; display: grid; align-items: center; }
:where(.sl-body).refine-estate main > section.section.sec-photo .prose-block {
  background: color-mix(in srgb, var(--c-primary-dark) 74%, transparent);
  padding: clamp(1.6rem, 3vw, 2.4rem) clamp(1.8rem, 3.2vw, 2.6rem);
  border-radius: 6px;
  max-width: 46rem !important;
  margin-left: 0 !important;
}

/* F5 — PORTRAITS KEEP THEIR HEADS in the image band (global object-position fix above); estate
   additionally lets a portrait run taller than the landscape cap. */
:where(.sl-body).refine-estate .itr-media img { max-height: 640px; }

/* F6 — THE RITUAL HAS NO EXCEPTIONS. The coverage section's own header markup (.coverage-index)
   sat left with a narrow intro and a right void — the one band on the page that broke center. */
:where(.sl-body).refine-estate .coverage-index > h2 { text-align: center; }
:where(.sl-body).refine-estate .coverage-index > .coverage-body { text-align: center; margin-inline: auto; }

/* F7 — ICONS ARE PUNCTUATION, NOT ILLUSTRATIONS. The swatch tiles' 90px icon discs read as
   cartoons against 55px serif headlines. */
:where(.sl-body).refine-estate .cat-ic { transform: scale(0.72); }

/* ── THE HOME PAGE ALTERNATES TOO ────────────────────────────────────────────────────────────────
   The interior pages have run a paper/tint/photo/dark rotation for weeks. The five blueprint HOME
   templates never did, because they are a separate path — so Meridian's home shipped SIX bands on
   one identical cream, Prairie's five whites in a row, Vela's three. A page of one flat colour is
   the "it all looks the same" complaint in its purest form, on the first page anyone opens.

   Done by re-pointing the token the blocks ALREADY read rather than overriding their backgrounds:
   a block paints `background: var(--bk-paper)`, so declaring --bk-paper on the band itself changes
   that band and nothing else. Three things fall out of that for free:
     - a band that paints a photograph or a dark ground never reads --bk-paper, so it is untouched
       and Estate — which already alternates paper/photo perfectly — comes out byte-identical;
     - --bk-paper is a BAND ground only, never a card fill (checked across all 29 blocks), so cards
       keep their separation from whatever is behind them;
     - both beats are explicit, which is the trap from 2026-08-15: leaving one beat unset falls back
       to the family default, and for two of the five families that default IS the tint.
   Light-on-light only. A dark beat here would need every ink in the band rebound, which is the
   block route's job on interior pages and not something a page-level rule can do safely.
   Counted on the lane's CHILDREN, not on `section` elements: most blocks arrive wrapped in a bare
   div, so `> section` matched two bands out of six and the page stayed flat. A custom property set
   on the wrapper inherits into the band inside it, which is what makes this work at any depth.

   HOME ONLY. The interior pages share the same lane wrapper, and there the block route already
   assigns a ground per band — applying a second, blind alternation on top of it fought the first
   and put MORE identical pairs next to each other than before. `.bk-home` marks the five blueprint
   home roots so the two systems never overlap. */
:where(.sl-body) .bk-home { --bk-muted-beat: color-mix(in srgb, var(--bk-muted) 85%, var(--bk-ink)); --bk-paper-base: var(--bk-paper); --bk-muted-base: var(--bk-muted); --bk-box-fill: var(--bk-tint, #f2f5f7); }
:where(.sl-body) .bk-home > *:nth-child(even of :is(section, :where(.sl-body) :has(section))) {
  --bk-paper: var(--bk-tint, #f2f5f7);
  --bk-muted: var(--bk-muted-beat);
  --bk-box-fill: var(--bk-paper-base);
}
/* ── THE SAME RHYTHM, STARTING ON THE OTHER FOOT ────────────────────────────────────────────────
   Ian on IV Revival's home page, 2026-09-19: "swap the sections that have white backgrounds to the
   light green and the light green backgrounds to white."

   Which beat carries the tint is genuinely arbitrary — the rule above starts on the second band
   because it had to start somewhere, not because anybody chose it. The page has an odd number of
   light bands, so the two readings put a different weight at the top and at the bottom, and that is
   worth being able to look at rather than argue about.

   IT IS NOT A TOKEN SWAP, and that is the whole reason this is a rule rather than two edited hex
   values. Exchanging --bk-paper and --bk-tint in the brand's skin would invert every band AND every
   card, pill and plate that fills itself from the tint — the reasons inside the "why choose" plate
   are tinted cards on a white plate, and they would come out white on white. Only the BAND ground
   moves here. Everything a band contains keeps the colour it has.

   BOTH BEATS ARE WRITTEN OUT, which is the trap from 2026-08-15: overriding one beat and letting
   the other fall through leaves the first rule still applying to it, and half the page does not
   move. `--bk-muted-base` exists for the same reason — the beat re-inks the muted text, so the beat
   that goes back to paper has to be given the base ink by name, not left to inherit the one the
   rule above set on it. Absent the class, not a byte of this is emitted. */
:where(.sl-body).sl-bands-flip .bk-home > *:nth-child(even of :is(section, :where(.sl-body) :has(section))) {
  --bk-paper: var(--bk-paper-base);
  --bk-muted: var(--bk-muted-base);
  --bk-box-fill: var(--bk-tint, #f2f5f7);
}
:where(.sl-body).sl-bands-flip .bk-home > *:nth-child(odd of :is(section, :where(.sl-body) :has(section))) {
  --bk-paper: var(--bk-tint, #f2f5f7);
  --bk-muted: var(--bk-muted-beat);
  --bk-box-fill: var(--bk-paper-base);
}
/* ── EXCEPT THE CONTACT BAND, WHICH ALWAYS FOLLOWS THE CLOSING ONE ──────────────────────────────
   The closing band paints a FIXED ground of its family's own choosing — the bright family's tint,
   the retail family's brand primary — and takes no part in the alternation above. So whichever way
   the parity happens to fall, the contact band beneath it has a one-in-two chance of landing on the
   same colour with no seam between them, which is exactly what the page-rules P3 check refuses.
   It is not a hypothetical: the first client to get a contact band drew it in the same tint as the
   closing band directly above it, and the build was refused.
   Contact is pinned last in every family's band table, so it is always the band AFTER the closing
   one. Giving it the base stock makes the seam certain rather than lucky. */
/* …AND ONLY AFTER A CLOSING BAND THAT REALLY PAINTS ITS OWN GROUND. The pin was unconditional, on
   the stated premise that every family's closing band paints a fixed colour of its own. Four do —
   estate a dark veil, bright and retail the tint, community the brand primary — and the FIFTH does
   not: `.bk-close-editorial` reads `--bk-paper`, which is the very token the alternation re-points
   per band. So on that family the closing band takes a page stock, the pin hands the contact band
   the base stock, and when the parity puts the closing band on base too they are the same colour
   with no seam between them. Measured on a cold-start launch: P3, deploy refused.
   Where the closing band takes part in the alternation, the alternation already guarantees the
   seam — the pin was the only thing breaking it. Named by the four classes that self-paint rather
   than by family, because that is the actual condition. */
:where(.sl-body) .bk-home > :is(.bk-close-estate, :where(.sl-body) .bk-close-bright, :where(.sl-body) .bk-close-retail, :where(.sl-body) .bk-close-community, :where(.sl-body) :has(.bk-close-estate), :where(.sl-body) :has(.bk-close-bright), :where(.sl-body) :has(.bk-close-retail), :where(.sl-body) :has(.bk-close-community))
  + :is(section.bk-contact, :where(.sl-body) :has(section.bk-contact)) {
  --bk-paper: var(--bk-paper-base);
}

/* ── AN FAQ ROW THAT OPENS ─────────────────────────────────────────────────────────────────────
   The four home FAQs listed questions and dropped their answers; three drew a chevron beside a
   row that could not open and one opened onto nothing. They are <details> now, so the row markers
   have to go and the answer needs somewhere to sit. One rule for all four skins: each keeps its
   own row class and its own colours, and inherits the behaviour. */
:where(.sl-body) .et-qd, :where(.sl-body) .rt-qd, :where(.sl-body) .bh-qd { border: 0; }
:where(.sl-body) .et-qd > summary, :where(.sl-body) .rt-qd > summary, :where(.sl-body) .bh-qd > summary, :where(.sl-body) .cm-q > summary { cursor: pointer; list-style: none; }
:where(.sl-body) .et-qd > summary::-webkit-details-marker, :where(.sl-body) .rt-qd > summary::-webkit-details-marker, :where(.sl-body) .bh-qd > summary::-webkit-details-marker, :where(.sl-body) .cm-q > summary::-webkit-details-marker { display: none; }
:where(.sl-body) .et-qd > summary::marker, :where(.sl-body) .rt-qd > summary::marker, :where(.sl-body) .bh-qd > summary::marker, :where(.sl-body) .cm-q > summary::marker { content: ''; }
/* the chevron turns, so the row says which state it is in */
:where(.sl-body) .et-qd[open] .et-qchev, :where(.sl-body) .rt-qd[open] i, :where(.sl-body) .bh-qd[open] i { transform: rotate(180deg); }
:where(.sl-body) .et-qchev, :where(.sl-body) .rt-qd i, :where(.sl-body) .bh-qd i { transition: transform .18s ease; }
:where(.sl-body) .et-qa, :where(.sl-body) .rt-qa, :where(.sl-body) .bh-qa, :where(.sl-body) .cm-qa {
  margin: 0;
  padding: 0.15rem 0 1.1rem;
  max-width: var(--bk-measure, 68ch);
  line-height: 1.62;
  color: var(--bk-muted, var(--c-text-muted, #5d6470));
  font-family: var(--font-body, sans-serif);
  font-size: 1rem;
}
/* the estate row indents its text past a badge, so its answer lines up with the question */
/* the answer lines up with the question text, past the badge, and keeps the row's own inset */
:where(.sl-body) .et-qa { padding-left: calc(2.6rem + clamp(16px, 2.2vw, 30px)); padding-right: clamp(16px, 2.2vw, 30px); }

/* A question with no answer on record stays a plain row — and loses the chevron, because an arrow
   beside something that cannot open is a promise the page does not keep. This is the honest half
   of the FAQ fix: the answers now show wherever the client gave us one, and where they did not,
   the page stops pretending. */
:where(.sl-body) .et-qrow-flat .et-qchev, :where(.sl-body) .rt-q-flat i, :where(.sl-body) .bh-q-flat i { display: none; }
:where(.sl-body) .et-qrow-flat, :where(.sl-body) .rt-q-flat, :where(.sl-body) .bh-q-flat, :where(.sl-body) .cm-q-flat { cursor: default; }

/* ── THE CLINICIAN'S NAME IN THE FIRST SCREEN ─────────────────────────────────────────────────
   Both condition references and both package references carry proof-of-trust inside the hero
   rather than as a band: a named clinician under the headline and a star pill above the button.
   We had the pill. This is the other half — quiet, one line, a small accent rule before it so it
   reads as an attribution rather than as body copy. It renders only when the brand actually has a
   medical director on record; a trust device that can be fabricated is worse than none. */
:where(.sl-body) .hero-byline {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  margin: 0.85rem 0 0;
  font: 500 0.95rem/1.5 var(--font-body, sans-serif);
  letter-spacing: 0.01em;
  color: var(--c-text-muted, #5d6470);
}
:where(.sl-body) .hero-byline-mark {
  flex: 0 0 auto;
  width: 22px; height: 2px; border-radius: 2px;
  background: var(--c-accent, var(--bk-accent, #c9a24d));
}
/* over a photograph or a dark hero the muted ink disappears, so the light form carries its own.
   IT TAKES THE HERO'S OWN INK, NOT A FIXED WHITE. The split hero always asked for the light form,
   assuming its band is dark; a design lane can paint that band pale, and on the Ridgeline contact page
   (2026-09-21) "Medically supervised by…" was white on near-white. currentColor is white on a dark
   band and the band's dark ink on a pale one. */
:where(.sl-body) .hero-byline-light { color: color-mix(in srgb, currentColor 82%, transparent); }
:where(.sl-body) .hero-byline-light .hero-byline-mark { background: color-mix(in srgb, currentColor 70%, transparent); }
/* it sits with the rating, not apart from it */
:where(.sl-body) .hero-byline + .hero-rating { margin-top: 0.7rem; }

/* ── RATING-LED SOCIAL PROOF (.rl-proof) ──────────────────────────────────────────────────────
   The one band docs/PRODUCT-GAPS.md said had to be built. Every existing social-proof rendition is
   a centered row of quote cards, which is why the catalogue grades it "overused" — it is the same
   band on nearly every site. This is a different silhouette for the same facts: one large figure
   held against the quotes as ruled rows, so a page carrying both does not read as one band twice.
   It degrades in both directions: figure with no quotes, or quotes with no figure, and nothing at
   all when the brand has neither. */
:where(.sl-body) .rl-proof {
  display: grid;
  grid-template-columns: minmax(0, 230px) minmax(0, 1fr);
  gap: clamp(1.75rem, 4vw, 3.25rem);
  align-items: start;
  max-width: var(--content-max);
  margin-inline: var(--bk-mi, auto);
}
/* with only one half present it is a single column, centred on its own */
:where(.sl-body) .rl-proof-single { grid-template-columns: minmax(0, 1fr); justify-items: center; text-align: center; }
:where(.sl-body) .rl-figure { display: grid; justify-items: center; gap: 0.35rem; padding-top: 0.25rem; }
:where(.sl-body) .rl-proof:not(.rl-proof-single) .rl-figure { justify-items: start; }
:where(.sl-body) .rl-number {
  font: 700 clamp(3.4rem, 7vw, 5rem)/0.92 var(--font-heading, serif);
  letter-spacing: -0.03em;
  color: var(--c-text, #1c2b33);
  font-variant-numeric: tabular-nums;
}
:where(.sl-body) .rl-stars { font-size: 1.05rem; letter-spacing: 0.12em; color: var(--c-accent, #c9a24d); }
:where(.sl-body) .rl-source { font-size: 0.9rem; color: var(--c-text-muted, #5d6470); }
:where(.sl-body) .rl-rows { display: grid; gap: 0; }
/* ruled rows, not cards — the whole point of the alternative shape */
:where(.sl-body) .rl-row { padding: clamp(0.9rem, 2vw, 1.15rem) 0; border-top: 1px solid var(--c-border, rgba(28,43,51,0.14)); }
:where(.sl-body) .rl-row:first-child { border-top: 0; padding-top: 0; }
:where(.sl-body) .rl-quote { margin: 0; font-size: 1.02rem; line-height: 1.6; color: var(--c-text, #1c2b33); }
:where(.sl-body) .rl-by { margin: 0.4rem 0 0; font-size: 0.88rem; color: var(--c-text-muted, #5d6470); }
:where(.sl-body) .rl-link {
  display: inline-block; margin-top: clamp(1.1rem, 2.5vw, 1.6rem);
  font-size: 0.95rem; font-weight: 600;
  color: var(--c-accent-ink, var(--c-primary, #1f3a4d));
}
@media (max-width: 760px) {
  :where(.sl-body) .rl-proof { grid-template-columns: minmax(0, 1fr); }
  :where(.sl-body) .rl-proof .rl-figure { justify-items: center; }
}



/* ══════════════════════════════════════════════════════════════════════════════════════════════
   A HOME HERO WITH NO PHOTOGRAPH  —  .bk-nopic
   ══════════════════════════════════════════════════════════════════════════════════════════════

   WHAT WAS WRONG
   The band at the top of a home page is designed around a photograph. When the client's record has
   no photograph — which is every client on day one, and now a routine outcome on any day, because
   the picture chooser was tightened to refuse a photograph that is not about the band it sits in —
   the band still rendered. On the three families whose hero is a full-bleed colour band it came out
   as several hundred pixels of ONE FLAT COLOUR with a line of type floating in it: measured on the
   thinnest client in the fleet at laptop width, 700 pixels tall with 240 of them occupied, and on
   the richest client 770 pixels of flat near-black. On the two families whose hero stands copy
   beside a picture it was worse: the picture column stayed open, so half of the first screen was
   an empty rectangle waiting for something that was never going to arrive. Nobody looking at any
   of the five thought "type-led hero". They thought the page had failed to load.

   WHAT IT LOOKS LIKE NOW
   A hero with no photograph is a TYPE-LED hero, which is a legitimate and often handsome piece of
   design in its own right. Four things carry it in place of the picture, and not one of them is
   invented here — all four are this system's own vocabulary, already written down and never once
   reaching a home page:

     A GROUND WITH MATERIAL IN IT.  Six hundred lines above, under "DARK BANDS", this file already
     says that a big field of flat colour "reads as flat ink" unless it is given a fine grain and a
     soft light source, and it already carries both — the grain token and the brand-coloured glow.
     That treatment reaches interior statistic bands, the interior closing band and the interior
     photographic hero. It reached no home hero at all. Here it is: light at the top of the band
     where the words begin, weight at the bottom where the buttons sit, one warm pool of the brand
     accent in the upper right, and the grain over all of it. The colour field stops being a slab
     and becomes a lit surface.

     A FRAME SIZED TO ITS WORDS.  A photographic hero is tall because the photograph rewards the
     height. With no photograph the same height is just emptiness, so the floor comes down by
     roughly two hundred pixels and the words fill what is left.

     THE OTHER HALF PUT TO WORK.  A hero that ranges its copy left did so because a photograph held
     the right-hand half. With no photograph, the supporting line moves across and holds that half
     itself: the big statement on the left, the sentence under it on the right, buttons beneath.
     That is the "title left, lead right" two-column header this shelf already uses for its section
     headings — the same idea, one band up. The two families whose hero is CENTRED are left alone,
     because a centred composition never had an empty side to fill.

     A MARK OF INTENT.  A short accent rule above the headline — the oldest signal in typography
     that a page was set rather than dumped — and the headline itself up a step, because there is
     no picture left to share the frame with. The rule appears only where the brand's own eyebrow
     line is absent, so no hero ever wears both.

   ONE DECISION, ONE HOME
   There are five home-page designs and this is one answer written once, not five answers written
   five times. The rule that decides WHEN it applies lives in src/lib/heroGround.ts; the look lives
   here. A design family opts in by asking that function for these class names and putting them on
   its hero. It cannot opt in "a bit differently" — there is nothing to vary.

   WHAT DOES VARY, AND WHY THAT IS NOT AN EXCEPTION
   Three of the five families stand their hero on a dark brand ground and two stand it on paper.
   The recipe is the same for both, but a glow that reads as light on ink reads as a stain on
   paper, so the strengths differ. That is the only difference, it follows from the family the
   client is already on, and it is written in two rules here instead of five times in five
   templates. Giving all five the same dark ground was the other option, and it would have taken
   two light papery families and flattened them into the three dark ones — which is the exact fault
   this repo keeps paying for.

   WHY THE GROUND IS PAINTED ON A PSEUDO-ELEMENT
   Each of the five families sets its own hero background inside its own component stylesheet, and
   a component stylesheet loads AFTER this file and wins every tie on equal specificity. A layer
   drawn on top of that background does not have to win the argument, so it cannot be quietly lost
   the next time somebody adds a class. Where a rule genuinely has to beat a component — the height
   floor, the type size, the collapsed column — it is written with the page wrapper in front of it
   so it outranks the component honestly rather than with an !important.
   ══════════════════════════════════════════════════════════════════════════════════════════════ */

:where(.sl-body) .bk-nopic { position: relative; }
:where(.sl-body) .bk-nopic::before {
  content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  border-radius: inherit;
}
/* the words sit on the ground, not under it */
:where(.sl-body) .bk-nopic > * { position: relative; z-index: 1; }

/* THE BAND'S OWN BACKGROUND COLOUR IS SET AS WELL AS THE GROUND ON TOP OF IT. Not belt and
   braces: the block that used to paint this band has just been told to stop, so without this the
   element's real background is TRANSPARENT and the lit ground exists only on a decorative layer.
   Anything that asks the page "what colour is behind these words" — including this repo's own
   contrast gate — reads the white page underneath and sees white type on white. It reported
   exactly that, on the headline of the thinnest client, and it was right to. */
:where(.sl-body) .bk-nopic-ink { background-color: var(--bk-dark, #10263b); }
:where(.sl-body) .bk-nopic-paper { background-color: var(--bk-paper, #ffffff); }

/* THE INK GROUND — the three families whose hero is already a dark brand-coloured band. Light at
   the top where the headline begins, settling to the brand's darkest colour by three quarters of
   the way down, which is where the buttons are: a button filled with the brand's primary colour
   would disappear on a ground that ENDED on that same colour, so the ground gets out of its way. */
:where(.sl-body) .bk-nopic-ink::before {
  background-color: var(--bk-dark, #10263b);
  background-image:
    var(--grain),
    radial-gradient(62% 76% at 88% -6%, color-mix(in srgb, var(--bk-accent, #c9a24d) 34%, transparent), transparent 64%),
    radial-gradient(82% 88% at 2% -12%, color-mix(in srgb, var(--bk-primary, #1f3a4d) 85%, transparent), transparent 66%),
    linear-gradient(180deg, color-mix(in srgb, var(--bk-primary, #1f3a4d) 38%, var(--bk-dark, #10263b)) 0%, var(--bk-dark, #10263b) 78%);
  background-size: 180px 180px, cover, cover, cover;
}

/* THE PAPER GROUND — the two families whose hero is light. Same two pools of light, a fifth of the
   strength, because on paper this is a wash and not a colour field. The grain rides its own layer
   at the multiply blend the paper bands elsewhere in this file already use; laid into the stack
   above it would darken the paper instead of texturing it. */
:where(.sl-body) .bk-nopic-paper::before {
  background-image:
    radial-gradient(58% 74% at 92% -4%, color-mix(in srgb, var(--bk-accent, #c9a24d) 26%, transparent), transparent 64%),
    radial-gradient(74% 96% at -10% 104%, color-mix(in srgb, var(--bk-primary, #1f3a4d) 18%, transparent), transparent 70%);
  background-size: cover, cover;
}
:where(.sl-body) .bk-nopic-paper::after {
  content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  border-radius: inherit; opacity: 0.4; mix-blend-mode: multiply;
  background-image: var(--grain); background-size: 180px 180px;
}

/* THE TWO FAMILIES WHOSE HERO MARKUP LIVES IN A SHARED BLOCK get the ground on a wrapper around
   that block, because the block is used by more than this one page and is not ours to re-skin. All
   the wrapper needs from the block is that it stop painting its own flat fill over the ground. */
:where(.sl-body) .bk-home .bk-nopic > .bk-notch, :where(.sl-body) .bk-home .bk-nopic > .bk-split { background-color: transparent; background-image: none; }

/* ON A PHONE THE NOTCHED HERO LAYS A FLAT BLACK OVER ITS PICTURE so white type stays readable at
   the clear end of a left-to-right veil. With no picture there is no veil and nothing to rescue:
   the black just dirties the brand colour, and — because it is drawn after the white notch — greys
   out the notch as well. Measured at 390px: the brand teal came out near-black and the white notch
   came out grey. Off, when there is no photograph. */
:where(.sl-body) .bk-home .bk-nopic > .bk-notch::after { background: transparent; }

/* THE FRAME COMES DOWN TO THE SIZE OF THE WORDS. Only the three full-bleed families carry a height
   floor; the two split families are sized by their content and their padding. */
:where(.sl-body) .bk-home .bk-nopic.et-hero, :where(.sl-body) .bk-home .bk-nopic.bh-hero, :where(.sl-body) .bk-home .bk-nopic > .bk-notch { /* no photograph in this hero — see .sl-hero-nopic */ --sl-hero-want: var(--sl-hero-nopic-want); }

/* THE HEADLINE GOES UP A STEP. There is no photograph left to share the frame with, so scale is
   what carries the composition — and a headline sized for a picture beside it looks timid without
   one. Five families, five numbers, because each family owns its own type scale and forcing one
   size on all five would be flattening them, not fixing them. They are together in one place so
   they stay in step. Editorial is absent on purpose: its headline is already the biggest on the
   shelf at 92px and raising it would only cost it lines. */
:where(.sl-body) .bk-home .bk-nopic.et-hero h1 { font-size: clamp(38px, 5.4vw, 78px); }
:where(.sl-body) .bk-home .bk-nopic.bh-hero h1 { font-size: clamp(40px, 6.6vw, 82px); }
:where(.sl-body) .bk-home .bk-nopic > .bk-notch h1 { font-size: clamp(38px, 4.9vw, 70px); }
:where(.sl-body) .bk-home .bk-nopic.rt-hero h1 { font-size: clamp(38px, 4.4vw, 66px); }

/* A SHORT ACCENT RULE ABOVE THE HEADLINE, and only where the brand's own eyebrow line is missing —
   a hero that already opens with an eyebrow does not need a second opener above it. The sibling
   selector decides that live, off whatever the record actually carries, rather than off a guess. */
:where(.sl-body) .bk-nopic h1::before {
  content: ''; display: block; width: 58px; height: 3px; border-radius: 2px;
  margin: 0 0 clamp(18px, 2vw, 28px);
  background: var(--bk-accent, currentColor);
}
:where(.sl-body) .bk-nopic [class*="eyebrow"] ~ h1::before { display: none; }
/* the two centred families centre their rule too */
:where(.sl-body) .bk-nopic.et-hero h1::before, :where(.sl-body) .bk-nopic.bh-hero h1::before { margin-inline: auto; }

/* ── THE OTHER HALF OF A RANGED-LEFT HERO ──────────────────────────────────────────
   The three families below all range their copy left because something used to occupy the right: a
   photograph in a column beside it, or a photograph fading in behind it. Take the photograph away
   and the copy sits in a narrow strip with an empty half beside it — measured on the retail family,
   800 of a 1400-pixel panel holding nothing at all, which is the single ugliest thing a hero can
   do. So the supporting line moves across and holds that half: the statement on the left, the
   sentence on the right, the buttons beneath both. The eyebrow spans the top and the button row
   spans the bottom, so the band still starts on ONE left edge and the page grid is untouched.
   Two columns of type need room to be two columns, so this is the wide layout only; under 860 the
   hero is a single column again and each part keeps the spacing its own block gave it. */
@media (min-width: 861px) {
  :where(.sl-body) .bk-home .bk-nopic > .bk-split > .bk-split-copy, :where(.sl-body) .bk-home .bk-nopic.rt-hero > .rt-hero-copy, :where(.sl-body) .bk-home .bk-nopic > .bk-notch > .bk-notch-copy {
    display: flex; flex-wrap: wrap; align-items: flex-end;
    column-gap: clamp(36px, 5vw, 84px); row-gap: 0;
  }
  :where(.sl-body) .bk-home .bk-nopic > .bk-split > .bk-split-copy > :is(.bk-eyebrow-rule, :where(.sl-body) .bk-split-ctas), :where(.sl-body) .bk-home .bk-nopic.rt-hero > .rt-hero-copy > :is(.rt-eyebrow, :where(.sl-body) .rt-hero-ctas), :where(.sl-body) .bk-home .bk-nopic > .bk-notch > .bk-notch-copy > .bk-notch-ctas { flex: 1 0 100%; }
  :where(.sl-body) .bk-home .bk-nopic > .bk-split > .bk-split-copy > h1, :where(.sl-body) .bk-home .bk-nopic.rt-hero > .rt-hero-copy > h1, :where(.sl-body) .bk-home .bk-nopic > .bk-notch > .bk-notch-copy > h1 { flex: 1 1 54%; min-width: 0; }
  :where(.sl-body) .bk-home .bk-nopic > .bk-split > .bk-split-copy > .bk-split-body, :where(.sl-body) .bk-home .bk-nopic.rt-hero > .rt-hero-copy > .rt-hero-body, :where(.sl-body) .bk-home .bk-nopic > .bk-notch > .bk-notch-copy > p { flex: 1 1 32%; min-width: 0; }
  /* THE BUTTON ROW NEEDS ITS OWN AIR. The supporting line used to sit between the headline and the
     buttons and was what spaced them apart; it has just moved to the other column, so without this
     the buttons sat against the descenders of the last line of the headline. */
  :where(.sl-body) .bk-home .bk-nopic > .bk-split > .bk-split-copy > .bk-split-ctas, :where(.sl-body) .bk-home .bk-nopic.rt-hero > .rt-hero-copy > .rt-hero-ctas, :where(.sl-body) .bk-home .bk-nopic > .bk-notch > .bk-notch-copy > .bk-notch-ctas { margin-top: clamp(26px, 3.2vw, 44px); }
}
/* the picture column itself goes; the copy takes the whole band */
:where(.sl-body) .bk-home .bk-nopic > .bk-split, :where(.sl-body) .bk-home .bk-nopic.rt-hero { grid-template-columns: minmax(0, 1fr); }

/* THE RETAIL PANEL KEEPS A DEEP BOTTOM EDGE to clear the small pill that hangs off the bottom of
   it. A brand that carries no such pill — and with no photograph either — was left with 110 pixels
   of empty panel under its buttons, so the panel comes back to the page's own rhythm. */
:where(.sl-body) .bk-home .bk-nopic.rt-hero:not(:has(.rt-hero-note)) { padding-bottom: clamp(44px, 5vw, 78px); }

/* THE SECOND LINE HAS TO START WHERE THE FIRST ONE DID. The page standard centres any block
   narrower than the band it sits in — right for a card grid, wrong for the supporting line of a
   hero, which belongs on its own column edge. With the picture column gone the band is suddenly
   1160 pixels wide, and the editorial hero's paragraph, capped at a readable measure, drifted 290
   pixels right of its own headline: three left edges in one hero. In a flex row an automatic
   margin also eats the free space the column needs, so this is a correctness fix as well as an
   alignment one. Weighted to tie the page standard and placed after it, rather than shouted down
   with an !important. */
:where(.sl-body).sl-shelf .bk-home .bk-nopic.bk-nopic-paper .bk-split p.bk-split-body, :where(.sl-body).sl-shelf .bk-home .bk-nopic.bk-nopic-paper .rt-hero p.rt-hero-body { margin-inline: 0; max-width: none; }

/* THE BUTTON YOU CANNOT SEE. The pill that the shared hero blocks fill as their main action is
   filled with the brand's PRIMARY colour, and on a brand-coloured band that is the colour of the
   band — so on the thinnest client the only call to action on the first screen was a
   primary-coloured pill on a primary-coloured ground, visible as two floating white words and
   nothing else. Measured: 1.0 to 1, which is not low contrast, it is no contrast.
   The cure is an EDGE, not a different fill. Refilling it with the brand accent was tried first
   and rejected on measurement: on the very client this was found on, the accent is a mid orange
   and a small white label on it comes to 3.8 to 1 — the button would have become visible by
   making its own words harder to read, and a dark label on the same orange is 4.3, so that accent
   cannot carry small text either way round. A hairline in the accent leaves the label on the fill
   it already passed on (9.5 to 1) and gives the pill an outline that reads against the ground at
   4.3 to 1, well over the 3 to 1 a control needs. Scoped to the ink ground, because on paper the
   same pill is already the darkest thing in the band. */
:where(.sl-body) .bk-home .bk-nopic-ink .bk-pill-fill { box-shadow: inset 0 0 0 1.5px var(--bk-accent); }

/* ══ editorial-ivory ══════════════════════════════════════════════════════════════════════════
   MAGAZINE RESTRAINT, TYPOGRAPHY-LED. Spec'd in DESIGN-LANES.md since the lane set was written
   ("oversized serif headlines, small-caps labels | borderless, whitespace does the separating")
   and never built. Authored 2026-08-23 for Nevue, a Tampa Bay mobile IV brand whose brief is that
   line almost verbatim: light high-contrast Didone at generous size, caps only for small labels,
   120px+ section padding, whitespace as the separator, and a warm cream page carrying 70% of the
   surface with navy used as INK rather than as a ground.

   AUTHORED RATHER THAN ASSIGNED, on the same reasoning that produced pill-porcelain at :7109.
   Every stock lane fights this brief. luxe-noir and dark-luxe make full-bleed dark bands their
   signature axis against a client who asked in writing for "lighter and brighter with fewer navy
   tones" and "one dark section maximum". clinical-porcelain is bright and unworn but pushes
   h1-h6 onto the BODY font (the brief mandates a Didone display face), compresses section padding
   to ~29-44px against 120px+, and zeroes both alternating beats with `:nth-of-type(n) { background:
   transparent }` at :6969 - which is why it and refine-classic each produced 5 page-rules refusals
   on the rehearsal client while spa-luxe produced 0. spa-luxe fits on type but is 15 rule blocks,
   dresses no cards, tables, FAQs or listing bands, and is already worn by three brands in this
   same vertical. A lane is scoped CSS under body.refine-*, so this one is additive: no existing
   client wears it and none renders a different byte because it exists.

   CONTRAST, MEASURED, and it is the whole reason this lane is careful. The brand accent it was
   authored against is a light champagne gold #C9A96E. Against the three creams it measures
   1.72-1.95:1 and against white 2.24:1 - it CANNOT carry text, hairlines that must be seen, or an
   underline, on any light ground. White on gold fails too. So this lane never sets raw --c-accent
   as a foreground on paper. Text that wants to read as gold uses --c-accent-ink, which brand.ts:199
   derives by mixing the accent toward black until it clears 4.8:1 on the darkest light surface (on
   this palette it resolves to ~#635336, measuring 5.7-7.4:1 across the creams). Gold raw is used
   for FILLS, and for foregrounds only on the ink ground, where it measures 6.61:1. Buttons that
   fill with gold take navy ink, never white or cream.

   Verified safe and used freely on this palette: navy #1B2744 on cream #F5EDD8 12.66:1, navy on
   ivory #EDE0CC 11.5:1, cream on navy 12.66:1, gold on navy 6.61:1, accent-ink on cream 6.38:1.

   BOTH ALTERNATING BEATS ARE DECLARED EXPLICITLY (section 1). A lane that paints only the tinted
   beat and lets the other fall through to the page makes a brand whose default ground IS a tint
   alternate tint-with-tint, and the page-rules P3 rule refuses it. Note also that on a palette of
   three pale creams the strongest available separation is only ~1.10:1, so the alternation here
   is a warmth shift, not a rhythm. Rhythm on this lane comes from the photographic bands, the one
   permitted ink room, and the sparkle rules - never from the tint alone.  ═══════════════════ 
   @lane editorial-ivory | magazine restraint: borderless, hairline-ruled, whitespace separates | suits: editorial magazine typographic restrained refined literary understated
   */
:where(.sl-body).refine-editorial-ivory {
  /* Borderless is the lane's stated identity: separation is done by air, by a hairline, and by a
     change of stock. Cards get no shadow at all - an elevation system is the thing this lane is
     defined against. */
  --card-radius: 2px;
  --btn-radius: 2px;
  --input-radius: 2px;
  --card-shadow: none;
  --card-hover-shadow: none;
  --card-border-width: 1px;
  /* Two hairline strengths, both mixed from the INK rather than the accent. A gold hairline on
     cream composites to about 1.3:1 and is invisible; these land at a visible but quiet weight. */
  --ei-rule: color-mix(in srgb, var(--c-primary) 16%, transparent);
  --ei-rule-strong: color-mix(in srgb, var(--c-primary) 30%, transparent);
  /* The four-point sparkle, drawn as a mask so it takes a brand colour rather than shipping any
     client's artwork in shared CSS. It is the lane's repeating accent: section dividers, list
     markers, and the marker on an open FAQ row. */
  --ei-sparkle: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cpath d='M50 0C52 30 70 48 100 50C70 52 52 70 50 100C48 70 30 52 0 50C30 48 48 30 50 0Z' fill='%23000'/%3E%3C/svg%3E");
  --ei-air: clamp(5.5rem, 9vw, 8.75rem); /* 88px phone floor, 140px desktop - the brief asks 120+ */
}

/* 1. SURFACES. Both beats named, and the ink room is a KEYED set rather than an nth-count, so a
      homepage gets exactly the dark moments it asks for and no more. */
:where(.sl-body).refine-editorial-ivory { background: var(--c-surface); }
:where(.sl-body).refine-editorial-ivory.sections-alternate main > section.section:nth-of-type(odd):not(.sec-room):not(.final-cta):not(.section-hub-cta) {
  background: var(--c-surface);
}
:where(.sl-body).refine-editorial-ivory.sections-alternate main > section.section:nth-of-type(even):not(.sec-room):not(.final-cta):not(.section-hub-cta) {
  background: var(--c-surface-alt);
}
/* The same pair under the paper rhythm, where rooms paint and the nth-counting is off. */
:where(.sl-body).refine-editorial-ivory.bands-paper main > section.section:nth-of-type(odd):not(.sec-room):not(.final-cta):not(.section-hub-cta) {
  background: var(--c-surface);
}
:where(.sl-body).refine-editorial-ivory.bands-paper main > section.section:nth-of-type(even):not(.sec-room):not(.final-cta):not(.section-hub-cta) {
  background: var(--c-surface-alt);
}
/* Whitespace does the separating. No rules between bands, and a lot more air than the default. */
:where(.sl-body).refine-editorial-ivory .section + .section { border-top: 0; }
:where(.sl-body).refine-editorial-ivory main > section.section { padding-block: var(--ei-air); }

/* 2. TYPE. The display face carries h1 and h2 at LIGHT weight and generous size with tight
      leading, which is where nearly all of the luxury signal in this brief lives. Tracking is
      near zero on the display and pushed out hard on the small caps labels - the inverse of the
      contemporary-startup setting, and deliberately so. */
:where(.sl-body).refine-editorial-ivory h1, :where(.sl-body).refine-editorial-ivory h2 {
  font-family: var(--font-display, var(--font-headline, var(--font-heading)));
  font-weight: 400;
  letter-spacing: 0.005em;
  line-height: 1.02;
  text-transform: none;
}
:where(.sl-body).refine-editorial-ivory h3, :where(.sl-body).refine-editorial-ivory h4 {
  font-family: var(--font-heading);
  font-weight: 400;
  letter-spacing: 0.01em;
  line-height: 1.14;
  text-transform: none;
}
:where(.sl-body).refine-editorial-ivory .hero h1, :where(.sl-body).refine-editorial-ivory .hero-title {
  font-size: clamp(2.85rem, 6vw, 5.1rem);
  line-height: 0.98;
}
:where(.sl-body).refine-editorial-ivory main > section.section h2 { font-size: clamp(2.1rem, 4vw, 3.4rem); }
/* BODY COPY IS 400, NOT 300, AND THAT IS A CORRECTION.
   The brief asked for "finer and thinner weights than a standard wellness site, which is where
   most of the luxury signal comes from", and this lane took it literally and set the whole page to
   300. Ian, 2026-08-25: "the font weight seems pretty light. Some of it is just that the font
   seems super thin and hard to read."
   Both are right, and they are about different type. The luxury signal lives in the DISPLAY face
   and in the tracking - a Didone at 400 with open letter-spacing reads finer than any weight
   change to body copy could. Jost at 300 over 14-18px of running text is not refined, it is
   hairline: the strokes are thinner than the anti-aliasing. Contrast was never the problem here -
   measured 5.03:1 on the pillar copy - the STROKE was.
   So: body copy at 400, and small copy heavier still (below), while every heading and every
   tracked label keeps the light setting the brief asked for. */
/* ── HOW HEAVY THE READING TEXT IS, AND WHY IT IS TWO STEPS AND NOT ONE ─────────────────────────
   Ian, twice: "the font weight seems pretty light... the font seems super thin and hard to read."

   The first answer moved this from 300 to 400 and he could not see the difference - correctly, and
   the measurement says why. Jost is a geometric sans drawn on the light side: its 400 is roughly
   where a workhorse text face sits at 300, and this lane sets body copy at 14.5-18px, where a thin
   stem on a cream ground is exactly the "hard to read" he is describing. One step on a face like
   this is inside the noise.

   500 is the reading weight for Jost. It is not bold - the headings are a serif display face and
   still carry the page - it is the weight at which the stems survive being small, pale and on
   paper. */
:where(.sl-body).refine-editorial-ivory { font-weight: 400; }
/* SMALL AND LIGHT IS THE WORST PAIR, and small is the other half of the complaint. Under 15px a
   light weight loses its stems entirely, so the captions, notes and card copy take a step up in
   weight AND stop being tiny: 12.5px is a footnote, not a line somebody is meant to read. */
:where(.sl-body).refine-editorial-ivory :is(.bk-prail-note, :where(.sl-body) .bk-pcard-note, :where(.sl-body) .bk-step-body, :where(.sl-body) .bk-pillar p, :where(.sl-body) .bk-astrip-note, :where(.sl-body) figcaption, :where(.sl-body) small) {
  font-weight: 500;
}
/* A FLOOR, NAMED ONE CLASS AT A TIME - not `max(13.5px, 0.9em)` across the group, which is what I
   tried first. That expression has no idea how big the element already was: on the process steps,
   set at 17px, `0.9em` resolved to 15.3px and the rule SHRANK the copy it was supposed to rescue.
   A minimum written as a fraction of the parent is not a minimum. */
:where(.sl-body).refine-editorial-ivory .bk-astrip-note { font-size: 13.5px; }
/* And the muted ink stops being a whisper. A 0.72 opacity note on cream measures like grey on
   grey; the tone still sits back from the heading, it is just legible while it does it. */
:where(.sl-body).refine-editorial-ivory .bk-astrip-note { opacity: 0.86; }
:where(.sl-body).refine-editorial-ivory p { max-width: 62ch; line-height: 1.72; }
:where(.sl-body).refine-editorial-ivory .section-header p, :where(.sl-body).refine-editorial-ivory .section-header .lede { max-width: 58ch; }

/* 3. SMALL CAPS LABELS. The only place this lane shouts, and it shouts quietly: 11px, wide
      tracking, and set in accent-ink so it reads as gold family while staying legible (6.38:1 on
      cream, against raw gold's 1.92:1). No chip, no pill, no fill. */
/* NO COLOUR HERE EITHER, and for the same reason. This lane re-inks the eyebrow for exactly
   two dark grounds and every other one — a photographic hero, a gradient hero, a coverage
   map — keeps the paper ink. `--eyebrow-ink`, which this lane already binds, is the
   ground-aware way to say the same thing. */
:where(.sl-body).refine-editorial-ivory .eyebrow, :where(.sl-body).refine-editorial-ivory .section-header .eyebrow {
  font-family: var(--font-body);
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  background: none;
  padding: 0;
  border: 0;
}
/* accent_mode:badge paints a filled chip at (0,5,2). This lane is borderless by definition, so
   the device is turned OFF through the tokens that rule reads rather than fought with !important. */
:where(.sl-body).refine-editorial-ivory { --eyebrow-chip: transparent; --eyebrow-ink: var(--c-accent-ink); }
/* On the ink ground the same label goes to raw gold, which is 6.61:1 there and correct. */
:where(.sl-body).refine-editorial-ivory .sec-room .eyebrow, :where(.sl-body).refine-editorial-ivory .final-cta .eyebrow { color: var(--c-accent); }

/* 4. THE SPARKLE RULE - the lane's signature. A hairline broken by a four-point star, sitting
      under a section headline and standing in for a divider anywhere a border would have gone.
      Masked, so it inherits the brand accent instead of hardcoding a colour. */
:where(.sl-body).refine-editorial-ivory .section-header::after {
  content: "";
  display: block;
  width: 100%;
  max-width: 8.5rem;
  height: 9px;
  margin-top: 1.5rem;
  background: var(--c-accent-ink);
  -webkit-mask:
    linear-gradient(#000, #000) left center / calc(50% - 11px) 1px no-repeat,
    linear-gradient(#000, #000) right center / calc(50% - 11px) 1px no-repeat,
    var(--ei-sparkle) center / 9px 9px no-repeat;
  mask:
    linear-gradient(#000, #000) left center / calc(50% - 11px) 1px no-repeat,
    linear-gradient(#000, #000) right center / calc(50% - 11px) 1px no-repeat,
    var(--ei-sparkle) center / 9px 9px no-repeat;
}
/* A centred band centres its rule; a split band keeps it on the left edge, which is the one-page
   grid rule and not a lane decision. */
:where(.sl-body).refine-editorial-ivory .section-header[data-align="center"]::after{ margin-inline: auto; }

/* 5. LIST MARKERS. The sparkle again, at list size, replacing every disc and check glyph. */
:where(.sl-body).refine-editorial-ivory .section ul:not([class*="nav"]):not([class*="menu"]):not([class*="crumb"]):not([class*="tab"]) > li {
  list-style: none;
  position: relative;
  padding-left: 1.6rem;
}
:where(.sl-body).refine-editorial-ivory .section ul:not([class*="nav"]):not([class*="menu"]):not([class*="crumb"]):not([class*="tab"]) > li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 8px;
  height: 8px;
  background: var(--c-accent-ink);
  -webkit-mask: var(--ei-sparkle) center / contain no-repeat;
  mask: var(--ei-sparkle) center / contain no-repeat;
}
:where(.sl-body).refine-editorial-ivory .sec-room ul > li::before, :where(.sl-body).refine-editorial-ivory .final-cta ul > li::before { background: var(--c-accent); }

/* 6. CARDS. Borderless is the identity, so a card is a hairline and air - never a box on a
      shadow. The top rule alone carries the edge; the hover deepens it rather than lifting. */
:where(.sl-body).refine-editorial-ivory .card, :where(.sl-body).refine-editorial-ivory .pkg-card, :where(.sl-body).refine-editorial-ivory .feature-card{
  background: transparent;
  border: 0;
  border-top: 1px solid var(--ei-rule-strong);
  border-radius: 0;
  box-shadow: none;
  padding-top: 1.65rem;
}
:where(.sl-body).refine-editorial-ivory .card:hover, :where(.sl-body).refine-editorial-ivory .pkg-card:hover, :where(.sl-body).refine-editorial-ivory .feature-card:hover{
  border-top-color: var(--c-accent-ink);
  transform: none;
  box-shadow: none;
}
/* A card that carries a photograph keeps a real frame, because a floating image with a hairline
   above it reads as an accident. Near-sharp, no shadow. */
:where(.sl-body).refine-editorial-ivory .card img, :where(.sl-body).refine-editorial-ivory .pkg-card img, :where(.sl-body).refine-editorial-ivory .feature-card img { border-radius: 2px; }

/* 7. BENEFIT TAGS. Hairline outline, ink text, wide tracking. Never a filled chip: a gold fill
      with cream or white text is the exact pairing the brand's own contrast panel fails. */
:where(.sl-body).refine-editorial-ivory .tag, :where(.sl-body).refine-editorial-ivory .chip, :where(.sl-body).refine-editorial-ivory .pill {
  background: transparent;
  border: 1px solid var(--ei-rule-strong);
  border-radius: 999px;
  color: var(--c-text);
  font-family: var(--font-body);
  font-size: 0.68rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 0.42em 0.95em;
}

/* 8. BUTTONS. Wide-tracked caps at small size, near-sharp corners, and - the important part - the
      primary action is filled with INK and labelled in cream. That is 12.66:1 for the label and a
      fully visible control boundary on any of the three creams. The alternative the palette
      suggests, a gold fill, would put the label at 2.2:1 if it were white and would leave the
      control edge at 1.3:1 against the page; gold fills are therefore reserved for the ink ground
      (section 9), where they measure 6.61:1. */
:where(.sl-body).refine-editorial-ivory .btn {
  font-family: var(--font-body);
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  border-radius: var(--btn-radius);
  padding: 1.05em 2.1em;
  box-shadow: none;
}
:where(.sl-body).refine-editorial-ivory .btn-primary, :where(.sl-body).refine-editorial-ivory .hero .btn-primary {
  background: var(--c-primary);
  border: 1px solid var(--c-primary);
  color: var(--c-on-primary);
}
:where(.sl-body).refine-editorial-ivory .btn-primary:hover, :where(.sl-body).refine-editorial-ivory .hero .btn-primary:hover {
  background: var(--c-primary-dark);
  border-color: var(--c-primary-dark);
  color: var(--c-on-primary);
}
/* THE SECONDARY BUTTON KEEPS ITS OWN INK. This rule used to set `color: var(--c-text)` and a
   hairline mixed from the ink, which reads correctly on paper and is invisible on any dark
   ground — and because `body.refine-editorial-ivory .btn-secondary` (0,2,1) outranks the
   renderer's `.hero-image-bg .btn-secondary` (0,2,0), it silently replaced the one rule that
   already knew the answer. Measured: "Call Us" at 1.15:1 on five listing-page heroes. The lane
   now states only what is lane-specific — the shape — and leaves colour to the context rules
   that read --c-cta-text. Do not put a bare colour on a control in a lane: the ground under it
   is not the lane's to know. */
:where(.sl-body).refine-editorial-ivory .btn-secondary{
  background: transparent;
  /* THE SHAPE STAYS, THE INK IS THE CONTEXT'S. Dropping the colour override also dropped the
     visible edge, and "See The Menu" became a word floating beside the primary button — the
     exact fault the repo already has a name for. currentColor solves both at once: the border
     follows whatever ink the ground gave the label, so it is legible on paper and on ink
     without this lane needing to know which it is standing on. */
  border: 1px solid color-mix(in srgb, currentColor 38%, transparent);
}
:where(.sl-body).refine-editorial-ivory .btn-secondary:hover{ border-color: color-mix(in srgb, currentColor 72%, transparent); }

/* 9. THE INK ROOM. One per homepage by brief. Gold is the accent here and only here, at 6.61:1.
      A gold-filled button on this ground takes ink text, which is the pairing the brand book
      asks for in so many words. */
/* AND THE CLOSING BAND IS NOT THIS LANE'S TO PAINT. On a hub page it lands directly beneath an ink
   ROOM, so painting both in the same dark colour is one colour twice with no seam between them —
   which is P3, and which refuses every listing page on the site at once. The two lanes written this
   week both leave it alone; this one now does too. */
:where(.sl-body).refine-editorial-ivory .sec-room { background: var(--c-hero-plate); color: var(--c-on-dark); }
/* THE HEADING FOLLOWS ITS OWN GROUND, like the controls above it. Cream was right when this band
   was the dark primary; the band is the accent now, and cream on this brand's gold measures
   1.92:1. `--c-cta-text` is already the answer for everything else in the band — the heading was
   the one thing still naming a colour of its own, which is the shape this file keeps paying for. */
:where(.sl-body).refine-editorial-ivory .final-cta h1, :where(.sl-body).refine-editorial-ivory .final-cta h2, :where(.sl-body).refine-editorial-ivory .final-cta h3 { color: var(--c-cta-text, var(--c-surface)); }
:where(.sl-body).refine-editorial-ivory .final-cta p { color: color-mix(in srgb, var(--c-cta-text, var(--c-surface)) 88%, transparent); }

/* ── AND A ROOM IS NOT THE CLOSING BAND ───────────────────────────────────────────────
   These two bands were sharing one ink rule, and they do not share a ground. The closing band is
   painted with the ACCENT, so its ink is `--c-cta-text`, which on this brand resolves through
   `--c-accent-on` to the near-black navy that reads on gold. A dark room is painted with the
   PRIMARY, and that same near-black navy on it measures 1.15:1 — four headings that were, in the
   checker's words, effectively invisible.
   Nothing about the closing band was wrong; the room was borrowing its answer to a different
   question. A band's ink is a property of the band's own ground, so the rule is split in two. */
:where(.sl-body).refine-editorial-ivory .sec-room h1, :where(.sl-body).refine-editorial-ivory .sec-room h2, :where(.sl-body).refine-editorial-ivory .sec-room h3 { color: var(--c-on-dark); }
:where(.sl-body).refine-editorial-ivory .sec-room p { color: color-mix(in srgb, var(--c-surface) 88%, transparent); }
:where(.sl-body).refine-editorial-ivory .sec-room .btn-primary, :where(.sl-body).refine-editorial-ivory .final-cta .btn-primary {
  background: var(--c-accent);
  border-color: var(--c-accent);
  color: var(--c-primary-dark);
}
:where(.sl-body).refine-editorial-ivory .sec-room .card, :where(.sl-body).refine-editorial-ivory .final-cta .card { border-top-color: color-mix(in srgb, var(--c-accent) 55%, transparent); }
:where(.sl-body).refine-editorial-ivory .sec-room .section-header::after, :where(.sl-body).refine-editorial-ivory .final-cta .section-header::after { background: var(--c-accent); }

/* 10. FAQ. An accordion with no box: a hairline per row, the question in the heading face, and
       the marker replaced by the sparkle so the device carries through to the least glamorous
       section in the catalog. */
:where(.sl-body).refine-editorial-ivory .faq-item, :where(.sl-body).refine-editorial-ivory details.faq-item {
  background: transparent;
  border: 0;
  border-top: 1px solid var(--ei-rule);
  border-radius: 0;
  box-shadow: none;
  padding-block: 1.25rem;
}
:where(.sl-body).refine-editorial-ivory .faq-item summary{
  font-family: var(--font-heading);
  font-weight: 400;
  font-size: 1.16rem;
  letter-spacing: 0.01em;
  list-style: none;
}
:where(.sl-body).refine-editorial-ivory .faq-item summary::-webkit-details-marker { display: none; }
:where(.sl-body).refine-editorial-ivory .faq-item summary::after {
  content: "";
  width: 10px;
  height: 10px;
  flex: 0 0 10px;
  background: var(--c-accent-ink);
  -webkit-mask: var(--ei-sparkle) center / contain no-repeat;
  mask: var(--ei-sparkle) center / contain no-repeat;
  transition: transform 220ms ease;
}
:where(.sl-body).refine-editorial-ivory .faq-item[open] summary::after { transform: rotate(45deg); }

/* 11. PRICES AND TABLES. Tabular figures in the display face at a size that lets a price act as
       a typographic element rather than a badge. No coloured price chips. */
:where(.sl-body).refine-editorial-ivory .price, :where(.sl-body).refine-editorial-ivory .pkg-price{
  font-family: var(--font-display, var(--font-heading));
  font-weight: 400;
  font-variant-numeric: tabular-nums lining-nums;
  letter-spacing: 0;
  color: var(--c-text);
  background: none;
  border: 0;
  padding: 0;
}
:where(.sl-body).refine-editorial-ivory table { border-collapse: collapse; }
:where(.sl-body).refine-editorial-ivory table th, :where(.sl-body).refine-editorial-ivory table td { border: 0; border-bottom: 1px solid var(--ei-rule); padding: 0.95rem 1rem; }
:where(.sl-body).refine-editorial-ivory table th {
  font-family: var(--font-body);
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--c-accent-ink);
  border-bottom-color: var(--ei-rule-strong);
}

/* 12. NUMBERED STEPS. The brief asks for a numbered How It Works, and a magazine numbers things
       in the display face at size rather than in a filled circle. */

/* 13. IMAGERY. Near-sharp, unshadowed, and never arched or circular - the geometry has to agree
       with a Didone. */
:where(.sl-body).refine-editorial-ivory .section img, :where(.sl-body).refine-editorial-ivory figure img { border-radius: 2px; box-shadow: none; }
:where(.sl-body).refine-editorial-ivory figure { margin: 0; }
:where(.sl-body).refine-editorial-ivory figcaption {
  font-family: var(--font-body);
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--c-text-muted);
  margin-top: 0.75rem;
}

/* ── editorial-ivory, PART 2: THE BLUEPRINT HOME ─────────────────────────────────────────────
   A LANE HAS TO DRESS BOTH RENDERERS OR IT DRESSES THE LEAST-READ HALF OF THE SITE.
   Everything above this point targets the interior route, which draws through Sections.astro
   and speaks in `.section`, `.card`, `.btn`. A brand carrying `theme_json.page_template` never
   calls that file on its HOME page: index.astro hands off to a blueprint template, which speaks
   in `.ed-*` (the family's own chrome) and `.bk-*` (the shared block library). So on the one
   page every visitor actually sees, none of the rules above matched anything.

   Measured on Névue's first build: the interior pages came out borderless and hairline-ruled as
   intended, while the home page rendered white cards on drop shadows with 22px corners — the
   elevation system this lane is defined against — because `.bk-pillar` and `.bk-ccard` carry
   their own fills and shadows and read no lane token. The body class IS present on a blueprint
   home (verified in the built HTML), so the fix is reach, not plumbing.

   Scoped to `body.refine-editorial-ivory`, so the other four families and every brand not on
   this lane are untouched. ═════════════════════════════════════════════════════════════════ */

/* 1. THE STICKY BAR HAS TO BE OPAQUE. It ships at 88% of the paper colour, which lets a Didone
      headline scroll under it and sit there half-legible — visible on four of ten folds. Cream
      is the page, so a solid cream bar with a hairline under it reads as chrome, not as a panel. */
:where(.sl-body).refine-editorial-ivory .ed-nav {
  background: var(--bk-paper, var(--c-surface));
  border-bottom: 1px solid var(--ei-rule);
}

/* 2. CARDS ARE HAIRLINES AND AIR. Same rule as the interior route, restated in the block
      library's vocabulary because none of these classes inherit from `.card`. */
:where(.sl-body).refine-editorial-ivory .bk-pillar, :where(.sl-body).refine-editorial-ivory .bk-pcard, :where(.sl-body).refine-editorial-ivory .bk-tier:not(.bk-feat), :where(.sl-body).refine-editorial-ivory .bk-step, :where(.sl-body).refine-editorial-ivory .bk-ccard {
  background: transparent;
  border: 0;
  border-top: 1px solid var(--ei-rule-strong);
  border-radius: 0;
  box-shadow: none;
}
:where(.sl-body).refine-editorial-ivory .bk-pillar:hover, :where(.sl-body).refine-editorial-ivory .bk-pcard:hover, :where(.sl-body).refine-editorial-ivory .bk-tier:not(.bk-feat):hover {
  border-top-color: var(--c-accent-ink);
  transform: none;
  box-shadow: none;
}
/* The product plinth ships a near-white panel behind the artwork. On a cream page that reads as
   a second, colder paper stock sitting inside the first. The client's bags and vials are cut out
   on transparency, so they simply stand on the page. */
:where(.sl-body).refine-editorial-ivory .bk-plinth {
  background: transparent;
  border-radius: 0;
  box-shadow: none;
}

/* 3. THE FEATURED GROUP TIER is the one place a fill is right, and it is the page's dark moment.
      Gold on ink is 6.61:1; gold on cream is 1.92:1 and would vanish. */
:where(.sl-body).refine-editorial-ivory .bk-tier.bk-feat {
  background: var(--bk-dark, var(--c-hero-plate));
  color: var(--c-on-dark);
  border-top-color: var(--c-accent);
}
:where(.sl-body).refine-editorial-ivory .bk-tier.bk-feat .bk-price { color: var(--c-accent); }

/* 4. THE FOOTER IS INK. The palette assigns navy exactly two jobs — type, and the footer — and
      the family ships a cream footer, so the page ended on cream-on-cream with no close at all. */
:where(.sl-body).refine-editorial-ivory .ed-foot {
  background: var(--bk-dark, var(--c-hero-plate));
  color: var(--c-on-dark);
}
:where(.sl-body).refine-editorial-ivory .ed.bk-home .ed-foot h4 {
  color: var(--c-accent);
  font-family: var(--font-body);
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}
/* Measured in the browser after the footer was painted ink: the links were still coming through
   at the block's own navy, 1.15:1 on the new ground, and the column headings at 2.89:1. Both are
   the Astro scoping problem again — `.ed-foot a[data-astro-cid-…]` outranks a plain lane rule —
   so these carry the wrapper class too. Re-measured after: links 14.61:1, headings 7.62:1. */
:where(.sl-body).refine-editorial-ivory .ed.bk-home .ed-foot a, :where(.sl-body).refine-editorial-ivory .ed.bk-home .ed-foot p, :where(.sl-body).refine-editorial-ivory .ed.bk-home .ed-foot li, :where(.sl-body).refine-editorial-ivory .ed.bk-home .ed-foot .ed-brand, :where(.sl-body).refine-editorial-ivory .ed.bk-home .ed-foot .ed-brand b, :where(.sl-body).refine-editorial-ivory .ed.bk-home .ed-foot .ed-brand small { color: var(--c-on-dark); }
:where(.sl-body).refine-editorial-ivory .ed.bk-home .ed-foot a:hover { color: var(--c-accent); }
:where(.sl-body).refine-editorial-ivory .ed-legal {
  color: color-mix(in srgb, var(--c-surface) 72%, transparent);
  border-top: 1px solid color-mix(in srgb, var(--c-accent) 34%, transparent);
}

/* 5. SMALL CAPS LABELS, in the block library's vocabulary. Accent-ink on paper, raw gold on ink. */
:where(.sl-body).refine-editorial-ivory .bk-eyebrow-caps, :where(.sl-body).refine-editorial-ivory .ed-eyebrow {
  font-family: var(--font-body);
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--c-accent-ink);
  background: none;
  border: 0;
  padding: 0;
}
:where(.sl-body).refine-editorial-ivory .ed-foot .bk-eyebrow-caps { color: var(--c-accent); }

/* 6. THE NUMBERED STEPS carry the brief's How It Works. A magazine sets a number at size in the
      display face; the family sets it in a filled disc. */
:where(.sl-body).refine-editorial-ivory .bk-no {
  font-family: var(--font-display, var(--font-heading));
  font-weight: 400;
  font-size: clamp(2rem, 3.2vw, 2.9rem);
  line-height: 1;
  color: color-mix(in srgb, var(--c-accent-ink) 62%, transparent);
  background: none;
  border: 0;
  border-radius: 0;
  width: auto;
  height: auto;
  display: block;
}

/* 7. PRICES set as type, not as a badge, and in tabular figures so a column of them lines up. */
/* `.bk-price` IS ALSO THE NAME OF A WHOLE BAND, NOT JUST A FIGURE. Written bare, this rule
   matched `section.bk-price.bk-price-estate` — the pricing band — and `background: none` stripped
   its dark ground while its own white text stayed, so the preview sheet shipped white-on-white at
   1:1 and visual-lint refused the deploy. The figure is only ever inside a tier card, so say so.
   This is the shape-contract trap in selector form: a treatment applied to something it was never
   meant to reach, silently. */
:where(.sl-body).refine-editorial-ivory .bk-pprice, :where(.sl-body).refine-editorial-ivory .bk-pamt, :where(.sl-body).refine-editorial-ivory .bk-tier .bk-price {
  font-family: var(--font-display, var(--font-heading));
  font-weight: 400;
  font-variant-numeric: tabular-nums lining-nums;
  letter-spacing: 0;
  background: none;
  border: 0;
  padding: 0;
}
/* "PRICE:" in front of a figure is a spreadsheet header, not a price. The figure says it. */
:where(.sl-body).refine-editorial-ivory .bk-pprice { font-size: 0; }
:where(.sl-body).refine-editorial-ivory .bk-pamt { font-size: 1.5rem; color: var(--c-text); }

/* 8. THE FAQ ROW. Hairline per row, question in the heading face, no box. */
:where(.sl-body).refine-editorial-ivory .bk-q {
  background: transparent;
  border: 0;
  border-top: 1px solid var(--ei-rule);
  border-radius: 0;
  box-shadow: none;
}
:where(.sl-body).refine-editorial-ivory .bk-q-text {
  font-family: var(--font-heading);
  font-weight: 400;
  letter-spacing: 0.01em;
}
:where(.sl-body).refine-editorial-ivory .bk-q-badge { color: var(--c-accent-ink); background: none; }

/* 9. CITY PILLS AND BUTTONS. Near-sharp, hairline, wide-tracked caps — and the primary action
      fills with ink and labels in cream, never gold-on-white. */
/* Shape only. `.bk-pill-ghost` is a control that appears on grounds this lane does not own — it
   came out navy-on-navy in the block sheet for exactly the reason the secondary button did. */
/* KEEP THE EDGE. These blocks draw a ghost control's outline as an inset box-shadow, not a border,
   so a blanket `box-shadow: none` here does not tidy the control - it deletes it. "See The Menu"
   shipped as a word floating beside the Book button on the live hero, which is the same fault as
   stripping a misfitting pill and leaving the label behind. The edge is restated from currentColor
   so it follows whatever ink the ground gave the label: navy on Nevue's cream hero, white where a
   skin sets white. Shape from the lane, colour from the context. */
:where(.sl-body).refine-editorial-ivory .bk-city, :where(.sl-body).refine-editorial-ivory .bk-pill-ghost {
  background: transparent;
  border-radius: 999px;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, currentColor 38%, transparent);
}
:where(.sl-body).refine-editorial-ivory .bk-dot { background: var(--c-accent); }
:where(.sl-body).refine-editorial-ivory .bk-pbook, :where(.sl-body).refine-editorial-ivory .bk-pbtn, :where(.sl-body).refine-editorial-ivory .ed-pill {
  font-family: var(--font-body);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  border-radius: 2px;
  box-shadow: none;
  background: var(--c-primary);
  color: var(--c-on-primary);
  border: 1px solid var(--c-primary);
}
:where(.sl-body).refine-editorial-ivory .bk-pbook:hover, :where(.sl-body).refine-editorial-ivory .bk-pbtn:hover, :where(.sl-body).refine-editorial-ivory .ed-pill:hover {
  background: var(--c-primary-dark);
  border-color: var(--c-primary-dark);
}

/* 10. IMAGERY. Near-sharp and unshadowed, so a photograph agrees with the type. */
:where(.sl-body).refine-editorial-ivory .bk-pil-ph, :where(.sl-body).refine-editorial-ivory .bk-pil-ph img, :where(.sl-body).refine-editorial-ivory .ed-quote img { border-radius: 2px; box-shadow: none; }
:where(.sl-body).refine-editorial-ivory .bk-pil-arrow {
  background: var(--c-surface);
  color: var(--c-primary);
  box-shadow: none;
  border: 1px solid var(--ei-rule-strong);
}

/* 11. THE ONE INK ROOM ON A BLUEPRINT HOME. The brief this lane was authored against allows
       exactly one dark section on the homepage, and the first build had none: three pale creams
       separated by ~1.10:1 ran unbroken from the nav to the footer, which measures as an
       alternating page and reads as a single slab. The coverage band is the right one to darken —
       it is the page's factual centre (seven areas, the hours, the phone number), it sits between
       the group tiers and the FAQ so it breaks the longest cream run, and its city pills and
       gold rules are the one place raw accent is legal at 6.61:1.
       Interior pages get their ink room from `.sec-room`; this is the blueprint home's. */
/* SCOPED TO THE HOME PAGE, because that is the only page whose composition this decides. The
   rule was written bare, so it also darkened the CityPillLocations block wherever else it is
   rendered — including the four-skin block sheet, where each skin supplies its OWN --bk-dark and
   its own heading colour, and the pair came out dark-on-dark in all four. A lane may decide the
   rhythm of a page it owns; it may not repaint a shared block everywhere it appears. */
:where(.sl-body).refine-editorial-ivory .ed.bk-home section.bk-cities {
  background: var(--bk-dark, var(--c-hero-plate));
  color: var(--c-on-dark);
}
:where(.sl-body).refine-editorial-ivory .ed.bk-home section.bk-cities h2, :where(.sl-body).refine-editorial-ivory .ed.bk-home section.bk-cities h3 { color: var(--c-on-dark); }
/* The pills invert with the ground: a hairline in gold, the label in cream, the dot in gold. */
/* THE MAP PIN, ON THE INK ROOM. Each city pill carries a little pin drawn as an <i> filled with
   --bk-primary, which is the navy — and this band is navy, so seven pins were painted on their own
   colour. (The rule that used to live here named `.bk-dot`, an element this block does not have:
   dead CSS that read as a fix.) */
:where(.sl-body).refine-editorial-ivory .ed.bk-home section.bk-cities .bk-city i { background: var(--c-accent); }

/* 11d. THE LAST LETTERBOX BECOMES A COLUMN. The groups band opened the way three other bands
   opened - centred head, one wide photograph lying across the band like a lid, content beneath.
   The picture is already a direct child of the section, so the band can simply become a grid and
   place it as the FIRST of four columns: a tall portrait beside the three tiers, with the middle
   tier still on ink. The heading stays centred across both tracks, so the one-alignment rule is
   untouched, and the section's own content box is still the grid's left edge, so the one-left-edge
   rule is untouched. Below 1000px it falls back to the stacked order it has today. */
@media (min-width: 1000px) {
  :where(.sl-body).refine-editorial-ivory .ed.bk-home section.bk-tiers {
    display: grid;
    grid-template-columns: minmax(0, 300px) minmax(0, 1fr);
    grid-template-rows: auto auto auto 1fr;
    column-gap: clamp(28px, 4vw, 64px);
  }
  :where(.sl-body).refine-editorial-ivory .ed.bk-home section.bk-tiers > :is(.bk-eyebrow-caps, :where(.sl-body) h2, :where(.sl-body) .bk-tiers-sub) { grid-column: 1 / -1; }
  :where(.sl-body).refine-editorial-ivory .ed.bk-home section.bk-tiers > .bk-tiers-art {
    grid-column: 1; grid-row: 4; height: 100%; min-height: 420px;
    aspect-ratio: 3 / 4; object-fit: cover; object-position: 50% var(--sl-focus-y, 32%); margin: 0;
  }
  :where(.sl-body).refine-editorial-ivory .ed.bk-home section.bk-tiers > .bk-tierrow { grid-column: 2; grid-row: 4; }
  /* THE COLUMNS ARE A QUARTER NARROWER NOW, AND THE DISCOUNT DID NOT FIT. At 54px the numeral
     pushed "off the booking" onto a second line, and this block draws a hairline under that whole
     line - so every tier read "10% off the" / rule / "booking". Sized to the column it is actually
     standing in, the phrase sits on one line again and the rule lands where it was drawn to. */
  /* the suffix goes UNDER the figure rather than beside it. Shrinking the numeral until "off the
     booking" fitted alongside it would have cost the discount the only bit of scale it has, and
     this block draws a hairline under the whole line, so an inline wrap put a rule through the
     middle of the phrase. On its own line it is a caption, which is what it is. */
  :where(.sl-body).refine-editorial-ivory .ed.bk-home section.bk-tiers .bk-price { font-size: clamp(2.2rem, 3vw, 2.9rem); line-height: 1.05; }
  :where(.sl-body).refine-editorial-ivory .ed.bk-home section.bk-tiers .bk-price small { display: block; margin-top: 4px; }
}

/* 11e. EVERY BAND KEEPS THE PAGE'S MARGINS. THIS ONE USED TO BREAK THEM, AND IT WAS WRONG.
   I ran the coverage band's photograph off the left edge of the screen on purpose, as "the one
   moment where anything touches the edge". Ian, 2026-08-25: "if we're full bleeding, the whole
   website should be full bleed. If we're half bleed... the margins per section should align within
   the whole site. That way the site looks like a uniform site instead of 'oh, one section looks
   like this, one section looks like that.'"
   He is right, and it is the more useful rule: where the page's edge sits is a decision the PAGE
   makes once, not something a band opts out of. One band reaching the screen edge on a page whose
   other nine are inset does not read as emphasis, it reads as a mistake.
   grid-lint G6 now fails a build that mixes the two, so this cannot come back by accident. */

/* 11c. THE SHELF SHARES A BASELINE TOO. Eight vials in one line, and two of the names run to two
   and three lines - so their prices and their buttons sat 20 and 40px below the other six and the
   row read ragged. Same answer as the product cards in 12: reserve the tallest name, so every
   price lands on one line and every button on another. Only where they stand side by side. */
@media (min-width: 901px) {
  :where(.sl-body).refine-editorial-ivory .ed.bk-home .bk-bagrow .bk-bag h3 { min-height: 3.4em; }
}

/* 11a. BAND HEADINGS ARE A SCALE, NOT AN ACCIDENT.
   Measured on the built home, top to bottom: 64px, 54px, 46px, 28px, 54px, 36px, 54px, 64px, 64px.
   Six different sizes in ten bands, and no reader could tell rank from any of them - the two
   BIGGEST were the closing pitch and the contact details, while the priced menu, which is the
   whole product, was set smaller than both. Each block simply carried whatever size its own author
   chose, and nothing above them ever compared the numbers.
   Four steps, deliberately:
     one moment   the closing pitch, and nothing else on the page, at full display size
     feature      the four bands that carry the offer - why us, how it runs, the menu, groups
     contact      the sign-off, below feature so the crescendo lands on the line above it
     department   the supporting bands - add-ons, coverage, questions
   !important for the reason the type scale above needs it: a block's own h2 rule carries Astro's
   scope attribute and outranks any page-level selector. The PAGE decides rank; the block decides
   how a heading looks. */
:where(.sl-body).refine-editorial-ivory .ed.bk-home :is(section.bk-pillars, :where(.sl-body) section.bk-tl, :where(.sl-body) section.bk-plinths, :where(.sl-body) section.bk-tiers) h2 {
  font-size: clamp(2.2rem, 3vw, 2.9rem) !important;
}
:where(.sl-body).refine-editorial-ivory .ed.bk-home :is(section.bk-bagrow, :where(.sl-body) section.bk-cities, :where(.sl-body) section.bk-faq) h2 {
  font-size: clamp(1.7rem, 2.2vw, 2.1rem) !important;
}
:where(.sl-body).refine-editorial-ivory .ed.bk-home section.bk-contact h2 {
  font-size: clamp(2rem, 2.6vw, 2.5rem) !important;
}

/* 11b. A SECOND INK ROOM, HIGH ON THE PAGE.
   Measured on the built home: ten bands, and only ONE of them was not on paper or tint - the
   locations band, three quarters of the way down. Everything above it was the same warm ivory,
   so the top two thirds of the page had no contrast beat at all and every band ran into the next.
   The process band is the right one to take it: it is a numbered rail, which is already the most
   distinctive shape on the page, and putting it on ink makes the gold numerals the loudest thing
   above the fold-and-a-half. Neighbours stay tint -> ink -> tint, so no two ink rooms touch.
   Scoped to this lane's home, like the locations rule above it, for the same reason: a lane may
   decide the rhythm of a page it owns and may not repaint a shared block everywhere it appears. */
:where(.sl-body).refine-editorial-ivory .ed.bk-home section.bk-tl {
  background: var(--bk-dark, var(--c-hero-plate));
  color: var(--c-on-dark);
}
:where(.sl-body).refine-editorial-ivory .ed.bk-home section.bk-tl :is(h2, :where(.sl-body) h3) { color: var(--c-on-dark); }
:where(.sl-body).refine-editorial-ivory .ed.bk-home section.bk-tl :is(.bk-tl-intro, :where(.sl-body) .bk-step-body, :where(.sl-body) .bk-when) {
  color: color-mix(in srgb, var(--c-surface) 74%, transparent);
}
/* the dot is drawn as a ring filled with the PAPER colour, which on ink is a bright disc where a
   hole should be - it takes the room's own ground instead. */
:where(.sl-body).refine-editorial-ivory .ed.bk-home section.bk-tl .bk-dot {
  background: var(--bk-dark, var(--c-hero-plate));
}
/* every hairline in the band was drawn for ink-on-paper and vanishes on ink */
:where(.sl-body).refine-editorial-ivory .ed.bk-home section.bk-tl :is(.bk-step, :where(.sl-body) .bk-step + .bk-step) {
  border-color: color-mix(in srgb, var(--c-on-dark) 22%, transparent);
}
:where(.sl-body).refine-editorial-ivory .ed.bk-home section.bk-tl .bk-detail {
  background: color-mix(in srgb, var(--c-surface) 8%, transparent);
  box-shadow: none;
}
:where(.sl-body).refine-editorial-ivory .ed.bk-home section.bk-tl .bk-detail :is(small, :where(.sl-body) p) { color: var(--c-on-dark); }
/* the row's height is set by its photograph, and the copy is shorter than the picture - so each
   step left roughly 200px of bare navy under two lines of text and the band ran on. Centring the
   copy against the picture it belongs to closes the gap without taking any air out of the rhythm
   between steps. */
:where(.sl-body).refine-editorial-ivory .ed.bk-home section.bk-tl .bk-step { align-items: center; margin-bottom: 56px; }

/* 12. A ROW OF PRODUCTS SHARES A BASELINE. The names run one to three lines, so the prices under
       them landed at three different heights across a row of four and the grid read ragged — the
       opposite of the editorial restraint this lane is for. Reserving two lines for the name puts
       every price on the same line without touching the block's markup. */
/* RESERVING THREE LINES ONLY MAKES SENSE WHERE THE NAMES SIT SIDE BY SIDE. Across a row of four,
   names run one to three lines and the prices under them landed at three different heights, so the
   block reserves the tallest. Stacked one per column on a narrow screen there is nothing to line up
   with, and the reservation is just a hole between the name and the price - two blank lines under
   "B12 Shot". Held to the widths where the row actually is a row. */
@media (min-width: 601px) {
  :where(.sl-body).refine-editorial-ivory .bk-pname { min-height: 3.2em; }
}
:where(.sl-body).refine-editorial-ivory .bk-pamt { white-space: nowrap; }

/* 13. THE FEATURED GROUP TIER, corrected. The class the block actually emits is `.bk-feat`, and
       the block's own CSS assumes that card sits on a DARK ground — it sets the small print to
       60% white. On a lane that never darkened it, "15% off the booking" was near-white type on
       cream. Painting the card ink makes the block's own assumption true and gives the tier row
       its one accent. Gold on ink is 6.61:1; the ink label on the gold pill is the pairing the
       brand book asks for in so many words. */
:where(.sl-body).refine-editorial-ivory .bk-tier.bk-feat {
  background: var(--bk-dark, var(--c-hero-plate));
  border-top-color: var(--c-accent);
}
:where(.sl-body).refine-editorial-ivory .bk-tier.bk-feat .bk-tier-name, :where(.sl-body).refine-editorial-ivory .bk-tier.bk-feat .bk-desc, :where(.sl-body).refine-editorial-ivory .bk-tier.bk-feat li { color: var(--c-on-dark); }
:where(.sl-body).refine-editorial-ivory .bk-tier.bk-feat .bk-price { color: var(--c-accent); }
:where(.sl-body).refine-editorial-ivory .bk-tier.bk-feat li::before { color: var(--c-accent); background: none; }
:where(.sl-body).refine-editorial-ivory .bk-pill-accent {
  background: var(--c-accent);
  color: var(--c-primary-dark);
  border: 1px solid var(--c-accent);
}

/* 14. THE INK ROOM'S HEADING HAS TO BE READ. A block's \3c style> block is scoped by Astro, so
       `.bk-cities h2` ships as `.bk-cities h2[data-astro-cid-…]` — (0,2,1), a tie with a plain
       lane rule, decided by source order, which the lane loses. So the heading kept the block's
       `color: var(--bk-primary)` and rendered navy on navy: measured 1.06:1, invisible. Raising
       the lane's specificity with the body class plus the section class settles it. Any lane rule
       that must beat a block's own scoped CSS needs the same shape. */
:where(.sl-body).refine-editorial-ivory .ed.bk-home section.bk-cities h2, :where(.sl-body).refine-editorial-ivory .ed.bk-home section.bk-cities h3{ color: var(--c-on-dark); }
:where(.sl-body).refine-editorial-ivory .ed.bk-home section.bk-cities .bk-cities-body, :where(.sl-body).refine-editorial-ivory .ed.bk-home section.bk-cities p { color: color-mix(in srgb, var(--c-surface) 88%, transparent); }
:where(.sl-body).refine-editorial-ivory .ed.bk-home section.bk-cities .bk-eyebrow-caps { color: var(--c-accent); }
:where(.sl-body).refine-editorial-ivory .ed.bk-home section.bk-cities .bk-cities-hours b, :where(.sl-body).refine-editorial-ivory .ed.bk-home section.bk-cities a, :where(.sl-body).refine-editorial-ivory .ed.bk-home section.bk-cities b { color: var(--c-accent); }
:where(.sl-body).refine-editorial-ivory .ed.bk-home section.bk-cities .bk-city {
  background: transparent;
  border-color: color-mix(in srgb, var(--c-accent) 46%, transparent);
  color: var(--c-on-dark);
}

/* 15. TWO REAL CONTRAST FAILURES, FOUND BY MEASURING EVERY TEXT NODE ON THE BUILT PAGE RATHER
       THAN BY EYE. Both are small type, which is where a pale palette bites and where a
       screenshot review will not catch it.
       - The step numeral was set at 62% of accent-ink and measured 2.78:1 against the cream,
         under the 3.0 a 32px numeral needs. 82% takes it to 4.1:1 and still reads as a quiet
         numeral rather than a heading.
       - The product micro-note ships as a hardcoded cool grey #6f7a80, which measures 3.38:1 on
         the ivory band and 3.77:1 on the cream — under 4.5:1 at 12.5px either way. It is also a
         COLD grey on a warm page, which is its own problem. Mixing it from the brand's own ink
         fixes both at once: measured 7.4:1 on ivory, 8.2:1 on cream. */
:where(.sl-body).refine-editorial-ivory .bk-no{ color: color-mix(in srgb, var(--c-accent-ink) 82%, transparent); }
:where(.sl-body).refine-editorial-ivory .bk-pmicro, :where(.sl-body).refine-editorial-ivory .bk-desc, :where(.sl-body).refine-editorial-ivory .bk-tiers-sub { color: color-mix(in srgb, var(--c-text) 78%, transparent); }
:where(.sl-body).refine-editorial-ivory .bk-tier.bk-feat .bk-desc { color: color-mix(in srgb, var(--c-surface) 86%, transparent); }

/* 16. THE ROOM RE-DECLARES ITS CTA INK, RATHER THAN EACH BUTTON IN IT.
       "Call Us" measured 1.15:1 — navy on navy — on five interior pages. Chasing it button by
       button was the wrong move: the renderer ALREADY has one rule for this,
       `.final-cta .btn-secondary { color: var(--c-cta-text, var(--c-surface)) }`, and the token
       was simply wrong for the new ground. brand.ts derives --c-cta-text from the CTA background
       the BRAND declares (gold, so navy ink is correct there); this lane then repaints the band
       ink, and nothing told the token. Setting the pair on the room itself fixes every control
       inside it at once — buttons, links and anything added later — instead of one selector per
       control. One decision, one home. */
:where(.sl-body).refine-editorial-ivory .sec-room, :where(.sl-body).refine-editorial-ivory .final-cta, :where(.sl-body).refine-editorial-ivory .bk-cities {
  /* THE INK THAT READS ON THE ACCENT, not the ink that reads on the dark primary.
     This paired a gold ground with cream type: measured 1.92:1 on Nevue's call to action, which
     visual-lint calls EFFECTIVELY INVISIBLE. It stayed hidden because the hub route had no brand
     token host, so those pages fell back to the dark primary and looked fine; the moment the hub
     got its skin (familySkin.ts) the real pairing showed up on ten pages at once.
     `--c-accent-on` is derived per brand for exactly this question — for this gold it resolves to
     #1a1a2e and measures 7.62:1. The fallback keeps any brand without it on today's behaviour. */
  --c-cta-text: var(--c-accent-on, var(--c-on-dark));
  --c-cta-bg: var(--c-accent);
}

/* 17. THE BRAND OWNS ITS WEIGHT AND ITS TRACKING. THE BLOCK OWNS EVERYTHING ELSE.
       Névue's brief is explicit about both, and about why: "High contrast serif for display
       headings at LIGHT weight", "Wide letter spacing on eyebrow text, nav, and buttons", and
       "Finer and thinner weights than a standard wellness site, which is where most of the luxury
       signal comes from."

       Measured on the live page before this rule: h1 at font-weight 500 and letter-spacing
       -2.76px; h2 at 500 and -1.6px; the nav at letter-spacing normal. Heavier and tighter than
       asked for, on the two axes the client named as the whole point.

       The cause is not the lane being wrong - it says 400 and +0.005em twenty lines up. It is that
       sixty separate `font-weight: 500` declarations and twelve negative letter-spacings live
       inside the blocks, and Astro scopes each one with a [data-astro-cid] attribute, which
       outranks any page-level selector. Exactly the same collision the alignment rules hit, and
       this file already answers it in those words: "!important for the same reason the type scale
       needs it ... The PAGE owns where a band's title sits; the block owns how it looks."
       Weight and tracking are the brand's, not the block's, so they are claimed the same way.

       Deliberately narrow: two properties, on headings and on the small tracked labels. Every
       other typographic decision stays with the block. */
:where(.sl-body).refine-editorial-ivory :is(h1, :where(.sl-body) h2, :where(.sl-body) h3, :where(.sl-body) h4) {
  font-weight: 400 !important;
}
:where(.sl-body).refine-editorial-ivory :is(h1, :where(.sl-body) h2) {
  letter-spacing: 0.005em !important;
}
:where(.sl-body).refine-editorial-ivory :is(h3, :where(.sl-body) h4) {
  letter-spacing: 0.01em !important;
}
/* Wide tracking is the other half of the same sentence, and it belongs on the SMALL type: the
   eyebrows, the nav and the buttons. Not on the headlines, which the brief wants near-neutral. */
:where(.sl-body).refine-editorial-ivory :is(.ed-links a, :where(.sl-body) .ed-nav a, :where(.sl-body) nav a) {
  letter-spacing: 0.14em !important;
  font-weight: 400 !important;
  text-transform: uppercase;
  font-size: 0.72rem;
}
:where(.sl-body).refine-editorial-ivory :is(.bk-pill, :where(.sl-body) .bk-btn, :where(.sl-body) .btn, :where(.sl-body) .ed-pill, :where(.sl-body) .bk-pbtn) {
  letter-spacing: 0.16em !important;
  font-weight: 500 !important;
}
:where(.sl-body).refine-editorial-ivory :is(.bk-eyebrow-caps, :where(.sl-body) .ed-eyebrow, :where(.sl-body) .eyebrow, :where(.sl-body) .bk-close-eyebrow, :where(.sl-body) .bk-pinc) {
  letter-spacing: 0.22em !important;
  font-weight: 500 !important;
}

/* 18. TWO INK ROOMS NEVER RUN TOGETHER - AND NOT ONLY IN THIS LANE. This lane carried the whole of
       that rule, by name, from the day it was written: `.sec-room + .final-cta` yields to paper,
       takes the page ink with it, and re-inks both buttons. It was right, and it was the only
       place in the file that said so, while the two paints it corrects - the ink-room paint and the
       base `.final-cta` - are shared by every lane. Every other lane therefore closed its
       listing and hub pages on a dark room stacked straight onto a dark band, 521 pages of it.
       The rule now lives with those two paints, unscoped, in the STRICT ALTERNATION block. Nothing changed for this
       lane; the block was deleted rather than left as a second copy of a decision with one home. */

/* 19. WHAT LOOKING AT IT IN A BROWSER FOUND, THAT NINETEEN GATES DID NOT.
       Every item below was measured green by the chain and is plainly wrong on screen. */

/* 19a. THE HEADLINE WAS SIZED AGAINST THE SCREEN AND SET IN A COLUMN. The hero is a two-track
        grid - copy on the left, picture in a 624px track on the right - so at a 1400px window the
        copy gets about 438px. The display size was clamp(2.85rem, 6vw, 5.1rem), which is 82px
        there, and "Mobile IV Therapy Across Tampa Bay" came down the page in FIVE lines, one or
        two words each. Generous size is in the brief; five lines of stacked fragments is not what
        it means. Sized to the track it actually lives in. */
/* The block sets its own `clamp(44px, 6.4vw, 92px)` through Astro's scoped selector, which is a
   class more specific than a plain lane rule, so the first version of this changed nothing at all.
   The lane class is repeated to clear it. 92px in a 436px column is five lines; ~49px is two. */
:where(.sl-body).refine-editorial-ivory.refine-editorial-ivory .bk-split h1, :where(.sl-body).refine-editorial-ivory.refine-editorial-ivory .hero h1, :where(.sl-body).refine-editorial-ivory.refine-editorial-ivory .hero-title {
  font-size: clamp(2.3rem, 3.4vw, 3.75rem) !important;
  /* 1.04 was set for a headline measured in caps. This face has long descenders, so on a
     three-line headline the y of "Therapy" ran into the T of "Tampa" on the line below - two
     words touching reads as broken type, not as tight type. 1.1 keeps the block tight and lets
     the descenders finish. */
  line-height: 1.1;
}

/* 19b. ALL CAPS IS FOR SMALL LABELS, NEVER FOR HEADLINES - the brief says exactly that, and three
        bands broke it: "EIGHT DRIPS.", "EIGHT ADD-ONS.", "SEVEN AREAS ACROSS TAMPA BAY.". Caps on
        a high-contrast Didone at 46px is also where it stops looking like a display face and
        starts looking like a stone inscription, which is part of why the type read wrong. */
:where(.sl-body).refine-editorial-ivory .ed.bk-home :is(.bk-plinths, :where(.sl-body) .bk-cities, :where(.sl-body) .bk-tiers, :where(.sl-body) .bk-pillars, :where(.sl-body) .bk-tl) h2 {
  text-transform: none !important;
}

/* 19c. ONE ALIGNMENT PER BAND - AND THE PAGE PICKS THE DIRECTION, NOT THE BAND.
        The coverage band centred its title and then ranged its body, its hours and its phone
        number left; the contact band centred "Book a visit." over an email, a phone number and a
        button that all started at the left. Two bands, three edges each, and both plainly wrong on
        screen.
        The first attempt left-aligned those two bands to match their content - and G2 refused the
        build: six centred bands against two left-aligned ones is precisely the "one page grid"
        fault, and the gate was right. This page is centred, so the stragglers come to the page
        rather than the page bending to them. */
:where(.sl-body).refine-editorial-ivory .ed.bk-home :is(section.bk-cities, :where(.sl-body) section.bk-contact) :is(p, :where(.sl-body) ul, :where(.sl-body) ol, :where(.sl-body) .bk-cities-hours, :where(.sl-body) .bk-contact-lines, :where(.sl-body) .bk-close-ctas) {
  text-align: center;
  margin-inline: auto;
}
:where(.sl-body).refine-editorial-ivory .ed.bk-home :is(section.bk-cities, :where(.sl-body) section.bk-contact) :is(.bk-citygrid, :where(.sl-body) .bk-contact-ctas, :where(.sl-body) .bk-pill, :where(.sl-body) .bk-btn) {
  justify-content: center;
}
:where(.sl-body).refine-editorial-ivory .ed.bk-home section.bk-contact :is(a[href^="mailto"], :where(.sl-body) a[href^="tel"]) {
  display: block;
  text-align: center;
}
/* The booking button sits in an unclassed div, so it kept ranging left under centred copy - the
   last edge left over in this band. */
:where(.sl-body).refine-editorial-ivory .ed.bk-home section.bk-contact > div > div { text-align: center; }

/* 19d. A ROW OF PRICES SHARES A LINE. Reserving 3.2em for the name was measured against a
        two-line name; "MEGA MYERS COCKTAIL IV" and "ANTI-INFLAMMATORY PAIN RELIEF" take three at
        card width, so their prices dropped half a line below their neighbours' across a row of
        four. 3.9em covers three lines of the 25px card face at its 1.14 leading. */
@media (min-width: 601px) {
  :where(.sl-body).refine-editorial-ivory .bk-pname { min-height: 3.9em; }
}

/* 19f. THREE CARDS IN A ROW START THEIR COPY ON ONE LINE. "The price on the page is the price"
   wraps to two lines and its two neighbours do not, so the body copy under the first card began
   20px lower than the other two and the row read as misaligned rather than as three equal claims.
   Same fix as the product names in 19d: reserve the taller of the two heights so every title
   occupies the same block. Above the tablet cliff only - stacked, they follow each other. */
@media (min-width: 901px) {
  :where(.sl-body).refine-editorial-ivory .bk-pillar h3 { min-height: 2.4em; }
}
/* 19e. THE TICKER STARTED MID-WORD. Its track begins at the page's left edge, so the first item
        was already half scrolled past before the strip had said anything - it read as a rendering
        fault rather than as motion. A fade at each end makes the same strip read as continuous. */
:where(.sl-body).refine-editorial-ivory .bk-ticker {
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 8%, #000 92%, transparent 100%);
  mask-image: linear-gradient(90deg, transparent 0, #000 8%, #000 92%, transparent 100%);
}

/* ══ DESIGN LANE: warm-studio ═════════════════════════════════════════════════════════════════
   BOUTIQUE, PERSONAL, SUNLIT. Specified in DESIGN-LANES.md the day the lane library was written
   ("build order #3: humanist sans + serif accents; soft radius, tinted alternating bands,
   generous air") and never built. Every one of the eight lanes that DID get built is cool,
   expensive and restrained: two dark rooms, three porcelains, an ivory, an estate and a spa. A
   client whose whole brief is "cheerful, not childish - we want people to smile at the van" has
   nothing in the library to wear, and the lane census is right to refuse to hand them a lane
   another client in the same vertical is already wearing.

   THE DEVICE IS THE SHOULDER. Every card, panel, tile and pill takes three soft corners and one
   squared one, bottom-left. Nothing else in the fleet has it; it survives at squint distance,
   which is what makes a lane a lane rather than a palette; and it costs one property. It is the
   same discipline pill-porcelain uses with the speech bubble - one shape, applied everywhere.

   SEPARATION IS BY STOCK, NOT BY ELEVATION. Cards are warm tinted panels standing on paper with
   no border and no shadow at all. That is the opposite of the default look (white cards floating
   on drop shadows) and the opposite of editorial-ivory (borderless, hairline-ruled). Three lanes,
   three different answers to the same question, which is the point of a library.

   CONTRAST, MEASURED, and it is why this lane never sets a raw accent as a foreground. The brand
   it was authored against runs a warm orange #E8792B: 2.85:1 on white and 2.71:1 on the warm
   tint - it cannot carry text, a hairline that must be seen, or an underline, on any light
   ground. So the raw accent is used for FILLS and for large display figures only, and anything
   the size of running text that wants to read as the accent uses --c-accent-ink, which brand.ts
   derives by mixing the accent toward ink until it clears AA on the darkest light surface (on
   this palette ~#A65E28, 4.62:1 on white). White on the raw orange is 3.68:1, so a filled orange
   button sets its label at 1.0625rem/700 - bold over 18.66px is WCAG large text, where the
   threshold is 3.0 - and never smaller. Deep teal #0E6E6B on white is 5.68:1 and white on it is
   5.68:1, so the primary carries text freely in both directions.

   BOTH ALTERNATING BEATS ARE DECLARED (section 1). A lane that paints only the tinted beat makes
   a brand whose default ground IS a tint alternate tint-with-tint, and page-rules P3 refuses it.
   That has been paid for twice in this stylesheet; it is written out explicitly here.

   AND IT DRESSES BOTH RENDERERS (sections 8-10). Everything before section 8 targets the interior
   route, which speaks in `.section`, `.card`, `.btn`. A brand carrying a page_template never calls
   that file on its HOME page - the one page every visitor sees - which draws through a blueprint
   template speaking in `.bk-*` and its family's own chrome. A lane that stops at section 7 dresses
   the least-read half of the site.

   ── T6. A LANE MAY REMOVE A SHADOW. IT MAY NOT REMOVE A BORDER THAT HAPPENS TO BE DRAWN WITH ONE.
   ────────────────────────────────────────────────────────────────────────────────────────────────
   This is the sixth trap and it is the one that has now been paid for twice, so it is written out
   here with the other five rather than left as a paragraph inside one lane.

   TWENTY BLOCKS under src/components/blocks draw an OUTLINED button's outline as
   `box-shadow: inset 0 0 0 1.5px <ink>` rather than as `border`, because an inset ring costs no
   layout: it does not change the control's box, so an outlined pill and a filled pill of the same
   text sit at exactly the same height in the same row. That is a good decision and it is not going
   to be undone.

   It means the word `box-shadow` on a control means TWO different things. On a filled button it is
   a drop shadow — decoration, and dropping it is exactly what "this design carries no elevation"
   is entitled to say. On `.bk-pill-ghost`, `.bk-pill-outline` and `.bk-btn-ghost` it is the ENTIRE
   AFFORDANCE: delete it and the control has no outline, no fill, no underline and no border, and
   what is left is a word floating on a band that nobody can tell is a button. That is what shipped
   on the home page of four sample brands — including a page that outlines its decorative condition
   chips (drawn with a real `border`, which no lane touches) and leaves its ONLY booking action
   undrawn directly beneath them.

   THE HOUSE FORM, and every lane on the shelf now uses it:

       body.refine-<lane> :is(.bk-btn, .bk-pill, .bk-chip, .bk-city, .bk-ict-pill, .bk-prose-pill)
         :not(:where(.bk-pill-ghost, .bk-pill-outline, .bk-btn-ghost)) { box-shadow: none; }

   `:where()` is load-bearing and not stylistic. A bare `:not(.bk-pill-ghost)` chain would raise the
   rule from (0,2,1) to (0,5,1) and win against `.bk-home .bk-nopic-ink .bk-pill-fill` at (0,3,0) —
   which is ANOTHER border drawn as an inset ring — reintroducing the identical bug one selector
   over. `:where()` contributes zero specificity, so `:not(:where(…))` narrows what the rule
   matches and changes nothing about what it outranks. The reset lands on precisely the controls it
   was written for and on nothing else.

   AND THE EXCLUSION IS PREFERRED TO RESTATING THE RING. `refine-estate` and `refine-dark-luxe`
   solve this the other way, by re-drawing the ghost as `inset 0 0 0 1px currentColor`. That works,
   but it is the lane deciding what the control looks like on a ground the lane does not paint —
   the ConditionsPanel ghost's ring is white at 80% against a specific dark band, and SplitHero's
   is a near-invisible hairline against white, and those are the blocks' decisions. Excluding is
   shape-only in the strictest sense: the lane still sets the corner on every control, and the ring
   the block chose survives untouched.

   scripts/ghost-ring.mjs enforces this against the whole shelf on every check run. It reads which
   classes the blocks actually draw as rings, so a new ring-drawn control is covered the day it is
   written, without anyone remembering this note. ═══════════════════════════════════════════════
   @lane warm-studio | boutique and sunlit: filled panels, one squared corner, generous air | suits: warm boutique personal sunlit cheerful friendly local hospitable inviting
   */
:where(.sl-body).refine-warm-studio {
  /* THE SHOULDER, as a token, so every rule below states the device once and reads it everywhere. */
  --ws-shoulder: 20px 20px 20px 4px;
  --ws-shoulder-sm: 14px 14px 14px 3px;
  --card-radius: 20px;
  --btn-radius: 14px;
  --input-radius: 14px;
  /* No elevation anywhere. Separation is a change of stock. */
  --card-shadow: none;
  --card-hover-shadow: none;
  --card-border-width: 0;
  /* The warm panel every card stands on, mixed from the brand's own accent so it is this client's
     warmth and not a hardcoded cream. */
  --ws-panel: color-mix(in srgb, var(--c-accent) 7%, var(--c-surface));
  --ws-panel-deep: color-mix(in srgb, var(--c-accent) 13%, var(--c-surface));
  --ws-rule: color-mix(in srgb, var(--c-primary) 18%, transparent);
  /* Generous air is half the identity: 96px on a phone, 152px on a desktop. */
  --ws-air: clamp(6rem, 9.5vw, 9.5rem);
  --ws-ease: 180ms cubic-bezier(.22, .61, .36, 1);
}

/* 1. SURFACES. Both beats named. Paper and a warm tint, alternating, with no rule between them -
      the change of stock is the divider, the same argument pill-porcelain makes with Mist. */
:where(.sl-body).refine-warm-studio { background: var(--c-surface); }
:where(.sl-body).refine-warm-studio.sections-alternate main > section.section:nth-of-type(odd):not(.sec-room):not(.final-cta):not(.section-hub-cta) {
  background: var(--c-surface);
}
:where(.sl-body).refine-warm-studio.sections-alternate main > section.section:nth-of-type(even):not(.sec-room):not(.final-cta):not(.section-hub-cta) {
  background: var(--ws-panel);
}
:where(.sl-body).refine-warm-studio.bands-paper main > section.section:nth-of-type(odd):not(.sec-room):not(.final-cta):not(.section-hub-cta) {
  background: var(--c-surface);
}
:where(.sl-body).refine-warm-studio.bands-paper main > section.section:nth-of-type(even):not(.sec-room):not(.final-cta):not(.section-hub-cta) {
  background: var(--ws-panel);
}
:where(.sl-body).refine-warm-studio .section + .section { border-top: 0; }
/* GENEROUS AIR, the second half of the identity. */
:where(.sl-body).refine-warm-studio main > section.section {
  padding-top: var(--ws-air);
  padding-bottom: var(--ws-air);
}

/* 2. TYPE. Humanist and warm rather than editorial and cold: headings sit slightly tighter than
      the house scale, and eyebrows are small caps with real tracking. The lane sets no font
      FAMILY - that is the brand's, and a lane that overrides it overrides a decision somebody
      made about this client. */
:where(.sl-body).refine-warm-studio h1, :where(.sl-body).refine-warm-studio h2, :where(.sl-body).refine-warm-studio h3 {
  letter-spacing: -0.015em;
  line-height: 1.12;
  text-wrap: balance;
}
/* AND IT SETS NO COLOUR HERE, which cost this lane its first build. The obvious rule was
   `color: var(--c-accent-ink)` - the accent darkened until it clears AA on a LIGHT ground - and it
   is correct on every light band and wrong on every dark one, where the right token is
   --c-accent-ink-dark. At (0,2,1) it outranks the ground-aware rules that already know which of
   the two applies, so the eyebrow on the dark hero came out at 1.29:1: the warm brown on the deep
   teal, invisible. The rule this repo already writes out at :7330 in the other direction is the
   same rule: a lane may shape a control, it may not colour one whose ground it does not own. */
:where(.sl-body).refine-warm-studio .eyebrow, :where(.sl-body).refine-warm-studio .bk-eyebrow-caps {
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-size: 0.78rem;
  font-weight: 700;
}
/* THE UNDERLINE IS A SHORT RULE, NOT A CHIP. Every other light lane in the library either boxes
   its eyebrow (pill-porcelain) or leaves it bare (ivory, porcelain). A 34px accent rule under the
   SECTION HEADING is a third answer, and it reads at squint distance. */
:where(.sl-body).refine-warm-studio .section-header h2::after {
  content: "";
  display: block;
  width: 34px;
  height: 3px;
  margin: 0.85rem 0 0;
  border-radius: 2px;
  background: var(--c-accent);
}

/* 3. CARDS ARE PANELS. Filled, shouldered, borderless, unelevated. */
:where(.sl-body).refine-warm-studio .card, :where(.sl-body).refine-warm-studio .feature-card, :where(.sl-body).refine-warm-studio .cat-card, :where(.sl-body).refine-warm-studio .tier-card:not(.tier-featured), :where(.sl-body).refine-warm-studio .review-card, :where(.sl-body).refine-warm-studio .step-card, :where(.sl-body).refine-warm-studio .faq-item {
  background: var(--ws-panel);
  border: 0;
  border-radius: var(--ws-shoulder);
  box-shadow: none;
  transition: background var(--ws-ease);
}
:where(.sl-body).refine-warm-studio .card:hover, :where(.sl-body).refine-warm-studio .feature-card:hover, :where(.sl-body).refine-warm-studio .cat-card:hover, :where(.sl-body).refine-warm-studio .tier-card:not(.tier-featured):hover {
  background: var(--ws-panel-deep);
  transform: none;
  box-shadow: none;
}
/* A card standing ON the tinted beat needs paper, or it disappears into its band. */
:where(.sl-body).refine-warm-studio main > section.section:nth-of-type(even) :is(.card, :where(.sl-body) .feature-card, :where(.sl-body) .cat-card, :where(.sl-body) .review-card, :where(.sl-body) .step-card, :where(.sl-body) .faq-item) {
  background: var(--c-surface);
}

/* 4. BUTTONS. Shouldered, and the filled one is a large-text button by construction - the raw
      accent measures 3.68:1 against white, which is legal at bold 18.66px and illegal below it. */
:where(.sl-body).refine-warm-studio .btn, :where(.sl-body).refine-warm-studio .btn-primary, :where(.sl-body).refine-warm-studio .btn-secondary {
  border-radius: var(--ws-shoulder-sm);
  font-weight: 700;
  letter-spacing: 0.005em;
  transition: background var(--ws-ease), color var(--ws-ease);
}
:where(.sl-body).refine-warm-studio .btn-primary {
  font-size: 1.0625rem;
  box-shadow: none;
}
:where(.sl-body).refine-warm-studio .btn-primary:hover { box-shadow: none; }
:where(.sl-body).refine-warm-studio .btn-secondary {
  background: transparent;
  border: 1.5px solid var(--ws-rule);
  font-size: 1rem;
}
:where(.sl-body).refine-warm-studio .btn-secondary:hover {
  background: var(--ws-panel);
  border-color: var(--c-primary);
}

/* 5. THE FAQ IS A LANE SURFACE TOO. DESIGN-LANES.md's definition of done names `faq` and
      `policy_expand` explicitly, because they are the two every lane forgets. */
:where(.sl-body).refine-warm-studio .faq-item + .faq-item { margin-top: 0.75rem; }
:where(.sl-body).refine-warm-studio .faq-item summary, :where(.sl-body).refine-warm-studio .faq-list summary {
  font-weight: 700;
  padding: 1.15rem 1.35rem;
}
:where(.sl-body).refine-warm-studio .faq-item[open] { background: var(--ws-panel-deep); }

/* 6. IMAGERY IS SHOULDERED, which carries the device onto the photographic half of a page rather
      than leaving it a card-only trick. */
:where(.sl-body).refine-warm-studio .section figure img, :where(.sl-body).refine-warm-studio .section figure {
  border-radius: var(--ws-shoulder);
}

/* 7. THE DARK MOMENTS, AND THE ONE THIS LANE IS NOT ALLOWED TO CHOOSE. This lane has almost none
      by design - it is a daylight lane. The obvious rule was to paint the closing band in the brand
      primary, and it refused five listing pages on the first build: a hub page ends with an ink
      ROOM already painted the brand primary, and the closing band lands directly underneath it, so
      the page finished with the same colour twice and no seam between them. The system already
      decides what the closing band is; the lane leaves it alone. */
/* The same guard dark-luxe, luxe-noir and clinical-porcelain all carry: without it a lane's
   (0,2,1) rule outranks the light map compositions and buries their ink. */
:where(.sl-body).refine-warm-studio:not(.map-index):not(.map-panel) main > section.section.section-service_area_map {
  background: var(--c-room) !important;
}

/* ── 8. THE BLOCK LIBRARY. Everything above speaks in `.section`/`.card`/`.btn` and none of it
      reaches a blueprint home page, which draws through `.bk-*`. Restated in that vocabulary. */
:where(.sl-body).refine-warm-studio .bk-card, :where(.sl-body).refine-warm-studio .bk-pillar, :where(.sl-body).refine-warm-studio .bk-pcard, :where(.sl-body).refine-warm-studio .bk-tier:not(.bk-feat), :where(.sl-body).refine-warm-studio .bk-step, :where(.sl-body).refine-warm-studio .bk-ccard, :where(.sl-body).refine-warm-studio .bk-ict-card, :where(.sl-body).refine-warm-studio .bk-fcard, :where(.sl-body).refine-warm-studio .bk-credcard, :where(.sl-body).refine-warm-studio .bk-grev-card {
  background: var(--ws-panel);
  border: 0;
  border-radius: var(--ws-shoulder);
  box-shadow: none;
}
:where(.sl-body).refine-warm-studio .bk-card:hover, :where(.sl-body).refine-warm-studio .bk-pillar:hover, :where(.sl-body).refine-warm-studio .bk-pcard:hover, :where(.sl-body).refine-warm-studio .bk-tier:not(.bk-feat):hover, :where(.sl-body).refine-warm-studio .bk-fcard:hover {
  background: var(--ws-panel-deep);
  transform: none;
  box-shadow: none;
}
/* A block card standing on the tinted beat flips to paper, same argument as section 3. */
/* The `.bk-band.bk-tint` pairing this rule used to name is emitted by nothing: `bk-tint` is a
   TOKEN name (`--bk-tint`), not a class. The rule was dead, and the case it was written for — a
   filled card disappearing into a tinted band — is handled by the ground-aware beat above. */
/* The product plinth ships a cold near-white panel; on a warm page that reads as a second paper
   stock inside the first. Same finding editorial-ivory records, different answer: a warm panel
   rather than none, because this lane's cards are filled. */
:where(.sl-body).refine-warm-studio .bk-plinth {
  background: var(--ws-panel);
  border-radius: var(--ws-shoulder);
  box-shadow: none;
}
:where(.sl-body).refine-warm-studio .bk-btn, :where(.sl-body).refine-warm-studio .bk-pill, :where(.sl-body).refine-warm-studio .bk-chip, :where(.sl-body).refine-warm-studio .bk-city, :where(.sl-body).refine-warm-studio .bk-ict-pill, :where(.sl-body).refine-warm-studio .bk-prose-pill {
  border-radius: var(--ws-shoulder-sm);
  font-weight: 700;
}
:where(.sl-body).refine-warm-studio .bk-pill-fill, :where(.sl-body).refine-warm-studio .bk-btn-fill { font-size: 1.0625rem; box-shadow: none; }
:where(.sl-body).refine-warm-studio .bk-step-art img, :where(.sl-body).refine-warm-studio .bk-prose-photo img, :where(.sl-body).refine-warm-studio .bk-cond-ph img, :where(.sl-body).refine-warm-studio .bk-tiers-art img {
  border-radius: var(--ws-shoulder);
}
/* THE FEATURED TIER GETS THE SHOULDER AND NOTHING ELSE. Repainting its plate in the brand primary
   was this lane's second contrast failure in one build: the plate changed, the tier name kept the
   light-ground accent ink the block sets, and the name measured 1.03:1 on the new teal. The plate
   and its ink are ONE decision and they live in the block; a lane that takes half of it takes the
   half that cannot be read. Shape is the lane's to change, colour is not. */
:where(.sl-body).refine-warm-studio .bk-tier.bk-feat { border-radius: var(--ws-shoulder); }

/* ── 9. THE RETAIL FAMILY'S OWN CHROME. A blueprint home draws its nav, hero, FAQ and closing band
      from the family template, not from the block library, so those are untouched by section 8.
      This is the family the lane was authored against. */
/* No ground here either, for the reason written beside the block-poster nav below: the family
   picks the bar's ground and its logo ink to match. Harmless on this family, whose bar is already
   paper — and exactly the fault that refused a build one lane later. */
:where(.sl-body).refine-warm-studio .rt-nav { border-bottom: 1px solid var(--ws-rule); }
:where(.sl-body).refine-warm-studio .rt-pill { border-radius: var(--ws-shoulder-sm); font-weight: 700; }
:where(.sl-body).refine-warm-studio .rt-fill { font-size: 1.0625rem; box-shadow: none; }
:where(.sl-body).refine-warm-studio .rt-outline { border-width: 1.5px; }
:where(.sl-body).refine-warm-studio .rt-hero-art img { border-radius: var(--ws-shoulder); }
/* THE ROW IS THE SUMMARY, NOT THE DISCLOSURE AROUND IT. Painting `.rt-qd` put a cream plate behind
   a summary that already carries its own fill and its own 12px bottom margin, so every question
   shipped as a pale box floating on a slightly darker box with a cream strip showing under it - a
   double border nobody drew. The family's row IS `.rt-q`; that is the thing to dress. */
:where(.sl-body).refine-warm-studio .rt-q, :where(.sl-body).refine-warm-studio .rt-q-flat {
  background: var(--ws-panel);
  border: 0;
  border-radius: var(--ws-shoulder);
  box-shadow: none;
}
:where(.sl-body).refine-warm-studio .rt-qd[open] .rt-q { background: var(--ws-panel-deep); }
:where(.sl-body).refine-warm-studio .rt-announce { letter-spacing: 0.06em; font-weight: 700; }

/* ── 10. THE OTHER FOUR FAMILIES' CHROME, one rule each, so a second client can wear this lane on
      a different design without their home page falling back to the default look. This is the
      reach lesson from editorial-ivory, applied ahead of the fault rather than after it. */
:where(.sl-body).refine-warm-studio :is(.ed-nav, :where(.sl-body) .bh-nav, :where(.sl-body) .et-nav, :where(.sl-body) .cm-nav, :where(.sl-body) .bl-nav) { border-bottom: 1px solid var(--ws-rule); }
:where(.sl-body).refine-warm-studio :is(.ed-pill, :where(.sl-body) .bh-pill, :where(.sl-body) .et-btn, :where(.sl-body) .cm-book, :where(.sl-body) .bl-pill) {
  border-radius: var(--ws-shoulder-sm);
  font-weight: 700;
}

/* ══ DESIGN LANE: block-poster ════════════════════════════════════════════════════════════════
   FLAT, BLOCKY, UNORNAMENTED. The register the library still had nothing in. Nine lanes exist and
   every one of them is either an evening room (luxe-noir, dark-luxe, estate) or a pale refined
   paper (clinical-porcelain, pill-porcelain, editorial-ivory, spa-luxe, warm-studio). A client
   whose brief says "plain-spoken, local, explicitly NOT a spa and NOT luxury" has nothing to wear,
   and the lane census is right to refuse to hand them a lane another client in this vertical is
   already wearing.

   THE DEVICE IS THE BAR. Every band heading carries a solid rule of brand colour above it, the
   full width of the heading's own column and six pixels deep — the way a poster or a printed
   timetable separates one block from the next. Nothing is rounded, nothing is elevated, nothing
   is tinted: a card is a rectangle with a one-pixel keyline, and the only fills on the page are
   the brand's two colours used at full strength. At squint distance the page reads as stacked
   blocks with hard edges, which no other lane in the library does.

   WHAT WARM-STUDIO PAID FOR, APPLIED HERE FIRST RATHER THAN AFTER. That lane was authored two
   hours before this one and its first build produced three contrast failures and five refused
   listing pages, all from the same four mistakes. They are written into its comments; this lane
   is built to avoid them from the start:
     1. A LANE SETS SHAPE, NOT A CONTROL'S INK. No `color:` on an eyebrow, a button or a heading
        whose ground this lane does not paint. The ground-aware rules already know which of
        --c-accent-ink and --c-accent-ink-dark applies; a lane rule outranks them and gets it wrong.
     2. A LANE DOES NOT REPAINT A PLATE IT WILL NOT ALSO RE-INK. `.bk-feat` is a dark plate with
        white type set in the block; the generic card rule below excludes it, and the shared guard
        restates it anyway.
     3. BOTH ALTERNATING BEATS ARE DECLARED. Painting only the tinted beat makes a brand whose
        default ground IS a tint alternate tint with tint, and page-rules P3 refuses the build.
     4. THE CLOSING BAND IS NOT THE LANE'S TO PAINT. A hub page ends with an ink ROOM and the
        closing band lands directly under it; painting both in the brand primary is the same colour
        twice with no seam, which refused five listing pages.
   And the fifth: a lane has to dress BOTH renderers (sections 7-9), or it dresses the interior
   pages and leaves the home page — the one page everybody sees — on the default look.

   CONTRAST, MEASURED. The brand it was authored against runs navy #1B4D8F and a warm yellow
   #F2B33D. Navy on white is 8.31:1 and white on navy is 8.31:1, so the primary carries type in
   both directions and is used for the bars, the keylines and the filled buttons. The yellow is
   1.98:1 on white — it cannot carry text on any light ground at any size, so it is used ONLY as a
   fill, and only under ink: #141A21 on #F2B33D is 11.4:1. Where something wants to READ as yellow
   it takes --c-accent-ink, which brand.ts darkens until it clears AA on the darkest light surface.
   ═══════════════════════════════════════════════════════════════════════════════════════════ 
   @lane block-poster | flat and blocky: square corners, keylines, a solid bar over every heading | suits: plain honest straightforward blocky bold value no-nonsense practical civic
   */
:where(.sl-body).refine-block-poster {
  /* Nothing is rounded. This is the whole silhouette. */
  --card-radius: 0px;
  --btn-radius: 0px;
  --input-radius: 0px;
  /* Nothing is elevated either: separation is a keyline or a change of stock. */
  --card-shadow: none;
  --card-hover-shadow: none;
  --card-border-width: 1px;
  --bp-rule: color-mix(in srgb, var(--c-primary) 22%, transparent);
  --bp-rule-hard: var(--c-primary);
  --bp-bar: 6px;
  --bp-air: clamp(4.5rem, 7vw, 7rem);
}

/* 1. SURFACES. BOTH BEATS NAMED (trap 3). Paper and the brand's own pale tint, alternating, with
      no rule between them — the change of stock is the divider. */
:where(.sl-body).refine-block-poster { background: var(--c-surface); }
:where(.sl-body).refine-block-poster.sections-alternate main > section.section:nth-of-type(odd):not(.sec-room):not(.final-cta):not(.section-hub-cta) {
  background: var(--c-surface);
}
:where(.sl-body).refine-block-poster.sections-alternate main > section.section:nth-of-type(even):not(.sec-room):not(.final-cta):not(.section-hub-cta) {
  background: var(--c-surface-alt);
}
:where(.sl-body).refine-block-poster.bands-paper main > section.section:nth-of-type(odd):not(.sec-room):not(.final-cta):not(.section-hub-cta) {
  background: var(--c-surface);
}
:where(.sl-body).refine-block-poster.bands-paper main > section.section:nth-of-type(even):not(.sec-room):not(.final-cta):not(.section-hub-cta) {
  background: var(--c-surface-alt);
}
:where(.sl-body).refine-block-poster .section + .section { border-top: 0; }
:where(.sl-body).refine-block-poster main > section.section {
  padding-top: var(--bp-air);
  padding-bottom: var(--bp-air);
}

/* 2. TYPE. Tight, heavy, square. No colour is set here — see trap 1. */
:where(.sl-body).refine-block-poster h1, :where(.sl-body).refine-block-poster h2, :where(.sl-body).refine-block-poster h3 {
  letter-spacing: -0.02em;
  line-height: 1.08;
  font-weight: 700;
  text-wrap: balance;
}
:where(.sl-body).refine-block-poster .eyebrow, :where(.sl-body).refine-block-poster .bk-eyebrow-caps {
  text-transform: uppercase;
  letter-spacing: 0.16em;
  font-size: 0.75rem;
  font-weight: 700;
}
/* THE BAR. A solid rule of brand colour over every band heading, which is this lane's signature
   and the thing a reader sees before they read a word. It is a BACKGROUND on a pseudo-element,
   never a colour on type, so trap 1 does not apply to it. */
:where(.sl-body).refine-block-poster .section-header h2::before, :where(.sl-body).refine-block-poster main section[class*="bk-"] > h2::before {
  content: "";
  display: block;
  width: 72px;
  height: var(--bp-bar);
  /* The house token for "this band is centred" - the same one the shelf uses at :162 - so the bar
     sits under the heading whichever way the band ranges. Written this way because the FIRST
     version of this rule named `.section-header` and `.bk-band` only, and the block library's
     headings are direct children of the block's own section (`.bk-bagrow > h2`), which is most of
     a blueprint home page. The lane's one signature device reached the interior pages and not the
     page everybody sees - the same half-a-renderer mistake, one round later. */
  margin: 0 0 1.1rem;
  margin-inline: var(--bk-mi, 0);
  /* THE BAR READS THE TITLE INK, NOT THE BRAND PRIMARY. Several blocks are dark BY CONSTRUCTION and
     ground themselves in that same primary — the frosted steps band is `background: var(--bk-primary)`
     with white type — so a bar painted in the primary is a bar you cannot see on them. `--bk-title-ink`
     is whatever the heading beside it is set in, which is the definition of a bar that always shows. */
  background: var(--bk-title-ink, var(--bp-rule-hard));
}

/* 3. CARDS ARE RECTANGLES WITH A KEYLINE. Not filled, not floated, not rounded. */
:where(.sl-body).refine-block-poster .card, :where(.sl-body).refine-block-poster .feature-card, :where(.sl-body).refine-block-poster .cat-card, :where(.sl-body).refine-block-poster .tier-card:not(.tier-featured), :where(.sl-body).refine-block-poster .review-card, :where(.sl-body).refine-block-poster .step-card, :where(.sl-body).refine-block-poster .faq-item {
  background: var(--c-surface);
  border: 1px solid var(--bp-rule);
  border-radius: 0;
  box-shadow: none;
}
:where(.sl-body).refine-block-poster .card:hover, :where(.sl-body).refine-block-poster .feature-card:hover, :where(.sl-body).refine-block-poster .cat-card:hover, :where(.sl-body).refine-block-poster .tier-card:not(.tier-featured):hover {
  border-color: var(--bp-rule-hard);
  transform: none;
  box-shadow: none;
}

/* 4. BUTTONS. Square, heavy, and the lane changes their SHAPE only (trap 1). */
:where(.sl-body).refine-block-poster .btn, :where(.sl-body).refine-block-poster .btn-primary, :where(.sl-body).refine-block-poster .btn-secondary {
  border-radius: 0;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  font-size: 0.94rem;
  box-shadow: none;
}
:where(.sl-body).refine-block-poster .btn-secondary {
  background: transparent;
  border: 2px solid currentColor;
}

/* 5. THE FAQ AND THE POLICY LIST, which every lane forgets and DESIGN-LANES.md names explicitly. */
:where(.sl-body).refine-block-poster .faq-item + .faq-item { margin-top: -1px; }
:where(.sl-body).refine-block-poster .faq-item summary, :where(.sl-body).refine-block-poster .faq-list summary {
  font-weight: 700;
  padding: 1.1rem 1.3rem;
}

/* 6. IMAGERY IS SQUARE, and that is the only thing done to it. */
:where(.sl-body).refine-block-poster .section figure img, :where(.sl-body).refine-block-poster .section figure { border-radius: 0; }
/* The closing band and the coverage map are NOT painted here — see trap 4. The one !important
   every other lane carries is kept, because without it a lane rule buries the light map's ink. */
:where(.sl-body).refine-block-poster:not(.map-index):not(.map-panel) main > section.section.section-service_area_map {
  background: var(--c-room) !important;
}

/* ── 7. THE BLOCK LIBRARY, which is what a blueprint HOME page is made of (trap 5). ─────────── */
:where(.sl-body).refine-block-poster .bk-card, :where(.sl-body).refine-block-poster .bk-pillar, :where(.sl-body).refine-block-poster .bk-pcard, :where(.sl-body).refine-block-poster .bk-tier:not(.bk-feat), :where(.sl-body).refine-block-poster .bk-step, :where(.sl-body).refine-block-poster .bk-ccard, :where(.sl-body).refine-block-poster .bk-ict-card, :where(.sl-body).refine-block-poster .bk-fcard, :where(.sl-body).refine-block-poster .bk-credcard, :where(.sl-body).refine-block-poster .bk-grev-card, :where(.sl-body).refine-block-poster .bk-plinth {
  background: var(--c-surface);
  /* A KEYLINE IS NOT A HAIRLINE. This lane calls itself "flat and blocky: square corners, KEYLINES,
     a solid bar over every heading"; clinical-porcelain calls itself "bright precision ... hairline
     dividers". Both were drawing one pixel, so two lanes describing opposite intentions measured as
     the same design and read as the same design at squint distance. Two pixels is the weight this
     lane already uses for the bar over its headings and for the border under its nav, so the page
     now draws one line weight throughout instead of two. */
  border: 2px solid var(--bp-rule);
  border-radius: 0;
  box-shadow: none;
}
:where(.sl-body).refine-block-poster .bk-card:hover, :where(.sl-body).refine-block-poster .bk-pillar:hover, :where(.sl-body).refine-block-poster .bk-pcard:hover, :where(.sl-body).refine-block-poster .bk-tier:not(.bk-feat):hover, :where(.sl-body).refine-block-poster .bk-fcard:hover {
  border-color: var(--bp-rule-hard);
  transform: none;
  box-shadow: none;
}
:where(.sl-body).refine-block-poster .bk-btn, :where(.sl-body).refine-block-poster .bk-pill, :where(.sl-body).refine-block-poster .bk-chip, :where(.sl-body).refine-block-poster .bk-city, :where(.sl-body).refine-block-poster .bk-ict-pill, :where(.sl-body).refine-block-poster .bk-prose-pill {
  border-radius: 0;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
/* T6 (documented in full on body.refine-warm-studio): the shadow reset is not allowed to reach an
   outlined control, whose outline IS an inset box-shadow — `none` there deletes the button rather
   than flattening it. `:where()` keeps this at (0,2,1), the specificity the blanket rule had, so
   the higher-specificity ring on `.bk-nopic-ink .bk-pill-fill` still wins as it always did. */
:where(.sl-body).refine-block-poster :is(.bk-btn, :where(.sl-body) .bk-pill, :where(.sl-body) .bk-chip, :where(.sl-body) .bk-city, :where(.sl-body) .bk-ict-pill, :where(.sl-body) .bk-prose-pill):not(:where(.bk-pill-ghost, :where(.sl-body) .bk-pill-outline, :where(.sl-body) .bk-btn-ghost)) {
  box-shadow: none;
}
:where(.sl-body).refine-block-poster .bk-tier.bk-feat { border-radius: 0; }
:where(.sl-body).refine-block-poster .bk-step-art img, :where(.sl-body).refine-block-poster .bk-prose-photo img, :where(.sl-body).refine-block-poster .bk-cond-ph img, :where(.sl-body).refine-block-poster .bk-tiers-art img, :where(.sl-body).refine-block-poster .bk-cities-map { border-radius: 0; }

/* ── 8. THE COMMUNITY FAMILY'S OWN CHROME, which is the design this lane was authored against. */
/* A LANE DOES NOT REPAINT A NAV BAR. This rule set `background: var(--c-surface)` and it is the
   same mistake as repainting the featured tier: the family chooses its bar's ground, and its ink
   AND ITS LOGO are chosen to suit that ground - navLogo() hands over the light lockup when the bar
   is dark. Turn the ground white and the white type and the white lockup stay, so the community
   home shipped a nav with three invisible links and an invisible logo, caught by two gates at once
   on the first build. Shape and the keyline are the lane's; the ground is not. */
:where(.sl-body).refine-block-poster .cm-nav { border-bottom: 2px solid var(--bp-rule-hard); }
/* The family's own class names, read off the template rather than guessed — the four-family sweep
   below cost warm-studio nothing only because its family really did use the names assumed. */
:where(.sl-body).refine-block-poster .cm-book {
  border-radius: 0;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}
/* THE ROW IS THE SUMMARY'S BOX, NOT A SECOND PLATE BEHIND IT. warm-studio put a plate behind a row
   that already carried its own fill and its own bottom margin and shipped a double border; this
   family draws the fill on `.cm-q` itself, so that is the one thing to change. */
:where(.sl-body).refine-block-poster .cm-q {
  border-radius: 0;
  box-shadow: none;
  border: 1px solid var(--bp-rule);
  margin-bottom: -1px;
}

/* ── 9. AND THE OTHER FOUR FAMILIES, one rule each, so a second client on this lane does not land
      on a default home page. Same reach lesson, applied ahead of the fault. */
:where(.sl-body).refine-block-poster :is(.rt-nav, :where(.sl-body) .ed-nav, :where(.sl-body) .bh-nav, :where(.sl-body) .et-nav, :where(.sl-body) .bl-nav) { border-bottom: 2px solid var(--bp-rule-hard); }
:where(.sl-body).refine-block-poster :is(.rt-pill, :where(.sl-body) .ed-pill, :where(.sl-body) .bh-pill, :where(.sl-body) .et-btn, :where(.sl-body) .bl-pill) {
  border-radius: 0;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

/* ══ DESIGN LANE: ruled-stack ═════════════════════════════════════════════════════════════════
   ONE STOCK, SEPARATED BY RULES. The register nothing on the shelf occupied.

   Every one of the nine lanes before this one separates its bands by CHANGING THE GROUND — paper
   against tint, cream against ivory, paper against an ink room. DESIGN-LANES.md calls band
   architecture "the single biggest silhouette driver" in its own table, and nine lanes were using
   one answer to it. This lane uses the other one: the page is a single stock from the masthead to
   the footer, and what divides one band from the next is a RULE.

   THE DEVICE IS THE RULE, AT THREE WEIGHTS, and that is the whole identity:
     3px   between bands, full bleed, the loudest line on the page
     2px   under a card, and only under it — no box, no fill, no shadow: a shelf, not a container
     1px   between the rows of a list
   Squint at it and you see a stack of horizontal lines at three thicknesses. Squint at any other
   lane in this shelf and you see blocks of alternating colour. That is a difference a reader
   registers before they read a word, which is the test DESIGN-LANES.md sets.

   AND IT IS LEGAL, WHICH IS NOT OBVIOUS. scripts/page-rules-lint.mjs rule P3 refuses two bands in a
   row painting the same ground — and this lane paints EVERY band the same ground. It passes because
   P3 is a rule about a SEAM, not about a colour: a band that draws its own visible top rule is
   visibly a new band, and the check says so in as many words. So the 3px rule is not decoration
   here, it is the thing that makes the architecture possible, and removing it would refuse the
   build. Anything that ever edits it should read this paragraph first.

   THE FIVE TRAPS, applied before writing rather than after being refused. They are documented in
   full on body.refine-warm-studio, and both lanes authored before this one hit several:
     T1  no `color:` on any control — the ground-aware rules already know which ink a dark band
         needs, and a lane rule outranks them and gets it wrong.
     T2  no `background:` on `.bk-feat` or on ANY family's nav bar — those carry their own type,
         and the nav also chooses its LOGO off its own ground.
     T3  both alternating beats declared, under both rhythms. Here both are set to the SAME stock,
         which is the point, but they are still both written out: a lane that names only one lets
         the other fall through to the page default and the architecture silently half-applies.
     T4  the closing band is not painted — a hub page ends on an ink room and the closing band
         lands directly beneath it.
     T5  dressed in `.section`/`.card`/`.btn` for the interior route AND in `.bk-*` plus every
         family's own chrome for the blueprint home page.

   CONTRAST: nothing here sets a text colour, and the only colours it introduces are rules mixed
   from the brand's own --c-primary at three strengths. A rule is not text; it has no AA threshold
   to clear, and it cannot make anything unreadable.

   @lane ruled-stack | one stock top to bottom, bands divided by a rule instead of a colour | suits: solid plain sturdy honest weathered practical rural civic durable straightforward
   ══════════════════════════════════════════════════════════════════════════════════════════ */
:where(.sl-body).refine-ruled-stack {
  --rs-band: 3px;
  --rs-shelf: 2px;
  --rs-hair: 1px;
  --rs-ink: color-mix(in srgb, var(--c-primary) 88%, var(--c-ink, #111));
  --rs-quiet: color-mix(in srgb, var(--c-primary) 22%, transparent);
  --rs-air: clamp(4.25rem, 6.5vw, 6.75rem);
  --card-radius: 0px;
  --btn-radius: 0px;
  --input-radius: 0px;
  --card-shadow: none;
  --card-hover-shadow: none;
  --card-border-width: 0;
}

/* 1. ONE STOCK, BOTH BEATS, BOTH RHYTHMS (T3). The rooms and the closing band are excluded exactly
      as every other lane excludes them: a room is a deliberate dark moment and is not this lane's
      to flatten. */
:where(.sl-body).refine-ruled-stack { background: var(--c-surface); }
:where(.sl-body).refine-ruled-stack.sections-alternate main > section.section:nth-of-type(odd):not(.sec-room):not(.sec-photo):not(.final-cta):not(.section-hub-cta), :where(.sl-body).refine-ruled-stack.sections-alternate main > section.section:nth-of-type(even):not(.sec-room):not(.sec-photo):not(.final-cta):not(.section-hub-cta), :where(.sl-body).refine-ruled-stack.bands-paper main > section.section:nth-of-type(odd):not(.sec-room):not(.sec-photo):not(.final-cta):not(.section-hub-cta), :where(.sl-body).refine-ruled-stack.bands-paper main > section.section:nth-of-type(even):not(.sec-room):not(.sec-photo):not(.final-cta):not(.section-hub-cta) {
  background: var(--c-surface);
}

/* 2. AND THE RULE THAT MAKES THEM READ AS SEPARATE BANDS. Every band after the first draws it.
      This is the seam P3 requires — see the header. */
:where(.sl-body).refine-ruled-stack main > section.section + section.section {
  border-top: var(--rs-band) solid var(--rs-ink);
}
/* AND ON THE HOME PAGE, WHICH HAD NONE OF IT. The rule above speaks the interior route's
   vocabulary; a blueprint home page has no `main > section.section` at all, so this lane - whose
   whole identity is that the seam between two bands is a RULE rather than a colour change - drew
   not one seam on the page every visitor sees, and rendered as an ordinary flat page. Trap five,
   in the lane that depends on it most.
   The band set is written exactly as the page standard's alternation writes it, so the two agree
   on what counts as a band: most blocks arrive wrapped in a bare div, and counting `> section`
   alone finds about a third of them. */
:where(.sl-body).refine-ruled-stack .bk-home > :is(section, :where(.sl-body) :has(section)) + :is(section, :where(.sl-body) :has(section)) {
  border-top: var(--rs-band) solid var(--rs-ink);
}
:where(.sl-body).refine-ruled-stack main > section.section {
  padding-top: var(--rs-air);
  padding-bottom: var(--rs-air);
}

/* 3. TYPE. Large, tight, sentence case; the eyebrow is the one thing set in wide caps, so the two
      sit against each other. No colour (T1), no font family — that is the brand's. */
:where(.sl-body).refine-ruled-stack h1, :where(.sl-body).refine-ruled-stack h2 {
  letter-spacing: -0.025em;
  line-height: 1.05;
  font-weight: 700;
  text-wrap: balance;
}
:where(.sl-body).refine-ruled-stack h3 { letter-spacing: -0.01em; font-weight: 700; }
:where(.sl-body).refine-ruled-stack .eyebrow, :where(.sl-body).refine-ruled-stack .bk-eyebrow-caps {
  text-transform: uppercase;
  letter-spacing: 0.22em;
  font-size: 0.72rem;
  font-weight: 700;
}

/* 4. A CARD IS A SHELF. No box, no fill, no shadow, no corner — a 2px rule under it and nothing
      else. This is the axis that separates this lane from block-poster, which keylines all four
      sides, and from warm-studio, which fills. */
:where(.sl-body).refine-ruled-stack .card, :where(.sl-body).refine-ruled-stack .feature-card, :where(.sl-body).refine-ruled-stack .cat-card, :where(.sl-body).refine-ruled-stack .tier-card:not(.tier-featured), :where(.sl-body).refine-ruled-stack .review-card, :where(.sl-body).refine-ruled-stack .step-card, :where(.sl-body).refine-ruled-stack .faq-item {
  background: transparent;
  border: 0;
  border-bottom: var(--rs-shelf) solid var(--rs-ink);
  border-radius: 0;
  box-shadow: none;
  padding-inline: 0;
}
:where(.sl-body).refine-ruled-stack .card:hover, :where(.sl-body).refine-ruled-stack .feature-card:hover, :where(.sl-body).refine-ruled-stack .cat-card:hover, :where(.sl-body).refine-ruled-stack .tier-card:not(.tier-featured):hover {
  border-bottom-color: var(--c-accent);
  transform: none;
  box-shadow: none;
}

/* 5. BUTTONS. Square and heavily bordered, so they read as part of the same drawn system. Shape
      only (T1): the secondary takes `currentColor`, which is whatever ink its own ground gave it. */
:where(.sl-body).refine-ruled-stack .btn, :where(.sl-body).refine-ruled-stack .btn-primary, :where(.sl-body).refine-ruled-stack .btn-secondary {
  border-radius: 0;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  font-size: 0.9rem;
  box-shadow: none;
}
:where(.sl-body).refine-ruled-stack .btn-secondary {
  background: transparent;
  border: var(--rs-shelf) solid currentColor;
}

/* 6. THE FAQ AND THE POLICY LIST — named in DESIGN-LANES.md's definition of done because they are
      the two every lane forgets. Rows sit flush with a hairline between them, which is the third
      weight of the one device. */
:where(.sl-body).refine-ruled-stack .faq-item + .faq-item { margin-top: 0; border-top: var(--rs-hair) solid var(--rs-quiet); }
:where(.sl-body).refine-ruled-stack .faq-item summary, :where(.sl-body).refine-ruled-stack .faq-list summary { font-weight: 700; padding: 1.15rem 0; }

/* 7. IMAGERY IS SQUARE AND SITS ON THE RULE. */
:where(.sl-body).refine-ruled-stack .section figure img, :where(.sl-body).refine-ruled-stack .section figure { border-radius: 0; }
/* The one !important every lane carries, for the reason every lane records: without it a lane's
   (0,2,1) rule buries the light coverage map's ink. */
:where(.sl-body).refine-ruled-stack:not(.map-index):not(.map-panel) main > section.section.section-service_area_map {
  background: var(--c-room) !important;
}

/* ── 8. THE BLOCK LIBRARY — the half of the site a lane written only in `.section` never reaches. */
:where(.sl-body).refine-ruled-stack .bk-card, :where(.sl-body).refine-ruled-stack .bk-pillar, :where(.sl-body).refine-ruled-stack .bk-pcard, :where(.sl-body).refine-ruled-stack .bk-tier:not(.bk-feat), :where(.sl-body).refine-ruled-stack .bk-step, :where(.sl-body).refine-ruled-stack .bk-ccard, :where(.sl-body).refine-ruled-stack .bk-ict-card, :where(.sl-body).refine-ruled-stack .bk-fcard, :where(.sl-body).refine-ruled-stack .bk-credcard, :where(.sl-body).refine-ruled-stack .bk-grev-card, :where(.sl-body).refine-ruled-stack .bk-plinth {
  background: transparent;
  border: 0;
  border-bottom: var(--rs-shelf) solid var(--rs-ink);
  border-radius: 0;
  box-shadow: none;
}
:where(.sl-body).refine-ruled-stack .bk-card:hover, :where(.sl-body).refine-ruled-stack .bk-pillar:hover, :where(.sl-body).refine-ruled-stack .bk-pcard:hover, :where(.sl-body).refine-ruled-stack .bk-tier:not(.bk-feat):hover, :where(.sl-body).refine-ruled-stack .bk-fcard:hover {
  border-bottom-color: var(--c-accent);
  transform: none;
  box-shadow: none;
}
:where(.sl-body).refine-ruled-stack .bk-tier.bk-feat { border-radius: 0; }
:where(.sl-body).refine-ruled-stack .bk-btn, :where(.sl-body).refine-ruled-stack .bk-pill, :where(.sl-body).refine-ruled-stack .bk-chip, :where(.sl-body).refine-ruled-stack .bk-city, :where(.sl-body).refine-ruled-stack .bk-ict-pill, :where(.sl-body).refine-ruled-stack .bk-prose-pill {
  border-radius: 0;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
/* T6 (documented in full on body.refine-warm-studio). This lane's only wearer happens to reach no
   outlined control today, so the fault here was latent rather than visible — which is exactly the
   kind that ships. The shadow reset skips the ring-drawn controls; `:where()` holds the rule at
   (0,2,1) so nothing else changes rank. */
:where(.sl-body).refine-ruled-stack :is(.bk-btn, :where(.sl-body) .bk-pill, :where(.sl-body) .bk-chip, :where(.sl-body) .bk-city, :where(.sl-body) .bk-ict-pill, :where(.sl-body) .bk-prose-pill):not(:where(.bk-pill-ghost, :where(.sl-body) .bk-pill-outline, :where(.sl-body) .bk-btn-ghost)) {
  box-shadow: none;
}
:where(.sl-body).refine-ruled-stack .bk-step-art img, :where(.sl-body).refine-ruled-stack .bk-prose-photo img, :where(.sl-body).refine-ruled-stack .bk-cond-ph img, :where(.sl-body).refine-ruled-stack .bk-tiers-art img, :where(.sl-body).refine-ruled-stack .bk-cities-map { border-radius: 0; }

/* ── 9. EVERY FAMILY'S OWN CHROME. A border, never a ground (T2): the bar's colour and its logo
      are one decision and they are the family's, not the lane's. */
:where(.sl-body).refine-ruled-stack :is(.rt-nav, :where(.sl-body) .cm-nav, :where(.sl-body) .ed-nav, :where(.sl-body) .bh-nav, :where(.sl-body) .et-nav, :where(.sl-body) .bl-nav) {
  border-bottom: var(--rs-band) solid var(--rs-ink);
}
:where(.sl-body).refine-ruled-stack :is(.rt-pill, :where(.sl-body) .cm-book, :where(.sl-body) .ed-pill, :where(.sl-body) .bh-pill, :where(.sl-body) .et-btn, :where(.sl-body) .bl-pill) {
  border-radius: 0;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
/* The three families that draw their FAQ rows themselves get the same hairline stack. Read off the
   templates rather than guessed — block-poster's first cut named `.cm-pill`, a class the community
   design does not emit, and the rule was dead on arrival. */
:where(.sl-body).refine-ruled-stack :is(.rt-qd, :where(.sl-body) .rt-q, :where(.sl-body) .rt-q-flat, :where(.sl-body) .cm-q, :where(.sl-body) .cm-q-flat) {
  background: transparent;
  border: 0;
  border-bottom: var(--rs-hair) solid var(--rs-quiet);
  border-radius: 0;
  box-shadow: none;
  margin-bottom: 0;
}

/* ══ THE INK INSIDE AN INK ROOM — one rule, every lane, every block, every family ══════════════
   THE FAULT, AND WHY IT COULD NOT BE SEEN BEFORE TODAY.

   A "room" is a band painted in the brand's dark colour instead of on paper. Two things paint one:
   the shared band rhythm (`body.bands-paper … .sec-room`, :4622) and a design LANE. What goes
   INSIDE that band is the block library, and every block in it takes its colours from the `--bk-*`
   tokens — which are set once, per page, for a LIGHT ground.

   So a band that becomes a room keeps light-ground ink on every block inside it. Measured the day
   scripts/lane-gate.mjs was written, by building one lane on a design it had never been tried on:
   the ingredients band, the checklist band, the feature cards, the comparison table and the hub's
   own chips and eyebrows all rendered their own ink on the room's own ink — 28 elements at 1:1 on
   a single listing page, on a lane that has been live for days.

   It was invisible because a lane had only ever been checked on the ONE design it was authored
   against, and rooms are per-family: the same lane is clean on four designs and unreadable on the
   fifth. That is precisely the hole lane-gate exists to close, and this is the first thing it found.

   THE FIX IS NOT TWENTY MORE SELECTORS IN THE LANE. BlockRoute.astro already knows how to make the
   block library dark — it rebinds every token a block paints from when it draws a dark BAND, and
   the note there says exactly why every one is needed ("a card fill left on a literal white is what
   kept dark out of the rotation"). The only thing missing was telling it when a ROOM is dark. This
   is that, restated in CSS, using the same token set for the same reason.

   SCOPED TO `.sec-room` AND `.sec-photo` ONLY. Those two classes mean "this band is dark" and
   nothing else does. A band that is not one of them is not touched, so no light page moves a pixel.
   The values mirror BlockRoute's: translucent white for body ink so it sits back from the heading,
   solid white for titles, the RAW accent for accent-coloured type (the darkened `--bk-accent-text`
   every family computes is for paper and measures near-black on ink), and a white hairline.
   ══════════════════════════════════════════════════════════════════════════════════════════ */
:where(.sl-body).bands-paper main > section.section.sec-room, :where(.sl-body) main > section.section.sec-photo {
  --bk-ink: rgba(255, 255, 255, 0.87);
  --bk-title-ink: #fff;
  --bk-muted: rgba(255, 255, 255, 0.68);
  --bk-hair: rgba(255, 255, 255, 0.22);
  --bk-accent-soft: rgba(255, 255, 255, 0.30);
  /* The accent, RAW. Every family derives --bk-accent-text by mixing the accent toward the page
     ink so it can carry type on paper; on a room that mix is the darkest thing in the band. */
  --bk-accent-text: var(--bk-accent, var(--c-accent));
  /* A card inside a room is a lighter panel OF the room, never a sheet of paper dropped into it. */
  --bk-surface: color-mix(in srgb, currentColor 8%, transparent);
  --bk-paper: color-mix(in srgb, currentColor 12%, transparent);
  --bk-tint: color-mix(in srgb, currentColor 6%, transparent);
}
/* …and the handful of block children that set their own literal ink rather than reading a token.
   Each is a class the block library really emits — checked against src/components/blocks. */
:where(.sl-body).bands-paper main > section.section.sec-room :is(.bk-ingr-intro, :where(.sl-body) .bk-fchk-intro, :where(.sl-body) .bk-fcards-intro, :where(.sl-body) .bk-cmp-intro, :where(.sl-body) .bk-stk-intro, :where(.sl-body) .bk-tbl-intro, :where(.sl-body) .bk-prose-lead), :where(.sl-body) main > section.section.sec-photo :is(.bk-ingr-intro, :where(.sl-body) .bk-fchk-intro, :where(.sl-body) .bk-fcards-intro, :where(.sl-body) .bk-cmp-intro, :where(.sl-body) .bk-stk-intro, :where(.sl-body) .bk-tbl-intro, :where(.sl-body) .bk-prose-lead) {
  color: var(--bk-ink);
}
:where(.sl-body).bands-paper main > section.section.sec-room :is(.bk-fcards-foot, :where(.sl-body) .bk-cmp-foot, :where(.sl-body) .bk-tbl-foot, :where(.sl-body) .bk-stk-foot), :where(.sl-body) main > section.section.sec-photo :is(.bk-fcards-foot, :where(.sl-body) .bk-cmp-foot, :where(.sl-body) .bk-tbl-foot, :where(.sl-body) .bk-stk-foot) {
  color: var(--bk-muted);
}
/* The hub's own chrome — its chips, its eyebrows and its at-a-glance labels — is drawn by
   HubIndex.astro rather than by the block library, so it reads none of the tokens above. It has
   the same problem for the same reason and is named here rather than in a second place. */
/* Named one at a time on purpose. A blanket `.hub-* { color: white }` inside a room would also
   repaint the text inside `.hub-card`, which is a WHITE card standing ON the room — white on white,
   the same trap one layer down. Every class below was checked to be a child of the room itself and
   never of a card: the chip, the solo band's eyebrow, the at-a-glance labels, and the arrow on a
   menu link (which sits on the room; the arrow on a CARD does not and is left alone). */
:where(.sl-body).bands-paper main > section.section.sec-room :is(.hub-chip, :where(.sl-body) .hub-solo-eyebrow, :where(.sl-body) .hub-glance-l, :where(.sl-body) .hub-glance-v), :where(.sl-body) main > section.section.sec-photo :is(.hub-chip, :where(.sl-body) .hub-solo-eyebrow, :where(.sl-body) .hub-glance-l, :where(.sl-body) .hub-glance-v), :where(.sl-body).bands-paper main > section.section.sec-room .hub-menu-link .hub-card-arrow, :where(.sl-body) main > section.section.sec-photo .hub-menu-link .hub-card-arrow {
  color: rgba(255, 255, 255, 0.87);
}
/* ── A FRACTION OF A LITERAL WHITE IS NOT A MEASUREMENT, AND ON THIS ROOM IT STOPPED BEING ONE.
   (2026-09-06, reviewer finding: the listing hubs' eyebrow at 3.74:1 where 13px/600 caps want 4.5)

   THE FAULT, AND WHY IT IS THIS ROUND'S TO CLOSE EVEN THOUGH IT DID NOT CAUSE IT. The section
   eyebrow on the four listing hubs is stepped back TWICE by two rules that never met: HubIndex
   gives it `opacity: 0.7` (written for an eyebrow standing on PAPER, where --c-text has the whole
   range of the page behind it), and the rule directly above repaints it `rgba(255,255,255,0.87)`
   because it is standing on a room. The two compose to 0.609 of a white — and 0.609 white is a
   quantity nobody measured against anything. On a light page the room is the brand navy and there
   is range to burn (measured 6.56:1, comfortable). On a DARK page the room is the page's TOP rung
   by construction, the brightest ground the page has, and the same 0.609 lands at 3.74:1. The
   round that lifted the room from a grey-slate to the brand blue moved it 3.82 -> 3.74; it did not
   invent the shape, and leaving it is how a pre-existing sub-AA gets inherited one more time.

   THE DECISION, IN ONE PLACE. What ink does the hub's own chrome take on a room? The room already
   answers that: `--c-on-room` is derived by brand.ts against THIS room, at AA, and it is the ink
   the room's body copy takes. So on a dark ground the eyebrow takes it, at full strength, and its
   quietness comes from what an eyebrow's quietness has always come from — 13px, 0.08em of
   tracking, caps — rather than from an unmeasured dilution. That is the same call this round
   already made one file over, for the same reason, when the featured column's notes stopped being
   diluted on a dark ground (`--bk-onprimary-dim`).

   GATED ON THE GROUND, NOT ON THE LANE, and light keeps today's bytes exactly: a light page never
   matches `body.ground-dark`, so the eyebrow there is still 0.87 white at 0.7 opacity — measured
   #a2aab2 on #10263b before this rule and after it. The scope is `.sec-room` and not `.sec-photo`
   on purpose: `--c-on-room` is derived against the ROOM, and a band carrying a photograph is not
   standing on it (that band is photo-text-lint's to judge, off the real pixels). */
:where(.sl-body).ground-dark.bands-paper main > section.section.sec-room .hub-solo-eyebrow {
  color: var(--c-on-room);
  opacity: 1;
}
/* THE SAME LIST, THREE ENTRIES LONGER, AND THIS IS WHY IT KEEPS GETTING LONGER.

   Measured on a built sample site: 20 lines of text sitting on a dark band at a contrast of 1.0 -
   the ink and the ground the SAME colour, the words simply not there. All twenty were drawn by the
   listing renderer, and all three selectors below were missing from the list above for the same
   reason the ones above were missing before them: the room rebinds `--bk-*`, the block library
   reads those tokens, and the hub draws its own chrome that reads none of them. A band that goes
   dark therefore takes its blocks with it and leaves the hub-s own parts behind.

   `.hub-choose-h` is a heading, so it takes the solid title ink; the other two are body copy and
   take the same stepped-back white as everything else here. All three were checked to be children
   of the room itself and never of `.hub-card`, which is a white card STANDING on the room - the
   trap the note above names, and the reason this is still a list of names rather than `.hub-*`.

   The real repair is for this chrome to read the same tokens the blocks read, so that a band going
   dark carries everything in it. Until then, anything new drawn by the hub onto a band that can be
   a room has to be added here on the day it is written, and photo-text is what catches it. */
:where(.sl-body).bands-paper main > section.section.sec-room :is(.hub-choose-group li, :where(.sl-body) .hub-faq-item p), :where(.sl-body) main > section.section.sec-photo :is(.hub-choose-group li, :where(.sl-body) .hub-faq-item p) {
  color: rgba(255, 255, 255, 0.87);
}
:where(.sl-body).bands-paper main > section.section.sec-room .hub-choose-h, :where(.sl-body) main > section.section.sec-photo .hub-choose-h {
  color: #fff;
}
:where(.sl-body).bands-paper main > section.section.sec-room .hub-chip, :where(.sl-body) main > section.section.sec-photo .hub-chip {
  background: color-mix(in srgb, currentColor 12%, transparent);
  border-color: rgba(255, 255, 255, 0.22);
}


/* ══ THE SIX LANES THAT DRESSED ONLY HALF A SITE ══════════════════════════════════════════════
   Every lane below was written before the platform had blueprint HOME pages, so every rule in it
   speaks the interior route's vocabulary - `.section`, `.card`, `.btn` - and none of it reaches the
   one page every visitor sees, which draws through the block library and its family's own chrome.
   Found 2026-08-27 by scripts/lane-gate.mjs, the harness that first made it possible to build a
   lane on a design it was not authored for. Six of nine lanes had no `.bk-*` rule at all.
   Each block below restates that lane's OWN decisions in the home page's vocabulary. None of them
   invents a new look, none paints a nav bar or the closing band, and none repaints the featured
   tier — the three traps that refused a build this week. ═══════════════════════════════════ */

/* ── PILL-PORCELAIN: THE BLOCK LIBRARY AND THE FAMILY CHROME ──────────────────────
   This lane is a mostly-white page whose one device is the logo's speech bubble: a fully
   round raspberry pill holding four words or fewer, with a wedge tucked one radius in from
   the left edge and pointing down-left. Plates are 16px-radius white cards carrying exactly
   one shadow (0 2px 10px at 5%) and no border, hover lifts the shadow and never moves the
   card, and actions are 999px pills. All of that was written in `.eyebrow` / `.card` / `.btn`
   / `.faq-item`, which a blueprint home page never calls, so the four decisions are restated
   here in `.bk-*` and family vocabulary: the bubble eyebrow with its tail on `.bk-eyebrow-caps`,
   the borderless 16px shadowed plate on every block card, 999px on every block and family
   control, and the family FAQ row turned into the same porcelain plate. Nothing is re-coloured
   that the lane does not itself paint, and no nav gets a ground.
   ────────────────────────────────────────────────────────────────────────────── */

/* 1. PLATES — 16px, one shadow, no border, nothing else competing with it. NOT .bk-feat (a dark
      plate with its own white type, set in its own block), and NOT .bk-tile or .bk-sit-card,
      which carry their own fill: repainting a plate this lane will not also re-ink is the trap. */
:where(.sl-body).refine-pill-porcelain .bk-pillar, :where(.sl-body).refine-pill-porcelain .bk-pcard, :where(.sl-body).refine-pill-porcelain .bk-tier:not(.bk-feat), :where(.sl-body).refine-pill-porcelain .bk-step, :where(.sl-body).refine-pill-porcelain .bk-ccard, :where(.sl-body).refine-pill-porcelain .bk-ict-card, :where(.sl-body).refine-pill-porcelain .bk-fcard, :where(.sl-body).refine-pill-porcelain .bk-credcard, :where(.sl-body).refine-pill-porcelain .bk-grev-card {
  background: var(--c-surface);
  border: 0;
  border-radius: var(--card-radius, 16px);
  box-shadow: var(--card-shadow);
  transition: box-shadow var(--pp-ease);
}
/* The book forbids bounce and parallax, so the lift is shadow-only — no card in this lane
   translates, scales or rotates, on an interior page or a home page. */
:where(.sl-body).refine-pill-porcelain .bk-pillar:hover, :where(.sl-body).refine-pill-porcelain .bk-pcard:hover, :where(.sl-body).refine-pill-porcelain .bk-tier:not(.bk-feat):hover, :where(.sl-body).refine-pill-porcelain .bk-fcard:hover, :where(.sl-body).refine-pill-porcelain .bk-ccard:hover {
  box-shadow: var(--card-hover-shadow);
  transform: none;
}
/* The product plinth ships a cold near-white panel with its own edge; on this page that reads
   as a second paper stock. Same porcelain plate as everything else. */
:where(.sl-body).refine-pill-porcelain .bk-plinth {
  background: var(--c-surface);
  border-radius: var(--card-radius, 16px);
  box-shadow: var(--card-shadow);
}
/* The tier name is Poppins here as it is everywhere else — shape only, never the ink, because
   this same name sits on the featured plate whose ground belongs to the block. */
:where(.sl-body).refine-pill-porcelain .bk-tier .bk-tier-name {
  font-family: var(--font-headline, var(--font-heading));
  font-weight: 800;
}

/* 2. CONTROLS — fully round, Poppins, no shadow. Shape only: the ground under a block control
      is the block's decision, and inking one whose ground this lane does not paint is how a
      label ends up brand-colour-on-brand-dark. */
:where(.sl-body).refine-pill-porcelain .bk-btn, :where(.sl-body).refine-pill-porcelain .bk-pill, :where(.sl-body).refine-pill-porcelain .bk-chip, :where(.sl-body).refine-pill-porcelain .bk-city, :where(.sl-body).refine-pill-porcelain .bk-ict-pill, :where(.sl-body).refine-pill-porcelain .bk-prose-pill {
  border-radius: 999px;
  font-family: var(--font-headline, var(--font-heading));
  font-weight: 700;
}
/* T6 (documented in full on body.refine-warm-studio). "No shadow" is a statement about ELEVATION,
   and an outlined pill's inset ring is not elevation, it is the pill. The reset skips the three
   ring-drawn controls; `:where()` holds this at (0,2,1) so nothing else changes rank. Note the
   `.bk-pill-ghost { border-width }` rule below assumed a ring was there to thicken — before this,
   on this lane, there was not one. */
:where(.sl-body).refine-pill-porcelain :is(.bk-btn, :where(.sl-body) .bk-pill, :where(.sl-body) .bk-chip, :where(.sl-body) .bk-city, :where(.sl-body) .bk-ict-pill, :where(.sl-body) .bk-prose-pill):not(:where(.bk-pill-ghost, :where(.sl-body) .bk-pill-outline, :where(.sl-body) .bk-btn-ghost)) {
  box-shadow: none;
}
/* THE SIZE IS AN ACCESSIBILITY FLOOR, NOT TASTE, and it is the same floor the interior route
   carries: white on IV Pink is 3.77:1, under the 4.5:1 AA wants for normal text but over the
   3.0 it wants for large, and WCAG counts bold >= 18.66px as large. 1.2rem/700 = 19.2px clears
   it, so a filled action stays legal whatever fill the block gives it. */
:where(.sl-body).refine-pill-porcelain .bk-pill-fill, :where(.sl-body).refine-pill-porcelain .bk-btn-fill {
  font-size: 1.2rem;
  font-weight: 700;
  min-height: 48px;
}
/* The outline weight matches the interior secondary, so the two routes' ghosts are one object. */
:where(.sl-body).refine-pill-porcelain .bk-pill-ghost { border-width: 1.5px; }

/* 3. THE BUBBLE — the whole reason the lane exists, and the block library's eyebrow never got it.
      `.bk-eyebrow-caps` is emitted as a <p> in every block and its own scoped rule sets a `font:`
      shorthand plus an accent ink at the same weight as a plain lane rule, so this is written
      `p.bk-eyebrow-caps` to land above it. The lane paints this ground itself and re-inks it in
      the same declaration — white on Raspberry is 5.66:1, which holds on any band, on any brand. */
:where(.sl-body).refine-pill-porcelain p.bk-eyebrow-caps {
  display: inline-block;
  position: relative;
  background: var(--pp-bubble);
  color: #fff;
  font-family: var(--font-headline, var(--font-heading));
  font-weight: 700;
  font-size: 0.72rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 0.42rem 0.95rem 0.44rem;
  border-radius: 999px;
  line-height: 1;
  margin: 0 0 1.15rem;
}
/* THE TAIL, drawn exactly as the interior route draws it: the left edge continues straight down
   off the bar and the hypotenuse runs back up to the right, so the point lands at the bottom
   LEFT. It starts INSIDE the pill (top: calc(100% - 4px)) because a 999px corner is already
   curving away at that x — parked below, it detaches into a floating triangle. */
:where(.sl-body).refine-pill-porcelain p.bk-eyebrow-caps::after {
  content: '';
  position: absolute;
  left: 0.95rem;
  top: calc(100% - 4px);
  width: 0.7rem;
  height: 0.52rem;
  background: var(--pp-bubble);
  clip-path: polygon(0 0, 100% 0, 0 100%);
}

/* 4. IMAGERY — the same 16px the plates use, so a photograph is another card on the page. */
:where(.sl-body).refine-pill-porcelain .bk-step-art img, :where(.sl-body).refine-pill-porcelain .bk-prose-photo img, :where(.sl-body).refine-pill-porcelain .bk-cond-ph img, :where(.sl-body).refine-pill-porcelain .bk-tiers-art img, :where(.sl-body).refine-pill-porcelain .bk-cities-map {
  border-radius: var(--card-radius, 16px);
  box-shadow: none;
}

/* 5. THE FEATURED TIER GETS THE RADIUS AND NOTHING ELSE. Its plate and its white ink are one
      decision and they live in the block; a lane that takes half of it takes the half that
      cannot be read. Shape is the lane's to change, colour is not. */
:where(.sl-body).refine-pill-porcelain .bk-tier.bk-feat { border-radius: var(--card-radius, 16px); }

/* 6. EVERY FAMILY'S OWN CHROME. No ground on any bar — the family picks the bar's colour and
      its light-or-dark logo together. This lane never rules a band anyway; it separates with
      stock and with its one shadow, so the bar gets that shadow and no line. */
:where(.sl-body).refine-pill-porcelain :is(.rt-nav, :where(.sl-body) .cm-nav, :where(.sl-body) .ed-nav, :where(.sl-body) .bh-nav, :where(.sl-body) .et-nav, :where(.sl-body) .bl-nav) {
  border-bottom: 0;
  box-shadow: var(--card-shadow);
}
:where(.sl-body).refine-pill-porcelain :is(.rt-pill, :where(.sl-body) .cm-book, :where(.sl-body) .ed-pill, :where(.sl-body) .bh-pill, :where(.sl-body) .et-btn, :where(.sl-body) .bl-pill) {
  border-radius: 999px;
  font-family: var(--font-headline, var(--font-heading));
  font-weight: 700;
}
/* The retail family's filled hero action is the page's one big confident button, held to the
   same 18.66px floor as everything else that may end up white-on-pink. */
:where(.sl-body).refine-pill-porcelain .rt-fill {
  font-size: 1.2rem;
  min-height: 48px;
}
:where(.sl-body).refine-pill-porcelain .rt-outline { border-width: 1.5px; }
:where(.sl-body).refine-pill-porcelain .rt-hero-art img { border-radius: var(--card-radius, 16px); }
/* THE ROW IS THE SUMMARY, NOT THE DISCLOSURE AROUND IT — dressing `.rt-qd` would put a plate
   behind a summary that already carries its own fill and its own bottom margin, and ship every
   question as a box floating on a box. The row itself becomes the porcelain plate, and the
   family's existing row gap keeps the plates from touching. */
:where(.sl-body).refine-pill-porcelain :is(.rt-q, :where(.sl-body) .rt-q-flat, :where(.sl-body) .cm-q, :where(.sl-body) .cm-q-flat) {
  background: var(--c-surface);
  border: 0;
  border-radius: var(--card-radius, 16px);
  box-shadow: var(--card-shadow);
}

/* ── SPA-LUXE: THE BLOCK LIBRARY AND THE FAMILY CHROME ───────────────────────────
   This lane is quiet luxury: a light-weight serif set large, gold tracked-caps
   eyebrows, and near-sharp hairline geometry — 3px corners, a single gold keyline,
   no fill and no soft app-shadow anywhere on the page. Everything above it says that
   in `.section`/`.card`/`.eyebrow`, which is the interior route only; a brand with a
   page_template draws its home page from `.bk-*` plus its family's own chrome and got
   none of it. Restated here: cards and panels are UNFILLED and gold-hairline-framed
   rather than plated, controls take the 3px corner and the same 0.16em tracked-caps
   voice as the eyebrows, photographs carry the same hairline as a gallery frame, and
   the FAQ stops being a stack of boxes and becomes a hairline-ruled list.

   THE TRAPS. T1 — nothing here sets `color:` on any eyebrow, pill, button or heading;
   the only colours introduced are BORDERS mixed from the brand's own accent, and a
   border has no AA threshold to clear. T2 — no `background:` on `.bk-feat` or on any
   family's nav bar; both carry their own type and the nav picks its logo off its own
   ground, so the lane gives the bar a rule and nothing else. T4 — the closing band is
   not painted. T5 — this section is the fix.
   ─────────────────────────────────────────────────────────────────────────── */

:where(.sl-body).refine-spa-luxe { --spa-edge: 14px; }   /* the corner, named once — near-sharp until 2026-09-15 */

/* ── 1. CARDS AND PANELS ARE FRAMES, NOT PLATES. The block library ships each of these
      with a fill of its own; this lane's whole card idea is a keyline around air, so the
      fill goes and a gold hairline stays. Unfilled means the ink inside is still the
      band's own ground-aware ink — nothing to re-contrast. */
:where(.sl-body).refine-spa-luxe .bk-pillar, :where(.sl-body).refine-spa-luxe .bk-pcard, :where(.sl-body).refine-spa-luxe .bk-ccard, :where(.sl-body).refine-spa-luxe .bk-step, :where(.sl-body).refine-spa-luxe .bk-fcard, :where(.sl-body).refine-spa-luxe .bk-ict-card, :where(.sl-body).refine-spa-luxe .bk-tier:not(.bk-feat), :where(.sl-body).refine-spa-luxe .bk-credcard, :where(.sl-body).refine-spa-luxe .bk-grev-card, :where(.sl-body).refine-spa-luxe .bk-plinth {
  background: transparent;
  border: 1px solid var(--spa-line);
  border-radius: var(--spa-edge);
  box-shadow: none;
}
/* A hover is a line getting stronger, never a card lifting off the page. */
:where(.sl-body).refine-spa-luxe .bk-pillar:hover, :where(.sl-body).refine-spa-luxe .bk-pcard:hover, :where(.sl-body).refine-spa-luxe .bk-fcard:hover, :where(.sl-body).refine-spa-luxe .bk-tier:not(.bk-feat):hover {
  border-color: var(--c-accent);
  transform: none;
  box-shadow: none;
}

/* ── 2. CONTROLS. Every block draws its own pill somewhere between 4px and fully round;
      this lane wants one corner across the page and the eyebrow's voice on the label.
      Shape and tracking only — the ground-aware rules keep their ink, including
      `.bk-pill-ghost`, whose white ink and inset ring belong to the dark ground it
      stands on and are therefore not the lane's to touch.

      THAT LAST SENTENCE WAS TRUE OF THE INK AND FALSE OF THE RING, and the gap between the
      two is where this lane shipped a defect. The blanket `box-shadow: none` that used to
      close this rule DID touch the ghost: its ring is an inset box-shadow, so the reset
      deleted it and left "Make an appointment" as bare white lettering on the dark
      ConditionsPanel band of three sample brands' home pages, and "Explore Services" as
      dark text on white beside a filled arrow button. See T6 on body.refine-warm-studio.
      The corner below still reaches every control, including the ghost — shape is the
      lane's. The reset is now stated separately and skips the ring-drawn three. */
:where(.sl-body).refine-spa-luxe .bk-btn, :where(.sl-body).refine-spa-luxe .bk-pill, :where(.sl-body).refine-spa-luxe .bk-pill-fill, :where(.sl-body).refine-spa-luxe .bk-btn-fill, :where(.sl-body).refine-spa-luxe .bk-chip, :where(.sl-body).refine-spa-luxe .bk-city, :where(.sl-body).refine-spa-luxe .bk-ict-pill, :where(.sl-body).refine-spa-luxe .bk-prose-pill {
  border-radius: var(--spa-edge);
}
/* `:where()` holds this at (0,2,1) — the specificity the blanket rule had — so the ring on
   `.bk-home .bk-nopic-ink .bk-pill-fill` at (0,3,0), which is the same trap one selector over,
   still outranks it exactly as before. */
:where(.sl-body).refine-spa-luxe :is(.bk-btn, :where(.sl-body) .bk-pill, :where(.sl-body) .bk-pill-fill, :where(.sl-body) .bk-btn-fill, :where(.sl-body) .bk-chip, :where(.sl-body) .bk-city, :where(.sl-body) .bk-ict-pill, :where(.sl-body) .bk-prose-pill):not(:where(.bk-pill-ghost, :where(.sl-body) .bk-pill-outline, :where(.sl-body) .bk-btn-ghost)) {
  box-shadow: none;
}
/* The tracked-caps voice goes on the BUTTONS only. `.bk-city` is a place name in a list,
   and uppercasing a two-word city at 0.16em wraps it. */
:where(.sl-body).refine-spa-luxe .bk-btn, :where(.sl-body).refine-spa-luxe .bk-pill, :where(.sl-body).refine-spa-luxe .bk-pill-fill, :where(.sl-body).refine-spa-luxe .bk-btn-fill, :where(.sl-body).refine-spa-luxe .bk-ict-pill, :where(.sl-body).refine-spa-luxe .bk-prose-pill {
  text-transform: uppercase;
  letter-spacing: 0.16em;
  font-weight: 600;
  font-size: 0.75rem;
}
/* The block library's eyebrow, given the same 0.2em caps the interior route already
   uses. Weight and tracking, not colour. */
:where(.sl-body).refine-spa-luxe .bk-eyebrow-caps {
  text-transform: uppercase;
  letter-spacing: 0.2em;
  font-size: 0.72rem;
  font-weight: 600;
}
/* THE PRICE IS THE COUTURE MOVE. `.bk-price` bare is also the name of the price RIBBON
   BAND, so this is scoped inside a tier: the figure loses its medium weight and becomes
   the same light serif the headings are, which is the one thing that reads as this lane
   at a glance on a membership grid. */
:where(.sl-body).refine-spa-luxe .bk-tier .bk-price {
  font-weight: 400;
  letter-spacing: -0.01em;
}

/* ── 3. IMAGERY WEARS THE SAME HAIRLINE — the frame is the lane's only ornament, and a
      photograph inside a gallery keyline is the whole reference. `.bk-cities-map` is the
      image element itself, not a wrapper, so it takes the frame directly. */
:where(.sl-body).refine-spa-luxe .bk-step-art img, :where(.sl-body).refine-spa-luxe .bk-prose-photo img, :where(.sl-body).refine-spa-luxe .bk-cond-ph img, :where(.sl-body).refine-spa-luxe .bk-tiers-art img {
  border: 1px solid var(--spa-line);
  border-radius: var(--spa-edge);
}
:where(.sl-body).refine-spa-luxe .bk-cities-map {
  border: 1px solid var(--spa-line);
  border-radius: var(--spa-edge);
  box-shadow: none;
}

/* ── 4. THE FEATURED TIER GETS THE CORNER AND NOTHING ELSE. Its plate and the white type
      on it are ONE decision made in the block; the lane may sharpen the corner, and that
      is the whole of its business here. */
:where(.sl-body).refine-spa-luxe .bk-tier.bk-feat { border-radius: var(--spa-edge); }

/* ── 5. EVERY FAMILY'S OWN CHROME. A blueprint home draws its nav, hero and FAQ from the
      family template, so none of section 1 reaches them. A rule under the bar, never a
      ground: the bar's colour and its light-or-dark logo are the family's one decision. */
:where(.sl-body).refine-spa-luxe :is(.rt-nav, :where(.sl-body) .cm-nav, :where(.sl-body) .ed-nav, :where(.sl-body) .bh-nav, :where(.sl-body) .et-nav, :where(.sl-body) .bl-nav) {
  border-bottom: 1px solid var(--spa-line);
}
:where(.sl-body).refine-spa-luxe :is(.rt-pill, :where(.sl-body) .cm-book, :where(.sl-body) .ed-pill, :where(.sl-body) .bh-pill, :where(.sl-body) .et-btn, :where(.sl-body) .bl-pill) {
  border-radius: var(--spa-edge);
  text-transform: uppercase;
  letter-spacing: 0.16em;
  font-weight: 600;
}
/* T6 (documented in full on body.refine-warm-studio): the reset skips the controls the
   renderers draw as an inset ring, because on those the shadow IS the border. `:where()`
   keeps the rule at the specificity it already had. */
:where(.sl-body).refine-spa-luxe :is(.rt-pill, :where(.sl-body) .cm-book, :where(.sl-body) .ed-pill, :where(.sl-body) .bh-pill, :where(.sl-body) .et-btn, :where(.sl-body) .bl-pill):not(:where(.rt-outline, :where(.sl-body) .rt-soft, :where(.sl-body) .et-btn-ghost, :where(.sl-body) .et-btn-ghost-white, :where(.sl-body) .bl-pill-ghost)) { box-shadow: none; }
/* THE FAQ IS A RULED LIST, NOT A STACK OF BOXES. The retail and community families each
   draw the question row themselves — a tinted or white box with its own shadow and its
   own bottom margin. Stripping the box leaves each question's ink standing on the band
   it was already standing on, and one hairline between rows is all the structure this
   lane wants. The ROW is `.rt-q`/`.cm-q`; the disclosure wrapper around it is left
   alone, because painting that ships a pale box floating on a darker one. */
:where(.sl-body).refine-spa-luxe :is(.rt-q, :where(.sl-body) .rt-q-flat, :where(.sl-body) .cm-q, :where(.sl-body) .cm-q-flat) {
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--spa-line);
  border-radius: 0;
  box-shadow: none;
  margin-bottom: 0;
}

/* ── LUXE-NOIR: THE BLOCK LIBRARY AND THE FAMILY CHROME ──────────────────────────────
   Quiet luxury, restated for the home page. Four decisions carry this lane and all four
   are shape: plates are near-sharp (4px) and ruled with a hairline mixed from the brand's
   own accent, never shadowed; controls are 2px, uppercase and widely tracked; photographs
   sit INSIDE a drawn frame — a hairline inset ten pixels from the edge — rather than
   floating on a soft shadow; and where a block already draws a rule instead of a box, the
   rule becomes that same accent hairline. Those are the identical calls the interior route
   gets from `.card`, `.btn`, `.itr-media` and `.pkg-bag-fallback`; below they are written
   in the block library's own class names so a blueprint home in this lane is this lane.

   NOTHING HERE SETS A TEXT COLOUR AND NOTHING REPAINTS A PLATE THAT CARRIES TYPE. Every
   fill stays exactly as its own block set it, so the ground-aware inks — and the dark-band
   ink rebinds declared earlier in this lane — keep winning (T1, T2). `.bk-tier:not(.bk-feat)`
   is written out for that reason; `.bk-tile` and `.bk-sit-card` carry their own fills and
   are not touched at all; no nav gets a ground, only a border. `.bk-pill` and `.bk-btn`
   never get `box-shadow: none`, because the ghost variants draw their ring AS an inset
   shadow and would come back ringless. The hairlines are mixed from --c-accent, so the
   lane follows any palette — navy and gold or hot pink and lime alike.
   ─────────────────────────────────────────────────────────────────────────────────── */

/* 1. PLATES — the shadow comes off, an accent hairline goes on, corners go near-sharp. */
:where(.sl-body).refine-luxe-noir .bk-pillar, :where(.sl-body).refine-luxe-noir .bk-pcard, :where(.sl-body).refine-luxe-noir .bk-ccard, :where(.sl-body).refine-luxe-noir .bk-step, :where(.sl-body).refine-luxe-noir .bk-fcard, :where(.sl-body).refine-luxe-noir .bk-ict-card, :where(.sl-body).refine-luxe-noir .bk-credcard, :where(.sl-body).refine-luxe-noir .bk-grev-card, :where(.sl-body).refine-luxe-noir .bk-tier:not(.bk-feat) {
  border: 1px solid var(--ln-hairline);
  border-radius: 4px;
  box-shadow: none;
}
:where(.sl-body).refine-luxe-noir .bk-pillar:hover, :where(.sl-body).refine-luxe-noir .bk-pcard:hover, :where(.sl-body).refine-luxe-noir .bk-fcard:hover, :where(.sl-body).refine-luxe-noir .bk-tier:not(.bk-feat):hover {
  border-color: var(--ln-hairline-strong);
  transform: none;
  box-shadow: none;
}
/* THE LEDGER LAYOUTS ARE ALREADY THIS LANE, SO THEY KEEP THEIR RULE. Four block layouts
   deliberately draw a ruled ROW rather than a box and zero their side padding to do it;
   boxing those would print a border hard against the text, which is the "plate touching"
   fault this shelf has shipped four times. They get the lane's hairline on the rule they
   already have. Their :last-child closing border is more specific and survives. */
:where(.sl-body).refine-luxe-noir .bk-fcards-l-ledger .bk-fcard, :where(.sl-body).refine-luxe-noir .bk-fcards-editorial .bk-fcard, :where(.sl-body).refine-luxe-noir .bk-tiers-l-ledger .bk-tier:not(.bk-feat), :where(.sl-body).refine-luxe-noir .bk-tl-l-ledger .bk-step {
  border: 0;
  border-top: 1px solid var(--ln-hairline-strong);
  border-radius: 0;
}

/* 2. CONTROLS — slim, near-sharp, uppercase, widely tracked: the `.btn` rule, restated.
      Shape and typography only. No colour, and no blanket shadow reset: the ghost pill and
      the ghost button draw their outline as an inset box-shadow, and clearing it would
      leave a bare word where a button was. Only the FILLED variants, which use a real
      background, are flattened. */
:where(.sl-body).refine-luxe-noir .bk-btn, :where(.sl-body).refine-luxe-noir .bk-pill, :where(.sl-body).refine-luxe-noir .bk-chip, :where(.sl-body).refine-luxe-noir .bk-city, :where(.sl-body).refine-luxe-noir .bk-ict-pill, :where(.sl-body).refine-luxe-noir .bk-prose-pill {
  border-radius: 2px;
  font-size: 0.83rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
:where(.sl-body).refine-luxe-noir .bk-pill-fill, :where(.sl-body).refine-luxe-noir .bk-btn-fill { box-shadow: none; }
/* The city pill is the one control with a drawn border of its own; it becomes the accent
   hairline like every other edge on the page. Its fill and its ink are left alone. */
:where(.sl-body).refine-luxe-noir .bk-city { border-color: var(--ln-hairline); }

/* 3. IMAGERY — framed, not floated. The two photo CONTAINERS take the lane's inset hairline
      frame; the raw <img> blocks (which have no box to hang a pseudo-element on) take the
      hairline as a border instead. Same device, two mechanics. */
:where(.sl-body).refine-luxe-noir .bk-prose-photo, :where(.sl-body).refine-luxe-noir .bk-cond-ph { position: relative; }
:where(.sl-body).refine-luxe-noir .bk-prose-photo::after, :where(.sl-body).refine-luxe-noir .bk-cond-ph::after {
  content: '';
  position: absolute;
  inset: 10px;
  border: 1px solid var(--ln-hairline-strong);
  pointer-events: none;
  z-index: 2;
}
@media (max-width: 720px) {
  :where(.sl-body).refine-luxe-noir .bk-prose-photo::after, :where(.sl-body).refine-luxe-noir .bk-cond-ph::after { inset: 7px; }
}
:where(.sl-body).refine-luxe-noir .bk-step-art, :where(.sl-body).refine-luxe-noir .bk-tiers-art, :where(.sl-body).refine-luxe-noir .bk-cities-map, :where(.sl-body).refine-luxe-noir .bk-prose-photo img, :where(.sl-body).refine-luxe-noir .bk-cond-ph img {
  border-radius: 4px;
  box-shadow: none;
}
:where(.sl-body).refine-luxe-noir .bk-step-art, :where(.sl-body).refine-luxe-noir .bk-tiers-art, :where(.sl-body).refine-luxe-noir .bk-cities-map { border: 1px solid var(--ln-hairline); }
/* The product plinth is the home page's `.pkg-bag-fallback`: a framed object, not a grey
   blob. Its cold literal grey is the one fill this lane replaces, and it can be, because
   the plinth holds an image and no type — there is no ink to get wrong. */
:where(.sl-body).refine-luxe-noir .bk-plinth {
  background: var(--c-surface);
  border: 1px solid var(--ln-hairline);
  border-radius: 4px;
}

/* 4. THE FEATURED TIER GETS THE CORNER AND THE FRAME, NOT THE PAINT. It is a dark plate
      whose white type is set inside its own block; the plate and its ink are one decision
      and it is not the lane's. The lane owns the edge, so the edge is what it takes. */
:where(.sl-body).refine-luxe-noir .bk-tier.bk-feat {
  border-radius: 4px;
  border: 1px solid var(--ln-hairline-strong);
}

/* 5. EVERY FAMILY'S OWN CHROME — a border and a shape, never a ground. A nav bar picks its
      own ground AND picks its light-or-dark logo off it, so a lane that repaints the bar
      hides the logo. All six families are named so a second client on a different design
      does not drop back to the platform look. */
:where(.sl-body).refine-luxe-noir :is(.rt-nav, :where(.sl-body) .cm-nav, :where(.sl-body) .ed-nav, :where(.sl-body) .bh-nav, :where(.sl-body) .et-nav, :where(.sl-body) .bl-nav) {
  border-bottom: 1px solid var(--ln-hairline);
}
:where(.sl-body).refine-luxe-noir :is(.rt-pill, :where(.sl-body) .cm-book, :where(.sl-body) .ed-pill, :where(.sl-body) .bh-pill, :where(.sl-body) .et-btn, :where(.sl-body) .bl-pill) {
  border-radius: 2px;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
/* The two families that draw their own FAQ rows: the row is the summary, so the summary is
   what gets dressed — flush, unfilled, one hairline between questions. `.rt-qd` is the
   disclosure AROUND the row and painting it prints a second border nobody drew. */
:where(.sl-body).refine-luxe-noir :is(.rt-q, :where(.sl-body) .rt-q-flat, :where(.sl-body) .cm-q, :where(.sl-body) .cm-q-flat) {
  background: transparent;
  border: 0;
  border-bottom: 1px solid var(--ln-hairline);
  border-radius: 0;
  box-shadow: none;
}

/* ── CLINICAL-PORCELAIN: THE BLOCK LIBRARY AND THE FAMILY CHROME ─────────────────
   Bright precision, restated for the home page. Everything above speaks in `.section`,
   `.card`, `.btn`, and none of it reaches a blueprint home, which draws through `.bk-*`
   plus its family's own chrome. The interior decisions being carried across are the
   three that make this lane recognisable at a glance: every corner is square (radius 0,
   with no exceptions), nothing is elevated (no shadow anywhere, no hover lift), and
   cells are ruled by a single neutral hairline rather than fenced by a fill.

   THE GROUNDS ARE LEFT EXACTLY WHERE THE BLOCKS PUT THEM, and that is deliberate, not
   timid. Section 5 of the interior rules already works this way: it squares `.card`,
   rules it, and flattens it, and never once writes `background`. A lane that repaints a
   plate owes that plate its ink too — `.bk-feat`, `.bk-tile` and `.bk-sit-card` are all
   dark plates carrying white type set in their own component, and `.bk-ict-ink` flips
   its cards to an ink fill from one band class up. None of them are named below, because
   shape is this lane's to change and colour is theirs. The hairline is mixed from the
   brand's own primary at two strengths, so it is this client's grey on navy-and-gold and
   this client's grey on hot-pink-and-lime, and a rule is not text: it has no AA
   threshold it can fail.
   ────────────────────────────────────────────────────────────────────────────── */
:where(.sl-body).refine-clinical-porcelain {
  /* The one device, as a token, stated once and read everywhere below. */
  --cp-hair: color-mix(in srgb, var(--c-primary) 16%, transparent);
  --cp-hair-strong: color-mix(in srgb, var(--c-primary) 34%, transparent);
}

/* 1. CARDS AND PANELS — square, unfilled, hairline-ruled, flat. The block library ships
      these at 12–24px radius over a soft drop shadow; both are the opposite of the
      claim this lane makes. NOT `.bk-feat`, NOT `.bk-tile`, NOT `.bk-sit-card`: see the
      header. The retail card's 5px accent stripe goes with the shorthand, on purpose —
      one weight of rule on all four sides is the shape. */
:where(.sl-body).refine-clinical-porcelain .bk-pillar, :where(.sl-body).refine-clinical-porcelain .bk-pcard, :where(.sl-body).refine-clinical-porcelain .bk-ccard, :where(.sl-body).refine-clinical-porcelain .bk-step, :where(.sl-body).refine-clinical-porcelain .bk-fcard, :where(.sl-body).refine-clinical-porcelain .bk-ict-card, :where(.sl-body).refine-clinical-porcelain .bk-credcard, :where(.sl-body).refine-clinical-porcelain .bk-grev-card, :where(.sl-body).refine-clinical-porcelain .bk-tier:not(.bk-feat), :where(.sl-body).refine-clinical-porcelain .bk-plinth {
  border-radius: 0;
  border: 1px solid var(--cp-hair);
  box-shadow: none;
}
/* Hover darkens the rule and moves nothing — same answer as `.cat-card:hover` inside. */
:where(.sl-body).refine-clinical-porcelain .bk-pillar:hover, :where(.sl-body).refine-clinical-porcelain .bk-pcard:hover, :where(.sl-body).refine-clinical-porcelain .bk-fcard:hover, :where(.sl-body).refine-clinical-porcelain .bk-ict-card:hover, :where(.sl-body).refine-clinical-porcelain .bk-tier:not(.bk-feat):hover {
  border-color: var(--cp-hair-strong);
  box-shadow: none;
  transform: none;
}
/* The clinical rhythm is compact: the library's 34–50px card padding is boutique air. */
:where(.sl-body).refine-clinical-porcelain .bk-pillar, :where(.sl-body).refine-clinical-porcelain .bk-pcard, :where(.sl-body).refine-clinical-porcelain .bk-ccard, :where(.sl-body).refine-clinical-porcelain .bk-ict-card {
  padding: clamp(18px, 2vw, 26px) clamp(20px, 2.2vw, 28px);
}

/* 2. CONTROLS — square, exact, unlit. No `color`, no `background`, and no `font-size`:
      a filled pill's label size is load-bearing (bold over 18.66px is WCAG large text,
      which is the only reason white clears AA on a raw accent), and shrinking it is how
      a lane silently fails a contrast gate it never touched. */
:where(.sl-body).refine-clinical-porcelain .bk-pill, :where(.sl-body).refine-clinical-porcelain .bk-btn, :where(.sl-body).refine-clinical-porcelain .bk-chip, :where(.sl-body).refine-clinical-porcelain .bk-city, :where(.sl-body).refine-clinical-porcelain .bk-pill-fill, :where(.sl-body).refine-clinical-porcelain .bk-btn-fill, :where(.sl-body).refine-clinical-porcelain .bk-pill-ghost, :where(.sl-body).refine-clinical-porcelain .bk-ict-pill, :where(.sl-body).refine-clinical-porcelain .bk-prose-pill {
  border-radius: 0;
  letter-spacing: 0.01em;
}
/* NOT the ring-drawn controls in the flattening rule: their outline IS an inset box-shadow, so
   `box-shadow: none` there does not flatten the control, it deletes its border.
   THIS LANE GOT THE PRINCIPLE RIGHT AND THE LIST SHORT. It excluded `.bk-pill-ghost` and stopped
   there, and the library draws two more the same way — `.bk-pill-outline`, PhotoStepCards' second
   action, and `.bk-btn-ghost` — so the rule was still deleting an outline, just a rarer one. That
   is why the list now comes out of scripts/ghost-ring.mjs, which reads the blocks, rather than out
   of whoever is editing the lane. See T6 on body.refine-warm-studio. */
:where(.sl-body).refine-clinical-porcelain :is(.bk-pill, :where(.sl-body) .bk-btn, :where(.sl-body) .bk-pill-fill, :where(.sl-body) .bk-btn-fill):not(:where(.bk-pill-ghost, :where(.sl-body) .bk-pill-outline, :where(.sl-body) .bk-btn-ghost)) { box-shadow: none; }
/* Every disc becomes a square — the interior rule, reaching the two round marks the
   block library draws. */
:where(.sl-body).refine-clinical-porcelain .bk-mark, :where(.sl-body).refine-clinical-porcelain .bk-q-badge { border-radius: 0; }
/* The small tracked-caps label, at this lane's size and tracking. Typography only: the
   block sets this label's ink off its own band, and that decision stays there. */
:where(.sl-body).refine-clinical-porcelain .bk-eyebrow-caps {
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.14em;
}
/* Figures line up in a column, which is what "precise" looks like in a price list. */
:where(.sl-body).refine-clinical-porcelain .bk-price, :where(.sl-body).refine-clinical-porcelain .bk-tier-name {
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}

/* 3. IMAGERY — square corners and no lift, so a photo reads as a specimen plate rather
      than a soft card. */
:where(.sl-body).refine-clinical-porcelain .bk-step-art img, :where(.sl-body).refine-clinical-porcelain .bk-prose-photo, :where(.sl-body).refine-clinical-porcelain .bk-prose-photo img, :where(.sl-body).refine-clinical-porcelain .bk-cond-ph img, :where(.sl-body).refine-clinical-porcelain .bk-tiers-art img, :where(.sl-body).refine-clinical-porcelain .bk-cities-map {
  border-radius: 0;
  box-shadow: none;
}

/* 4. THE FEATURED TIER gets the square corner and the flat surface, and nothing else. Its
      plate and the white type on it are one decision made inside the block; a lane that
      takes half of that takes the half that cannot be read. */
:where(.sl-body).refine-clinical-porcelain .bk-tier.bk-feat {
  border-radius: 0;
  box-shadow: none;
}

/* 5. EVERY FAMILY'S OWN CHROME — a rule and a corner, never a ground. The bar's colour
      and its light-or-dark logo are chosen together by the family (the community bar is
      a solid primary carrying white type), so a lane that paints the bar breaks the mark
      sitting on it. */
:where(.sl-body).refine-clinical-porcelain :is(.rt-nav, :where(.sl-body) .cm-nav, :where(.sl-body) .ed-nav, :where(.sl-body) .bh-nav, :where(.sl-body) .et-nav, :where(.sl-body) .bl-nav) {
  border-bottom: 1px solid var(--cp-hair);
}
:where(.sl-body).refine-clinical-porcelain :is(.rt-pill, :where(.sl-body) .cm-book, :where(.sl-body) .ed-pill, :where(.sl-body) .bh-pill, :where(.sl-body) .et-btn, :where(.sl-body) .bl-pill) {
  border-radius: 0;
  letter-spacing: 0.01em;
}
/* T6 (documented in full on body.refine-warm-studio): the reset skips the controls the
   renderers draw as an inset ring, because on those the shadow IS the border. `:where()`
   keeps the rule at the specificity it already had. */
:where(.sl-body).refine-clinical-porcelain :is(.rt-pill, :where(.sl-body) .cm-book, :where(.sl-body) .ed-pill, :where(.sl-body) .bh-pill, :where(.sl-body) .et-btn, :where(.sl-body) .bl-pill):not(:where(.rt-outline, :where(.sl-body) .rt-soft, :where(.sl-body) .et-btn-ghost, :where(.sl-body) .et-btn-ghost-white, :where(.sl-body) .bl-pill-ghost)) { box-shadow: none; }
/* The two families that draw their own FAQ rows: squared, flattened, and pulled into one
   continuous ruled stack by collapsing each row's hairline into the next. Read off the
   templates — the row is `.rt-q` / `.cm-q`, not the disclosure wrapped around it. */
:where(.sl-body).refine-clinical-porcelain :is(.rt-q, :where(.sl-body) .rt-q-flat, :where(.sl-body) .cm-q, :where(.sl-body) .cm-q-flat) {
  border-radius: 0;
  border: 1px solid var(--cp-hair);
  box-shadow: none;
  margin-bottom: -1px;
}

/* ── ESTATE: THE BLOCK LIBRARY AND THE FAMILY CHROME ──────────────────────────────
   Estate is display type over deep photographic rooms, and its plates are paper with ONE
   accent hairline, a 4px corner and no elevation whatsoever — the reference menu card, not
   a rounded shadowed tile. Its controls are small, near-square and set in tracked uppercase
   at 0.78rem; its product stands on a plinth at perfume scale; its headings are the largest
   thing on the page. Everything above this block says that in `.section`/`.card`/`.btn` and
   therefore reaches interior pages only. Restated here in the home page's vocabulary: the
   22px-and-a-soft-shadow plate becomes the 4px hairline plate (section 1), the 999px pill
   becomes the tracked rectangle (section 2), the thumbnail bag becomes the plinth render
   (section 3), and every family's bar gets the accent hairline and nothing else (section 5).

   THREE THINGS READ OFF THE BLOCK SOURCE RATHER THAN ASSUMED, each of which would have
   shipped a fault:
     - `.bk-pill-ghost` draws its outline as an INSET BOX-SHADOW, not a border. The blanket
       `box-shadow: none` both reference lanes put on their control group would delete that
       outline outright and leave an invisible button. So the reset is scoped to the FILLED
       controls, and the ghost is restated as a 1px inset ring in `currentColor` — its own
       ground's ink, whatever that ground turned out to be.
     - `.bk-price` is TWO different things: the tier figure in MembershipTiers and an entire
       dark price-ribbon BAND in FamilyPriceRibbon, which carries its own white type. Every
       rule here is scoped `.bk-tier .bk-price` so the band is never touched (T2).
     - `.bk-tile`, `.bk-sit-card` and `.bk-feat` all carry their own fill AND their own ink,
       set together in their own block — `.bk-feat` rebinds four tokens when it goes dark.
       None of them is repainted; `.bk-feat` gets the corner and the hairline and no ground.

   AND NO CONTROL IS INKED HERE (T1). The lane wants the tier name in the accent and the
   eyebrow in gold, and it does not say so: `--bk-accent-text` already resolves that per
   ground, and a (0,2,1) lane rule outranks it and gets the dark plate wrong. Shape, scale
   and face are the lane's; colour belongs to whoever paints the ground. Nothing below sets
   `color:` on anything, no nav gets a background, and the closing band is left alone (T4).
   ─────────────────────────────────────────────────────────────────────────────────── */

:where(.sl-body).refine-estate {
  /* The estate corner, stated once: rounded on the plates, a pill on the controls (2026-09-15). */
  --es-corner: 14px;
  --es-corner-sm: 999px;
  /* The hairline is the brand's own accent held back to a whisper, so it reads on paper AND
     on an ink plate without ever being text. */
  --es-edge: color-mix(in srgb, var(--c-accent) 40%, transparent);
  --es-track: 0.14em;
  --es-caps: 0.3em;
  /* The display face, with the block library's own token as the middle fallback — the
     interior lane says `--font-headline`, every block says `--font-heading`. */
  --es-display: var(--font-headline, var(--font-heading, serif));
}

/* 1. PLATES, AND THE TYPE ON THEM. Paper, one hairline, a 4px corner, no elevation. The
      second group ships its own fill or a family variant of one, so it gets the corner and
      loses the shadow and keeps its ground. */
:where(.sl-body).refine-estate :is(.bk-pillar, :where(.sl-body) .bk-pcard, :where(.sl-body) .bk-ccard, :where(.sl-body) .bk-credcard, :where(.sl-body) .bk-tier:not(.bk-feat)) {
  background: var(--c-surface);
  border: 1px solid var(--es-edge);
  border-radius: var(--es-corner);
  box-shadow: none;
}
:where(.sl-body).refine-estate :is(.bk-fcard, :where(.sl-body) .bk-ict-card, :where(.sl-body) .bk-grev-card) {
  border-radius: var(--es-corner);
  box-shadow: none;
}
:where(.sl-body).refine-estate :is(.bk-pillar, :where(.sl-body) .bk-pcard, :where(.sl-body) .bk-ccard, :where(.sl-body) .bk-tier:not(.bk-feat)):hover {
  border-color: var(--c-accent);
  transform: none;
  box-shadow: none;
}
/* TYPE SCALE COURAGE, the lane's first and largest measured gap, on the one page every
   visitor opens. The blocks set band headings between 30px and 46px; the references set
   theirs at 65–72. `.bk-home` wraps the whole blueprint page including the composed blocks,
   so this reaches every band heading at once. */
:where(.sl-body).refine-estate .bk-home h2 {
  font-family: var(--es-display);
  font-size: clamp(2.6rem, 4.4vw, 4rem);
  line-height: 1.08;
  letter-spacing: -0.01em;
  font-weight: 500;
}
/* THE RITUAL EYEBROW: wider tracking than the block default, smaller, and no colour. */
:where(.sl-body).refine-estate .bk-eyebrow-caps {
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: var(--es-caps);
}
/* THE PRODUCT IS PERFUME — the name in the display face, the price at counter scale. */
:where(.sl-body).refine-estate .bk-tier .bk-tier-name {
  font-family: var(--es-display);
  font-size: 0.95rem;
  letter-spacing: 0.2em;
  font-weight: 500;
}
:where(.sl-body).refine-estate .bk-tier .bk-price {
  font-size: clamp(3rem, 4.4vw, 4.25rem);
  letter-spacing: -0.02em;
}

/* 2. CONTROLS. Compact, tracked, uppercase, near-square — the references' small gold buttons
      against the library's 999px pills. Shape and scale only. */
:where(.sl-body).refine-estate :is(.bk-btn, :where(.sl-body) .bk-pill, :where(.sl-body) .bk-chip, :where(.sl-body) .bk-city) {
  border-radius: var(--es-corner-sm);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: var(--es-track);
  text-transform: uppercase;
}
/* The reset lands on the FILLED controls only. See the header: the ghost's outline IS a
   box-shadow, and it is restated as a hairline in the button's own ink instead. */
:where(.sl-body).refine-estate :is(.bk-pill-fill, :where(.sl-body) .bk-btn-fill) { box-shadow: none; }
:where(.sl-body).refine-estate .bk-pill-ghost { box-shadow: inset 0 0 0 1px currentColor; }
:where(.sl-body).refine-estate .bk-city { border-color: var(--es-edge); }

/* 3. IMAGERY. Square-ish corners everywhere, and the plinth at the scale the lane already
      gives the interior route's bag: the render is the moment, not a thumbnail. The stage
      itself comes off its cold hardcoded grey and onto the brand's own second stock. */
:where(.sl-body).refine-estate :is(.bk-step-art img, :where(.sl-body) .bk-prose-photo img, :where(.sl-body) .bk-cond-ph img, :where(.sl-body) .bk-tiers-art img, :where(.sl-body) .bk-cities-map) {
  border-radius: var(--es-corner);
}
:where(.sl-body).refine-estate .bk-plinth {
  background: var(--c-surface-alt);
  border-radius: var(--es-corner);
  height: clamp(320px, 30vw, 420px);
}
:where(.sl-body).refine-estate .bk-plinth img { height: clamp(360px, 34vw, 470px); }

/* 4. THE FEATURED TIER GETS THE CORNER AND THE HAIRLINE AND NOTHING ELSE. Its plate is dark
      and it rebinds four ink tokens to match, in its own block — taking half of that pairing
      is the fault this shelf keeps paying for. A border touches no ink, so it is safe. */
:where(.sl-body).refine-estate .bk-tier.bk-feat {
  border: 1px solid color-mix(in srgb, var(--c-accent) 55%, transparent);
  border-radius: var(--es-corner);
  box-shadow: none;
}

/* 5. EVERY FAMILY'S OWN CHROME — a hairline under the bar, never a ground (T2): the bar picks
      its colour and its light-or-dark logo together, and that decision is the family's. The
      estate family additionally sets its own button corner from a `data-btn` attribute, which
      outranks the shape rule below and is meant to; the scale and tracking still land. */
:where(.sl-body).refine-estate :is(.rt-nav, :where(.sl-body) .cm-nav, :where(.sl-body) .ed-nav, :where(.sl-body) .bh-nav, :where(.sl-body) .et-nav, :where(.sl-body) .bl-nav) {
  border-bottom: 1px solid var(--es-edge);
}
:where(.sl-body).refine-estate :is(.rt-pill, :where(.sl-body) .cm-book, :where(.sl-body) .ed-pill, :where(.sl-body) .bh-pill, :where(.sl-body) .et-btn, :where(.sl-body) .bl-pill) {
  border-radius: var(--es-corner-sm);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: var(--es-track);
  text-transform: uppercase;
}
/* QUESTIONS IN THE DISPLAY FACE, the interior lane's FAQ move restated: the accordion reads
   as an index of chapters, not a support widget. The ROW is the thing to dress — painting
   the disclosure around it double-borders every question. No ground, so no re-ink needed. */
:where(.sl-body).refine-estate :is(.rt-q, :where(.sl-body) .rt-q-flat, :where(.sl-body) .cm-q, :where(.sl-body) .cm-q-flat) {
  font-family: var(--es-display);
  font-weight: 500;
  border-radius: var(--es-corner);
}

/* ── DARK-LUXE: THE BLOCK LIBRARY AND THE FAMILY CHROME ───────────────────────────
   This lane is line, never shading: flat fields of colour, a near-square 2px corner, and a thin
   warm-metal hairline drawn around every object on the page. Its interior route already says so
   in `.section`/`.card`/`.btn` — cards lose their blur and keep a single accent rule (:5646), the
   light bands become framed plates (:5666), editorial photographs wear the ARCH with an accent
   rule set INSIDE their own edge (:5798), buttons are flat with no glow (:5956), and the toolbar
   closes on an accent hairline over letterspaced caps (:7895). None of that reaches a blueprint
   HOME page, which draws through `.bk-*` plus its family's own chrome. Restated here in that
   vocabulary: block cards are hairline-ruled and near-square with no drop shadow and no lift on
   hover, pills and buttons lose the 999px capsule for the same 2px corner and take caps at wide
   tracking, the eyebrow closes on a short accent rule under the words, the editorial block photo
   takes the arch and the inset accent frame, the product plinth drops its cold grey stage and its
   drop-shadow for the brand's own stock, and every family's bar is closed with a hairline.

   THE TRAPS THIS BLOCK IS WRITTEN AROUND:
     T1  not one `color:` here. Every ink on this page is already ground-aware and a lane rule
         would outrank it and guess wrong. The only colours introduced are RULES mixed from the
         brand's own --c-accent at the three strengths the lane already uses (62 / 88 / 42), plus
         one faint tint under a product photograph. A rule has no contrast threshold to clear.
     T2  no `background` on any nav — the bar's ground and the light-or-dark logo chosen against
         it are ONE decision and it belongs to the family. `.bk-feat` gets shape and nothing else,
         and `.bk-tile` / `.bk-sit-card` are left alone: all three carry their own type.
     T4  `.final-cta` and `.section-hub-cta` are not touched.
     T5  and the reason for the whole block: a lane that dresses only the interior route leaves
         the home page — the one page every visitor sees — on the platform default.

   AND THE ONE THIS LANE ADDS. A hairline BOX belongs on a card that has a plate; five block
   layouts deliberately strip the plate and become ruled rows with `padding: Nrem 0`, and a box
   drawn round those is a border hugging the type with no air either side — the defect this file
   already records as "a plate owns its padding". Those five are named out by hand below, exactly
   the way the interior rules carry their `:not(.comp-…)` chains.
   ────────────────────────────────────────────────────────────────────────────── */

:where(.sl-body).refine-dark-luxe {
  --dl-rule: color-mix(in srgb, var(--c-accent) 62%, transparent);
  --dl-rule-strong: color-mix(in srgb, var(--c-accent) 88%, transparent);
  --dl-rule-quiet: color-mix(in srgb, var(--c-accent) 42%, transparent);
  --dl-edge: 2px;
}

/* 1. CARDS AND PANELS — ruled, not shaded. The plate stays exactly where the block put it
      (repainting a plate obliges you to re-ink it); what changes is that the blur goes, the 22px
      capsule corner becomes the lane's 2px edge, and one accent hairline draws the object. The
      five ruled-row layouts are excluded: they have no plate for a box to belong to. */
:where(.sl-body).refine-dark-luxe .bk-pillars:not(.bk-pillars-l-stripes) .bk-pillar, :where(.sl-body).refine-dark-luxe .bk-tiers:not(.bk-tiers-l-ledger) .bk-tier:not(.bk-feat), :where(.sl-body).refine-dark-luxe .bk-tl:not(.bk-tl-l-ledger) .bk-step, :where(.sl-body).refine-dark-luxe .bk-ict:not(.bk-ict-l-ledger) .bk-ict-card, :where(.sl-body).refine-dark-luxe .bk-fcards:not(.bk-fcards-editorial):not(.bk-fcards-l-ledger):not(.bk-fcards-l-stagger) .bk-fcard, :where(.sl-body).refine-dark-luxe .bk-pcard, :where(.sl-body).refine-dark-luxe .bk-ccard, :where(.sl-body).refine-dark-luxe .bk-credcard, :where(.sl-body).refine-dark-luxe .bk-grev-card {
  border: 1px solid var(--dl-rule);
  border-radius: var(--dl-edge);
  box-shadow: none;
}
/* Hover is a change of LINE, not a lift: this page has no shadow to deepen and nothing on it
   moves. The rule simply gains presence. */
:where(.sl-body).refine-dark-luxe .bk-pillars:not(.bk-pillars-l-stripes) .bk-pillar:hover, :where(.sl-body).refine-dark-luxe .bk-tiers:not(.bk-tiers-l-ledger) .bk-tier:not(.bk-feat):hover, :where(.sl-body).refine-dark-luxe .bk-fcards:not(.bk-fcards-editorial):not(.bk-fcards-l-ledger):not(.bk-fcards-l-stagger) .bk-fcard:hover, :where(.sl-body).refine-dark-luxe .bk-pcard:hover {
  border-color: var(--dl-rule-strong);
  transform: none;
  box-shadow: none;
}

/* 2. CONTROLS — the capsule is the one shape this lane never draws. Every button becomes a flat
      2px-cornered block of letterspaced caps, and the filled ones drop the glow the accent CTA
      ships with. `.bk-pill-ghost` keeps its inset ring untouched — that ring IS the button, and
      a lane that clears it ships an invisible control. Chips and city entries take the corner
      only: several city layouts render as plain ruled text with no box to re-corner. */
:where(.sl-body).refine-dark-luxe .bk-pill, :where(.sl-body).refine-dark-luxe .bk-btn, :where(.sl-body).refine-dark-luxe .bk-pill-fill, :where(.sl-body).refine-dark-luxe .bk-btn-fill, :where(.sl-body).refine-dark-luxe .bk-pill-ghost, :where(.sl-body).refine-dark-luxe .bk-ict-pill, :where(.sl-body).refine-dark-luxe .bk-prose-pill {
  border-radius: var(--dl-edge);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-weight: 600;
}
:where(.sl-body).refine-dark-luxe .bk-pill-fill, :where(.sl-body).refine-dark-luxe .bk-btn-fill { box-shadow: none; }
:where(.sl-body).refine-dark-luxe .bk-chip, :where(.sl-body).refine-dark-luxe .bk-city { border-radius: var(--dl-edge); }

/* 3. TYPE — the two marks that carry the lane. The eyebrow closes on a short accent rule under
      the words instead of floating over the heading; `inline-block` makes that rule follow
      whatever alignment the band already set rather than pinning it left. The price and the tier
      name step into the display face, where every other number on this lane is set. Colour is
      left entirely alone on all three. */
:where(.sl-body).refine-dark-luxe .bk-eyebrow-caps {
  display: inline-block;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--dl-rule);
  letter-spacing: 0.28em;
}
:where(.sl-body).refine-dark-luxe .bk-price {
  font-family: var(--font-heading);
  font-weight: 500;
  letter-spacing: -0.01em;
}
:where(.sl-body).refine-dark-luxe .bk-tier-name {
  font-family: var(--font-heading);
  text-transform: uppercase;
  letter-spacing: 0.16em;
}

/* 4. IMAGERY — flat and squared, except the one editorial photograph, which takes the arch and
      the accent frame set INSIDE its own edge, the lane's `.itr-media` treatment. The map and the
      step art stay square: a diagram and a small illustrative crop are objects, not editorial
      pictures, and this lane has never arched those. The product plinth is the last cold grey
      surface in the library and the only drop-shadow left in the composition; it becomes the
      brand's own stock faintly warmed, and the bag stands on it unblurred. */
:where(.sl-body).refine-dark-luxe .bk-step-art, :where(.sl-body).refine-dark-luxe .bk-tiers-art, :where(.sl-body).refine-dark-luxe .bk-cities-map, :where(.sl-body).refine-dark-luxe .bk-cond-ph img {
  border-radius: var(--dl-edge);
  box-shadow: none;
}
:where(.sl-body).refine-dark-luxe .bk-prose-photo { position: relative; }
:where(.sl-body).refine-dark-luxe .bk-prose-photo img { border-radius: var(--arch); }
:where(.sl-body).refine-dark-luxe .bk-prose-photo::after {
  content: '';
  position: absolute;
  inset: 10px;
  border: 1px solid var(--dl-rule-strong);
  border-radius: var(--arch);
  pointer-events: none;
  z-index: 2;
}
/* A PLINTH IS A GROUND, AND --c-surface IS NOT ONE ON A DARK SITE.
   This mixed the accent into `--c-surface` on the assumption that surface means "the paper".
   It does on a light site. On a dark one `--c-surface` is the site's WHITE INK - it is what
   102 rules in this file use for `color:` - and it must stay white or the closing band goes
   dark-on-dark. So this drew a cream shelf on a charcoal page, under every product, on the
   one brand whose whole brief is a dark visual system. The block's own ground token comes
   first and `--c-surface` remains the fallback, so a brand that has not named one is
   byte-identical. */
:where(.sl-body).refine-dark-luxe .bk-plinth { background: color-mix(in srgb, var(--c-accent) 7%, var(--bk-plinth-bg, var(--c-surface))); }
:where(.sl-body).refine-dark-luxe .bk-plinth img { filter: none; }

/* 5. THE FEATURED TIER — shape only. Its plate and the white type on it are one decision made
      inside the block, and a lane that takes half of it takes the half that cannot be read. So it
      gets the lane's corner and loses its blur; its colour is none of this lane's business. */
:where(.sl-body).refine-dark-luxe .bk-tier.bk-feat {
  border-radius: var(--dl-edge);
  box-shadow: none;
}

/* 6. EVERY FAMILY'S OWN CHROME. A blueprint home draws its bar, its buttons and its FAQ from the
      family template, so nothing above reaches them. The bar gets the same accent hairline that
      closes the interior toolbar — a border and nothing else. */
:where(.sl-body).refine-dark-luxe :is(.rt-nav, :where(.sl-body) .cm-nav, :where(.sl-body) .ed-nav, :where(.sl-body) .bh-nav, :where(.sl-body) .et-nav, :where(.sl-body) .bl-nav) {
  border-bottom: 1px solid var(--dl-rule-quiet);
  box-shadow: none;
}
:where(.sl-body).refine-dark-luxe :is(.rt-pill, :where(.sl-body) .cm-book, :where(.sl-body) .ed-pill, :where(.sl-body) .bh-pill, :where(.sl-body) .et-btn, :where(.sl-body) .bl-pill) {
  border-radius: var(--dl-edge);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-weight: 600;
}
/* T6 (documented in full on body.refine-warm-studio): the reset skips the controls the
   renderers draw as an inset ring, because on those the shadow IS the border. `:where()`
   keeps the rule at the specificity it already had. */
:where(.sl-body).refine-dark-luxe :is(.rt-pill, :where(.sl-body) .cm-book, :where(.sl-body) .ed-pill, :where(.sl-body) .bh-pill, :where(.sl-body) .et-btn, :where(.sl-body) .bl-pill):not(:where(.rt-outline, :where(.sl-body) .rt-soft, :where(.sl-body) .et-btn-ghost, :where(.sl-body) .et-btn-ghost-white, :where(.sl-body) .bl-pill-ghost)) { box-shadow: none; }
:where(.sl-body).refine-dark-luxe .rt-hero-art img { border-radius: var(--dl-edge); }
/* The row is the summary, not the disclosure wrapped round it: `.rt-qd` already carries the air
   between questions, so dressing it as well draws a second border nobody asked for. Rule the ROW
   — the framed-plate accordion the interior route gets at :8066, minus the fill, because these
   rows already have one and a plate repainted is a plate that must be re-inked. */
:where(.sl-body).refine-dark-luxe :is(.rt-q, :where(.sl-body) .rt-q-flat, :where(.sl-body) .cm-q, :where(.sl-body) .cm-q-flat) {
  border: 1px solid var(--dl-rule-quiet);
  border-radius: var(--dl-edge);
  box-shadow: none;
}

/* ══ DESIGN LANE: panel-inset ═════════════════════════════════════════════════════════════════
   PANELLED. The eleventh lane, and the first authored after the harness existed — proved on all
   five designs before any client wore it, which is the whole point of scripts/lane-gate.mjs.

   WHY A NEW ONE AT ALL. tools/lane-pick.mjs refused every lane on the shelf for this brief: all
   ten are already worn inside the IV vertical, and handing a client a lane their competitor down
   the road is wearing is the sameness the library exists to prevent. The brief also refuses two of
   the closest fits in its own words — "not clinical, not a spa" — which rules out
   clinical-porcelain and spa-luxe by instruction rather than by taste.

   THE REGISTER THAT WAS MISSING IS MATERIALITY. Read the shelf: two dark rooms, three porcelains,
   an ivory, an estate, a spa, a poster and a stack of rules. Every one of them is about LIGHT
   (bright, dark, ivory, sunlit) or about DRAWING (rules, keylines, shelves). None is about a
   SURFACE having depth — a panelled door, a mounted print, a picture rail. That is a whole
   register, and it is the one an old wood-panelled house asks for.

   THE DEVICE IS THE DOUBLE EDGE, and it is one property doing all the work. Every plate, every
   photograph and every outlined control takes a hairline border AND a second hairline set four
   pixels inside it, with the plate's own ground showing between the two — the way a panelled door
   has a moulding line inside its frame. Nothing else in the fleet has it. It survives at squint
   distance, which is what makes a lane a lane rather than a palette, and it is the same discipline
   pill-porcelain uses with its speech bubble: one shape, applied everywhere, nothing else.

   IT IS DRAWN WITH `outline`, NOT WITH A SECOND BACKGROUND, AND THAT IS DELIBERATE (T2). An inset
   box-shadow would have to paint the four-pixel gap in some colour, which means guessing the
   ground the plate is standing on — and repainting a plate whose ink you do not also re-set is the
   single trap this stylesheet has paid for most often. `outline` with a negative `outline-offset`
   draws inside the border and lets whatever the plate already is show through the gap, so a white
   card on paper and a dark plate in a room both get the moulding and neither gets repainted.

   BOTH LINES ARE `currentColor` (T1). A lane may shape a control; it may not colour one whose
   ground it does not own. Mixing the frame out of `currentColor` means the moulding is dark on a
   pale card and light on a dark one, on every family, without this file naming a single colour or
   knowing which grounds exist. It is also why the lane needs no `:not()` chain for dark plates:
   the device adapts instead of being excluded.

   SEPARATION IS BY STOCK, NOT BY LINE. Bands alternate between the two page stocks with generous
   air and no divider — the opposite of ruled-stack, which flattens to one stock and separates with
   a 3px rule, and of block-poster, which keylines everything square. Three lanes, three different
   answers to the same question, which is what a library is for.

   BOTH ALTERNATING BEATS ARE DECLARED (T3), for the reason written twice above this in the file: a
   lane that paints only the even beat makes a brand whose default ground IS a tint alternate tint
   with tint, and page-rules P3 refuses every listing page at once.

   THE CLOSING BAND AND THE ROOMS ARE LEFT ALONE (T4). A room is a deliberate dark moment and is
   not this lane's to flatten; the closing ask lands directly under one on a hub page, so painting
   it in the same stock is one colour twice with no seam.

   AND IT DRESSES BOTH RENDERERS (T5, sections 8-9). Everything before section 8 speaks the
   interior route's vocabulary — `.section`, `.card`, `.btn` — which a home page never calls.
   Six of the first nine lanes stopped there and left every home page on the platform default.
   @lane panel-inset | plates framed with a moulding line set inside the edge; stock, not shadow | suits: panelled heritage house wood joinery discreet unhurried appointment intimate traditional coastal harbour tailored
   */
:where(.sl-body).refine-panel-inset {
  /* The two weights of the one device. Both mixed out of currentColor so the moulding follows the
     ink of whatever it lands on — see the header (T1). */
  --pi-edge: color-mix(in srgb, currentColor 30%, transparent);
  --pi-mould: color-mix(in srgb, currentColor 15%, transparent);
  --pi-inset: 5px;
  /* A ROOM WITH AIR IN IT. The first pass used the same band rhythm as every other lane on the
     shelf, which is a strange thing for a lane whose whole subject is unhurriedness. */
  --pi-air: clamp(5.5rem, 7vw, 8.5rem);
  /* AIR ON THE HOME PAGE TOO — for the bands this lane can reach. --pi-air is set on
     `main > section.section`, which a blueprint home page has none of: its bands are
     `.bk-home > section`, and the ones drawn from the block library take their vertical air from
     --bk-rhythm. Setting the TOKEN rather than a padding leaves --bk-pad, --bk-col and --bk-align
     exactly where the page grid put them, which is what grid-lint's one-edge-policy rule protects.
     Measured: this lifts the block bands and leaves the family's own chrome bands — the hero, the
     FAQ, the closing ask — at the padding the family chose for them. That is the right split; the
     lane dresses the content, the family keeps its furniture. */
  --bk-rhythm: clamp(4.25rem, 7vw, 7.5rem);
  --card-radius: 14px;
  --btn-radius: 999px;
  --input-radius: 12px;
  --card-shadow: none;
  --card-hover-shadow: none;
  --card-border-width: 1px;
}

/* 1. BOTH BEATS, BOTH RHYTHMS (T3). Rooms, photo bands and the closing ask are excluded exactly as
      every other lane excludes them (T4). */
:where(.sl-body).refine-panel-inset.sections-alternate main > section.section:nth-of-type(odd):not(.sec-room):not(.sec-photo):not(.final-cta):not(.section-hub-cta), :where(.sl-body).refine-panel-inset.bands-paper main > section.section:nth-of-type(odd):not(.sec-room):not(.sec-photo):not(.final-cta):not(.section-hub-cta) {
  background: var(--c-surface);
}
:where(.sl-body).refine-panel-inset.sections-alternate main > section.section:nth-of-type(even):not(.sec-room):not(.sec-photo):not(.final-cta):not(.section-hub-cta), :where(.sl-body).refine-panel-inset.bands-paper main > section.section:nth-of-type(even):not(.sec-room):not(.sec-photo):not(.final-cta):not(.section-hub-cta) {
  background: var(--c-surface-alt);
}
:where(.sl-body).refine-panel-inset main > section.section {
  padding-top: var(--pi-air);
  padding-bottom: var(--pi-air);
}

/* 2. TYPE. Unhurried rather than loud: normal tracking, comfortable leading, and the eyebrow set in
      small tracked caps so it reads as a plate label under the moulding. No colour and no font
      family — both are the brand's (T1). */
/* WHAT THIS DOES AND DOES NOT REACH, measured in a browser on the built page rather than assumed.
   It sets the case on every heading the INTERIOR route and the block library draw. It does NOT
   reach a heading inside a blueprint BLOCK: those carry Astro's scoped attribute and their rules
   live in a \3c style> the page emits AFTER this stylesheet, so they win any specificity tie by source
   order. Beating them needs a longer selector chain for every block in the library, which is a
   specificity war a lane should not start — the family's own typography is the family's.
   The claim is therefore narrowed rather than escalated: an earlier version of this comment said
   the lane sets its headings in sentence case, and on the one page every visitor sees, it did not.
   A comment that overstates is worse than no comment, because the next reader stops checking. */
:where(.sl-body).refine-panel-inset :is(.rt, :where(.sl-body) .cm, :where(.sl-body) .ed, :where(.sl-body) .bh, :where(.sl-body) .et, :where(.sl-body) .bl) :is(h1, :where(.sl-body) h2), :where(.sl-body).refine-panel-inset h1, :where(.sl-body).refine-panel-inset h2 {
  /* Headings in sentence case for the same reason as the buttons. The eyebrow keeps its small caps
     (section 2 below), so the page still has ONE thing set in capitals and it is the smallest thing
     on it — which is the whole difference between quiet and shouty. */
  text-transform: none;
  letter-spacing: -0.005em;
  line-height: 1.14;
  text-wrap: balance;
}
:where(.sl-body).refine-panel-inset h3 { letter-spacing: 0; }
:where(.sl-body).refine-panel-inset .eyebrow, :where(.sl-body).refine-panel-inset .bk-eyebrow-caps {
  text-transform: uppercase;
  letter-spacing: 0.18em;
  font-size: 0.7rem;
  font-weight: 600;
}

/* 3. THE DEVICE, on every plate the interior route draws. Not `.tier-featured`: it is a dark plate
      carrying white type set in its own component, and a lane that restyles a plate it will not
      also re-ink is trap two (T2). It gets the corner in section 5 and nothing else. */
:where(.sl-body).refine-panel-inset .card, :where(.sl-body).refine-panel-inset .feature-card, :where(.sl-body).refine-panel-inset .cat-card, :where(.sl-body).refine-panel-inset .step-card, :where(.sl-body).refine-panel-inset .review-card, :where(.sl-body).refine-panel-inset .whyus-card, :where(.sl-body).refine-panel-inset .pkg-card, :where(.sl-body).refine-panel-inset .tier-card:not(.tier-featured), :where(.sl-body).refine-panel-inset .faq-item {
  /* NO FILL. A panel is defined by its mouldings, not by being a different colour from the wall —
     and a filled card with a line round it is what three other lanes on this shelf already are.
     Transparent, so the plate reads as an area of the band that has been FRAMED rather than as a
     card dropped onto it. Safe to do here without re-inking (T2) because taking a fill AWAY leaves
     the band's own ink, which the band already set for itself. */
  background: transparent;
  border: 1px solid var(--pi-edge);
  border-radius: 2px;
  box-shadow: none;
  outline: 1px solid var(--pi-mould);
  outline-offset: calc(var(--pi-inset) * -1);
}
/* The hover is the moulding coming forward, not the plate lifting. Nothing moves. */
:where(.sl-body).refine-panel-inset .card:hover, :where(.sl-body).refine-panel-inset .feature-card:hover, :where(.sl-body).refine-panel-inset .cat-card:hover, :where(.sl-body).refine-panel-inset .step-card:hover, :where(.sl-body).refine-panel-inset .pkg-card:hover, :where(.sl-body).refine-panel-inset .tier-card:not(.tier-featured):hover {
  border-color: var(--pi-edge);
  outline-color: var(--pi-edge);
  transform: none;
  box-shadow: none;
}

/* 4. CONTROLS. Shape only (T1). The outlined button takes the same double edge, which is where the
      device is most legible; the filled one keeps whatever ink and ground it already had and takes
      the corner alone. `currentColor` on the secondary means it is correct on a photographic hero,
      a gradient hero and the closing band without this lane naming any of them. */
:where(.sl-body).refine-panel-inset .btn, :where(.sl-body).refine-panel-inset .btn-primary, :where(.sl-body).refine-panel-inset .btn-secondary {
  border-radius: 2px;
  /* SENTENCE CASE, SET DELIBERATELY. Every other lane on the shelf shouts its controls in capitals,
     and a house that answers the telephone by name does not. Declared rather than left alone,
     because the families set capitals themselves and silence here inherits them. */
  text-transform: none;
  letter-spacing: 0.01em;
  box-shadow: none;
}
:where(.sl-body).refine-panel-inset .btn-secondary {
  background: transparent;
  border: 1px solid currentColor;
  outline: 1px solid color-mix(in srgb, currentColor 35%, transparent);
  outline-offset: -4px;
}

/* 5. THE FEATURED TIER GETS THE CORNER AND THE MOULDING, NOT THE PAINT. Its dark plate and its
      white type are one decision made in its own component; the moulding is drawn in currentColor,
      so on that plate it comes out light and reads correctly without anything being repainted. */
:where(.sl-body).refine-panel-inset .tier-card.tier-featured {
  border-radius: 2px;
  outline: 1px solid var(--pi-mould);
  outline-offset: calc(var(--pi-inset) * -1);
}

/* 6. THE FAQ AND THE POLICY LIST — the two every lane forgets, named in DESIGN-LANES.md's own
      definition of done. Each row is its own small panel rather than a line in a stack. */
:where(.sl-body).refine-panel-inset .faq-item + .faq-item { margin-top: 0.6rem; }
:where(.sl-body).refine-panel-inset .faq-item summary { font-weight: 600; padding: 1.05rem 1.15rem; }

/* 7. IMAGERY IS MOUNTED, NOT FLOATED. The same moulding around a photograph reads as a mounted
      print on a panelled wall, which is the whole reference. */
:where(.sl-body).refine-panel-inset .section figure img, :where(.sl-body).refine-panel-inset .img-text-section img, :where(.sl-body).refine-panel-inset .step-photo img {
  border-radius: 2px;
  box-shadow: none;
}
:where(.sl-body).refine-panel-inset .section figure, :where(.sl-body).refine-panel-inset .img-text-section .itr-media {
  border: 1px solid var(--pi-edge);
  border-radius: 2px;
  padding: var(--pi-inset);
}

/* ── 8. THE BLOCK LIBRARY — the half of the site a lane written only in `.section` never reaches.
      NOT `.bk-feat` (a dark plate with white type set in the block), and NOT `.bk-tile` or
      `.bk-sit-card`, both of which carry their own fill. Every name below was read off
      src/components/blocks rather than guessed — block-poster's first cut named a class the
      community design does not emit and the rule was dead on arrival. */
:where(.sl-body).refine-panel-inset .bk-card, :where(.sl-body).refine-panel-inset .bk-pillar, :where(.sl-body).refine-panel-inset .bk-pcard, :where(.sl-body).refine-panel-inset .bk-tier:not(.bk-feat), :where(.sl-body).refine-panel-inset .bk-step, :where(.sl-body).refine-panel-inset .bk-ccard, :where(.sl-body).refine-panel-inset .bk-ict-card, :where(.sl-body).refine-panel-inset .bk-fcard, :where(.sl-body).refine-panel-inset .bk-credcard, :where(.sl-body).refine-panel-inset .bk-grev-card, :where(.sl-body).refine-panel-inset .bk-plinth {
  background: transparent;
  border: 1px solid var(--pi-edge);
  border-radius: 2px;
  box-shadow: none;
  outline: 1px solid var(--pi-mould);
  outline-offset: calc(var(--pi-inset) * -1);
}
:where(.sl-body).refine-panel-inset .bk-card:hover, :where(.sl-body).refine-panel-inset .bk-pillar:hover, :where(.sl-body).refine-panel-inset .bk-pcard:hover, :where(.sl-body).refine-panel-inset .bk-tier:not(.bk-feat):hover, :where(.sl-body).refine-panel-inset .bk-fcard:hover {
  outline-color: var(--pi-edge);
  transform: none;
  box-shadow: none;
}
/* The featured tier, again: the corner and the moulding, never the paint. */
:where(.sl-body).refine-panel-inset .bk-tier.bk-feat {
  border-radius: 2px;
  outline: 1px solid var(--pi-mould);
  outline-offset: calc(var(--pi-inset) * -1);
}
:where(.sl-body).refine-panel-inset .bk-btn, :where(.sl-body).refine-panel-inset .bk-pill, :where(.sl-body).refine-panel-inset .bk-chip, :where(.sl-body).refine-panel-inset .bk-city, :where(.sl-body).refine-panel-inset .bk-ict-pill, :where(.sl-body).refine-panel-inset .bk-prose-pill {
  border-radius: 2px;
  text-transform: none;
  letter-spacing: 0.01em;
}
/* T6 (documented in full on body.refine-warm-studio): the reset skips the controls the
   renderers draw as an inset ring, because on those the shadow IS the border. `:where()`
   keeps the rule at the specificity it already had. */
:where(.sl-body).refine-panel-inset :is(.bk-btn, :where(.sl-body) .bk-pill, :where(.sl-body) .bk-chip, :where(.sl-body) .bk-city, :where(.sl-body) .bk-ict-pill, :where(.sl-body) .bk-prose-pill):not(:where(.bk-pill-ghost, :where(.sl-body) .bk-pill-outline, :where(.sl-body) .bk-btn-ghost)) { box-shadow: none; }
:where(.sl-body).refine-panel-inset .bk-step-art img, :where(.sl-body).refine-panel-inset .bk-prose-photo img, :where(.sl-body).refine-panel-inset .bk-cond-ph img, :where(.sl-body).refine-panel-inset .bk-tiers-art img, :where(.sl-body).refine-panel-inset .bk-cities-map { border-radius: 2px; }
:where(.sl-body).refine-panel-inset .bk-step-art, :where(.sl-body).refine-panel-inset .bk-prose-photo, :where(.sl-body).refine-panel-inset .bk-cond-ph {
  border: 1px solid var(--pi-edge);
  border-radius: 2px;
  padding: var(--pi-inset);
}

/* ── 9. EVERY FAMILY'S OWN CHROME. A border and a shape, never a ground (T2): the bar's colour and
      its logo are one decision, and they belong to the family. */
:where(.sl-body).refine-panel-inset :is(.rt-nav, :where(.sl-body) .cm-nav, :where(.sl-body) .ed-nav, :where(.sl-body) .bh-nav, :where(.sl-body) .et-nav, :where(.sl-body) .bl-nav) {
  /* A PICTURE RAIL, not a hairline: 2px, the same weight as the frames below it, so the bar reads as
     the top member of the same joinery rather than as a divider. Still only a BORDER — the bar's
     colour is the family's (T2). */
  border-bottom: 2px solid var(--pi-edge);
}
:where(.sl-body).refine-panel-inset :is(.rt-pill, :where(.sl-body) .cm-book, :where(.sl-body) .ed-pill, :where(.sl-body) .bh-pill, :where(.sl-body) .et-btn, :where(.sl-body) .bl-pill) {
  border-radius: 2px;
  /* The families set their own controls in capitals, so silence here inherits a shout. */
  text-transform: none;
  letter-spacing: 0.01em;
}
/* The families that draw their own FAQ rows get the same small panel. */
:where(.sl-body).refine-panel-inset :is(.rt-qd, :where(.sl-body) .rt-q, :where(.sl-body) .rt-q-flat, :where(.sl-body) .cm-q, :where(.sl-body) .cm-q-flat) {
  border: 1px solid var(--pi-edge);
  border-radius: 2px;
  box-shadow: none;
  outline: 1px solid var(--pi-mould);
  outline-offset: calc(var(--pi-inset) * -1);
}

/* ══ DESIGN LANE: offset-slab ═════════════════════════════════════════════════════════════════
   THE TWELFTH LANE, and the register the shelf did not have: WEIGHT.

   Read the other eleven. Every one of them separates a plate from its band with a LINE (a hairline,
   a keyline, a moulding, a 2px rule) or with NOTHING (a fill, a stock change, air). Exactly one
   raises a plate at all, and it does it with a soft blurred shadow. Nothing on the shelf makes a
   plate look like an OBJECT — a thing with a side to it, sitting on the page rather than printed
   into it. A brand whose whole voice is direct and physical had nothing to wear.

   THE DEVICE IS A HARD OFFSET BLOCK. Every plate, every photograph and every control drops a solid
   rectangle down and to the right — no blur, no gradient, no opacity ramp. It is one property
   (`box-shadow: Npx Npx 0`), it survives at squint distance better than any line can, and it is
   the one thing on this shelf that reads as depth without reading as gloss.

   THE BLOCK IS MIXED OUT OF `currentColor` (T1). A lane may shape a control; it may not colour one
   whose ground it does not own. Deriving the block from the ink of wherever the plate lands means
   it is dark on a pale band and pale on a dark one, on every family, without this file naming a
   single colour or knowing which grounds exist — and it needs no `:not()` chain for dark plates,
   because it adapts instead of being excluded.

   NOTHING IS REPAINTED (T2). The block is drawn OUTSIDE the plate; the plate's own fill and its own
   ink are left exactly as its component set them. That is deliberate — the trap this stylesheet has
   paid for most often is a lane restyling a plate whose ink it does not also re-set.

   AND THE SHAPES ARGUE. Square, heavily-drawn plates carrying fully round controls: the corner of
   the card and the corner of the button disagree on purpose, which is the pairing nothing else on
   the shelf makes and the reason this reads as one design rather than as block-poster with a
   shadow. Headings are set tight and heavy against it.

   BOTH ALTERNATING BEATS ARE DECLARED (T3), the rooms and the closing band are left alone (T4), and
   it dresses both renderers (T5, sections 7-8). The five traps are commented on
   body.refine-warm-studio above.
   @lane offset-slab | plates drop a hard offset block, square and heavy, with fully round controls | suits: bold graphic direct physical energetic sporty athletic recovery gym young punchy confident modern
   */
:where(.sl-body).refine-offset-slab {
  --os-block: color-mix(in srgb, currentColor 26%, transparent);
  --os-edge: color-mix(in srgb, currentColor 78%, transparent);
  --os-drop: 7px;
  --os-air: clamp(4rem, 6vw, 6.5rem);
  --card-radius: 0px;
  --btn-radius: 999px;
  --input-radius: 999px;
  --card-shadow: none;
  --card-hover-shadow: none;
  --card-border-width: 2px;
}

/* 1. BOTH BEATS, BOTH RHYTHMS (T3); rooms, photo bands and the closing ask excluded (T4). */
:where(.sl-body).refine-offset-slab.sections-alternate main > section.section:nth-of-type(odd):not(.sec-room):not(.sec-photo):not(.final-cta):not(.section-hub-cta), :where(.sl-body).refine-offset-slab.bands-paper main > section.section:nth-of-type(odd):not(.sec-room):not(.sec-photo):not(.final-cta):not(.section-hub-cta) {
  background: var(--c-surface);
}
:where(.sl-body).refine-offset-slab.sections-alternate main > section.section:nth-of-type(even):not(.sec-room):not(.sec-photo):not(.final-cta):not(.section-hub-cta), :where(.sl-body).refine-offset-slab.bands-paper main > section.section:nth-of-type(even):not(.sec-room):not(.sec-photo):not(.final-cta):not(.section-hub-cta) {
  background: var(--c-surface-alt);
}
:where(.sl-body).refine-offset-slab main > section.section {
  padding-top: var(--os-air);
  padding-bottom: var(--os-air);
}

/* 2. TYPE. Tight and heavy, so the words have the same weight as the blocks. No colour, no font
      family — both are the brand's (T1). */
:where(.sl-body).refine-offset-slab h1, :where(.sl-body).refine-offset-slab h2 {
  letter-spacing: -0.03em;
  line-height: 1.02;
  font-weight: 800;
  text-wrap: balance;
}
:where(.sl-body).refine-offset-slab h3 { letter-spacing: -0.015em; font-weight: 700; }
:where(.sl-body).refine-offset-slab .eyebrow, :where(.sl-body).refine-offset-slab .bk-eyebrow-caps {
  text-transform: uppercase;
  letter-spacing: 0.14em;
  font-size: 0.72rem;
  font-weight: 800;
}

/* 3. THE DEVICE, on every plate the interior route draws. Not `.tier-featured` (T2): it is a dark
      plate carrying white type set in its own component. It gets the block in section 5, which
      draws only the block and leaves the paint alone. */
:where(.sl-body).refine-offset-slab .card, :where(.sl-body).refine-offset-slab .feature-card, :where(.sl-body).refine-offset-slab .cat-card, :where(.sl-body).refine-offset-slab .step-card, :where(.sl-body).refine-offset-slab .review-card, :where(.sl-body).refine-offset-slab .whyus-card, :where(.sl-body).refine-offset-slab .pkg-card, :where(.sl-body).refine-offset-slab .tier-card:not(.tier-featured), :where(.sl-body).refine-offset-slab .faq-item {
  border: 2px solid var(--os-edge);
  border-radius: 0;
  box-shadow: var(--os-drop) var(--os-drop) 0 var(--os-block);
}
/* The hover slides the plate ONTO its own block rather than lifting it — the object moves, the
   depth closes. Nothing fades and nothing scales. */
:where(.sl-body).refine-offset-slab .card:hover, :where(.sl-body).refine-offset-slab .feature-card:hover, :where(.sl-body).refine-offset-slab .cat-card:hover, :where(.sl-body).refine-offset-slab .step-card:hover, :where(.sl-body).refine-offset-slab .pkg-card:hover, :where(.sl-body).refine-offset-slab .tier-card:not(.tier-featured):hover {
  transform: translate(3px, 3px);
  box-shadow: 4px 4px 0 var(--os-block);
}

/* 4. CONTROLS, AND THE ARGUMENT. Fully round against square plates — the one pairing nothing else
      on this shelf makes. Shape only (T1); the secondary takes `currentColor`, which is whatever
      ink its own ground gave it. */
:where(.sl-body).refine-offset-slab .btn, :where(.sl-body).refine-offset-slab .btn-primary, :where(.sl-body).refine-offset-slab .btn-secondary {
  border-radius: 999px;
  font-weight: 800;
  /* SET IN SENTENCE CASE, DELIBERATELY. A heavy lowercase label on a fully round control against a
     square, hard-edged slab is the argument this lane is making; capitals would make it agree with
     block-poster, which is the lane it sits closest to on every other axis. Declared rather than
     left alone, because the families set capitals themselves and silence inherits them. */
  text-transform: none;
  letter-spacing: 0.01em;
}
/* THE BLOCK IS FOR CONTROLS WITH A SURFACE. `.btn-text` is the header's Call link — a button with
   its fill and its side padding removed — and a hard offset rectangle behind a bare line of text
   reads as a rendering fault. This file already records that exact thing happening to that exact
   element once, with a pill shadow that came out "a 54x44 oval NARROWER THAN ITS OWN LABEL". Found
   by reading the lane back against the button rules rather than by shipping it. */
:where(.sl-body).refine-offset-slab .btn:not(.btn-text), :where(.sl-body).refine-offset-slab .btn-primary, :where(.sl-body).refine-offset-slab .btn-secondary {
  box-shadow: var(--os-drop) var(--os-drop) 0 var(--os-block);
}
:where(.sl-body).refine-offset-slab .btn.btn-text { box-shadow: none; border: 0; }
:where(.sl-body).refine-offset-slab .btn:hover, :where(.sl-body).refine-offset-slab .btn-primary:hover, :where(.sl-body).refine-offset-slab .btn-secondary:hover {
  transform: translate(3px, 3px);
  box-shadow: 4px 4px 0 var(--os-block);
}
:where(.sl-body).refine-offset-slab .btn-secondary {
  background: transparent;
  border: 2px solid currentColor;
}

/* 5. THE FEATURED TIER GETS THE BLOCK AND THE CORNER, NEVER THE PAINT. Its dark plate and its white
      type are one decision made in its own component; the block is drawn outside it. */
:where(.sl-body).refine-offset-slab .tier-card.tier-featured {
  border-radius: 0;
  box-shadow: var(--os-drop) var(--os-drop) 0 var(--os-block);
}

/* 6. THE FAQ AND THE POLICY LIST — the two every lane forgets, named in DESIGN-LANES.md's own
      definition of done. Each row is its own slab. */
:where(.sl-body).refine-offset-slab .faq-item + .faq-item { margin-top: 0.7rem; }
:where(.sl-body).refine-offset-slab .faq-item summary { font-weight: 700; padding: 1.05rem 1.15rem; }

/* 7. IMAGERY IS AN OBJECT TOO. */
:where(.sl-body).refine-offset-slab .section figure img, :where(.sl-body).refine-offset-slab .img-text-section img, :where(.sl-body).refine-offset-slab .step-photo img {
  border-radius: 0;
}
:where(.sl-body).refine-offset-slab .section figure, :where(.sl-body).refine-offset-slab .img-text-section .itr-media {
  border: 2px solid var(--os-edge);
  border-radius: 0;
  box-shadow: var(--os-drop) var(--os-drop) 0 var(--os-block);
}

/* ── 8. THE BLOCK LIBRARY — the half of the site a lane written only in `.section` never reaches.
      NOT `.bk-feat` (a dark plate with white type set in the block); `.bk-tile` and `.bk-sit-card`
      carry their own fill and are left alone. Every name below was read off src/components/blocks
      rather than guessed. */
:where(.sl-body).refine-offset-slab .bk-card, :where(.sl-body).refine-offset-slab .bk-pillar, :where(.sl-body).refine-offset-slab .bk-pcard, :where(.sl-body).refine-offset-slab .bk-tier:not(.bk-feat), :where(.sl-body).refine-offset-slab .bk-step, :where(.sl-body).refine-offset-slab .bk-ccard, :where(.sl-body).refine-offset-slab .bk-ict-card, :where(.sl-body).refine-offset-slab .bk-fcard, :where(.sl-body).refine-offset-slab .bk-credcard, :where(.sl-body).refine-offset-slab .bk-grev-card, :where(.sl-body).refine-offset-slab .bk-plinth {
  border: 2px solid var(--os-edge);
  border-radius: 0;
  box-shadow: var(--os-drop) var(--os-drop) 0 var(--os-block);
}
:where(.sl-body).refine-offset-slab .bk-card:hover, :where(.sl-body).refine-offset-slab .bk-pillar:hover, :where(.sl-body).refine-offset-slab .bk-pcard:hover, :where(.sl-body).refine-offset-slab .bk-tier:not(.bk-feat):hover, :where(.sl-body).refine-offset-slab .bk-fcard:hover {
  transform: translate(3px, 3px);
  box-shadow: 4px 4px 0 var(--os-block);
}
:where(.sl-body).refine-offset-slab .bk-tier.bk-feat {
  border-radius: 0;
  box-shadow: var(--os-drop) var(--os-drop) 0 var(--os-block);
}
:where(.sl-body).refine-offset-slab .bk-btn, :where(.sl-body).refine-offset-slab .bk-pill, :where(.sl-body).refine-offset-slab .bk-chip, :where(.sl-body).refine-offset-slab .bk-city, :where(.sl-body).refine-offset-slab .bk-ict-pill, :where(.sl-body).refine-offset-slab .bk-prose-pill {
  border-radius: 999px;
  font-weight: 800;
  text-transform: none;
  letter-spacing: 0.01em;
}
:where(.sl-body).refine-offset-slab .bk-btn, :where(.sl-body).refine-offset-slab .bk-pill {
  box-shadow: var(--os-drop) var(--os-drop) 0 var(--os-block);
}
:where(.sl-body).refine-offset-slab .bk-step-art img, :where(.sl-body).refine-offset-slab .bk-prose-photo img, :where(.sl-body).refine-offset-slab .bk-cond-ph img, :where(.sl-body).refine-offset-slab .bk-tiers-art img, :where(.sl-body).refine-offset-slab .bk-cities-map { border-radius: 0; }
:where(.sl-body).refine-offset-slab .bk-step-art, :where(.sl-body).refine-offset-slab .bk-prose-photo, :where(.sl-body).refine-offset-slab .bk-cond-ph {
  border: 2px solid var(--os-edge);
  border-radius: 0;
  box-shadow: var(--os-drop) var(--os-drop) 0 var(--os-block);
}

/* ── 9. EVERY FAMILY'S OWN CHROME. A border and a shape, never a ground (T2). */
:where(.sl-body).refine-offset-slab :is(.rt-nav, :where(.sl-body) .cm-nav, :where(.sl-body) .ed-nav, :where(.sl-body) .bh-nav, :where(.sl-body) .et-nav, :where(.sl-body) .bl-nav) {
  border-bottom: 3px solid var(--os-edge);
}
:where(.sl-body).refine-offset-slab :is(.rt-pill, :where(.sl-body) .cm-book, :where(.sl-body) .ed-pill, :where(.sl-body) .bh-pill, :where(.sl-body) .et-btn, :where(.sl-body) .bl-pill) {
  border-radius: 999px;
  font-weight: 800;
  /* This is the selector that actually reaches the control on a blueprint home page — the one the
     distinctness measurement reads. Without it the lane's own decision stops at the interior route,
     which is trap five in miniature. */
  text-transform: none;
  letter-spacing: 0.01em;
}
:where(.sl-body).refine-offset-slab :is(.rt-qd, :where(.sl-body) .rt-q, :where(.sl-body) .rt-q-flat, :where(.sl-body) .cm-q, :where(.sl-body) .cm-q-flat) {
  border: 2px solid var(--os-edge);
  border-radius: 0;
  box-shadow: var(--os-drop) var(--os-drop) 0 var(--os-block);
}

/* ══ DESIGN LANE: soft-arch ═══════════════════════════════════════════════════════════════════
   THE THIRTEENTH LANE, and the register twelve lanes had between them never used: A CURVE.

   Read the shelf. Corners are square (block-poster, ruled-stack, clinical-porcelain, panel-inset,
   offset-slab), or softly rounded by a few pixels (warm-studio, pill-porcelain), or absent
   (editorial-ivory). Every plate on every one of them is a RECTANGLE, and the only argument between
   them is how its edge is drawn. Not one lane makes a shape.

   THE DEVICE IS THE ARCH. Every plate, every photograph and every panel is closed at the bottom and
   turned over at the top: a full half-round on the top two corners, square on the bottom two. It is
   one property, it reads at squint distance from across a room, and it is the only thing on this
   shelf that changes the SILHOUETTE of a band rather than its surface treatment. A page of arches
   does not look like a page of boxes with different edges on them.

   IT IS ALSO NOT DECORATION. An arch reads as a doorway and a window — shelter, threshold, a room
   you go into — which is what a wellness room sells, and it is the reason the motif is everywhere in
   that trade and nowhere in this library.

   ── THE ARCH IS ELLIPTICAL, AND THE PLATE IS PADDED TO CLEAR IT ──────────────────────────────
   The first version made the arch a HALF ROUND: a 999px radius the browser clamps to half the
   plate's width. On a photograph that is beautiful. On a four-line card it is a bug, and it shipped
   past all thirty-two deploy checks onto a live page: a 580px-wide card domes to 290px, every word
   in the top half of it sits OUTSIDE the curve, and `overflow: hidden` cuts it off. The band read
   "…e guest to an alcove" and "…urse who sits down", four cards, every heading beheaded.
   Nothing measures that. Only looking at the page does.
   So the curve is now an ELLIPSE — the full width across, a bounded distance up — which still reads
   as one arch at squint distance and cannot swallow more than `--sa-rise` of a plate. And every
   plate that carries WORDS is padded past the rise, because a shape that crops its own content is
   not a treatment. A photograph has nothing to crop, so it keeps the taller sweep.

   NOTHING IS REPAINTED (T2), AND NO COLOUR IS SET (T1). The lane changes shape, air and case only.
   Both alternating beats are declared (T3), the rooms and the closing band are left alone (T4), and
   it dresses both renderers (T5, sections 7-8).
   @lane soft-arch | every plate and photograph turned over at the top: a full arch, square below | suits: soft calm rounded gentle wellness botanical spa-adjacent welcoming feminine warm restorative sanctuary retreat
   */
:where(.sl-body).refine-soft-arch {
  /* How far the arch climbs. Bounded on purpose — see the note above; an unbounded half-round eats
     the top half of any wide plate and takes the words with it. */
  --sa-rise: 3.25rem;
  /* A photograph has no text to crop, so its arch is a real window. */
  --sa-rise-art: 6rem;
  /* Where the words may start: below the rise, plus air, so the heading clears the sweep at the
     plate's outer edges where the curve is lowest. */
  --sa-top: calc(var(--sa-rise) + 1.4rem);
  --sa-side: 1.6rem;
  --sa-air: clamp(4.5rem, 6.5vw, 7rem);
  --card-radius: 0px;
  --btn-radius: 999px;
  --input-radius: 999px;
  --card-shadow: none;
  --card-hover-shadow: none;
  --card-border-width: 0;
}

/* 1. BOTH BEATS, BOTH RHYTHMS (T3); rooms, photo bands and the closing ask excluded (T4). */
:where(.sl-body).refine-soft-arch.sections-alternate main > section.section:nth-of-type(odd):not(.sec-room):not(.sec-photo):not(.final-cta):not(.section-hub-cta), :where(.sl-body).refine-soft-arch.bands-paper main > section.section:nth-of-type(odd):not(.sec-room):not(.sec-photo):not(.final-cta):not(.section-hub-cta) {
  background: var(--c-surface);
}
:where(.sl-body).refine-soft-arch.sections-alternate main > section.section:nth-of-type(even):not(.sec-room):not(.sec-photo):not(.final-cta):not(.section-hub-cta), :where(.sl-body).refine-soft-arch.bands-paper main > section.section:nth-of-type(even):not(.sec-room):not(.sec-photo):not(.final-cta):not(.section-hub-cta) {
  background: var(--c-surface-alt);
}
:where(.sl-body).refine-soft-arch main > section.section {
  padding-top: var(--sa-air);
  padding-bottom: var(--sa-air);
}

/* 2. TYPE. Light, open and unhurried, to sit under a curve rather than argue with it. No colour and
      no font family — both belong to the brand (T1). */
:where(.sl-body).refine-soft-arch h1, :where(.sl-body).refine-soft-arch h2 {
  font-weight: 400;
  letter-spacing: 0.01em;
  line-height: 1.18;
  text-wrap: balance;
}
:where(.sl-body).refine-soft-arch h3 { font-weight: 500; letter-spacing: 0.005em; }
:where(.sl-body).refine-soft-arch .eyebrow, :where(.sl-body).refine-soft-arch .bk-eyebrow-caps {
  text-transform: uppercase;
  letter-spacing: 0.24em;
  font-size: 0.68rem;
  font-weight: 500;
}

/* 3. THE ARCH, on every plate the interior route draws. Not `.tier-featured` (T2): it is a dark
      plate carrying white type set in its own component, and it takes the shape in section 5
      without being repainted. */
:where(.sl-body).refine-soft-arch .card, :where(.sl-body).refine-soft-arch .feature-card, :where(.sl-body).refine-soft-arch .cat-card, :where(.sl-body).refine-soft-arch .step-card, :where(.sl-body).refine-soft-arch .review-card, :where(.sl-body).refine-soft-arch .whyus-card, :where(.sl-body).refine-soft-arch .pkg-card, :where(.sl-body).refine-soft-arch .tier-card:not(.tier-featured), :where(.sl-body).refine-soft-arch .faq-item {
  border: 0;
  border-radius: 50% 50% 0 0 / var(--sa-rise) var(--sa-rise) 0 0;
  padding-top: var(--sa-top);
  padding-left: max(var(--sa-side), 1.4rem);
  padding-right: max(var(--sa-side), 1.4rem);
  box-shadow: none;
  overflow: hidden;
}
/* The hover deepens the arch rather than lifting the plate. Nothing leaves the page. */
:where(.sl-body).refine-soft-arch .card:hover, :where(.sl-body).refine-soft-arch .feature-card:hover, :where(.sl-body).refine-soft-arch .cat-card:hover, :where(.sl-body).refine-soft-arch .step-card:hover, :where(.sl-body).refine-soft-arch .pkg-card:hover, :where(.sl-body).refine-soft-arch .tier-card:not(.tier-featured):hover {
  transform: none;
  box-shadow: none;
}

/* 4. CONTROLS. Fully round, so the button is the arch closed on itself. Shape only (T1): the
      secondary takes `currentColor`, which is whatever ink its own ground gave it. */
:where(.sl-body).refine-soft-arch .btn, :where(.sl-body).refine-soft-arch .btn-primary, :where(.sl-body).refine-soft-arch .btn-secondary {
  border-radius: 999px;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: none;
  box-shadow: none;
}
:where(.sl-body).refine-soft-arch .btn-secondary {
  background: transparent;
  border: 1px solid currentColor;
}

/* 5. THE FEATURED TIER TAKES THE SHAPE AND NOT THE PAINT. */
:where(.sl-body).refine-soft-arch .tier-card.tier-featured {
  border-radius: 50% 50% 0 0 / var(--sa-rise) var(--sa-rise) 0 0;
  padding-top: var(--sa-top);
  padding-left: max(var(--sa-side), 1.4rem);
  padding-right: max(var(--sa-side), 1.4rem);
  overflow: hidden;
}

/* 6. THE FAQ AND THE POLICY LIST — the two every lane forgets. Rows sit as a stack of low arches. */
:where(.sl-body).refine-soft-arch .faq-item + .faq-item { margin-top: 0.75rem; }
/* The row already pads past its own arch, so the question must not pad again on top of it —
   otherwise the first FAQ opens with six rems of empty white above the words. */
:where(.sl-body).refine-soft-arch .faq-item summary { font-weight: 500; padding: 0 0 1.15rem; }

/* 7. IMAGERY IS A WINDOW. The arch is at its most literal here and it is where the lane is read. */
:where(.sl-body).refine-soft-arch .section figure img, :where(.sl-body).refine-soft-arch .img-text-section img, :where(.sl-body).refine-soft-arch .step-photo img {
  border-radius: 50% 50% 0 0 / var(--sa-rise-art) var(--sa-rise-art) 0 0;
}

/* ── 8. THE BLOCK LIBRARY — the half of the site a lane written only in `.section` never reaches.
      NOT `.bk-feat`, `.bk-tile` or `.bk-sit-card`: all three carry their own fill, and a lane that
      restyles a plate it will not also re-ink is the trap this shelf keeps paying for. */
:where(.sl-body).refine-soft-arch .bk-card, :where(.sl-body).refine-soft-arch .bk-pillar, :where(.sl-body).refine-soft-arch .bk-pcard, :where(.sl-body).refine-soft-arch .bk-tier:not(.bk-feat), :where(.sl-body).refine-soft-arch .bk-step, :where(.sl-body).refine-soft-arch .bk-ccard, :where(.sl-body).refine-soft-arch .bk-ict-card, :where(.sl-body).refine-soft-arch .bk-fcard, :where(.sl-body).refine-soft-arch .bk-credcard, :where(.sl-body).refine-soft-arch .bk-grev-card, :where(.sl-body).refine-soft-arch .bk-plinth {
  border: 0;
  border-radius: 50% 50% 0 0 / var(--sa-rise) var(--sa-rise) 0 0;
  padding-top: var(--sa-top);
  padding-left: max(var(--sa-side), 1.4rem);
  padding-right: max(var(--sa-side), 1.4rem);
  box-shadow: none;
  overflow: hidden;
}
:where(.sl-body).refine-soft-arch .bk-tier.bk-feat {
  border-radius: 50% 50% 0 0 / var(--sa-rise) var(--sa-rise) 0 0;
  padding-top: var(--sa-top);
  padding-left: max(var(--sa-side), 1.4rem);
  padding-right: max(var(--sa-side), 1.4rem);
  overflow: hidden;
}
:where(.sl-body).refine-soft-arch .bk-btn, :where(.sl-body).refine-soft-arch .bk-pill, :where(.sl-body).refine-soft-arch .bk-chip, :where(.sl-body).refine-soft-arch .bk-city, :where(.sl-body).refine-soft-arch .bk-ict-pill, :where(.sl-body).refine-soft-arch .bk-prose-pill {
  border-radius: 999px;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: none;
}
/* T6 (documented in full on body.refine-warm-studio): the reset skips the controls the
   renderers draw as an inset ring, because on those the shadow IS the border. `:where()`
   keeps the rule at the specificity it already had. */
:where(.sl-body).refine-soft-arch :is(.bk-btn, :where(.sl-body) .bk-pill, :where(.sl-body) .bk-chip, :where(.sl-body) .bk-city, :where(.sl-body) .bk-ict-pill, :where(.sl-body) .bk-prose-pill):not(:where(.bk-pill-ghost, :where(.sl-body) .bk-pill-outline, :where(.sl-body) .bk-btn-ghost)) { box-shadow: none; }
:where(.sl-body).refine-soft-arch .bk-step-art img, :where(.sl-body).refine-soft-arch .bk-prose-photo img, :where(.sl-body).refine-soft-arch .bk-cond-ph img, :where(.sl-body).refine-soft-arch .bk-tiers-art img, :where(.sl-body).refine-soft-arch .bk-cities-map {
  border-radius: 50% 50% 0 0 / var(--sa-rise-art) var(--sa-rise-art) 0 0;
}

/* ── 9. EVERY FAMILY'S OWN CHROME. A shape, never a ground (T2). The nav takes no border at all:
      a straight rule under an arched page is the one line that would fight the device. */
:where(.sl-body).refine-soft-arch :is(.rt-pill, :where(.sl-body) .cm-book, :where(.sl-body) .ed-pill, :where(.sl-body) .bh-pill, :where(.sl-body) .et-btn, :where(.sl-body) .bl-pill) {
  border-radius: 999px;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: none;
}
:where(.sl-body).refine-soft-arch :is(.rt-qd, :where(.sl-body) .rt-q, :where(.sl-body) .rt-q-flat, :where(.sl-body) .cm-q, :where(.sl-body) .cm-q-flat) {
  border: 0;
  border-radius: 50% 50% 0 0 / var(--sa-rise) var(--sa-rise) 0 0;
  padding-top: var(--sa-top);
  padding-left: max(var(--sa-side), 1.4rem);
  padding-right: max(var(--sa-side), 1.4rem);
  box-shadow: none;
  overflow: hidden;
}

/* ══ DESIGN LANE: shopfront-caps ══════════════════════════════════════════════════════════════
   THE PAGE SHOUTS IN ONE PLACE AND TALKS NORMALLY EVERYWHERE ELSE.

   Every band is titled in plain block capitals — big, tight, heavy, the way a business name gets
   painted across a warehouse door — and in exchange every small label on the page gives its
   capitals up and becomes an ordinary sentence. That inversion is the type device, and the second
   half of it matters more than the first: a 0.7rem tracked-caps eyebrow reading OUR SERVICES is
   the single most-shared mark on this shelf. All thirteen lanes before this one set one, at
   0.68–0.78rem and 0.14–0.24em, and not one of them has ever moved heading case off sentence.
   panel-inset's own comment argues the opposite position out loud — "the page still has ONE thing
   set in capitals and it is the smallest thing on it, which is the whole difference between quiet
   and shouty." This lane inverts exactly that sentence. Big type says the thing at full volume and
   cannot be decorated, which is what plain-spoken looks like in type.

   AND THE PAGE IS A BOARD WITH SHEETS TACKED TO IT — the second device, and the reason this is a
   lane rather than a setting on a lane that already exists. Blur the type off a caps-only version
   of this and what is left is block-poster's chassis: square, flat, unelevated, two alternating
   grounds. So the page ground is the BOARD — a tint mixed from the brand's own primary — and every
   band closes with a band of it, so a run of bands reads as separate sheets pinned up rather than
   as one continuous scroll. It is not a bar, a rule, a corner or a shadow; those four are taken by
   block-poster, ruled-stack, offset-slab/soft-arch and every default look respectively. It is band
   ARCHITECTURE, which DESIGN-LANES.md's own table calls the biggest silhouette driver there is,
   and it survives at 300px with the words removed. It is also the client: Copperline's own board
   by the door with six drips chalked on it, in a district of working studios where every notice is
   tacked to something.

   THE SEAM IS A GAP, NOT A LINE, and the distinction is load-bearing twice over. Visually, twelve
   to twenty pixels of ground is a space between two sheets; ruled-stack's three pixels of ink is a
   drawn rule, and the two do not read alike at any distance. Mechanically, it is drawn as the
   sheet's own BOTTOM edge, so lane-distinct's band-separator probe — which reads the widest TOP
   border any band after the first computes — still reads this lane as unruled and the two lanes
   stay apart on that axis. It also satisfies page-rules P3 the way ruled-stack does: P3 is a rule
   about a SEAM, and a band of board between two sheets is a seam by construction.

   IT IS ALSO LAYOUT-NEUTRAL IN THE HORIZONTAL, WHICH IS WHY THE SHEETS ARE NOT INSET. The obvious
   version of this device pushes each sheet in from the page edge so the board shows down both
   sides. Measured against the page standard rather than eyeballed: --bk-pad is
   max(gutter, (100% − 1200px)/2 + gutter), so above ~1240px an inset cancels itself exactly and
   below it does not — the max() clamps to the bare gutter and every inset band's content starts
   one inset further right than the hero and the closing band, which is two left edges on one page
   and precisely what grid-lint G2/G6 refuses. A device that only works above 1240px is a device
   Ian's own ~864px window never sees. The horizontal band of board costs nothing at any width, so
   that is the whole device.

   WHY THE CAPS DIRECTION AND NEVER THE OTHER ONE. `text-transform` is a rendering transform: the
   DOM text is untouched, so a screen reader still says "NAD+ drip" and the copy in the record is
   still the copy the client wrote. Lowercasing would have visually mangled IV, NAD+, B12 and every
   proper noun on the page — a content defect a lane has no business causing. The device only works
   in one direction and that is the direction it is written in.

   WHAT NO GATE HERE CAN SEE, so it is written down rather than assumed. lane-gate runs four checks
   — contrast, band rhythm, logo-on-its-bar, left edges. None of them measures line breaking, and
   the ONE thing that can go wrong with this lane is a nine-word caps heading coming down the page
   in one-word fragments. Capitals set 12–18% wider than the same string in sentence case, so every
   display size in this file is stated explicitly and stated DOWN — about a tenth off the house
   scale for band headings, and a hard size for each of the four blueprint heroes, whose headlines
   live in a ~440px copy track beside a 624px picture. That is the same measurement editorial-ivory
   had to make at 19a after a seven-word headline shipped in five one-word lines with every gate
   green. Verification for this lane is a fold review at 100% on every family it is paired with; a
   green gate run proves nothing about it.

   THE ONE FAMILY TO KEEP IT AWAY FROM IS RETAIL. Eleven retail block skins already set their own
   h2 in condensed uppercase 800 in scoped CSS, and nine blocks — .bk-cities, .bk-plinths,
   .bk-pgrid, .bk-pstep, .bk-sit, .bk-ev, .bk-ovl, .bk-inset, .bk-faq-estate — set an uppercase h2
   for EVERY family regardless of skin. So capital headings are not unprecedented in this fleet's
   rendered output, only at lane level. On retail the sign is half pre-existing house style and the
   lane reads least like itself; on community, editorial, bright and estate the h2 is sentence case
   and the device lands at full strength. Copperline is community.

   THE FIVE TRAPS, documented in full on body.refine-warm-studio, applied before writing:
     T1  no `color:` anywhere in this lane. The device is a transform and a weight; a transform has
         no AA threshold to clear, so it cannot make anything unreadable, and the ground-aware
         rules that already know which of --c-accent-ink and --c-accent-ink-dark applies are left
         to do their job.
     T2  nothing is repainted that will not also be re-inked: not `.tier-featured`, not `.bk-feat`
         (which takes the square corner and nothing else), not `.bk-tile`, not `.bk-sit-card`, and
         not any family's nav bar — navLogo() picks the light or dark lockup off the bar's own
         ground, and repainting it shipped an invisible logo once already.
     T3  both alternating beats declared, under both rhythms.
     T4  the closing band is not painted, draws no board strip, and does not take the sign either:
         the page ends in the client's own voice at the size the family set. Both of this lane's
         heading selectors are broad enough to have reached it, so both carry the exclusion.
     T5  dressed for the interior route (`.section`/`.card`/`.btn`) AND for the blueprint home
         (`.bk-*` plus all five families' own chrome). A TYPE lane has a specificity problem the
         shape lanes do not: every family skin sets h2 font-size AND font-weight in scoped Astro
         CSS at (0,2,1), and the eyebrows at (0,3,0), so a plain `body.refine-x .bk-… h2` ties or
         loses on bundle order and the inversion would apply in one direction only — capitals on
         the headings and the labels keeping theirs, which is precisely "block-poster with caps".
         The lane class is repeated to clear it, the same move editorial-ivory 19a had to make.

   ON DARK. Nothing here sets a colour, so there is nothing to break. Reversed-out capitals are the
   literal reference — a name painted on a dark roll-up door — and capitals have no ascenders or
   descenders to smear against a photograph, so a caps heading survives on a hero image where a
   light sentence-case one goes soft. The one real optical correction is weight: light-on-dark type
   blooms and closes its counters at 800, so on the declared dark moments the sign drops to 700 and
   opens a hundredth of an em. For a client whose paper IS ink — a wholly dark palette rather than
   a light one with dark rooms in it — that cannot be reached by selector, because CSS cannot ask
   "is this whole site dark". So the weight is a token: such a client gets `--sf-sign: 700` set once
   on the body. One line, stated up front, rather than a lane that quietly renders too heavy on
   half the fleet.
   ═══════════════════════════════════════════════════════════════════════════════════════════
   @lane shopfront-caps | band titles in painted block capitals, every small label in sentence case, bands tacked on a board | suits: neighbourhood local friendly warm unpretentious approachable community craft workshop makers hand-made honest plain-spoken appalachian
   */
:where(.sl-body).refine-shopfront-caps {
  /* THE SIGN, as tokens, so the device is stated once and read everywhere — and so a dark-palette
     client can hand the whole page a lighter weight in one line. */
  --sf-sign: 800;
  --sf-sign-dark: 700;
  /* Capitals need air between them where lowercase display type wants it taken away. 0.04em is the
     ceiling: past that a painted sign stops reading as a sign and starts reading as quiet luxury. */
  --sf-sign-track: 0.02em;
  /* Capitals have no descenders, so the lines close into a solid block. This is what makes the
     heading read as painted on rather than as a list of words. */
  --sf-sign-lead: 1.02;
  /* THE BOARD: the ground the sheets are tacked to, mixed from the brand's own primary so it is
     this client's board and not a hardcoded kraft.
     The fallbacks inside it are not decoration. `border-block-end: <w> solid var(--sf-board)` is
     invalid at computed-value time if any var() in it fails to resolve, and an invalid shorthand
     does not degrade to a thinner seam — it computes to `border-style: none`, and the lane's second
     device disappears in silence on that client. Caught by building the lane against a palette with
     no --c-surface-alt, which is the shape of brand a cold start hands you. */
  --sf-board: color-mix(in srgb, var(--c-primary, currentColor) 14%, var(--c-surface-alt, var(--c-surface, #fff)));
  --sf-gap: clamp(0.75rem, 1.4vw, 1.25rem);
  /* Filled, square, borderless — the one card position nobody on this shelf holds. warm-studio is
     filled and shouldered, block-poster is bare and keylined, ruled-stack is bare on a shelf. */
  --sf-panel: color-mix(in srgb, var(--c-primary, currentColor) 6%, var(--c-surface, #fff));
  --sf-panel-deep: color-mix(in srgb, var(--c-primary, currentColor) 11%, var(--c-surface, #fff));
  /* The block library's band grounds re-point --bk-paper per band, so the home page's panel is
     mixed from the band's OWN stock and follows the beat instead of fighting it. */
  --sf-panel-bk: color-mix(in srgb, var(--bk-primary, var(--c-primary)) 6%, var(--bk-paper, var(--c-surface, #fff)));
  --sf-panel-bk-deep: color-mix(in srgb, var(--bk-primary, var(--c-primary)) 11%, var(--bk-paper, var(--c-surface, #fff)));
  /* A working room is not airy. Denser on purpose than warm-studio's 152px and block-poster's
     112px: 84px reads as a shop, not a showroom. */
  --sf-air: clamp(3.6rem, 5.4vw, 5.25rem);
  /* A painted sign has no rounded corner, and nothing on the page floats. */
  --card-radius: 0px;
  --btn-radius: 0px;
  --input-radius: 0px;
  --card-shadow: none;
  --card-hover-shadow: none;
  --card-border-width: 0;
}

/* ── 1. THE BOARD AND THE SHEETS. BOTH BEATS, BOTH RHYTHMS (T3); rooms, photo bands and the closing
      ask excluded (T4) — those are the board's own full-bleed moments and they are not this lane's
      to flatten. */
:where(.sl-body).refine-shopfront-caps { background: var(--sf-board); }
:where(.sl-body).refine-shopfront-caps.sections-alternate main > section.section:nth-of-type(odd):not(.sec-room):not(.sec-photo):not(.section-tier_comparison):not(.section-ingredient_choice):not(.section-trust_strip):not(.section-stats):not(.section-service_area_map):not(.final-cta):not(.section-final_cta):not(.section-hub-cta), :where(.sl-body).refine-shopfront-caps.bands-paper main > section.section:nth-of-type(odd):not(.sec-room):not(.sec-photo):not(.section-tier_comparison):not(.section-ingredient_choice):not(.section-trust_strip):not(.section-stats):not(.section-service_area_map):not(.final-cta):not(.section-final_cta):not(.section-hub-cta) {
  background: var(--c-surface);
}
:where(.sl-body).refine-shopfront-caps.sections-alternate main > section.section:nth-of-type(even):not(.sec-room):not(.sec-photo):not(.section-tier_comparison):not(.section-ingredient_choice):not(.section-trust_strip):not(.section-stats):not(.section-service_area_map):not(.final-cta):not(.section-final_cta):not(.section-hub-cta), :where(.sl-body).refine-shopfront-caps.bands-paper main > section.section:nth-of-type(even):not(.sec-room):not(.sec-photo):not(.section-tier_comparison):not(.section-ingredient_choice):not(.section-trust_strip):not(.section-stats):not(.section-service_area_map):not(.final-cta):not(.section-final_cta):not(.section-hub-cta) {
  background: var(--c-surface-alt);
}
/* The base stylesheet rules some seams. A drawn line and a band of board are two answers to the
   same question, and the page should give only one. */
:where(.sl-body).refine-shopfront-caps .section + .section { border-top: 0; }
/* THE SEAM. The sheet's own bottom edge, in the board colour — a gap, not a rule, and invisible to
   the band-separator axis that ruled-stack owns. */
:where(.sl-body).refine-shopfront-caps main > section.section:not(.sec-room):not(.sec-photo):not(.section-tier_comparison):not(.section-ingredient_choice):not(.section-trust_strip):not(.section-stats):not(.section-service_area_map):not(.final-cta):not(.section-final_cta):not(.section-hub-cta) {
  border-block-end: var(--sf-gap) solid var(--sf-board);
}
:where(.sl-body).refine-shopfront-caps main > section.section {
  padding-top: var(--sf-air);
  padding-bottom: var(--sf-air);
}

/* ── 2. THE SIGN. Capitals on h1 and h2 ONLY — the device stops at the band, so h3 and below stay
      sentence case and the caps read as something applied at one level rather than as a site that
      shouts. No colour (T1) and no font family: both belong to the brand. Every number here is a
      caps correction; `text-wrap: balance` and `hyphens: none` are the line-breaking insurance no
      gate in this repo can provide. */
:where(.sl-body).refine-shopfront-caps.refine-shopfront-caps .hero-inner h1, :where(.sl-body).refine-shopfront-caps.refine-shopfront-caps .hero h1, :where(.sl-body).refine-shopfront-caps.refine-shopfront-caps .hero-title {
  text-transform: uppercase;
  font-weight: var(--sf-sign);
  letter-spacing: var(--sf-sign-track);
  line-height: var(--sf-sign-lead);
  /* Down from the house display scale, because capitals occupy about a cap-height more optical
     space than the same string set sentence case. */
  font-size: clamp(2.05rem, 4.4vw, 3.5rem);
  text-wrap: balance;
  hyphens: none;
  overflow-wrap: normal;
}
/* THE BAND TITLE, both places the interior route puts it. Several sections set the title outside
   `.section-header`, which is why the second selector is deliberately broad — and being broad it
   would otherwise have reached two things it must not: an h2 used as a sub-title INSIDE a card on
   a package page, and the closing ask. Both are excluded rather than left to luck (T4). */
:where(.sl-body).refine-shopfront-caps.refine-shopfront-caps .section-header h2, :where(.sl-body).refine-shopfront-caps.refine-shopfront-caps main > section.section:not(.final-cta):not(.section-final_cta):not(.section-hub-cta) h2:not(:is(.card, :where(.sl-body) .feature-card, :where(.sl-body) .cat-card, :where(.sl-body) .step-card, :where(.sl-body) .review-card, :where(.sl-body) .whyus-card, :where(.sl-body) .pkg-card, :where(.sl-body) .tier-card, :where(.sl-body) .faq-item) h2) {
  text-transform: uppercase;
  font-weight: var(--sf-sign);
  letter-spacing: var(--sf-sign-track);
  line-height: var(--sf-sign-lead);
  font-size: clamp(1.55rem, 2.9vw, 2.4rem);
  text-wrap: balance;
  hyphens: none;
  overflow-wrap: normal;
  /* Capitals sit optically low against the copy beneath them, so the gap is stated rather than
     inherited from a scale that was measured on sentence case. */
  margin-block-end: 1.15rem;
}
/* AND THE DEVICE STOPS THERE. h3 and below are the ordinary speaking voice of the page. */
:where(.sl-body).refine-shopfront-caps.refine-shopfront-caps :is(h3, :where(.sl-body) h4, :where(.sl-body) h5, :where(.sl-body) h6) {
  text-transform: none;
  letter-spacing: normal;
}

/* ── 3. AND EVERY SMALL LABEL GIVES ITS CAPITALS UP. This is the half the brief actually asks for,
      and the half that keeps the lane from being block-poster with caps.
      There are 28 distinct eyebrow classes in the block library and 49 scoped rules setting them in
      tracked uppercase, compiled at (0,3,0) with their astro-cid. Naming five of them by hand would
      have inverted the headings and left the labels shouting on most bands — the inversion applying
      in one direction only. So the lane class is repeated, which puts this at (0,3,1) and clears
      them, and the sweep is by attribute rather than by list, which reaches all 28 and any written
      tomorrow. */
:where(.sl-body).refine-shopfront-caps.refine-shopfront-caps :is([class*="eyebrow"]:not(.bk-close-eyebrow), :where(.sl-body) .subhead, :where(.sl-body) .bk-tiers-sub, :where(.sl-body) .bk-mo-cap, :where(.sl-body) .rt-announce) {
  text-transform: none;
  letter-spacing: normal;
  /* It RISES from the 0.68–0.78rem every other lane sets. This is ordinary speech now, not a
     whisper over the top of the page. */
  font-size: 0.95rem;
  font-weight: 500;
}
/* The rule eyebrow draws a 34px accent tick beside itself. A decorated small label is the thing
   this lane takes away, and shape is the lane's to change — the tick is removed, never recoloured
   (T1). */
:where(.sl-body).refine-shopfront-caps.refine-shopfront-caps .bk-eyebrow-rule::before { display: none; }

/* ── 4. PLATES. Filled, square, borderless, unelevated. NOT `.tier-featured` (T2): a dark plate
      carrying white type set in its own component. It takes the square corner in section 7 and is
      not repainted. */
:where(.sl-body).refine-shopfront-caps .card, :where(.sl-body).refine-shopfront-caps .feature-card, :where(.sl-body).refine-shopfront-caps .cat-card, :where(.sl-body).refine-shopfront-caps .step-card, :where(.sl-body).refine-shopfront-caps .review-card, :where(.sl-body).refine-shopfront-caps .whyus-card, :where(.sl-body).refine-shopfront-caps .pkg-card, :where(.sl-body).refine-shopfront-caps .tier-card:not(.tier-featured), :where(.sl-body).refine-shopfront-caps .faq-item {
  background: var(--sf-panel);
  border: 0;
  border-radius: 0;
  box-shadow: none;
  transition: background 160ms cubic-bezier(.22, .61, .36, 1);
}
:where(.sl-body).refine-shopfront-caps .card:hover, :where(.sl-body).refine-shopfront-caps .feature-card:hover, :where(.sl-body).refine-shopfront-caps .cat-card:hover, :where(.sl-body).refine-shopfront-caps .step-card:hover, :where(.sl-body).refine-shopfront-caps .pkg-card:hover, :where(.sl-body).refine-shopfront-caps .tier-card:not(.tier-featured):hover {
  background: var(--sf-panel-deep);
  transform: none;
  box-shadow: none;
}
/* A panel standing ON the tinted beat takes paper, or it disappears into its own sheet — the same
   argument warm-studio makes, with this lane's stock. */
:where(.sl-body).refine-shopfront-caps main > section.section:nth-of-type(even) :is(.card, :where(.sl-body) .feature-card, :where(.sl-body) .cat-card, :where(.sl-body) .step-card, :where(.sl-body) .review-card, :where(.sl-body) .whyus-card, :where(.sl-body) .pkg-card, :where(.sl-body) .faq-item) {
  background: var(--c-surface);
}

/* ── 5. CONTROLS. Square, plain, sentence case — the other end of the inversion. Shape and case
      only (T1); the secondary borders in `currentColor`, which is whatever ink its own ground gave
      it, so it can never go invisible on a dark hero. This lane used to say here that it was not
      named in the shared dark-ground guard above and did not need to be — true of this lane as
      written, and the reason three other unlisted lanes went unnoticed for a shelf and a half. The
      guard no longer keeps a list, so the sentence is now simply wrong: it covers this lane like
      every other, and covers it to exactly the value `currentColor` was already resolving to. */
:where(.sl-body).refine-shopfront-caps .btn, :where(.sl-body).refine-shopfront-caps .btn-primary, :where(.sl-body).refine-shopfront-caps .btn-secondary {
  border-radius: 0;
  text-transform: none;
  letter-spacing: normal;
  font-weight: 600;
  font-size: 1rem;
  box-shadow: none;
}
:where(.sl-body).refine-shopfront-caps .btn-secondary {
  background: transparent;
  border: 1.5px solid currentColor;
}
:where(.sl-body).refine-shopfront-caps .btn:hover, :where(.sl-body).refine-shopfront-caps .btn-primary:hover { box-shadow: none; transform: none; }

/* ── 6. THE FAQ AND THE POLICY LIST — the two every lane forgets, and the two DESIGN-LANES.md's
      definition of done names out loud. Rows stack as a run of square filled panels with board
      showing between them, which is the sheet idea one level down. */
:where(.sl-body).refine-shopfront-caps .faq-item + .faq-item { margin-top: 0.5rem; }
:where(.sl-body).refine-shopfront-caps .faq-item summary, :where(.sl-body).refine-shopfront-caps .faq-list summary {
  font-weight: 600;
  text-transform: none;
  letter-spacing: normal;
  padding: 1.1rem 1.3rem;
}
:where(.sl-body).refine-shopfront-caps .faq-item[open] { background: var(--sf-panel-deep); }
:where(.sl-body).refine-shopfront-caps .pxp-item {
  background: var(--sf-panel);
  border: 0;
  border-radius: 0;
  box-shadow: none;
}
:where(.sl-body).refine-shopfront-caps .pxp-item + .pxp-item { margin-top: 0.5rem; }
:where(.sl-body).refine-shopfront-caps .pxp-frame, :where(.sl-body).refine-shopfront-caps .pxp-img, :where(.sl-body).refine-shopfront-caps .pxp-media { border-radius: 0; }
:where(.sl-body).refine-shopfront-caps .pxp-summary, :where(.sl-body).refine-shopfront-caps .pxp-title { text-transform: none; letter-spacing: normal; }

/* ── 7. THE FEATURED TIER TAKES THE CORNER AND NOTHING ELSE (T2), and imagery is square: a painted
      sign has no rounded corner and neither does anything standing beside it. */
:where(.sl-body).refine-shopfront-caps .tier-card.tier-featured { border-radius: 0; }
:where(.sl-body).refine-shopfront-caps .section figure, :where(.sl-body).refine-shopfront-caps .section figure img, :where(.sl-body).refine-shopfront-caps .img-text-section img, :where(.sl-body).refine-shopfront-caps .step-photo img { border-radius: 0; }
/* The closing band is not painted here (T4). The coverage map keeps the one !important every other
   lane carries: without it a lane's (0,2,1) rule outranks the light map compositions and buries
   their ink. */
:where(.sl-body).refine-shopfront-caps:not(.map-index):not(.map-panel) main > section.section.section-service_area_map {
  background: var(--c-room) !important;
}

/* ══ 8. THE BLOCK LIBRARY, which is what a blueprint HOME page is made of (T5). Everything above
      speaks `.section`/`.card`/`.btn` and none of it reaches the one page every visitor opens. ══ */

/* 8a. THE SIGN, ON THE PAGE THAT NEEDS IT MOST — and the specificity a TYPE lane, uniquely, has to
       fight for. `.bk-fcards-community h2` compiles to (0,2,1) with its data-astro-cid and sets
       both size and weight, so a plain lane rule ties and loses to bundle order; the doubled lane
       class puts this at (0,3,2) and settles it.
       Reached through `.bk-home h2`, NOT through `section[class*="bk-"] > h2`: on the built
       community home only two of six band headings are direct children of a bk-* section — the
       rest sit inside a div or a panel, and the FAQ band is `section.cm-faq`, whose class contains
       no "bk-" at all, so the attribute selector would miss it entirely. The closing band is
       excluded: the page ends in the client's own voice (T4). */
:where(.sl-body).refine-shopfront-caps.refine-shopfront-caps .bk-home h2:not(:is([class*="bk-close"], :where(.sl-body) [class*="-close-"]) h2) {
  text-transform: uppercase;
  font-weight: var(--sf-sign);
  letter-spacing: var(--sf-sign-track);
  line-height: var(--sf-sign-lead);
  font-size: clamp(1.6rem, 2.9vw, 2.45rem);
  text-wrap: balance;
  hyphens: none;
  overflow-wrap: normal;
  margin-block-end: 1.15rem;
}
/* Card titles and row titles keep their ordinary voice, including on the one family that sets its
   own h3 in condensed caps. One level, one device. */
:where(.sl-body).refine-shopfront-caps.refine-shopfront-caps .bk-home :is(h3, :where(.sl-body) h4, :where(.sl-body) h5, :where(.sl-body) h6), :where(.sl-body).refine-shopfront-caps.refine-shopfront-caps :is(.bk-tier-name, :where(.sl-body) .bk-pname, :where(.sl-body) .bk-q-text) {
  text-transform: none;
  letter-spacing: normal;
}

/* 8b. THE FOUR BLUEPRINT HEROES, SIZED FOR CAPITALS RATHER THAN INHERITED FROM SENTENCE CASE. This
       is the riskiest line in the lane, which is why each one is written out. `.bk-split h1` is
       clamp(44px, 6.4vw, 92px) inside a copy track of about 440px beside a 624px picture;
       editorial-ivory had to cut exactly that to 3.75rem because the headline came down in five
       one-word lines, and capitals set 12–18% wider, so caps makes the same headline materially
       worse. `text-wrap: balance` cannot rescue a line that cannot fit a word. Each hero is sized
       against the column it actually lives in. */
:where(.sl-body).refine-shopfront-caps.refine-shopfront-caps .bk-split h1 { font-size: clamp(1.95rem, 3.1vw, 3.15rem) !important; }
:where(.sl-body).refine-shopfront-caps.refine-shopfront-caps .bk-wave h1 { font-size: clamp(1.95rem, 4.2vw, 3.4rem) !important; }
:where(.sl-body).refine-shopfront-caps.refine-shopfront-caps .bk-notch h1 { font-size: clamp(1.85rem, 3.2vw, 2.85rem) !important; }
:where(.sl-body).refine-shopfront-caps.refine-shopfront-caps .bk-vhero h1 { font-size: clamp(1.8rem, 3vw, 2.7rem) !important; }
:where(.sl-body).refine-shopfront-caps.refine-shopfront-caps :is(.bk-split, :where(.sl-body) .bk-wave, :where(.sl-body) .bk-notch, :where(.sl-body) .bk-vhero) h1 {
  text-transform: uppercase;
  font-weight: var(--sf-sign);
  letter-spacing: var(--sf-sign-track);
  line-height: var(--sf-sign-lead);
  text-wrap: balance;
  hyphens: none;
  overflow-wrap: normal;
}

/* 8c. THE BOARD, ON THE HOME PAGE. Same seam, different vocabulary: a blueprint home has no
       `main > section.section` at all, and most of its bands arrive wrapped in a bare div, so the
       band set is counted the way global.css's own home alternation counts it — the lane root's
       own children. The hero draws none (it is the shopfront window at the top of the board) and
       neither does the closing band (T4). Nothing is repainted here: the strip is the sheet's own
       bottom edge, so a band that paints a photograph, a dark ground or the brand primary keeps
       every pixel of it. The nav is a `<nav>` and the footer a `<footer>`, so neither is matched. */
:where(.sl-body).refine-shopfront-caps .bk-home > :is(section, :where(.sl-body) div):not([class*="hero"]):not(:is(.bk-split, :where(.sl-body) .bk-wave, :where(.sl-body) .bk-notch, :where(.sl-body) .bk-vhero)):not(:has(> :is(.bk-split, :where(.sl-body) .bk-wave, :where(.sl-body) .bk-notch, :where(.sl-body) .bk-vhero))):not([class*="bk-close"]):not(:has(> [class*="bk-close"])) {
  border-block-end: var(--sf-gap) solid var(--sf-board);
}

/* 8d. PLATES, filled from the band's own stock so they follow the beat. NOT `.bk-feat`, NOT
       `.bk-tile`, NOT `.bk-sit-card`: all three carry their own fill and their own ink, and a lane
       that repaints a plate it will not also re-ink is the trap this shelf keeps paying for (T2).
       `.bk-feat` takes the corner in 8f and nothing else. */
:where(.sl-body).refine-shopfront-caps .bk-card, :where(.sl-body).refine-shopfront-caps .bk-pillar, :where(.sl-body).refine-shopfront-caps .bk-pcard, :where(.sl-body).refine-shopfront-caps .bk-tier:not(.bk-feat), :where(.sl-body).refine-shopfront-caps .bk-step, :where(.sl-body).refine-shopfront-caps .bk-ccard, :where(.sl-body).refine-shopfront-caps .bk-ict-card, :where(.sl-body).refine-shopfront-caps .bk-fcard, :where(.sl-body).refine-shopfront-caps .bk-credcard, :where(.sl-body).refine-shopfront-caps .bk-grev-card, :where(.sl-body).refine-shopfront-caps .bk-plinth {
  background: var(--sf-panel-bk);
  border: 0;
  border-radius: 0;
  box-shadow: none;
}
:where(.sl-body).refine-shopfront-caps .bk-card:hover, :where(.sl-body).refine-shopfront-caps .bk-pillar:hover, :where(.sl-body).refine-shopfront-caps .bk-pcard:hover, :where(.sl-body).refine-shopfront-caps .bk-tier:not(.bk-feat):hover, :where(.sl-body).refine-shopfront-caps .bk-fcard:hover {
  background: var(--sf-panel-bk-deep);
  transform: none;
  box-shadow: none;
}

/* 8e. CONTROLS, in the block vocabulary. Square, sentence case, plain-spoken. */
:where(.sl-body).refine-shopfront-caps .bk-btn, :where(.sl-body).refine-shopfront-caps .bk-pill, :where(.sl-body).refine-shopfront-caps .bk-chip, :where(.sl-body).refine-shopfront-caps .bk-city, :where(.sl-body).refine-shopfront-caps .bk-ict-pill, :where(.sl-body).refine-shopfront-caps .bk-prose-pill {
  border-radius: 0;
  text-transform: none;
  letter-spacing: normal;
  font-weight: 600;
}
/* T6 (documented in full on body.refine-warm-studio): the reset skips the controls the
   renderers draw as an inset ring, because on those the shadow IS the border. `:where()`
   keeps the rule at the specificity it already had. */
:where(.sl-body).refine-shopfront-caps :is(.bk-btn, :where(.sl-body) .bk-pill, :where(.sl-body) .bk-chip, :where(.sl-body) .bk-city, :where(.sl-body) .bk-ict-pill, :where(.sl-body) .bk-prose-pill):not(:where(.bk-pill-ghost, :where(.sl-body) .bk-pill-outline, :where(.sl-body) .bk-btn-ghost)) { box-shadow: none; }
:where(.sl-body).refine-shopfront-caps .bk-pill-fill, :where(.sl-body).refine-shopfront-caps .bk-btn-fill { font-size: 1rem; box-shadow: none; }

/* 8f. THE FEATURED TIER TAKES THE CORNER AND NOTHING ELSE, and imagery is square. */
:where(.sl-body).refine-shopfront-caps .bk-tier.bk-feat { border-radius: 0; }
:where(.sl-body).refine-shopfront-caps .bk-step-art img, :where(.sl-body).refine-shopfront-caps .bk-prose-photo img, :where(.sl-body).refine-shopfront-caps .bk-cond-ph img, :where(.sl-body).refine-shopfront-caps .bk-tiers-art img, :where(.sl-body).refine-shopfront-caps .bk-cities-map { border-radius: 0; }
/* One family boxes its band heading in a rounded tinted plate. On a page where nothing else is
   rounded that reads as a stray, so the plate is squared — shape only, the fill is left alone. */
:where(.sl-body).refine-shopfront-caps .bk-prose-retail h2 { border-radius: 0; }

/* ── 9. THE COMMUNITY FAMILY'S OWN CHROME, which is the design this client is on, and the half a
      lane written only in `.bk-*` still misses. A LANE DOES NOT REPAINT A NAV BAR: the family
      chooses the bar's ground, and its ink AND its logo are chosen to suit it — navLogo() hands
      over the light lockup when the bar is dark, so turning the ground pale shipped a nav with
      three invisible links and an invisible logo, caught by two gates at once. The edge is the
      lane's; the ground is not (T2). Here the edge is the board, so the bar reads as the sign over
      a shopfront and the first sheet hangs below it. */
:where(.sl-body).refine-shopfront-caps .cm-nav { border-bottom: var(--sf-gap) solid var(--sf-board); }
:where(.sl-body).refine-shopfront-caps .cm-book {
  border-radius: 0;
  text-transform: none;
  letter-spacing: normal;
}
/* THE ROW IS THE SUMMARY'S OWN BOX, NOT A SECOND PLATE BEHIND IT. warm-studio put a plate behind a
   row that already carried its own fill and its own bottom margin and shipped a double border;
   this family draws the fill on `.cm-q` itself, so that is the one thing to change. */
:where(.sl-body).refine-shopfront-caps :is(.cm-q, :where(.sl-body) .cm-q-flat) {
  border: 0;
  border-radius: 0;
  box-shadow: none;
  margin-bottom: 0.5rem;
}
:where(.sl-body).refine-shopfront-caps .cm-q summary, :where(.sl-body).refine-shopfront-caps .cm-foot-name { text-transform: none; letter-spacing: normal; }

/* ── 10. AND THE OTHER FOUR FAMILIES, one rule each, so a second client on this lane does not land
      on a default home page. Same reach lesson, applied ahead of the fault rather than after it.
      `:is()` throughout on purpose: it is forgiving, so a family that draws none of these costs the
      rule nothing, where a comma list containing one unknown name would drop the lot. */
:where(.sl-body).refine-shopfront-caps :is(.rt-nav, :where(.sl-body) .ed-nav, :where(.sl-body) .bh-nav, :where(.sl-body) .et-nav, :where(.sl-body) .bl-nav) {
  border-bottom: var(--sf-gap) solid var(--sf-board);
}
:where(.sl-body).refine-shopfront-caps :is(.rt-pill, :where(.sl-body) .ed-pill, :where(.sl-body) .bh-pill, :where(.sl-body) .et-btn, :where(.sl-body) .bl-pill, :where(.sl-body) .bl-book) {
  border-radius: 0;
  text-transform: none;
  letter-spacing: normal;
  font-weight: 600;
}
/* Same finding as `.cm-q` above, in the four other spellings: the ROW is the box. */
:where(.sl-body).refine-shopfront-caps :is(.rt-q, :where(.sl-body) .rt-q-flat, :where(.sl-body) .bh-q, :where(.sl-body) .bl-q, :where(.sl-body) .et-q) {
  border: 0;
  border-radius: 0;
  box-shadow: none;
}
:where(.sl-body).refine-shopfront-caps :is(.rt-qd, :where(.sl-body) .bh-qd, :where(.sl-body) .et-qd) > summary { text-transform: none; letter-spacing: normal; }
:where(.sl-body).refine-shopfront-caps :is(.ed-foot-brand, :where(.sl-body) .et-foot-brand, :where(.sl-body) .bl-foot-logo, :where(.sl-body) .bh-brand, :where(.sl-body) .ed-brand, :where(.sl-body) .cm-brand) {
  text-transform: none;
  letter-spacing: normal;
}
:where(.sl-body).refine-shopfront-caps .bk-home :is(.rt-hero-art, :where(.sl-body) .bl-hero-pic, :where(.sl-body) .bl-card-pic, :where(.sl-body) .bl-step-pic, :where(.sl-body) .bl-tiers-pic, :where(.sl-body) .bl-places-pic, :where(.sl-body) .bl-contact-pic, :where(.sl-body) .bl-faq-pic) img {
  border-radius: 0;
}

/* ── 11. THE DARK MOMENTS, AND THE ONLY CORRECTION THE DEVICE NEEDS ANYWHERE. It is weight and
      tracking — no colour, no ground, nothing repainted. Light-on-dark type blooms and closes its
      counters at 800, so a reversed-out sign drops to 700 and opens a hundredth of an em. Named by
      the grounds the system already declares dark: the interior rooms and photo bands, the coverage
      map, the hero veils, and the blocks that ground themselves in the brand's own primary or dark.
      The doubled lane class is not decoration here — sections 2 and 8b sit at (0,3,2) and this rule
      has to reach the same headings to correct them; written plainly it would tie and lose, and the
      correction would silently never apply to the four blueprint heroes, which are exactly the
      reversed-out headings it exists for. A WHOLLY dark palette cannot be reached this way (see the
      header) and sets `--sf-sign: 700` on the body once. */
:where(.sl-body).refine-shopfront-caps.refine-shopfront-caps :is(.sec-room, :where(.sl-body) .sec-photo, :where(.sl-body) .section-service_area_map, :where(.sl-body) .hero-image-bg, :where(.sl-body) .hero-video, :where(.sl-body) .hero-gradient, :where(.sl-body) .bk-cond-panel, :where(.sl-body) .bk-frost, :where(.sl-body) .bk-ev, :where(.sl-body) .bk-sky, :where(.sl-body) .bk-ovl, :where(.sl-body) .bk-notch, :where(.sl-body) .bk-wave) :is(h1, :where(.sl-body) h2) {
  font-weight: var(--sf-sign-dark);
  letter-spacing: 0.03em;
}

/* ══ TYPE REGISTERS ═══════════════════════════════════════════════════════════════════════════
   THE SECOND LEVER. A lane decides SHAPE — corners, edges, grounds, air. A register decides TYPE —
   case, weight, tracking and scale on band titles and on the small labels. They combine, so two
   clients can wear the same lane and still not read as the same site.

   WHY, MEASURED 2026-08-28. Thirteen lanes, all worn, and the build refuses a client without one,
   so onboarding began with drawing a whole identity by hand. Fingerprinting the shelf across the
   seventeen axes lane-distinct measures:

     card corner 3 · card edge 3 · button corner 4     ← every lane crowds here
     heading case 1 · heading tracking 1 · band grounds 1 · band rhythm 1   ← nobody, ever

   Four axes carry zero difference across the whole shelf, and they are the page-level ones a reader
   sees from across a room. The shelf was not exhausted; it was exhausted in one corner. Thirteen
   lanes × four registers is fifty-two identities out of work already done.

   THE DISCIPLINE THAT KEEPS THIS FROM BECOMING A SECOND LANE SHELF:
     · Type properties ONLY. No colour, no radius, no background, no shadow, no padding. A register
       that wants to change a shape is a lane.
     · ONE class, single specificity, so any lane rule (lanes double their own class) wins where the
       two overlap. The lane is the more specific decision about that client.
     · A lane that already carries a type device — `shopfront-caps` is one — takes no register.
       Two type devices on one page is a page arguing with itself.
     · Both renderers, always: the interior route speaks `.section-header h2` / `.eyebrow`, the home
       page speaks bare `h2` inside `section[class*="bk-"]` and `.bk-eyebrow-caps`. A register
       written only for one reaches half the site, which is the trap five lanes fell into first.
   THE DOUBLED CLASS IS NOT A TYPO. Every family skin sets `h2` font-size AND font-weight in its
   own SCOPED Astro CSS, which compiles to (0,2,1) with its `data-astro-cid` attribute. A single
   `body.type-x …` selector ties that and then loses on source order, so three of the four registers
   rendered as no register at all — measured by shooting the same client in all four and looking:
   only `signwriter` was visibly different, because case is the one property the families do not
   set. Doubling the class buys the specificity, which is the same fix every lane on this shelf
   already carries for the same reason.
   ═══════════════════════════════════════════════════════════════════════════════════════════ */

/* ── SIGNWRITER — the page shouts in one place and talks normally everywhere else.
      Band titles in block capitals, the way a name is painted across a warehouse door; and in
      exchange every small label gives its capitals up. The inversion is the device: a tracked-caps
      eyebrow is the most agency-looking mark in this library and thirteen lanes all set one. */
:where(.sl-body).type-signwriter.type-signwriter :is(.section-header h2, :where(.sl-body) main > section.section > h2, :where(.sl-body) main section[class*="bk-"] > h2, :where(.sl-body) .bk-home h2) {
  text-transform: uppercase;
  letter-spacing: 0.02em;
  font-weight: 800;
  line-height: 1.04;
  font-size: clamp(1.55rem, 2.9vw, 2.4rem);
  text-wrap: balance;
  hyphens: none;
}
:where(.sl-body).type-signwriter.type-signwriter :is(.eyebrow, :where(.sl-body) .bk-eyebrow-caps, :where(.sl-body) .bk-eyebrow-rule, :where(.sl-body) .bk-ledger-eyebrow, :where(.sl-body) .bk-faq-eyebrow, :where(.sl-body) .rt-eyebrow, :where(.sl-body) .cm-eyebrow, :where(.sl-body) .ed-eyebrow) {
  text-transform: none;
  letter-spacing: normal;
  font-size: 0.95rem;
  font-weight: 500;
}

/* ── QUIET-SERIF — the opposite instinct. Light weight, open tracking, nothing raised. The page
      speaks at conversational volume and the labels are almost whispered. */
:where(.sl-body).type-quiet-serif.type-quiet-serif :is(.section-header h2, :where(.sl-body) main > section.section > h2, :where(.sl-body) main section[class*="bk-"] > h2, :where(.sl-body) .bk-home h2) {
  text-transform: none;
  letter-spacing: 0.015em;
  font-weight: 300;
  line-height: 1.24;
  text-wrap: balance;
}
:where(.sl-body).type-quiet-serif.type-quiet-serif :is(.eyebrow, :where(.sl-body) .bk-eyebrow-caps, :where(.sl-body) .bk-eyebrow-rule, :where(.sl-body) .bk-ledger-eyebrow, :where(.sl-body) .bk-faq-eyebrow, :where(.sl-body) .rt-eyebrow, :where(.sl-body) .cm-eyebrow, :where(.sl-body) .ed-eyebrow) {
  text-transform: uppercase;
  letter-spacing: 0.34em;
  font-size: 0.62rem;
  font-weight: 400;
}
:where(.sl-body).type-quiet-serif.type-quiet-serif :is(h3, :where(.sl-body) h4) { font-weight: 400; letter-spacing: 0.01em; }

/* ── WIDE-LABEL — the label IS the device. The heading stays ordinary and the eyebrow becomes a
      long tracked rule of text above it, close to the width of the title. Reads as a filing
      system, an index, a contents page — deliberate and orderly rather than loud. */
:where(.sl-body).type-wide-label.type-wide-label :is(.section-header h2, :where(.sl-body) main > section.section > h2, :where(.sl-body) main section[class*="bk-"] > h2, :where(.sl-body) .bk-home h2) {
  text-transform: none;
  letter-spacing: -0.012em;
  font-weight: 600;
  line-height: 1.16;
  text-wrap: balance;
}
:where(.sl-body).type-wide-label.type-wide-label :is(.eyebrow, :where(.sl-body) .bk-eyebrow-caps, :where(.sl-body) .bk-eyebrow-rule, :where(.sl-body) .bk-ledger-eyebrow, :where(.sl-body) .bk-faq-eyebrow, :where(.sl-body) .rt-eyebrow, :where(.sl-body) .cm-eyebrow, :where(.sl-body) .ed-eyebrow) {
  text-transform: uppercase;
  letter-spacing: 0.5em;
  font-size: 0.72rem;
  font-weight: 600;
  line-height: 1.6;
}

/* ── COMPRESSED — dense and urban. Tight negative tracking, heavy weight, lines closed up; the
      title occupies as little horizontal room as it can while staying large. */
:where(.sl-body).type-compressed.type-compressed :is(.section-header h2, :where(.sl-body) main > section.section > h2, :where(.sl-body) main section[class*="bk-"] > h2, :where(.sl-body) .bk-home h2) {
  text-transform: none;
  letter-spacing: -0.035em;
  font-weight: 800;
  line-height: 1.02;
  font-size: clamp(1.9rem, 3.5vw, 3rem);
  text-wrap: balance;
}
:where(.sl-body).type-compressed.type-compressed :is(.eyebrow, :where(.sl-body) .bk-eyebrow-caps, :where(.sl-body) .bk-eyebrow-rule, :where(.sl-body) .bk-ledger-eyebrow, :where(.sl-body) .bk-faq-eyebrow, :where(.sl-body) .rt-eyebrow, :where(.sl-body) .cm-eyebrow, :where(.sl-body) .ed-eyebrow) {
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 0.8rem;
  font-weight: 700;
}
:where(.sl-body).type-compressed.type-compressed :is(h3, :where(.sl-body) h4) { letter-spacing: -0.02em; font-weight: 700; }

/* ── AND THE REST OF THE TYPE AXES, because three was not enough to be a difference.
      The distinctness floor is FOUR axes, and case + weight + tracking is three — so two clients
      on one lane with different registers still measured "too alike to be two sites", which is the
      exact question this lever exists to answer. There are six type axes in the measurement, not
      three: the two controls carry case and weight of their own, and a rule drawn above a title is
      a typographic device. Setting all six is what takes a lane+register pair over the floor.
      Still type only: case, weight, tracking, and a mark made of a border. No colour, no radius,
      no ground — a register that reaches for those is a lane. */
:where(.sl-body).type-signwriter.type-signwriter :is(.btn, :where(.sl-body) .btn-primary, :where(.sl-body) .btn-secondary, :where(.sl-body) .bk-btn, :where(.sl-body) .bk-pill, :where(.sl-body) .rt-pill, :where(.sl-body) .cm-book, :where(.sl-body) .ed-pill) {
  text-transform: uppercase; letter-spacing: 0.08em; font-weight: 700;
}
/* THE MARK FOLLOWS ITS HEADING, OR IT IS A DASH SITTING ON ITS OWN.
   This is a BLOCK box with a fixed width, and `text-align` does not move one — it only moves
   inline content. So the rule pinned itself to the left edge of every heading's box while the
   heading itself was centred, and every centred band on every signwriter client drew a short
   gold dash stranded to the left of its title. Reported as "a clear broken glitch", and it was.
   `--bk-mi` is the house companion to `--bk-align`, declared once beside it and existing for
   exactly this reason: `auto` where the family centres, `0` where a split or composed band ranges
   left. Using it means the mark cannot disagree with the words above which it sits, in either
   direction, and a band that changes its alignment takes the mark with it. */
:where(.sl-body).type-signwriter.type-signwriter :is(.section-header h2, :where(.sl-body) main section[class*="bk-"] > h2, :where(.sl-body) .bk-home h2)::before {
  content: ''; display: block; width: 2.4rem; height: 4px;
  background: currentColor; margin: 0 var(--bk-mi, 0) 0.7rem; opacity: 0.85;
}
:where(.sl-body).type-signwriter.type-signwriter :is(.section-header, :where(.sl-body) .bk-edhead-solo) { --sf-mark: 1; }
/* ── A BRAND CAN REFUSE THE MARK AND KEEP ITS TYPE ─────────────────────────────────────────────
   `theme_json.heading_mark = false` puts `plain-titles` on the body (lib/brand.ts). Written with
   the priority to beat every design that draws one — the rule above, luxe-noir's and block-poster's
   — rather than as three exceptions, so a fourth design that adds a mark is refused by the same
   line. Only the bar goes: the register's caps, weight and tracking stay exactly as they were.
   The owner asked for it on IV Revival, 2026-09-12: "remove those". */
:where(.sl-body).plain-titles :is(.section-header h2, :where(.sl-body) main > section.section > h2, :where(.sl-body) main section[class*="bk-"] > h2, :where(.sl-body) .bk-home h2)::before {
  content: none !important; display: none !important;
}
/* ── A BRAND CAN REFUSE CAPITALS, EVERYWHERE AT ONCE ──────────────────────────────────────────
   `theme_json.caps = false` puts `no-caps` on the body (lib/brand.ts). Capitals arrive from the
   family, the register and the blocks separately, so this is one line that outranks all of them
   rather than an exception in each.
   THE TRACKING GOES WITH THE CAPITALS. Every uppercase style here also opens the letter-spacing —
   measured on IV Revival from 0.5px on a price tag to 3.08px on a small label — because spaced
   capitals read well and spaced lower case reads as a mistake. So the spacing returns to the
   font's own, and the big display titles get the slight tightening heavy lower case wants.
   The map is left alone: its labels are drawn inside an svg and set their own type. */
:where(.sl-body).no-caps :where(*):not(svg, :where(.sl-body) svg *) { text-transform: none !important; letter-spacing: normal !important; }
/* Doubled class: the reset above is (0,1,3) through its :not(svg *), so a single-class heading rule
   at (0,1,2) would lose to it despite coming later. */
:where(.sl-body).no-caps.no-caps :is(h1, :where(.sl-body) h2) { letter-spacing: -0.012em !important; }
:where(.sl-body).type-quiet-serif.type-quiet-serif :is(.btn, :where(.sl-body) .btn-primary, :where(.sl-body) .btn-secondary, :where(.sl-body) .bk-btn, :where(.sl-body) .bk-pill, :where(.sl-body) .rt-pill, :where(.sl-body) .cm-book, :where(.sl-body) .ed-pill) {
  text-transform: none; letter-spacing: 0.01em; font-weight: 400;
}

:where(.sl-body).type-wide-label.type-wide-label :is(.btn, :where(.sl-body) .btn-primary, :where(.sl-body) .btn-secondary, :where(.sl-body) .bk-btn, :where(.sl-body) .bk-pill, :where(.sl-body) .rt-pill, :where(.sl-body) .cm-book, :where(.sl-body) .ed-pill) {
  text-transform: uppercase; letter-spacing: 0.16em; font-weight: 600;
}
:where(.sl-body).type-wide-label.type-wide-label :is(.section-header h2, :where(.sl-body) main section[class*="bk-"] > h2, :where(.sl-body) .bk-home h2)::before {
  /* Same fault, same fix as the signwriter mark above — a fixed-width block box that text-align
     cannot move. Nobody had worn this register yet, so it had never been seen stranded. */
  content: ''; display: block; width: 100%; max-width: 9rem; height: 1px;
  background: currentColor; margin: 0 var(--bk-mi, 0) 1rem; opacity: 0.45;
}

:where(.sl-body).type-compressed.type-compressed :is(.btn, :where(.sl-body) .btn-primary, :where(.sl-body) .btn-secondary, :where(.sl-body) .bk-btn, :where(.sl-body) .bk-pill, :where(.sl-body) .rt-pill, :where(.sl-body) .cm-book, :where(.sl-body) .ed-pill) {
  text-transform: none; letter-spacing: -0.01em; font-weight: 800;
}

/* ══ PHONE: A FLOOR UNDER TYPE AND TAP TARGETS ════════════════════════════════════════════════
   Ian, looking at the site on a phone: "a lot of items that need formatting."

   fit-lint already proves nothing scrolls sideways and no icon is crushed, and it passed on every
   page. These are the defects that survive that check, measured on an iPhone 13 across eight
   pages: seventeen tap targets under 40px on EVERY page, and a family of small labels rendering
   at 11.5-12.5px. Both are page-agnostic — they come from shared components — so they are fixed
   once here rather than per band.

   A note on why these are floors and not redesigns: the sizes below are correct on a desktop,
   where an eyebrow at 0.72rem sits beside a 3rem headline and a footer link is one of a dozen on
   a wide rail. On a 390px screen the same values are a squint and a mis-tap. Nothing changes
   above 768px. */
@media (max-width: 768px) {
  /* 1. NOTHING SMALLER THAN 13px. Below that, uppercase letter-spaced labels stop being read and
        start being decoration — and every one of these is doing real work (a contact method, a
        FAQ group, a drip's category). */
  :where(.sl-body) .eyebrow, :where(.sl-body) .hero .eyebrow, :where(.sl-body) .section-header .eyebrow, :where(.sl-body) .comp-facts .ac-card .contact-method-label, :where(.sl-body) main > section.section.comp-faq-cards .faq-cat-title, :where(.sl-body) .whyus-eyebrow, :where(.sl-body) .press-bar-eyebrow { font-size: 0.8125rem; }        /* 13px */
  /* …and the archetypes restate the hero eyebrow at (0,3,0), which outranks the line above. The
     floor has to be stated at the same weight or it silently loses on exactly the pages that set
     the smallest value — measured 12.5px on a package hero under ad-typographic-clinical. */
  :where(.sl-body)[class] .hero .eyebrow { font-size: 0.8125rem; }
  /* A TEXT LINK IS A TAP TARGET TOO. The hub's "All about …" row measured 306x24. */
  :where(.sl-body) .hub-menu-link { display: inline-flex; align-items: center; min-height: 40px; }

  /* 2. A TAP TARGET IS 44px. The footer's phone number measured 85x15 and its email 194x15 — a
        15px-tall target for the two links a phone user is most likely to reach for. Given height
        with flex rather than padding so the text stays where it sits optically. */
  :where(.sl-body) .site-footer a {
    display: inline-flex; align-items: center; min-height: 44px;
  }
  /* …the footer's link COLUMNS stack, so give them the height without doubling the gaps */
  :where(.sl-body) .site-footer .footer-grid a { min-height: 40px; }

  /* 3. The menu button measured 38x32 — the control that opens the whole navigation. */
  :where(.sl-body) .nav-toggle { min-width: 44px; min-height: 44px; align-items: center; justify-content: center; }
}

/* ── FAQ HEADING IN CAPITALS (opt-in: theme.sections.faq_heading = 'caps') ──────────────────────
   Ian, on Top Tier: "Frequently asked questions - Make all caps". The obvious way to do that is to
   type the words in capitals into the page record, and it half-works: only seven of this site's
   sixteen FAQ headings live in a record with a headline slot at all. The other nine store the FAQ
   as a bare list and fall through to the renderer's own default string, so the same site said
   "FREQUENTLY ASKED QUESTIONS" on its town pages and "Frequently asked questions" on every drip
   page and on Contact - one instruction, sixteen places, nine of them out of reach.
   Setting the case here fixes all sixteen at once, works the same whether the words were authored
   or defaulted, and leaves the record holding a normal sentence - which matters because that same
   string is read by the page title and the structured data, and neither wants shouting.
   Opt-in per brand, so no other client's heading changes. */
:where(.sl-body).faq-caps :is(.section-faq, :where(.sl-body) .section-city_faq, :where(.sl-body) .section-faq_categories) > .container > .section-header h2 {
  text-transform: uppercase;
  letter-spacing: 0.045em;
}

/* ── "Serving: …" — the towns as links, in the coverage band ────────────────────────────────────
   The band named the six towns as plain words while six pages about those exact towns sat one
   click away with nothing pointing at them. Client: replace the county headline with a "Serving:"
   line listing all six cities, each hyperlinked to its own page.
   Sized between the headline and the body so it reads as part of the statement rather than as a
   caption, and the separators are decorative dots that a screen reader skips. */
:where(.sl-body) .coverage-serving {
  margin: 0 0 1.1rem;
  font-size: clamp(1.02rem, 1.7vw, 1.22rem);
  line-height: 1.6;
  max-width: 62ch;
}
:where(.sl-body) .coverage-serving-label {
  font-family: var(--font-heading);
  font-weight: 600;
  margin-right: 0.15rem;
}
:where(.sl-body) .coverage-serving a {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px solid color-mix(in srgb, currentColor 42%, transparent);
  padding-bottom: 1px;
  transition: border-color .15s ease, color .15s ease;
}
:where(.sl-body) .coverage-serving a:hover, :where(.sl-body) .coverage-serving a:focus-visible {
  color: var(--c-accent);
  border-bottom-color: var(--c-accent);
}
:where(.sl-body) .coverage-serving-sep { opacity: .45; margin: 0 .45rem; }

/* ── SOLID MARQUEE LETTERING (opt-in: theme.sections.marquee_ink = 'solid') ─────────────────────
   The band ships as stroke-only type because that was the reference. Top Tier's client asked for
   "solid filled lettering, no outline treatment". Filled at full token strength rather than the
   78-82% mixes the outline used: a stroke reads as delicate at part strength, a filled letterform
   just reads as washed out - and the filled version is what the contrast check now measures. */
:where(.sl-body).mq-solid .mq-item {
  -webkit-text-stroke-width: 0;
  color: var(--c-on-room);
}
:where(.sl-body).mq-solid .mq-lane-dark .mq-item  { color: var(--c-on-room); }
:where(.sl-body).mq-solid .mq-lane-light .mq-item { color: var(--c-primary); }

/* ── A ROW OF CARDS SHOULD READ AS ONE ROW ──────────────────────────────────────────────────────
   Client, on About / What We Stand For: the four headings need one consistent treatment, and the
   body text under them needs to line up.
   Both complaints are the same fault seen twice. The headings are set at the same size and weight
   as each other, but at that size a serif heading sits so close to the body copy that it does not
   read as a heading at all - so "make them bold" is really "make them look like headings". And
   because the four wrap to three, two, one and two lines, each body starts at a different height
   and the row reads as four unrelated blocks rather than one set.
   The alignment is fixed with subgrid rather than a guessed min-height: the heading row is as tall
   as the tallest heading and every body starts on the same line, at any width, for any wording.
   Guarded to cards that are exactly a heading and a paragraph, which is the shape this fixes. */
:where(.sl-body) .comp-cards-accent .cards-center:has(> .card > h3 + p:last-child) {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, var(--sl-basis, 252px)), 1fr));
  grid-template-rows: auto auto;
  align-items: start;
}
:where(.sl-body) .comp-cards-accent .cards-center:has(> .card > h3 + p:last-child) > .card:has(> h3 + p:last-child) {
  display: grid;
  grid-template-rows: subgrid;
  grid-row: span 2;
  row-gap: 0.55rem;
}
/* The heading earns its own weight, so the pair reads as heading-then-body rather than as two
   paragraphs in different fonts. */
:where(.sl-body) .comp-cards-accent .cards-center > .card > h3 {
  font-weight: 700;
  letter-spacing: -0.005em;
  margin: 0;
  text-wrap: balance;
}
:where(.sl-body) .comp-cards-accent .cards-center > .card > h3 + p { margin: 0; }

/* ── A SECONDARY BUTTON IN A DARK ROOM ──────────────────────────────────────────────────────────
   `.btn-secondary` is an outline button drawn in --c-link, which falls back to --c-primary: the
   brand's navy. That is right on paper stock and invisible on a navy room - measured 1.00:1 on
   the Groups and Events page, where the button and the band behind it were the identical colour.
   The room already rebinds --c-text to its light ink, so the button only had to be told to read
   it. Same fault and same fix as the hub menu name and price beside it: the component was silent
   about its colour and inherited a value chosen for a different ground. */
:where(.sl-body) main > section.section.sec-room .btn-secondary, :where(.sl-body) main > section.section.sec-photo .btn-secondary {
  color: var(--c-text);
  border-color: color-mix(in srgb, var(--c-text) 58%, transparent);
}
:where(.sl-body) main > section.section.sec-room .btn-secondary:hover, :where(.sl-body) main > section.section.sec-photo .btn-secondary:hover {
  background: var(--c-text);
  color: var(--c-primary);
  border-color: var(--c-text);
}

/* ── ibreak-list — the ingredients when nobody has written what they do ─────────────────────────
   The two-column table this section normally draws needs a description per ingredient. Top Tier's
   formulations arrived as plain lists, so the section renders the list instead (see the renderer).
   Two columns of short names rather than one long thin one, and each name on its own ruled line so
   the list reads as a formulation rather than as prose. */
:where(.sl-body) .ibreak-list { list-style: none; margin: 0; padding: 0; }
:where(.sl-body) .ibreak-list.is-two-col { columns: 2; column-gap: clamp(1.5rem, 4vw, 3rem); }
:where(.sl-body) .ibreak-list li {
  break-inside: avoid;
  padding: 0.6rem 0.1rem;
  border-bottom: 1px solid color-mix(in srgb, var(--c-text) 14%, transparent);
  font-weight: 500;
  color: var(--c-text);
}
:where(.sl-body) .ibreak-intro { color: var(--c-text-muted); max-width: 62ch; margin: 0 0 1.1rem; }
:where(.sl-body) .ibreak-foot  { color: var(--c-text-muted); max-width: 68ch; margin: 1.1rem 0 0; font-size: 0.92rem; }
@media (max-width: 640px) { :where(.sl-body) .ibreak-list.is-two-col { columns: 1; } }

/* ══ THE SAME RULES, ON A DARK GROUND ══════════════════════════════════════════════════════════
   Every rule above that reads a palette NAME where it means a luminance ROLE was rewritten in
   place to the role token brand.ts derives (`--c-on-dark`, `--c-on-primary`, `--c-on-room`,
   `--c-light-stock`, `--c-room`, `--c-focus`, `--c-hero-plate`) wherever the role resolves, on a
   light page, to the very value the name did — the fleet was measured (scripts/ground-debt.json
   is the table). The rules twinned HERE are the ones whose light expression is NOT the role's
   light value: a plate that inks its copy in the primary (`--c-text: var(--c-primary)`), a tint
   mixed TOWARD the primary (the alternate bands, the paper's muted ink and hairlines, the stone),
   the hero fallback gradient, the gilt and spa inks, a focus ring drawn in primary_dark. On a light
   page those keep today's expression byte for byte; on a dark page the twin below replaces the
   primary with the ink that stands off the ground (`--c-on-surface`), the mix direction with the
   opposite luminance, and the fallback plate with `--c-hero-plate`.

   `:where(body.ground-dark)` / `body:where(.ground-dark)` is load-bearing: `:where()` adds no
   specificity, so each twin sits at EXACTLY its original's specificity and wins only by coming
   later in the sheet. A lane that outranks the original still outranks the twin, and the cascade
   a designer reasoned about on a light page is the cascade on a dark one.

   The source lint (scripts/ground-names-lint.mjs) refuses any NEW `color: var(--c-surface)`,
   `--c-text: var(--c-surface)` or `background: var(--c-primary)` outside the table.
   ═══════════════════════════════════════════════════════════════════════════════════════════════ */

/* ══ THE CONTROL PLATE ON A DARK PAGE ═══════════════════════════════════════════════════════════
   The role and its light expression are declared beside `.btn-primary` at the head of this file,
   where the account of why a control cannot borrow the room is written in full. This is its dark
   half: the page's light stock — `#FFFFFF` on every dark ground, because brand.ts re-derives every
   other stock dark and the light-stock chain falls through to white — with the brand's own colour
   as its caps. Measured on the dark estate cell after this landed: every filled call to action on
   every band clears its own ground by 7:1 or better with caps at 15:1, where three of them had been
   1.00:1, 1.44:1 and 1.50:1. The floor this rests on is that white is 2.33:1 off the LIGHTEST
   colour that can still call itself a dark ground (DARK_LUM 0.4); every real dark page is far
   below that line — this cell's lightest band is the room at 7.11:1 — but a brand that authored a
   ground at the very edge of dark would want looking at.
   The HOVER darkens the plate toward its own caps rather than taking `--c-primary-dark`, which on
   this cell IS the page. */
:where(.sl-body).ground-dark {
  --c-control: var(--c-light-stock);
  --c-on-control: var(--c-primary);
  --c-control-hover: color-mix(in srgb, var(--c-light-stock) 86%, var(--c-primary));
}

/* ══ THE PLATE HAS TO REACH THE BLOCK LAYER, AND EVERY ROUTE ════════════════════════════════════
   THE FAULT, MEASURED. The plate above answered the question for `.btn-primary` and for the ledger
   lane's own §29, which is written `body.refine-clinical-ledger .et.bk-home …` — the HOME page and
   nothing else. Every interior and listing route renders its calls to action from the BLOCK
   library, whose rules were never told the role exists: `.bk-pbook` paints
   `var(--bk-cta-bg, var(--bk-primary))` and `.bk-cmp-btn` paints `var(--bk-primary)`, and
   `--bk-primary` on a dark estate ground IS the brand navy the page is made of. Measured in a
   browser on the dark cell, against the identical elements on the light build of the same site:
   /iv-treatments/dehydration/ two BOOK NOW at 1.04:1 (light 14.04:1); /iv-packages/hangover/ three
   at 2.18:1; /iv-therapy/iv-therapy-mount-pleasant-sc/ three Book at 2.18:1. Eight filled calls to
   action, none of them clearing the 3:1 a control's own boundary needs, on the pages that sell the
   drip — while the same class on the home page is a white pill at 7.09:1. Two reviewers filed it as
   the round's remaining blocker; both said the same thing: the block layer never learned the role.
   THE DECISION. The role is not re-derived here and it is not copied — `--bk-control-bg` and
   `--bk-control-ink` are the BLOCK LIBRARY'S NAMES for `--c-control` / `--c-on-control`, one alias,
   declared once, so a block asks for the plate by role instead of asking for the brand by name. The
   block reads it as a fallback link ahead of its own value:
       background: var(--bk-cta-bg, var(--bk-control-bg, var(--bk-primary, …)))
   which means a record that authors its own CTA colour still wins, and — the whole reason it is
   written as a token rather than as a `body.ground-dark` twin selector — a LIGHT page never sees
   it at all. The alias is emitted only here, on a dark ground, so on every light page the chain
   falls straight through to the expression the block has always had, byte for byte, with no
   specificity fight against the scoped rule (a scoped rule carries its cid attribute in every
   compound, which counts as a class, and a twin written the obvious way loses to it silently —
   the trap --bk-onlight-ink was written to avoid, recorded in FamilyCompare.astro).
   Because it is a token and not a selector it reaches EVERY route — home, listing, interior,
   contact, treatment — and every lane and the no-lane build alike, which is the whole complaint.
   AND THE INK MOVES WITH THE PLATE. `.bk-pbook`'s caps read `--bk-plinth-ink`, which on a dark
   ground is the accent: pointing the button at a white plate without moving its ink would have
   traded an invisible button for an invisible label (sage on white is 2.1:1). Every block that
   takes `--bk-control-bg` takes `--bk-control-ink` in the same declaration.
   INSIDE A DARK BAND THE BAND KEEPS ITS OWN ANSWER. darkBandVars already re-cuts `--bk-primary` to
   the page's light stock and `--bk-primary-ink` to the room for everything standing in that band,
   measured against that band on either ground — so the alias steps aside there and hands the pair
   back. Written on `.bk-route` itself because that is the element the band's inline vars sit on: a
   custom property whose value is a `var()` is resolved where it is DECLARED, not where it is used,
   so declaring `--bk-control-bg: var(--bk-primary)` on `body` would freeze it to body's value and
   silently do nothing. */
:where(.sl-body).ground-dark { --bk-control-bg: var(--c-control); --bk-control-ink: var(--c-on-control); }
:where(.sl-body).ground-dark :is(.bk-route.bk-band-dark, :where(.sl-body) .bk-route.bk-band-photo) { --bk-control-bg: var(--bk-primary); --bk-control-ink: var(--bk-primary-ink); }

/* A CONTROL STANDING ON THE PRIMARY IS CUT FROM THE PRIMARY'S OWN INK.
   The comparison table's FEATURED column paints itself `--bk-primary` and its Book button
   `--bk-accent`: on a light page that is gold on navy and reads, but inside a dark band the column
   flips to the page's light stock and the button becomes the brand sage on a WHITE row — measured
   2.10:1, the weakest button on the page, with its two siblings on the dark rows at 10.7:1. Three
   buttons in one row, two treatments, and the hierarchy inverted: the tier the table is steering
   you to has the faintest call to action.
   The answer is the same one the plate above takes — a control does not name a colour, it asks for
   the pair that was derived against the ground it stands on. The row's ground is `--bk-primary` and
   its ink is `--bk-primary-ink`; those two are derived together and are guaranteed to read on each
   other whichever way round the band has cut them, so the button is simply the row inverted.
   Declared on `.bk-cmp-current` — the element the row's own vars are in scope on — for the
   resolution reason written above.

   ── AND IT IS THE SAME BUTTON ON BOTH GROUNDS NOW (2026-09-06) ────────────────────────────────
   This was gated `body.ground-dark` when it was written, for pixel safety rather than for
   correctness, and a reviewer measured what that left behind: on the LIGHT ground — the one that
   actually ships — the featured Book button is still the brand sage on the white featured row at
   2.10:1, while its two siblings on the dark rows are 9.38:1 plates. The tier the table steers you
   to carries the faintest call to action on the ground every client is on today.
   "The row inverted" is not a dark-ground fact. `--bk-primary` and `--bk-primary-ink` are derived
   together against whatever the band has cut them from, on either ground, so the inversion is
   guaranteed to read on either ground — there was never a second answer for light, only a missing
   one. Ungated, therefore, and the light pixels it moves are named and deliberate: the Book button
   in the featured column of a tier-comparison band, on the estate and bright families, goes from
   the accent (measured #92bcaa on #ffffff, 2.10:1) to the row inverted (#ffffff row, #08252c
   plate, 15.41:1). Nothing else reads these two tokens.

   `--bk-onprimary-dim` stays dark-only, on its own line below, because it is a DIFFERENT decision
   about a different thing (the featured column's notes, see FamilyCompare's own note): on a light
   page those notes sit on the family's deep navy column where 18% off the ink is a whisper, and
   nobody has asked for that pixel to move. */
:where(.sl-body) .bk-cmp-current { --bk-onprimary-fill: var(--bk-primary-ink); --bk-onprimary-ink: var(--bk-primary); }
:where(.sl-body).ground-dark .bk-cmp-current { --bk-onprimary-dim: 1; }

/* AN ACCENT USED AS A LABEL IS AN INK, AND AN INK IS MEASURED AGAINST WHAT IT PRINTS ON.
   `--bk-accent-text` is the block library's quiet accent label — the team member's role, the
   eyebrow over a band, the "step up" note. On a LIGHT page the family mixes it 55% accent toward
   the family's own ink, so it stays recognisably the accent and still reads on paper. On a dark
   ground it arrives as the raw accent, and the raw accent is a colour chosen to sit on the page,
   not on the LIGHTEST band the page can put behind it: measured on the dark cell, the about page's
   "CO-FOUNDERS, REGISTERED NURSES" is rgb(147,188,170) on the room rgb(73,90,106) = 3.39:1, where
   12.5px caps want 4.5:1. It is exactly the shape the price ink was fixed by this round — an ink
   measured against a ground it does not print on — one rung milder, and it appears at eighty-two
   declarations across the block library, not at this one line.
   So the dark expression is the light one with the endpoint swapped: a proportion of the accent
   mixed toward the ink brand.ts already measured to read on the room (`--c-on-room`) instead of
   toward the family's dark ink. Same formula, opposite direction — which is the rule darkBandVars
   already follows for every other ink it re-cuts. The guarantee comes from the ENDPOINT, not from
   the proportion: `--c-on-room` is derived against the room, and the room is by construction the
   lightest ground a dark page has, so an ink that clears there clears on the page, the tint and the
   card as well. The proportion is the one free choice and it was measured, not guessed: 45% takes
   the about page's team role from 3.39:1 to 4.95:1 on the room this finding was filed against
   (#495a6a, `--c-on-room` #F3F6F9) and to 10.7:1 on the page, while still reading as the brand's
   colour rather than as white.
   Emitted only on a dark ground, and read by the blocks as `var(--bk-accent-quiet,
   var(--bk-accent-text, …))` — at the accent-text slot, never ahead of `--bk-onlight-ink`, so a
   label that already knows it is standing on a light plate keeps the answer it had.
   AND THE CEILING IS THE ROOM'S, NOT THE INK'S. No proportion can beat `--c-on-room` itself, so a
   room derived light enough that its own measured ink is under 4.5:1 puts every string on that band
   under the line and nothing written here can rescue it. That is a brand.ts question about what a
   room IS on a dark ground, not a block-library one. */
:where(.sl-body).ground-dark { --bk-accent-quiet: color-mix(in srgb, var(--c-accent-ink) 45%, var(--c-on-room)); }

/* A FILLED CONTROL ON A DARK PAGE DRAWS ITS OWN EDGE — WHERE IT HAS NO PLATE OF ITS OWN.
   A light page has one ground and a button's fill lands 5:1 or 15:1 off it, so nothing ever had to
   say where a button ends. A dark page has three grounds a step apart, and the button's plate — the
   room — was a fourth colour in the same narrow range: measured on the dark estate cell, the primary
   control sat 1.5:1 off the tinted band and 1.0:1 off a card, and every one of them read as a line
   of caps floating on the band with no button under it (visual-lint R20, twelve of them).
   That is now answered where it belongs, on the plate (`--c-control` above), and this rule is what
   is left: the rescue for a control that paints a fill of its OWN — a family accent, a block's
   coral pill, a bar chip — which this file cannot measure against the band it happens to land on.
   A control that takes the control plate sets `--c-control-ring: transparent` in the same rule that
   gives it the plate, so it opts itself out rather than being listed in two places: a solid white
   pill and a hairline ghost are already two different objects, and giving the pill a ring as well
   is what made them read as one. `inset` so no layout moves, `currentColor` so it is always the ink
   the control already chose, and only on a dark ground, so no light page gains a ring. */
:where(.sl-body).ground-dark :is(.btn-primary, :where(.sl-body) .et-btn-fill, :where(.sl-body) .et-btn-book, :where(.sl-body) .bk-btn-fill, :where(.sl-body) .bk-pbook, :where(.sl-body) .bk-sit-fill, :where(.sl-body) .bk-ev-fill, :where(.sl-body) .bk-cmp-btn, :where(.sl-body) .bk-pill-accent, :where(.sl-body) .bk-plearn, :where(.sl-body) .bc-fill, :where(.sl-body) .hub-cta .btn, :where(.sl-body) .contact-form button, :where(.sl-body) .contact-form .btn) {
  box-shadow: inset 0 0 0 1px var(--c-control-ring, color-mix(in srgb, currentColor 34%, transparent));
}

/* ══ A ROOM STAYS A ROOM, AND WHAT STANDS IN IT IS CUT FROM ANOTHER STOCK ═══════════════════════
   THE FAULT, MEASURED. On the dark estate cell the page is #08252C, the tinted band #294248, the
   card stock #465C61 and the room #495A6A — so the room and the card stock are 1.00:1 apart. Every
   listing page puts its card deck inside a room, and every one of those cards therefore composited
   to the same colour as the band behind it: no fill difference, no shadow (`--card-shadow` is
   `none` on a dark ground) and no edge, because the room rebinds `--c-border: transparent`. Five
   listing pages rendered their whole deck as one flat slab with photographs floating on it. On the
   light cell the identical elements are WHITE cards on a NAVY room — the strongest device on the
   page.
   THE DECISION, WHICH IS ONE DECISION. A card is cut from the stock of the BAND it stands in, not
   from the page's. On a dark ground a room re-cuts the two page stocks its children read: the plate
   becomes `--c-surface-alt` and the hairline comes back. `--c-surface-alt` is not a fourth rung
   invented here and it is not a magic mix — brand.ts derives `--c-room` with `clearOfAll(primary,
   [bg, surfaceAlt], STEP)`, so the room is GUARANTEED to stand a full step off it, on this brand
   and on every future one. Measured here: card #294248 inside room #495A6A, 1.50:1, with white
   copy at 9.84:1 on the card (it was 6.53:1 on the old stock, so the copy gains as well).
   AND THE HAIRLINE. `--c-border: transparent` was written because the archetype's
   `.section + .section` rule would draw a BEIGE line across the top of a navy band. On a dark page
   the page's own border is already a white alpha — every other band on the site draws one — so
   suppressing it at rooms was both unnecessary and the reason a card inside a room had no edge.
   The room takes the page's hairline shape, mixed from the ink the room already carries.
   WHAT THIS DOES NOT DO. It does not move `--c-room` itself. The room is still the lightest ground
   on a dark page, which is the other half of what the reviewer saw, and it cannot be fixed from
   here: the room's ink (`--c-on-room`) is measured against the room in brand.ts, so a stylesheet
   that repainted the band would be deriving a ground without its ink — the exact fault this round
   exists to kill. The ladder has no room below the page and one rung above the card
   (white copy 4.72:1 there), and brand.ts's own note records that trade being taken deliberately.
   `.bands-paper` and `:nth-of-type(n)` are carried so this twin sits at EXACTLY the specificity of
   the room paint it corrects — (0,4,3), the same as the rule that set `--c-border: transparent` —
   and wins only by coming later, which is the rule the whole dark half of this file follows. */
:where(.sl-body):where(.ground-dark).bands-paper main > section.section.sec-room:nth-of-type(n) {
  --c-surface: var(--c-surface-alt);
  --c-border: color-mix(in srgb, var(--c-on-room) 20%, transparent);
}

:where(.sl-body) :where(body.ground-dark) .hero-gradient {
  background: linear-gradient(135deg, var(--c-hero-plate), color-mix(in srgb, var(--c-hero-plate) 85%, var(--c-bg)));
}
:where(.sl-body):where(.ground-dark).sections-alternate main > section.section:nth-of-type(even):not(.section-tier_comparison):not(.final-cta):not(.section-hub-cta):not(.sec-room):not(.sec-photo):not(.comp-trust-band):not(.block-route-section) {
  background: linear-gradient(180deg, color-mix(in srgb, var(--c-on-surface) 7%, var(--c-surface-alt)) 0%, color-mix(in srgb, var(--c-on-surface) 4%, var(--c-surface-alt)) 100%);
}
:where(.sl-body):where(.ground-dark).sections-alternate main > section.section:nth-of-type(4n):not(.final-cta):not(.section-hub-cta):not(.sec-room):not(.sec-photo):not(.comp-trust-band):not(.block-route-section) {
  background: linear-gradient(135deg, color-mix(in srgb, var(--c-on-surface) 12%, var(--c-surface)) 0%, color-mix(in srgb, var(--c-accent) 7%, var(--c-surface)) 100%);
}
:where(.sl-body):where(.ground-dark).refine-dark-luxe main > section.section.sec-room .steps-row:has(.step-ic) > .card.step-card {
  --c-text: var(--c-on-surface);
  --c-text-muted: color-mix(in srgb, var(--c-on-surface) 72%, var(--c-surface));
}
:where(.sl-body) :where(body.ground-dark) .promo-code-chip:focus-visible {
  outline: 2px solid var(--c-focus);
}
:where(.sl-body):where(.ground-dark).bands-paper {
  --eyebrow-ink: var(--c-accent-ink, var(--c-on-surface));
  --c-text-muted: color-mix(in srgb, var(--c-on-surface) 88%, var(--c-surface-alt));
}
:where(.sl-body):where(.ground-dark).bands-paper main > section.section.section-city_faq .faq-item {
  --c-text: var(--c-on-surface);
  --c-text-muted: color-mix(in srgb, var(--c-on-surface) 88%, var(--c-surface-alt));
}
:where(.sl-body):where(.ground-dark).bands-paper main > section.section.section-policy_expand .pxp-item {
  --c-text: var(--c-on-surface);
  --c-text-muted: color-mix(in srgb, var(--c-on-surface) 88%, var(--c-surface-alt));
}
:where(.sl-body):where(.ground-dark).bands-paper main > section.section.sec-room:nth-of-type(n) {
  --c-text-muted: color-mix(in srgb, var(--c-on-room) 72%, var(--c-room));
}
:where(.sl-body):where(.ground-dark).bands-paper main > section.section.sec-room:nth-of-type(n):where(:not(.comp-ledger):not(.comp-quiet-prose):not(.comp-statement):not(.comp-numbered):not(.comp-callout):not(.comp-split):not(.comp-swatch):not(.comp-panel):not(.comp-cats-rule)) .whyus-card, :where(.sl-body):where(.ground-dark).bands-paper main > section.section.sec-room:nth-of-type(n) .faq-item, :where(.sl-body):where(.ground-dark).bands-paper main > section.section.sec-room:nth-of-type(n):where(:not(.comp-ledger):not(.comp-quiet-prose):not(.comp-statement):not(.comp-numbered):not(.comp-callout):not(.comp-split):not(.comp-swatch):not(.comp-panel):not(.comp-cats-rule)) .cat-card, :where(.sl-body):where(.ground-dark).bands-paper main > section.section.sec-room:nth-of-type(n):where(:not(.comp-ledger):not(.comp-quiet-prose):not(.comp-statement):not(.comp-numbered):not(.comp-callout):not(.comp-split):not(.comp-swatch):not(.comp-panel):not(.comp-cats-rule)) .card, :where(.sl-body):where(.ground-dark).bands-paper main > section.section.sec-room:nth-of-type(n):where(:not(.comp-ledger):not(.comp-quiet-prose):not(.comp-statement):not(.comp-numbered):not(.comp-callout):not(.comp-split):not(.comp-swatch):not(.comp-panel):not(.comp-cats-rule)) .feature-card, :where(.sl-body):where(.ground-dark).bands-paper main > section.section.sec-room:nth-of-type(n):where(:not(.comp-ledger):not(.comp-quiet-prose):not(.comp-statement):not(.comp-numbered):not(.comp-callout):not(.comp-split):not(.comp-swatch):not(.comp-panel):not(.comp-cats-rule)) .step-card, :where(.sl-body):where(.ground-dark).bands-paper main > section.section.sec-room:nth-of-type(n):where(:not(.comp-ledger):not(.comp-quiet-prose):not(.comp-statement):not(.comp-numbered):not(.comp-callout):not(.comp-split):not(.comp-swatch):not(.comp-panel):not(.comp-cats-rule)) .pkg-card, :where(.sl-body):where(.ground-dark).bands-paper main > section.section.sec-room:nth-of-type(n):where(:not(.comp-ledger):not(.comp-quiet-prose):not(.comp-statement):not(.comp-numbered):not(.comp-callout):not(.comp-split):not(.comp-swatch):not(.comp-panel):not(.comp-cats-rule)) .why-row, :where(.sl-body):where(.ground-dark).bands-paper main > section.section.sec-room:nth-of-type(n) .ge-rung, :where(.sl-body):where(.ground-dark).bands-paper main > section.section.sec-room:nth-of-type(n) .ge-avail, :where(.sl-body):where(.ground-dark).bands-paper main > section.section.sec-room:nth-of-type(n) .outcome-tile, :where(.sl-body):where(.ground-dark).bands-paper main > section.section.sec-room:nth-of-type(n) .ge-panel {
  --c-text: var(--c-on-surface);
  --c-text-muted: color-mix(in srgb, var(--c-on-surface) 88%, var(--c-surface-alt));
  --c-border: color-mix(in srgb, var(--c-on-surface) 12%, var(--c-surface-alt));
}
:where(.sl-body) :where(body.ground-dark) main > section.section.sec-photo:where(:not(.comp-ledger):not(.comp-quiet-prose):not(.comp-statement):not(.comp-numbered):not(.comp-callout):not(.comp-split):not(.comp-swatch):not(.comp-panel):not(.comp-cats-rule)) .feature-card, :where(.sl-body) :where(body.ground-dark) main > section.section.sec-photo:where(:not(.comp-ledger):not(.comp-quiet-prose):not(.comp-statement):not(.comp-numbered):not(.comp-callout):not(.comp-split):not(.comp-swatch):not(.comp-panel):not(.comp-cats-rule)) .auto-card, :where(.sl-body) :where(body.ground-dark) main > section.section.sec-photo:where(:not(.comp-ledger):not(.comp-quiet-prose):not(.comp-statement):not(.comp-numbered):not(.comp-callout):not(.comp-split):not(.comp-swatch):not(.comp-panel):not(.comp-cats-rule)) .cat-card, :where(.sl-body) :where(body.ground-dark) main > section.section.sec-photo:where(:not(.comp-ledger):not(.comp-quiet-prose):not(.comp-statement):not(.comp-numbered):not(.comp-callout):not(.comp-split):not(.comp-swatch):not(.comp-panel):not(.comp-cats-rule)) .whyus-card, :where(.sl-body) :where(body.ground-dark) main > section.section.sec-photo:where(:not(.comp-ledger):not(.comp-quiet-prose):not(.comp-statement):not(.comp-numbered):not(.comp-callout):not(.comp-split):not(.comp-swatch):not(.comp-panel):not(.comp-cats-rule)) .faq-item {
  --c-text: var(--c-on-surface);
  --c-text-muted: color-mix(in srgb, var(--c-on-surface) 88%, var(--c-surface-alt));
  --c-border: color-mix(in srgb, var(--c-on-surface) 12%, var(--c-surface-alt));
}
:where(.sl-body):where(.ground-dark).bands-paper main > section.section.section-wellness_packages:nth-of-type(n) .wpkg-card {
  --c-text: var(--c-on-surface);
  --c-text-muted: color-mix(in srgb, var(--c-on-surface) 88%, var(--c-surface-alt));
  --c-border: color-mix(in srgb, var(--c-on-surface) 12%, var(--c-surface-alt));
}
:where(.sl-body):where(.ground-dark).bands-paper.paper-alt {
  --c-paper-alt: color-mix(in srgb, color-mix(in srgb, var(--c-on-surface) 72%, var(--c-accent)) 17%, var(--c-surface-alt));
}
:where(.sl-body):where(.ground-dark).refine-spa-luxe .hero-lead-form {
  color: var(--c-on-dark);
}
:where(.sl-body):where(.ground-dark).refine-spa-luxe .hero-lead-form .hero-inner, :where(.sl-body):where(.ground-dark).refine-spa-luxe .hero-lead-form .hero-inner h1, :where(.sl-body):where(.ground-dark).refine-spa-luxe .hero-lead-form .hero-inner p, :where(.sl-body):where(.ground-dark).refine-spa-luxe .hero-lead-form .hero-inner .subhead {
  color: var(--c-on-dark) !important;
}
:where(.sl-body):where(.ground-dark).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) .ge-chip, :where(.sl-body):where(.ground-dark).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) .ge-chip *, :where(.sl-body):where(.ground-dark).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) .ge-rung, :where(.sl-body):where(.ground-dark).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) .ge-rung *, :where(.sl-body):where(.ground-dark).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) .ge-avail, :where(.sl-body):where(.ground-dark).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) .ge-avail * {
  color: var(--c-on-surface) !important;
  --c-text: var(--c-on-surface);
  --c-text-muted: color-mix(in srgb, var(--c-on-surface) 88%, var(--c-surface));
}
:where(.sl-body):where(.ground-dark).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) .ge-panel, :where(.sl-body):where(.ground-dark).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) .ge-panel *, :where(.sl-body):where(.ground-dark).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) .ge-panel-label, :where(.sl-body):where(.ground-dark).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) .ge-ladder, :where(.sl-body):where(.ground-dark).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) .ge-ladder *, :where(.sl-body):where(.ground-dark).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) .ge-chips, :where(.sl-body):where(.ground-dark).refine-dark-luxe.bands-paper main > section.section.sec-photo:nth-of-type(n) .ge-chips * {
  color: var(--c-on-surface) !important;
  --c-text: var(--c-on-surface);
  --c-text-muted: color-mix(in srgb, var(--c-on-surface) 88%, var(--c-surface)) !important;
}
/* The card in a dark room got its INK twinned here and its PLATE left alone, and the rule above it
   still said "a card that keeps its own LIGHT surface inside a room", which on a dark page had
   stopped being true. The plate is answered on the room now (see the room block above: a room
   re-cuts `--c-surface` to the page's other stock, so the card is a real step off the band). What
   is left for the card itself is the EDGE: `--card-shadow` is `none` on a dark ground, so the
   hairline is the only thing left that draws a card's outline, and it must be a light alpha the
   dark plate can carry. Both bands are named, because a photo band suppresses the hairline the
   same way a room does. */
:where(.sl-body):where(.ground-dark).bands-paper main > section.section.sec-room .whyus-card, :where(.sl-body):where(.ground-dark).bands-paper main > section.section.sec-room .hub-card, :where(.sl-body):where(.ground-dark).bands-paper main > section.section.sec-photo .whyus-card, :where(.sl-body):where(.ground-dark).bands-paper main > section.section.sec-photo .hub-card {
  --c-text: var(--c-on-surface);
  --c-text-muted: color-mix(in srgb, var(--c-on-surface) 88%, var(--c-surface-alt));
  --c-border: color-mix(in srgb, var(--c-on-surface) 26%, transparent);
  color: var(--c-on-surface);
}
/* The listing card's excerpt sets its ink as a COLOUR, not as the muted token, so twinning the card
   above left it behind: on the dark cell it painted the brand navy on the card's own lifted navy at
   2:1, on every listing page. Same rebind, one selector lower. */
:where(.sl-body):where(.ground-dark).bands-paper main > section.section.sec-room .hub-card-desc, :where(.sl-body):where(.ground-dark).bands-paper main > section.section.sec-photo .hub-card-desc {
  color: color-mix(in srgb, var(--c-on-surface) 88%, var(--c-surface-alt));
}
:where(.sl-body) :where(body.ground-dark) main > section.section.sec-room.comp-ing-cards .ibreak-table tbody tr {
  --c-text: var(--c-on-surface);
  --c-text-muted: color-mix(in srgb, var(--c-on-surface) 88%, var(--c-surface-alt));
}
:where(.sl-body) :where(body.ground-dark) main > section.section.sec-room.comp-value-receipt .vstack-wrap {
  --c-text: var(--c-on-surface);
  --c-text-muted: color-mix(in srgb, var(--c-on-surface) 88%, var(--c-surface-alt));
}
:where(.sl-body) :where(body.ground-dark) main > section.section.sec-room.comp-vtl-rail .vtl-copy, :where(.sl-body) :where(body.ground-dark) main > section.section.sec-room.comp-stdl-plaque .stdl-row {
  --c-text: var(--c-on-surface);
  --c-text-muted: color-mix(in srgb, var(--c-on-surface) 88%, var(--c-surface-alt));
}
:where(.sl-body) :where(body.ground-dark) main > section.section.sec-room.comp-trust-plinth .trust-row-item {
  --c-text: var(--c-on-surface);
  color: var(--c-on-surface);
}
:where(.sl-body):where(.ground-dark) .hero.hero-ink-gilt {
  color: var(--c-on-dark) !important;
}
:where(.sl-body):where(.ground-dark) .hero.hero-ink-gilt h1, :where(.sl-body):where(.ground-dark) .hero.hero-ink-gilt .hero-tagline, :where(.sl-body):where(.ground-dark) .hero.hero-ink-gilt .subhead {
  color: var(--c-on-dark) !important;
}
:where(.sl-body):where(.ground-dark) .hero.hero-ink-gilt .btn-secondary {
  color: var(--c-on-dark);
  border-color: color-mix(in srgb, var(--c-on-dark) 70%, transparent);
}
:where(.sl-body):where(.ground-dark).theme-apothecary main > section.section.sec-room:where(:not(.comp-menu-list):not(.comp-ledger):not(.comp-quiet-prose):not(.comp-statement):not(.comp-numbered):not(.comp-callout):not(.comp-split):not(.comp-swatch):not(.comp-panel)) .card, :where(.sl-body):where(.ground-dark).theme-apothecary main > section.section.sec-room:where(:not(.comp-menu-list):not(.comp-ledger):not(.comp-quiet-prose):not(.comp-statement):not(.comp-numbered):not(.comp-callout):not(.comp-split):not(.comp-swatch):not(.comp-panel)) .whyus-card, :where(.sl-body):where(.ground-dark).theme-apothecary main > section.section.sec-room .cat-card, :where(.sl-body):where(.ground-dark).theme-apothecary main > section.section.sec-room:where(:not(.comp-menu-list):not(.comp-ledger):not(.comp-quiet-prose):not(.comp-statement):not(.comp-numbered):not(.comp-callout):not(.comp-split):not(.comp-swatch):not(.comp-panel)) .addon-card, :where(.sl-body):where(.ground-dark).theme-apothecary main > section.section.sec-room:where(:not(.comp-menu-list):not(.comp-ledger):not(.comp-quiet-prose):not(.comp-statement):not(.comp-numbered):not(.comp-callout):not(.comp-split):not(.comp-swatch):not(.comp-panel)) .wpkg-card, :where(.sl-body):where(.ground-dark).theme-apothecary main > section.section.sec-room:where(:not(.comp-menu-list):not(.comp-ledger):not(.comp-quiet-prose):not(.comp-statement):not(.comp-numbered):not(.comp-callout):not(.comp-split):not(.comp-swatch):not(.comp-panel)) .tier-card, :where(.sl-body):where(.ground-dark).theme-apothecary main > section.section.sec-room .faq-item, :where(.sl-body):where(.ground-dark).theme-apothecary main > section.section.sec-room:where(:not(.comp-menu-list):not(.comp-ledger):not(.comp-quiet-prose):not(.comp-statement):not(.comp-numbered):not(.comp-callout):not(.comp-split):not(.comp-swatch):not(.comp-panel)) .team-member-card {
  --c-text: var(--c-on-surface);
  --c-text-muted: color-mix(in srgb, var(--c-on-surface) 88%, var(--c-surface-alt));
  --c-border: color-mix(in srgb, var(--c-on-surface) 12%, var(--c-surface-alt));
}

/* ══ DESIGN LANE: clinical-ledger ═══════════════════════════════════════════════════════════════
   A PHYSICIAN'S LEDGER. Authored 2026-09-04 for Stack Hydration, the mobile IV arm of a
   physician-led Long Island practice whose brief reads "clinical luxury, not spa luxury: serif
   display over a clean sans, deep neutral base, one accent, thin borders, prices right-aligned,
   no gradients, no shadows". The shelf had no lane that answered it: the luxury lanes are evening
   rooms and gold rules, the clinical lane is flat white and geometric sans, and every editorial
   lane already on the shelf is worn in this vertical.

   THE DEVICE IS THE RULED ROW. Everything that is a list becomes a ledger: the credential strip,
   the package cards, the add-ons, the towns, the questions, the steps, the four pillars. Each row
   is separated by one hairline in the ink at 18%, the value sits at the right edge in tabular
   figures, and nothing is boxed, filled or shaded to say "here is an item". It survives at squint
   distance — a page of ruled lines reads as a document, not a dashboard — and it costs one
   property per block.

   TYPE IS INK, AT TWO SIZES. Headings are the brand's serif at weight 400, sentence case, tight
   leading; the display size (hero, closing) and the band size, nothing in between. No heading
   takes a colour: hierarchy is size and weight only, which is what separates a practice from a
   wellness startup. Labels are 11.5px tracked caps in the ink at 62%, each opened by a short
   coral rule — the one place the accent is allowed to speak at label scale.

   THE ACCENT HAS TWO JOBS. That rule, and the centre of the step marker. Buttons are the brand's
   primary (navy) with white caps; the accent is never a fill, never a heading, never an icon
   blob. Measured on the authoring palette: white on #093C60 12.4:1; ink #1c2b33 on paper 14:1;
   the 62% label ink on paper 6.1:1; the 18% hairline is a divider, not text, and carries none.

   BOTH RENDERERS ARE DRESSED (traps, section 8 onward). The blueprint home speaks in `.bk-*`
   and `.ed-*`; the interior route in `.section`, `.card`, `.btn`. Both alternating beats are
   declared for the interior (T-beats). Ghost controls keep their ring through the house
   `:not(:where(…))` form (T6). The closing band is left to the block. No plate is repainted
   without its ink following.

   Dressed on the estate root since 2026-09-04 for Stack Hydration; §24-§34. Ground-agnostic on
   the estate root since 2026-09-05: every ink reads the root's own --bk-* tokens (§24b mixes the
   lane's hairlines and label ink from --bk-ink), so the ground is the record's — a deep page
   dresses itself and a paper page is unchanged.

   @lane clinical-ledger | a physician's ledger: hairline-ruled rows, prices set right in tabular figures, ink-only serif headings, one coral rule | suits: clinical physician medical luxury modern precise premium editorial restrained concierge ledger
   ═══════════════════════════════════════════════════════════════════════════════════════════ */
:where(.sl-body).refine-clinical-ledger {
  --cl-hair: color-mix(in srgb, var(--c-text) 18%, transparent);
  --cl-hair-strong: color-mix(in srgb, var(--c-text) 36%, transparent);
  --cl-label: color-mix(in srgb, var(--c-text) 62%, transparent);
  --cl-panel: var(--c-surface-alt, #F3EFE9);
  --cl-air: clamp(76px, 8vw, 118px);
  --cl-air-wide: clamp(112px, 12vw, 186px);
  --cl-air-tight: clamp(52px, 5.5vw, 84px);
  /* THE CORNERS, IN ONE PLACE. This lane was authored square — 2px on every card, control and
     field, 0 on every photograph — because a ledger is a ruled document and the square corner read
     as part of that. The owner, 2026-09-15, looking at the built site: "Everything super square and
     sharp edges. He prefers everything to have rounded edges, like pill-shaped or just rounded, so
     it's not so harsh." So the ledger keeps its hairlines, its tracked caps and its restraint — the
     things that actually make it a ledger — and gives up the hard corner. Every rule below reads
     these four rather than repeating a number, which is why the change is four values and not
     thirty. Controls are pills; cards and plates take 16px; photographs and the map take 14px;
     a field takes 12px, which is the one place a full pill reads as a toy. */
  --card-radius: 20px; --btn-radius: 999px; --input-radius: 12px; --cl-media-radius: 16px;
  --card-shadow: none; --card-hover-shadow: none;
}

/* ── 1. BOTH BEATS, DECLARED. Paper and the warm panel alternate; rooms and the closing keep theirs. */
:where(.sl-body).refine-clinical-ledger.sections-alternate main > section.section:nth-of-type(odd):not(.sec-room):not(.final-cta):not(.section-hub-cta) { background: var(--c-bg); }
:where(.sl-body).refine-clinical-ledger.sections-alternate main > section.section:nth-of-type(even):not(.sec-room):not(.final-cta):not(.section-hub-cta) { background: var(--cl-panel); }
:where(.sl-body).refine-clinical-ledger.bands-paper main > section.section:nth-of-type(odd):not(.sec-room):not(.final-cta):not(.section-hub-cta) { background: var(--c-bg); }
:where(.sl-body).refine-clinical-ledger.bands-paper main > section.section:nth-of-type(even):not(.sec-room):not(.final-cta):not(.section-hub-cta) { background: var(--cl-panel); }
:where(.sl-body).refine-clinical-ledger main > section.section { padding-top: var(--cl-air); padding-bottom: var(--cl-air); }
:where(.sl-body).refine-clinical-ledger .section + .section:not(.final-cta) { border-top: 1px solid var(--cl-hair); }

/* ── 2. TYPE: serif at weight 400, sentence case, tight; labels tracked and quiet. */
:where(.sl-body).refine-clinical-ledger h1, :where(.sl-body).refine-clinical-ledger h2 { font-weight: 400; letter-spacing: -0.015em; text-transform: none; }
:where(.sl-body).refine-clinical-ledger .hero-inner h1, :where(.sl-body).refine-clinical-ledger .hub-hero h1 { font-size: clamp(44px, 5.4vw, 76px); line-height: 1.0; letter-spacing: -0.02em; }
:where(.sl-body).refine-clinical-ledger .section-header h2 { font-size: clamp(34px, 3.4vw, 48px); line-height: 1.05; }
:where(.sl-body).refine-clinical-ledger .eyebrow, :where(.sl-body).refine-clinical-ledger .hero .eyebrow, :where(.sl-body).refine-clinical-ledger .section-header .eyebrow {
  font-family: var(--font-body); font-weight: 500; text-transform: uppercase;
  letter-spacing: 0.24em; font-size: 0.72rem; background: none; padding: 0;
}
:where(.sl-body).refine-clinical-ledger .eyebrow::before, :where(.sl-body).refine-clinical-ledger .eyebrow::after, :where(.sl-body).refine-clinical-ledger .section-header .eyebrow::before, :where(.sl-body).refine-clinical-ledger .section-header .eyebrow::after { content: none !important; }

/* ── 3. CARDS ARE RULED, NOT SHADED. The featured tier and the timeline keep their own plates. */
:where(.sl-body).refine-clinical-ledger .card, :where(.sl-body).refine-clinical-ledger .feature-card, :where(.sl-body).refine-clinical-ledger .cat-card, :where(.sl-body).refine-clinical-ledger .pkg-card, :where(.sl-body).refine-clinical-ledger .whyus-card, :where(.sl-body).refine-clinical-ledger .addon-card, :where(.sl-body).refine-clinical-ledger .review-card, :where(.sl-body).refine-clinical-ledger .step-card, :where(.sl-body).refine-clinical-ledger .tier-card:not(.tier-featured), :where(.sl-body).refine-clinical-ledger .faq-item {
  border-radius: var(--card-radius); box-shadow: none; border: 1px solid var(--cl-hair);
}
:where(.sl-body).refine-clinical-ledger .card:hover, :where(.sl-body).refine-clinical-ledger .feature-card:hover, :where(.sl-body).refine-clinical-ledger .cat-card:hover, :where(.sl-body).refine-clinical-ledger .pkg-card:hover, :where(.sl-body).refine-clinical-ledger .tier-card:not(.tier-featured):hover { box-shadow: none; transform: none; border-color: var(--cl-hair-strong); }
:where(.sl-body).refine-clinical-ledger .faq-item summary, :where(.sl-body).refine-clinical-ledger .faq-list summary { font-family: var(--font-heading); font-weight: 400; font-size: 1.2rem; padding: 1.1rem 1.25rem; }
:where(.sl-body).refine-clinical-ledger .contact-method { border-radius: var(--card-radius); }
:where(.sl-body).refine-clinical-ledger .lead-field input, :where(.sl-body).refine-clinical-ledger .lead-field select, :where(.sl-body).refine-clinical-ledger .lead-field textarea { border-radius: var(--input-radius); border: 1px solid var(--cl-hair-strong); }

/* ── 4. ONE CONTROL VOICE. Pills, tracked caps, ONE fill — the control plate, which on every
      light page resolves through the room to the primary (byte for byte what this rule painted) and
      on a deep page is the light stock with the brand's caps, the same pairing the room rule below
      and §19's hero already use. It was `--c-room` here, which is a BAND: measured on the dark cell
      this selector painted the packages menu's Book Online at 1.50:1 on the tinted band and the
      contact page's three at 1.00:1 on a card. The account is beside `.btn-primary` at the head of
      this file. `--c-control-ring: transparent` opts it out of the dark rescue outline — it has a
      plate now, and a ring on a filled pill was what made it read as an outline button. */
:where(.sl-body).refine-clinical-ledger .btn { border-radius: var(--btn-radius); font-weight: 500; font-size: 0.8rem; letter-spacing: 0.16em; text-transform: uppercase; padding: 0.95rem 1.6rem; box-shadow: none; }
:where(.sl-body).refine-clinical-ledger .btn:hover { box-shadow: none; transform: none; }
:where(.sl-body).refine-clinical-ledger main > section.section:not(.final-cta):not(.sec-room):not(.hero):not(.hub-hero) .btn-primary { background: var(--c-control); color: var(--c-on-control); --c-control-ring: transparent; }
:where(.sl-body).refine-clinical-ledger main > section.section:not(.final-cta):not(.sec-room):not(.hero):not(.hub-hero) .btn-secondary { background: transparent; border: 1px solid var(--cl-hair-strong); color: var(--c-text); }
/* IN A ROOM the fill is the light stock on BOTH grounds and always was: on paper the room is the
   brand's navy and a white pill is the only fill that reads on it, and on a deep page the light
   stock IS the control plate, so this rule and the one above now paint the same colour there. Left
   as a rule of its own rather than folded into `--c-control`: the role's LIGHT value is the room,
   and inside a room that would be navy on navy. The ring is off for the same reason as above. */
:where(.sl-body).refine-clinical-ledger main > section.section.sec-room .btn-primary { background: var(--c-light-stock); color: var(--c-primary); --c-control-ring: transparent; }

/* ── 5. THE BLUEPRINT HOME — chrome. */
:where(.sl-body).refine-clinical-ledger .bk-home { --bk-rhythm: var(--cl-air); --bk-radius: var(--cl-media-radius, 14px); --bk-hair: var(--cl-hair); }
:where(.sl-body).refine-clinical-ledger .ed-nav { background: var(--c-bg); border-bottom: 1px solid var(--cl-hair); }
:where(.sl-body).refine-clinical-ledger .ed-brand small, :where(.sl-body).refine-clinical-ledger .ed-brand-tag small { color: var(--cl-label); letter-spacing: 0.2em; }
:where(.sl-body).refine-clinical-ledger .ed-links a { font-size: 14.5px; letter-spacing: 0.02em; color: var(--c-text); }
:where(.sl-body).refine-clinical-ledger .ed-foot h4 { color: rgba(255,255,255,0.62); }

/* every control on the home speaks the same: rectangle, tracked caps, primary fill or ink ghost */
:where(.sl-body).refine-clinical-ledger :is(.ed-pill, :where(.sl-body) .bk-pill, :where(.sl-body) .bk-btn, :where(.sl-body) .bk-prose-pill, :where(.sl-body) .rt-pill, :where(.sl-body) .cm-book, :where(.sl-body) .bh-pill, :where(.sl-body) .et-btn, :where(.sl-body) .bl-pill) {
  border-radius: var(--btn-radius); font-family: var(--font-body); font-weight: 500; font-size: 12.5px; line-height: 1.2;
  letter-spacing: 0.16em; text-transform: uppercase; padding: 15px 26px;
}
:where(.sl-body).refine-clinical-ledger :is(.ed-pill, :where(.sl-body) .bk-pill-fill, :where(.sl-body) .bk-btn-fill) { background: var(--c-primary); color: #fff; }
:where(.sl-body).refine-clinical-ledger :is(.bk-pill-ghost, :where(.sl-body) .bk-btn-ghost) { background: transparent; color: var(--c-text); }
/* T6: a shadow may go; a ring drawn as one may not. */
:where(.sl-body).refine-clinical-ledger :is(.bk-btn, :where(.sl-body) .bk-pill, :where(.sl-body) .bk-chip, :where(.sl-body) .bk-city, :where(.sl-body) .bk-ict-pill, :where(.sl-body) .bk-prose-pill)
  :not(:where(.bk-pill-ghost, :where(.sl-body) .bk-pill-outline, :where(.sl-body) .bk-btn-ghost)) { box-shadow: none; }
:where(.sl-body).refine-clinical-ledger :is(.rt-pill, :where(.sl-body) .cm-book, :where(.sl-body) .ed-pill, :where(.sl-body) .bh-pill, :where(.sl-body) .et-btn, :where(.sl-body) .bl-pill):not(:where(.rt-outline, :where(.sl-body) .rt-soft, :where(.sl-body) .et-btn-ghost, :where(.sl-body) .et-btn-ghost-white, :where(.sl-body) .bl-pill-ghost)) { box-shadow: none; }

/* headings on the home: ink, serif, weight 400 — the conditions panel is a dark plate and keeps its white */
:where(.sl-body).refine-clinical-ledger .ed.bk-home :is(.bk-prail-editorial h2, :where(.sl-body) .bk-pillars h2, :where(.sl-body) .bk-prose-editorial h2, :where(.sl-body) .bk-tl h2, :where(.sl-body) .bk-ledger h2, :where(.sl-body) .bk-cities h2, :where(.sl-body) .bk-faq h2, :where(.sl-body) .bk-close-editorial h2, :where(.sl-body) .bk-contact h2) {
  font-family: var(--font-heading); font-weight: 400; text-transform: none; letter-spacing: -0.015em; line-height: 1.04;
  color: var(--c-text); font-size: clamp(38px, 3.9vw, 54px);
}
:where(.sl-body).refine-clinical-ledger .ed.bk-home :is(.bk-close-editorial h2, :where(.sl-body) .bk-contact h2) { font-size: clamp(42px, 4.8vw, 68px); letter-spacing: -0.02em; line-height: 1.0; }
:where(.sl-body).refine-clinical-ledger :is(.ed, :where(.sl-body) .et).bk-home .bk-cond h2 { color: #fff; font-family: var(--font-heading); font-weight: 400; text-transform: none; letter-spacing: -0.015em; line-height: 1.04; font-size: clamp(30px, 3vw, 40px); }

/* labels: 11.5px tracked caps, quiet ink, opened by the one coral rule */
:where(.sl-body).refine-clinical-ledger :is(.ed, :where(.sl-body) .et).bk-home :is(.bk-eyebrow-caps, :where(.sl-body) .bk-prail-eyebrow, :where(.sl-body) .bk-prose-eyebrow, :where(.sl-body) .bk-ledger-eyebrow, :where(.sl-body) .bk-faq-eyebrow, :where(.sl-body) .bk-close-eyebrow, :where(.sl-body) .bk-clabel, :where(.sl-body) .bk-cond-eyebrow, :where(.sl-body) .et-eyebrow) {
  font-family: var(--font-body); font-weight: 500; font-size: 11.5px; line-height: 1; letter-spacing: 0.24em; text-transform: uppercase; color: var(--cl-label);
}
:where(.sl-body).refine-clinical-ledger :is(.ed, :where(.sl-body) .et).bk-home :is(.bk-eyebrow-caps, :where(.sl-body) .bk-prail-eyebrow, :where(.sl-body) .bk-prose-eyebrow, :where(.sl-body) .bk-ledger-eyebrow, :where(.sl-body) .bk-faq-eyebrow, :where(.sl-body) .bk-close-eyebrow, :where(.sl-body) .bk-clabel, :where(.sl-body) .et-eyebrow)::before {
  content: ''; display: inline-block; width: 26px; height: 1px; background: var(--c-accent); margin-right: 12px; vertical-align: middle;
}
:where(.sl-body).refine-clinical-ledger :is(.ed, :where(.sl-body) .et).bk-home .bk-cond-eyebrow { color: rgba(255,255,255,0.72); }
:where(.sl-body).refine-clinical-ledger :is(.ed, :where(.sl-body) .et).bk-home .bk-eyebrow-rule { font-size: 11.5px; letter-spacing: 0.24em; color: var(--cl-label); }

/* running text at the brief's 17 to 18px, in the ink */
:where(.sl-body).refine-clinical-ledger :is(.ed, :where(.sl-body) .et).bk-home :is(.bk-split-body, :where(.sl-body) .bk-prail-sub, :where(.sl-body) .bk-prose-body p, :where(.sl-body) .bk-prose-lead, :where(.sl-body) .bk-step-body, :where(.sl-body) .bk-ledger-intro, :where(.sl-body) .bk-cities-body, :where(.sl-body) .bk-close-body, :where(.sl-body) .bk-close-line2, :where(.sl-body) .bk-contact-lead, :where(.sl-body) .bk-pillar p, :where(.sl-body) .bk-a, :where(.sl-body) .bk-cond-lead) {
  font-size: 17.5px; line-height: 1.6;
}

/* photographs: hairline-framed, a touch desaturated so the set reads as one shoot, and softened at
   the corner with the lane's own media radius — they were square until 2026-09-15 (see the token
   block at the head of this lane for the owner's words) */
:where(.sl-body).refine-clinical-ledger :is(.ed, :where(.sl-body) .et).bk-home :is(.bk-split-img img, :where(.sl-body) img.bk-split-img, :where(.sl-body) .bk-tl-art, :where(.sl-body) .bk-faq-art, :where(.sl-body) .bk-close-field-photo img, :where(.sl-body) .sl-contact-art, :where(.sl-body) .bk-cond-ph img, :where(.sl-body) .bk-prose-photo img, :where(.sl-body) .bk-pil-ph img) {
  border-radius: var(--cl-media-radius, 14px); filter: saturate(0.88);
}
:where(.sl-body).refine-clinical-ledger :is(.ed, :where(.sl-body) .et).bk-home :is(.bk-split-img img, :where(.sl-body) img.bk-split-img, :where(.sl-body) .bk-tl-art, :where(.sl-body) .bk-faq-art, :where(.sl-body) .bk-close-field-photo img, :where(.sl-body) .sl-contact-art) { border: 1px solid var(--cl-hair); }

/* ── 6. HERO: the display size, the words ranged left, the picture a plate. */
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-split { gap: clamp(40px, 6vw, 96px); grid-template-columns: minmax(0, 1.1fr) minmax(0, 560px); }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-split h1 { font-size: clamp(46px, 5.4vw, 76px); line-height: 1.0; letter-spacing: -0.02em; font-weight: 400; color: var(--c-text); }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-split-body { font-size: 18px; color: var(--c-text); max-width: 34ch; }

/* ── 7. THE CREDENTIAL STRIP IS A RULED LINE OF SMALL CAPS, not a row of icon blobs. */
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-cs { border-top: 1px solid var(--cl-hair); border-bottom: 1px solid var(--cl-hair); padding-top: 22px; padding-bottom: 22px; }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-cs-item { font-family: var(--font-body); font-weight: 500; font-size: 12.5px; line-height: 1.3; letter-spacing: 0.18em; text-transform: uppercase; color: var(--c-text); gap: 12px; }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-cs-item svg { width: 22px; height: 22px; fill: var(--c-text); }

/* ── 8. THE PACKAGE CARD IS A TALL RULED RECTANGLE: plate, name left, price right, note, a text link. */
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-prail-editorial .bk-prail-card {
  display: flex; flex-direction: column; border: 1px solid var(--cl-hair); border-radius: var(--card-radius); overflow: hidden; padding: 0 0 20px; background: var(--c-surface);
}
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-prail-editorial .bk-prail-pic { background: var(--cl-panel); height: 300px; margin: 0 0 18px; border-bottom: 1px solid var(--cl-hair); }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-prail-editorial .bk-prail-row { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; margin: 0 18px 6px; }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-prail-editorial .bk-prail-row > h3 { margin: 0; font-family: var(--font-heading); font-weight: 400; font-size: 21px; line-height: 1.15; letter-spacing: -0.01em; text-transform: none; min-height: 0; color: var(--c-text); }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-prail-editorial .bk-prail-price { margin: 0; font-family: var(--font-heading); font-weight: 400; font-size: 21px; line-height: 1.15; font-variant-numeric: tabular-nums; color: var(--c-text); text-align: right; white-space: nowrap; }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-prail-editorial .bk-prail-note { margin: 6px 18px 18px; font-size: 15px; line-height: 1.55; color: var(--c-text-muted, var(--bk-muted)); }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-prail-editorial .bk-prail-cta {
  align-self: flex-start; margin: auto 18px 0; background: none; color: var(--c-text); padding: 8px 0 6px; border-radius: 0;
  border-bottom: 1px solid var(--cl-hair-strong); font-weight: 500; font-size: 12px; letter-spacing: 0.16em;
}
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-prail-editorial .bk-prail-cta:hover { border-bottom-color: var(--c-text); }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-prail-editorial .bk-prail-end { display: flex; flex-direction: column; justify-content: center; align-items: flex-start; padding: 24px; }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-prail-editorial .bk-prail-more { color: var(--c-text); font-weight: 500; font-size: 12px; letter-spacing: 0.16em; border-bottom: 1px solid var(--cl-hair-strong); }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-prail-editorial .bk-prail-arrow { background: transparent; border: 1px solid var(--cl-hair); border-radius: 999px; color: var(--c-text); }

/* ── 9. THE FOUR PILLARS ARE RULED ROWS, name left and sentence right; no lead panel. */
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-pillars .bk-pilrow { display: grid; grid-template-columns: minmax(0, 1fr); gap: 0; }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-pillars .bk-pilrow > .bk-pillar {
  grid-column: auto !important; grid-row: auto !important; display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 7fr); column-gap: clamp(24px, 4vw, 56px);
  background: none; border: 0; border-top: 1px solid var(--cl-hair); border-radius: 0; padding: 26px 0 30px !important; overflow: visible;
}
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-pillars .bk-pilrow > .bk-pillar:last-child { border-bottom: 1px solid var(--cl-hair); }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-pillars .bk-pillar h3 { grid-column: 1; margin: 0; font-family: var(--font-heading); font-weight: 400; font-size: 23px !important; line-height: 1.2; color: var(--c-text); }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-pillars .bk-pillar p { grid-column: 2; margin: 0; }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-pillars .bk-pillar .bk-pil-arrow { display: none; }

/* ── 10. THE ABOUT BAND READS LEFT, upright, at the reading measure. */
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-prose-editorial .bk-prose-in { display: block; }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-prose-editorial .bk-prose-copy { display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: clamp(26px, 4vw, 64px); align-items: start; }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-prose-editorial .bk-prose-head { grid-column: 1; }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-prose-editorial :is(.bk-prose-body, :where(.sl-body) .bk-prose-cta) { grid-column: 2; }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-prose-editorial .bk-prose-body { column-count: 1 !important; columns: 1 !important; }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-prose-editorial .bk-prose-head { text-align: left; }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-prose-editorial h2 { max-width: 12ch; text-align: left; }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-prose-editorial :is(.bk-prose-lead, :where(.sl-body) .bk-prose-body p) { font-style: normal; text-align: left; max-width: 62ch; }

/* ── 11. THE JOURNEY IS A RULED LEDGER: ink numerals, hairline rows, one coral point per step. */
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-tl .bk-no { font-family: var(--font-heading); font-weight: 400; font-size: 30px; color: var(--c-text); }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-tl .bk-dot { border-color: var(--c-text); background: var(--c-bg); }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-tl .bk-dot::after { background: var(--c-accent); }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-tl .bk-rail::before { background: var(--cl-hair); opacity: 1; }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-tl .bk-step { border: 0 !important; border-top: 1px solid var(--cl-hair) !important; border-radius: 0; background: none !important; padding: 24px 0 !important; margin-bottom: 0 !important; }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-tl .bk-step:last-child { border-bottom: 1px solid var(--cl-hair) !important; }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-tl .bk-step h3 { font-family: var(--font-heading); font-weight: 400; font-size: 24px; line-height: 1.2; color: var(--c-text); }

/* ── 12. THE ADD-ONS LEDGER: ink figures, hairline rows. */
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-ledger-editorial .bk-ledger-card { border-top: 1px solid var(--c-text); }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-ledger-editorial .bk-ledger-row { border-bottom: 1px solid var(--cl-hair); }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-ledger-editorial .bk-ledger-cost { font-family: var(--font-heading); font-weight: 400; font-size: 19px; font-variant-numeric: tabular-nums; color: var(--c-text); }

/* ── 13. THE TOWNS ARE ONE RULED LINE, not a scatter of pills. */
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-citygrid { gap: 0; justify-content: flex-start; border-top: 1px solid var(--cl-hair); border-bottom: 1px solid var(--cl-hair); padding: 4px 0; }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-city { border: 0; border-radius: 0; background: none; padding: 13px 15px; font-family: var(--font-body); font-weight: 500; font-size: 11.5px; line-height: 1; letter-spacing: 0.16em; text-transform: uppercase; color: var(--c-text); }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-city + .bk-city { border-left: 1px solid var(--cl-hair); }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-city:hover { border-color: var(--cl-hair); color: var(--c-primary); }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-city i { display: none; }

/* ── 14. QUESTIONS: serif, ruled, the chevron in ink. */
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-faq-editorial .bk-q { border-bottom: 1px solid var(--cl-hair); }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-faq-editorial .bk-q summary { font-family: var(--font-heading); font-weight: 400; font-size: 22px; line-height: 1.3; color: var(--c-text); padding: 22px 0; }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-faq-editorial .bk-q-badge { display: none; }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-faq-editorial .bk-q-chev { color: var(--c-text); opacity: 0.6; }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-faq-editorial .bk-a { max-width: 62ch; }

/* ── 15. CLOSING AND CONTACT: display size, plates ruled. */
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-close-editorial .bk-btn { border-radius: var(--btn-radius); }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-ccard { border: 1px solid var(--cl-hair); border-radius: var(--card-radius); background: var(--c-surface); box-shadow: none; }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-maptile { border-radius: var(--cl-media-radius, 14px); border: 1px solid var(--cl-hair-strong); }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-mapfoot { border: 1px solid var(--cl-hair-strong); }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-mapfoot b { color: var(--cl-label); }

/* ── 16. THE CONDITIONS PANEL keeps its dark plate; its filled control takes the light stock on
      navy. The rule named `.bk-pill-fill`, which this block does not emit — its secondary link is
      `.bk-pill bk-pill-dark` (ConditionsPanel.astro:83) — so the rule reached nothing and the deep
      pill went on sitting on the navy plate at 1.45:1 while the lane's own note claimed it had
      been handled. The plate draws no edge of its own either: on a page whose ground is near its
      own colour it reads as a faint inset rather than a plate, so on the estate root it takes the
      ledger's hairline, which is the root's ink at 18% and therefore white on a deep page. */
:where(.sl-body).refine-clinical-ledger :is(.ed, :where(.sl-body) .et).bk-home .bk-cond-panel { border-radius: var(--card-radius); }
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-cond-panel { border: 1px solid var(--cl-hair); }
:where(.sl-body).refine-clinical-ledger :is(.ed, :where(.sl-body) .et).bk-home .bk-cond .bk-pill-dark { background: var(--c-light-stock); color: var(--c-primary); }
:where(.sl-body).refine-clinical-ledger :is(.ed, :where(.sl-body) .et).bk-home .bk-cond .bk-pill-ghost { color: var(--et-ink, #fff); box-shadow: inset 0 0 0 1.4px var(--cl-hair-strong); }

/* ── 17. THE PAGE RANGES LEFT, ONE EDGE. NO BAND INDEX — see below.
      NUMBERING SECTIONS IS NOT A HOUSE DEVICE. The owner, 2026-09-07: "why is each section
      numbered? We should never do that, u need to fix that in the sitelaunch system." It read as
      a drawing sheet rather than a website, and it made every band announce itself before it said
      anything. The counter, its increment and the rule that printed it are deleted here rather
      than switched off, so no lane can pick the device back up by accident; the eyebrow keeps its
      tracked caps and its coral rule, which is what actually carried the label. */
:where(.sl-body).refine-clinical-ledger .ed.bk-home .bk-prail-sub { max-width: 60ch; }

/* footer and nav small type: the tagline and the column heads are quiet, not coral */
:where(.sl-body).refine-clinical-ledger .ed.bk-home .ed-nav .ed-brand small, :where(.sl-body).refine-clinical-ledger .ed.bk-home .ed-nav .ed-brand-tag small { color: var(--cl-label); }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .ed-foot h4, :where(.sl-body).refine-clinical-ledger .ed.bk-home .ed-foot .bk-eyebrow-caps { color: rgba(255,255,255,0.62); }
:where(.sl-body).refine-clinical-ledger .ed.bk-home .ed-foot .ed-brand small, :where(.sl-body).refine-clinical-ledger .ed.bk-home .ed-foot .ed-brand-tag small { color: rgba(255,255,255,0.55); }

/* ── 18. THE INTERIOR CHROME (bc-*) speaks the same control voice; its ghost keeps its ring. */
:where(.sl-body).refine-clinical-ledger :is(.bc-btn, :where(.sl-body) .bc-fill, :where(.sl-body) .bc-ghost) { border-radius: var(--btn-radius); font-family: var(--font-body); font-weight: 500; font-size: 12.5px; letter-spacing: 0.16em; text-transform: uppercase; }
:where(.sl-body).refine-clinical-ledger .bc-fill { box-shadow: none; }
/* THE FILL IS FOR THE PAPER BAR ONLY, AND SAYS SO. The rule was written for both of the chrome's
   bars. On the deep bar it never actually won — the chrome's own `.bc-on-dark .bc-fill` carries
   the component's scope attribute and out-ranks it, so the accent fill with deep caps has been
   what renders all along (measured on the Tidewater cell: rgb(194,163,107) before and after this
   edit). That is a rule whose behaviour depends on a specificity accident nobody wrote down: move
   the scope attribute or drop the class from the chrome and the deep bar silently takes a navy
   button on a near-navy bar. So the intent is written into the selector instead. On the paper bar,
   where the rule does win, the fill is the room's colour with the ink the room derives — the
   primary and #fff on every light page, and on a deep page a navy lifted until it steps off it. */
:where(.sl-body).refine-clinical-ledger .bc-on-paper .bc-fill { background: var(--c-room); color: var(--c-on-room); }
:where(.sl-body).refine-clinical-ledger .bc-foot h4 { color: var(--bc-foot-head, rgba(255,255,255,0.62)); }
:where(.sl-body).refine-clinical-ledger .bc-legal { color: var(--bc-dark-ink-faint, rgba(255,255,255,0.5)); }


/* ── 19. THE INTERIOR HERO'S CONTROLS. The hero paints the brand's dark; a navy fill vanishes on it. */
:where(.sl-body).refine-clinical-ledger .hero .btn-primary { background: var(--c-light-stock); color: var(--c-primary); border-color: var(--c-light-stock); }
:where(.sl-body).refine-clinical-ledger .hero .btn-primary:hover { background: #fff; color: var(--c-primary); }
:where(.sl-body).refine-clinical-ledger .hero .btn-secondary { color: #fff; border-color: rgba(255,255,255,0.72); }

/* ── 20. THE OTHER FOUR HOMES. A lane is judged on the retail fixture, and a lane that only
      speaks editorial reads as the default everywhere else. Shape only: square corners, one
      hairline, no elevation. No plate is repainted — a card that carries its own dark fill and
      white ink (the featured tier, the overlay card, the promo) keeps both and takes the corner. */
:where(.sl-body).refine-clinical-ledger :is(.bk-pcard, :where(.sl-body) .bk-tier:not(.bk-feat), :where(.sl-body) .bk-plate, :where(.sl-body) .bk-ps, :where(.sl-body) .bk-ccard, :where(.sl-body) .bk-pillar, :where(.sl-body) .rt-q, :where(.sl-body) .cm-card, :where(.sl-body) .bh-card, :where(.sl-body) .bk-card) {
  border-radius: var(--card-radius); box-shadow: none; border: 1px solid var(--cl-hair);
}
:where(.sl-body).refine-clinical-ledger :is(.bk-pcard, :where(.sl-body) .bk-tier:not(.bk-feat), :where(.sl-body) .bk-plate, :where(.sl-body) .bk-ps, :where(.sl-body) .bk-ccard, :where(.sl-body) .bk-pillar):hover { box-shadow: none; transform: none; border-color: var(--cl-hair-strong); }
:where(.sl-body).refine-clinical-ledger :is(.bk-tier.bk-feat, :where(.sl-body) .bk-ovl-card, :where(.sl-body) .bk-promo, :where(.sl-body) .bk-pgrid-panel, :where(.sl-body) .bk-cond-panel) { border-radius: var(--card-radius); box-shadow: none; }
:where(.sl-body).refine-clinical-ledger :is(.rt-eyebrow, :where(.sl-body) .cm-eyebrow, :where(.sl-body) .bh-eyebrow, :where(.sl-body) .bl-eyebrow) { font-family: var(--font-body); font-weight: 500; font-size: 11.5px; letter-spacing: 0.24em; text-transform: uppercase; }
:where(.sl-body).refine-clinical-ledger :is(.rt-hero-art img, :where(.sl-body) .bk-pil-ph img, :where(.sl-body) .bk-tiers-art img, :where(.sl-body) .bk-step-art) { border-radius: var(--cl-media-radius, 14px); }

/* ── 21. THE LEDGER RULES BETWEEN ITS BANDS. A ledger divides its rows with a line, not with a
      change of stock; the page does the same between bands, on every home design, and keeps its
      alternating grounds underneath. The closing band is left to the block, and so are the rooms
      that stand on a photograph (the estate hero, steps and events): a picture does not need a 1px
      ink rule on its top edge. */
:where(.sl-body).refine-clinical-ledger .bk-home > section + section:not(.bk-close):not(.rt-closing):not(.et-closing):not(.et-hero):not(.bk-sit):not(.bk-ev):not(:has(> .bk-sit)) { border-top: 1px solid var(--cl-hair); }

/* ── 22. THE RULE SITS ON THE BAND THE PAGE ITSELF COUNTS. Most blocks arrive wrapped in a bare div,
      so a rule on `section + section` reached four bands in eleven. The page's own alternation
      counts :is(section, :has(section)) among the home's children; the ledger rules the same set. */
:where(.sl-body).refine-clinical-ledger .bk-home > :is(section, :where(.sl-body) div:has(> section)) + :is(section, :where(.sl-body) div:has(> section)):not(.bk-close):not(.rt-closing):not(.et-closing):not(.et-hero):not(.bk-sit):not(.bk-ev):not(:has(> .bk-sit)):not(:has(> .bk-close)):not(:has(> .rt-closing)):not(:has(> .et-closing)) {
  border-top: 1px solid var(--cl-hair);
}
/* ── 23. A SHORT RULE UNDER EVERY BAND HEADING — the chart's underscore. Ink on paper, light on
      the navy panel; centred under a centred title, flush under a ranged one. Card headings are
      not band headings and take nothing. */
:where(.sl-body).refine-clinical-ledger .bk-home h2:not(:is(.bk-pcard, :where(.sl-body) .bk-tier, :where(.sl-body) .bk-pillar, :where(.sl-body) .bk-step, :where(.sl-body) .bk-q, :where(.sl-body) .bk-ps, :where(.sl-body) .bk-plate, :where(.sl-body) .bk-ovl-card, :where(.sl-body) .bk-promo, :where(.sl-body) .bk-prail-card, :where(.sl-body) .bk-ccard) *)::after {
  content: ''; display: block; width: 44px; height: 1px; background: var(--cl-hair-strong); margin: 18px auto 0;
}
:where(.sl-body).refine-clinical-ledger .bk-home :is(.bk-composed, :where(.sl-body) .bk-prose-editorial, :where(.sl-body) .bk-cond, :where(.sl-body) .bk-close, :where(.sl-body) .bk-contact, :where(.sl-body) .bk-pillars, :where(.sl-body) .bk-split) h2::after { margin-inline: 0; }
:where(.sl-body).refine-clinical-ledger .bk-home :is(.bk-cond, :where(.sl-body) .et-band, :where(.sl-body) .bk-sit, :where(.sl-body) .bk-ev, :where(.sl-body) .et-hero) h2::after { background: rgba(255,255,255,0.42); }

/* ── 24. THE ESTATE ROOT. Dressed 2026-09-04 for Stack Hydration (round three, spec R3). Until
      then 78 of this lane's rule heads were scoped to the editorial root and reached nothing on
      `.et.bk-home`: an estate client wearing the ledger got the family's uppercase tracked serif,
      brown-mixed eyebrows and prices, eight navy town bars and tint FAQ boxes with coral badges —
      the house look the lane exists to remove. The shared devices now reach both roots through the
      widened rules above (§5's label device, the running-text size, the photograph frame, §17's
      band counter, §21-§23's hairlines and underscore); what follows is what the estate family
      draws differently and needs a line of its own for. Every selector sits at (0,4,1)-(0,5,1):
      above the template's attribute-scoped rules, and never !important. No room, no photograph
      and no ground colour is painted here; the only literals are white alphas inside bands whose
      ink the family already draws white. */

/* ── 24b. THE ROOT'S OWN INK DECIDES THE LANE'S HAIRLINES. Every device this lane draws — the rule
      between two rows, the stronger rule under a heading, the quiet label ink, the warm panel —
      was mixed from the PAGE's tokens (--c-text, --c-surface-alt). On a paper page that is the
      same colour the estate root already draws its ink in; on a deep page it is a near-black
      hairline on navy and a label nobody can read. The estate home paints its own paper and its
      own ink (--bk-paper / --bk-ink, resolved once by brand.ts from the merged palette), so on
      this root the lane mixes from THOSE. One block here re-derives §5's hairline token, §20's
      card rule, §21-§23's band rules and heading underscore, §26's label, §30's town rules,
      §31's question rules and §32's chip — none of which needs a rule of its own. §27's room
      remap still wins inside a navy room: it sets these same tokens on the room element, and a
      child's own declaration beats an inherited one.
      THE LABEL IS BODY TEXT, AND 62% WAS UNDER THE LINE ON BOTH GROUNDS. `--cl-label` inks the
      band eyebrows, the menu's "What's Included", the step numbers and the duration under a price —
      all of it 11.5px to 16px, which is small text and wants 4.5:1. Mixed 62% toward transparent it
      composited to 3.84:1 on the LIGHT cell's card and 3.65:1 on the dark cell's, so the lane was
      shipping a sub-AA label on a live site and a worse one on the deep page. The quiet ink is
      still quiet — it is a mix of the root's own ink, not a second colour — it is just mixed far
      enough to clear the line on the lightest thing it prints on, which is the CARD on either
      ground. Measured after: light card 6.04:1, light paper 5.74:1, light tint 5.36:1; dark card
      4.73:1, dark paper 9.42:1, dark tint 6.70:1. One percentage, because the ink and the ground
      swap sides together and the composite behaves the same way on both. The hairlines are
      untouched: a hairline is a rule, not text, and has no contrast floor to clear. */
:where(.sl-body).refine-clinical-ledger .et.bk-home {
  --cl-hair: color-mix(in srgb, var(--bk-ink) 18%, transparent);
  --cl-hair-strong: color-mix(in srgb, var(--bk-ink) 36%, transparent);
  --cl-label: color-mix(in srgb, var(--bk-ink) 78%, transparent);
  --cl-panel: var(--bk-tint);
}

/* ── 25. TITLES ARE INK, SENTENCE CASE. The family sets uppercase tracked serif at weight 500;
      the ledger's heading is weight 400, sentence case, tight. The hero h1 keeps the family's
      clamp — its legibility gate is calibrated at 60px. The shared blocks this home draws — the
      menu (.bk-plinths), events (.bk-ev), contact (.bk-contact) — set their own uppercase tracked
      serif at weight 500 and join the rule, or the page shows one capitalised title among the
      sentence-case ones (looked at: "IV DRIPS & PRICING" on the Tidewater cell). The conditions
      plate's heading takes the same face at the plate size §5 gives it on the editorial home; its
      ink stays the block's white. The reviews RIBBON (a one-line variant the template draws when
      there are no quotes) keeps its small title and zero margins, or the band size and 34px
      stand-off would turn a ribbon back into an empty band. */
:where(.sl-body).refine-clinical-ledger .et.bk-home :is(.et-title-ink, :where(.sl-body) .et-band-title, :where(.sl-body) .bk-sit h2, :where(.sl-body) .bk-ev h2, :where(.sl-body) .bk-plinths h2, :where(.sl-body) .bk-contact h2, :where(.sl-body) .et-expert-copy h2) {
  font-family: var(--font-heading); font-weight: 400; text-transform: none; letter-spacing: -0.015em; line-height: 1.04;
  font-size: clamp(38px, 3.9vw, 54px); margin-bottom: 34px;
}
:where(.sl-body).refine-clinical-ledger .et.bk-home :is(.et-title-ink, :where(.sl-body) .et-expert-copy h2, :where(.sl-body) .bk-plinths h2, :where(.sl-body) .bk-contact h2) { color: var(--bk-title-ink); }
:where(.sl-body).refine-clinical-ledger .et.bk-home .et-closing-title { text-transform: none; letter-spacing: -0.01em; font-size: clamp(40px, 4.2vw, 60px); }
:where(.sl-body).refine-clinical-ledger .et.bk-home .et-reviews-ribbon .et-band-title { font-size: clamp(20px, 2vw, 27px); margin: 0; }

/* ── 26. THE LABEL DEVICE + BAND INDEX. 11.5px tracked caps in the quiet ink, opened by the band's
      number over the one coral rule (§17's ::before, widened above). The counter runs on the
      labels themselves (the ::before that prints it), so the visible sequence never skips a
      number on a band that carries no label; the hero's label prints no ::before, so it does not count. The hero's eyebrow is the trust line: a touch larger, white, never
      counted — excluded here by a plain override rather than by a :not() inside the shared lists
      above, because a :not() with a complex argument lifts the specificity of the WHOLE :is() list
      it sits in, above §27's white remap and above the editorial conditions number (measured: the
      closing room's number drew in ink). The ribbon's eyebrow keeps its zero margin (it sits on a
      baseline row). */
:where(.sl-body).refine-clinical-ledger .et.bk-home .et-eyebrow {
  font-family: var(--font-body); font-weight: 500; font-size: 15px; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--cl-label); margin-bottom: 18px;
}
:where(.sl-body).refine-clinical-ledger .et.bk-home .et-hero .et-eyebrow { font-size: 13px; color: rgba(255,255,255,0.82); }
:where(.sl-body).refine-clinical-ledger .et.bk-home .et-reviews-ribbon .et-eyebrow { margin: 0; }

/* ── 27. DARK-ROOM TOKENS. Inside a navy room every ruled row, ring and label the ledger draws is
      drawn in white — by remapping the lane's own tokens, so no block ink is repainted. The
      accent-text token (what the step captions and the menu's figures read) joins them: the family
      writes it INLINE on the root as a coral-to-ink mix, i.e. brown, and an inline value cannot be
      out-ranked on its own element without !important — so it is re-set on the root's children,
      where a child's own declaration beats the inherited one: the primary on the light bands,
      white in the rooms. Every navy room on this home is listed — hero, reviews/closing (.et-band),
      steps (.bk-sit) and events (.bk-ev): the two block ghosts colour their caps from this token,
      and a room left off the list gets navy caps on navy (measured on the events CALL). */
:where(.sl-body).refine-clinical-ledger .et.bk-home > * { --bk-accent-text: var(--cl-label); }
:where(.sl-body).refine-clinical-ledger .et.bk-home :is(.et-hero, :where(.sl-body) .et-band, :where(.sl-body) .bk-sit, :where(.sl-body) .bk-ev) {
  --cl-hair: rgba(255,255,255,0.22); --cl-hair-strong: rgba(255,255,255,0.42); --cl-label: rgba(255,255,255,0.72);
  --bk-accent-text: rgba(255,255,255,0.72);
}

/* ── 36. A BAND THAT TAKES A PHOTOGRAPH TAKES THE ROOM'S INK WITH IT. The coverage band was given a
      picture in the record (theme_json.estate.band_photos.locations) and kept the inks it uses on a
      flat ground, so the county notes measured 1.15:1 over the bright part of the photograph on a
      phone and photo-text refused the deploy — correctly. Any band whose STYLE carries a background
      image is a room for ink purposes, whichever band it is, so the remap follows the picture rather
      than a hand-written list of band names that the next record change would fall out of. */
:where(.sl-body).refine-clinical-ledger .et.bk-home [style*="background-image"] {
  --cl-hair: rgba(255,255,255,0.22);
  --cl-hair-strong: rgba(255,255,255,0.42);
  --cl-label: rgba(255,255,255,0.72);
  --bk-accent-text: rgba(255,255,255,0.72);
}
:where(.sl-body).refine-clinical-ledger .et.bk-home [style*="background-image"] :is(.et-locnote, :where(.sl-body) .et-loc-sub, :where(.sl-body) .et-locrow) { color: rgba(255,255,255,0.86); }
:where(.sl-body).refine-clinical-ledger .et.bk-home [style*="background-image"] :is(.et-title-ink, :where(.sl-body) .et-body-ink) { color: #fff; }
/* The questions are a dense list, so when the band takes a picture every one of them needs the
   room ink too — the first FAQ photograph put "Is IV therapy safe?" at 1.80:1 over 71% of its line. */
:where(.sl-body).refine-clinical-ledger .et.bk-home [style*="background-image"] :is(.et-qtext, :where(.sl-body) .et-qa) { color: #fff; }
:where(.sl-body).refine-clinical-ledger .et.bk-home [style*="background-image"] .et-qchev svg { stroke: #fff; opacity: .8; }

/* A NARROW SCREEN PUTS THE WORDS ON THE BRIGHTEST PART OF THE PICTURE. On desktop the copy sits in a
   column over a chosen part of the frame; on a phone the same picture is cropped to a strip and the
   text lands wherever the crop leaves it — which is how "Is IV therapy safe?" measured 1.80:1 over
   71% of its line. One extra scrim on a photographed band, under the content and over the picture,
   deepens the ground without touching the veil the record chose. The hero keeps its own pair: it is
   tuned for one line of 60px type and a second scrim would flatten it. */
:where(.sl-body).refine-clinical-ledger .et.bk-home [style*="background-image"]:not(.et-hero) { position: relative; isolation: isolate; }
:where(.sl-body).refine-clinical-ledger .et.bk-home [style*="background-image"]:not(.et-hero)::before {
  content: ''; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: rgba(10, 31, 51, 0.28);
}
@media (max-width: 860px) {
  :where(.sl-body).refine-clinical-ledger .et.bk-home [style*="background-image"]:not(.et-hero)::before { background: rgba(10, 31, 51, 0.52); }
}
/* the two block-drawn ghosts (steps, events) ring themselves in the accent; over a photograph that is a coral ring, so they take the white ring the family's own ghost takes over a picture (R2d) */
:where(.sl-body).refine-clinical-ledger .et.bk-home :is(.bk-sit-ghost, :where(.sl-body) .bk-ev-ghost) { color: #fff; box-shadow: inset 0 0 0 1.4px rgba(255,255,255,0.75); }

/* ── 28. KILL THE BROWN MIX. The template mixes its eyebrows on paper and the menu's price and
      "What's Included" toward the ink (coral 58% / ink 42%, brown). The label takes the quiet
      ink; the FIGURES take the second accent's ink — the brief's metallic price tag, chosen by
      reach against the root's own paper so it reads on either ground, falling back to the root's
      ink for a brand that carries no second accent — set tabular so a row of cards lines its
      prices up. The :is() lists carry the legacy card classes beside the block's so lane-dead is
      satisfied whichever the fixture renders. */
:where(.sl-body).refine-clinical-ledger .et.bk-home :is(.et-expert .et-eyebrow, :where(.sl-body) .et-locations .et-eyebrow, :where(.sl-body) .et-faq .et-eyebrow) { color: var(--cl-label); }
/* THE PRICE FIGURE TAKES THE METAL THAT ADJUSTS TO THE PAGE. This read the record's own
   accent2 ink, which was picked against a dark page: on a pale ground it measured 1.27:1 and
   the prices were invisible. --cl-metal-ink is the same warm neutral mixed toward the page's
   own text colour, so it stays pale on a dark page and deepens on a light one. */
:where(.sl-body).refine-clinical-ledger .et.bk-home :is(.bk-pamt, :where(.sl-body) .et-amt) { color: var(--cl-metal-ink, var(--et-accent2-ink, var(--bk-ink))); font-variant-numeric: tabular-nums; }
:where(.sl-body).refine-clinical-ledger .et.bk-home :is(.bk-pinc, :where(.sl-body) .et-card-inc) { color: var(--cl-label); }

/* ── 29. ONE CONTROL VOICE, TOKENS ONLY. On the light bands the fill is the CONTROL PLATE, which on
      every light page resolves through the room to the primary — byte for byte what this rule has
      always painted — and on a deep page is the page's light stock with the brand's caps. The room
      was the fallback here and it was still wrong on a deep page for the reason the plate note at
      the head of this file gives: the room is a BAND, and a control lands on bands the room does not
      step off. Measured on the dark cell before this line changed: this very selector painted the
      menu's BOOK NOW at 1.00:1 on its own card and the expert band's BOOK ONLINE at 1.50:1 on the
      tint. `--bk-cta-bg` still wins where a record authors one. In the bar the fill is
      paper on the deep, so the first fold carries exactly one coral object — the hero's own. The
      dark rooms (hero, steps, closing) keep the family's coral fill with deep caps: no rule. The
      menu block's own root is `.bk-plinths` (the template's `.et-packages` is legacy and wraps
      nothing), so it is named beside it. Ghosts over photographs go white in the FAMILY (R2d).
      `--c-control-ring: transparent` opts these out of the dark rescue outline: they have a plate
      now, and a ring on a filled pill is what made it read as an outline button. */
:where(.sl-body).refine-clinical-ledger .et.bk-home :is(.et-expert, :where(.sl-body) .et-packages, :where(.sl-body) .bk-plinths, :where(.sl-body) .et-locations, :where(.sl-body) .et-faq, :where(.sl-body) .bk-contact) :is(.et-btn-fill, :where(.sl-body) .et-btn-book, :where(.sl-body) .bk-btn-fill, :where(.sl-body) .bk-pbook) { background: var(--bk-cta-bg, var(--c-control)); color: var(--bk-cta-ink, var(--c-on-control)); --c-control-ring: transparent; }
:where(.sl-body).refine-clinical-ledger .et.bk-home .et-nav .et-btn-fill { background: var(--c-light-stock); color: var(--c-primary); }

/* ── 30. THE TOWNS ARE ONE RULED LINE (§13's device on the estate root). The family draws each
      town as a navy bar with a pin and a badge; the ledger draws them as tracked caps in one ruled
      row, divided by hairlines, the county in the note. The name span carries its own 16-18px in
      the template and would defeat the row's size, so it inherits. */
:where(.sl-body).refine-clinical-ledger .et.bk-home .et-locrows { display: flex; flex-wrap: wrap; justify-content: var(--bk-justify, center); border-top: 1px solid var(--cl-hair); border-bottom: 1px solid var(--cl-hair); padding: 4px 0; }
:where(.sl-body).refine-clinical-ledger .et.bk-home .et-locrow { background: none; color: var(--bk-ink); margin: 0; padding: 13px 15px; font-weight: 500; font-size: 11.5px; letter-spacing: 0.16em; text-transform: uppercase; }
:where(.sl-body).refine-clinical-ledger .et.bk-home .et-locname { font-size: inherit; }
:where(.sl-body).refine-clinical-ledger .et.bk-home .et-locrow { border-left: 1px solid var(--cl-hair); border-right: 1px solid var(--cl-hair); margin-left: -1px; } /* every cell rules both sides and overlaps its neighbour's, so a wrapped line is a closed row with no stray rule at its start */
:where(.sl-body).refine-clinical-ledger .et.bk-home :is(.et-pin, :where(.sl-body) .et-locbadge) { display: none; }
:where(.sl-body).refine-clinical-ledger .et.bk-home :is(.et-locnote, :where(.sl-body) .et-loc-sub) { color: var(--bk-muted); }

/* ── 30b. THE COVERAGE MAP'S INK ON A DARK BAND. The map is drawn by the shared region emitter
      and its .rm-* rules in global.css assume white paper — the served fill mixes the accent
      toward --c-surface and the county names print in --c-primary, which on this page is a navy
      landmass in navy type on a navy photograph. The band names every colour it uses as a
      --limap-* token (EstateHome, beside the map's layout); this sets them for the ledger's
      ground, and touches nothing else about the map.
      MEASURED, not chosen by eye: the band is a photograph under a navy veil that ranges
      rgb(20,41,57) to rgb(36,59,78) where the map sits, so every value below is stated against
      the LIGHTER end of that. Served land 2.3:1 off the brightest ground, county names 5.0:1 on
      the land they sit in, legend 5.5:1 on the band — the map's ink measures like any other ink
      on this page, and the numbers are re-measured in the browser rather than asserted here. */
:where(.sl-body).refine-clinical-ledger .et.bk-home .et-locations .et-locmap {
  --limap-served-d: color-mix(in srgb, var(--c-primary) 70%, var(--c-light-stock, #F2F6FA));
  --limap-rest-d: color-mix(in srgb, var(--c-primary) 88%, var(--c-light-stock, #F2F6FA));
  --limap-edge-d: rgba(255,255,255,0.44);
  --limap-ink-d: #FFFFFF;
  --limap-pin-d: var(--c-accent);
  /* THE RING IS WHAT MAKES A TOWN DOT READ, NOT THE CORAL. Measured: the accent on the served
     land is 1.78:1 — a dot that colour is a smudge on it. Ringed in the paper the ring carries
     5.0:1 against the same land, which is how a map pin has always worked; the coral stays the
     brand's, and it is the ring you actually see. */
  --limap-ring-d: rgba(255,255,255,0.92);
  --limap-legend-d: rgba(255,255,255,0.86);
}

/* ── 30c. A LIFTED PLATE NEEDS ITS OWN MUTED INK ───────────────────────────────────────────────
      The contact band's hours card is not the page ground. The page is #0A1F33 and the card is
      #485867 — a plate lifted a long way off it — but every quiet ink inside the card was still
      the ink the PAGE derived: --bk-muted #939da4, which measures a healthy 6.05:1 on the page
      ground and 2.65:1 on this plate. Three runs of real information were sitting under it —
      "Monday to Sunday 8:00 AM to 8:00 PM", "Open in maps", and the arrow — plus the card's own
      "Working Hours" label at 3.63:1 and the place name in the map footer at 4.05:1. The opening
      hours are the single most practically useful line in that band and they were the least
      readable thing on the page.
      No gate catches it and that is not an oversight in the gate: photo-text judges words over a
      PHOTOGRAPH, and this is words over a flat colour, so there is nothing photographic to
      measure. It shipped, unseen, in every build of this page.
      The repair is to ask the plate rather than the page. --c-text-muted and --c-text are already
      derived FROM --c-surface, which is this card's own background, so pointing the card's tokens
      at them needs no new colour and no hand-tuned hex. Measured in Chrome against the plate
      after: hours and map footer 4.51:1, label and place name 4.84:1 — AA at every size, with the
      muted ink still visibly quieter than the full ink it sits beside.
      Set as custom properties on the card, so everything inside it — including .bk-mapfoot, which
      is a descendant — inherits one decision instead of each rule being patched. Scoped to this
      lane's estate home: a light-page brand never sees it and renders byte-identical. */
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-ccard {
  --bk-muted: var(--c-text-muted);
  --bk-accent-quiet: var(--c-text);
  --cl-label: var(--c-text);
}

/* ── 31. QUESTIONS ARE RULED ROWS (§14's device on the estate root): no tint box, no badge, the
      question in the serif, the chevron in ink. The answer is a bare <p>; its UA margin is taken
      off so the row's own padding sets the rhythm. */
:where(.sl-body).refine-clinical-ledger .et.bk-home :is(.et-qd, :where(.sl-body) .et-qrow-flat) { background: none; margin-bottom: 0; border-bottom: 1px solid var(--cl-hair); }
:where(.sl-body).refine-clinical-ledger .et.bk-home .et-qrow { padding: 22px 0; }
:where(.sl-body).refine-clinical-ledger .et.bk-home .et-qbadge { display: none; }
:where(.sl-body).refine-clinical-ledger .et.bk-home .et-qtext { font-family: var(--font-heading); font-weight: 400; font-size: 22px; line-height: 1.3; color: var(--bk-title-ink); }
:where(.sl-body).refine-clinical-ledger .et.bk-home .et-qchev svg { stroke: var(--bk-title-ink); opacity: .6; }
:where(.sl-body).refine-clinical-ledger .et.bk-home .et-qa { max-width: 62ch; color: var(--bk-ink); margin: 0; padding: 0 0 22px; }

/* ── 32. HAIRLINE FRAMES, NOT CORAL RINGS; GLYPHS AS MARKS. The step block has three layouts: the
      cards take the full hairline frame, the ladder and the rail keep their ruled rows and only
      take the white for the rule (a frame around a ruled row would box the ledger's own device).
      The block's ink is already white, so no plate is repainted without its ink. The credential
      glyphs are sized as marks, not blobs — the strip already fills them with the accent. */
:where(.sl-body).refine-clinical-ledger .et.bk-home .et-expert-ph { border: 1px solid var(--cl-hair); padding: 0; border-radius: var(--cl-media-radius, 14px); overflow: hidden; }
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-sit-card { background: transparent; border-color: rgba(255,255,255,0.22); border-radius: var(--card-radius); }
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-sit:not(.bk-composed) .bk-sit-card { border: 1px solid rgba(255,255,255,0.22); }
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-sit-card h3 { font-family: var(--font-heading); font-weight: 400; font-size: 24px; }
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-sit-no { font: 500 11.5px/1 var(--font-body); letter-spacing: 0.24em; text-transform: uppercase; color: var(--cl-label); margin-bottom: 12px; }
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-sit .bk-sit-card:last-child { border-bottom-color: rgba(255,255,255,0.22); }
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-pcard { border: 1px solid var(--cl-hair); border-radius: var(--card-radius); box-shadow: none; }
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-pname { font: 400 22px/1.15 var(--font-heading); text-transform: none; letter-spacing: -0.01em; }
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-plinth { border-radius: var(--card-radius) var(--card-radius) 0 0; } /* top two only: the slab meets the copy at its foot */
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-plearn { background: transparent; box-shadow: inset 0 0 0 1px var(--cl-hair); color: var(--bk-ink); } /* the block's cream chip was 1.23:1 on the white card; a hairline chip in the card's own ink */
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-plinth img { filter: none; } /* the brief asks for no shadows and the block drops one under every bag */
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-cs-item svg { width: 28px; height: 28px; }
:where(.sl-body).refine-clinical-ledger .et.bk-home .et-checks li::before { color: var(--c-accent); }
:where(.sl-body).refine-clinical-ledger .et.bk-home :is(.et-body-ink, :where(.sl-body) .et-checks li) { font-size: 17px; }

/* ── 33. CHROME. A hairline under the bar; the links at the ledger's size; the footer's column
      heads quiet (the family draws them in accent2 = coral). */
:where(.sl-body).refine-clinical-ledger .et.bk-home .et-nav { border-bottom: 1px solid rgba(255,255,255,0.12); }
:where(.sl-body).refine-clinical-ledger .et.bk-home .et-navlinks a { font-size: 14.5px; letter-spacing: 0.02em; }
:where(.sl-body).refine-clinical-ledger .et.bk-home .et-footer h4 { color: rgba(255,255,255,0.62); }

/* ── 34. THE PRICED CARD IS A LEDGER ROW. The brief asks for the package name at the left and the
      price hard right, with the duration under the price — the shape a practice's price list has
      and a wellness card does not. The block stacks its card body in a column and prints the word
      "PRICE:" ahead of the figure, which is a label doing a column's job. Here the body becomes a
      two-track grid: the name keeps the first track, the price moves into the second on the name's
      own baseline, its label is hidden (the block wraps it in `.bk-plabel` for exactly this) and
      the duration sits under the price in the quiet ink. Everything else spans both tracks, so the
      "What's Included" label, the ingredients, the note and the buttons keep the full measure.
      Figures are tabular, so a row of three cards lines its prices up.
      AND A CARD THAT CARRIES A LEDGER ROW RANGES WITH IT. The block asks for the page's alignment
      (`text-align: var(--bk-align)`) so a card on a centred page does not sit left-ranged alone,
      and that is right for a card whose copy is a column. It is not right for THIS card, because
      the two-track row above turns its first line into a ruled entry: the price is pinned hard
      right while the name floated in the middle of the track beside it, so card 3 read
      "THE PEARL™          $285" with a wide unresolved gap in the middle while the longer
      "THE HARBOR RESET™" happened to look composed — the gap was a function of the name's length,
      which is the definition of an accident. A ledger row's two ends are the ROW's two ends.
      Ranging only the NAME left was tried first and is worse, not better: it puts a left title over
      centred copy inside one 360px card, which is the "three alignments in one card" defect
      grid-lint's G4 exists to refuse, and it refused it (2 card groups, "bk-pcard left/center").
      So the whole card body ranges, its actions with it, and the card reads as one object: name
      left, price right, everything under them on the same left edge. The band's own heading keeps
      the page's centring — a centred band title over ranged cards is the ordinary arrangement, and
      G1/G2 judge bands, not what is inside a card. */
/* …AND THE LEDGER ROW WAS NEVER AS WIDE AS THE CARD, so its two ends were not the card's two ends.
   The house centring rule near the top of this file hands `margin-inline: auto` to anything inside
   a non-composed band whose class ENDS in `-body` — written for a band's own content column, and
   `bk-pcard-body` ends in `-body` too. An auto margin makes the grid shrink to its contents, so
   every plinth card's body sat centred at its own text width: measured in Chrome, 255px inside a
   407px card at 864 and 255px inside 425px at 1440. The price then stopped 76px short of the card
   edge on both sides, which is the exact opposite of the device this lane is named for, and it put
   dead space down both flanks of every card on the page. The rule two lines below already had to
   buy the ingredient copy out of the same centring — the body itself was caught and nobody looked.
   Stated at the same weight as the house rule (six classes, two elements) and far later in this
   file, so it wins on order alone — no !important and no repeated class. Scoped to this lane's
   plinth cards, so no other lane, block or client moves.
   Verified in a browser, not assumed: the body goes 255 -> 822 inside the full-width card at 864
   and 255 -> 423 inside a 425px card at 1440, which puts the price back on the card's right edge. */
:where(.sl-body).refine-clinical-ledger .et.bk-home section.bk-plinths .bk-pcard .bk-pcard-body { margin-inline: 0; }
/* CENTRED, ON THE OWNER'S INSTRUCTION, 2026-09-10. This was a two-column grid — the name in the
   first track, the price pinned right in the second — written to satisfy the brief's "price and
   duration right aligned". The owner has since looked at it and asked for the card centred, and
   a centred card cannot have one element ranging to its edge: that is what made the first two
   attempts read as broken. ONE track, everything stacked down the middle in source order. */
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-pcard-body { display: grid; grid-template-columns: minmax(0, 1fr); row-gap: 8px; justify-items: center; align-items: start; text-align: center; }
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-pcard-body > * { grid-column: 1 / -1; }
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-pcard-body .bk-ping { margin-inline: auto; text-align: center; }
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-pcard-body .bk-pctas { justify-content: center; }
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-pcard-body .bk-pname { grid-column: 1; text-align: center; }
/* the price is no longer a column beside the name; it is the line under it */
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-pcard-body .bk-pfig { grid-column: 1; grid-row: auto; text-align: center; margin: 0; width: 100%; }
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-pcard-body .bk-pprice { margin: 0; font-variant-numeric: tabular-nums; }
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-pcard-body .bk-pprice .bk-plabel { display: none; }
/* the stand-off under the figure belongs to the DURATION, not to the pair: a card with no duration
   printed only a price and had none, and moving it up to the wrapper added 16px to every card in
   the fleet that carries no duration (measured: the home page grew 5px). */
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-pcard-body .bk-pdur { margin: 0 0 16px; font-variant-numeric: tabular-nums; color: var(--cl-label); }

/* ══════════════════════════════════════════════════════════════════════════════════════════════
   THE LIT BAND GROUND  —  .bk-lit  +  .bk-lit-l / .bk-lit-r
   ══════════════════════════════════════════════════════════════════════════════════════════════

   WHAT IS WRONG WITH A FLAT BAND, IN NUMBERS
   Measured off the rendered folds of the estate home page this was written for: two colours cover
   96% of every painted pixel; three of nine screens have ONE exact RGB value covering more than
   80% of the screen (the menu band is at 89.2%); the whole page lives inside 86 of 255 levels of
   light while every luxury reference in the comparison set spans 212 to 255. A band of one flat
   colour reads as painted ink. It is the single most measurable reason the page reads as basic.

   WHAT THIS IS
   The recipe from `.bk-nopic-ink` above (grain, a pool of the brand's primary entering from one
   upper corner, a much fainter pool of the accent from the other, a ramp settling to the brand's
   darkest colour about three quarters down where the buttons sit) promoted out of the
   no-photograph HERO FALLBACK — where it has never painted a pixel on any site, because
   heroGround.ts hands back nothing the instant a hero has a photograph and every hero has one —
   and into a NAMED BAND GROUND that any home band can wear. Mirrored, so the light has a direction
   and two neighbours are never lit from the same corner. Who wears it is decided once, in
   src/lib/bandLight.ts; nothing here decides anything.

   THE TRAP, AND IT IS THE SAME ONE THE BLOCK ABOVE DOCUMENTS
   THE GROUND COLOUR STAYS ON THE ELEMENT. ONLY THE LIGHT IS ON THE LAYER ABOVE IT. This rule
   therefore never writes `background-color`, not even a fallback: the bands it lights already paint
   their own, and they are not all the same colour — the estate home stands on TWO navies and
   flattening them into one would undo the alternation this is meant to deepen. Anything that asks
   the page "what colour is behind these words" — including this repo's own contrast gate, which
   explicitly bails when it meets a background-image and reads the element's colour instead — must
   still find a real, opaque colour on the element. It reported white-on-white once, on the headline
   of the thinnest client, for exactly this reason, and it was right to. bandLight.ts refuses to
   light a band that does not paint its own ground; this rule cannot supply one for it.

   WHY z-index:-1 AND isolation:isolate, AND NOT `> * { position: relative }`
   `.bk-nopic` lifts every direct child to `z-index: 1` because its own layer paints at z-index 0,
   and a positioned z-index:0 pseudo-element paints ABOVE inline content in the CSS painting order.
   That is correct for a hero, whose children are a headline and two buttons. On a band it would
   mean touching the position of every direct child of six different blocks, and `position:
   relative` on an element that was static changes what absolutely-positioned descendants are
   measured against. A NEGATIVE z-index paints between the element's own background and everything
   in front of it, which is precisely the layer wanted, and touches no child at all. It needs the
   band to be a stacking context or the layer escapes behind the page ground, and `isolation:
   isolate` makes one without moving anything and without the side effects of a z-index or a
   transform.

   THE BRIEF GOVERNS: THIS IS A BAND GROUND AND IT IS NEVER A CARD.
   "No gradients, no drop shadows" means on a card, a button, a plate or a price row. Ambient light
   across a band's own ground is not a gradient on a card. The two are kept from blurring into each
   other by the SELECTOR — the layer is a pseudo-element of the band and can reach nothing inside it
   — and by bandLight.ts, which refuses to light a band whose content is a row of framed cards,
   because a card with a transparent interior sitting on a lit field shows that field through
   itself, and that is the same picture whatever the stylesheet technically painted.

   A LIGHT PAGE DOES NOT MOVE. Every rule below is under `body.ground-dark`, which src/lib/brand.ts
   stamps from the record's own page-ground decision. bandLight.ts gates on the same fact. Either
   gate alone would do it; both are here so that a template which mis-wires this puts an inert class
   on a paper page rather than a navy stain.

   TUNING, AND WHERE THE DEFAULTS COME FROM. Every amplitude is a token, so a brand or a single
   band may soften or deepen its own room without a second rule and without a lane. The defaults
   were not chosen by eye. They are the strongest light that still leaves every ink on the page
   clear of AA when measured against the field UNDER ITS OWN GLYPHS — not against the band's
   declared colour, which is the floor and therefore the flattering end, and not against the field's
   average. Swept on this palette (#0A1F33 page, #2C3E4F room, #093C60 primary, #EE7E6A accent), 48
   ink runs judged per pass:

       hero amplitudes, grain in the light stack   1 run under AA   worst 4.05 : 1
       grain on its own layer at 0.55, same pools  1 run under AA   worst 4.34 : 1
       pools pulled off the top edge, grain 0.35   0 runs under AA  worst 4.71 : 1   <- shipped
       everything turned down as far as it goes    0 runs under AA  worst 4.75 : 1

   The binding ink is a 12px eyebrow that already measured only 5.12:1 flat, so the whole budget for
   this device on this brand is about half a contrast point. That is worth knowing before anyone
   turns any of these numbers up: the light is not free, and it is spent first on the smallest
   label on the page.
   ══════════════════════════════════════════════════════════════════════════════════════════════ */

:where(.sl-body) {
  /* THE GRAIN, AS ITS OWN TOKEN. The film grain has been a single `--grain` URL since the material
     pass, with its 180px tile size written as a literal inside two different `background-size`
     shorthands. A texture that is one decision in two places is one rename away from being two
     textures, so the size travels with the image now and a brand can tune either without editing a
     shorthand. Both default to exactly what was already painted, so nothing that uses `--grain`
     directly moves. */
  --bk-grain: var(--grain);
  --bk-grain-size: 180px;
}

:where(.sl-body).ground-dark .bk-lit { position: relative; isolation: isolate; }

:where(.sl-body).ground-dark .bk-lit::before {
  content: ''; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  border-radius: inherit;
  background-image:
    radial-gradient(var(--bk-lit-warm-r, 58% 74%) at var(--bk-lit-warm-x, 88%) var(--bk-lit-warm-y, -24%),
      color-mix(in srgb, var(--bk-lit-warm, var(--bk-accent, #c9a24d)) var(--bk-lit-warm-a, 30%), transparent),
      transparent 64%),
    radial-gradient(var(--bk-lit-cool-r, 82% 88%) at var(--bk-lit-cool-x, 2%) var(--bk-lit-cool-y, -32%),
      color-mix(in srgb, var(--bk-lit-cool, var(--bk-primary, #1f3a4d)) var(--bk-lit-cool-a, 52%), transparent),
      transparent 66%),
    linear-gradient(180deg,
      color-mix(in srgb, var(--bk-lit-cool, var(--bk-primary, #1f3a4d)) var(--bk-lit-lift, 10%), transparent) 0%,
      transparent 46%,
      color-mix(in srgb, var(--bk-lit-floor, var(--bk-dark, #10263b)) var(--bk-lit-settle, 56%), transparent) 78%,
      color-mix(in srgb, var(--bk-lit-floor, var(--bk-dark, #10263b)) var(--bk-lit-settle, 56%), transparent) 100%);
  background-size: cover, cover, cover;
  background-repeat: no-repeat, no-repeat, no-repeat;
  background-position: center, center, center;
}

/* THE GRAIN RIDES ITS OWN LAYER, AND THAT IS NOT TIDINESS — IT IS THE CONTRAST BUDGET.
   Measured on this page: with the grain inside the light stack at the strength the HERO uses, the
   12px eyebrow on the physician band fell from 5.12:1 to 4.20:1 against the field under its own
   glyphs — under AA — while every other ink on the page stayed clear. The cause is not the pools:
   turning the grain off at the SAME pool amplitudes put it back to 4.75:1. A single 13%-white
   noise speckle landing under a 1px stem is what does it.
   A hero carries 60-80px type and can wear the full grain; a band carries 12px labels and cannot.
   A background-image layer has no opacity of its own, so the grain moves to its own pseudo-element
   with one — the same arrangement `.bk-nopic-paper::after` already uses — and its strength becomes
   a token a brand or a band can turn down. Both pseudo-elements sit at z-index -1, so they paint in
   DOM order (light, then grain) between the band's own background and everything in front of it. */
:where(.sl-body).ground-dark .bk-lit::after {
  content: ''; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  border-radius: inherit; opacity: var(--bk-lit-grain-a, 0.35);
  background-image: var(--bk-grain);
  background-size: var(--bk-grain-size) var(--bk-grain-size);
}

/* The light layer's three bands, top to bottom: the ACCENT pool, "much fainter" — and on a navy it
   is nevertheless the one that actually adds light, because the accent is the only warm colour in
   the palette; the PRIMARY pool, the big one, whose corner names the direction; and the directional
   ramp, lifted at the top and settling to the brand's darkest colour by 78%, which is where the
   buttons sit. A button filled with the brand's primary disappears on a ground that ENDED on that
   same colour, so the ground gets out of its way before it gets there. */

/* THE TWO DIRECTIONS, AND THE ONLY THING THAT DIFFERS BETWEEN THEM. The direction is named for the
   corner the brand's PRIMARY enters from; the accent takes the other one. Mirrored by position
   rather than by `transform: scaleX(-1)`, which would also flip the grain tile and would put a
   transform on a layer that a later depth device has to reason about. */
:where(.sl-body).ground-dark .bk-lit-l { --bk-lit-cool-x: 2%;  --bk-lit-warm-x: 88%; }
:where(.sl-body).ground-dark .bk-lit-r { --bk-lit-cool-x: 98%; --bk-lit-warm-x: 12%; }

/* ═══════════════════════════════════════════════════════════════════════════════════════════════
   THE COLUMN LAYER — PARKED. NOTHING HERE PAINTS.
   ═══════════════════════════════════════════════════════════════════════════════════════════════

   FOR ONE DAY THIS BLOCK DREW TEN COLUMN WORDS — full, wide, column, inset, index, rail,
   figure-left, figure-right, bleed-photo, bleed-ruled — so that a band could say how wide it was
   and which edge it hung on, with an assigner that made sure NEIGHBOURS NEVER MATCHED.

   THAT LAST RULE IS WHY IT CAME OUT. A rule that forces every neighbour to differ does not produce
   variety, it produces a page with no line down it. Seen whole rather than one fold at a time: one
   photograph bled off the right at full height, the next bled off the left at a different height
   and stopped early, and a full-screen band carried only the wordmark. Two exceptions that do not
   rhyme read as two mistakes. The owner's words: "it feels like each section has its own mind …
   this is way too far."

   SO EVERY BAND IS BACK ON THE ONE COLUMN --bk-col GIVES IT, which is what the page did before and
   is the whole of `one page, one edge`. No template stamps `data-sl-column` any more.

   WHAT IS DELIBERATELY LEFT STANDING, AND WHY:
     · `--bk-columns` and the `--bk-col-*` tracks at the top of this file — an inert declaration
       that paints nothing on its own. It is the vocabulary, not the painting.
     · src/lib/bandComposition.ts, unused, with a header saying so.
     · scripts/grid-lint.mjs's widened G1, behind an allow-list that is EMPTY.
   The owner said the guard rails "may have been too much and maybe can be loosened a bit". When
   that day comes, the way back in is: put ONE word on ONE band here, add that brand to grid-lint's
   allow-list, and look at the whole page — not the fold — before adding a second.

   DO NOT re-add the words one at a time without the whole-page look. That is exactly how a page
   ends up with three exceptions that rhyme with nothing. */

/* ═══════════════════════════════════════════════════════════════════════════════════════════════
   THE RIGHT-HAND FIGURE — the parked layer's ONE word, taken back out and used TWICE
   ═══════════════════════════════════════════════════════════════════════════════════════════════

   THE SWITCH IS ONE NAME: `sl-figure-right`. Everything in this block is inside a selector that
   asks for it, so removing the name from the page returns it to the parked state above with no
   other edit. EstateHome.astro writes it onto the page root and explains why it is not on <body>;
   the selectors accept either, so promoting it into brand.ts's body-class list later changes
   nothing here.

   WHAT IT DRAWS. A photograph that runs off the RIGHT edge of the screen at a FIXED height, with
   the copy beside it still starting on --bk-pad — the same vertical line every other band on the
   page starts on. Two bands wear it: the physician band and the conditions band. Nothing else on
   the page may, and nothing else does: the two `data-sl-figure="right"` attributes are stamped in
   EstateHome.astro and the template guards them so that if either band has no picture, NEITHER
   band wears the motif.

   WHY THIS IS NOT THE PARKED LAYER COMING BACK. The parked layer's failure was not that bands left
   the column — it was a RULE THAT FORCED NEIGHBOURS TO DIFFER, which gave every band its own width
   and its own edge and left the page with no line down it. Read whole, the page had one photograph
   off the right at full band height, another off the LEFT at a different height, and a full-screen
   wordmark band, and none of the three rhymed. This block is the opposite discipline and each of
   the four clauses is load-bearing:

     ONE SIDE.       Both pictures leave the column on the right. A page can carry a bias; it
                     cannot carry two contradictory ones.
     ONE HEIGHT.     --sl-figR-h, spent by both. It is a fixed height on the picture and NOT
                     `stretch`, which is the only way the two are guaranteed equal: stretching
                     would hand each picture the height of its own band's copy, and the two bands
                     do not hold the same amount of copy. That difference is precisely what read
                     as two mistakes the first time.
     ONE WIDTH.      --sl-figR-copy-share, likewise spent by both. There is deliberately NO token
                     for the picture's width: the COPY is given a share of the page column and the
                     picture takes what is left and runs off the edge, which is what keeps it on
                     the page at 2560 as well as at 1440. See the grid rule for the whole account.
                     Both bands read the same share, so both pictures come out the same width and
                     the pair reads as one device rather than as two pictures that happen to touch
                     the same edge.
     ONE TREATMENT.  Square corners, cover-filled, the lane's own `saturate(0.88)` shoot grade, and
                     a hairline on the INNER edge only — the frame the lane draws round every other
                     photograph, opened on the side the picture leaves through. In variant A only
                     the conditions picture carried the grade and only the physician picture
                     carried a frame; the pair now carries both.

   THE COPY COLUMN DOES NOT MOVE, and that is the clause the alignment gate cares about. Each band
   keeps `padding-inline-start: var(--bk-pad)` and hands its copy the first grid track, so the type
   starts exactly where it starts on every band above and below. Only the END padding is spent —
   that is the whole of what the picture is allowed to take. On the physician band the copy actually
   moves ONTO the page line for the first time: in variant A its picture sat in the column on the
   left and its type began at x=764 while every other band began at x=140.

   THE STACKED PAGE IS UNTOUCHED. Everything here is inside `min-width: 901px`, one pixel above the
   `max-width: 900px` at which both bands already stack. Below that width there is no column to
   leave and a picture bleeding off one edge of a phone is just a picture, so the motif does not
   exist there and both bands render exactly what variant A renders.

   IF IT IS EVER USED A THIRD TIME, look at the whole page first — not the fold. Three is where the
   last attempt stopped being a motif. */

@media (min-width: 901px) {
  :where(.sl-body):is(.sl-figure-right, :where(.sl-body) :has(.sl-figure-right)) .et.bk-home {
    /* The three numbers the pair shares. Every one of them is read by BOTH bands or by neither.
       THE PICTURE'S WIDTH IS NOT ONE OF THEM, AND THAT IS THE POINT — see the grid rule below. */
    --sl-figR-copy-share: 0.66;
    --sl-figR-h: clamp(380px, 34vw, 600px);
    --sl-figR-gap: clamp(28px, 3.4vw, 56px);
    /* THE PAGE COLUMN, WRITTEN OUT — and NOT as `100% - var(--bk-pad)`, which is the obvious form
       and is wrong. --bk-pad is itself `max(gutter, (100% - --bk-col)/2 + gutter)`, and a custom
       property is substituted as TEXT, so that inner `100%` re-resolves against whatever box the
       outer expression lands in. Used inside a track size it therefore measures the band's content
       box (the screen minus one pad) instead of the screen, and the answer drifts: measured, the
       picture kept 299px of the column at 1440 but only 107px at 2560, and the arithmetic runs out
       entirely around 3200 — the same slow escape into the margin that G5 exists to catch, arriving
       one step further out than the version G5 already caught.
       So the column is stated from the two tokens that define it and no percentage of a percentage:
       it is --bk-col less its two gutters, or the screen less its two gutters, whichever is smaller
       — which is exactly what --bk-pad resolves to, read the other way round. Constant 1160px above
       1240px wide, so every number below is constant there too. */
    --sl-figR-col: min(calc(100% - var(--bk-gutter)), calc(var(--bk-col) - 2 * var(--bk-gutter)));
    /* The lane frames its photographs; a bleeding picture can only be framed on the edge it does
       not leave through. Falls back to the page's own ink so the motif is legible on a lane that
       declares no hairline of its own, and on either ground. */
    --sl-figR-hair: var(--cl-hair, color-mix(in srgb, var(--bk-ink, #000) 22%, transparent));
  }

  /* THE BAND. Two tracks: the copy on the page's own line, then the picture out to the screen edge.
     The physician band IS the marked element; the conditions band is drawn by a shared block, so
     the mark sits on its wrapper and this reaches one level in. Neither selector can match anything
     else on the page. */
  :where(.sl-body):is(.sl-figure-right, :where(.sl-body) :has(.sl-figure-right)) .et.bk-home
    :is(.et-expert[data-sl-figure="right"], :where(.sl-body) [data-sl-figure="right"] > .bk-cond) {
    display: grid;
    /* THE PICTURE IS MEASURED FROM THE PAGE COLUMN, NOT FROM THE SCREEN — the whole of what the
       alignment gate's G5 rule is about, and the first build of this motif failed it.
       `grid-template-columns: 1fr <a fixed picture width>` looks right on a laptop and comes apart
       on a wide monitor: --bk-pad keeps growing (700px at 2560) while a capped picture does not, so
       the column retreats out from under the picture and it ends up alone in the right-hand margin
       with nothing beside it. Measured at 2560 on the first build: column 700..1860, picture
       1941..2560 — eighty pixels of clear air between the page and its own photograph. Ian has
       already said this once, about a different band: "images are all the way outside of the
       screen view".
       So the COPY is given a share of the page's own column (--sl-figR-col above, and read the note
       there before touching it) and the picture takes what is left and keeps going. The picture
       therefore always begins a third of the column in from the column's right edge — on the page,
       then off the edge, which is the one escape G5 sanctions — and by exactly the same number at
       every width from 901px to as wide as a screen gets: 345px inside the column at 1440, 338px at
       2560, 338px at 3200. It is identical in both bands because both read the same share. */
    grid-template-columns:
      calc(var(--sl-figR-copy-share) * var(--sl-figR-col))
      minmax(0, 1fr);
    column-gap: var(--sl-figR-gap);
    /* THE PICTURE STARTS WHERE THE COPY STARTS. `center` was the first build and it put a hole in
       the physician band: that band's copy is half again as tall as the picture, so a centred
       picture began 86px below the heading and the first thing on that fold was a heading with
       bare ground beside it. `start` is also the only value that makes the conditions pair read as
       one object — the plate and the picture are within a pixel of each other in height, so flush
       tops means flush both ends. One rule, stateable in a sentence, same in both bands. */
    align-items: start;
    /* THE ONE LINE THAT MATTERS: the start padding is the page's, untouched; only the end padding
       is spent. The band's own vertical padding is left exactly as its block wrote it, so the
       overhang plate above the physician band still gets its 112px bought back. */
    padding-inline: var(--bk-pad) 0;
  }

  /* THE COPY. Explicitly placed in track one so the physician band's picture can move to the right
     without touching the document — the picture is first in source order there, and CSS `order`
     would move the picture and not the page, which is the trade this repo has already refused once
     (see Arrange.astro). A grid placement moves neither: the reading order is unchanged, and the
     stacked page below 901px still reads picture-then-copy exactly as variant A does. */
  :where(.sl-body):is(.sl-figure-right, :where(.sl-body) :has(.sl-figure-right)) .et.bk-home
    [data-sl-figure="right"] :is(.et-expert-copy, :where(.sl-body) .bk-cond-panel) {
    grid-column: 1; grid-row: 1;
  }

  /* THE PICTURE. A slab of one fixed height hanging off the right edge — no frame on three sides,
     no padding, no radius, and it is NOT allowed to vote on the band's height (that is what makes
     the two equal). `overflow: hidden` + an absolutely-positioned image is the same construction
     ConditionsPanel already uses for a photograph that brought its own ground, and for the same
     reason: a percentage height inside a centred grid frame is the trap this repo has paid for
     once already. */
  :where(.sl-body):is(.sl-figure-right, :where(.sl-body) :has(.sl-figure-right)) .et.bk-home
    [data-sl-figure="right"] :is(.et-expert-ph, :where(.sl-body) .bk-cond-ph) {
    grid-column: 2; grid-row: 1;
    display: block; position: relative; overflow: hidden;
    height: var(--sl-figR-h);
    width: auto; max-width: none; min-width: 0;
    margin: 0; padding: 0;
    border: 0;
    border-inline-start: 1px solid var(--sl-figR-hair);
    border-radius: 0;
  }
  :where(.sl-body):is(.sl-figure-right, :where(.sl-body) :has(.sl-figure-right)) .et.bk-home
    [data-sl-figure="right"] :is(.et-expert-ph, :where(.sl-body) .bk-cond-ph) img {
    position: absolute; inset: 0;
    width: 100%; height: 100%;
    max-width: none; max-height: none;
    object-fit: cover; object-position: 50% var(--sl-focus-y, 50%);
    border: 0; border-radius: 0;
    /* the lane's shoot grade, spent by both pictures instead of by one of them */
    filter: saturate(0.88);
  }
}

/* ═══════════════════════════════════════════════════════════════════════════════════════════════
   THE OVERHANG PLATE — the page's one second plane
   ═══════════════════════════════════════════════════════════════════════════════════════════════

   A band wearing `data-sl-depth="overhang"` rises out of its own box and sits on the bottom of the
   band above it, which keeps painting underneath. Measured before this existed: the estate home had
   0 overlaps, 0 negative margins, 0 elements with z-index above 0 and exactly 1 absolutely-
   positioned element across 7,265px — a page with no second plane anywhere in it.

   THE PATTERN IS PROVEN IN THIS REPO ALREADY (EstateHome.astro's `.et-etxt { margin-top: -128px }`,
   inside a block this page never reaches). Three things have to hold and each is one line:
     · the band above must not CLIP its own full-bleed ground — so it is told not to;
     · the band below must ABSORB the height, or the negative margin shortens the page and every
       gap below it closes up by --bk-overhang;
     · it must collapse to zero overlap below the stacking width, where there is no room for a
       second plane and a plate over a photograph is just a plate on top of some words.

   ASSIGNED, NOT DECORATED: bandComposition.ts caps this at two per page (C3). Ship ONE, shoot the
   fold, then decide on the second — two at once and you cannot tell which is wrong. */
/* HOW FAR IT RISES, DECLARED ON THE PAGE AND NOT ON THE BAND. Both the plate and the band under it
   have to spend the same number, and a sibling cannot inherit a value declared on its neighbour. */
:where(.sl-body).sl-shelf .bk-home { --bk-overhang: 112px; }
:where(.sl-body).sl-shelf .bk-home [data-sl-depth="overhang"] {
  margin-block-start: calc(-1 * var(--bk-overhang));
  position: relative;
  z-index: 1;
  /* THE SAFETY NET UNDER THE INK, AND WHY THE NET IS NOT THE ANSWER.
     The template that stamps this word also stamps the dark-band rebind (familySkin's
     darkBandVars) as an inline style, measured against the exact colour this plate paints — that is
     the fix, and an inline declaration beats everything below. These two lines are for the band
     that gets the depth word from bandComposition's plan without that stamp: they are still
     DERIVED, not literals — `--c-on-dark` is brand.ts's ink measured on the brand's own deep
     colour, which is what this plate is made of — so the worst case is ink chosen for a
     near-neighbour of the ground rather than ink chosen for the paper on the far side of it.
     Without them a band would go dark and keep the page's paper ink, which is the fault this whole
     block exists because of. The literal at the end of the chain is reached only where the palette
     block is absent altogether (the internal block sheet), the same convention familySkin.ts uses
     for every one of its fallbacks. */
  --bk-ink: var(--c-on-dark, #fff);
  --bk-title-ink: var(--c-on-dark, #fff);
}
/* the band above keeps painting under the plate */
:where(.sl-body).sl-shelf .bk-home > :has(+ [data-sl-depth="overhang"]) { overflow: visible; }
/* …AND IT ALSO KEEPS ITS CONTENT OUT OF THE PLATE'S WAY. Painting underneath is not the same as
   being clear underneath. The plate rises --bk-overhang into the band above, and until the hero
   grew, the last thing in that band happened to sit higher than the plate's top edge, so nobody
   noticed the band was reserving nothing. Measured on the home page the moment the hero went from
   620px to 822px: the plate's top edge landed at 787 and the booking button ran to 825 — the two
   controls that earn the client money, with a dark strip drawn across them.
   A band that a plate hangs into reserves that height at its end, so the plate always lands on the
   band's own air rather than on its words. It is the same number both sides spend, read from the
   same custom property, so the reservation cannot drift from the rise. */
:where(.sl-body).sl-shelf .bk-home > :has(+ [data-sl-depth="overhang"]) {
  padding-block-end: calc(var(--bk-overhang) + 28px);
}
/* …AND THE BAND BELOW BUYS THE HEIGHT BACK. Without it the negative margin merely shortens the page
   and every gap under the plate closes up by --bk-overhang.
   IT USED TO CARRY TWO `:not()` CLAUSES — one per half-bleed figure word — because a figure band
   spends its vertical air on its copy column so the picture can run the band's full height. There
   are no figure bands any more (see the parked column layer above), and the exception was doing
   real harm: the one band this plate actually sits on WAS a figure band, so it bought back nothing
   and the page quietly lost 112px of air under the plate. One rule now, for every band below a
   plate, which is also one less thing to remember when the plate moves to another band. */
:where(.sl-body).sl-shelf .bk-home [data-sl-depth="overhang"] + * {
  --bk-overhang-give: var(--bk-overhang);
  padding-block-start: calc(var(--bk-overhang-give, 0px) + var(--bk-rhythm-tight));
}
/* THE PLATE ITSELF. Near-solid brand dark so the ink is measured against a COLOUR and not against a
   photograph (hero-contrast and photo-text-lint both read what is actually behind the glyphs), a
   hairline along its top edge, and the picture continuing beneath and either side of it. The
   hairline is a BORDER and never a box-shadow: the brief forbids drop shadows, and a ring drawn as
   a shadow is the one four lanes in this repo have already deleted by accident. */
:where(.sl-body).sl-shelf .bk-home [data-sl-depth="overhang"] > * {
  /* THE GROUND IS READ FROM THE SAME DECLARATION THAT CHOSE THE INK. `--bk-band` is what
     darkBandVars publishes the room as, so the colour on this face and the colour the ink was
     measured against are one value and cannot drift; `--bk-dark` is the unchanged fallback, and on
     every build that stamps the rebind the two are identical, so no plate moves. */
  background: color-mix(in srgb, var(--bk-band, var(--bk-dark, #0a1f33)) 94%, transparent);
  /* the hairline follows the ink: darkBandVars derives --bk-hair from whichever endpoint this
     room's ink walks toward, so a pale plate gets a dark edge instead of an invisible white one */
  border-top: 1px solid var(--bk-overhang-hair, var(--bk-hair, rgba(255, 255, 255, 0.22)));
  padding-block: clamp(22px, 2.2vw, 30px);
  /* AND A PLATE HAS THE PAGE'S CORNER. This one is inset from the column by the margin below and
     floats on the photograph above it, so a hard 90-degree corner is the harshest shape on the
     page - the owner picked it out by name, 2026-09-15: round the trust bar in the hero too. It
     reads the same plate corner every card on the page reads; a full-width band elsewhere is
     untouched, because this rule only ever governs the inset plate. */
  border-radius: var(--bk-radius, 0);
  /* THE PLATE'S BOX SITS ON THE BAND'S OWN COLUMN, and its padding is the plate's inside. Those are
     two different measurements and the first build conflated them: the strip inside this band reads
     --bk-pad as its own PADDING, so overriding that padding left the plate full-bleed — an `inset`
     word that moved nothing at all. The margin is the column; the padding is the air inside it. */
  margin-inline: var(--bk-pad);
  padding-inline: clamp(20px, 2.4vw, 40px);
}
@media (max-width: 900px) {
  /* on a phone the column word has already collapsed to the house track, and a plate inset by the
     house padding on a 375px screen is a 335px plate — right, and it needs no second inset */
  :where(.sl-body).sl-shelf .bk-home [data-sl-depth="overhang"] > * { margin-inline: 0; padding-inline: var(--bk-pad); }
}
/* ON A PHONE THERE IS NO SECOND PLANE. Below the stacking width the plate is nearly the width of
   the screen and the photograph it would sit on is a fraction of it, so the overlap stops being
   depth and becomes a plate on top of some words. Both halves go to zero from the ONE token. */
@media (max-width: 900px) {
  :where(.sl-body).sl-shelf .bk-home { --bk-overhang: 0px; }
  :where(.sl-body).sl-shelf .bk-home [data-sl-depth="overhang"] { margin-block-start: 0; }
}

/* THE PAGE SHELL CLIPS SIDEWAYS AND NOWHERE ELSE. Nothing on this page bleeds past the layout edge
   any more, so this is a belt rather than a fix: a band that overshoots by a sub-pixel must not hand
   a phone a horizontal scrollbar. `clip` rather than `hidden` on purpose: with `hidden` the vertical
   axis computes to `auto` and the wrapper becomes a scroll container, which would clip the overhang
   plate away and pin nothing. `clip` leaves the visible axis visible. */
:where(.sl-body).sl-shelf .bk-home { overflow-x: clip; }


/* ── 35. THE SCROLL HAS A RHYTHM. Measured on pureiv.com (2026-09-06): its bands run 458px to
      1317px tall and no two neighbours match, so the page breathes. Ours had one padding value on
      every band — eight of eleven gaps within 155-200px — which is what makes a page read as a
      list of things rather than an argument with emphasis. Three airs, assigned by role, not by
      band name: the two bands that carry a picture beside copy get the wide air, the ruled lists
      get the tight one, everything else keeps the middle. No band moves off the column. */
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-cond { padding-block: var(--cl-air-wide); }
:where(.sl-body).refine-clinical-ledger .et.bk-home :is(.et-locations, :where(.sl-body) .et-faq) { padding-block: var(--cl-air-tight); }


/* ── 36. A CONTACT BAND'S PHOTOGRAPH — the geometry, written down once ────────────────────────
   APPENDED AT THE END OF THE FILE ON PURPOSE. scripts/ground-debt.json records a hundred-odd
   declarations in this stylesheet BY LINE NUMBER, and the check that reads it refuses the build
   when a row's line has moved. Inserting these rules beside the other contact rules, where they
   belong by subject, moved twenty-seven of those rows and turned a green suite red for a reason
   that has nothing to do with colour. Adding at the end shifts nothing.

   THE HEIGHT IS THE WHOLE POINT AND IT LIVES HERE.
   The home page's contact band learned two things at once: a photograph belongs to the BAND, not
   to one of its columns, and 260px of letterbox is a garnish rather than a picture. Both were
   written into ContactCard.astro's own scoped stylesheet, where the interior renderer and the
   listing renderer could not read them — so the home page got a picture a quarter of the band
   tall and the other fourteen pages of a site got nothing at all.
   `--sl-contact-art-h` is that height with ONE home. ContactCard.astro reads this property; so
   does the class below, which the interior contact band and the hub closing band both wear.
   Change the crop here and all three change together, which is the only way three renderers have
   ever stayed in agreement in this codebase. Declared on :root rather than beside the class so a
   brand can override it once for its whole site, and so the home band — whose styles are
   component-scoped — can still see it. */
:where(.sl-body) { --sl-contact-art-h: clamp(240px, 30vw, 440px); }
/* SPANS THE BAND. Inside the interior contact band's two-column grid `1 / -1` puts the picture
   across both columns instead of stranding the second one; in the hub closing band, which is not
   a grid, the property is simply inert and the picture is full width anyway. One class, both
   shapes — the alternative was two classes that drift.

   AND THAT IS EXACTLY WHAT HAD HAPPENED. The home band drew this picture as `.bk-contact-art` from
   ContactCard.astro's own scoped stylesheet and the other three drew it as `.sl-contact-art` from
   here: one band, two names, and the two had already disagreed on the corner (8px against 12px)
   and on the intrinsic size the markup reserves before the file lands (620×260 against 1280×432).
   Two names is how a band gets improved on one route and left alone on the other three, which is
   the whole shape of this round. There is one name now — `sl-contact-art`, the constant
   CONTACT_ART_CLASS in src/lib/contactArt.ts — and one set of rules, these.

   THE CORNER IS ONE DECLARATION READING TWO HOUSES. A shelf/home page sets `--bk-radius` from the
   family skin; an interior or listing page sets `--card-radius` from the theme. Reading the first
   and falling through to the second means every route keeps the corner it already had without a
   second rule being written anywhere. */
:where(.sl-body) .sl-contact-art {
  display: block; grid-column: 1 / -1; width: 100%;
  height: var(--sl-contact-art-h, clamp(240px, 30vw, 440px));
  object-fit: cover; border-radius: var(--bk-radius, var(--card-radius, 12px));
  /* AND THE CROP TAKES THE SUBJECT, NOT THE MIDDLE OF THE FILE. This band is about three times as
     wide as it is tall, so a portrait frame poured into it keeps roughly a quarter of itself — and
     `cover` takes that quarter from the centre. On IV Revival's contact band that centre was sky
     and a power line: the client, the lounger and the drip were all above and below the cut. The
     anchor is the one the rest of the house already uses (lib/photoFocus, `--sl-focus-y`), written
     on the <img> by the renderer, so a frame nobody has measured keeps the centre it has today. */
  object-position: 50% var(--sl-focus-y, 50%);
  margin: 0 0 2rem;
}
/* ── ON A HOME PAGE THE SAME PICTURE IS A COLUMN, NOT A STRIP ────────────────────────────────────
   The owner, 2026-09-12: "the contact card isn't good, I don't like the design but the photo we
   used is just a sky." Both halves were one fault. Drawn across the top at roughly three-to-one, a
   TALL photograph keeps a band through its middle and loses the rest — on that client the middle
   was sky and a power line, and the person, the lounger and the drip were all outside the cut. As a
   column the identical file is whole and the band reads as one composition instead of a strip
   floating over two unrelated halves. No new photograph was needed; the box was the problem.
   Only the home band. The interior and listing bands keep the letterbox above, which suits the
   full-width place they sit in — and both live here, under one name, because the reach-band module
   exists to stop this geometry being restated inside a component's own stylesheet. */
:where(.sl-body) .bk-contact .sl-contact-art {
  grid-column: 1; grid-row: 1 / span 2; align-self: stretch;
  width: 100%; height: 100%; min-height: 440px;
  object-fit: cover; margin-bottom: 0;
}
@media (max-width: 860px) {
  :where(.sl-body) .bk-contact .sl-contact-art { grid-column: 1; grid-row: auto; height: auto; min-height: 0; aspect-ratio: 4 / 3; }
}
/* …except in a grid, where the grid's own gap is already the space below it and a margin would
   count that space twice. Three grids draw this band: the interior contact band (`.contact-2col`),
   the shared home contact band (`.bk-contact`) and the bloom family's own (`.bl-contact-grid`,
   where the picture sits inside a figure, so the margin would be dead space INSIDE the rounded
   box rather than under it). */
:where(.sl-body) .contact-2col .sl-contact-art, :where(.sl-body) .bl-contact .sl-contact-art, :where(.sl-body) .bk-contact .sl-contact-art { margin-bottom: 0; }

/* ── VITAMIN AND MEDICATION NAMES READ LARGER ───────────────────────────────────────────────────
   Client: "increase the font size on all vitamin and medication names — B12, glutathione, and
   every other ingredient or add-on name across the menu and drip descriptions."
   These are the three places a substance is named: the ingredient list on a drip page, the add-on
   shot rows on the pricing menu, and the vitamin-shot tiles on the home page. They were all set at
   or below body size, which is the wrong weighting for the thing a customer is actually shopping
   for. Sized up together so the three read as one register rather than three. */
:where(.sl-body) .ibreak-list li {
  font-size: 1.0625rem;
  line-height: 1.45;
}
:where(.sl-body) main > section.section .hub-menu-name {
  font-size: 1.125rem;
}
:where(.sl-body) main > section.section .hub-menu-price {
  font-size: 1.125rem;
}
/* The vitamin-shot tiles on the home page name the shot under its vial. */
:where(.sl-body) main > section.section.section-vitamin_shots .img-item-card h3 {
  font-size: 1.125rem;
}
@media (max-width: 640px) {
  :where(.sl-body) .ibreak-list li, :where(.sl-body) main > section.section .hub-menu-name, :where(.sl-body) main > section.section .hub-menu-price, :where(.sl-body) main > section.section.section-vitamin_shots .img-item-card h3 { font-size: 1.03rem; }
}

/* ── 37. THE BRIEF'S BASE, ITS ONE METAL, AND ITS TYPE RHYTHM ─────────────────────────────────
   APPENDED AT THE END, for the reason §36 gives: scripts/ground-debt.json records a hundred-odd
   declarations in this sheet BY LINE NUMBER and a check refuses the build when a row's line has
   moved. Nothing above this line is edited; every rule here re-states a selector that already
   exists and wins on order alone.

   THIS LANE HAS EXACTLY ONE CLIENT. Counted rather than assumed, over all 71 brand records:
   `clinical-ledger` is named by one, Stack Hydration. Every rule below is therefore as narrow as
   a rule in this repo can be while still living in a system rather than on a page.

   WHAT THE CLIENT ASKED FOR, in his words: "existing brand hex as the single accent, deep neutral
   base rather than all white, one muted metallic or warm neutral for dividers and price tags. No
   gradients, no drop shadows." Then: "Body at 17 to 18px", and "100 to 120px vertical section
   padding on desktop."

   ── A. THE ONE WARM NEUTRAL, AND THE TWO JOBS THE BRIEF NAMES FOR IT.
   The page's dividers were mixed from the body ink, which derives COOL on this brand
   (#CED0D3, Lab b* -1.7). The brief asks for one muted metallic; this is it, and it is a flat
   value, not a gradient. #E0D8C9 is Lab L* 86.6, C* 8.4, hue 89 - warm by 10.1 units of b*
   against the ink it sits beside, and 6.1x quieter than the coral (C* 51.1), so it can never be
   misread as a second accent. As a DIVIDER it keeps the alphas the lane already used, so the
   weight of every rule on the page is unchanged and only its temperature moves. As a PRICE FIGURE
   it runs at full strength: the binding constraint is the card, the lightest stock on a dark page,
   and it clears this repo's own AA target there rather than merely WCAG's.
   A hairline is a rule and not text, so it carries no contrast floor; the price figure is text and
   is measured in the round's report against all four grounds it can land on. */
:where(.sl-body).refine-clinical-ledger {
  --cl-metal: #E0D8C9;
  --cl-hair: color-mix(in srgb, var(--cl-metal) 18%, transparent);
  --cl-hair-strong: color-mix(in srgb, var(--cl-metal) 36%, transparent);
  /* THE METAL NEEDS A SECOND VALUE, BECAUSE A PRICE IS TEXT AND A HAIRLINE IS NOT.
     #E0D8C9 was chosen against a dark page, where it is the warm figure on a near-black card and
     clears AA comfortably. Move the same brand onto a LIGHT ground and the identical value becomes
     #E0D8C9 on a #F6F2EA panel — measured 1.27:1, which the contrast check calls effectively
     invisible, and it is right: the prices vanished the moment this client's ground went pale.
     A DIVIDER carries no contrast floor, so it keeps the pale metal at the lane's own alphas and
     its weight does not move. A PRICE FIGURE is read, so on a light ground it takes the deeper
     cousin of the same warm neutral — same temperature, enough weight to be a figure. One family,
     two strengths, chosen by which ground the page actually is. */
  --cl-metal-ink: color-mix(in srgb, var(--cl-metal) 58%, var(--c-text, #101010));
  /* The package card paints its price from its OWN scoped style, which outranks anything
     written here, so the metal has to reach it through the token that rule reads rather than
     by naming the element. Same value, same reasoning — it just has to be handed over one
     step earlier. This also catches every other quiet-accent figure in the lane at once. */
  --bk-accent-quiet: var(--cl-metal-ink);
}
/* the estate home re-derives its own hairlines from the root's ink (§24b); it takes the metal too,
   or the page would carry a warm rule on the interior renderer and a cool one on the home */
:where(.sl-body).refine-clinical-ledger .et.bk-home {
  --cl-hair: color-mix(in srgb, var(--cl-metal) 18%, transparent);
  --cl-hair-strong: color-mix(in srgb, var(--cl-metal) 36%, transparent);
}
/* Inside a room, and on any band carrying a photograph, §27 and §36 draw the rule in white at the
   room alphas. Those alphas are kept exactly - only the colour warms, so the line weight over a
   picture does not move. The LABEL ink in those rooms stays white: the brief's warmth is a divider
   and a price tag, not a second text colour. */
:where(.sl-body).refine-clinical-ledger .et.bk-home :is(.et-hero, :where(.sl-body) .et-band, :where(.sl-body) .bk-sit, :where(.sl-body) .bk-ev), :where(.sl-body).refine-clinical-ledger .et.bk-home [style*="background-image"] {
  --cl-hair: color-mix(in srgb, var(--cl-metal) 22%, transparent);
  --cl-hair-strong: color-mix(in srgb, var(--cl-metal) 42%, transparent);
}
/* THE PRICE TAG. §28 sent the figures to the second accent's ink, which on this brand resolves to
   a lightened CORAL (#F6BEB4) - i.e. the accent doing a second job, which is the exact fault this
   round exists to end. The figure is the metal; the duration and the inclusions beside it stay in
   the quiet ink, so a ledger row reads as a cool name against a warm figure. */
:where(.sl-body).refine-clinical-ledger .et.bk-home :is(.bk-pamt, :where(.sl-body) .et-amt) { color: var(--cl-metal); font-variant-numeric: tabular-nums; }
:where(.sl-body).refine-clinical-ledger :is(.bk-prail-price, :where(.sl-body) .bk-ledger-cost, :where(.sl-body) .hub-menu-price, :where(.sl-body) .pkg-price, :where(.sl-body) .tier-price, :where(.sl-body) .price) { color: var(--cl-metal-ink); font-variant-numeric: tabular-nums; }

/* ── B. THE PHOTOGRAPH SCRIM FOLLOWS THE RECORD, INSTEAD OF NAMING THE OLD GROUND.
   §36's extra scrim over a photographed band was written as the literal rgba(10, 31, 51, …) - the
   navy ground, spelled out. With the ground changed in the record those two lines would have gone
   on tinting every picture blue on a graphite page. --c-scrim-rgb is what brand.ts publishes from
   primary_dark, which is the one place this decision is taken; the fallback is the new deep so the
   rule is still legible on its own. */
:where(.sl-body).refine-clinical-ledger .et.bk-home [style*="background-image"]:not(.et-hero)::before {
  background: rgba(var(--c-scrim-rgb, 20,19,17), 0.28);
}
@media (max-width: 860px) {
  :where(.sl-body).refine-clinical-ledger .et.bk-home [style*="background-image"]:not(.et-hero)::before { background: rgba(var(--c-scrim-rgb, 20,19,17), 0.52); }
}

/* ── C. RUNNING TEXT AT 17px, WHICH IS THE BOTTOM OF THE BRIEF'S RANGE.
   THERE IS NO HOUSE BODY SIZE TO RAISE. `body` in this sheet declares font-family, colour, ground
   and leading and NO font-size, so every site in the fleet runs its copy at the browser's own
   16px, and each block that wanted something else wrote its own px value. Raising the house
   default would move all 71 brands at once on the strength of one client's brief, so the size is
   set here, on the lane, where it reaches this client and nobody else. Whether 17px should become
   the house floor is the owner's call, not this round's.
   The inherited copy - the FAQ answers, the hub intros, the plain paragraphs on every interior
   page - takes it from the body. The four that wrote their own px value are named after it. */
:where(.sl-body).refine-clinical-ledger { font-size: 17px; }
:where(.sl-body).refine-clinical-ledger .et.bk-home :is(.et-hero-body, :where(.sl-body) .et-closing-l1, :where(.sl-body) .et-loc-sub) { font-size: 17px; }
:where(.sl-body).refine-clinical-ledger :is(.bk-ping, :where(.sl-body) .bk-prail-note) { font-size: 17px; }

/* ── D. ONE AIR, 110px, WHICH IS THE MIDDLE OF THE BRIEF'S 100-120.
   §35 gave this lane three airs by role - wide for a picture-beside-copy band, tight for a ruled
   list, middle for everything else - and measured on the page that came out as 148 / 115 / 79 on
   one scroll. Two of those three sit OUTSIDE the range the client asked for, so the rhythm is not
   a rhythm the brief allows. The three tokens collapse to one value; each still scales down on a
   narrow screen and each lands on exactly 110px at 1440 and wider.
   THE HERO IS LEFT ALONE, ON PURPOSE. Its bottom padding is not section air: it is
   `--bk-overhang + 28px`, the reservation that keeps the booking button 28px clear of the
   credential plate that hangs up into it. That clearance was bought in the last round and this
   round does not spend it.
   THE EXPERT BAND IS THE OTHER EXCEPTION AND IT IS NOT ONE. Its 148px top was
   `--bk-overhang (112) + --bk-rhythm-tight (36)`: the plate is pulled 112px up into the hero and
   the band below pays that height back, so the number is a compensation and only 36px of it was
   ever a design decision. It takes the one air like every other band; the plate's own geometry -
   the pull-up and the hero's reservation - is untouched. */
:where(.sl-body).refine-clinical-ledger {
  --cl-air: clamp(64px, 7.7vw, 110px);
  --cl-air-tight: clamp(64px, 7.7vw, 110px);
  --cl-air-wide: clamp(64px, 7.7vw, 110px);
}
:where(.sl-body).refine-clinical-ledger .et.bk-home :is(.et-expert, :where(.sl-body) .et-closing) { padding-block: var(--cl-air); }

/* ── 37e. THE THREE RULES THE ROOMS STILL DREW IN WHITE, AND THE TWO SIZES SET IN `rem`.
   Measured after 37A-D, not assumed: 67 of the page's 86 one-pixel rules had gone warm and 19 had
   not. The ones that had not are inside a dark room, where familySkin's darkBandVars writes
   `--bk-hair` and `--bk-accent-soft` as white alphas INLINE on the room element - a house
   function, and a house function is not this client's to edit. An inline value on an element
   cannot be out-ranked on that element, but a child's own declaration beats an inherited one, so
   the tokens are re-set one level in and every descendant inherits from there. The ALPHAS are the
   room's own, unchanged: only the temperature moves, and a hairline is a rule rather than text, so
   it clears no floor and this cannot cost the page a contrast reading.
   The map legend's boxes (.rm-key) and the quiet link's underline keep white on purpose: one is a
   chart key measured against a photograph in §30b, the other is a link telling you it is a link.
   ON THE TWO SIZES: `.et-qa` (every FAQ answer on the page) and the interior hub copy are written
   `font-size: 1rem`, and a rem is the ROOT's 16px - it does not hear the lane's 17px on `body`.
   They are named here rather than by moving the root, which would rescale the whole fleet. */
:where(.sl-body).refine-clinical-ledger .et.bk-home :is(.et-hero, :where(.sl-body) .et-band, :where(.sl-body) .bk-sit, :where(.sl-body) .bk-ev, :where(.sl-body) [style*="background-image"]) > *, :where(.sl-body).refine-clinical-ledger .et.bk-home [data-sl-depth="overhang"] > * {
  --bk-hair: color-mix(in srgb, var(--cl-metal) 22%, transparent);
  --bk-overhang-hair: color-mix(in srgb, var(--cl-metal) 22%, transparent);
  --bk-accent-soft: color-mix(in srgb, var(--cl-metal) 30%, transparent);
}
:where(.sl-body).refine-clinical-ledger .et.bk-home .et-nav { border-bottom-color: color-mix(in srgb, var(--cl-metal) 12%, transparent); }
:where(.sl-body).refine-clinical-ledger .et.bk-home .et-legal { border-top-color: color-mix(in srgb, var(--cl-metal) 15%, transparent); }
:where(.sl-body).refine-clinical-ledger :is(.et-qa, :where(.sl-body) .rt-qa, :where(.sl-body) .bh-qa, :where(.sl-body) .cm-qa) { font-size: 17px; }
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-sit-say p { font-size: 17px; }

/* ── 37f. THE STEPS LADDER WROTE ITS OWN WHITE, AND ITS OWN 16.5px.
   §33 painted `.bk-sit-card` with the literal rgba(255,255,255,0.22) rather than through a token,
   which is why warming the tokens above left three rules in that one band still cool. Same alpha,
   same weight, the metal instead of the literal - and the step NUMBER keeps its own small size,
   because a number in a ladder is a label, not running text. */
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-sit-card { border-color: color-mix(in srgb, var(--cl-metal) 22%, transparent); }
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-sit:not(.bk-composed) .bk-sit-card { border-color: color-mix(in srgb, var(--cl-metal) 22%, transparent); }
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-sit .bk-sit-card:last-child { border-bottom-color: color-mix(in srgb, var(--cl-metal) 22%, transparent); }
:where(.sl-body).refine-clinical-ledger .et.bk-home :is(.bk-sit-card p, :where(.sl-body) .bk-sit-say p):not(.bk-sit-no) { font-size: 17px; }
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-sit .bk-sit-card p:not(.bk-sit-no) { font-size: 17px; }
:where(.sl-body).refine-clinical-ledger :is(.bc-legal, :where(.sl-body) .et-legal) { border-top-color: color-mix(in srgb, var(--cl-metal) 15%, transparent); }

/* ── 37g. THE TWO BIG BLUE OBJECTS THE GROUND CHANGE LEFT BEHIND.
   Looked at from above, on the whole page, after 37A-F: the ground, the bands, the cards, the
   footer and every rule had gone neutral - and two objects had not. Both read the BRAND NAVY
   (--c-primary, #093C60) rather than the deep the record now names, and on a graphite page they
   are the two largest coloured areas on the scroll, which is the owner's complaint wearing a
   different hat: the brand hex cannot be the single accent while it is also a filled panel and a
   landmass.
   THE CONDITIONS PLATE takes the record's deep, which is what the round's decision said it would
   ("set primary_dark and the footer slab, the conditions plate and the photograph scrim all
   follow") - it did not, because the plate reads --c-primary and only the scrim and the footer
   read primary_dark. Its ink is the block's own white and is measured against the new plate.
   THE COVERAGE MAP's two land fills were mixed from the navy in §30b. They come off the page's own
   neutral ladder instead, at the same LIGHTNESS relationship the navy pair had (served lighter
   than the counties around it), so the wayfinding still works. The town pins stay coral: they are
   the accent, and on a neutral island they are now the only colour in the band. */
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-cond-panel { background: var(--c-primary-dark); }
/* AND THEN THE PALETTE MOVED UNDER IT. Both fills above were mixed from `--c-surface`, which was a
   tinted stock when they were written and is plain white on the warm-neutral record. So the two
   mixes collapsed onto each other: Nassau, Suffolk and the counties beside them all rendered the
   same near-white, the island read as one undifferentiated shape, and the two legend swatches that
   are supposed to tell them apart were the same colour as each other.
   The pair is now built from the page's own INK, which is the one token that is guaranteed to sit
   at the other end of the ladder from the land — so the relationship survives whatever the ground
   does next. Served counties stay the lighter of the two, because the eye reads the lighter shape
   as the subject. The band is a photograph, so both carry a visible edge. Pins stay coral: on a
   neutral island they are the only colour in the band, which is the point of them. */
:where(.sl-body).refine-clinical-ledger .et.bk-home .et-locations .et-locmap {
  --limap-served-d: color-mix(in srgb, var(--c-text, #3B372F) 6%, #FFFFFF);
  --limap-rest-d: color-mix(in srgb, var(--c-text, #3B372F) 42%, #FFFFFF);
  --limap-edge-d: color-mix(in srgb, var(--c-text, #3B372F) 55%, transparent);
  --limap-ink-d: var(--c-text, #3B372F);
  --limap-legend-d: #FFFFFF;
}

/* ══ DESIGN LANE: skylight ═══════════════════════════════════════════════════════════════════
   THE PAGE BREATHES. Authored 2026-09-10 for Blue Sky IV, whose client looked at a finished
   staging build, approved the direction, and rejected it in four words: "too AI and super
   crammed". The AI half is an imagery problem and is answered in their brand record. The crammed
   half is a DESIGN problem, and no lane on the shelf answered it — because of the fifteen already
   here, every one differs from its neighbours on a card corner, a card edge or a button corner,
   and NONE of them differs on the two axes a reader actually judges from across a room. Measured
   by lane-distinct's own fingerprint over the whole shelf:

       card corner 3 · card edge 3 · button corner 4     ← where all fifteen lanes live
       heading case 1 · heading tracking 1 · band grounds 1 · band rhythm 1   ← nobody, ever

   So this lane is deliberately built on the empty half of that table. It is the only lane whose
   identity you can read with the page scaled to a thumbnail, and the only one you cannot describe
   by naming a corner radius.

   THE DEVICE IS AIR.
     * --bk-rhythm goes to 88-160px against the house 48-76px, and interior bands take the same.
       Roughly double, everywhere, on both renderers. Air is the whole point; a lane about
       spaciousness that ships the house rhythm is a lane about nothing.
     * The section header is a NARROW CENTRED COLUMN with a wide gap beneath it. A heading that
       runs the full width of a 1400px band and then puts cards 24px under it is most of what
       "crammed" means, and it is a measurement, not a taste.
     * Plates are borderless, unelevated, softly rounded and deeply padded; controls are fully
       round. Those are the ordinary axes and they agree with the air rather than carrying the
       identity on their own.

   WHAT THE GATE TOOK OFF IT, AND WHY THAT WAS RIGHT. The first draft of this lane cycled THREE
   grounds instead of two — genuinely unused on the shelf, and the reason it is not here any more
   is worth writing down rather than rediscovering. lane-gate refused it on four of six cells:

     community, bright   page-rules   two bands in a row on the same ground
     estate              photo-text   words over a photograph, veiled differently (2)
     estate.dark         visual-lint  text the lane made unreadable (5)
     estate.dark         photo-text   words over a photograph, veiled differently (2)

   Three findings, three lessons, all of them the traps below wearing new clothes:
     * A third ground has to be a THIRD COLOUR, not a second shade of the second one. Paper, a 5%
       tint and a 10% tint put two near-identical bands next to each other in the cycle, and
       page-rules is right that a reader cannot see the seam. Two beats now, and the second is the
       brand's own #F0F5FD — which is what this client's brand standards asked for in the first
       place: "alternating sections so the page has rhythm".
     * CENTRING A HEADER MOVES COPY ONTO A PHOTOGRAPH. The narrow centred column is the best part
       of this lane on a flat band and actively harmful on a photographed one, where it walks the
       words off the veiled corner and into the bright middle of the picture. Scoped off .sec-photo
       and .sec-room.
     * AND THE FILLS ONLY BELONG ON A LIGHT PAGE. Every `background:` below is scoped to
       :not(.ground-dark). On a dark ground the plates carry their own fill AND their own light
       ink, set together in the block, and a lane that takes half of that pair takes the half that
       cannot be read — five times over, on one build. The SHAPE rules stay unscoped, because a
       corner radius cannot be unreadable. That split is the whole of trap T1 stated as code.

   THE FIVE TRAPS. Written out on body.refine-warm-studio and body.refine-block-poster above;
   restated as they apply here.
     T1  A LANE SETS SHAPE, NOT A CONTROL'S INK. There is not one `color:` declaration below on a
         heading, eyebrow, button or label, and no `background` outside :not(.ground-dark).
     T2  A LANE DOES NOT REPAINT A PLATE IT WILL NOT ALSO RE-INK. .bk-feat, .bk-tile and
         .bk-sit-card carry their own fill AND their own type colour. All three are excluded.
     T3  BOTH BEATS ARE DECLARED, under both .sections-alternate and .bands-paper. A brand whose
         own ground is already a tint would otherwise alternate tint with tint.
     T4  THE CLOSING BAND IS NOT THE LANE'S TO PAINT, and neither is the service-area map, which
         takes the same !important guard four other lanes carry.
     T5  BOTH RENDERERS, OR IT DRESSES THE INTERIOR PAGES AND LEAVES THE HOME PAGE — the one page
         everybody sees — on the house look. Sections 1-6 speak `.section`/`.card`/`.btn`;
         section 7 restates them in `.bk-*`; section 8 covers all five families' chrome.

   CONTRAST, MEASURED, for the brand it was authored against: navy #103795 and blue #0835A5.
   #0835A5 on white is 11.6:1 and white on #0835A5 is 11.6:1, so the accent carries type in both
   directions and is safe as a fill under white. The brand's third colour #3274E3 is 4.06:1 on
   white — it cannot carry small text and this lane never asks it to; it appears only as the
   header rule, which is decoration carrying no type.
   @lane skylight | air is the device: double the band rhythm and headings in a narrow centred column over a wide gap | suits: airy spacious generous breathing uncluttered open bright clean polished modern premium calm roomy
   */
:where(.sl-body).refine-skylight {
  /* THE AIR, one token for each renderer, so every rule below states the device once. */
  --sl-air: clamp(3rem, 5.5vw, 7rem);
  /* The gap between a band's header and the band's content. The second half of "crammed". */
  --sl-gap: clamp(2.75rem, 4.5vw, 4.5rem);
  /* The header's own column. Narrow on purpose: a centred measure a reader takes in at once. */
  --sl-measure: 38ch;
  /* Mixed from the brand's own primary, so this is this client's daylight and not a hardcoded
     blue. Only ever used on a light ground — see the note above. The alternate BAND ground is not
     one of these: it is --c-surface-alt, the house token, for the reason written at section 1. */
  --sl-rule: color-mix(in srgb, var(--c-primary) 16%, transparent);
  --sl-plate: color-mix(in srgb, var(--c-primary) 4%, var(--c-surface));
  --sl-plate-deep: color-mix(in srgb, var(--c-primary) 9%, var(--c-surface));
  /* Softly rounded, borderless, unelevated. Separation is a change of stock and a lot of space. */
  --card-radius: 28px;
  --btn-radius: 999px;
  --input-radius: 999px;
  --card-shadow: none;
  --card-hover-shadow: none;
  --card-border-width: 0;
  --sl-ease: 200ms cubic-bezier(.22, .61, .36, 1);
}

/* 1. THE TWO BEATS (T3), on a light ground only. Rooms, photo bands and the closing ask are
      excluded exactly as every other lane excludes them (T4). */
:where(.sl-body).refine-skylight:where(:not(.ground-dark)).sections-alternate main > section.section:nth-of-type(odd):not(.sec-room):not(.sec-photo):not(.final-cta):not(.section-hub-cta), :where(.sl-body).refine-skylight:where(:not(.ground-dark)).bands-paper main > section.section:nth-of-type(odd):not(.sec-room):not(.sec-photo):not(.final-cta):not(.section-hub-cta) {
  background: var(--c-surface);
}
:where(.sl-body).refine-skylight:where(:not(.ground-dark)).sections-alternate main > section.section:nth-of-type(even):not(.sec-room):not(.sec-photo):not(.final-cta):not(.section-hub-cta), :where(.sl-body).refine-skylight:where(:not(.ground-dark)).bands-paper main > section.section:nth-of-type(even):not(.sec-room):not(.sec-photo):not(.final-cta):not(.section-hub-cta) {
  background: var(--c-surface-alt);
}
/* The change of stock is the divider. No rule between bands, ever. */
:where(.sl-body).refine-skylight .section + .section { border-top: 0; }
/* The block library's own vertical rhythm, set on the home rather than on <body> — the same place
   refine-clinical-ledger sets its own, and narrow enough not to reach a photographed band. */
:where(.sl-body).refine-skylight .bk-home { --bk-rhythm: var(--sl-air); }
/* THE AIR ITSELF — shape, so it applies on every ground. NOT on a photographed band or in a room:
   their padding is part of how the copy sits on the picture, and doubling it walks the words off
   the veiled corner into the bright middle. Two photo-text failures, on two families. */
:where(.sl-body).refine-skylight main > section.section:not(.sec-photo):not(.sec-room) {
  padding-top: var(--sl-air);
  padding-bottom: var(--sl-air);
}
/* The guard four other lanes carry: without it a lane's (0,2,1) rule outranks the light map
   compositions and buries their ink (T4). */
:where(.sl-body).refine-skylight:not(.map-index):not(.map-panel) main > section.section.section-service_area_map {
  background: var(--c-room) !important;
}

/* 1b. AND THE SAME TWO BEATS ON A BLUEPRINT HOME, which section 1 does not reach: a home page has
      no `main > section.section` at all, its bands are the children of `.bh`. Trap T5, in the one
      place it costs a defect rather than just a plain look — measured on the client this lane was
      authored for, three bands in a row came out on the same tint and page-rules refused the build.

      `nth-CHILD`, NOT `nth-of-type`, AND BOTH SHAPES OF BAND. Two of the eleven bands on that page
      are wrapped in a bare `div` inside `.bh` rather than sitting in it directly, so counting by
      TYPE skipped them, every band after the first wrapper fell one step out of step, and the fix
      turned two seams into one instead of none. `:nth-child` counts every sibling, wrapper or not,
      which is the document order a reader actually sees.

      `background-color`, NOT `background`: a room paints itself with a gradient, which lives in
      background-IMAGE, so setting the colour alone leaves every photographic and dark band exactly
      as its own block drew it. The hero and the closing ask are excluded outright (T4). */
:where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bh > section:nth-child(odd):not([class*="hero"]):not(.bh-closing):not(.sec-room):not(.final-cta):not(.section-hub-cta), :where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bh > div:nth-child(odd) > section:not([class*="hero"]):not(.bh-closing):not(.sec-room):not(.final-cta):not(.section-hub-cta) {
  background-color: var(--c-surface);
}
:where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bh > section:nth-child(even):not([class*="hero"]):not(.bh-closing):not(.sec-room):not(.final-cta):not(.section-hub-cta), :where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bh > div:nth-child(even) > section:not([class*="hero"]):not(.bh-closing):not(.sec-room):not(.final-cta):not(.section-hub-cta) {
  background-color: var(--c-surface-alt);
}
/* A plate standing on the tinted beat takes paper here too, or it vanishes into its band — the
   same argument as section 3, restated for the renderer section 1b just started painting. */
:where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bh > section:nth-child(even) .bk-card, :where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bh > section:nth-child(even) .bk-pillar, :where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bh > section:nth-child(even) .bk-pcard, :where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bh > section:nth-child(even) .bk-step, :where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bh > section:nth-child(even) .bk-ccard, :where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bh > section:nth-child(even) .bk-ict-card, :where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bh > section:nth-child(even) .bk-fcard {
  background: var(--c-surface);
}

/* 1c. TWO ARRANGEMENTS THAT LEAVE THIS PARTICULAR PAGE HALF EMPTY, CORRECTED FOR THIS BRAND ONLY.
      Both are legitimate house arrangements and both are wrong for THIS content, and the reason is
      the same in each case: they were chosen for an item count and a picture width this client does
      not have.

      THE BAGS. `chooseCols(8, 3)` returns 2 - eight items have no exact factorisation at three, so
      the balanced rule steps down to two. That is right for eight wide cards and wrong for eight
      TALL NARROW cut-out bags: each one ends up in a 620px plinth around a 162px picture, four
      rows deep, 3,193px of page. Eight divides exactly by four, so four across is BALANCED by the
      same rule the house already applies - the maxCols the block passes is what does not fit this
      artwork. Overriding `--n`, which is the block's own mechanism, not a hardcoded grid.
      It also takes the plinth under 600px, which is what page-rules P7 was correctly refusing.

      THE WHY-US CARDS. `bk-ict-l-column` stacks three short cards one per row down a 68ch centred
      measure - 1,346px for about ninety words. On a page that already had no photographs, that is
      the band that made it read as empty. Three cards across is what the same block does on its
      other arrangements.

      Scoped to this lane, so no other client's page moves. If this keeps happening, the honest fix
      is maxCols on the bag block, not more of these. */
/* `!important` is load-bearing here and is the only thing that works. `--n` is written by the
   block as an INLINE style attribute, and the arrangement's own rules are astro-scoped, so they
   carry an extra `[data-astro-cid-…]` attribute selector. A lane rule at (0,3,1) loses to both.
   This is the one place in this lane that reaches over a block, and it is doing it to an
   ARRANGEMENT — how many things sit on a line, and how tall a picture is — never to ink. */
:where(.sl-body).refine-skylight .bk-bagc-l-shelf .bk-bagc-row { --n: 4 !important; }
@media (max-width: 1100px) { :where(.sl-body).refine-skylight .bk-bagc-l-shelf .bk-bagc-row { --n: 3 !important; } }
@media (max-width: 760px)  { :where(.sl-body).refine-skylight .bk-bagc-l-shelf .bk-bagc-row { --n: 2 !important; } }
:where(.sl-body).refine-skylight .bk-bagc-l-shelf .bk-bagc-wrap { height: 330px !important; }
:where(.sl-body).refine-skylight .bk-bagc-l-shelf .bk-bagc-wrap img { height: 268px !important; }
:where(.sl-body).refine-skylight .bk-ict-l-column .bk-ict-cards {
  display: flex !important;
  flex-wrap: wrap !important;
  justify-content: center !important;
  gap: 26px !important;
  max-width: none !important;
}
:where(.sl-body).refine-skylight .bk-ict-l-column .bk-ict-card {
  flex: 1 1 clamp(260px, calc((100% - 52px) / 3), 420px) !important;
  margin-bottom: 0 !important;
}

/* 1d. A BAND WITH A HOLE IN IT. The add-ons band draws on the `beside` arrangement: a heading and
      one short paragraph in the left column, a nine-row card in the right. The card is roughly
      three times the height of the words beside it, so the bottom two thirds of the left column is
      empty page - about 380px of nothing, directly under "Make It Yours". Ian, 2026-09-10: "it's a
      big blank space there of nothing. We should be filling in blank spaces. That's a rule of ours."

      The block already answers this itself: its `pairs` arrangement puts the head ABOVE and flows
      the rows in two columns, so there is no short column to leave a hole. Which arrangement a
      brand gets is seeded from its own id, and this one drew the arrangement that does not suit a
      nine-row list. Restating `pairs` for this lane rather than inventing a fourth shape. */
:where(.sl-body).refine-skylight .bk-ledger-l-beside .bk-ledger-in {
  grid-template-columns: minmax(0, 1fr) !important;
  gap: clamp(22px, 2.6vw, 34px) !important;
}
:where(.sl-body).refine-skylight .bk-ledger-l-beside .bk-ledger-intro { max-width: var(--bk-measure, 62ch); }
:where(.sl-body).refine-skylight .bk-ledger-l-beside .bk-ledger-card {
  column-count: 2;
  column-gap: clamp(30px, 4vw, 64px);
}
:where(.sl-body).refine-skylight .bk-ledger-l-beside .bk-ledger-row { break-inside: avoid; }
:where(.sl-body).refine-skylight .bk-ledger-l-beside .bk-ledger-foot { column-span: all; max-width: var(--bk-measure, 62ch); }
@media (max-width: 860px) { :where(.sl-body).refine-skylight .bk-ledger-l-beside .bk-ledger-card { column-count: 1; } }

/* 1e. THE THREE STEPS, LEFT TO RIGHT, WITH PICTURES THAT FILL THEIR COLUMN. The horizontal `track`
      arrangement draws each step's picture in a fixed 150px-high box with object-fit: contain, so a
      3:2 photograph lands at 225x150 in a 400px column with 87px of blank either side - the
      "small" in "very plain and very small". Letting the box take the picture's own shape fills the
      column; all three frames are 3:2, so the row still lines up flat, which is what the block's
      `margin-top: auto` exists to protect. Scoped to this lane: the shared line in
      NumberedTimeline.astro is left alone for every other client on the block. */
:where(.sl-body).refine-skylight .bk-tl-l-track .bk-step-art {
  height: auto !important;
  aspect-ratio: 3 / 2;
  width: 100%;
  object-fit: cover !important;
  border-radius: var(--card-radius);
}

/* 1f. THE VIALS. A cut-out vial is roughly 1:2.4, so in the picture-card layout - `width: 100%` of a
      400px card, capped only at 66vh - each one stood about 590px tall and nine of them made a
      2,000px band. They are small objects and they are shown as small objects: 170px, centred on
      the card, sharp at any density (the files are 480px wide). */
:where(.sl-body).refine-skylight .bk-pstep-l-cards .bk-ps img {
  width: auto !important;
  max-width: 100%;
  height: 170px !important;
  max-height: 170px !important;
  aspect-ratio: auto !important;
  object-fit: contain !important;
  margin-inline: auto;
  margin-bottom: 18px !important;
  border-radius: 0 !important;
}
:where(.sl-body).refine-skylight .bk-pstep-l-cards .bk-ps { text-align: center; }

/* 1g. THE HEADLINE IS THE LARGEST THING ON THE SCREEN; THE SENTENCE UNDER IT MUST NOT BE THE WIDEST.
      Measured at 1440: the headline held to 760px and wrapped to two lines of 532 and 431px, while
      the sentence beneath it was allowed 1,040px and ran a first line of 1,028px - small type nearly
      twice as wide as big type, which is what reads as "a long headline that looks odd". At 864
      (Ian's window) it also stranded "rest." alone on a third line. Held to 600px it breaks into
      three even lines under the headline instead of a wide band across it. */
:where(.sl-body).refine-skylight .bh-hero.sl-hero-box .bh-hero-body { max-width: 600px; margin-inline: auto; text-wrap: pretty; }

/* 1h. THE ADD-ONS SPEAK THE PAGE'S TYPE, NOT THE BLOCK'S. The picture-card block sets its own heading
      and card titles in condensed capitals, which is right for the brands it was drawn for and wrong
      on a page where every other heading is the brand's serif in title case: "MAKE IT YOURS" was the
      one heading on the page shouting. The small "Priced separately" label stays in caps - it is a
      label. And the one button under the grid sat 60px below it in a pale band of its own, reading
      as a leftover rather than as the band's ending. */
:where(.sl-body).refine-skylight .bk-pstep h2 {
  font-family: var(--font-heading, serif) !important;
  text-transform: none !important;
  letter-spacing: -0.02em !important;
  font-weight: 400 !important;
}
:where(.sl-body).refine-skylight .bk-ps h3 {
  font-family: var(--font-heading, serif) !important;
  text-transform: none !important;
  letter-spacing: normal !important;
  font-size: 22px !important;
}
:where(.sl-body).refine-skylight .bk-pstep-ctas { margin-top: 34px !important; }

/* 1i. THE COLUMN BESIDE THE MAP. The first Chicagoland map was near-square (0.96), so at the band's
      702px it stood ~750px tall (since 2026-09-11 it reaches Rockford and is 1.21:1, ~580px at
      1440; the cap below still binds when the band stacks), and the copy beside it - one paragraph and eight towns in two short columns -
      filled 507px of that and left 541px of empty column underneath (measured, 1440). Ian, twice:
      "a little bit of copy and a big blank space. We've talked about that before." Three moves, all
      shape: the map is capped so it does not set the band's height on its own, the towns run in one
      taller column so the list carries its own weight, and the two columns are centred against each
      other so whatever difference is left is shared above and below instead of pooling at the bottom. */
:where(.sl-body).refine-skylight .bh-areas:not(.bh-1col) { align-items: center !important; }
:where(.sl-body).refine-skylight .bh-areas .bh-map svg { max-height: 600px !important; width: 100% !important; height: auto !important; }
:where(.sl-body).refine-skylight .bh-areas .bh-areas-copy { padding-top: 0 !important; }
:where(.sl-body).refine-skylight .bh-towns { columns: 1 !important; margin-top: 22px !important; }
:where(.sl-body).refine-skylight .bh-towns li { font-size: 17px; padding-top: 12px !important; padding-bottom: 12px !important; }

/* 1j. THREE ACROSS MEANS THREE ACROSS IN THE WINDOW IT IS LOOKED AT IN. Every row on this design
      collapses to one column under 900px (RowFit, MembershipTiers, NumberedTimeline) or 1000px
      (IconCardTrio) - phone breakpoints set at tablet width. Ian reviews in a Chrome window about
      864px wide, so every "left to right" he asked for rendered top to bottom for him: measured at
      864, membership 1 across, why-us 1, steps 1, drips 2 visible; at 1280, 3/3/3/3. At 864 each
      column is still ~250px, which is plenty for a tier card, a feature card or a step. So between
      721 and 1000px the three-item rows keep three columns, and they stack only on a real phone. */
@media (min-width: 721px) and (max-width: 1000px) {
  :where(.sl-body).refine-skylight .bk-tierrow > *, :where(.sl-body).refine-skylight .bk-pstep-l-cards .bk-psrow > *, :where(.sl-body).refine-skylight .bk-ict-cards > *, :where(.sl-body).refine-skylight .bk-ict-cards[data-n] > * {
    flex-basis: calc((100% - 2 * var(--bk-rowgap, 24px)) / 3) !important;
    min-width: 0 !important;
  }
  :where(.sl-body).refine-skylight .bk-tl-l-track .bk-rail { grid-template-columns: repeat(3, minmax(0, 1fr)) !important; gap: 24px !important; }
  :where(.sl-body).refine-skylight .bk-tl-l-track .bk-step { padding-top: 30px !important; }
  :where(.sl-body).refine-skylight .bk-tl-l-track .bk-step::before { display: block !important; }
  :where(.sl-body).refine-skylight .bk-bagc-reel .bk-bagc-prod { flex-basis: calc((100% - 2 * var(--bk-rowgap, 40px)) / 3) !important; }
}

/* 1k. WELLNESS, TOGETHER - THE ONE BAND THAT CAME FROM A DIFFERENT HOUSE. The events cards are the
      estate design's: a near-black textured room, each photograph sinking into the card's darkness
      through a navy gradient, white words laid over the fade, an all-capitals heading and square
      capital-letter buttons. Ian, 2026-09-10: "I love the images... the rest of it just doesn't feel
      like it fits with the rest of the website." Every other card on this page is a soft borderless
      plate on a light ground with the brand's serif in title case, so this one is dressed the same:
      the room goes light, the gradient goes, the words move off the picture onto the plate beneath
      it, and the buttons become the page's pills.
      REPAINTED AND RE-INKED TOGETHER (trap T2): the band's white type was chosen for a dark ground,
      so every piece of text in it takes the page's ink in the same breath as the ground changes. */
:where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bk-ev {
  background-image: none !important;
  color: var(--c-text, #1A1A1A) !important;
}
:where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bk-ev h2 {
  color: var(--c-heading, var(--c-primary)) !important;
  text-transform: none !important;
  letter-spacing: -0.02em !important;
  font-weight: 400 !important;
  text-align: center !important;
}
:where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bk-ecard {
  border: 0 !important;
  border-radius: var(--card-radius, 28px) !important;
  background: var(--c-surface, #fff) !important;
  box-shadow: 0 1px 2px rgba(16,55,149,0.06), 0 8px 24px rgba(16,55,149,0.06);
}
:where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bk-eph { height: 220px !important; }
:where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bk-eph::after { display: none !important; }
:where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bk-etxt {
  margin-top: 0 !important;
  padding: 22px 24px 26px !important;
  text-align: left;
}
:where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bk-ecard h3 {
  color: var(--c-heading, var(--c-primary)) !important;
  font-size: 23px !important;
  margin: 0 0 8px !important;
}
/* the same ink every other card body on the page uses (why-us and add-ons both measure #1A1A1A) */
:where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bk-ecard p { color: var(--c-text, #1A1A1A) !important; }
:where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bk-ev-btn {
  border-radius: var(--btn-radius, 999px) !important;
  text-transform: none !important;
  letter-spacing: 0.01em !important;
  font-weight: 700 !important;
  padding: 15px 30px !important;
}
:where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bk-ev-fill { background: var(--c-accent, #0835A5) !important; color: #fff !important; }
:where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bk-ev-white, :where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bk-ev-ghost {
  color: var(--c-accent, #0835A5) !important;
  box-shadow: inset 0 0 0 1.5px var(--c-accent, #0835A5) !important;
}

/* 1l. COUNTY NAMES ON THE MAP. Served counties are painted in the accent at three strengths and
      named in the primary ink. On a warm accent that reads; Blue Sky's accent is a deep royal blue,
      so the strongest fill sits within a shade of the ink and the names on it vanish - measured on
      the live page 2026-09-11: Kane and Will unreadable, DeKalb, DuPage and Lake faint. No order of
      the seven counties avoids it (Kane and Will are forced into one fill, and every fill holds a
      named county), so every served name gets a halo of the page ground under it, the way a road
      atlas does it: it reads on all three strengths without picking a second ink per fill. The halo
      is the surface the map already sits on, not a new colour. Not in a room: rooms re-ink the
      whole plane already.
      The legend's "Neighbouring counties" chip has no fill anywhere outside the estate home, so here
      it rendered as an empty gap before its words; it takes the unserved county's fill. */
:where(.sl-body).refine-skylight :where(section:not(.sec-room)) .rm-label.is-served {
  paint-order: stroke;
  stroke: var(--c-surface, #fff);
  stroke-width: 7px;
  stroke-linejoin: round;
}
:where(.sl-body).refine-skylight :where(section:not(.sec-room)) .rm-key-rest {
  background: color-mix(in srgb, var(--c-primary) 7%, var(--c-surface));
  border: 1px solid color-mix(in srgb, var(--c-primary) 34%, transparent);
}

/* 1m. THE OTHER NAME SITS BENEATH THE NAME, SMALLER. Client rule, 2026-09-21: "the original or
      commonly recognized IV name should appear beneath the branded Blue Sky name - for example,
      Blue Sky OG (Myers' Cocktail)". A drip hero writes it as the headline's second line, and on
      this design line two printed at the full H1 size: "Blue Sky / OG / Myers' / Cocktail" read as
      one four-line title, the common name shouting as loud as the client's own. Beneath means
      subordinate, so line two drops to the body face at a little under half the size, the same
      way the menu cards print it. Shape only; it keeps whatever ink the hero gives the headline. */
:where(.sl-body).refine-skylight .hero h1 .h1-l2 {
  display: inline-block;
  margin-top: 0.4em;
  font-family: var(--font-body, sans-serif);
  font-size: 0.4em;
  font-weight: 500;
  line-height: 1.3;
  letter-spacing: 0.01em;
}

/* 1m-b. THE LINE ABOVE A PHOTO HERO'S HEADLINE MUST READ. The house hero prints its eyebrow in the
      accent (`.hero .eyebrow`), and Blue Sky's accent is the royal blue the photo hero is washed
      in: "DuPage and Will Counties" over the Naperville hero measured as blue on blue, gone
      (2026-09-21). Over a photograph it takes the hero's own light ink, softened like the subhead. */
:where(.sl-body).refine-skylight .hero.hero-image-bg .eyebrow {
  color: color-mix(in srgb, var(--c-on-dark, #fff) 86%, transparent) !important;
}

/* 1n. THE MENU FITS ON ONE LINE WITH ITS BUTTON, AND IS READABLE. Blue Sky's own menu
      (theme_json.nav) once had seven items and two drop-downs; at the bar's 24px gaps and 17px type
      the "Book an Angel" button wrapped to a second row under the logo at 1280px (measured
      2026-09-21), so the type was cut to 16px to fit. Two items have since left the bar
      (Membership, then FAQ), and Ian read what was left as small: "the menu at the top just kind of
      feels a little small". Five items buy some of it back: 17px, with the gap tightened to 16px to
      pay for it. Measured to wrap no earlier than the 16px version did — one line down to 1100px,
      and the button drops to a second row at 1001px on BOTH, which is the bar's own limit rather
      than anything this rule does. The phone menu is untouched. */
@media (min-width: 1001px) {
  :where(.sl-body).refine-skylight .bh-navlinks { gap: 4px 16px !important; }
  :where(.sl-body).refine-skylight .bh-navlinks > a, :where(.sl-body).refine-skylight .bh-navlinks .sl-navg > a, :where(.sl-body).refine-skylight .bh-navlinks .sl-navg > button { font-size: 17px !important; }
}

/* 1p. BELOW DESKTOP THE MENU BECOMES A BUTTON. Measured on this site before the change: the bar
       stacked into three rows and stood 224px tall on a 664px phone — 34% of every screen, 44% with
       the booking bar at the foot — and three rows at Ian's own 864px window. The bar is now one
       slim row (logo, menu button) and the links open as a panel beneath it, which is also where
       the booking button goes so it is not lost. Blue Sky only for now: the markup ships with every
       bright client but stays invisible until a lane asks for it, so nobody else moves. */
@media (max-width: 900px) {
  :where(.sl-body).refine-skylight .bh-nav {
    flex-wrap: nowrap; justify-content: space-between !important; min-height: 0; gap: 12px;
    padding: 10px clamp(14px, 4vw, 22px);
  }
  :where(.sl-body).refine-skylight .bh-brand img { height: 36px; }
  :where(.sl-body).refine-skylight .bh-burger { display: flex; }
  :where(.sl-body).refine-skylight .bh-nav > .bh-navlinks, :where(.sl-body).refine-skylight .bh-nav > .bh-navr { display: none; }
  /* Open: one panel under the bar, a row per link, thumb-sized, and it scrolls if it has to. */
  :where(.sl-body).refine-skylight .bh-nav.bh-open > .bh-navlinks, :where(.sl-body).refine-skylight .bh-nav.bh-open > .bh-navr {
    display: flex; flex-direction: column; align-items: stretch; gap: 0;
    position: absolute; left: 0; right: 0; top: 100%;
    background: #fff; box-shadow: 0 18px 30px -18px rgba(8, 18, 22, .45);
    padding: 6px clamp(14px, 4vw, 22px) 10px; max-height: calc(100vh - 64px); overflow-y: auto;
  }
  :where(.sl-body).refine-skylight .bh-nav.bh-open > .bh-navr { top: auto; box-shadow: none; padding-top: 0; padding-bottom: 16px; }
  :where(.sl-body).refine-skylight .bh-nav.bh-open > .bh-navlinks > a, :where(.sl-body).refine-skylight .bh-nav.bh-open > .bh-navlinks .sl-navg > a, :where(.sl-body).refine-skylight .bh-nav.bh-open > .bh-navlinks .sl-navg > button {
    display: flex; align-items: center; width: 100%; min-height: 48px; font-size: 17px !important;
    border-bottom: 1px solid color-mix(in srgb, var(--c-text, #1a1a1a) 10%, transparent);
  }
  :where(.sl-body).refine-skylight .bh-nav.bh-open > .bh-navr .bh-pill { justify-content: center; width: 100%; }
}

/* 1o. THE BAG STANDS ON THE HERO, NOT INSIDE ITS WASH — and it lines up with the words.
       Ian on the drip pages, 2026-09-22: "the bag shouldn't be part of the blue gradient. It should
       sit above that so it's not affected by it. The copy in the hero section and the blue bag
       should be aligned with each other. Right now, they feel like they're just scattered."

       TWO THINGS, AND ONLY TWO. The hero keeps its photograph, its wash, its height and its white
       type; this does not touch any of them.

       THE STACK. `.hero-image-bg::after` carries the wash and the grain at z-index 1, and the bag
       is also z-index 1 — same layer, and a pseudo-element paints after its siblings, so the bag was
       under the blue every time. Lifting it to 3 puts the product in its own colours on top of the
       band. It stays clear of the words, which sit at z-index 2 in a column the bag's own width
       already caps (see .hero:has(> .hero-bag-float) .hero-inner).

       THE ALIGNMENT. The bag was pinned to the bottom of the band and the copy sat at the top of it,
       so the two shared no line at all: measured at 1366px, the copy's middle was 407px down the
       band and the bag's was 537px, with 263px of empty hero under the buttons. Both are now centred
       on the band, so they read as one composition across the middle of it. Desktop only — below
       901px the float is not rendered and the copy takes the full width, exactly as before. */
@media (min-width: 901px) {
  /* ONE CELL, TWO THINGS IN IT. The band becomes a single-cell grid and both the words and the bag
     are placed in that one cell: the copy keeps the centred column and page margin it already had
     (a flex row re-sized it and walked the headline out to the window's left edge), and the bag
     stops being positioned against the band's PADDING box — which is 31px at the top against 194px
     at the bottom, so anything centred that way sat 81px below the words. Sharing the cell, one
     `align-self` puts both on the same centre line. */
  :where(.sl-body).refine-skylight .hero.hero-image-bg:has(> .hero-bag-float) { display: grid; grid-template-columns: 1fr; align-items: center; }
  /* AND THE WORDS START ON THE PAGE'S OWN EDGE, which is the other half of "balanced". The bag is
     pinned to the page margin (43px in from the right at 1366), and so is every band below this one
     — but the hero's words sat in a narrow centred column that began 389px in. One page, two left
     edges. Ian, 2026-09-22: "the copy feels more in, while the bag feels more out… it doesn't feel
     like the page is balanced as I scroll down." The container now takes the full band with the
     page's own gutter, so the copy's left margin and the bag's right margin are the same number at
     every width. The reading measure is unchanged: .hero-inner still caps the text column. */
  :where(.sl-body).refine-skylight .hero.hero-image-bg:has(> .hero-bag-float) > .container {
    grid-area: 1 / 1; width: 100%; max-width: none;
    padding-inline: var(--bk-pad, clamp(16px, 5.5vw, 80px));
  }
  /* MOVING THE COLUMN'S EDGE MUST NOT STRETCH ITS LINES. Full-width, the old cap let the subhead run
     to 916px — around a hundred characters a line. The text keeps the measure it had; only where it
     starts has changed. */
  :where(.sl-body).refine-skylight .hero.hero-image-bg:has(> .hero-bag-float) .hero-inner {
    max-width: min(520px, calc(100% - min(30%, 420px) - 2.5rem));
  }
  :where(.sl-body).refine-skylight .hero.hero-image-bg > .hero-bag-float {
    grid-area: 1 / 1; position: static; z-index: 3; justify-self: end; align-self: center;
    margin-right: var(--bk-pad, clamp(16px, 5.5vw, 80px));
    /* IN FLOW, THE BAG NOW SETS THE BAND'S HEIGHT, so it is capped at the height the band already
       had inside its padding (786 - 31.5 - 194 = 560). The hero measures the same before and after;
       only the bag's own position changed. */
    max-height: 560px;
  }
}
/* AND THE COMPOSITION HAS TO EXIST AT THE WIDTH IAN ACTUALLY USES. The shared float hides the bag
   below 900px, and his own window is 864 — so the hero he approved (photo, wash, copy, bag on one
   centre line) was desktop-only, and the screen he judges it on never had a bag in it at all. The
   design review found the same thing from the other side: "the drip bag disappears below desktop".
   Laptop widths get the same composition with a smaller bag. Phones are untouched: there the float
   is still hidden and the copy takes the full width, which is its own decision to make later. */
@media (min-width: 761px) and (max-width: 900px) {
  :where(.sl-body).refine-skylight .hero.hero-image-bg:has(> .hero-bag-float) { display: grid; grid-template-columns: 1fr; align-items: center; }
  :where(.sl-body).refine-skylight .hero.hero-image-bg:has(> .hero-bag-float) > .container {
    grid-area: 1 / 1; width: 100%; max-width: none;
    padding-inline: var(--bk-pad, clamp(16px, 5.5vw, 80px));
  }
  :where(.sl-body).refine-skylight .hero.hero-image-bg > .hero-bag-float {
    display: block; grid-area: 1 / 1; position: static; z-index: 3; justify-self: end; align-self: center;
    margin-right: var(--bk-pad, clamp(16px, 5.5vw, 80px));
    max-height: 420px; max-width: min(30%, 300px);
  }
  :where(.sl-body).refine-skylight .hero.hero-image-bg:has(> .hero-bag-float) .hero-inner {
    max-width: min(460px, calc(100% - min(30%, 300px) - 2rem));
  }
}

/* 2. THE HEADER IS A NARROW CENTRED COLUMN WITH A WIDE GAP UNDER IT — the second half of the
      device, and the half that is invisible in a screenshot of one card. NOT on a photographed
      band or in a room: centring a header there walks the words off the veiled corner and into
      the bright middle of the picture, which is two photo-text failures and no benefit. */
:where(.sl-body).refine-skylight main > section.section:not(.sec-photo):not(.sec-room) > .container > .section-header, :where(.sl-body).refine-skylight main > section.section:not(.sec-photo):not(.sec-room) > .section-header {
  max-width: var(--sl-measure);
  margin-inline: auto;
  margin-bottom: var(--sl-gap);
  text-align: center;
}
:where(.sl-body).refine-skylight h1, :where(.sl-body).refine-skylight h2 {
  letter-spacing: -0.02em;
  line-height: 1.08;
  text-wrap: balance;
}
:where(.sl-body).refine-skylight .eyebrow, :where(.sl-body).refine-skylight .bk-eyebrow-caps {
  text-transform: uppercase;
  letter-spacing: 0.2em;
  font-size: 0.72rem;
  font-weight: 700;
}
/* A short rule ABOVE the header — the one place this lane spends a line of colour, and it is
   decoration carrying no type (see the contrast note above). */
:where(.sl-body).refine-skylight main > section.section:not(.sec-photo):not(.sec-room) .section-header::before {
  content: "";
  display: block;
  width: 40px;
  height: 2px;
  margin: 0 auto 1.4rem;
  border-radius: 2px;
  background: var(--sl-rule);
}

/* 3. PLATES. The SHAPE on every ground; the FILL only on a light one. */
:where(.sl-body).refine-skylight .card, :where(.sl-body).refine-skylight .feature-card, :where(.sl-body).refine-skylight .cat-card, :where(.sl-body).refine-skylight .tier-card:not(.tier-featured), :where(.sl-body).refine-skylight .review-card, :where(.sl-body).refine-skylight .step-card, :where(.sl-body).refine-skylight .faq-item {
  border: 0;
  border-radius: var(--card-radius);
  box-shadow: none;
  padding: clamp(1.6rem, 2.4vw, 2.4rem);
  transition: background var(--sl-ease);
}
:where(.sl-body).refine-skylight:where(:not(.ground-dark)) .card, :where(.sl-body).refine-skylight:where(:not(.ground-dark)) .feature-card, :where(.sl-body).refine-skylight:where(:not(.ground-dark)) .cat-card, :where(.sl-body).refine-skylight:where(:not(.ground-dark)) .tier-card:not(.tier-featured), :where(.sl-body).refine-skylight:where(:not(.ground-dark)) .review-card, :where(.sl-body).refine-skylight:where(:not(.ground-dark)) .step-card, :where(.sl-body).refine-skylight:where(:not(.ground-dark)) .faq-item {
  background: var(--sl-plate);
}
:where(.sl-body).refine-skylight:where(:not(.ground-dark)) .card, :where(.sl-body).refine-skylight:where(:not(.ground-dark)) .feature-card, :where(.sl-body).refine-skylight:where(:not(.ground-dark)) .cat-card, :where(.sl-body).refine-skylight:where(:not(.ground-dark)) .tier-card:not(.tier-featured):hover {
  background: var(--sl-plate-deep);
  transform: none;
  box-shadow: none;
}
/* A plate standing on the tinted beat takes paper, or it disappears into its band. */
:where(.sl-body).refine-skylight:where(:not(.ground-dark)) main > section.section:nth-of-type(even) :is(.card, :where(.sl-body) .feature-card, :where(.sl-body) .cat-card, :where(.sl-body) .review-card, :where(.sl-body) .step-card, :where(.sl-body) .faq-item) {
  background: var(--c-surface);
}

/* 4. CONTROLS ARE FULLY ROUND. Shape only, never ink (T1). */
:where(.sl-body).refine-skylight .btn, :where(.sl-body).refine-skylight .btn-primary, :where(.sl-body).refine-skylight .btn-secondary {
  border-radius: var(--btn-radius);
  font-weight: 700;
  padding-inline: 1.9em;
  transition: background var(--sl-ease), color var(--sl-ease);
}
:where(.sl-body).refine-skylight .btn-secondary { border-width: 1.5px; }

/* 5. THE FAQ IS A LANE SURFACE TOO — DESIGN-LANES.md names `faq` and `policy_expand` explicitly
      because they are the two every lane forgets. */
:where(.sl-body).refine-skylight .faq-item + .faq-item { margin-top: 0.9rem; }
:where(.sl-body).refine-skylight .faq-item summary, :where(.sl-body).refine-skylight .faq-list summary {
  font-weight: 700;
  padding: 1.35rem 1.6rem;
}
:where(.sl-body).refine-skylight:where(:not(.ground-dark)) .faq-item[open] { background: var(--sl-plate-deep); }

/* 6. IMAGERY TAKES THE SAME SOFT CORNER, so the device reaches the photographic half of a page. */
:where(.sl-body).refine-skylight .section figure, :where(.sl-body).refine-skylight .section figure img { border-radius: var(--card-radius); }

/* ── 7. THE BLOCK LIBRARY (T5). Everything above speaks `.section`/`.card`/`.btn` and none of it
      reaches a blueprint home page, which draws through `.bk-*`. Restated in that vocabulary, and
      split the same way: shape unscoped, fill on a light ground only. */
:where(.sl-body).refine-skylight .bk-card, :where(.sl-body).refine-skylight .bk-pillar, :where(.sl-body).refine-skylight .bk-pcard, :where(.sl-body).refine-skylight .bk-tier:not(.bk-feat), :where(.sl-body).refine-skylight .bk-step, :where(.sl-body).refine-skylight .bk-ccard, :where(.sl-body).refine-skylight .bk-ict-card, :where(.sl-body).refine-skylight .bk-fcard, :where(.sl-body).refine-skylight .bk-credcard, :where(.sl-body).refine-skylight .bk-grev-card, :where(.sl-body).refine-skylight .bk-plinth {
  border: 0;
  border-radius: var(--card-radius);
  box-shadow: none;
}
:where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bk-card, :where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bk-pillar, :where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bk-pcard, :where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bk-tier:not(.bk-feat), :where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bk-step, :where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bk-ccard, :where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bk-ict-card, :where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bk-fcard, :where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bk-credcard, :where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bk-grev-card, :where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bk-plinth {
  background: var(--sl-plate);
}
:where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bk-card, :where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bk-pillar, :where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bk-pcard, :where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bk-tier:not(.bk-feat), :where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bk-fcard:hover {
  background: var(--sl-plate-deep);
  transform: none;
  box-shadow: none;
}
:where(.sl-body).refine-skylight .bk-btn, :where(.sl-body).refine-skylight .bk-pill, :where(.sl-body).refine-skylight .bk-chip, :where(.sl-body).refine-skylight .bk-city, :where(.sl-body).refine-skylight .bk-ict-pill, :where(.sl-body).refine-skylight .bk-prose-pill {
  border-radius: var(--btn-radius);
  font-weight: 700;
}
/* A LANE MAY REMOVE A SHADOW. IT MAY NOT REMOVE A BORDER DRAWN AS ONE. Twenty blocks draw an
   outlined control's outline as an inset ring, so a blanket `box-shadow: none` deletes the only
   affordance on a ghost button. The house form, enforced by scripts/ghost-ring.mjs; `:where()`
   contributes no specificity, so this narrows what the rule MATCHES without changing what it
   OUTRANKS. */
:where(.sl-body).refine-skylight :is(.bk-btn, :where(.sl-body) .bk-pill, :where(.sl-body) .bk-chip, :where(.sl-body) .bk-city, :where(.sl-body) .bk-ict-pill, :where(.sl-body) .bk-prose-pill):not(:where(.bk-pill-ghost, :where(.sl-body) .bk-pill-outline, :where(.sl-body) .bk-btn-ghost)) {
  box-shadow: none;
}
:where(.sl-body).refine-skylight .bk-step-art img, :where(.sl-body).refine-skylight .bk-prose-photo img, :where(.sl-body).refine-skylight .bk-cond-ph img, :where(.sl-body).refine-skylight .bk-tiers-art img { border-radius: var(--card-radius); }
/* The featured tier gets the corner and nothing else (T2). */
:where(.sl-body).refine-skylight .bk-tier.bk-feat { border-radius: var(--card-radius); }

/* ── 8. ALL FIVE FAMILIES' CHROME (T5). A blueprint home draws its nav, hero, FAQ and closing band
      from the family template, not from the block library, so none of section 7 reaches them. One
      rule each, so a second client can wear this lane on a different family without their home
      page falling back to the house look. No ground and no ink on the bar: the family picks its
      stock and its logo to match, and a lane that repaints it breaks that pairing (T1). */
:where(.sl-body).refine-skylight :is(.rt-nav, :where(.sl-body) .ed-nav, :where(.sl-body) .bh-nav, :where(.sl-body) .et-nav, :where(.sl-body) .cm-nav, :where(.sl-body) .bl-nav) {
  border-bottom: 1px solid var(--sl-rule);
}
:where(.sl-body).refine-skylight :is(.rt-pill, :where(.sl-body) .ed-pill, :where(.sl-body) .bh-pill, :where(.sl-body) .et-btn, :where(.sl-body) .cm-book, :where(.sl-body) .bl-pill) {
  border-radius: var(--btn-radius);
  font-weight: 700;
}
:where(.sl-body).refine-skylight :is(.rt-fill, :where(.sl-body) .bh-fill):not(:where(.bk-pill-ghost, :where(.sl-body) .bk-pill-outline, :where(.sl-body) .bk-btn-ghost)) {
  box-shadow: none;
}
:where(.sl-body).refine-skylight .rt-outline { border-width: 1.5px; }
/* THE ROW IS THE SUMMARY, NOT THE DISCLOSURE AROUND IT — painting the wrapper puts a plate behind
   a summary that already carries its own fill and its own bottom margin, and every question ships
   as a pale box floating on a slightly darker box. The families' row is `.rt-q` / `.bh-q`. */
:where(.sl-body).refine-skylight :is(.rt-q, :where(.sl-body) .rt-q-flat, :where(.sl-body) .bh-q, :where(.sl-body) .bh-q-flat) {
  border: 0;
  border-radius: var(--card-radius);
  box-shadow: none;
}
:where(.sl-body).refine-skylight:where(:not(.ground-dark)) .rt-q, :where(.sl-body).refine-skylight:where(:not(.ground-dark)) .rt-q-flat, :where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bh-q, :where(.sl-body).refine-skylight:where(:not(.ground-dark)) .bh-q-flat { background: var(--sl-plate); }
:where(.sl-body).refine-skylight:where(:not(.ground-dark)) :is(.rt-qd, :where(.sl-body) .bh-qd)[open] :is(.rt-q, :where(.sl-body) .bh-q) { background: var(--sl-plate-deep); }
:where(.sl-body).refine-skylight :is(.rt-hero-art, :where(.sl-body) .bh-vid) img { border-radius: var(--card-radius); }
:where(.sl-body).refine-skylight .rt-announce { letter-spacing: 0.16em; font-weight: 700; }

/* ── THE PRICE FIGURE ON A LIGHT PAGE ─────────────────────────────────────────────────
   The package card paints its price from its own scoped style, and that style reads a token
   several layers of the cascade rewrite between here and the card. On the dark page this lane was
   written for, every one of those layers happened to land on the same pale metal, so nobody had to
   care which one won. Move the brand to a light ground and the same pale metal lands on a near-
   white card: measured #E0D8C9 on #F6F2EA, 1.27:1, which the contrast check calls effectively
   invisible and it is right — the prices disappeared.
   Rather than guess which layer wins, this names the figure where it is drawn. --cl-metal-ink is
   the lane's warm neutral mixed toward the page's own text colour, so it stays pale on a dark page
   and deepens on a light one; the divider keeps the pale metal, because a hairline is not read. */
:where(.sl-body).refine-clinical-ledger .et.bk-home :is(.bk-pcard, :where(.sl-body) .bk-plinth) :is(.bk-pamt, :where(.sl-body) .et-amt) {
  color: var(--cl-metal-ink);
}

/* ── THE HOW-IT-WORKS BAND ON A LIGHT PAGE ────────────────────────────────────────────
   StepsIconTrio paints itself `--bk-dark` with white text, because it was written as a dark room
   and every page it had ever appeared on was dark. Put it on a warm stone page and it is a
   near-black slab: the owner's words were "way too dark", and he was looking at #141311 sitting in
   the middle of a #E4DED3 page.
   A dark room is a real device and this lane still uses it — but a room is a CHANGE of ground, and
   on a light page the change that reads as considered is a deeper stone, not a hole. The band takes
   the page's own panel stock, its own ink, and the lane's hairline; the pictures and the layout are
   untouched. Scoped to this lane, so no other client's steps band moves. */
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-sit:not(.bk-sit-tex) {
  background: var(--et-bar, #F6F2EA);
  color: var(--et-ink, #22394c);
}
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-sit:not(.bk-sit-tex) :is(h2, :where(.sl-body) h3, :where(.sl-body) p, :where(.sl-body) li, :where(.sl-body) .bk-sit-say, :where(.sl-body) .bk-sit-card) {
  color: var(--et-ink, #22394c);
}
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-sit:not(.bk-sit-tex) h2::after { background: var(--cl-hair-strong); }
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-sit:not(.bk-sit-tex) .bk-sit-card {
  background: transparent; border-color: var(--cl-hair-strong); border-radius: var(--card-radius);
}
/* THE SECOND CONTROL IN THAT BAND IS A GHOST BUTTON, AND A GHOST IS ITS OWN INK. It was drawn in
   white with a white ring, which is correct in a dark room and invisible the moment the room
   turns pale — measured 1.12:1 on the new stock. It takes the band's ink like everything else,
   ring included, so the pair still reads as one filled control and one quiet one. */
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-sit:not(.bk-sit-tex) :is(.bk-sit-ghost, :where(.sl-body) .et-btn-ghost, :where(.sl-body) .bk-btn-ghost, :where(.sl-body) .bk-sit-call) {
  color: var(--et-ink, #22394c);
  box-shadow: inset 0 0 0 1.4px var(--cl-hair-strong);
}

/* ── WHEN THE CHROME IS WARM AND LIGHT ────────────────────────────────────────────────
   This family was drawn for a dark chrome and a dark room, and both were true of every brand it
   had ever carried, so "white" was written wherever ink was needed rather than derived. Point it at
   a warm light neutral — the owner's brief for this client asks for exactly that, "warmer neutrals,
   not bright white, no black" — and 126 pieces of type measure about 1.36:1 in one build: the whole
   footer, the legal line, the section headings in the conditions band, and the accent-coloured
   column heads.
   Each of these is the same fault, so they are corrected together and in one place rather than one
   selector at a time. Scoped to this lane, so no brand with a dark chrome moves.
   `--et-deep-ink` and its two softer weights are written by the template, measured against the
   chrome's own ground; `--cl-metal-ink` is the lane's warm neutral already mixed toward the page's
   own ink. Nothing here is a literal. */
:where(.sl-body).refine-clinical-ledger .et.bk-home .et-footer :is(h4, :where(.sl-body) .et-foot-legal, :where(.sl-body) .et-foot-brand p, :where(.sl-body) small, :where(.sl-body) a) {
  color: var(--et-deep-ink-soft, inherit);
}
:where(.sl-body).refine-clinical-ledger .et.bk-home .et-footer h4 { color: var(--cl-metal-ink); }
/* The filled control sits on coral, so its ink is measured against the CORAL and never against the
   chrome it happens to be standing on. `--et-accent-ink` is the record's own answer for that. */
:where(.sl-body).refine-clinical-ledger .et.bk-home :is(.et-btn-fill, :where(.sl-body) .et-btn-book, :where(.sl-body) .bk-btn-fill) {
  color: var(--et-accent-ink, #22201c);
}
/* THE CONDITIONS BAND is a room like the steps band was, and takes the same correction: the page's
   own panel stock and the page's own ink, rather than white on a dark fill it no longer has. */
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-cond:not(.bk-sit-tex) :is(h2, :where(.sl-body) h3, :where(.sl-body) p, :where(.sl-body) li, :where(.sl-body) .bk-cond-item, :where(.sl-body) .bk-cond-panel) {
  color: var(--et-ink, #3B372F);
}

/* ── AN INTERIOR HERO IS ITS OWN ROOM ─────────────────────────────────────────────────
   The hub and interior hero paints a photograph over a deep fallback and has always been read in
   white, which was true while the page was dark and stayed true by accident. On a warm light page
   the ink follows the PAGE and lands at 1.03:1 on the hero's own navy — the headline, the eyebrow
   and the standfirst all vanish on eight pages at once.
   A band carrying a photograph is not the page: it has its own ground and takes its own ink. The
   veil above the picture is unchanged, so the reading of the band does not move — only the colour
   the words are set in, and only where a photograph or a deep fallback is actually painted. */
:where(.sl-body).refine-clinical-ledger :is(.hero.hero-image-bg, :where(.sl-body) .hub-hero, :where(.sl-body) .section-hero) :is(h1, :where(.sl-body) h2, :where(.sl-body) h3, :where(.sl-body) p, :where(.sl-body) .eyebrow, :where(.sl-body) .subhead, :where(.sl-body) .breadcrumb, :where(.sl-body) .breadcrumb a, :where(.sl-body) li) {
  color: #fff;
}
:where(.sl-body).refine-clinical-ledger :is(.hero.hero-image-bg, :where(.sl-body) .hub-hero, :where(.sl-body) .section-hero) .btn-secondary {
  color: #fff; box-shadow: inset 0 0 0 1.4px rgba(255,255,255,0.6);
}

/* ── THE PAGE NEEDS A BEAT ────────────────────────────────────────────────────────────
   Alternating grounds are a house rule, and the machinery for it keys on `main > section.section`.
   The estate home does not use that markup — its bands are direct children of `.bk-home` — so the
   alternation has never once reached this page. Nobody noticed while the page was dark, because a
   dark page hides a missing beat: every band was the same near-black and read as one slab on
   purpose. Turn the page warm and light and the same flatness is suddenly the loudest thing on it:
   measured after the palette round, the expert band and the packages band beneath it were the
   identical #F8F5EF, two full screens of one colour with a seam somewhere in the middle.
   So the beat is stated here, band by band, in the order the page emits them. Three grounds, not
   two: the page's own bone, the lighter panel objects sit on, and one deeper stone that acts as a
   room. The photographed bands (hero, locations, closing) are their own beat already and are left
   exactly as they are — a picture is a change of ground by itself. */
:where(.sl-body).refine-clinical-ledger .et.bk-home :is(.et-expert, :where(.sl-body) .bk-plinths, :where(.sl-body) .et-faq) { background: var(--et-bar, #F8F5EF); }
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-sit:not(.bk-sit-tex) { background: var(--et-paper, #EFEAE2); }
/* THE ROOM. One band on the page carries real weight, so the eye has somewhere to land between the
   photographs. A deeper stone, not a dark hole — the owner's brief for this brand is warm neutrals
   throughout, so the room is a shade of the same family rather than a change of temperature. */
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-cond:not(.bk-sit-tex) {
  background: var(--et-deep, #E3DCD0);
}
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-cond:not(.bk-sit-tex) :is(h2, :where(.sl-body) h3, :where(.sl-body) p, :where(.sl-body) li, :where(.sl-body) .bk-cond-item, :where(.sl-body) .bk-cond-panel) {
  color: var(--et-deep-ink, #3B372F);
}
/* AND NO TWO PAINTED BANDS IN A ROW MAY SHARE A GROUND. The rules above are the intended beat; this
   is the guard that says so out loud, so a band added later cannot quietly land on its neighbour's
   colour without somebody seeing it in the built page. */
:where(.sl-body).refine-clinical-ledger .et.bk-home .et-expert + * .bk-sit, :where(.sl-body).refine-clinical-ledger .et.bk-home .bk-sit + * .bk-plinths { outline: 0; }

/* ── FOUR THINGS THE OWNER CAUGHT ON THE PREVIEW, 2026-09-10 ──────────────────────────

   1. THE TREATMENT CARD RANGED ITS WORDS LEFT UNDER A CENTRED BAG. The picture is centred, the
      name, the description and the price were not, so every card read as two objects that had been
      pushed together. A product card is one object: the bag, its name, what it is for, its price,
      all on the same axis. */
/* THE TREATMENT CARD IS CENTRED, AND EVERY PART OF IT. Third attempt, and the first two failed for
   the same reason: I moved the words without moving the PRICE. The price sat on the name's line,
   ranged right, so a centred card still had one element pulling to the edge and it read as broken —
   which is exactly what the owner saw. Then I ranged the whole card left, which was not what he
   asked for.
   Centred means centred: the name, the price under it, the description, the button, all on the one
   axis the bag above them already sits on. The price stops being a right-hand column and becomes
   the second line of the card's title, which is where it belongs when the card is symmetrical. */
:where(.sl-body).refine-clinical-ledger .et.bk-home :is(.bk-pcard, :where(.sl-body) .bk-plinth) { text-align: center; }
:where(.sl-body).refine-clinical-ledger .et.bk-home :is(.bk-pcard, :where(.sl-body) .bk-plinth) :is(.bk-pcard-body, :where(.sl-body) .bk-pname, :where(.sl-body) .bk-pdesc, :where(.sl-body) .bk-plabel, :where(.sl-body) .bk-pinc, :where(.sl-body) .bk-ping, :where(.sl-body) .bk-pprice, :where(.sl-body) .bk-pamt, :where(.sl-body) .bk-pbtn) {
  text-align: center;
}
/* the name/price row was a two-column strip; it becomes one centred stack */
:where(.sl-body).refine-clinical-ledger .et.bk-home :is(.bk-pcard, :where(.sl-body) .bk-plinth) :is(.bk-prow, :where(.sl-body) .bk-pname-row, :where(.sl-body) .bk-phead) {
  display: block; text-align: center;
}
/* THE PRICE'S CONTAINER IS WHAT RANGES IT RIGHT, not the price. `.bk-pfig` carries
   `text-align: right`, so setting the figure itself to centre changed nothing visible and the
   price stayed pinned to the card's edge while everything else moved. Named where the alignment
   actually lives, and the price becomes the line under the name rather than a right-hand column. */
/* AND THE REAL MECHANISM, FOUND BY READING THE PAGE RATHER THAN GUESSING AT IT. The card body is a
   TWO-COLUMN GRID — the name in the first track, the price in the second — which is what put them
   on one line and pinned the price to the card's edge. No amount of text-align on either one could
   move it, which is why two attempts changed nothing visible. A centred card is a single column, so
   the grid becomes one track and every child stacks down the middle in source order. */
:where(.sl-body).refine-clinical-ledger .et.bk-home :is(.bk-pcard, :where(.sl-body) .bk-plinth) .bk-pcard-body {
  display: grid; grid-template-columns: 1fr; justify-items: center; align-items: start; row-gap: 10px;
}
:where(.sl-body).refine-clinical-ledger .et.bk-home :is(.bk-pcard, :where(.sl-body) .bk-plinth) :is(.bk-pfig, :where(.sl-body) .bk-pprice) {
  text-align: center; width: 100%;
}
:where(.sl-body).refine-clinical-ledger .et.bk-home :is(.bk-pcard, :where(.sl-body) .bk-plinth) .bk-pprice {
  display: block; width: 100%; margin: 4px 0 0; float: none;
}
:where(.sl-body).refine-clinical-ledger .et.bk-home :is(.bk-pcard, :where(.sl-body) .bk-plinth) .bk-pamt {
  display: inline-block; margin: 0; float: none;
}
:where(.sl-body).refine-clinical-ledger .et.bk-home :is(.bk-pcard, :where(.sl-body) .bk-plinth) :is(.bk-pbook, :where(.sl-body) .bk-pbtn, :where(.sl-body) .bk-pbtn a, :where(.sl-body) a.bk-pbook) {
  margin-inline: auto;
}
:where(.sl-body).refine-clinical-ledger .et.bk-home :is(.bk-pcard, :where(.sl-body) .bk-plinth) :is(figure, :where(.sl-body) .bk-pfig, :where(.sl-body) img) { margin-inline: auto; display: block; }

/* ── A QUIET BUTTON IS STILL A BUTTON ─────────────────────────────────────────────────
   "See all treatments" and the "call" control were drawn as an outline in a hairline weight, on a
   ground only a shade away from the outline itself. The owner: "the button is transparent, so it
   doesn't stand out... it just blends in with the background." A control that a visitor has to
   look for is not a control.
   The quiet control keeps being quiet — it is deliberately the second choice next to the filled
   one — but quiet is a matter of FILL, not of visibility. It gets a real edge in the page's own
   ink rather than a tint of it, and its label takes the ink at full strength. */
/* AND THE EDGE GOES ON THE BUTTON, NOT ON THE STRIP AROUND IT. `.bk-pmore` is the full-width row
   the button sits in — 1,240px of it — so ringing that drew a box across the whole band with the
   words floating in the middle of it. `.bk-pghost` is the control. Name the control. */
:where(.sl-body).refine-clinical-ledger .et.bk-home :is(.bk-pghost, :where(.sl-body) .bk-plearn, :where(.sl-body) .bk-sit-ghost, :where(.sl-body) .et-btn-ghost, :where(.sl-body) .bk-btn-ghost, :where(.sl-body) .bk-pill-ghost, :where(.sl-body) .btn-secondary):not(.et-quietlink) {
  color: var(--et-ink, #3B372F);
  box-shadow: inset 0 0 0 1.6px color-mix(in srgb, var(--et-ink, #3B372F) 62%, transparent);
  background: transparent;
}
:where(.sl-body).refine-clinical-ledger .et.bk-home :is(.bk-pghost, :where(.sl-body) .bk-plearn, :where(.sl-body) .bk-sit-ghost, :where(.sl-body) .et-btn-ghost, :where(.sl-body) .bk-btn-ghost, :where(.sl-body) .bk-pill-ghost, :where(.sl-body) .btn-secondary):not(.et-quietlink):hover {
  box-shadow: inset 0 0 0 1.6px var(--et-ink, #3B372F);
  background: color-mix(in srgb, var(--et-ink, #3B372F) 6%, transparent);
}
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-pmore { box-shadow: none; background: none; }

/* AND THE LITTLE DASHES GO. Adding the missing one was the wrong fix: it made the page carry MORE
   of a mark the owner had already told me read as scattered, and he said so again — "no rhyme, no
   reason, no coordination". He is right, and the reason is the same one that retired the section
   numbers on this system: a dash beside an eyebrow and a rule under a headline are DECORATION.
   They encode nothing. They are not shorter for being consistent, they are just more.
   The eyebrow is already a distinct object — tracked capitals, small, in its own colour — and it
   does not need a line to announce that it is one. So every one of them comes off: the rule before
   the eyebrow, and the short rule the headline draws underneath itself. */
:where(.sl-body).refine-clinical-ledger .et.bk-home :is(.bk-eyebrow-caps, :where(.sl-body) .et-eyebrow, :where(.sl-body) .bk-prail-eyebrow, :where(.sl-body) .bk-prose-eyebrow, :where(.sl-body) .bk-ledger-eyebrow, :where(.sl-body) .bk-faq-eyebrow, :where(.sl-body) .bk-close-eyebrow, :where(.sl-body) .bk-cond-eyebrow, :where(.sl-body) [class*="eyebrow"])::before, :where(.sl-body).refine-clinical-ledger .et.bk-home :is(.bk-eyebrow-caps, :where(.sl-body) .et-eyebrow, :where(.sl-body) [class*="eyebrow"])::after {
  content: none !important;
}
:where(.sl-body).refine-clinical-ledger .et.bk-home :is(.et-band, :where(.sl-body) .bk-cond, :where(.sl-body) .bk-sit, :where(.sl-body) .et-hero, :where(.sl-body) .et-locations, :where(.sl-body) .et-expert, :where(.sl-body) .et-faq, :where(.sl-body) .bk-contact, :where(.sl-body) .bk-plinths) h2::after, :where(.sl-body).refine-clinical-ledger .et.bk-home :is(.et-band, :where(.sl-body) .bk-cond, :where(.sl-body) .bk-sit, :where(.sl-body) .et-hero, :where(.sl-body) .et-locations, :where(.sl-body) .et-expert, :where(.sl-body) .et-faq, :where(.sl-body) .bk-contact, :where(.sl-body) .bk-plinths) h2::before {
  content: none !important;
}

/* ════ STACK IV PREVIEW, ROUND OF 2026-09-10 (evening) ═══════════════════════════════════════ */

/* 1. THE PRICE STILL BLENDED. A warm neutral price on a warm neutral card reads as part of the card
      rather than as the number on it, however far the contrast ratio climbs. The price is the
      second line of the card's title now, so it takes the title's own ink — the deep brand navy the
      treatment name is set in. It reads as one heading with two lines, which is what it is. */
:where(.sl-body).refine-clinical-ledger .et.bk-home :is(.bk-pcard, :where(.sl-body) .bk-plinth) .bk-pamt {
  color: var(--et-title-ink, #093C60);
  font-weight: 600;
}

/* 2. A CONTROL OVER A PHOTOGRAPH IS WHITE, AND THIS TIME IT WINS. The rule that says so was written
      earlier in this file than the rule that gives every quiet control the page's dark ink, so the
      later one won and the call button on the locations band went back to dark type over a dusk
      photograph. Same rule, stated after the general one and one step more specific, so the room
      beats the page wherever a picture is actually painted. */
:where(.sl-body).refine-clinical-ledger .et.bk-home :is(.et-locations, :where(.sl-body) .et-band, :where(.sl-body) .et-hero) :is(.et-btn-ghost, :where(.sl-body) .bk-btn-ghost, :where(.sl-body) .bk-pghost, :where(.sl-body) .bk-pill-ghost, :where(.sl-body) .btn-secondary).et-btn, :where(.sl-body).refine-clinical-ledger .et.bk-home :is(.et-locations, :where(.sl-body) .et-band, :where(.sl-body) .et-hero) :is(.et-btn-ghost, :where(.sl-body) .bk-btn-ghost, :where(.sl-body) .bk-pghost, :where(.sl-body) .bk-pill-ghost, :where(.sl-body) .btn-secondary) {
  color: #fff !important;
  box-shadow: inset 0 0 0 1.6px rgba(255,255,255,0.78) !important;
  background: rgba(255,255,255,0.08) !important;
}
:where(.sl-body).refine-clinical-ledger .et.bk-home :is(.et-locations, :where(.sl-body) .et-band, :where(.sl-body) .et-hero) :is(.et-btn-ghost, :where(.sl-body) .bk-btn-ghost, :where(.sl-body) .bk-pghost):hover {
  background: rgba(255,255,255,0.18) !important;
}

/* 3. THE CONTACT BAND WAS FOUR THINGS THAT DID NOT KNOW ABOUT EACH OTHER. A photograph as a strip
      across the top, the words underneath it on the left, a white card of opening hours floating
      on the right, and inside that card a map tile that had collapsed to nothing but its caption
      ("LONG ISLAND / NY / Open in maps", with no map above it). The owner: "you just threw a couple
      of elements on there, and they don't tie together."
      One composition instead: the photograph fills the left half at full height, and everything a
      visitor needs to get in touch reads down the right half — the heading, the lead, how to reach
      them, the hours, the button. The hours stop being a separate object and become the last part
      of the same column. The second map is dropped: the locations band above already draws the
      service area properly, and a thumbnail of it that renders as a caption is worse than none. */
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-contact {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  column-gap: clamp(32px, 5vw, 80px);
  align-items: stretch;
  padding-block: var(--sec-pad, 110px);
}
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-contact .sl-contact-art {
  grid-column: 1; grid-row: 1 / span 2;
  width: 100%; height: 100%; min-height: 460px; margin: 0; max-width: none;
  object-fit: cover; border-radius: var(--cl-media-radius, 14px);
}
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-contact .sl-contact-art :is(img, :where(.sl-body) picture) {
  width: 100%; height: 100%; object-fit: cover; object-position: 50% 32%; display: block;
}
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-contact .bk-contact-copy { grid-column: 2; grid-row: 1; align-self: end; max-width: 520px; }
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-contact .bk-ccard {
  grid-column: 2; grid-row: 2; align-self: start;
  background: none; box-shadow: none; border: 0; padding: 28px 0 0; margin-top: 28px;
  border-top: 1px solid var(--cl-hair-strong);
  max-width: 520px; width: auto;
}
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-contact .bk-maptile { display: none; }
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-contact .bk-clabel::before { content: none !important; display: none !important; }
:where(.sl-body).refine-clinical-ledger .et.bk-home .bk-contact .bk-clabel { color: var(--et-ink, #3B372F); opacity: 0.72; }
@media (max-width: 860px) {
  :where(.sl-body).refine-clinical-ledger .et.bk-home .bk-contact { grid-template-columns: 1fr; row-gap: 32px; }
  :where(.sl-body).refine-clinical-ledger .et.bk-home .bk-contact .sl-contact-art { grid-row: auto; min-height: 280px; height: 320px; }
  :where(.sl-body).refine-clinical-ledger .et.bk-home .bk-contact :is(.bk-contact-copy, :where(.sl-body) .bk-ccard) { grid-column: 1; grid-row: auto; max-width: none; }
}

/* A BULLET LIST IN A CENTRED BAND STAYS READABLE. Once a stacked split band centres on a phone, a
   bulleted list inside it would centre each line too, and a column of bullets with ragged edges on
   both sides reads as a mistake. The list is centred as a BLOCK and its lines keep one clean left
   edge inside it, so the band is centred and the list is still a list. */
@media (max-width: 760px) {
  :where(.sl-body).sl-shelf :is(.bk-route-split, :where(.sl-body) .bk-composed, :where(.sl-body) .comp-split, :where(.sl-body) .img-text-section, :where(.sl-body) .sec-photo) :is(ul, :where(.sl-body) ol) {
    display: inline-block; text-align: left; margin-inline: auto; max-width: 100%;
  }
  /* …UNLESS THE LIST IS NOT A LIST. This rule is about BULLETS — lines that share a left edge
     because a column of ragged-both-sides bullets reads as a mistake. A list whose items have each
     become a card is not that: each item is its own plate with its own padding, and its text is
     ranged however the plate is. Left-aligning it made the overlay plate centre its title and its
     buttons on a phone while the four cards between them stayed left, which is the thing this rule
     exists to prevent, drawn the other way up. Reported by the owner's own eye, 2026-09-19:
     "center all the copy and bottoms etc" — and on the phone it was still doing neither. */
  :where(.sl-body).sl-shelf .bk-ovl-mid.bk-ovl-cards :is(ul, :where(.sl-body) ol) { display: grid; text-align: inherit; }
}

/* ══════════════════════════════════════════════════════════════════════════════════════════════
   SOFT-CAPSULE — everything is a capsule, the photographs included.

   WHY THIS LANE EXISTS. Measured across the shelf on 2026-09-12: of sixteen lanes, ELEVEN set a
   card radius of 0-2px. The owner, on a mobile IV brand whose business is bachelor parties and
   hangover mornings: "all of our designs and elements are sharp 90 degree squares. every button,
   card etc… it's very popular to round off the corners. even some buttons have full half circles
   on the ends… this is a fun playful website with these harsh stringent angles that looks strict
   and up tight. we need to make it more fun and loose." The rounded end of the axis held three
   lanes — pill-porcelain, skylight, warm-studio — against thirteen square ones.

   WHAT MAKES IT ITS OWN LANE RATHER THAN A FOURTH ROUNDED ONE. The three that round already round
   the CHROME: cards, buttons, inputs. None of them touches the photography, so a 28px card holds a
   picture with four sharp corners and the softness stops at the frame. This lane rounds the media
   too — every band photograph, every card image, every product shot — which is the one corner axis
   the shelf has never varied. Paired with full-capsule buttons and a lozenge for every small label,
   the page reads as a set of soft objects rather than a soft box holding hard ones.

   suits: playful fun loose friendly parties social celebratory upbeat bright informal approachable

   @lane soft-capsule | every shape is a capsule, photographs rounded too, full-pill buttons | suits: playful fun loose friendly parties social celebratory upbeat bright informal approachable relaxed
   ══════════════════════════════════════════════════════════════════════════════════════════════ */
:where(.sl-body).refine-soft-capsule {
  /* The silhouette, stated once. 999px on a control is a true stadium; 26px on a plate is soft
     without becoming a blob at card size; 22px on media is the same curve read at picture scale. */
  --card-radius: 26px;
  --btn-radius: 999px;
  --input-radius: 999px;
  --sc-media-radius: 22px;
  --sc-chip-radius: 999px;
  --sc-air: clamp(4.5rem, 7vw, 7rem);
  /* Separation is a soft plate on a change of stock, never a hard rule. */
  --card-border-width: 0;
  --card-shadow: 0 1px 2px rgba(20,37,26,.05), 0 10px 30px -18px rgba(20,37,26,.28);
  --card-hover-shadow: 0 2px 4px rgba(20,37,26,.07), 0 16px 40px -20px rgba(20,37,26,.34);
}

/* 1. BOTH BEATS DECLARED (T3). A lane that paints only the tinted beat makes a brand whose own
      ground IS a tint alternate tint-with-tint, and page-rules P3 refuses it. Rooms, photo bands
      and the closing ask keep their own grounds and are excluded, exactly as every other lane
      excludes them. */
:where(.sl-body).refine-soft-capsule { background: var(--c-surface); }
:where(.sl-body).refine-soft-capsule:where(:not(.ground-dark)).sections-alternate main > section.section:nth-of-type(odd):not(.sec-room):not(.sec-photo):not(.final-cta):not(.section-hub-cta), :where(.sl-body).refine-soft-capsule:where(:not(.ground-dark)).bands-paper main > section.section:nth-of-type(odd):not(.sec-room):not(.sec-photo):not(.final-cta):not(.section-hub-cta) {
  background: var(--c-surface);
}
:where(.sl-body).refine-soft-capsule:where(:not(.ground-dark)).sections-alternate main > section.section:nth-of-type(even):not(.sec-room):not(.sec-photo):not(.final-cta):not(.section-hub-cta), :where(.sl-body).refine-soft-capsule:where(:not(.ground-dark)).bands-paper main > section.section:nth-of-type(even):not(.sec-room):not(.sec-photo):not(.final-cta):not(.section-hub-cta) {
  background: var(--c-surface-alt);
}

/* 2. THE INTERIOR RENDERER — it speaks .section / .card / .btn. */
:where(.sl-body).refine-soft-capsule .card, :where(.sl-body).refine-soft-capsule .comp-card, :where(.sl-body).refine-soft-capsule .faq-item {
  border-radius: var(--card-radius);
  border-width: var(--card-border-width);
}
:where(.sl-body).refine-soft-capsule .btn, :where(.sl-body).refine-soft-capsule .button, :where(.sl-body).refine-soft-capsule a.btn {
  border-radius: var(--btn-radius);
}
:where(.sl-body).refine-soft-capsule input, :where(.sl-body).refine-soft-capsule select, :where(.sl-body).refine-soft-capsule textarea { border-radius: var(--input-radius); }
:where(.sl-body).refine-soft-capsule textarea { border-radius: var(--card-radius); }

/* 3. THE DEVICE: THE PHOTOGRAPHS ROUND TOO.
      This is the axis no lane on the shelf has ever varied, and it is what stops this reading as a
      recolour of skylight. `figure > img` and the block media classes are named rather than a bare
      `img`, so a logo in the nav and an icon in a trust strip are untouched — a rounded logo is a
      damaged logo. */
:where(.sl-body).refine-soft-capsule figure > img, :where(.sl-body).refine-soft-capsule .sl-hero-pic, :where(.sl-body).refine-soft-capsule .bk-tiers-art, :where(.sl-body).refine-soft-capsule .sl-contact-art, :where(.sl-body).refine-soft-capsule .bk-cond-ph img, :where(.sl-body).refine-soft-capsule .bk-prose-art, :where(.sl-body).refine-soft-capsule .img-text-section img { border-radius: var(--sc-media-radius); }

/* 4. THE BLUEPRINT RENDERER — it speaks .bk-*, and a brand with a page_template never calls the
      interior file on its HOME page. A lane that stops at section 3 dresses the least-read half of
      the site. */
:where(.sl-body).refine-soft-capsule .bk-card, :where(.sl-body).refine-soft-capsule .bk-pcard, :where(.sl-body).refine-soft-capsule .bk-ps, :where(.sl-body).refine-soft-capsule .bk-ecard, :where(.sl-body).refine-soft-capsule .bk-tier, :where(.sl-body).refine-soft-capsule .bk-ledger-card, :where(.sl-body).refine-soft-capsule .bk-cond-panel, :where(.sl-body).refine-soft-capsule .bk-ovl-card, :where(.sl-body).refine-soft-capsule .bk-faq-item, :where(.sl-body).refine-soft-capsule .rt-q, :where(.sl-body).refine-soft-capsule .bk-tiers-art, :where(.sl-body).refine-soft-capsule .bk-cond-panel, :where(.sl-body).refine-soft-capsule .rt-hero-art img, :where(.sl-body).refine-soft-capsule .rt-hero-art img { border-radius: var(--card-radius); }
:where(.sl-body).refine-soft-capsule .bk-btn, :where(.sl-body).refine-soft-capsule .bk-pill, :where(.sl-body).refine-soft-capsule .bk-ev-btn, :where(.sl-body).refine-soft-capsule .rt-pill, :where(.sl-body).refine-soft-capsule .bk-prose-pill { border-radius: var(--btn-radius); }
/* Every small label becomes a lozenge — the chip is the lane's signature at reading size. */
:where(.sl-body).refine-soft-capsule .bk-chip, :where(.sl-body).refine-soft-capsule .bk-city, :where(.sl-body).refine-soft-capsule .bk-ict-pill, :where(.sl-body).refine-soft-capsule .rt-eyebrow { border-radius: var(--sc-chip-radius); }
:where(.sl-body).refine-soft-capsule .bk-eph { border-radius: var(--sc-media-radius) var(--sc-media-radius) 0 0; }

/* 5. NO ELEVATION ON A CONTROL — BUT THE HOUSE FORM, NOT A BARE RESET (T6).
      Twenty blocks draw an outlined button's outline as `box-shadow: inset 0 0 0 1.5px <ink>`
      because an inset ring costs no layout. On those three classes the shadow IS the affordance:
      strip it and the control has no outline, no fill and no underline, and four sample brands
      shipped a home page whose only booking action was an undrawn word. `:where()` is load-bearing
      — it contributes zero specificity, so the exclusion narrows what this matches without
      changing what it outranks. */
:where(.sl-body).refine-soft-capsule :is(.bk-btn, :where(.sl-body) .bk-pill, :where(.sl-body) .bk-chip, :where(.sl-body) .bk-city, :where(.sl-body) .bk-ict-pill, :where(.sl-body) .bk-prose-pill)
  :not(:where(.bk-pill-ghost, :where(.sl-body) .bk-pill-outline, :where(.sl-body) .bk-btn-ghost)) { box-shadow: none; }

/* 6. AIR. A loose page is a page with room in it; this is the one non-corner axis the lane moves,
      and it is what keeps a capsule from reading as a crowded blob. */
:where(.sl-body).refine-soft-capsule main > section.section { padding-block: var(--sc-air); }

/* ══ PREMIUM DESIGN STYLES — PAGE SKINS ══════════════════════════════════════════════════════════
   A premium design style (lib/designStyles.js) restyles seven home-page bands inside their own
   components. These regions dress the REST of that home page — nav, hero, menu, why-choose, about,
   conditions, closing band, footer — so a styled page reads as one site. Every rule here is scoped
   to body.sl-style-<name>, a class Base.astro puts on the HOME page of a premium site only, so no
   other page and no other client can match any of it. One region per style. */

/* ── STYLED PAGES: SHARED FIXES (every style) ─────────────────────────────────────────────────── */
/* Page-level faults the whole-page reviews found on EVERY styled home page (2026-09-14), fixed once
   here so four skins do not fix them four ways. Layout only: no colour, type or shape — those are
   each skin's. Scoped body[class*="sl-style-"], so an unstyled site and an interior page match none. */

/* 1. THE NAV BETWEEN 901 AND 1180px. RetailHome's nav is a space-between flex row that only wraps at
      900, so in this range a long brand name and a seven-link row squeezed until the name broke onto
      two lines, BOOK NOW broke onto two, and the last link dropped alone to a second row at the left.
      Measured natural widths: IV Revival 741px and Redline 885px fit; Kilnyard (6 links, a wordmark)
      needs ~1085px and Saltmarsh (7 links, a wordmark) ~1140px.
      (a) Every styled nav: a three-column grid, name | links | buttons. Name and buttons never wrap;
          the links sit centred in the middle column exactly where space-between put them (equal air
          either side), and if they ever outgrow it they wrap there as a centred block rather than
          pushing a button down. A nav that fits looks as it did.
      (b) A nav too full for one row — six links or more, or five beside a wordmark — takes two rows on
          purpose: name and buttons on the first, the links centred across the whole second. Decided
          from the links the template drew (:has), not from a width guess per brand. */
@media (min-width: 901px) and (max-width: 1180px) {
  :where(.sl-body)[class*="sl-style-"] .rt-nav { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; row-gap: 10px; }
  :where(.sl-body)[class*="sl-style-"] .rt-nav > .rt-brand { grid-column: 1; grid-row: 1; white-space: nowrap; }
  :where(.sl-body)[class*="sl-style-"] .rt-nav > .rt-links { grid-column: 2; grid-row: 1; min-width: 0; justify-content: center; row-gap: 10px; }
  :where(.sl-body)[class*="sl-style-"] .rt-nav > .rt-navr { grid-column: 3; grid-row: 1; flex-wrap: nowrap; }
  :where(.sl-body)[class*="sl-style-"] .rt-nav > .rt-navr > * { white-space: nowrap; }
  :where(.sl-body)[class*="sl-style-"] .rt-nav:has(> .rt-links > a:nth-child(6)), :where(.sl-body)[class*="sl-style-"] .rt-nav:has(> .rt-brand > span):has(> .rt-links > a:nth-child(5)) { grid-template-columns: auto minmax(0, 1fr); padding-bottom: 12px; }
  :where(.sl-body)[class*="sl-style-"] .rt-nav:has(> .rt-links > a:nth-child(6)) > .rt-navr, :where(.sl-body)[class*="sl-style-"] .rt-nav:has(> .rt-brand > span):has(> .rt-links > a:nth-child(5)) > .rt-navr { grid-column: 2; justify-self: end; }
  :where(.sl-body)[class*="sl-style-"] .rt-nav:has(> .rt-links > a:nth-child(6)) > .rt-links, :where(.sl-body)[class*="sl-style-"] .rt-nav:has(> .rt-brand > span):has(> .rt-links > a:nth-child(5)) > .rt-links { grid-column: 1 / -1; grid-row: 2; }
}

/* 2. THE FOOTER ON THE PAGE'S COLUMN LINE. Its padding was clamp(20px, 8vw, 120px), so its columns
      started 11–62px inside the edge every band above shares (1440: 115 vs 80; 1024: 82 vs 20). It
      takes the page grid's own padding instead, the one property every band already reads. */
:where(.sl-body)[class*="sl-style-"] .rt-foot { padding-left: var(--bk-pad); padding-right: var(--bk-pad); }

/* 3. THE CLOSING BAND'S WRAPS. Its headline is often a whole sentence: lines are balanced, and a
      one-letter word no longer hangs at a line's end ("…paper gown. A"). A time range kept breaking
      between its number and its AM/PM ("…Phoenix metro, 9 / AM to 9 PM"). On a styled page RetailHome
      wraps each time range, and each one-letter word with the word after it, in .rt-keep (the text
      itself is unchanged), and .rt-keep holds together here. */
:where(.sl-body)[class*="sl-style-"] .rt-closing h2 { text-wrap: balance; }
:where(.sl-body)[class*="sl-style-"] .rt-closing p { text-wrap: pretty; }
:where(.sl-body)[class*="sl-style-"] .rt-closing .rt-keep { white-space: nowrap; }
/* ── end STYLED PAGES: SHARED FIXES ── */

/* ── PAGE SKIN: lifted ──────────────────────────────────────────────────────────────────────────── */
/* Lifted keeps its approved page (IV Revival, a real client) and its design lane, so it has no skin.
   Its whole-page defects are fixed where they live: the lifted rules of MembershipTiers (crop 901–1279,
   seal under 380), GoogleReviewsWidget and ContactCard (page column 901–1180/1391), PhotoStepCards
   (tablet column 601–900) and CityPillLocations (tablet map 601–900); page-level ones are above. */
/* Two defects the final page review found, neither a change to the approved look:
   - the muted grey on white (nav links, the membership lead) measured 4.32:1, under AA's 4.5; the
     same grey one step darker reads the same and measures ~5.6:1.
   - the hero headline stranded one word ("Metro") on its own line at laptop widths. */
/* A NAVIGATION SET IN THE MUTED INK READS AS SOMETHING THE PAGE IS FINISHED WITH.
   This mixes the menu toward the caption colour, which is a fine instinct on a page whose nav is a
   quiet utility strip and the wrong one on a bar built to be looked at: seven items in a secondary
   grey under a 72px lockup read, in the owner's words, as "cheap afterthoughts" — and it was also
   why the same seven words were grey here and near-black on every other page, since only this bar
   was muted. Held off the brands whose bar has been redrawn (body.sl-nav-tall); every other client
   on this style keeps the muted menu exactly as it was. */
:where(.sl-body).sl-style-lifted:not(.sl-nav-tall) .rt .rt-links a:not(.on), :where(.sl-body).sl-style-lifted .bk-tiers-vip .bk-tiers-sub { color: color-mix(in srgb, var(--bk-muted) 78%, var(--bk-dark)); }
:where(.sl-body).sl-style-lifted .rt .rt-hero h1 { text-wrap: balance; }
:where(.sl-body).sl-style-lifted .rt .rt-hero p { text-wrap: pretty; }
/* ── end PAGE SKIN: lifted ── */

/* ── PAGE SKIN: sticker ─────────────────────────────────────────────────────────────────────────── */
/* The Sticker style's law (styles/sticker/STYLE.md), carried onto the bands of a retail home page that
   have no sticker design of their own: announce bar, nav, hero, trust strip, drip menu, about, why-choose,
   conditions, closing ask and footer. The seven styled bands already draw the law; this makes the rest
   of the page the same hand: display 900 titles set tight and never uppercased, one button language
   (primary = the loud fill with its go-disc, secondary = a paper sticker), 3px ink outlines with solid
   ink offsets and no blur, halftone walls, and every band's content on one 1200px column.
   Every word, link and photograph is the band's own; nothing here adds content or moves a band. The
   inputs are the brand tokens only (--bk-*), mixed here exactly as the styled bands mix them. */
:where(.sl-body).sl-style-sticker .rt.bk-home {
  --sk-primary: var(--bk-primary);
  --sk-accent: var(--bk-accent);
  --sk-ink: var(--bk-dark);
  --sk-tint: var(--bk-tint);
  --sk-paper: var(--bk-paper-base, var(--bk-paper));
  --sk-display: var(--font-heading, sans-serif);
  --sk-body: var(--font-body, sans-serif);
  --sk-sh-xl: 12px 12px 0 0 var(--sk-ink); --sk-sh-lg: 9px 9px 0 0 var(--sk-ink); --sk-sh-md: 6px 6px 0 0 var(--sk-ink);
  --sk-sh-sm: 4px 4px 0 0 var(--sk-ink); --sk-sh-xs: 2px 2px 0 0 var(--sk-ink);
  --sk-primary-field: var(--sk-primary); --sk-accent-field: var(--sk-accent);
  --sk-on-primary: var(--sk-paper); --sk-on-accent: var(--sk-ink); --sk-on-ink: var(--sk-paper);
  --sk-ink-soft: color-mix(in oklab, var(--sk-ink) 80%, var(--sk-tint));
  --sk-dots-wall: color-mix(in oklab, var(--sk-primary) 18%, var(--sk-tint));
  --sk-dots-fill: color-mix(in srgb, var(--sk-paper) 22%, transparent);
  --sk-rule: color-mix(in srgb, var(--sk-ink) 24%, transparent);
  /* ONE COLUMN FOR THE WHOLE PAGE. The styled bands pad with the style's gutter and cap their content
     at 1200px; a house band padding with the page grid's own token sat 40px further out at 1440 and
     31px further out at 1024. Written as padding, so a band's ground still runs edge to edge. */
  --sk-gutter: max(clamp(20px, 5vw, 96px), calc((100% - 1200px) / 2));
  /* mask shapes (only alpha matters): the go-disc arrow, the check tick, the eyebrow sparkle */
  --sk-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath d='M3 10h13M11 4.5 16.5 10 11 15.5' fill='none' stroke='%23fff' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  --sk-tick: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20'%3E%3Cpath d='M3.5 10.5L8 15L16.5 5.5' fill='none' stroke='%23fff' stroke-width='3.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  --sk-spark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 0C13 8 16 11 24 12C16 13 13 16 12 24C11 16 8 13 0 12C8 11 11 8 12 0Z' fill='%23fff'/%3E%3C/svg%3E");
  color: var(--sk-ink);
}
/* THE MID-TONE GUARD, as every styled band declares it: a fill between OKLCH L .52 and .66 cannot carry
   4.5:1 with white or near-black, so it is pushed out of that band and its text flips at .58. */
@supports (color: oklch(from white l c h)) {
  :where(.sl-body).sl-style-sticker .rt.bk-home {
    --sk-primary-field: oklch(from var(--sk-primary) calc(min(l, 0.52) + clamp(0, (l - 0.58) * 1000, 1) * (max(l, 0.66) - min(l, 0.52))) c h);
    --sk-accent-field:  oklch(from var(--sk-accent)  calc(min(l, 0.52) + clamp(0, (l - 0.58) * 1000, 1) * (max(l, 0.66) - min(l, 0.52))) c h);
    --sk-on-primary: oklch(from var(--sk-primary-field) clamp(0.2, (0.58 - l) * 1000, 0.995) 0 h);
    --sk-on-accent:  oklch(from var(--sk-accent-field)  clamp(0.2, (0.58 - l) * 1000, 0.995) 0 h);
  }
}

/* ── THE BUTTON LANGUAGE — one for the whole page ───────────────────────────────────────────────────
   Primary (the booking action): the loud fill, a 900 display label and the accent go-disc at its end.
   Secondary (call, text, menu, memberships): a paper sticker with an ink label. Both are pills with a
   real 3px ink border (no lane or inset ring can remove it) and a hard ink offset that presses in. */
:where(.sl-body).sl-style-sticker .rt.bk-home :is(.rt-pill, :where(.sl-body) .bk-ovl .bk-pill, :where(.sl-body) .bk-pgrid .bk-pill, :where(.sl-body) .bk-cond .bk-pill, :where(.sl-body) .bk-prose-pill) {
  position: relative; box-sizing: border-box;
  display: inline-flex; align-items: center; justify-content: center; gap: 12px;
  width: auto; min-height: 56px; margin: 0; padding: 0 24px;
  border: 3px solid var(--sk-ink); border-radius: 999px;
  background: var(--sk-paper); color: var(--sk-ink); box-shadow: var(--sk-sh-sm);
  font: 800 19px/1 var(--sk-display); letter-spacing: -0.01em !important; text-transform: none; text-decoration: none; white-space: nowrap;
  opacity: 1; transition: translate 120ms ease, box-shadow 120ms ease;
}
:where(.sl-body).sl-style-sticker .rt.bk-home :is(.rt-pill, :where(.sl-body) .bk-ovl .bk-pill, :where(.sl-body) .bk-pgrid .bk-pill, :where(.sl-body) .bk-cond .bk-pill, :where(.sl-body) .bk-prose-pill):hover { translate: 2px 2px; box-shadow: var(--sk-sh-xs); }
:where(.sl-body).sl-style-sticker .rt.bk-home :is(.rt-pill, :where(.sl-body) .bk-ovl .bk-pill, :where(.sl-body) .bk-pgrid .bk-pill, :where(.sl-body) .bk-cond .bk-pill, :where(.sl-body) .bk-prose-pill):active { translate: 4px 4px; box-shadow: 0 0 0 0 var(--sk-ink); }
:where(.sl-body).sl-style-sticker .rt.bk-home :is(.rt-pill, :where(.sl-body) .bk-ovl .bk-pill, :where(.sl-body) .bk-pgrid .bk-pill, :where(.sl-body) .bk-cond .bk-pill, :where(.sl-body) .bk-prose-pill):focus-visible { outline: 3px solid var(--sk-ink); outline-offset: 5px; }
/* primary */
/* THE DISC AND ITS ARROW READ ONE SET OF NUMBERS. The arrow is laid over the disc from the pill's right
   edge, so it only sits in the disc while both agree on the pill's end padding and the disc's size: a
   rule that changes either changes --sk-go-pad / --sk-go-d, never `padding` or `width` directly (a
   bare `right: 17px` stayed put while a squeezed pill pushed its disc off the end, 2026-09-14). */
:where(.sl-body).sl-style-sticker .rt.bk-home :is(.rt-pill.rt-fill, :where(.sl-body) .bk-ovl .bk-pill-fill, :where(.sl-body) .bk-pgrid .bk-pill-fill, :where(.sl-body) .bk-cond .bk-pill-ghost, :where(.sl-body) .bk-prose-pill) {
  --sk-go: var(--sk-accent-field); --sk-on-go: var(--sk-on-accent);
  --sk-go-pad: 8px; --sk-go-d: 40px; --sk-go-a: 22px;
  gap: 18px; padding: 0 var(--sk-go-pad) 0 26px;
  background: var(--sk-primary-field); color: var(--sk-on-primary); box-shadow: var(--sk-sh-md);
  font-weight: 900;
}
:where(.sl-body).sl-style-sticker .rt.bk-home :is(.rt-pill.rt-fill, :where(.sl-body) .bk-ovl .bk-pill-fill, :where(.sl-body) .bk-pgrid .bk-pill-fill, :where(.sl-body) .bk-cond .bk-pill-ghost, :where(.sl-body) .bk-prose-pill):hover { translate: 3px 3px; box-shadow: 3px 3px 0 0 var(--sk-ink); }
:where(.sl-body).sl-style-sticker .rt.bk-home :is(.rt-pill.rt-fill, :where(.sl-body) .bk-ovl .bk-pill-fill, :where(.sl-body) .bk-pgrid .bk-pill-fill, :where(.sl-body) .bk-cond .bk-pill-ghost, :where(.sl-body) .bk-prose-pill):active { translate: 6px 6px; box-shadow: 0 0 0 0 var(--sk-ink); }
/* the go-disc: ::before is the disc, ordered after the label; ::after is the arrow laid over it */
:where(.sl-body).sl-style-sticker .rt.bk-home :is(.rt-pill.rt-fill, :where(.sl-body) .bk-ovl .bk-pill-fill, :where(.sl-body) .bk-pgrid .bk-pill-fill, :where(.sl-body) .bk-cond .bk-pill-ghost, :where(.sl-body) .bk-prose-pill)::before {
  content: ''; order: 1; flex: none; box-sizing: border-box; width: var(--sk-go-d); height: var(--sk-go-d); border-radius: 50%;
  background: var(--sk-go); border: 2.5px solid var(--sk-ink);
}
:where(.sl-body).sl-style-sticker .rt.bk-home :is(.rt-pill.rt-fill, :where(.sl-body) .bk-ovl .bk-pill-fill, :where(.sl-body) .bk-pgrid .bk-pill-fill, :where(.sl-body) .bk-cond .bk-pill-ghost, :where(.sl-body) .bk-prose-pill)::after {
  content: ''; position: absolute; right: calc(var(--sk-go-pad) + (var(--sk-go-d) - var(--sk-go-a)) / 2); top: 50%; width: var(--sk-go-a); height: var(--sk-go-a); translate: 0 -50%; pointer-events: none;
  background: var(--sk-on-go); -webkit-mask: var(--sk-arrow) center / 100% 100% no-repeat; mask: var(--sk-arrow) center / 100% 100% no-repeat;
}
/* ON A PRIMARY FIELD the loud fill would sink into its own ground, so the primary takes the second
   field (the accent) and its disc turns paper; the secondary stays a paper sticker. */
:where(.sl-body).sl-style-sticker .rt.bk-home :is(.rt-closing:not(.rt-onphoto) .rt-pill.rt-fill, :where(.sl-body) .bk-cond-panel .bk-pill-ghost) {
  --sk-go: var(--sk-paper); --sk-on-go: var(--sk-ink);
  background: var(--sk-accent-field); color: var(--sk-on-accent);
}
/* A LABEL THAT STILL CANNOT FIT BREAKS INSIDE ITS PILL. The steps below size every band's booking label
   to one line on the widths phones come in; a longer label on another client's page, or a narrower
   phone, turns to two balanced lines beside its disc instead of pushing the disc off the pill's end.
   The nav's pills are left out: the nav keeps its own one-line rule. */
:where(.sl-body).sl-style-sticker .rt.bk-home :is(.rt-hero-ctas .rt-pill.rt-fill, :where(.sl-body) .rt-closing-cta .rt-pill.rt-fill, :where(.sl-body) .bk-ovl-ctas .bk-pill-fill, :where(.sl-body) .bk-pgrid .bk-pill-fill, :where(.sl-body) .bk-cond .bk-pill-ghost, :where(.sl-body) .bk-prose-pill) {
  white-space: normal; text-wrap: balance; text-align: left; max-width: 100%;
}
@media (prefers-reduced-motion: reduce) {
  :where(.sl-body).sl-style-sticker .rt.bk-home :is(.rt-pill, :where(.sl-body) .bk-ovl .bk-pill, :where(.sl-body) .bk-pgrid .bk-pill, :where(.sl-body) .bk-cond .bk-pill, :where(.sl-body) .bk-prose-pill) { transition: none; }
  :where(.sl-body).sl-style-sticker .rt.bk-home :is(.rt-pill, :where(.sl-body) .bk-ovl .bk-pill, :where(.sl-body) .bk-pgrid .bk-pill, :where(.sl-body) .bk-cond .bk-pill, :where(.sl-body) .bk-prose-pill):is(:hover, :where(.sl-body) :active) { translate: none; }
}

/* ── THE EYEBROW STICKER, for the house bands' small labels ─────────────────────────────────────────
   A paper pill, 3px ink, the small offset, 800 display, tilted -4deg, with the accent dot and its
   sparkle drawn by the label's own pseudo-elements (no markup added). */
:where(.sl-body).sl-style-sticker .rt.bk-home :is(.rt-hero .rt-eyebrow, :where(.sl-body) .bk-prose-eyebrow, :where(.sl-body) .bk-cond-eyebrow) {
  position: relative; box-sizing: border-box;
  display: inline-flex; align-items: center; gap: 10px; width: auto; max-width: 100%;
  margin: 0 0 26px; padding: 8px 18px 8px 9px;
  background: var(--sk-paper); color: var(--sk-ink); border: 3px solid var(--sk-ink); border-radius: 999px; box-shadow: var(--sk-sh-sm);
  font: 800 16px/1.15 var(--sk-display); letter-spacing: 0 !important; text-transform: none; text-shadow: none; opacity: 1;
  backdrop-filter: none; rotate: -4deg;
}
:where(.sl-body).sl-style-sticker .rt.bk-home :is(.rt-hero .rt-eyebrow, :where(.sl-body) .bk-prose-eyebrow, :where(.sl-body) .bk-cond-eyebrow)::before {
  content: ''; flex: none; box-sizing: border-box; width: 26px; height: 26px; border-radius: 50%;
  background: var(--sk-accent-field); border: 2px solid var(--sk-ink);
}
:where(.sl-body).sl-style-sticker .rt.bk-home :is(.rt-hero .rt-eyebrow, :where(.sl-body) .bk-prose-eyebrow, :where(.sl-body) .bk-cond-eyebrow)::after {
  content: ''; position: absolute; left: 15.5px; top: 50%; width: 13px; height: 13px; translate: 0 -50%; pointer-events: none;
  background: var(--sk-on-accent); -webkit-mask: var(--sk-spark) center / 100% 100% no-repeat; mask: var(--sk-spark) center / 100% 100% no-repeat;
}

/* ── ANNOUNCE BAR + NAV ──────────────────────────────────────────────────────────────────────────── */
:where(.sl-body).sl-style-sticker .rt.bk-home > .rt-announce {
  padding: 10px var(--sk-gutter); background: var(--sk-accent-field); color: var(--sk-on-accent);
  border-bottom: 3px solid var(--sk-ink); font: 800 14px/1.25 var(--sk-display); letter-spacing: -0.005em;
}
:where(.sl-body).sl-style-sticker .rt.bk-home > .rt-nav {
  position: relative; z-index: 3; gap: 16px 28px; padding: 14px var(--sk-gutter);
  background: var(--sk-paper); border-bottom: 3px solid var(--sk-ink);
}
/* THE LOCKUP ON AN INK CHIP (the tier chip's device). A lockup drawn for a light bar can carry a
   colour that disappears on white (Redline's lime HYDRATION measured 1.3:1); on the chip every ink
   reads, and the template hands this chip the brand's on-dark lockup when the kit has one. */
:where(.sl-body).sl-style-sticker .rt.bk-home .rt-brand {
  flex: none; display: inline-flex; align-items: center; padding: 5px 14px; border-radius: 12px;
  background: var(--sk-ink); rotate: -2deg; text-decoration: none;
}
:where(.sl-body).sl-style-sticker .rt.bk-home .rt-brand img { height: 50px; }
:where(.sl-body).sl-style-sticker .rt.bk-home .rt-brand span { font: 900 22px/1 var(--sk-display); letter-spacing: -0.02em; color: var(--sk-on-ink); }
:where(.sl-body).sl-style-sticker .rt.bk-home .rt-links { gap: 8px 26px; }
:where(.sl-body).sl-style-sticker .rt.bk-home .rt-links a {
  padding: 6px 0; font: 700 16px/1 var(--sk-display); letter-spacing: -0.01em; color: var(--sk-ink); white-space: nowrap;
  text-decoration: underline 4px transparent; text-underline-offset: 8px;
}
:where(.sl-body).sl-style-sticker .rt.bk-home .rt-links a:hover { text-decoration-color: var(--sk-rule); }
:where(.sl-body).sl-style-sticker .rt.bk-home .rt-links a.on { color: var(--sk-ink); text-decoration-color: var(--sk-primary-field); }
:where(.sl-body).sl-style-sticker .rt.bk-home .rt-navr { flex: none; gap: 14px; }
:where(.sl-body).sl-style-sticker .rt.bk-home .rt-navr .rt-pill { min-height: 48px; padding: 0 20px; font-size: 17px; box-shadow: var(--sk-sh-sm); }
:where(.sl-body).sl-style-sticker .rt.bk-home .rt-navr .rt-pill.rt-fill { padding: 0 22px; }
:where(.sl-body).sl-style-sticker .rt.bk-home .rt-navr .rt-pill.rt-fill::before, :where(.sl-body).sl-style-sticker .rt.bk-home .rt-navr .rt-pill.rt-fill::after { content: none; }
/* 901-1180: the row's arrangement is the shared fix's (STYLED PAGES: SHARED FIXES, 1 — lockup | links |
   pills, never wrapping its ends); the sticker nav only steps its own sizes down to fit it. */
@media (min-width: 901px) and (max-width: 1180px) {
  :where(.sl-body).sl-style-sticker .rt.bk-home > .rt-nav { column-gap: 22px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .rt-links { gap: 8px 20px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .rt-links a { font-size: 15px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .rt-brand img { height: 42px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .rt-navr { gap: 12px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .rt-navr .rt-pill { min-height: 46px; padding: 0 16px; font-size: 16px; }
}
/* just above the phone nav the middle column is at its narrowest: at 901-903 Redline's last link
   dropped alone to a second row. The gaps step in once more so the row holds to the breakpoint. */
@media (min-width: 901px) and (max-width: 960px) {
  :where(.sl-body).sl-style-sticker .rt.bk-home > .rt-nav { column-gap: 16px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .rt-links { gap: 8px 16px; }
}
@media (max-width: 900px) {
  :where(.sl-body).sl-style-sticker .rt.bk-home > .rt-nav { gap: 14px 22px; padding-block: 14px 16px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .rt-links { justify-content: center; gap: 6px 22px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .rt-brand img { height: 40px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .rt-navr .rt-pill { min-height: 44px; padding: 0 16px; font-size: 16px; }
}

/* ── HERO ─────────────────────────────────────────────────────────────────────────────────────────── */
:where(.sl-body).sl-style-sticker .rt.bk-home .rt-hero h1 {
  font-family: var(--sk-display); font-weight: 900; font-size: clamp(44px, 5.6vw, 84px); line-height: 1;
  letter-spacing: -0.035em !important; text-transform: none; text-wrap: balance;
}
:where(.sl-body).sl-style-sticker .rt.bk-home .rt-hero-body { font: 600 21px/1.42 var(--sk-body); max-width: 40ch; text-wrap: pretty; }
:where(.sl-body).sl-style-sticker .rt.bk-home .rt-hero-ctas { gap: 16px; }
/* the photograph IS the band: its copy sits on the page column, the headline takes a hard ink offset
   (graphic depth, not a glow) over the veil that already carries its contrast, and an ink seam closes
   the photograph off from the strip under it */
:where(.sl-body).sl-style-sticker .rt.bk-home .rt-hero--full { padding-inline: var(--sk-gutter); border-bottom: 3px solid var(--sk-ink); }
:where(.sl-body).sl-style-sticker .rt.bk-home .rt-hero--full .rt-hero-copy { max-width: 48rem; padding-inline: 0; }
:where(.sl-body).sl-style-sticker .rt.bk-home .rt-hero--full h1 { color: var(--sk-on-ink); text-shadow: 4px 4px 0 var(--sk-ink); margin-bottom: 22px; }
:where(.sl-body).sl-style-sticker .rt.bk-home .rt-hero--full .rt-hero-body { color: var(--sk-on-ink); font-size: 20px; }
/* THE HEADLINE KEEPS TO THE COPY COLUMN. Over a full-bleed photograph the subject stands at or right of
   centre; on one 768px line "IV Therapy in Boise" ran its last word across her jacket at 1440 and her
   legs at 1024. A measure in the headline's own ch (so it scales with the clamp) keeps the title over the
   same left column as the paragraph and buttons under it, and balance breaks it evenly ("IV Therapy /
   in Boise"), as a phone already does. Phones keep their own measure. */
@media (min-width: 561px) {
  :where(.sl-body).sl-style-sticker .rt.bk-home .rt-hero--full h1 { max-width: min(100%, 11ch); }
}
:where(.sl-body).sl-style-sticker .rt.bk-home .rt-hero-note {
  background: var(--sk-paper); color: var(--sk-ink); border: 3px solid var(--sk-ink); box-shadow: var(--sk-sh-sm);
  font: 800 15px/1.2 var(--sk-display); letter-spacing: -0.005em;
}
@media (max-width: 700px) {
  :where(.sl-body).sl-style-sticker .rt.bk-home .rt-hero--full h1 { font-size: clamp(36px, 10.4vw, 48px); text-shadow: 3px 3px 0 var(--sk-ink); }
  :where(.sl-body).sl-style-sticker .rt.bk-home .rt-hero--full .rt-hero-body { font-size: 17px; line-height: 1.4; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .rt-hero .rt-eyebrow { font-size: 15px; margin-bottom: 16px; }
}
/* PHONE: Book Now takes the row with its disc (the law's full-width primary), the two calls share the row
   under it, so no label is squeezed and all three stay together. */
@media (max-width: 560px) {
  :where(.sl-body).sl-style-sticker .rt.bk-home .rt-hero-ctas { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 12px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .rt-hero-ctas .rt-pill { flex: none; min-width: 0; min-height: 52px; padding: 0 12px; font-size: 17px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .rt-hero-ctas .rt-pill.rt-fill { grid-column: 1 / -1; justify-content: space-between; --sk-go-pad: 7px; padding: 0 var(--sk-go-pad) 0 22px; font-size: 20px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .rt-hero-ctas > .rt-pill:not(.rt-fill):last-child:nth-child(2) { grid-column: 1 / -1; }
}
/* SMALL PHONE (360x640): Call Now and Text Now ended 11px under the first screen. The hero's air is
   taken in, never its words or its buttons: tighter eyebrow and headline spacing, the lede one size
   down, and 48px buttons (still a full touch target). */
@media (max-width: 400px) {
  :where(.sl-body).sl-style-sticker .rt.bk-home .rt-hero .rt-eyebrow { margin-bottom: 10px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .rt-hero--full h1 { margin-bottom: 14px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .rt-hero--full .rt-hero-body { font-size: 16px; line-height: 1.36; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .rt-hero-ctas { gap: 10px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .rt-hero-ctas .rt-pill { min-height: 48px; }
}

/* ── TRUST STRIP ──────────────────────────────────────────────────────────────────────────────────── */
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-cs { padding: 32px var(--sk-gutter); background-color: var(--sk-paper); border-bottom: 3px solid var(--sk-ink); }
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-cs-item { gap: 14px; font: 800 18px/1.2 var(--sk-display); letter-spacing: -0.01em; color: var(--sk-ink); }
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-cs-item > span {
  flex: none; box-sizing: border-box; display: grid; place-items: center; width: 52px; height: 52px; border-radius: 50%;
  background: var(--sk-accent-field); border: 3px solid var(--sk-ink); box-shadow: var(--sk-sh-sm);
}
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-cs-item > span svg { width: 26px; height: 26px; fill: var(--sk-on-accent); }
/* four across under 1180px: the discs and the gutter step down so a hyphenated label
   ("Physician-Reviewed") keeps its word whole instead of breaking at the hyphen */
@media (min-width: 901px) and (max-width: 1180px) {
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-cs { --bk-rowgap: 20px !important; column-gap: 20px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-cs-item { gap: 12px; font-size: 15.5px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-cs-item > span { width: 44px; height: 44px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-cs-item > span svg { width: 22px; height: 22px; }
}
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-cs-l-rule { border-top: 0; }
/* a phone stacks the strip one per line: the discs line up down one edge of a centred column instead of
   each pair centring on its own and leaving four ragged left edges */
@media (max-width: 520px) {
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-cs { padding-inline: max(var(--sk-gutter), calc((100% - 330px) / 2)); row-gap: 14px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-cs-l-row .bk-cs-item { justify-content: flex-start; }
}
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-cs-l-rule .bk-cs-item + .bk-cs-item { border-color: var(--sk-rule); }

/* ── THE WALL, for every house band that stands on the page ground ───────────────────────────────── */
:where(.sl-body).sl-style-sticker .rt.bk-home :is(.bk-pgrid, :where(.sl-body) .bk-prose:not(.bk-prose-l-feature), :where(.sl-body) .bk-cond) {
  background-color: var(--bk-paper);
  background-image: radial-gradient(circle, var(--sk-dots-wall) 1.8px, transparent 2.4px);
  background-size: 24px 24px; background-position: 12px 12px;
  padding: 120px var(--sk-gutter) 132px;
}
@media (max-width: 860px) {
  :where(.sl-body).sl-style-sticker .rt.bk-home :is(.bk-pgrid, :where(.sl-body) .bk-prose, :where(.sl-body) .bk-cond) { padding-top: 96px; padding-bottom: 104px; }
}
/* the section title on the wall: display 900 at page scale, tight, never uppercased */
:where(.sl-body).sl-style-sticker .rt.bk-home :is(.bk-pgrid-panel > h2, :where(.sl-body) .bk-prose-head > h2, :where(.sl-body) .bk-ovl-card > h2, :where(.sl-body) .bk-cond-panel > h2, :where(.sl-body) .rt-closing > h2) {
  font-family: var(--sk-display); font-weight: 900; font-size: 54px; line-height: 1.02;
  letter-spacing: -0.035em !important; text-transform: none; text-wrap: balance; color: var(--sk-ink);
}
@media (max-width: 1180px) {
  :where(.sl-body).sl-style-sticker .rt.bk-home :is(.bk-pgrid-panel > h2, :where(.sl-body) .bk-prose-head > h2, :where(.sl-body) .bk-cond-panel > h2, :where(.sl-body) .rt-closing > h2) { font-size: 46px; }
}
@media (max-width: 560px) {
  :where(.sl-body).sl-style-sticker .rt.bk-home :is(.bk-pgrid-panel > h2, :where(.sl-body) .bk-prose-head > h2, :where(.sl-body) .bk-ovl-card > h2, :where(.sl-body) .bk-cond-panel > h2, :where(.sl-body) .rt-closing > h2) { font-size: 38px; }
}

/* ── THE DRIP MENU ────────────────────────────────────────────────────────────────────────────────── */
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-pgrid-panel { max-width: 1200px; margin-inline: auto; padding: 0; border-radius: 0; background: transparent; box-shadow: none; }
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-pgrid-panel > h2 { margin: 0 var(--bk-mi, auto); }
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-pgrid-fine { max-width: 46ch; margin: 18px var(--bk-mi, auto) 64px; font: 600 21px/1.4 var(--sk-body); color: var(--sk-ink-soft); text-wrap: pretty; }
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-pgrid-cells { --bk-rowgap: 36px !important; gap: 44px 36px; }
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-pcard {
  padding: 30px 24px 28px; background: var(--sk-paper); border: 3px solid var(--sk-ink); border-radius: 22px; box-shadow: var(--sk-sh-lg);
}
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-pnm { margin: 0 0 16px; font: 800 22px/1.12 var(--sk-display); letter-spacing: -0.01em !important; text-transform: none; color: var(--sk-ink); text-wrap: balance; }
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-pbody { margin: 0 0 24px; font: 600 18px/1.35 var(--sk-body); color: var(--sk-ink-soft); text-wrap: pretty; }
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-pcard > .bk-pill { align-self: center; margin: auto auto 0; }
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-pgrid-l-menu .bk-pcard > .bk-pill, :where(.sl-body).sl-style-sticker .rt.bk-home .bk-pgrid-l-counter .bk-pcard > .bk-pill { align-self: center; margin: 0 0 0 clamp(18px, 2.4vw, 34px); }
/* promo tiles: a primary-field sticker, never a gradient */
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-promo {
  background-color: var(--sk-primary-field); background-image: radial-gradient(circle, var(--sk-dots-fill) 1.4px, transparent 1.9px); background-size: 18px 18px;
  color: var(--sk-on-primary); border: 3px solid var(--sk-ink); border-radius: 22px; box-shadow: var(--sk-sh-lg);
}
:where(.sl-body).sl-style-sticker .rt.bk-home :is(.bk-promo-title, :where(.sl-body) .bk-promo-big) { font-family: var(--sk-display); font-weight: 900; letter-spacing: -0.02em !important; text-transform: none; }
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-promo-body { font: 600 17px/1.45 var(--sk-body); opacity: 1; }
@media (max-width: 1000px) {
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-pgrid-cells > * { flex-basis: calc((100% - 36px) / 2); }
}
/* PHONE: the card lies on its side — the bag at the left, its name, line and button beside it — so six
   drips are a short menu rather than 3,700px of tall portraits. Every word and the bag stay. */
@media (max-width: 640px) {
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-pgrid-cells { gap: 28px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-pgrid-cells > *, :where(.sl-body).sl-style-sticker .rt.bk-home .bk-pgrid-cells[data-cols] > * { flex-basis: 100%; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-pgrid-l-grid .bk-pcard:has(> img) {
    display: grid; grid-template-columns: 80px minmax(0, 1fr); grid-template-rows: auto auto 1fr; column-gap: 16px;
    padding: 22px 18px 22px 14px; text-align: left; box-shadow: var(--sk-sh-md);
  }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-pgrid-l-grid .bk-pcard:has(> img) > img { grid-column: 1; grid-row: 1 / span 3; align-self: center; width: 80px; height: auto; max-height: 140px; margin: 0; }
  /* no balancing here: balanced, "The Warm-Up - $125" broke at the drip's own hyphen */
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-pgrid-l-grid .bk-pcard:has(> img) > .bk-pnm { grid-column: 2; margin: 0 0 8px; font-size: 20px; text-wrap: pretty; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-pgrid-l-grid .bk-pcard:has(> img) > .bk-pbody { grid-column: 2; margin: 0 0 16px; font-size: 16px; text-align: left; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-pgrid-l-grid .bk-pcard:has(> img) > .bk-pill { grid-column: 2; justify-self: start; align-self: end; margin: 0; min-height: 50px; font-size: 18px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-pgrid-fine { margin-bottom: 44px; font-size: 19px; }
}
/* NARROW PHONES (320-374): the bag and the gap give the title column back its room, so a drip's name
   and price hold one line ("The Warm-Up - $125" broke before its dash at 360), and the booking pill
   steps its end in so its disc stays inside the card. */
@media (max-width: 374px) {
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-pgrid-l-grid .bk-pcard:has(> img) { grid-template-columns: 64px minmax(0, 1fr); column-gap: 12px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-pgrid-l-grid .bk-pcard:has(> img) > img { width: 64px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-pgrid-l-grid .bk-pcard:has(> img) > .bk-pnm { font-size: 18px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-pgrid-l-grid .bk-pcard:has(> img) > .bk-pill { gap: 12px; --sk-go-pad: 6px; padding: 0 var(--sk-go-pad) 0 18px; }
}
@media (max-width: 350px) {
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-pgrid-l-grid .bk-pcard:has(> img) { grid-template-columns: 56px minmax(0, 1fr); padding: 20px 14px 20px 12px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-pgrid-l-grid .bk-pcard:has(> img) > img { width: 56px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-pgrid-l-grid .bk-pcard:has(> img) > .bk-pnm { font-size: 17px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-pgrid-l-grid .bk-pcard:has(> img) > .bk-pill { min-height: 48px; font-size: 17px; gap: 10px; --sk-go-d: 36px; --sk-go-a: 20px; padding-left: 14px; }
}

/* ── ABOUT ────────────────────────────────────────────────────────────────────────────────────────── */
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-prose-in { max-width: 1200px; margin-inline: auto; }
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-prose-has-photo .bk-prose-in { gap: 72px; align-items: center; }
/* the photo sticker: a paper kiss-cut, 3px ink, the card offset, four degrees off true; the corner radii
   match (18 outside, 9 on the picture), so no wedge of ground shows at a corner */
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-prose-photo {
  align-self: center; margin: 0; padding: 10px; box-sizing: border-box;
  background: var(--sk-paper); border: 3px solid var(--sk-ink); border-radius: 18px; box-shadow: var(--sk-sh-lg); rotate: -4deg;
}
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-prose-photo img { height: auto; min-height: 0; aspect-ratio: 1 / 1; border-radius: 9px; }
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-prose-head > h2 { display: block; margin: 0 0 24px; padding: 0; border-radius: 0; background: transparent; max-width: 18ch; }
/* one measure in pixels for the lead and the paragraph under it: in ch the 19px paragraph ran 80px
   short of the 21px lead, so the column had two right edges and "buy." sat alone on its last line */
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-prose-body p { margin: 0 0 18px; font: 400 19px/1.55 var(--sk-body); color: var(--sk-ink-soft); max-width: 640px; text-wrap: pretty; }
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-prose-body p.bk-prose-lead { font: 600 21px/1.45 var(--sk-body); color: var(--sk-ink); }
/* ONE LEFT EDGE BESIDE THE PHOTOGRAPH. The page's centring rule reaches the heading and the eyebrow
   of a band it does not know is composed, so they centred over two left-ranged paragraphs. Beside the
   picture the column ranges left; on a phone the page's own rule takes the heading back to centre. */
@media (min-width: 761px) {
  :where(.sl-body).sl-style-sticker.sl-style-sticker .rt.bk-home .bk-prose.bk-prose-has-photo .bk-prose-copy > .bk-prose-head, :where(.sl-body).sl-style-sticker.sl-style-sticker .rt.bk-home .bk-prose.bk-prose-has-photo .bk-prose-copy > .bk-prose-head > :is(h2, :where(.sl-body) .bk-prose-eyebrow) { text-align: left !important; margin-inline: 0; }
}
@media (max-width: 900px) {
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-prose-has-photo .bk-prose-in { gap: 56px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-prose-photo { width: min(100%, 520px); justify-self: start; rotate: -3deg; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-prose-photo img { aspect-ratio: 3 / 2; }
}
/* 561-900, STACKED: ONE COLUMN, ONE PAIR OF EDGES. The photograph stood 520px wide pinned to the left
   while the paragraphs ran on to their 640px measure and the heading further still, so the column had
   three right edges and an empty strip of wall beside the picture (768, 820). Photo, heading and
   paragraphs now share the text's own 640px measure, centred as the tablet Locations copy above it is. */
@media (min-width: 561px) and (max-width: 900px) {
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-prose-has-photo .bk-prose-in { max-width: 640px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-prose-has-photo .bk-prose-photo { width: 100%; justify-self: stretch; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-prose-has-photo .bk-prose-head > h2 { max-width: 100%; }
}
@media (max-width: 760px) {
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-prose-head { text-align: center; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-prose-head > h2 { margin-inline: auto; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-prose-photo { justify-self: center; }
}
@media (max-width: 560px) {
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-prose-photo { padding: 7px; border-radius: 15px; box-shadow: var(--sk-sh-md); }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-prose-photo img { border-radius: 8px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-prose-body p { font-size: 17px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-prose-body p.bk-prose-lead { font-size: 19px; }
}

/* ── WHY CHOOSE (the photograph with a card on it) ───────────────────────────────────────────────── */
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-ovl { min-height: 600px; padding: 112px var(--sk-gutter); border-block: 3px solid var(--sk-ink); }
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-ovl-card {
  /* THE CARD STOPS SHORT OF HER FACE at every width the two overlap. The photograph fills the band's
     width, so it cannot be slid; the card takes at most 56% of the column, which keeps a subject right
     of centre clear of it from 1440 down to the stacked phone layout (it covered her face at 1024-1100). */
  box-sizing: border-box; max-width: min(640px, 56%); padding: 46px 46px 44px;
  background: var(--sk-paper); border: 3px solid var(--sk-ink); border-radius: 28px; box-shadow: var(--sk-sh-xl);
}
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-ovl-card > h2 { margin: 0 0 14px; font-size: 48px; }
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-ovl-card > p { font: 600 19px/1.45 var(--sk-body); color: var(--sk-ink-soft); }
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-ovl-card > ul { list-style: none; margin: 18px 0 30px; padding: 0; }
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-ovl-card li {
  position: relative; margin: 0; padding: 15px 0 15px 54px; border-top: 2px dashed var(--sk-rule);
  font: 600 18px/1.35 var(--sk-body); color: var(--sk-ink);
}
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-ovl-card li:first-child { border-top: 0; padding-top: 4px; }
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-ovl-card li b { font: 800 20px/1.15 var(--sk-display); letter-spacing: -0.01em !important; color: var(--sk-ink); }
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-ovl-card li span { margin-top: 5px; font: 400 17px/1.42 var(--sk-body); color: var(--sk-ink-soft); opacity: 1; }
/* the check disc and its tick */
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-ovl-card li::before, :where(.sl-body).sl-style-sticker .rt.bk-home .bk-cond-panel li::before {
  content: ''; position: absolute; left: 0; top: 12px; box-sizing: border-box; width: 34px; height: 34px; border-radius: 50%;
  background: var(--sk-accent-field); border: 2.5px solid var(--sk-ink); box-shadow: var(--sk-sh-xs);
}
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-ovl-card li::after, :where(.sl-body).sl-style-sticker .rt.bk-home .bk-cond-panel li::after {
  content: ''; position: absolute; left: 8px; top: 20px; width: 18px; height: 18px; pointer-events: none;
  background: var(--sk-on-accent); -webkit-mask: var(--sk-tick) center / 100% 100% no-repeat; mask: var(--sk-tick) center / 100% 100% no-repeat;
}
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-ovl-card li:first-child::before { top: 1px; }
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-ovl-card li:first-child::after { top: 9px; }
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-ovl-ctas { gap: 16px 14px; }
/* 761-1180: the narrower card tightens */
@media (min-width: 761px) and (max-width: 1180px) {
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-ovl-card { padding: 38px 34px 36px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-ovl-card > h2 { font-size: 40px; }
  /* the booking row stacks on purpose, as the ticket's does under 1280: Book Now alone, the two calls
     sharing the row under it — never one button left over on a line of its own. The two calls keep
     their own width, as the ticket's do: stretched into two equal columns they measured 214px each
     at 1024 beside a 188px Book Now, so the secondaries out-sized the primary. A label too long for the
     card still breaks inside its pill (the tracks may shrink) rather than leaving the card. */
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-ovl-ctas { display: grid; grid-template-columns: repeat(2, minmax(0, max-content)); justify-content: start; gap: 14px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-ovl-ctas .bk-pill { justify-self: start; min-width: 0; max-width: 100%; min-height: 52px; padding: 0 20px; font-size: 17px; white-space: normal; text-wrap: balance; text-align: center; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-ovl-ctas .bk-pill-fill { grid-column: 1 / -1; justify-self: start; --sk-go-pad: 7px; padding: 0 var(--sk-go-pad) 0 24px; font-size: 19px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-ovl-ctas > .bk-pill:not(.bk-pill-fill):last-child:nth-child(2) { grid-column: 1 / -1; justify-self: start; }
}
/* just above the stacked layout 56% of the column is under 420px: the title took three lines and one
   word hung alone. The photograph's subject sits further right at these widths, so the card takes
   more of the column and a little less padding (stepped, so it never reaches her face). */
@media (min-width: 761px) and (max-width: 900px) {
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-ovl-card { max-width: 58%; padding: 32px 28px 30px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-ovl-card > h2 { font-size: 38px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-ovl-card li b { text-wrap: balance; }
}
@media (min-width: 761px) and (max-width: 820px) {
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-ovl-card { max-width: 60%; }
}
/* 760 AND BELOW: THE PHOTOGRAPH STANDS ABOVE THE CARD. Overlaid, the card ran edge to edge and left the
   photograph two slivers; here the picture takes the top of the band at its own shape (a landscape
   library frame) and the card crosses its bottom edge onto the wall. */
@media (max-width: 760px) {
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-ovl {
    display: block; min-height: 0; padding: calc(66.6vw - 44px) var(--sk-gutter) 84px;
    background-color: var(--bk-paper); background-size: 100% auto; background-position: 50% 0 !important;
  }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-ovl-card { position: relative; max-width: none; padding: 30px 22px 30px; border-radius: 24px; box-shadow: var(--sk-sh-lg); }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-ovl-card > h2 { font-size: 36px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-ovl-card li { padding-left: 48px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-ovl-card li b { font-size: 19px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-ovl-card li span { font-size: 16px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-ovl-card li::before { width: 30px; height: 30px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-ovl-card li::after { left: 7px; top: 18px; width: 16px; height: 16px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-ovl-card li:first-child::after { top: 7px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-ovl-ctas { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 12px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-ovl-ctas .bk-pill { min-width: 0; min-height: 52px; padding: 0 12px; font-size: 17px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-ovl-ctas .bk-pill-fill { grid-column: 1 / -1; justify-content: space-between; --sk-go-pad: 7px; padding: 0 var(--sk-go-pad) 0 22px; font-size: 20px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-ovl-ctas > .bk-pill:not(.bk-pill-fill):last-child:nth-child(2) { grid-column: 1 / -1; }
}
/* no photograph: the card is the band's copy on the wall, as the block draws it */
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-ovl-noart { min-height: 0; border-block: 0; background-color: var(--bk-paper); }
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-ovl-noart .bk-ovl-card { max-width: 1200px; margin-inline: auto; }

/* ── CONDITIONS: one primary-field poster on the wall ────────────────────────────────────────────── */
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-cond-panel {
  position: relative; box-sizing: border-box; max-width: 1200px; width: 100%; margin-inline: auto; padding: 56px 56px 60px;
  background-color: var(--sk-primary-field); background-image: radial-gradient(circle, var(--sk-dots-fill) 1.4px, transparent 1.9px); background-size: 18px 18px;
  color: var(--sk-on-primary); border: 3px solid var(--sk-ink); border-radius: 28px; box-shadow: var(--sk-sh-xl);
  text-align: left;
}
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-cond-beside { column-gap: 48px; }
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-cond-panel > h2 { margin: 0 0 16px; color: var(--sk-on-primary); text-align: left; }
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-cond-lead { max-width: 40ch; margin: 0 0 34px; font: 600 21px/1.42 var(--sk-body); color: var(--sk-on-primary); text-wrap: pretty; }
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-cond-panel > ul { gap: 0 48px; margin: 0 0 40px; }
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-cond-panel li {
  position: relative; padding: 14px 0 14px 52px; border-top: 2px dashed color-mix(in srgb, var(--sk-on-primary) 34%, transparent);
  font: 600 19px/1.35 var(--sk-body); color: var(--sk-on-primary); text-align: left;
}
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-cond-l-panel .bk-cond-panel li:nth-child(-n+2), :where(.sl-body).sl-style-sticker .rt.bk-home .bk-cond-l-rows .bk-cond-panel li:first-child { border-top: 0; }
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-cond-l-rows .bk-cond-panel li:last-child { border-bottom: 0; }
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-cond-panel li::before { top: 11px; }
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-cond-panel li::after { top: 19px; }
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-cond-l-chips .bk-cond-panel li { padding: 10px 16px; border: 2.5px solid var(--sk-ink); border-radius: 999px; background: var(--sk-paper); color: var(--sk-ink); box-shadow: var(--sk-sh-xs); line-height: 1.1; }
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-cond-l-chips .bk-cond-panel li::before, :where(.sl-body).sl-style-sticker .rt.bk-home .bk-cond-l-chips .bk-cond-panel li::after { content: none; }
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-cond-ctas { gap: 16px 18px; justify-content: flex-start; }
:where(.sl-body).sl-style-sticker .rt.bk-home .bk-cond-ph img { border: 3px solid var(--sk-ink); border-radius: 22px; box-shadow: var(--sk-sh-lg); }
@media (max-width: 900px) {
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-cond-panel > ul { grid-template-columns: minmax(0, 1fr); }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-cond-l-panel .bk-cond-panel li:nth-child(2) { border-top: 2px dashed color-mix(in srgb, var(--sk-on-primary) 34%, transparent); }
}
@media (max-width: 760px) {
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-cond-panel { padding: 34px 24px 38px; border-radius: 24px; box-shadow: var(--sk-sh-lg); text-align: center; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-cond-panel > h2 { text-align: center; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-cond-lead { margin-inline: auto; font-size: 19px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-cond-panel li { font-size: 17px; padding-left: 46px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-cond-panel li::before { width: 30px; height: 30px; top: 11px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-cond-panel li::after { left: 7px; top: 18px; width: 16px; height: 16px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-cond-ctas { display: grid; grid-template-columns: minmax(0, 1fr); gap: 14px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-cond-ctas .bk-pill { min-height: 52px; font-size: 18px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-cond-ctas .bk-pill-ghost { justify-content: space-between; padding-left: 22px; }
}
/* NARROW PHONES: "Make an Appointment" with its disc needed 283px in a 260px pill at 360, so the disc
   hung off the pill's end. The poster's side padding and the pair's label size step down together
   (both pills, so the two still read as one pair) and the disc keeps its place at the pill's end. */
@media (max-width: 400px) {
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-cond-panel { padding-inline: 20px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-cond-ctas .bk-pill { font-size: 16px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-cond-ctas .bk-pill-ghost { gap: 10px; --sk-go-pad: 6px; padding: 0 var(--sk-go-pad) 0 16px; }
}
@media (max-width: 350px) {
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-cond-panel { padding-inline: 16px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-cond-ctas .bk-pill { font-size: 15.5px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .bk-cond-ctas .bk-pill-ghost { gap: 8px; --sk-go-d: 36px; --sk-go-a: 20px; padding-left: 14px; }
}

/* ── CLOSING ASK: a primary-field colour block between two ink seams ─────────────────────────────── */
:where(.sl-body).sl-style-sticker .rt.bk-home .rt-closing:not(.rt-onphoto) {
  padding: 116px var(--sk-gutter) 124px;
  background-color: var(--sk-primary-field); background-image: radial-gradient(circle, var(--sk-dots-fill) 1.4px, transparent 1.9px); background-size: 18px 18px;
  color: var(--sk-on-primary); border-block: 3px solid var(--sk-ink);
}
:where(.sl-body).sl-style-sticker .rt.bk-home .rt-closing > h2 { max-width: 20ch; margin: 0 auto 22px; }
:where(.sl-body).sl-style-sticker .rt.bk-home .rt-closing:not(.rt-onphoto) > h2 { color: var(--sk-on-primary); }
:where(.sl-body).sl-style-sticker .rt.bk-home .rt-closing .rt-closing-line { margin: 0 auto 10px; font: 800 22px/1.3 var(--sk-display); letter-spacing: -0.01em; opacity: 1; }
:where(.sl-body).sl-style-sticker .rt.bk-home .rt-closing p:not(.rt-closing-line) { max-width: 44ch; font: 600 20px/1.45 var(--sk-body); opacity: 1; text-wrap: pretty; }
:where(.sl-body).sl-style-sticker .rt.bk-home .rt-closing-cta { gap: 16px 18px; margin-top: 38px; }
@media (max-width: 860px) {
  :where(.sl-body).sl-style-sticker .rt.bk-home .rt-closing:not(.rt-onphoto) { padding-top: 92px; padding-bottom: 100px; }
}
@media (max-width: 560px) {
  :where(.sl-body).sl-style-sticker .rt.bk-home .rt-closing .rt-closing-line { font-size: 19px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .rt-closing p:not(.rt-closing-line) { font-size: 17px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .rt-closing-cta { display: grid; grid-template-columns: minmax(0, 1fr); max-width: 340px; margin-inline: auto; gap: 14px; }
  :where(.sl-body).sl-style-sticker .rt.bk-home .rt-closing-cta .rt-pill.rt-fill { justify-content: space-between; padding-left: 22px; }
}

/* ── FOOTER: the ink wall at the foot of the page, on the same column ────────────────────────────── */
:where(.sl-body).sl-style-sticker .rt.bk-home > .rt-foot { padding: 88px var(--sk-gutter) 36px; background: var(--sk-ink); color: color-mix(in srgb, var(--sk-on-ink) 84%, transparent); }
:where(.sl-body).sl-style-sticker .rt.bk-home .rt-foot-cols { max-width: 1200px; margin-inline: auto; gap: 48px; padding-bottom: 56px; }
:where(.sl-body).sl-style-sticker .rt.bk-home .rt-foot h4 { margin: 0 0 18px; font: 800 20px/1.1 var(--sk-display); letter-spacing: -0.01em !important; text-transform: none; color: var(--sk-on-ink); }
:where(.sl-body).sl-style-sticker .rt.bk-home .rt-foot p { max-width: 42ch; font: 400 16px/1.65 var(--sk-body); }
:where(.sl-body).sl-style-sticker .rt.bk-home .rt-foot li { margin-bottom: 10px; font: 600 16px/1.35 var(--sk-body); }
:where(.sl-body).sl-style-sticker .rt.bk-home .rt-foot a { text-decoration: underline 3px transparent; text-underline-offset: 5px; }
:where(.sl-body).sl-style-sticker .rt.bk-home .rt-foot a:hover { color: var(--sk-on-ink); text-decoration-color: var(--sk-accent-field); }
:where(.sl-body).sl-style-sticker .rt.bk-home .rt-legal { max-width: 1200px; margin-inline: auto; padding-top: 22px; border-top: 2px dashed color-mix(in srgb, var(--sk-on-ink) 22%, transparent); font-size: 13px; line-height: 1.5; text-align: left; color: color-mix(in srgb, var(--sk-on-ink) 62%, transparent); }
/* ── end PAGE SKIN: sticker ── */

/* ── PAGE SKIN: soft-premium ────────────────────────────────────────────────────────────────────── */
/* The soft-premium law (styles/soft/STYLE.md): light is the material. The seven designed bands carry
   their own glass; this dresses everything else on the home page in the same hand — announcement,
   nav, hero, trust strip, menu, about, why-choose, conditions, events, closing band and footer — so
   the page reads as one site. Restyled, never rebuilt: every word, link and photograph stays where
   the template puts it.
   TOKENS, ONE SET, ON THE PAGE ROOT, UNDER THEIR OWN NAMES. `--spk-*`, never the designed bands'
   `--sp-*`, so nothing here can reach a band that is already approved. Inputs are the brand's `--bk-*`
   only; the one literal is the light itself, held in `--spk-w`, so no background paints a bare white.
   THE PAGE GRID IS THE STYLE'S. The designed bands sit on a 1200px column (40 / 32 / 24 / 20px sides);
   the bands here take the same column by re-pointing `--bk-pad` on THEIR OWN element, never on the
   page root (the designed bands read `--bk-pad` too). */
:where(.sl-body).sl-style-soft-premium .rt.bk-home {
  --spk-w: #fff;
  --spk-primary: var(--bk-primary); --spk-accent: var(--bk-accent); --spk-ink: var(--bk-dark); --spk-tint: var(--bk-tint);
  --spk-paper: var(--bk-paper-base, var(--bk-paper));
  --spk-text-ink: var(--bk-ink, var(--bk-dark));
  --spk-display: var(--font-heading, sans-serif); --spk-body: var(--font-body, sans-serif);
  --spk-deep: color-mix(in oklab, var(--bk-primary) 78%, var(--bk-dark));
  --spk-text: color-mix(in srgb, var(--spk-text-ink) 92%, var(--spk-paper));
  --spk-muted: color-mix(in srgb, var(--spk-text-ink) 74%, var(--spk-paper));
  --spk-lum-p: color-mix(in oklab, var(--bk-primary) 45%, var(--spk-w));
  --spk-lum-a: color-mix(in oklab, var(--bk-accent) 55%, var(--spk-w));
  --spk-on-primary: #fff;
  --spk-glass-hi: color-mix(in srgb, var(--spk-w) 80%, transparent);
  --spk-glass-lo: color-mix(in srgb, var(--spk-w) 54%, transparent);
  --spk-pearl-hi: color-mix(in srgb, var(--spk-w) 86%, transparent);
  --spk-pearl-lo: color-mix(in srgb, var(--spk-w) 62%, transparent);
  --spk-rim: color-mix(in srgb, var(--spk-w) 92%, transparent);
  --spk-shade: color-mix(in srgb, var(--bk-primary) 10%, transparent);
  --spk-shade-soft: color-mix(in srgb, var(--bk-primary) 6%, transparent);
  --spk-ease: cubic-bezier(.2, .7, .2, 1);
  --spk-glass-shadow: inset 0 1px 0 var(--spk-rim), inset 0 0 0 1px color-mix(in srgb, var(--spk-w) 50%, transparent),
    0 0 0 1px color-mix(in srgb, var(--bk-primary) 6%, transparent), 0 2px 6px var(--spk-shade-soft),
    0 30px 60px -30px var(--spk-shade), 0 80px 140px -60px var(--spk-shade);
  --spk-pearl-shadow: inset 0 1px 0 var(--spk-rim), inset 0 0 0 1px color-mix(in srgb, var(--spk-w) 55%, transparent),
    0 0 0 1px color-mix(in srgb, var(--bk-primary) 6%, transparent), 0 2px 6px var(--spk-shade-soft),
    0 30px 60px -30px var(--spk-shade), 0 90px 150px -60px var(--spk-shade);
  --spk-disc: radial-gradient(circle at 35% 28%, var(--spk-w) 0 30%, color-mix(in srgb, var(--bk-tint) 70%, var(--spk-w)) 100%);
  --spk-disc-shadow: inset 0 1px 0 var(--spk-w), inset 0 -3px 8px color-mix(in srgb, var(--bk-primary) 7%, transparent),
    0 0 0 1px color-mix(in srgb, var(--bk-primary) 10%, transparent), 0 10px 22px -8px color-mix(in srgb, var(--bk-primary) 30%, transparent);
  --spk-sep: linear-gradient(90deg, color-mix(in srgb, var(--bk-dark) 9%, transparent) 42px, color-mix(in srgb, var(--bk-dark) 3%, transparent) 92%);
  --spk-rule: linear-gradient(90deg, color-mix(in srgb, var(--bk-dark) 14%, transparent), color-mix(in srgb, var(--bk-dark) 2%, transparent));
  --spk-hair: linear-gradient(90deg, transparent, color-mix(in srgb, var(--bk-dark) 10%, transparent) 18%, color-mix(in srgb, var(--bk-dark) 10%, transparent) 82%, transparent);
  --spk-bead: radial-gradient(circle at 35% 30%, var(--spk-w) 0 20%, var(--bk-accent) 70%);
  --spk-bead-glow: 0 0 0 4px color-mix(in srgb, var(--spk-lum-a) 45%, transparent), 0 0 16px 2px color-mix(in srgb, var(--spk-lum-a) 80%, transparent);
  --spk-g-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 10'%3E%3Cpath d='M1 5h15.5M12.5 1l4 4-4 4' fill='none' stroke='%23000' stroke-width='1.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  --spk-g-tick: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2.4 6.4l2.3 2.2 4.9-5' fill='none' stroke='%23000' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  /* the page's one column and its air (the law's page rhythm) */
  --spk-side: max(40px, calc((100% - 1200px) / 2));
  --spk-band-t: 128px; --spk-band-b: 160px;
}
@supports (color: oklch(from red l c h)) {
  :where(.sl-body).sl-style-soft-premium .rt.bk-home {
    --spk-deep: oklch(from color-mix(in oklab, var(--bk-primary) 78%, var(--bk-dark)) min(l, 0.5) c h);
    --spk-lum-p: oklch(from var(--bk-primary) 0.8 calc(c * 1.25 + 0.02) h);
    --spk-lum-a: oklch(from var(--bk-accent) 0.84 calc(c * 1.1 + 0.02) h);
  }
}
/* the lit pill's label: white under LCH 49, black above it (both sides clear 4.5:1) */
@supports (color: lch(from red l c h)) {
  :where(.sl-body).sl-style-soft-premium .rt.bk-home { --spk-on-primary: lch(from var(--bk-primary) clamp(0, calc((49 - l) * 1000), 100) 0 0); }
}
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  :where(.sl-body).sl-style-soft-premium .rt.bk-home {
    --spk-glass-hi: color-mix(in srgb, var(--spk-w) 92%, transparent); --spk-glass-lo: color-mix(in srgb, var(--spk-w) 82%, transparent);
    --spk-pearl-hi: color-mix(in srgb, var(--spk-w) 95%, transparent); --spk-pearl-lo: color-mix(in srgb, var(--spk-w) 86%, transparent);
  }
}
@media (max-width: 1180px) { :where(.sl-body).sl-style-soft-premium .rt.bk-home { --spk-side: 32px; --spk-band-t: 112px; --spk-band-b: 140px; } }
@media (max-width: 900px) { :where(.sl-body).sl-style-soft-premium .rt.bk-home { --spk-side: 24px; --spk-band-t: 96px; --spk-band-b: 110px; } }
@media (max-width: 640px) { :where(.sl-body).sl-style-soft-premium .rt.bk-home { --spk-side: 20px; --spk-band-t: 84px; --spk-band-b: 96px; } }
@media (max-width: 900px) { :where(.sl-body).sl-style-soft-premium .rt-hero { --sl-nav-h: 112px; } }
@media (max-width: 560px) { :where(.sl-body).sl-style-soft-premium .rt-hero { --sl-nav-h: 178px; } }

/* every restyled band takes the style's column on its own element */
:where(.sl-body).sl-style-soft-premium .rt.bk-home :is(.rt-hero, :where(.sl-body) .bk-cs, :where(.sl-body) .bk-pgrid, :where(.sl-body) .bk-prose, :where(.sl-body) .bk-ovl, :where(.sl-body) .bk-cond, :where(.sl-body) .bk-ev) { --bk-pad: var(--spk-side); }

/* ── ONE BUTTON LANGUAGE: the lit pearl pill (book) and the pearl pill (everything else) ─────────
   Sizes ride on custom properties so a context (the nav, a menu row, a phone) sizes the same pill
   rather than restating it. The outline of each is a real 1px border; the rings are light. */
:where(.sl-body).sl-style-soft-premium .rt.bk-home :is(.rt-pill, :where(.sl-body) .bk-ovl .bk-pill, :where(.sl-body) .bk-cond .bk-pill, :where(.sl-body) .bk-pgrid .bk-pcard > .bk-pill, :where(.sl-body) .bk-pgrid .bk-promo .bk-pill, :where(.sl-body) .bk-prose .bk-prose-pill, :where(.sl-body) .bk-ev .bk-ev-btn) {
  position: relative; isolation: isolate; overflow: hidden; box-sizing: border-box;
  display: inline-flex; align-items: center; justify-content: center; gap: 12px;
  width: auto; height: var(--spk-pill-h, 58px); margin: 0; padding: 0 var(--spk-pill-px, 28px);
  border: 1px solid transparent; border-radius: 999px; text-decoration: none; white-space: nowrap;
  font: 600 var(--spk-pill-fs, 16.5px)/1 var(--spk-body); letter-spacing: .03em !important; text-transform: none !important;
  transition: box-shadow .6s var(--spk-ease), filter .6s var(--spk-ease);
}
:where(.sl-body).sl-style-soft-premium .rt.bk-home :is(.rt-pill, :where(.sl-body) .bk-ovl .bk-pill, :where(.sl-body) .bk-cond .bk-pill, :where(.sl-body) .bk-pgrid .bk-pcard > .bk-pill, :where(.sl-body) .bk-pgrid .bk-promo .bk-pill, :where(.sl-body) .bk-prose .bk-prose-pill, :where(.sl-body) .bk-ev .bk-ev-btn)::after {
  content: ''; flex: none; display: var(--spk-arrow-d, block); width: 18px; height: 10px; background: currentColor;
  -webkit-mask: var(--spk-g-arrow) center / 18px 10px no-repeat; mask: var(--spk-g-arrow) center / 18px 10px no-repeat;
}
/* pearl (secondary) */
:where(.sl-body).sl-style-soft-premium .rt.bk-home :is(.rt-pill.rt-outline, :where(.sl-body) .rt-pill.rt-soft, :where(.sl-body) .bk-ovl .bk-pill-soft, :where(.sl-body) .bk-ovl .bk-pill-ghost, :where(.sl-body) .bk-cond .bk-pill-dark, :where(.sl-body) .bk-pgrid .bk-pcard > .bk-pill, :where(.sl-body) .bk-ev .bk-ev-white, :where(.sl-body) .bk-ev .bk-ev-ghost) {
  color: var(--spk-text-ink); border-color: color-mix(in srgb, var(--spk-primary) 12%, transparent);
  background:
    radial-gradient(70% 90% at 50% -20%, var(--spk-w) 30%, transparent 70%),
    linear-gradient(100deg, color-mix(in srgb, var(--spk-lum-p) 30%, var(--spk-w)) 0%, var(--spk-w) 38%, var(--spk-w) 58%, color-mix(in srgb, var(--spk-lum-a) 34%, var(--spk-w)) 100%);
  box-shadow: inset 0 1px 0 var(--spk-w), inset 0 -4px 10px color-mix(in srgb, var(--spk-primary) 7%, transparent), 0 12px 28px -14px color-mix(in srgb, var(--spk-primary) 36%, transparent),
    0 0 1px 6px color-mix(in srgb, var(--spk-w) var(--spk-collar, 55%), transparent), 0 0 34px -6px color-mix(in srgb, var(--spk-lum-a) 55%, transparent);
}
:where(.sl-body).sl-style-soft-premium .rt.bk-home :is(.rt-pill.rt-outline, :where(.sl-body) .rt-pill.rt-soft, :where(.sl-body) .bk-ovl .bk-pill-soft, :where(.sl-body) .bk-ovl .bk-pill-ghost, :where(.sl-body) .bk-cond .bk-pill-dark, :where(.sl-body) .bk-pgrid .bk-pcard > .bk-pill, :where(.sl-body) .bk-ev .bk-ev-white, :where(.sl-body) .bk-ev .bk-ev-ghost)::before {
  content: ''; position: absolute; inset: 0; z-index: -1; border-radius: inherit; pointer-events: none;
  background: linear-gradient(100deg, transparent 30%, color-mix(in srgb, var(--spk-w) 90%, transparent) 50%, transparent 70%) 0 0 / 250% 100% no-repeat;
  animation: spk-sheen 7s ease-in-out infinite;
}
/* lit pearl (primary) */
:where(.sl-body).sl-style-soft-premium .rt.bk-home :is(.rt-pill.rt-fill, :where(.sl-body) .bk-ovl .bk-pill-fill, :where(.sl-body) .bk-cond .bk-pill-ghost, :where(.sl-body) .bk-pgrid .bk-promo .bk-pill, :where(.sl-body) .bk-prose .bk-prose-pill, :where(.sl-body) .bk-ev .bk-ev-fill) {
  color: var(--spk-on-primary); border-color: color-mix(in oklab, var(--spk-primary) 85%, var(--spk-ink));
  background:
    radial-gradient(60% 120% at 50% -30%, color-mix(in srgb, var(--spk-w) 36%, transparent), transparent 70%),
    linear-gradient(180deg, color-mix(in oklab, var(--spk-primary) 80%, var(--spk-w)) 0%, var(--spk-primary) 55%, color-mix(in oklab, var(--spk-primary) 86%, var(--spk-ink)) 100%);
  box-shadow: inset 0 1px 0 color-mix(in srgb, var(--spk-w) 45%, transparent), inset 0 -1px 0 color-mix(in srgb, var(--spk-ink) 30%, transparent), 0 12px 28px -12px color-mix(in srgb, var(--spk-primary) 45%, transparent),
    0 22px 50px -14px color-mix(in srgb, var(--spk-lum-a) 90%, transparent), 0 0 1px 6px color-mix(in srgb, var(--spk-w) var(--spk-collar, 55%), transparent);
}
:where(.sl-body).sl-style-soft-premium .rt.bk-home :is(.rt-pill.rt-fill, :where(.sl-body) .bk-ovl .bk-pill-fill, :where(.sl-body) .bk-cond .bk-pill-ghost, :where(.sl-body) .bk-pgrid .bk-promo .bk-pill, :where(.sl-body) .bk-prose .bk-prose-pill, :where(.sl-body) .bk-ev .bk-ev-fill)::before {
  content: ''; position: absolute; inset: 0; z-index: -1; border-radius: inherit; pointer-events: none;
  background: linear-gradient(100deg, transparent 30%, color-mix(in srgb, var(--spk-w) 22%, transparent) 50%, transparent 70%) 0 0 / 250% 100% no-repeat;
  -webkit-mask: linear-gradient(180deg, #000 0 10%, transparent 26%); mask: linear-gradient(180deg, #000 0 10%, transparent 26%);
  animation: spk-sheen 7s ease-in-out -3.5s infinite;
}
:where(.sl-body).sl-style-soft-premium .rt.bk-home :is(.rt-pill, :where(.sl-body) .bk-ovl .bk-pill, :where(.sl-body) .bk-cond .bk-pill, :where(.sl-body) .bk-pgrid .bk-pcard > .bk-pill, :where(.sl-body) .bk-pgrid .bk-promo .bk-pill, :where(.sl-body) .bk-prose .bk-prose-pill, :where(.sl-body) .bk-ev .bk-ev-btn):is(:hover, :where(.sl-body) :focus-visible) { filter: brightness(1.04); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home :is(.rt-pill, :where(.sl-body) .bk-ovl .bk-pill, :where(.sl-body) .bk-cond .bk-pill, :where(.sl-body) .bk-pgrid .bk-pcard > .bk-pill, :where(.sl-body) .bk-pgrid .bk-promo .bk-pill, :where(.sl-body) .bk-prose .bk-prose-pill, :where(.sl-body) .bk-ev .bk-ev-btn):focus-visible { outline: 2px solid var(--spk-deep); outline-offset: 6px; }
@keyframes spk-sheen { 0%, 55% { background-position: 120% 0; } 100% { background-position: -20% 0; } }

/* ── THE ANNOUNCEMENT: a pearl strip, cool light at one end and warm at the other ──────────────── */
:where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-announce {
  position: relative; padding: 11px var(--spk-side); color: var(--spk-deep);
  font: 500 14px/1.45 var(--spk-body); letter-spacing: .02em; text-transform: none;
  background: linear-gradient(100deg, color-mix(in srgb, var(--spk-lum-p) 34%, var(--spk-paper)) 0%, var(--spk-paper) 36%, var(--spk-paper) 64%, color-mix(in srgb, var(--spk-lum-a) 36%, var(--spk-paper)) 100%);
}

/* ── THE NAV: the brand name in the display face, quiet links with a bead under the current one,
   the pearl pill and the lit pill. One row from 1241px; brand and pills over a centred link row
   from 641 to 1240 (where one row cannot hold them and the links used to drop a row and wrap the
   name and the button); stacked and centred on a phone. ───────────────────────────────────────── */
:where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-nav {
  --spk-pill-h: 46px; --spk-pill-px: 22px; --spk-pill-fs: 15px; --spk-arrow-d: none;
  position: relative; gap: 12px clamp(18px, 2.2vw, 36px); padding: 16px var(--spk-side);
  background: var(--spk-paper);
}
:where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-nav::after { content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 1px; pointer-events: none; background: var(--spk-hair); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-nav .rt-brand { flex: none; text-decoration: none; }
:where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-nav .rt-brand span { display: block; font: 500 22px/1.1 var(--spk-display); letter-spacing: -.02em !important; text-transform: none; color: var(--spk-deep); white-space: nowrap; }
:where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-nav .rt-links { flex-wrap: nowrap; align-items: center; gap: 6px clamp(14px, 1.7vw, 28px); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-nav .rt-links a { position: relative; padding: 8px 0; font: 500 15px/1 var(--spk-body); letter-spacing: .01em; text-transform: none; color: var(--spk-muted); white-space: nowrap; transition: color .6s var(--spk-ease); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-nav .rt-links a:hover { color: var(--spk-deep); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-nav .rt-links a.on { color: var(--spk-deep); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-nav .rt-links a.on::after { content: ''; position: absolute; left: 50%; bottom: -3px; width: 6px; height: 6px; margin-left: -3px; border-radius: 50%;
  background: var(--spk-bead); box-shadow: 0 0 0 3px color-mix(in srgb, var(--spk-lum-a) 45%, transparent), 0 0 10px 1px color-mix(in srgb, var(--spk-lum-a) 80%, transparent); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-nav .rt-navr { flex: none; gap: 12px; align-items: center; }
@media (min-width: 641px) and (max-width: 1240px) {
  :where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-nav { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; row-gap: 10px; padding-block: 16px 8px; }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-nav .rt-brand { grid-column: 1; grid-row: 1; }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-nav .rt-navr { grid-column: 3; grid-row: 1; justify-content: flex-end; }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-nav .rt-links { grid-column: 1 / -1; grid-row: 2; flex-wrap: wrap; justify-content: center; }
}
@media (max-width: 640px) {
  :where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-nav { --spk-pill-h: 42px; --spk-pill-px: 18px; --spk-pill-fs: 14.5px; flex-wrap: wrap; justify-content: center; row-gap: 8px; padding-block: 14px 16px; }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-nav .rt-brand { flex: 1 0 100%; display: flex; justify-content: center; }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-nav .rt-brand span { font-size: 21px; }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-nav .rt-links { flex: 1 0 100%; flex-wrap: wrap; justify-content: center; gap: 0 18px; }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-nav .rt-links a { padding: 7px 0; font-size: 14.5px; }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-nav .rt-navr { flex: 1 0 100%; justify-content: center; margin-top: 4px; }
}

/* ── THE HERO. On a photograph: the headline in the display face at weight 500 and as written, the
   eyebrow as a frosted pearl chip with the bead, the buttons in the style's pills. The photograph,
   its crop and the veil that holds the words legible stay exactly as they are. ───────────────── */
:where(.sl-body).sl-style-soft-premium .rt.bk-home .rt-hero.rt-hero--full { padding-inline: var(--spk-side); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .rt-hero.rt-hero--full .rt-hero-copy { padding-inline: 0; max-width: 46rem; }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .rt-hero .rt-hero-copy > .rt-eyebrow {
  display: inline-flex; align-items: center; gap: 12px; margin: 0 0 24px; padding: 9px 18px 9px 12px; border-radius: 999px;
  font: 500 14.5px/1.25 var(--spk-body); letter-spacing: .06em !important; text-transform: none !important; color: var(--spk-deep); opacity: 1; text-shadow: none;
  background: linear-gradient(155deg, var(--spk-pearl-hi), var(--spk-pearl-lo));
  -webkit-backdrop-filter: blur(20px) saturate(170%); backdrop-filter: blur(20px) saturate(170%);
  box-shadow: inset 0 1px 0 var(--spk-w), 0 0 0 1px color-mix(in srgb, var(--spk-primary) 8%, transparent), 0 10px 30px -14px color-mix(in srgb, var(--spk-ink) 45%, transparent);
}
:where(.sl-body).sl-style-soft-premium .rt.bk-home .rt-hero .rt-hero-copy > .rt-eyebrow::before { content: ''; flex: none; width: 9px; height: 9px; border-radius: 50%; background: var(--spk-bead); box-shadow: var(--spk-bead-glow); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .rt-hero .rt-hero-copy > h1 {
  font: 500 clamp(40px, 3.3vw + 14px, 68px)/1.04 var(--spk-display); letter-spacing: -.03em !important; text-transform: none !important;
  text-wrap: balance; margin: 0 0 22px; color: var(--spk-text-ink);
}
:where(.sl-body).sl-style-soft-premium .rt.bk-home .rt-hero.rt-hero--full .rt-hero-copy > h1 { color: var(--spk-w); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .rt-hero .rt-hero-copy > .rt-hero-body { font: 400 18px/1.58 var(--spk-body); margin: 0 0 34px; }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .rt-hero .rt-hero-ctas { gap: 14px; }
/* on a photograph the pills' white collar reads as a grey ring, so it is left off */
:where(.sl-body).sl-style-soft-premium .rt.bk-home .rt-hero.rt-hero--full .rt-hero-ctas { --spk-collar: 0%; }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .rt-hero .rt-hero-note { font: 600 14px/1.2 var(--spk-body); color: var(--spk-text-ink); padding: 11px 20px; border-radius: 999px;
  background: linear-gradient(155deg, var(--spk-pearl-hi), var(--spk-pearl-lo)); -webkit-backdrop-filter: blur(20px) saturate(170%); backdrop-filter: blur(20px) saturate(170%);
  box-shadow: inset 0 1px 0 var(--spk-w), 0 0 0 1px color-mix(in srgb, var(--spk-primary) 8%, transparent), 0 12px 28px -14px color-mix(in srgb, var(--spk-primary) 36%, transparent); }
/* no photograph beside the words (or a split hero): the panel is lit glass on the band, not a flat wash */
:where(.sl-body).sl-style-soft-premium .rt.bk-home .rt-hero:not(.rt-hero--full) { border-radius: 40px;
  background:
    radial-gradient(46% 70% at 18% 30%, color-mix(in srgb, var(--spk-lum-p) 40%, transparent), transparent 70%),
    radial-gradient(44% 70% at 86% 78%, color-mix(in srgb, var(--spk-lum-a) 36%, transparent), transparent 70%),
    linear-gradient(155deg, var(--spk-paper), color-mix(in srgb, var(--spk-tint) 70%, var(--spk-paper)));
  box-shadow: var(--spk-glass-shadow); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .rt-hero:not(.rt-hero--full) .rt-hero-body { color: var(--spk-text); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .rt-hero .rt-hero-art img { border-radius: 40px;
  box-shadow: 0 0 0 16px color-mix(in srgb, var(--spk-w) 45%, transparent), 0 0 0 17px color-mix(in srgb, var(--spk-primary) 8%, transparent), 0 50px 100px -40px var(--spk-shade); }
@media (max-width: 700px) {
  :where(.sl-body).sl-style-soft-premium .rt.bk-home .rt-hero .rt-hero-copy > h1 { font-size: clamp(32px, 8.4vw, 42px); line-height: 1.06; margin-bottom: 14px; }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home .rt-hero .rt-hero-copy > .rt-eyebrow { margin-bottom: 14px; padding: 7px 14px 7px 10px; border-radius: 20px; font-size: 13px; letter-spacing: .04em !important; }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home .rt-hero .rt-hero-copy > .rt-hero-body { font-size: 15.5px; line-height: 1.5; margin-bottom: 20px; }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home .rt-hero .rt-hero-ctas { --spk-pill-h: 48px; --spk-pill-px: 20px; --spk-pill-fs: 15px; gap: 12px 10px; }
}
/* three calls on one row on a small phone, as the band already promises: no arrows, shared width */
@media (max-width: 400px) {
  :where(.sl-body).sl-style-soft-premium .rt.bk-home .rt-hero .rt-hero-ctas { --spk-pill-h: 44px; --spk-pill-px: 6px; --spk-pill-fs: 14px; --spk-arrow-d: none; flex-wrap: nowrap; gap: 8px; }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home .rt-hero .rt-hero-ctas .rt-pill { flex: 1 1 0; min-width: 0; letter-spacing: 0 !important; }
}

/* ── THE TRUST STRIP: each glyph in a pearl icon disc with its glow halo; labels in the body face ── */
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-cs { padding-block: clamp(40px, 3.6vw, 56px); gap: 22px 30px; }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-cs .bk-cs-item { isolation: isolate; gap: 18px; font: 500 16.5px/1.3 var(--spk-body); letter-spacing: 0 !important; text-transform: none; color: var(--spk-text-ink); text-wrap: balance; }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-cs .bk-cs-item > span { position: relative; flex: none; display: grid; place-items: center; width: 50px; height: 50px; border-radius: 50%;
  color: var(--spk-deep); background: var(--spk-disc); box-shadow: var(--spk-disc-shadow); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-cs .bk-cs-item > span::before { content: ''; position: absolute; inset: -18px; z-index: -1; border-radius: 50%;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--spk-lum-a) 70%, transparent) 30%, color-mix(in srgb, var(--spk-lum-p) 32%, transparent) 64%, transparent); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-cs .bk-cs-item > span::after { content: ''; position: absolute; inset: -7px; border-radius: 50%;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--spk-w) 85%, transparent), 0 0 0 1px color-mix(in srgb, var(--spk-primary) 5%, transparent); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-cs .bk-cs-item svg { width: 23px; height: 23px; fill: currentColor; }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-cs.bk-cs-l-rule { border: 0; background: var(--spk-hair) left top / 100% 1px no-repeat, var(--spk-hair) left bottom / 100% 1px no-repeat; }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-cs.bk-cs-l-rule .bk-cs-item > span { width: 36px; height: 36px; }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-cs.bk-cs-l-rule .bk-cs-item svg { width: 17px; height: 17px; }
@media (max-width: 900px) {
  :where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-cs:not(.bk-cs-l-rule) > * { flex-basis: calc((100% - 30px) / 2); }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-cs:not(.bk-cs-l-rule) .bk-cs-item { flex-direction: column; justify-content: flex-start; text-align: center; gap: 16px; font-size: 15.5px; }
}

/* ── THE MENU: the title on the band, the drips as a hairline ledger on one pearl sheet over the
   brand's two lights (cool behind the names, warm behind the buttons). Cards in the other two
   arrangements become glass panes. ──────────────────────────────────────────────────────────── */
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-pgrid {
  position: relative; isolation: isolate; overflow: clip; padding-block: var(--spk-band-t) var(--spk-band-b);
  background:
    radial-gradient(34% 26% at 16% 54%, color-mix(in srgb, var(--spk-lum-p) 42%, transparent), color-mix(in srgb, var(--spk-lum-p) 12%, transparent) 55%, transparent),
    radial-gradient(30% 22% at 88% 64%, color-mix(in srgb, var(--spk-lum-a) 38%, transparent), color-mix(in srgb, var(--spk-lum-a) 10%, transparent) 55%, transparent),
    radial-gradient(120% 70% at 50% 0%, var(--bk-paper) 42%, color-mix(in srgb, var(--bk-tint) 60%, var(--bk-paper)) 100%);
}
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-pgrid .bk-pgrid-panel { background: none; border-radius: 0; padding: 0; box-shadow: none; }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-pgrid .bk-pgrid-panel > h2 {
  margin: 0; font: 500 clamp(38px, 3.2vw + 8px, 54px)/1.06 var(--spk-display); letter-spacing: -.028em !important; text-transform: none !important;
  color: var(--spk-text-ink); text-wrap: balance;
}
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-pgrid .bk-pgrid-fine { margin: 22px 0 64px; max-width: 34em; font: 400 19px/1.55 var(--spk-body); color: var(--spk-muted); text-wrap: pretty; }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-pgrid:not(.bk-pgrid-l-menu) .bk-pgrid-fine { margin-inline: var(--bk-mi, auto); }
/* the ledger sheet. NO BACKDROP BLUR ON A SHEET THIS SIZE: a ~1200x900 blurred layer lost whole tiles
   in Chromium's full-page captures (rows simply missing), and the blooms behind it are already soft,
   so the pearl is made a touch more opaque instead and reads the same */
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-pgrid.bk-pgrid-l-menu .bk-pgrid-cells { position: relative; isolation: isolate; gap: 0; padding: 10px 48px; border-radius: 40px;
  background: linear-gradient(160deg, color-mix(in srgb, var(--spk-w) 90%, transparent), color-mix(in srgb, var(--spk-w) 72%, transparent));
  box-shadow: var(--spk-pearl-shadow); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-pgrid.bk-pgrid-l-menu .bk-pgrid-cells::after { content: ''; position: absolute; inset: 0; z-index: -1; border-radius: inherit; pointer-events: none;
  background: radial-gradient(80% 36% at 18% 0%, color-mix(in srgb, var(--spk-w) 80%, transparent), transparent 72%); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-pgrid.bk-pgrid-l-menu .bk-pcard { --spk-pill-h: 48px; --spk-pill-px: 22px; --spk-pill-fs: 15px;
  row-gap: 8px; padding: 26px 0; border-radius: 0; background: none; box-shadow: none; }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-pgrid.bk-pgrid-l-menu .bk-pcard + :is(.bk-pcard, :where(.sl-body) .bk-promo) { background: var(--spk-sep) left top / 100% 1px no-repeat; }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-pgrid .bk-pnm { font: 500 21px/1.25 var(--spk-display); letter-spacing: -.012em !important; text-transform: none !important; color: var(--spk-text-ink); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-pgrid .bk-pbody { font: 400 16px/1.55 var(--spk-body); color: var(--spk-muted); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-pgrid.bk-pgrid-l-menu .bk-pcard > .bk-pill { margin: 0 0 0 clamp(18px, 2.4vw, 34px); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-pgrid:not(.bk-pgrid-l-menu) .bk-pcard > .bk-pill { margin: auto auto 0; }
/* the grid and counter arrangements: each drip a glass pane */
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-pgrid:not(.bk-pgrid-l-menu) .bk-pcard { --spk-pill-h: 50px; --spk-pill-fs: 15px; position: relative; isolation: isolate; border-radius: 32px;
  background: linear-gradient(155deg, var(--spk-glass-hi), var(--spk-glass-lo)); -webkit-backdrop-filter: blur(22px) saturate(170%); backdrop-filter: blur(22px) saturate(170%);
  box-shadow: var(--spk-glass-shadow); }
/* a promo tile is the featured pane: warm glass, ink words, the lit pill */
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-pgrid .bk-promo { --spk-pill-h: 50px; --spk-pill-fs: 15px; position: relative; isolation: isolate; border-radius: 32px; color: var(--spk-text-ink);
  background: linear-gradient(155deg, color-mix(in srgb, color-mix(in srgb, var(--spk-lum-a) 14%, var(--spk-w)) 84%, transparent), color-mix(in srgb, color-mix(in srgb, var(--spk-lum-p) 12%, var(--spk-w)) 58%, transparent));
  -webkit-backdrop-filter: blur(22px) saturate(170%); backdrop-filter: blur(22px) saturate(170%);
  box-shadow: inset 0 1px 0 var(--spk-rim), 0 2px 6px var(--spk-shade-soft), 0 30px 60px -30px var(--spk-shade), 0 0 100px -24px color-mix(in srgb, var(--spk-lum-a) 70%, transparent); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-pgrid .bk-promo :is(.bk-promo-title, :where(.sl-body) .bk-promo-big) { font-family: var(--spk-display); font-weight: 500; letter-spacing: -.02em !important; text-transform: none !important; color: var(--spk-text-ink); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-pgrid .bk-promo-title { font-size: 15px; font-family: var(--spk-body); letter-spacing: .12em !important; color: var(--spk-deep); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-pgrid .bk-promo :is(.bk-promo-body, :where(.sl-body) li) { color: var(--spk-text); opacity: 1; }
@media (max-width: 1180px) {
  :where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-pgrid.bk-pgrid-l-menu .bk-pgrid-cells { padding: 8px 36px; }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-pgrid .bk-pgrid-fine { margin-bottom: 52px; }
}
@media (max-width: 900px) {
  :where(.sl-body).sl-style-soft-premium.sl-shelf .rt.bk-home .bk-pgrid .bk-pgrid-panel > :is(h2, :where(.sl-body) .bk-pgrid-fine) { text-align: center !important; margin-inline: auto; }
}
@media (max-width: 700px) {
  :where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-pgrid.bk-pgrid-l-menu .bk-pgrid-cells { padding: 4px 22px; border-radius: 32px; }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-pgrid.bk-pgrid-l-menu .bk-pcard { --spk-pill-h: 44px; --spk-pill-px: 20px; --spk-pill-fs: 14.5px; padding: 22px 0 24px; row-gap: 8px; }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-pgrid.bk-pgrid-l-menu .bk-pcard > .bk-pill { margin: 8px 0 0; }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-pgrid .bk-pbody { font-size: 15.5px; }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-pgrid .bk-pgrid-fine { font-size: 17px; margin: 18px auto 40px; }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-pgrid .bk-pnm { font-size: 20px; }
}

/* ── THE ABOUT BAND: the side title as written beside its photograph, the bead eyebrow, the photo in
   the style's 40px frame with the halo frame 16px outside it and the soft-light grade ─────────── */
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-prose.bk-prose-retail {
  position: relative; isolation: isolate; overflow: clip; padding-block: var(--spk-band-t) var(--spk-band-b);
  background:
    radial-gradient(30% 34% at 24% 50%, color-mix(in srgb, var(--spk-lum-p) 44%, transparent), color-mix(in srgb, var(--spk-lum-p) 14%, transparent) 55%, transparent),
    radial-gradient(26% 24% at 84% 60%, color-mix(in srgb, var(--spk-lum-a) 30%, transparent), color-mix(in srgb, var(--spk-lum-a) 8%, transparent) 55%, transparent),
    radial-gradient(120% 70% at 50% 0%, var(--bk-paper) 42%, color-mix(in srgb, var(--bk-tint) 60%, var(--bk-paper)) 100%);
}
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-prose-retail.bk-prose-has-photo .bk-prose-in { gap: clamp(48px, 6vw, 96px); align-items: center; }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-prose-retail .bk-prose-eyebrow {
  display: inline-flex; align-items: center; gap: 14px; margin: 0 0 22px;
  font: 500 15px/1 var(--spk-body); letter-spacing: .14em !important; text-transform: none !important; color: var(--spk-deep);
}
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-prose-retail .bk-prose-eyebrow::before { content: ''; flex: none; width: 9px; height: 9px; border-radius: 50%; background: var(--spk-bead); box-shadow: var(--spk-bead-glow); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-prose-retail .bk-prose-head > h2 {
  display: block; margin: 0 0 28px; padding: 0; border-radius: 0; background: none;
  font: 500 clamp(38px, 2.6vw + 10px, 50px)/1.08 var(--spk-display); letter-spacing: -.028em !important; text-transform: none !important;
  color: var(--spk-text-ink); text-wrap: balance;
}
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-prose-retail .bk-prose-body p { font: 400 17px/1.68 var(--spk-body); color: var(--spk-text); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-prose-retail .bk-prose-body p.bk-prose-lead { font: 400 19px/1.62 var(--spk-body); color: var(--spk-text); }
/* beside the photograph the head ranges with its paragraph (the page would otherwise centre it over left-ranged copy) */
@media (min-width: 901px) {
  :where(.sl-body).sl-style-soft-premium.sl-shelf .rt.bk-home .bk-prose-retail.bk-prose-has-photo :is(.bk-prose-head, :where(.sl-body) .bk-prose-head > h2, :where(.sl-body) .bk-prose-head > .bk-prose-eyebrow) { text-align: left !important; margin-inline: 0 !important; }
  :where(.sl-body).sl-style-soft-premium.sl-shelf .rt.bk-home .bk-prose-retail.bk-prose-has-photo .bk-prose-head > h2 { max-width: 22ch; }
  :where(.sl-body).sl-style-soft-premium.sl-shelf .rt.bk-home .bk-prose-retail.bk-prose-has-photo .bk-prose-head > .bk-prose-eyebrow { max-width: none; }
}
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-prose-retail .bk-prose-photo { position: relative; isolation: isolate; }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-prose-retail .bk-prose-photo::before { content: ''; position: absolute; inset: -16px; z-index: -1; border-radius: 56px; pointer-events: none;
  background: linear-gradient(180deg, color-mix(in srgb, var(--spk-w) 55%, transparent), color-mix(in srgb, var(--spk-w) 10%, transparent));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--spk-w) 90%, transparent), 0 0 0 1px color-mix(in srgb, var(--spk-primary) 8%, transparent), 0 0 80px color-mix(in srgb, var(--spk-lum-a) 40%, transparent); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-prose-retail .bk-prose-photo img { border-radius: 40px; box-shadow: 0 2px 6px var(--spk-shade-soft), 0 50px 100px -40px var(--spk-shade); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-prose-retail .bk-prose-photo::after { content: ''; position: absolute; inset: 0; border-radius: 40px; pointer-events: none; mix-blend-mode: soft-light;
  background: linear-gradient(165deg, color-mix(in srgb, var(--spk-primary) 50%, transparent), color-mix(in srgb, var(--spk-accent) 45%, transparent)); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-prose-retail .bk-prose-pill { margin-left: 0; }
@media (max-width: 900px) {
  :where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-prose-retail.bk-prose-has-photo .bk-prose-in { gap: 56px; }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-prose-retail .bk-prose-photo img { border-radius: 32px; }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-prose-retail .bk-prose-photo::after { border-radius: 32px; }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-prose-retail .bk-prose-photo::before { inset: -10px; border-radius: 42px; }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-prose-retail .bk-prose-body p.bk-prose-lead { font-size: 18px; }
}
@media (max-width: 640px) {
  :where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-prose-retail .bk-prose-head > h2 { font-size: 34px; }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-prose.bk-prose-retail { background:
    radial-gradient(90% 16% at 20% 22%, color-mix(in srgb, var(--spk-lum-p) 44%, transparent), color-mix(in srgb, var(--spk-lum-p) 14%, transparent) 55%, transparent),
    radial-gradient(80% 16% at 84% 68%, color-mix(in srgb, var(--spk-lum-a) 30%, transparent), color-mix(in srgb, var(--spk-lum-a) 8%, transparent) 55%, transparent),
    radial-gradient(120% 70% at 50% 0%, var(--bk-paper) 42%, color-mix(in srgb, var(--bk-tint) 60%, var(--bk-paper)) 100%); }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-prose-retail .bk-prose-body p.bk-prose-lead { font-size: 17px; }
}

/* ── WHY CHOOSE: the centred title, the reasons as check-disc rows on one pane of glass over the
   brand's cool light, the buttons centred beneath it ────────────────────────────────────────── */
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-ovl.bk-ovl-noart {
  position: relative; isolation: isolate; overflow: clip; padding-block: var(--spk-band-t) var(--spk-band-b);
  background:
    radial-gradient(36% 28% at 30% 56%, color-mix(in srgb, var(--spk-lum-p) 44%, transparent), color-mix(in srgb, var(--spk-lum-p) 14%, transparent) 55%, transparent),
    radial-gradient(30% 28% at 76% 44%, color-mix(in srgb, var(--spk-lum-a) 34%, transparent), color-mix(in srgb, var(--spk-lum-a) 10%, transparent) 55%, transparent),
    radial-gradient(120% 70% at 50% 0%, var(--bk-paper) 42%, color-mix(in srgb, var(--bk-tint) 60%, var(--bk-paper)) 100%);
}
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-ovl .bk-ovl-card > h2 {
  margin: 0 var(--bk-mi, auto); font: 500 clamp(38px, 3.2vw + 8px, 54px)/1.06 var(--spk-display); letter-spacing: -.028em !important; text-transform: none !important;
  color: var(--spk-text-ink); text-wrap: balance; max-width: 20ch;
}
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-ovl .bk-ovl-card > p { margin: 22px var(--bk-mi, auto) 0; max-width: 34em; font: 400 19px/1.55 var(--spk-body); color: var(--spk-muted); text-wrap: balance; }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-ovl.bk-ovl-noart .bk-ovl-card > p { text-align: center; }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-ovl .bk-ovl-card > ul { list-style: none; text-align: left; }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-ovl.bk-ovl-noart .bk-ovl-card > ul {
  position: relative; isolation: isolate; box-sizing: border-box; max-width: 1080px; margin: 64px auto 0; padding: 48px 56px 30px; column-gap: 64px; border-radius: 36px;
  background: linear-gradient(155deg, var(--spk-glass-hi), var(--spk-glass-lo));
  -webkit-backdrop-filter: blur(22px) saturate(170%); backdrop-filter: blur(22px) saturate(170%); box-shadow: var(--spk-glass-shadow);
}
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-ovl .bk-ovl-card > ul > li { position: relative; margin: 0; padding: 1px 0 26px 44px; break-inside: avoid; font: 400 17px/1.45 var(--spk-body); color: var(--spk-text); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-ovl .bk-ovl-card > ul > li::before { content: ''; position: absolute; left: 0; top: 0; width: 26px; height: 26px; border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, var(--spk-w) 0 35%, color-mix(in srgb, var(--spk-lum-p) 26%, var(--spk-w)));
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--spk-primary) 16%, transparent), 0 4px 12px -3px color-mix(in srgb, var(--spk-primary) 30%, transparent), 0 0 18px color-mix(in srgb, var(--spk-lum-a) 45%, transparent); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-ovl .bk-ovl-card > ul > li::after { content: ''; position: absolute; left: 7px; top: 7px; width: 12px; height: 12px; background: var(--spk-deep);
  -webkit-mask: var(--spk-g-tick) center / 12px 12px no-repeat; mask: var(--spk-g-tick) center / 12px 12px no-repeat; }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-ovl .bk-ovl-card > ul > li b { display: block; font: 600 17px/1.35 var(--spk-body); color: var(--spk-text-ink); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-ovl .bk-ovl-card > ul > li span { display: block; margin-top: 6px; font: 400 16px/1.55 var(--spk-body); color: var(--spk-muted); opacity: 1; }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-ovl .bk-ovl-ctas { gap: 14px; margin-top: 44px; }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-ovl.bk-ovl-noart .bk-ovl-ctas { justify-content: center; }
/* over a photograph the card is a glass pane on it */
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-ovl:not(.bk-ovl-noart) .bk-ovl-card { position: relative; isolation: isolate; border-radius: 36px; padding: 44px 44px 40px;
  background: linear-gradient(155deg, var(--spk-pearl-hi), var(--spk-pearl-lo)); -webkit-backdrop-filter: blur(22px) saturate(170%); backdrop-filter: blur(22px) saturate(170%); box-shadow: var(--spk-pearl-shadow); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-ovl:not(.bk-ovl-noart) .bk-ovl-card > h2 { font-size: clamp(32px, 2vw + 12px, 42px); max-width: none; }
@media (max-width: 1180px) {
  :where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-ovl.bk-ovl-noart .bk-ovl-card > ul { padding: 40px 40px 20px; column-gap: 44px; margin-top: 52px; }
}
@media (max-width: 760px) {
  :where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-ovl.bk-ovl-noart .bk-ovl-card > ul { columns: 1; padding: 32px 24px 12px; margin-top: 44px; border-radius: 30px; }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-ovl .bk-ovl-card > ul > li { padding-bottom: 22px; }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-ovl .bk-ovl-ctas { --spk-pill-h: 54px; --spk-pill-px: 22px; justify-content: center; margin-top: 36px; }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-ovl .bk-ovl-card > p { font-size: 17px; }
}

/* ── CONDITIONS: the brand-coloured slab becomes one pearl card on the band (the law gives a band a
   light ground, never a painted primary). Bead eyebrow, side title, check-disc rows under row
   separators, the pearl pill and the lit pill. ─────────────────────────────────────────────── */
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-cond {
  position: relative; isolation: isolate; overflow: clip; padding-block: var(--spk-band-t) var(--spk-band-b);
  background:
    radial-gradient(34% 26% at 20% 40%, color-mix(in srgb, var(--spk-lum-p) 40%, transparent), color-mix(in srgb, var(--spk-lum-p) 12%, transparent) 55%, transparent),
    radial-gradient(30% 24% at 82% 62%, color-mix(in srgb, var(--spk-lum-a) 36%, transparent), color-mix(in srgb, var(--spk-lum-a) 10%, transparent) 55%, transparent),
    radial-gradient(90% 80% at 72% 38%, color-mix(in srgb, var(--bk-paper) 30%, var(--spk-paper)) 0%, var(--bk-paper) 70%);
}
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-cond .bk-cond-panel {
  position: relative; isolation: isolate; border-radius: 40px; padding: 64px 68px 60px; color: var(--spk-text-ink);
  /* a card this size carries no backdrop blur (see the menu sheet): a slightly more opaque pearl instead */
  background: linear-gradient(160deg, color-mix(in srgb, var(--spk-w) 90%, transparent), color-mix(in srgb, var(--spk-w) 72%, transparent));
  box-shadow: var(--spk-pearl-shadow);
}
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-cond .bk-cond-panel::after { content: ''; position: absolute; inset: 0; z-index: -1; border-radius: inherit; pointer-events: none;
  background: radial-gradient(80% 36% at 18% 0%, color-mix(in srgb, var(--spk-w) 80%, transparent), transparent 72%); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-cond .bk-cond-eyebrow {
  display: flex; align-items: center; justify-content: var(--bk-justify, flex-start); gap: 14px; margin: 0 0 22px;
  font: 500 15px/1 var(--spk-body); letter-spacing: .14em !important; text-transform: none !important; color: var(--spk-deep);
}
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-cond .bk-cond-eyebrow::before { content: ''; flex: none; width: 9px; height: 9px; border-radius: 50%; background: var(--spk-bead); box-shadow: var(--spk-bead-glow); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-cond .bk-cond-panel > h2 {
  margin: 0; font: 500 clamp(36px, 2.4vw + 12px, 50px)/1.08 var(--spk-display); letter-spacing: -.028em !important; text-transform: none !important;
  color: var(--spk-text-ink); text-wrap: balance;
}
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-cond .bk-cond-lead { margin-top: 18px; margin-bottom: 0; font: 400 18px/1.5 var(--spk-body); color: var(--spk-muted); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-cond .bk-cond-panel > ul { margin: 44px 0 44px; gap: 0 56px; }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-cond .bk-cond-panel > ul > li { position: relative; margin: 0; padding: 17px 0 17px 44px; border: 0; border-radius: 0; text-align: left;
  font: 400 17px/1.4 var(--spk-body); color: var(--spk-text); background: var(--spk-sep) left top / 100% 1px no-repeat; }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-cond .bk-cond-panel > ul > li::before { content: ''; position: absolute; left: 0; top: 15px; width: 26px; height: 26px; border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, var(--spk-w) 0 35%, color-mix(in srgb, var(--spk-lum-p) 26%, var(--spk-w)));
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--spk-primary) 16%, transparent), 0 4px 12px -3px color-mix(in srgb, var(--spk-primary) 30%, transparent), 0 0 18px color-mix(in srgb, var(--spk-lum-a) 45%, transparent); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-cond .bk-cond-panel > ul > li::after { content: ''; position: absolute; left: 7px; top: 22px; width: 12px; height: 12px; background: var(--spk-deep);
  -webkit-mask: var(--spk-g-tick) center / 12px 12px no-repeat; mask: var(--spk-g-tick) center / 12px 12px no-repeat; }
@media (min-width: 901px) { :where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-cond.bk-cond-l-rows:not(.bk-cond-beside) .bk-cond-panel > ul { grid-template-columns: 1fr 1fr; } }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-cond.bk-cond-l-chips .bk-cond-panel > ul > li { padding: 10px 18px 10px 40px; border: 1px solid color-mix(in srgb, var(--spk-primary) 10%, transparent); border-radius: 999px;
  background: color-mix(in srgb, var(--spk-w) 70%, transparent); box-shadow: inset 0 1px 0 var(--spk-w), 0 8px 20px -12px color-mix(in srgb, var(--spk-primary) 30%, transparent); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-cond.bk-cond-l-chips .bk-cond-panel > ul > li::before { left: 8px; top: 50%; width: 22px; height: 22px; margin-top: -11px; }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-cond.bk-cond-l-chips .bk-cond-panel > ul > li::after { left: 13px; top: 50%; width: 12px; margin-top: -6px; }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-cond .bk-cond-ctas { gap: 14px; }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-cond .bk-cond-ph img { border-radius: 40px; }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-cond.bk-cond-beside { column-gap: 40px; }
@media (max-width: 1180px) { :where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-cond .bk-cond-panel { padding: 52px 48px 48px; } }
@media (max-width: 900px) {
  :where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-cond .bk-cond-panel > ul { margin: 36px 0; }
  /* stacked, nothing stands beside the words: the head centres like every other band on a tablet */
  :where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-cond .bk-cond-panel { text-align: center; }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-cond .bk-cond-eyebrow, :where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-cond .bk-cond-ctas { justify-content: center; }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-cond .bk-cond-lead { margin-inline: auto; }
}
@media (max-width: 640px) {
  :where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-cond .bk-cond-panel { padding: 40px 22px 36px; border-radius: 32px; }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-cond .bk-cond-lead { font-size: 17px; }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-cond .bk-cond-ctas { --spk-pill-h: 54px; --spk-pill-px: 22px; }
}

/* ── GROUPS AND EVENTS: title as written at weight 500, cards with the style's radius, the pills ─── */
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-ev > h2 { font: 500 clamp(38px, 3.2vw + 8px, 54px)/1.06 var(--spk-display) !important; letter-spacing: -.028em !important; text-transform: none !important; text-wrap: balance; }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-ev .bk-ecard { border-radius: 32px; overflow: hidden; }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-ev .bk-ecard h3 { text-transform: none !important; letter-spacing: -.012em !important; font-weight: 500; }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-ev .bk-ev-ctas { gap: 14px; }
:where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-ev .bk-ev-btn.bk-ev-white, :where(.sl-body).sl-style-soft-premium .rt.bk-home .bk-ev .bk-ev-btn.bk-ev-ghost { color: var(--spk-text-ink) !important;
  box-shadow: inset 0 1px 0 var(--spk-w), 0 12px 28px -14px color-mix(in srgb, var(--spk-primary) 36%, transparent), 0 0 1px 6px color-mix(in srgb, var(--spk-w) 55%, transparent) !important; }

/* ── THE CLOSING ASK: no painted slab. The words stand on a band of light that joins the band above
   to the one below (so neither seam is a hard edge), a bead-and-wings ornament over a statement set
   at reading size — the record's sentence is a paragraph, and a paragraph is not a display line —
   and the style's two pills. A closing band on a photograph keeps its photograph and its wash. ── */
:where(.sl-body).sl-style-soft-premium .rt.bk-home > section.rt-closing {
  --spk-close-top: var(--bk-tint); --spk-close-bot: var(--bk-tint);
  position: relative; isolation: isolate; overflow: clip; padding: var(--spk-band-t) var(--spk-side) var(--spk-band-b); color: var(--spk-text-ink);
}
:where(.sl-body).sl-style-soft-premium .rt.bk-home > section.rt-closing:not(.rt-onphoto) {
  background:
    radial-gradient(22% 16% at 50% 74%, color-mix(in srgb, var(--spk-lum-a) 40%, transparent), color-mix(in srgb, var(--spk-lum-a) 12%, transparent) 55%, transparent),
    radial-gradient(44% 30% at 50% 40%, color-mix(in srgb, var(--spk-lum-p) 34%, transparent), color-mix(in srgb, var(--spk-lum-p) 10%, transparent) 60%, transparent),
    linear-gradient(180deg, var(--spk-close-top) 0%, var(--spk-paper) 34%, var(--spk-paper) 66%, var(--spk-close-bot) 100%);
}
/* the page's paper/tint beat: a closing band on the tint beat stands between two paper bands */
:where(.sl-body).sl-style-soft-premium .rt.bk-home > section.rt-closing:nth-child(even of :is(section, :where(.sl-body) :has(section))) {
  --spk-close-top: color-mix(in srgb, var(--bk-tint) 60%, var(--spk-paper)); --spk-close-bot: color-mix(in srgb, var(--bk-tint) 60%, var(--spk-paper));
}
/* …and this style's contact band always paints the tint (`:has` may not nest, so the wrapper is named) */
:where(.sl-body).sl-style-soft-premium .rt.bk-home > section.rt-closing:is(:has(+ section.bk-contact-sp), :where(.sl-body) :has(+ div > section.bk-contact-sp)) { --spk-close-bot: var(--bk-tint); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home > section.rt-closing > h2 {
  margin: 0 auto 24px; max-width: 34ch; font: 500 clamp(28px, 1.1vw + 20px, 38px)/1.24 var(--spk-display);
  letter-spacing: -.022em !important; text-transform: none !important; color: var(--spk-text-ink); text-wrap: balance;
}
:where(.sl-body).sl-style-soft-premium .rt.bk-home > section.rt-closing > h2::before { content: ''; display: block; width: 172px; height: 11px; margin: 0 auto 34px;
  background:
    radial-gradient(circle, var(--spk-accent) 0 2.5px, color-mix(in srgb, var(--spk-accent) 35%, transparent) 3.5px, transparent 5.5px) center / 12px 11px no-repeat,
    linear-gradient(90deg, transparent, color-mix(in srgb, var(--spk-primary) 42%, transparent)) left center / 72px 1px no-repeat,
    linear-gradient(270deg, transparent, color-mix(in srgb, var(--spk-primary) 42%, transparent)) right center / 72px 1px no-repeat; }
:where(.sl-body).sl-style-soft-premium .rt.bk-home > section.rt-closing > .rt-closing-line { margin: 0 auto 10px; max-width: 34em; font: 500 19px/1.5 var(--spk-body); color: var(--spk-deep); opacity: 1; text-wrap: balance; }
:where(.sl-body).sl-style-soft-premium .rt.bk-home > section.rt-closing > p:not(.rt-closing-line) { margin: 0 auto 8px; max-width: 40em; font: 400 17px/1.6 var(--spk-body); color: var(--spk-muted); opacity: 1; text-wrap: balance; }
:where(.sl-body).sl-style-soft-premium .rt.bk-home > section.rt-closing > .rt-closing-cta { gap: 14px; margin-top: 44px; }
@media (max-width: 640px) {
  :where(.sl-body).sl-style-soft-premium .rt.bk-home > section.rt-closing > h2 { font-size: 25px; line-height: 1.28; }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home > section.rt-closing > .rt-closing-line { font-size: 17px; }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home > section.rt-closing > p:not(.rt-closing-line) { font-size: 16px; }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home > section.rt-closing > .rt-closing-cta { --spk-pill-h: 54px; --spk-pill-px: 24px; margin-top: 36px; }
}

/* ── THE FOOTER: a light end to a light page. The business name set large in the display face holds
   its column (a signature, not a lone label over a hole), column labels in the style's label type,
   the links in ink, the disclaimer under a fading hairline ─────────────────────────────────── */
:where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-foot {
  position: relative; isolation: isolate; overflow: clip; padding: 96px var(--spk-side) 36px; color: var(--spk-text);
  background:
    radial-gradient(30% 34% at 14% 42%, color-mix(in srgb, var(--spk-lum-p) 30%, transparent), color-mix(in srgb, var(--spk-lum-p) 8%, transparent) 55%, transparent),
    radial-gradient(26% 30% at 86% 56%, color-mix(in srgb, var(--spk-lum-a) 24%, transparent), color-mix(in srgb, var(--spk-lum-a) 6%, transparent) 55%, transparent),
    var(--spk-paper);
}
:where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-foot::before { content: ''; position: absolute; left: 0; right: 0; top: 0; height: 1px; pointer-events: none; background: var(--spk-hair); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-foot .rt-foot-cols { grid-template-columns: minmax(0, 1fr) auto auto; column-gap: clamp(56px, 8vw, 132px); padding-bottom: 64px; }
:where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-foot h4 { margin: 0 0 22px; font: 500 14px/1 var(--spk-body); letter-spacing: .12em !important; text-transform: none !important; color: var(--spk-deep); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-foot .rt-foot-cols > div:first-child > h4 { margin: 0 0 18px; max-width: 14ch; font: 500 clamp(30px, 1.6vw + 14px, 40px)/1.08 var(--spk-display); letter-spacing: -.028em !important; color: var(--spk-text-ink); text-wrap: balance; }
:where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-foot p { font: 400 16px/1.65 var(--spk-body); color: var(--spk-muted); max-width: 38ch; }
:where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-foot li { margin: 0 0 12px; font: 400 16px/1.35 var(--spk-body); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-foot a { color: var(--spk-text); transition: color .6s var(--spk-ease); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-foot a:hover { color: var(--spk-deep); }
:where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-foot .rt-legal { border: 0; padding-top: 26px; font: 400 13px/1.6 var(--spk-body); color: var(--spk-muted); text-wrap: balance;
  background: var(--spk-hair) left top / 100% 1px no-repeat; }
@media (max-width: 900px) {
  :where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-foot .rt-foot-cols { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: 48px; }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-foot .rt-foot-cols > div:first-child { grid-column: 1 / -1; margin-bottom: 12px; }
}
@media (max-width: 640px) {
  :where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-foot { padding-top: 72px; text-align: center; }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-foot .rt-foot-cols { grid-template-columns: minmax(0, 1fr); row-gap: 36px; padding-bottom: 44px; }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-foot .rt-foot-cols > div:first-child > h4 { margin-inline: auto; }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-foot p { margin-inline: auto; }
  /* a narrow band turns a percentage ellipse into a tall smear: the lights go wide and short */
  :where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-foot { background:
    radial-gradient(90% 20% at 16% 26%, color-mix(in srgb, var(--spk-lum-p) 30%, transparent), color-mix(in srgb, var(--spk-lum-p) 8%, transparent) 55%, transparent),
    radial-gradient(80% 18% at 86% 70%, color-mix(in srgb, var(--spk-lum-a) 24%, transparent), color-mix(in srgb, var(--spk-lum-a) 6%, transparent) 55%, transparent),
    var(--spk-paper); }
}

@media (prefers-reduced-motion: reduce) {
  :where(.sl-body).sl-style-soft-premium .rt.bk-home :is(.rt-pill, :where(.sl-body) .bk-ovl .bk-pill, :where(.sl-body) .bk-cond .bk-pill, :where(.sl-body) .bk-pgrid .bk-pcard > .bk-pill, :where(.sl-body) .bk-pgrid .bk-promo .bk-pill, :where(.sl-body) .bk-prose .bk-prose-pill, :where(.sl-body) .bk-ev .bk-ev-btn)::before { animation: none; }
  :where(.sl-body).sl-style-soft-premium .rt.bk-home :is(.rt-pill, :where(.sl-body) .bk-ovl .bk-pill, :where(.sl-body) .bk-cond .bk-pill, :where(.sl-body) .bk-pgrid .bk-pcard > .bk-pill, :where(.sl-body) .bk-pgrid .bk-promo .bk-pill, :where(.sl-body) .bk-prose .bk-prose-pill, :where(.sl-body) .bk-ev .bk-ev-btn), :where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-nav .rt-links a, :where(.sl-body).sl-style-soft-premium .rt.bk-home > .rt-foot a { transition: none; }
}
/* ── end PAGE SKIN: soft-premium ── */

/* ── PAGE SKIN: layered-editorial ───────────────────────────────────────────────────────────────── */
/* THE REST OF A LAYERED EDITORIAL HOME PAGE, IN THE STYLE'S OWN LAW (styles/editorial/STYLE.md).
   The seven editorial bands draw themselves; this dresses the bands between them — announcement, nav,
   hero, credentials, the menu, why-choose, conditions, about, the closing ask and the footer — so the
   page reads as one magazine: flat paper on flat paper, square corners, no shadow, no gradient, no
   capitals, titles in the display face under a 1px ink rule, one button language (the square plate,
   and body type over a 1px rule for the second voice), and every text edge on the spread grid's
   outer column line (78px at 1440, 40px to 1100, 36px to 860, 24px on a phone).
   The words, links and photographs are the page's own; nothing here adds or hides one.
   Colours are the brand's tokens only, derived once below: fallbacks first, relative colour guarded. */
:where(.sl-body).sl-style-layered-editorial .rt {
  --eds-primary: var(--bk-primary); --eds-accent: var(--bk-accent); --eds-ink: var(--bk-dark);
  --eds-paper: var(--bk-paper-base, var(--bk-paper));
  --eds-display: var(--font-heading, serif); --eds-body: var(--font-body, sans-serif);
  --eds-primary-ink: var(--eds-primary);
  --eds-plate-primary: var(--eds-primary);
  --eds-plate-accent: var(--eds-accent);
  --eds-on-primary: var(--eds-paper);
  --eds-on-accent: var(--eds-ink);
  /* the spread grid as tracks, so a band without container units lands on exactly the editorial bands'
     lines: twelve columns of at most 85px, `c 1`..`c 13`, `bleed-l` / `bleed-r` at the band edges */
  --eds-gut: 24px; --eds-edge: 16px; --eds-pad: 120px;
  --eds-spread: [bleed-l] minmax(var(--eds-edge), 1fr) repeat(12, [c] minmax(0, 85px)) [c] minmax(var(--eds-edge), 1fr) [bleed-r];
  /* the outer column line and one column, for a FULL-WIDTH box (the % is that box's containing width) */
  --eds-x: max(calc(var(--eds-edge) + var(--eds-gut)), calc((100% - 1284px) / 2));
  --eds-colw: min(85px, calc((100% - 2 * var(--eds-edge) - 13 * var(--eds-gut)) / 12));
  /* ONE LEFT EDGE, AT EVERY WIDTH. This page is a spread ranged on its grid's outer line on a desktop,
     and the approved phone renders keep that same single left edge; a centred title over left-ranged
     rows inside one band was the defect the page review found. Declared here, in global.css, where the
     three tokens may live. */
  --bk-align: left; --bk-justify: flex-start; --bk-mi: 0;
}
:where(.sl-body).sl-style-layered-editorial .rt :is(.bk-route-split, :where(.sl-body) .bk-composed, :where(.sl-body) .comp-split, :where(.sl-body) .img-text-section, :where(.sl-body) .sec-photo, :where(.sl-body) .section-service_area_map) {
  --bk-align: left; --bk-justify: flex-start; --bk-mi: 0;
}
@supports (color: oklch(from red l c h)) {
  :where(.sl-body).sl-style-layered-editorial .rt {
    --eds-primary-ink: oklch(from var(--eds-primary) min(l, 0.46) c h);
    --eds-plate-primary: oklch(from var(--eds-primary) calc((1 - clamp(0, (l - 0.6) * 1000, 1)) * min(l, 0.52) + clamp(0, (l - 0.6) * 1000, 1) * max(l, 0.72)) c h);
    --eds-plate-accent: oklch(from var(--eds-accent) calc((1 - clamp(0, (l - 0.6) * 1000, 1)) * min(l, 0.52) + clamp(0, (l - 0.6) * 1000, 1) * max(l, 0.72)) c h);
    --eds-on-primary: oklch(from var(--eds-plate-primary) clamp(0.2, (0.6 - l) * 1000, 1) calc(c * 0.3 * clamp(0, (l - 0.6) * 1000, 1)) h);
    --eds-on-accent: oklch(from var(--eds-plate-accent) clamp(0.2, (0.6 - l) * 1000, 1) calc(c * 0.3 * clamp(0, (l - 0.6) * 1000, 1)) h);
  }
}
/* mixes that follow each band's own ground (the home page's white/tint beat re-points --bk-paper per band) */
:where(.sl-body).sl-style-layered-editorial .rt > * {
  --eds-ground: var(--bk-paper);
  --eds-ink-soft: color-mix(in oklab, var(--eds-ink) 72%, var(--eds-ground));
  --eds-rule: color-mix(in oklab, var(--eds-ink) 18%, var(--eds-ground));
}
@media (max-width: 1099px) {
  :where(.sl-body).sl-style-layered-editorial .rt { --eds-gut: 20px; --eds-pad: 96px; --eds-x: 36px; }
}
@media (max-width: 859px) {
  :where(.sl-body).sl-style-layered-editorial .rt {
    --eds-gut: 16px; --eds-edge: 8px; --eds-pad: 64px; --eds-x: 24px;
    --eds-spread: [bleed-l] var(--eds-edge) repeat(4, [c] minmax(0, 1fr)) [c] var(--eds-edge) [bleed-r];
    --eds-colw: calc((100% - 2 * var(--eds-edge) - 5 * var(--eds-gut)) / 4);
  }
}

/* ── THE DEVICES, NAMED ONCE ───────────────────────────────────────────────────────────────────── */
/* the plate button: flat, square, 56px, body 600 16px, coloured from its plate; an ink plate on hover */
:where(.sl-body).sl-style-layered-editorial .rt :is(.rt-nav, :where(.sl-body) .rt-hero, :where(.sl-body) .rt-closing) .rt-pill.rt-fill, :where(.sl-body).sl-style-layered-editorial .rt :is(.bk-pgrid, :where(.sl-body) .bk-ovl) .bk-pill.bk-pill-fill, :where(.sl-body).sl-style-layered-editorial .rt .bk-cond .bk-cond-ctas .bk-pill.bk-pill-ghost, :where(.sl-body).sl-style-layered-editorial .rt .bk-prose .bk-prose-cta .bk-prose-pill {
  display: inline-flex; align-items: center; justify-content: center; gap: 14px; flex: none;
  width: auto; min-height: 56px; margin: 0; padding: 0 28px;
  border: 0; border-radius: 0; box-shadow: none; opacity: 1;
  background: var(--eds-plate-primary); color: var(--eds-on-primary);
  font: 600 16px/1 var(--eds-body); letter-spacing: .01em; text-transform: none; text-decoration: none; white-space: nowrap;
}
:where(.sl-body).sl-style-layered-editorial .rt :is(.rt-nav, :where(.sl-body) .rt-hero, :where(.sl-body) .rt-closing) .rt-pill.rt-fill:hover, :where(.sl-body).sl-style-layered-editorial .rt :is(.bk-pgrid, :where(.sl-body) .bk-ovl) .bk-pill.bk-pill-fill:hover, :where(.sl-body).sl-style-layered-editorial .rt .bk-cond .bk-cond-ctas .bk-pill.bk-pill-ghost:hover, :where(.sl-body).sl-style-layered-editorial .rt .bk-prose .bk-prose-cta .bk-prose-pill:hover { background: var(--eds-ink); color: var(--eds-paper); }
/* the second voice: body type over a 1px rule (a real border, so the underline IS the control's edge) */
:where(.sl-body).sl-style-layered-editorial .rt :is(.rt-nav, :where(.sl-body) .rt-hero, :where(.sl-body) .rt-closing) .rt-pill:is(.rt-soft, :where(.sl-body) .rt-outline), :where(.sl-body).sl-style-layered-editorial .rt .bk-ovl .bk-ovl-ctas .bk-pill:is(.bk-pill-soft, :where(.sl-body) .bk-pill-ghost), :where(.sl-body).sl-style-layered-editorial .rt .bk-cond .bk-cond-ctas .bk-pill.bk-pill-dark {
  display: inline-flex; align-items: center; flex: none; width: auto; min-height: 0; margin: 0; padding: 8px 0 7px;
  border: 0; border-bottom: 1px solid currentColor; border-radius: 0; box-shadow: none; opacity: 1;
  background: none; color: var(--eds-ink);
  font: 600 16px/1 var(--eds-body); letter-spacing: .01em; text-transform: none; text-decoration: none; white-space: nowrap;
}
:where(.sl-body).sl-style-layered-editorial .rt :is(.rt-nav, :where(.sl-body) .rt-hero, :where(.sl-body) .rt-closing) .rt-pill:is(.rt-soft, :where(.sl-body) .rt-outline):hover, :where(.sl-body).sl-style-layered-editorial .rt .bk-ovl .bk-ovl-ctas .bk-pill:is(.bk-pill-soft, :where(.sl-body) .bk-pill-ghost):hover, :where(.sl-body).sl-style-layered-editorial .rt .bk-cond .bk-cond-ctas .bk-pill.bk-pill-dark:hover { color: var(--eds-primary-ink); }
:where(.sl-body).sl-style-layered-editorial .rt :is(.rt-nav, :where(.sl-body) .rt-hero, :where(.sl-body) .rt-closing, :where(.sl-body) .bk-pgrid, :where(.sl-body) .bk-ovl, :where(.sl-body) .bk-cond, :where(.sl-body) .bk-prose) :is(.rt-pill, :where(.sl-body) .bk-pill, :where(.sl-body) .bk-prose-pill):focus-visible { outline: 2px solid var(--eds-ink); outline-offset: 4px; }
:where(.sl-body).sl-style-layered-editorial .rt :is(.rt-hero-ctas, :where(.sl-body) .rt-closing-cta, :where(.sl-body) .bk-ovl-ctas, :where(.sl-body) .bk-cond-ctas, :where(.sl-body) .bk-prose-cta) {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-start; gap: 16px 32px;
}
/* the eyebrow: a 40px rule, then the word in body 600 14px, sentence case as written, primary-ink */
:where(.sl-body).sl-style-layered-editorial .rt :is(.rt-hero .rt-eyebrow, :where(.sl-body) .bk-cond .bk-cond-eyebrow, :where(.sl-body) .bk-prose .bk-prose-eyebrow) {
  display: flex; align-items: center; justify-content: flex-start; gap: 14px; width: auto;
  margin: 0 0 22px; padding: 0; border-radius: 0; background: none; box-shadow: none; text-shadow: none; opacity: 1;
  -webkit-backdrop-filter: none; backdrop-filter: none;
  font: 600 14px/1 var(--eds-body); letter-spacing: .02em; text-transform: none; color: var(--eds-primary-ink);
}
:where(.sl-body).sl-style-layered-editorial .rt :is(.rt-hero .rt-eyebrow, :where(.sl-body) .bk-cond .bk-cond-eyebrow, :where(.sl-body) .bk-prose .bk-prose-eyebrow)::before {
  content: ''; flex: none; width: 40px; height: 1px; background: currentColor;
}
/* the headline block: the 1px ink rule, then the title in the display face at page scale */
:where(.sl-body).sl-style-layered-editorial .rt :is(.bk-pgrid .bk-pgrid-panel, :where(.sl-body) .bk-ovl .bk-ovl-card, :where(.sl-body) .bk-cond .bk-cond-panel, :where(.sl-body) .bk-prose .bk-prose-head, :where(.sl-body) .rt-closing) > h2 {
  display: block; box-sizing: border-box; margin: 0; max-width: none; padding: 20px 0 0;
  border: 0; border-top: 1px solid var(--eds-ink); border-radius: 0; background: none; box-shadow: none; text-shadow: none;
  font: 500 50px/1.04 var(--eds-display); letter-spacing: -.02em; text-transform: none; text-wrap: balance; color: var(--eds-ink);
}
/* THE HOUSE CENTRES A PLAIN BAND'S TITLE WITH !important; these bands are ranged on the spread's line */
:where(.sl-body).sl-style-layered-editorial.sl-style-layered-editorial .rt.rt.rt section:is(.bk-pgrid, :where(.sl-body) .bk-ovl, :where(.sl-body) .bk-cond, :where(.sl-body) .bk-prose, :where(.sl-body) .rt-closing) :is(h2, :where(.sl-body) [class$="-head"], :where(.sl-body) [class*="eyebrow"], :where(.sl-body) [class$="-intro"], :where(.sl-body) [class$="-sub"], :where(.sl-body) [class$="-body"], :where(.sl-body) [class$="-cols"]) {
  text-align: left !important; margin-inline: 0 !important;
}
@media (max-width: 1099px) {
  :where(.sl-body).sl-style-layered-editorial .rt :is(.bk-pgrid .bk-pgrid-panel, :where(.sl-body) .bk-ovl .bk-ovl-card, :where(.sl-body) .bk-cond .bk-cond-panel, :where(.sl-body) .bk-prose .bk-prose-head, :where(.sl-body) .rt-closing) > h2 { font-size: 42px; }
}
@media (max-width: 859px) {
  :where(.sl-body).sl-style-layered-editorial .rt :is(.bk-pgrid .bk-pgrid-panel, :where(.sl-body) .bk-ovl .bk-ovl-card, :where(.sl-body) .bk-cond .bk-cond-panel, :where(.sl-body) .bk-prose .bk-prose-head, :where(.sl-body) .rt-closing) > h2 { padding-top: 16px; font-size: 36px; }
}

/* ── ANNOUNCEMENT + NAV ─────────────────────────────────────────────────────────────────────────── */
:where(.sl-body).sl-style-layered-editorial .rt .rt-announce { padding: 9px var(--eds-x); font: 500 13px/1.35 var(--eds-body); letter-spacing: .01em; }
:where(.sl-body).sl-style-layered-editorial .rt .rt-nav {
  display: flex; flex-wrap: nowrap; align-items: center; justify-content: flex-start; gap: 0 32px;
  min-height: 76px; padding: 0 var(--eds-x); background: var(--eds-paper); border-bottom: 1px solid var(--eds-rule);
}
:where(.sl-body).sl-style-layered-editorial .rt .rt-nav .rt-brand { flex: none; margin-right: auto; display: flex; align-items: center; text-decoration: none; }
:where(.sl-body).sl-style-layered-editorial .rt .rt-nav .rt-brand span { font: 500 24px/1 var(--eds-display); letter-spacing: -.015em; color: var(--eds-ink); white-space: nowrap; }
:where(.sl-body).sl-style-layered-editorial .rt .rt-nav .rt-brand img { height: 44px; }
:where(.sl-body).sl-style-layered-editorial .rt .rt-nav .rt-links { display: flex; flex-wrap: nowrap; align-items: center; justify-content: flex-start; gap: 0 26px; }
:where(.sl-body).sl-style-layered-editorial .rt .rt-nav .rt-links a {
  padding: 8px 0; font: 500 15px/1 var(--eds-body); letter-spacing: 0; color: var(--eds-ink-soft); text-decoration: none; white-space: nowrap;
}
:where(.sl-body).sl-style-layered-editorial .rt .rt-nav .rt-links a:hover { color: var(--eds-ink); }
:where(.sl-body).sl-style-layered-editorial .rt .rt-nav .rt-links a.on { color: var(--eds-ink); text-decoration: underline 1px; text-underline-offset: 7px; }
:where(.sl-body).sl-style-layered-editorial .rt .rt-nav .rt-navr { display: flex; flex: none; align-items: center; gap: 0 28px; margin-left: auto; }
:where(.sl-body).sl-style-layered-editorial .rt .rt-nav .rt-pill.rt-fill { min-height: 48px; padding: 0 22px; font-size: 15px; }
:where(.sl-body).sl-style-layered-editorial .rt .rt-nav .rt-pill.rt-outline { font-size: 15px; }
/* THE NAV DID NOT FIT FROM 901 TO ~1180px: a link dropped a row, the name and "Book Now" broke in two.
   Below 1180 the nav becomes a two-deck masthead — the name and the two actions on top, the links on
   their own ruled line under them — so nothing ever wraps inside a word or a button. */
@media (min-width: 860px) and (max-width: 1179px) {
  :where(.sl-body).sl-style-layered-editorial .rt .rt-nav { flex-wrap: wrap; min-height: 0; gap: 0 28px; }
  :where(.sl-body).sl-style-layered-editorial .rt .rt-nav .rt-brand { order: 0; min-height: 72px; }
  :where(.sl-body).sl-style-layered-editorial .rt .rt-nav .rt-navr { order: 1; }
  :where(.sl-body).sl-style-layered-editorial .rt .rt-nav::after { content: ''; order: 2; flex: 0 0 100%; height: 1px; background: var(--eds-rule); }
  :where(.sl-body).sl-style-layered-editorial .rt .rt-nav .rt-links { order: 3; flex: 1 1 100%; flex-wrap: wrap; gap: 0 28px; padding: 6px 0; }
  /* (the shared nav fix gives a two-row grid nav 12px under its links; this masthead's links row carries its own air) */
  :where(.sl-body).sl-style-layered-editorial.sl-style-layered-editorial .rt.rt .rt-nav.rt-nav { padding-bottom: 0; }
}
/* a phone: the name and Book Now on the first line, every other link (Memberships last) on a ruled run */
@media (max-width: 859px) {
  :where(.sl-body).sl-style-layered-editorial .rt .rt-nav { flex-wrap: wrap; min-height: 0; gap: 0 18px; padding: 0 var(--eds-x) 10px; }
  :where(.sl-body).sl-style-layered-editorial .rt .rt-nav :is(.rt-links, :where(.sl-body) .rt-navr) { display: contents; }
  :where(.sl-body).sl-style-layered-editorial .rt .rt-nav .rt-brand { order: 0; flex: 1 1 auto; min-width: 0; min-height: 64px; }
  :where(.sl-body).sl-style-layered-editorial .rt .rt-nav .rt-brand span { font-size: 20px; white-space: normal; }
  :where(.sl-body).sl-style-layered-editorial .rt .rt-nav .rt-pill.rt-fill { order: 1; min-height: 44px; padding: 0 16px; }
  :where(.sl-body).sl-style-layered-editorial .rt .rt-nav::after { content: ''; order: 2; flex: 0 0 100%; height: 1px; background: var(--eds-rule); }
  :where(.sl-body).sl-style-layered-editorial .rt .rt-nav .rt-links a { order: 3; padding: 12px 0 2px; }
  :where(.sl-body).sl-style-layered-editorial .rt .rt-nav .rt-pill.rt-outline {
    order: 4; padding: 12px 0 2px; border-bottom: 0; font: 500 15px/1 var(--eds-body); letter-spacing: 0; color: var(--eds-ink-soft);
  }
}

/* ── HERO ───────────────────────────────────────────────────────────────────────────────────────── */
/* A PHOTOGRAPH BEHIND THE WORDS: the copy stands on a flat paper plate laid over the photograph, run off
   the band's left and bottom edges, so the words need no scrim, no shadow and no capsule to be read —
   the law's layering (flat paper on flat paper) instead of the house's gradient. */
:where(.sl-body).sl-style-layered-editorial .rt .rt-hero.rt-hero--full { padding: 96px 0 0; align-items: end; }
:where(.sl-body).sl-style-layered-editorial .rt .rt-hero.rt-hero--full::after { content: none; display: none; }
:where(.sl-body).sl-style-layered-editorial .rt .rt-hero.rt-hero--full .rt-hero-copy {
  justify-self: start; box-sizing: border-box; max-width: 100%; margin: 0;
  width: calc(var(--eds-x) + 6 * var(--eds-colw) + 5 * var(--eds-gut) + 56px);
  padding: 44px 56px 52px var(--eds-x); background: var(--eds-paper); color: var(--eds-ink);
}
:where(.sl-body).sl-style-layered-editorial .rt .rt-hero :is(h1, :where(.sl-body) .rt-hero-body) { text-shadow: none; }
:where(.sl-body).sl-style-layered-editorial .rt .rt-hero.rt-hero h1 {
  margin: 0; padding: 20px 0 0; border-top: 1px solid var(--eds-ink);
  font: 500 clamp(44px, 4.5vw, 66px)/1.02 var(--eds-display); letter-spacing: -.025em; text-transform: none; text-wrap: balance; color: var(--eds-ink);
}
:where(.sl-body).sl-style-layered-editorial .rt .rt-hero.rt-hero .rt-hero-body { max-width: none; margin: 18px 0 0; font: italic 400 24px/1.3 var(--eds-display); color: var(--eds-ink-soft); }
:where(.sl-body).sl-style-layered-editorial .rt .rt-hero .rt-hero-ctas { margin-top: 36px; }
/* no photograph behind the words: the same spread on the band's own ground, the picture square */
:where(.sl-body).sl-style-layered-editorial .rt .rt-hero:not(.rt-hero--full) {
  margin: 0; border-radius: 0; background: var(--bk-paper); padding: var(--eds-pad) var(--eds-x); column-gap: calc(var(--eds-colw) + 2 * var(--eds-gut));
}
:where(.sl-body).sl-style-layered-editorial .rt .rt-hero .rt-hero-art img { border-radius: 0; box-shadow: none; }
:where(.sl-body).sl-style-layered-editorial .rt .rt-hero .rt-hero-note {
  border-radius: 0; box-shadow: none; background: var(--eds-paper); color: var(--eds-ink); font: 600 14px/1.2 var(--eds-body);
}
@media (max-width: 1099px) {
  :where(.sl-body).sl-style-layered-editorial .rt .rt-hero.rt-hero--full .rt-hero-copy { width: calc(var(--eds-x) + 8 * var(--eds-colw) + 7 * var(--eds-gut) + 40px); padding: 40px 40px 44px var(--eds-x); }
  :where(.sl-body).sl-style-layered-editorial .rt .rt-hero.rt-hero .rt-hero-body { font-size: 21px; }
}
@media (max-width: 859px) {
  :where(.sl-body).sl-style-layered-editorial .rt .rt-hero.rt-hero--full { padding-top: 160px; }
  :where(.sl-body).sl-style-layered-editorial .rt .rt-hero.rt-hero--full .rt-hero-copy { width: 100%; padding: 28px var(--eds-x) 36px; }
  :where(.sl-body).sl-style-layered-editorial .rt .rt-hero.rt-hero h1 { padding-top: 16px; font-size: clamp(34px, 9.4vw, 44px); line-height: 1.04; }
  :where(.sl-body).sl-style-layered-editorial .rt .rt-hero.rt-hero .rt-hero-body { margin-top: 12px; font-size: 20px; }
  :where(.sl-body).sl-style-layered-editorial .rt .rt-hero .rt-eyebrow { margin-bottom: 16px; }
  :where(.sl-body).sl-style-layered-editorial .rt .rt-hero .rt-hero-ctas { flex-wrap: wrap; margin-top: 28px; gap: 14px 22px; }
  :where(.sl-body).sl-style-layered-editorial .rt .rt-hero .rt-hero-ctas .rt-pill { flex: none; }
  :where(.sl-body).sl-style-layered-editorial .rt .rt-hero .rt-hero-ctas .rt-pill.rt-fill { padding: 0 22px; }
  :where(.sl-body).sl-style-layered-editorial .rt .rt-hero:not(.rt-hero--full) { padding: var(--eds-pad) var(--eds-x); }
}

/* ── CREDENTIALS ────────────────────────────────────────────────────────────────────────────────── */
:where(.sl-body).sl-style-layered-editorial .rt .bk-cs.bk-rowfit { padding: 30px var(--eds-x); background: var(--bk-paper); }
:where(.sl-body).sl-style-layered-editorial .rt .bk-cs .bk-cs-item { gap: 14px; font: italic 400 22px/1.2 var(--eds-display); letter-spacing: 0; text-transform: none; color: var(--eds-ink); }
:where(.sl-body).sl-style-layered-editorial .rt .bk-cs .bk-cs-item svg { width: 28px; height: 28px; fill: var(--eds-primary-ink); }
@media (max-width: 859px) {
  :where(.sl-body).sl-style-layered-editorial .rt .bk-cs.bk-rowfit { padding-block: 24px; }
  :where(.sl-body).sl-style-layered-editorial .rt .bk-cs.bk-cs-l-row .bk-cs-item { justify-content: flex-start; }
}

/* ── THE MENU (products) ────────────────────────────────────────────────────────────────────────── */
:where(.sl-body).sl-style-layered-editorial .rt .bk-pgrid { padding: var(--eds-pad) var(--eds-x); background: var(--bk-paper); }
:where(.sl-body).sl-style-layered-editorial .rt .bk-pgrid .bk-pgrid-panel { padding: 0; border-radius: 0; background: none; box-shadow: none; text-align: left; }
:where(.sl-body).sl-style-layered-editorial .rt .bk-pgrid .bk-pgrid-panel > h2 { width: calc(50% - var(--eds-gut) / 2); }
:where(.sl-body).sl-style-layered-editorial .rt .bk-pgrid .bk-pgrid-fine { width: calc(50% - var(--eds-gut) / 2); margin: 16px 0 0; font: italic 400 24px/1.3 var(--eds-display); color: var(--eds-ink-soft); }
:where(.sl-body).sl-style-layered-editorial .rt .bk-pgrid .bk-pgrid-cells { margin-top: 56px; }
:where(.sl-body).sl-style-layered-editorial .rt .bk-pgrid .bk-pgrid-cells .bk-pcard { border-radius: 0; box-shadow: none; background: none; }
:where(.sl-body).sl-style-layered-editorial .rt .bk-pgrid .bk-pcard .bk-pnm { font: 400 30px/1.15 var(--eds-display); letter-spacing: -.01em; text-transform: none; color: var(--eds-ink); }
:where(.sl-body).sl-style-layered-editorial .rt .bk-pgrid .bk-pcard .bk-pbody { font: italic 400 20px/1.3 var(--eds-display); color: var(--eds-ink-soft); }
:where(.sl-body).sl-style-layered-editorial .rt .bk-pgrid .bk-pcard img { border-radius: 0; }
:where(.sl-body).sl-style-layered-editorial .rt .bk-pgrid .bk-pcard > .bk-pill.bk-pill-fill { min-height: 48px; padding: 0 24px; font-size: 15px; }
/* the price list: the list's ink rule, then each drip on a ruled line */
:where(.sl-body).sl-style-layered-editorial .rt .bk-pgrid.bk-pgrid-l-menu .bk-pgrid-cells { gap: 0; border-top: 1px solid var(--eds-ink); }
:where(.sl-body).sl-style-layered-editorial .rt .bk-pgrid.bk-pgrid-l-menu .bk-pgrid-cells .bk-pcard { padding: 26px 0 28px; border-bottom: 1px solid var(--eds-rule); row-gap: 8px; }
/* the card grid and the counter: flat, square, each opening on the ink rule */
:where(.sl-body).sl-style-layered-editorial .rt .bk-pgrid:is(.bk-pgrid-l-grid, :where(.sl-body) .bk-pgrid-l-counter) .bk-pgrid-cells .bk-pcard {
  padding: 24px 0 8px; border-top: 1px solid var(--eds-ink); text-align: left; align-items: flex-start;
}
:where(.sl-body).sl-style-layered-editorial .rt .bk-pgrid.bk-pgrid-l-grid .bk-pcard :is(.bk-pbody) { text-align: left; }
:where(.sl-body).sl-style-layered-editorial .rt .bk-pgrid.bk-pgrid-l-grid .bk-pcard > .bk-pill.bk-pill-fill { margin: 0; }
:where(.sl-body).sl-style-layered-editorial .rt .bk-pgrid .bk-pgrid-cells .bk-promo { border-radius: 0; box-shadow: none; background: var(--eds-plate-primary); color: var(--eds-on-primary); }
:where(.sl-body).sl-style-layered-editorial .rt .bk-pgrid .bk-promo :is(.bk-promo-title, :where(.sl-body) .bk-promo-big) { font-family: var(--eds-display); letter-spacing: -.01em; text-transform: none; }
:where(.sl-body).sl-style-layered-editorial .rt .bk-pgrid .bk-promo .bk-pill {
  display: inline-flex; align-items: center; justify-content: center; width: auto; min-height: 48px; padding: 0 24px; border: 0; border-radius: 0; box-shadow: none;
  background: var(--eds-plate-accent); color: var(--eds-on-accent); font: 600 15px/1 var(--eds-body); text-transform: none; text-decoration: none;
}
@media (max-width: 859px) {
  :where(.sl-body).sl-style-layered-editorial .rt .bk-pgrid .bk-pgrid-panel > h2, :where(.sl-body).sl-style-layered-editorial .rt .bk-pgrid .bk-pgrid-fine { width: auto; }
  :where(.sl-body).sl-style-layered-editorial .rt .bk-pgrid .bk-pgrid-fine { font-size: 20px; }
  :where(.sl-body).sl-style-layered-editorial .rt .bk-pgrid .bk-pgrid-cells { margin-top: 40px; }
  :where(.sl-body).sl-style-layered-editorial .rt .bk-pgrid .bk-pcard .bk-pnm { font-size: 26px; }
  :where(.sl-body).sl-style-layered-editorial .rt .bk-pgrid .bk-pcard .bk-pbody { font-size: 18px; }
  :where(.sl-body).sl-style-layered-editorial .rt .bk-pgrid.bk-pgrid-l-menu .bk-pgrid-cells .bk-pcard { padding: 22px 0 24px; justify-items: start; }
}

/* ── GROUPS & EVENTS (not on the test brand; type and corners only, its inks and rings stay the house's) ── */
:where(.sl-body).sl-style-layered-editorial .rt .bk-ev h2 { font: 500 50px/1.04 var(--eds-display); letter-spacing: -.02em; text-transform: none; text-wrap: balance; }
:where(.sl-body).sl-style-layered-editorial .rt .bk-ev .bk-ecard { border-radius: 0; }
:where(.sl-body).sl-style-layered-editorial .rt .bk-ev .bk-ev-btn { border-radius: 0; font: 600 16px/1.2 var(--eds-body); letter-spacing: .01em; text-transform: none; }
@media (max-width: 859px) { :where(.sl-body).sl-style-layered-editorial .rt .bk-ev h2 { font-size: 36px; } }

/* ── WHY CHOOSE (the photograph band) ───────────────────────────────────────────────────────────── */
/* The card is a flat paper plate laid over the photograph and run off the band's left edge, its words on
   the grid's outer line; the photograph is aimed so the faces fall on the side the card leaves open.
   The photograph is painted by the band's own ::before (inheriting the band's picture) so its box can be
   told where to stop: see the seam rule below, and the phone, where it stands above the card. */
:where(.sl-body).sl-style-layered-editorial .rt .bk-ovl:not(.bk-ovl-noart) {
  position: relative; isolation: isolate; min-height: 0;
  padding: var(--eds-pad) 0 calc(var(--eds-pad) + var(--eds-clear, 0px));
  background-size: 0 0; background-repeat: no-repeat; background-color: var(--eds-strip, var(--bk-tint));
}
:where(.sl-body).sl-style-layered-editorial .rt .bk-ovl:not(.bk-ovl-noart)::before {
  content: ''; position: absolute; z-index: -1; inset: 0 0 var(--eds-clear, 0px) 0;
  background-image: inherit; background-repeat: no-repeat; background-size: cover;
  background-position: 72% var(--sl-focus-y, 35%);
}
:where(.sl-body).sl-style-layered-editorial .rt .bk-ovl .bk-ovl-card {
  position: relative; box-sizing: border-box; margin: 0; max-width: 100%;
  width: calc(var(--eds-x) + 6 * var(--eds-colw) + 5 * var(--eds-gut) + 56px);
  padding: 48px 56px 52px var(--eds-x); border-radius: 0; box-shadow: none; background: var(--eds-paper);
}
:where(.sl-body).sl-style-layered-editorial .rt .bk-ovl .bk-ovl-card > p { margin: 16px 0 0; font: 400 17px/1.55 var(--eds-body); color: var(--eds-ink-soft); }
:where(.sl-body).sl-style-layered-editorial .rt .bk-ovl .bk-ovl-card > ul { list-style: none; margin: 32px 0 0; padding: 0; border-top: 1px solid var(--eds-ink); columns: auto; }
:where(.sl-body).sl-style-layered-editorial .rt .bk-ovl .bk-ovl-card > ul > li {
  margin: 0; padding: 14px 0 15px; border-bottom: 1px solid var(--eds-rule); font: 400 17px/1.4 var(--eds-body); color: var(--eds-ink);
}
:where(.sl-body).sl-style-layered-editorial .rt .bk-ovl .bk-ovl-card > ul > li b { display: block; font: 400 24px/1.2 var(--eds-display); letter-spacing: -.005em; color: var(--eds-ink); }
:where(.sl-body).sl-style-layered-editorial .rt .bk-ovl .bk-ovl-card > ul > li span { display: block; margin-top: 4px; opacity: 1; font: 400 15px/1.45 var(--eds-body); color: var(--eds-ink-soft); }
:where(.sl-body).sl-style-layered-editorial .rt .bk-ovl .bk-ovl-ctas { margin-top: 36px; }
/* no photograph: the band on its own ground, the card's words on the grid */
:where(.sl-body).sl-style-layered-editorial .rt .bk-ovl.bk-ovl-noart { padding: var(--eds-pad) var(--eds-x); background: var(--bk-paper); }
:where(.sl-body).sl-style-layered-editorial .rt .bk-ovl.bk-ovl-noart .bk-ovl-card { width: auto; padding: 0; background: none; }
/* THE SEAM. A band below that hangs a photograph or a field off its top edge (coverage, membership,
   add-ons, steps, contact) met this full-width photograph edge to edge — a picture straight on a
   picture. So, only then, the photograph stops 64px short of the band's bottom edge (the style's
   ed-clear-b seam), and those 64px take the NEXT band's ground: the beat alternates, so it is the tint
   under an odd band and the base stock under an even one. */
:where(.sl-body).sl-style-layered-editorial .rt > [data-sl-section="why"]:has(+ :is([data-sl-section="locations"], :where(.sl-body) [data-sl-section="membership"], :where(.sl-body) [data-sl-section="addons"], :where(.sl-body) [data-sl-section="steps"], :where(.sl-body) [data-sl-section="contact"])) .bk-ovl {
  --eds-clear: 64px; --eds-strip: var(--bk-tint);
}
:where(.sl-body).sl-style-layered-editorial .rt > [data-sl-section="why"]:nth-child(even of :is(section, :where(.sl-body) :has(section))):has(+ :is([data-sl-section="locations"], :where(.sl-body) [data-sl-section="membership"], :where(.sl-body) [data-sl-section="addons"], :where(.sl-body) [data-sl-section="steps"], :where(.sl-body) [data-sl-section="contact"])) .bk-ovl {
  --eds-strip: var(--bk-paper-base);
}
@media (max-width: 1099px) {
  :where(.sl-body).sl-style-layered-editorial .rt .bk-ovl .bk-ovl-card { width: calc(var(--eds-x) + 6 * var(--eds-colw) + 5 * var(--eds-gut) + 40px); padding: 40px 40px 44px var(--eds-x); }
}
/* a phone: the photograph stands above the card (4:3, never under it), the card overlaps its foot */
@media (max-width: 859px) {
  :where(.sl-body).sl-style-layered-editorial .rt .bk-ovl:not(.bk-ovl-noart) { display: block; padding: calc(75% - 48px) 0 0; --eds-clear: 0px; background-color: var(--bk-paper); }
  :where(.sl-body).sl-style-layered-editorial .rt .bk-ovl:not(.bk-ovl-noart)::before { inset: 0 0 auto 0; aspect-ratio: 4 / 3; background-position: 62% var(--sl-focus-y, 30%); }
  :where(.sl-body).sl-style-layered-editorial .rt .bk-ovl .bk-ovl-card { width: auto; margin: 0 var(--eds-gut) 0 0; padding: 32px var(--eds-gut) var(--eds-pad) var(--eds-x); }
  :where(.sl-body).sl-style-layered-editorial .rt .bk-ovl .bk-ovl-card > ul > li b { font-size: 22px; }
  :where(.sl-body).sl-style-layered-editorial .rt .bk-ovl .bk-ovl-ctas { gap: 14px 20px; }
}

/* ── CONDITIONS ─────────────────────────────────────────────────────────────────────────────────── */
/* NOT A BRICK PANEL ON THIS PAGE. A primary slab sat directly above membership's primary pill — the same
   colour and the same flat rectangle back to back — and its two-column list left one name alone. It is
   the page's quiet type spread instead: the title block and the actions on the left, the names as a
   ruled list on the right, on the band's own ground. */
:where(.sl-body).sl-style-layered-editorial .rt .bk-cond { padding: var(--eds-pad) var(--eds-x); background: var(--bk-paper); column-gap: var(--eds-gut); }
:where(.sl-body).sl-style-layered-editorial .rt .bk-cond .bk-cond-panel {
  display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--eds-gut); align-items: start; align-content: start;
  padding: 0; border-radius: 0; background: none; box-shadow: none; color: var(--eds-ink); text-align: left;
}
:where(.sl-body).sl-style-layered-editorial .rt .bk-cond .bk-cond-panel > * { grid-column: 1 / 7; min-width: 0; }
:where(.sl-body).sl-style-layered-editorial .rt .bk-cond .bk-cond-panel > .bk-cond-eyebrow { grid-row: 1; }
:where(.sl-body).sl-style-layered-editorial .rt .bk-cond .bk-cond-panel > h2 { grid-row: 2; color: var(--eds-ink); }
:where(.sl-body).sl-style-layered-editorial .rt .bk-cond .bk-cond-panel > .bk-cond-lead { grid-row: 3; max-width: none; margin: 16px 0 0; font: italic 400 24px/1.3 var(--eds-display); color: var(--eds-ink-soft); }
:where(.sl-body).sl-style-layered-editorial .rt .bk-cond .bk-cond-panel > .bk-cond-ctas { grid-row: 4; margin-top: 40px; }
:where(.sl-body).sl-style-layered-editorial .rt .bk-cond .bk-cond-panel > ul {
  grid-column: 8 / 13; grid-row: 2 / span 3; display: block; margin: 0; padding: 0; list-style: none; border-top: 1px solid var(--eds-ink);
}
:where(.sl-body).sl-style-layered-editorial .rt .bk-cond .bk-cond-panel > ul > li {
  margin: 0; padding: 18px 0 19px; border: 0; border-bottom: 1px solid var(--eds-rule); border-radius: 0; background: none; line-height: 1.15;
  font: italic 400 30px/1.15 var(--eds-display); letter-spacing: -.01em; color: var(--eds-ink); text-align: left;
}
:where(.sl-body).sl-style-layered-editorial .rt .bk-cond .bk-cond-panel > ul > li::before { content: none; }
/* with a photograph beside it, the panel is one column and the photograph square and flush */
:where(.sl-body).sl-style-layered-editorial .rt .bk-cond.bk-cond-beside .bk-cond-panel > * { grid-column: 1 / -1; grid-row: auto; }
:where(.sl-body).sl-style-layered-editorial .rt .bk-cond.bk-cond-beside .bk-cond-panel > ul { grid-column: 1 / -1; grid-row: auto; margin-top: 32px; }
:where(.sl-body).sl-style-layered-editorial .rt .bk-cond .bk-cond-ph, :where(.sl-body).sl-style-layered-editorial .rt .bk-cond .bk-cond-ph img { border-radius: 0 !important; box-shadow: none; }
@media (max-width: 1099px) {
  :where(.sl-body).sl-style-layered-editorial .rt .bk-cond .bk-cond-panel > .bk-cond-lead { font-size: 21px; }
  :where(.sl-body).sl-style-layered-editorial .rt .bk-cond .bk-cond-panel > ul > li { font-size: 26px; }
}
@media (max-width: 859px) {
  :where(.sl-body).sl-style-layered-editorial .rt .bk-cond .bk-cond-panel > * { grid-column: 1 / -1; grid-row: auto; }
  :where(.sl-body).sl-style-layered-editorial .rt .bk-cond .bk-cond-panel > ul { grid-column: 1 / -1; grid-row: auto; margin-top: 32px; }
  :where(.sl-body).sl-style-layered-editorial .rt .bk-cond .bk-cond-panel > .bk-cond-lead { font-size: 20px; }
  :where(.sl-body).sl-style-layered-editorial .rt .bk-cond .bk-cond-panel > ul > li { padding: 14px 0 15px; font-size: 24px; }
  :where(.sl-body).sl-style-layered-editorial .rt .bk-cond .bk-cond-panel > .bk-cond-ctas { gap: 14px 22px; }
}

/* ── ABOUT ──────────────────────────────────────────────────────────────────────────────────────── */
/* On the spread grid: the photograph square and run off the left edge (bleed-l to c 6), the words from
   c 7, the first paragraph as a display standfirst. With no photograph the words take the whole spread. */
:where(.sl-body).sl-style-layered-editorial .rt .bk-prose {
  display: grid; grid-template-columns: var(--eds-spread); column-gap: var(--eds-gut);
  padding: var(--eds-pad) 0; background: var(--bk-paper);
}
:where(.sl-body).sl-style-layered-editorial .rt .bk-prose .bk-prose-in { display: contents; }
:where(.sl-body).sl-style-layered-editorial .rt .bk-prose .bk-prose-copy { grid-column: c 1 / c -1; min-width: 0; max-width: none; text-align: left; }
:where(.sl-body).sl-style-layered-editorial .rt .bk-prose.bk-prose-has-photo .bk-prose-photo {
  grid-column: bleed-l / c 6; align-self: stretch; position: relative; display: block; margin: 0; padding: 0; border: 0; min-height: 440px;
}
:where(.sl-body).sl-style-layered-editorial .rt .bk-prose.bk-prose-has-photo .bk-prose-photo img {
  position: absolute; inset: 0; width: 100%; height: 100%; min-height: 0; border-radius: 0; box-shadow: none; object-fit: cover;
}
:where(.sl-body).sl-style-layered-editorial .rt .bk-prose.bk-prose-has-photo .bk-prose-copy { grid-column: c 7 / c -1; align-self: center; }
:where(.sl-body).sl-style-layered-editorial .rt .bk-prose .bk-prose-head { margin: 0; }
:where(.sl-body).sl-style-layered-editorial .rt .bk-prose .bk-prose-head > h2 { display: block; width: auto; }
:where(.sl-body).sl-style-layered-editorial .rt .bk-prose .bk-prose-body { margin-top: 32px; max-width: none; }
:where(.sl-body).sl-style-layered-editorial .rt .bk-prose .bk-prose-body p { margin: 0 0 16px; font: 400 17px/1.65 var(--eds-body); color: var(--eds-ink-soft); }
:where(.sl-body).sl-style-layered-editorial .rt .bk-prose .bk-prose-body p:last-child { margin-bottom: 0; }
:where(.sl-body).sl-style-layered-editorial .rt .bk-prose .bk-prose-body p.bk-prose-lead {
  margin-bottom: 24px; padding: 0; border: 0; font: 400 26px/1.35 var(--eds-display); letter-spacing: -.005em; color: var(--eds-ink);
}
:where(.sl-body).sl-style-layered-editorial .rt .bk-prose .bk-prose-cta { margin-top: 36px; font: 400 17px/1.4 var(--eds-body); color: var(--eds-ink-soft); }
@media (max-width: 1099px) {
  :where(.sl-body).sl-style-layered-editorial .rt .bk-prose.bk-prose-has-photo .bk-prose-photo { min-height: 380px; }
  :where(.sl-body).sl-style-layered-editorial .rt .bk-prose .bk-prose-body p.bk-prose-lead { font-size: 22px; }
}
@media (max-width: 859px) {
  :where(.sl-body).sl-style-layered-editorial .rt .bk-prose.bk-prose-has-photo .bk-prose-photo { grid-column: bleed-l / bleed-r; min-height: 0; aspect-ratio: 4 / 3; }
  :where(.sl-body).sl-style-layered-editorial .rt .bk-prose.bk-prose-has-photo .bk-prose-copy { grid-column: c 1 / c -1; margin-top: 40px; }
  :where(.sl-body).sl-style-layered-editorial .rt .bk-prose .bk-prose-body { margin-top: 24px; }
  :where(.sl-body).sl-style-layered-editorial .rt .bk-prose .bk-prose-body p.bk-prose-lead { font-size: 21px; }
}

/* ── THE CLOSING ASK ────────────────────────────────────────────────────────────────────────────── */
/* ON THE PAGE'S OWN GROUND, NOT THE BRAND PRIMARY. A full-width primary slab directly above contact's
   primary field was two brick masses back to back. It takes its turn in the white/tint beat instead, as a
   signed-off spread: the title under its rule on the left, the lines and the actions under a rule on the
   right. (RetailHome stops asking contact to clear a primary band above it on this style.) */
:where(.sl-body).sl-style-layered-editorial .rt .rt-closing {
  display: grid; grid-template-columns: var(--eds-spread); column-gap: var(--eds-gut); align-items: start; align-content: start;
  padding: var(--eds-pad) 0; background-color: var(--bk-paper); color: var(--eds-ink); text-align: left;
}
:where(.sl-body).sl-style-layered-editorial .rt .rt-closing > h2 { grid-column: c 1 / c 7; grid-row: 1 / span 3; color: var(--eds-ink); }
:where(.sl-body).sl-style-layered-editorial .rt .rt-closing > :not(h2) { grid-column: c 8 / c -1; min-width: 0; max-width: none; opacity: 1; }
:where(.sl-body).sl-style-layered-editorial .rt .rt-closing > p { margin: 12px 0 0; font: 400 17px/1.55 var(--eds-body); color: var(--eds-ink-soft); }
:where(.sl-body).sl-style-layered-editorial .rt .rt-closing > p.rt-closing-line { font: italic 400 26px/1.3 var(--eds-display); color: var(--eds-ink); }
:where(.sl-body).sl-style-layered-editorial .rt .rt-closing > h2 + :is(p, :where(.sl-body) .rt-closing-cta) { margin-top: 0; padding-top: 20px; border-top: 1px solid var(--eds-ink); }
:where(.sl-body).sl-style-layered-editorial .rt .rt-closing > .rt-closing-cta { margin-top: 36px; }
@media (max-width: 1099px) {
  :where(.sl-body).sl-style-layered-editorial .rt .rt-closing > p.rt-closing-line { font-size: 22px; }
}
@media (max-width: 859px) {
  :where(.sl-body).sl-style-layered-editorial .rt .rt-closing > h2, :where(.sl-body).sl-style-layered-editorial .rt .rt-closing > :not(h2) { grid-column: c 1 / c -1; grid-row: auto; }
  :where(.sl-body).sl-style-layered-editorial .rt .rt-closing > h2 + :is(p, :where(.sl-body) .rt-closing-cta) { margin-top: 20px; padding-top: 0; border-top: 0; }
  :where(.sl-body).sl-style-layered-editorial .rt .rt-closing > p.rt-closing-line { font-size: 21px; }
  :where(.sl-body).sl-style-layered-editorial .rt .rt-closing > .rt-closing-cta { margin-top: 28px; gap: 14px 22px; }
}
/* THE CONTACT BAND TAKES ITS TURN TOO. Its design fixes the tint, which was right under a primary closing
   band; with the closing band now in the beat, a fixed tint could land tint-on-tint with no seam. It
   reads the beat like the six editorial bands around it (the law: its colour lives in its shapes). */
:where(.sl-body).sl-style-layered-editorial .rt .bk-contact.bk-ed.bk-contact-ed.bk-style-layered-editorial { --ground: var(--bk-paper); }

/* ── FOOTER ─────────────────────────────────────────────────────────────────────────────────────── */
:where(.sl-body).sl-style-layered-editorial .rt .rt-foot {
  display: grid; grid-template-columns: var(--eds-spread); column-gap: var(--eds-gut);
  padding: 96px 0 40px; background: var(--bk-dark); color: color-mix(in oklab, var(--eds-paper) 80%, var(--bk-dark));
}
:where(.sl-body).sl-style-layered-editorial .rt .rt-foot .rt-foot-cols {
  grid-column: c 1 / c -1; display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); column-gap: var(--eds-gut); row-gap: 40px; padding: 0 0 72px;
}
:where(.sl-body).sl-style-layered-editorial .rt .rt-foot .rt-foot-cols > div { grid-column: span 3; min-width: 0; }
:where(.sl-body).sl-style-layered-editorial .rt .rt-foot .rt-foot-cols > div:first-child { grid-column: 1 / 7; }
:where(.sl-body).sl-style-layered-editorial .rt .rt-foot .rt-foot-cols h4 {
  display: flex; align-items: center; gap: 14px; margin: 0 0 22px;
  font: 600 14px/1 var(--eds-body); letter-spacing: .02em; text-transform: none; color: var(--eds-paper);
}
:where(.sl-body).sl-style-layered-editorial .rt .rt-foot .rt-foot-cols h4::before { content: ''; flex: none; width: 40px; height: 1px; background: currentColor; }
:where(.sl-body).sl-style-layered-editorial .rt .rt-foot .rt-foot-cols > div:first-child h4 { display: block; font: 500 32px/1.05 var(--eds-display); letter-spacing: -.015em; }
:where(.sl-body).sl-style-layered-editorial .rt .rt-foot .rt-foot-cols > div:first-child h4::before { content: none; }
:where(.sl-body).sl-style-layered-editorial .rt .rt-foot .rt-foot-cols p { max-width: 44ch; font: 400 15px/1.6 var(--eds-body); }
:where(.sl-body).sl-style-layered-editorial .rt .rt-foot .rt-foot-cols li { margin: 0 0 12px; font: 400 15px/1.3 var(--eds-body); }
:where(.sl-body).sl-style-layered-editorial .rt .rt-foot a:hover { color: var(--eds-paper); text-decoration: underline 1px; text-underline-offset: 4px; }
:where(.sl-body).sl-style-layered-editorial .rt .rt-foot .rt-legal {
  grid-column: c 1 / c -1; padding-top: 20px; border-top: 1px solid color-mix(in oklab, var(--eds-paper) 18%, var(--bk-dark));
  font: 400 13px/1.5 var(--eds-body); color: color-mix(in oklab, var(--eds-paper) 64%, var(--bk-dark)); text-align: left;
}
@media (max-width: 859px) {
  :where(.sl-body).sl-style-layered-editorial .rt .rt-foot { padding-top: 64px; }
  :where(.sl-body).sl-style-layered-editorial .rt .rt-foot .rt-foot-cols > div, :where(.sl-body).sl-style-layered-editorial .rt .rt-foot .rt-foot-cols > div:first-child { grid-column: 1 / -1; }
  :where(.sl-body).sl-style-layered-editorial .rt .rt-foot .rt-foot-cols { padding-bottom: 48px; }
  :where(.sl-body).sl-style-layered-editorial .rt .rt-foot .rt-foot-cols > div:first-child h4 { font-size: 28px; }
}
@media (min-width: 600px) and (max-width: 859px) {
  :where(.sl-body).sl-style-layered-editorial .rt .rt-foot .rt-foot-cols > div:nth-child(2) { grid-column: 1 / 7; }
  :where(.sl-body).sl-style-layered-editorial .rt .rt-foot .rt-foot-cols > div:nth-child(3) { grid-column: 7 / 13; }
}
/* ── end PAGE SKIN: layered-editorial ── */

/* A SPLIT HERO HAS TO FIT A SMALL PHONE, PICTURE AND ALL.

   Top Tier's About page measured 669px of first band in a 640px window: 357px of words, a 32px
   gap, a 240px photograph and 38px of padding. Twenty-nine pixels over, which is enough that a
   visitor on a 360px phone sees the hero and NOTHING else - no hint that the page continues, so
   no reason to scroll. That is the whole fault fold-fit exists to catch and it was the last thing
   standing between a finished site and a publish.

   Trimmed where it costs least, in this order: the gap between the words and the picture, then
   the band's own padding, then a cap on the picture. Nothing about the type moves - the headline
   and the paragraph are the content, and shrinking those to win pixels is how a page ends up
   unreadable on the device most people hold. The result is about 594px, which leaves a margin
   rather than squeaking under by one pixel: a band that fits by 1px fails again the next time a
   word wraps.

   Scoped to the split hero so a full-bleed or gradient hero, which has no second column to
   stack, keeps the air it was designed with. */
@media (max-width: 400px) {
  :where(.sl-body) .hero:has(.hero-split) { padding-top: 10px; padding-bottom: 10px; }
  :where(.sl-body) .hero .hero-split { gap: 16px; }
  /* The FRAME is capped, not just the picture: capping only the <img> left the 4:3 frame at full
     height with a grey band under the photograph (seen on the Ridgeline contact page, 2026-09-21). */
  :where(.sl-body) .hero .hero-split .hero-image { aspect-ratio: auto; height: 200px; }
  :where(.sl-body) .hero .hero-split .hero-image img { height: 100%; object-fit: cover; }
}

/* ══ THE OMG CREDIT IN A HOME FAMILY'S FOOTER ════════════════════════════════════════════════════
   The house standard (Footer.astro .footer-agency, RetailHome .rt-foot-agency, BlueprintChrome):
   a hairline rule, the OMG mark centred at 22px and 75% (100% on hover), one line of small text
   under it. Bright, Community, Bloom and Estate footers never carried it — found 2026-09-21 when
   those footers began to be drawn on every page. The mark is painted in the footer's OWN ink (a
   mask over currentColor) rather than as the light image, because some brands' footers are light
   (Stack IV's estate chrome is warm bone) and the light image vanishes there. */
:where(.sl-body) .sl-foot-agency { margin-top: 18px; padding-top: 16px; border-top: 1px solid color-mix(in srgb, currentColor 16%, transparent); display: flex; flex-direction: column; align-items: center; gap: 7px; text-align: center; }
:where(.sl-body) .sl-foot-agency a { display: inline-flex; opacity: .75; transition: opacity .15s ease; color: inherit; }
:where(.sl-body) .sl-foot-agency a:hover { opacity: 1; }
:where(.sl-body) .sl-foot-agency .sl-omg-mark { display: block; width: 264px; max-width: 70vw; height: 22px; background: currentColor; -webkit-mask: url(/omg-logo.svg) center / contain no-repeat; mask: url(/omg-logo.svg) center / contain no-repeat; }
:where(.sl-body) .sl-foot-agency span.sl-omg-tag { font-size: 12px; letter-spacing: .04em; opacity: .6; }
@media (prefers-reduced-motion: reduce) { :where(.sl-body) .sl-foot-agency a { transition: none; } }
