
/* Fraunces and Inter, self-hosted (2026-10-10). They replaced Bricolage Grotesque, which was
   doing both jobs at once -- every heading squeezed to 72% width in capitals, and every paragraph
   in the same face. Peter: "I need something different because this is just not working well."
   He chose this pairing off a specimen sheet of five: a warm serif announces, a plain sans
   explains. The two files together are 137KB, within a kilobyte of the one Bricolage file they
   replace, so the first paint costs what it always did.

   FRAUNCES is the display face: headings, the story lines, the note card's blanks, ordinals.
   Mixed case, weight 600 -- NOT uppercase. Putting the capitals back puts the old problem back.
   INTER is everything else: body copy, the small tracked-caps labels (eyebrows, tags, nav, the
   tab bar, the plates' own stamped names) and measured numbers.

   Both are the exact latin variable woff2 Google served for this site's axis request, all axes
   intact: Fraunces opsz 9..144, wght 300..900; Inter opsz 14..32, wght 300..800. Licences:
   assets/fonts/OFL-Fraunces.txt and OFL-Inter.txt (SIL OFL 1.1 -- shipping them alongside the
   fonts is a condition of the licence, not a courtesy).

   There is no @font-face descriptor for the optical-size axis: opsz is carried in each font's
   own fvar table and applied by font-optical-sizing, whose initial value is auto. body restates
   font-optical-sizing:auto so the dependency is visible rather than implied.

   latin-ext is declared but gated by unicode-range, so it costs nothing on the wire for the
   current content and is fetched only if a product name ever gains a character that needs it.

   Nothing on this site touches a Google server: a grep for their hostnames across site-src/ and
   the generated pages should stay empty. Both templates preload BOTH latin files -- the headline
   and the first paragraph are above the fold, so each one is render-critical. */
@font-face{
  font-family:"Fraunces";
  font-style:normal;
  font-weight:300 900;
  font-display:swap;
  src:url("assets/fonts/fraunces-v38-latin.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:"Fraunces";
  font-style:normal;
  font-weight:300 900;
  font-display:swap;
  src:url("assets/fonts/fraunces-v38-latin-ext.woff2") format("woff2");
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C4,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
@font-face{
  font-family:"Inter";
  font-style:normal;
  font-weight:300 800;
  font-display:swap;
  src:url("assets/fonts/inter-v20-latin.woff2") format("woff2");
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}
@font-face{
  font-family:"Inter";
  font-style:normal;
  font-weight:300 800;
  font-display:swap;
  src:url("assets/fonts/inter-v20-latin-ext.woff2") format("woff2");
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C4,U+2113,U+2C60-2C7F,U+A720-A7FF;
}
:root{
  /* Two darks, one sand, one greige ground */
  --teal:#002E3B;--pearl:#1E262F;--beige:#E2C8AE;--sand:#E6D3C5;--soft:#D6D4C9;--tile:#E2DFD7;--chalk:#FAF6EF;--mindful:#BDB6AD;
  --text:#415365;--ink:#1E262F;--line:rgba(30,38,47,.18);--on-dark:#C4D2D4;
  --r:0px;
  /* NEITHER FACE HAS A WIDTH AXIS, so any font-stretch left in a rule does nothing at all --
     it is not a squeeze that became subtle, it is dead. Say what you mean with weight and size.
     Fraunces is set MIXED CASE at 600; see the note above the @font-face blocks. */
  --display:Fraunces,Georgia,"Times New Roman",serif;
  --sans:Inter,system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
  /* the accent, every real button and the keyword in a heading. It was the XS can's blue (#3340B8)
     until 2026-10-29, when Peter chose a warmer ground and a copper accent ("the pale feels just a touch
     too pale"). #A9471F, not the prototype's #B4512A: white on it is 5.82:1 and it is 4.59:1 as text on
     the ground, where #B4512A was 3.99 and failed small copy. */
  --accent:#A9471F;
  --accent-ink:#8C3A19;   /* the same copper a step deeper, for SMALL copper text: 4.9:1 even at the warm glow's peak, where --accent is 3.7 */
  --hero:#033246; /* the dark half of the hero video, so the panel and the film share one edge */
  --pad:max(20px,env(safe-area-inset-left,0px),env(safe-area-inset-right,0px));--sec:72px;--mast:60px;
  /* --mast is the bar's own height; --tabh the tab switch's row under it (0 from 1024, where the switch
     stands in the bar); --mh the whole masthead, which is what anchors and the pinned strip clear */
  --tabh:40px;--mh:calc(var(--mast) + var(--tabh));
  --ease:520ms cubic-bezier(.2,.7,.2,1);
}
*,*::before,*::after{box-sizing:border-box}
/* the canvas takes its colour from html and extends the gradient's end colours into the
   overscroll areas: teal above the mast, black under the black footer. body's own chalk
   covers the document, so the gradient is only ever seen past the ends of the page. */
html{-webkit-text-size-adjust:100%;scroll-padding-top:calc(var(--mh) + var(--srch,0px));background:linear-gradient(var(--teal) 0 50%,#000 50% 100%)}
html.locked{overflow:hidden}
body::before{content:"";position:fixed;inset:0;z-index:9;pointer-events:none;opacity:.5;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='.055'/%3E%3C/svg%3E");background-size:160px 160px}
body{margin:0;background:var(--chalk);color:var(--text);font:16px/1.55 var(--sans);font-optical-sizing:auto;-webkit-tap-highlight-color:transparent;-webkit-font-smoothing:antialiased}
h1,h2{font-family:var(--display);font-weight:600;color:var(--teal);margin:0;line-height:1.03;letter-spacing:-.018em;text-wrap:balance}
h3{font:600 17px/1.3 var(--sans);color:var(--ink);margin:0}
p{margin:0}
a{color:inherit}
img{max-width:100%}
button,input{font:inherit;color:inherit}
button{cursor:pointer}
a,button,summary,label,[role="button"]{touch-action:manipulation}
/* a long-press on a control selects its words, or opens the iOS link preview on a nav link; neither
   is wanted on a control (emilkowalski/skills, mobile-native). Body text and product cards keep both. */
.btn,.tlink,.icon-btn,.chip,.mc-opt,.rk-plate,.tab,.mtab a,.g-jump a,.lbpin-go,.st-rev>summary,.repeat-go{-webkit-user-select:none;user-select:none}
.tab,.mtab a,.g-jump a,.lbpin-go,.rk-plate{-webkit-touch-callout:none}
:focus-visible{outline:2px solid var(--teal);outline-offset:3px}
.dark :focus-visible,.mast :focus-visible,.menu :focus-visible,.rk-panel :focus-visible{outline-color:var(--sand)}
[hidden]{display:none!important}
.vh{position:absolute!important;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.skip{position:absolute;left:8px;top:-200px;z-index:50;background:var(--sand);color:var(--teal);padding:12px 16px;min-height:44px;border-radius:var(--r)}
.skip:focus{top:8px}
.ic{width:24px;height:24px;fill:none;stroke:currentColor;stroke-width:1.5;stroke-linecap:square;flex:none}
.ic-sm{width:18px;height:18px}
.wrap{width:100%;max-width:calc(1200px + 2 * var(--pad));margin:0 auto;padding:0 var(--pad)}

/* One label style, one size */
.label{font:600 12px/1.3 var(--sans);letter-spacing:.16em;text-transform:uppercase;color:var(--text)}

/* Actions */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:10px;min-height:54px;padding:0 28px;border:0;border-radius:var(--r);background:var(--accent);color:#fff;font:600 16px/1.2 var(--sans);text-decoration:none;text-align:center}
.btn{transition:transform 160ms cubic-bezier(.23,1,.32,1),opacity 160ms}
.btn:active{opacity:.85;transform:scale(.97)}
@media (prefers-reduced-motion:reduce){.btn:active{transform:none}}

.btn-line{background:transparent;color:var(--teal);box-shadow:inset 0 0 0 1px var(--teal)}
/* the same button at the 44px hit height the mast and the text links already use */
.btn-sm{min-height:44px;padding:0 18px;font-size:14px}
.tlink{display:inline-flex;align-items:center;min-height:44px;padding:0;border:0;background:transparent;color:var(--teal);font:600 16px/1.2 var(--sans);text-decoration:underline;text-decoration-thickness:1.5px;text-underline-offset:6px}
.tlink:active{opacity:.7}
.tlink:active{opacity:.7}
.icon-btn{position:relative;display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;padding:0;border:0;border-radius:var(--r);background:transparent;color:inherit}
.icon-btn:active{background:rgba(255,255,255,.1)}

/* Motion: rise-in on entry */
.motion .grow{opacity:0;transform:translate(0,16px);transition:transform var(--ease),opacity var(--ease);transition-delay:calc(var(--d,0) * 70ms)}
.motion .grow.in{opacity:1;transform:none}
@media (prefers-reduced-motion:reduce){.motion .grow{opacity:1;transform:none;transition:none}}

/* 1 + 2. Header: menu, wordmark, search. Search opens as a row on phones. */
.mast{position:sticky;top:env(safe-area-inset-top,0px);z-index:20;background:var(--teal);color:var(--sand)}
.bar{display:grid;grid-template-columns:44px 1fr auto auto;align-items:center;gap:4px;height:60px}
.sound-toggle{color:var(--sand)}
.wordmark{justify-self:center;display:inline-flex;align-items:center;gap:10px;min-height:44px;font-family:var(--sans);font-weight:800;font-size:14px;letter-spacing:.2em;text-transform:uppercase;white-space:nowrap;color:var(--sand);text-decoration:none}
/* the wave: 4.11:1, filled rather than stroked, so it needs a wide slot of its own */
.wordmark .mark{width:103px;height:25px;flex:none;fill:currentColor;stroke:none}
/* 361-479: the compact bar cannot carry the 103px wave beside the wordmark at full size.
   The content is 404px wide; with the page's 40px of side padding it needs a 444px
   viewport, so below that the name takes the compact setting and the mark 84x20. Measured,
   not guessed: at 390 this was 404px of content in a 350px bar, and the search toggle was
   clipped off the page entirely. */
@media (max-width:479px){.mast .wordmark{gap:6px;font-size:11px;letter-spacing:.08em}
  .mast .wordmark .mark{width:84px;height:20px}}
/* the menu bar carries only the close button and the wordmark, so the wave keeps its
   103px there; under 420 the name takes the compact setting, as 260px of wordmark
   overruns a 320px panel by 23px. */
.menu .wordmark .mark{width:103px;height:25px}
@media (max-width:419px){.menu .wordmark{gap:6px;font-size:11px;letter-spacing:.08em}}
/* 419 and down the wave alone carries the bar. Beside the name it could only be 56px
   there, which is not really the mark; with the name out of the way the bar has room for
   140. The name stays in the accessibility tree and in the page title. */
/* 2026-10-24: THE NAME IS BACK ON PHONES, UNDER THE WAVE. A Fable critic found that below 420 the masthead
   was the wave alone and the hero's eyebrow was hidden too, so a visitor from a shared link never saw
   "Aspire Health" until the footer, ~5,000px down. There is no room beside the wave (menu, wave, sound and
   search share 280-350px), so the two stack: the wave, then the name in small tracked caps under it. */
@media (max-width:419px){.mast .wordmark{flex-direction:column;gap:3px;line-height:1}
  .mast .wordmark .wm-name{font-size:9.5px;letter-spacing:.24em;padding-left:.24em}
  .mast .wordmark .mark{width:112px;height:27px}}
/* the smallest phones: the wave steps down so the pair still clears the sound and search buttons */
@media (max-width:360px){.mast .wordmark .mark{width:96px;height:23px}}
.nav-inline{display:none}
.search{display:flex;gap:8px;padding:0 0 14px}
.js .mast:not(.s-open) .search{display:none}
.search{position:relative}
.search input{flex:1;min-width:0;height:44px;padding:0 44px 0 14px;border:1px solid rgba(230,211,197,.4);border-radius:var(--r);background:rgba(230,211,197,.06);color:var(--chalk);font-size:16px;-webkit-appearance:none;appearance:none}
.search input::placeholder{color:var(--on-dark);opacity:1}
.search input:focus{border-color:var(--sand);outline:none;box-shadow:inset 0 0 0 1px var(--sand)}
.search-go{position:absolute;right:0;top:0;color:var(--sand)}
html:not(.js) .search-toggle{visibility:hidden}

/* The tab: the calculator and the call, hung from the foot of the window. The pair moves as
   one: off screen and out of the tab order until the script adds .on, which it does only
   while nothing it could cover is in view and the curtain is gone (the tab block in the
   script lists what); the open menu (html.locked) sends it away again. No script, no tab.
   The calculator wears the mast's teal and micro-type; the call is the filled blue of every
   primary button, because it is the one that matters. Each half runs down into the safe
   area, so its colour reaches the edge of the glass. */
.mtab{position:fixed;left:0;right:0;bottom:0;z-index:19;width:max-content;max-width:100%;margin:0 auto;
  display:flex;border:1px solid rgba(230,211,197,.3);border-bottom:0;border-radius:var(--r);background:var(--teal);
  transform:translateY(calc(100% + 2px));visibility:hidden;
  transition:transform var(--ease),visibility 0s linear 520ms}
.mtab.on{transform:none;visibility:visible;transition:transform var(--ease),visibility 0s}
/* the bar steps aside while someone is typing, so it never floats over a field or the keyboard (mobile-native) */
html:has(:is(input:not([type=checkbox],[type=radio],[type=hidden]),textarea,select):focus) .mtab{transform:translateY(calc(100% + 2px));visibility:hidden}
html.locked .mtab{transform:translateY(calc(100% + 2px));visibility:hidden}
.mtab a{display:flex;align-items:center;justify-content:center;min-height:calc(44px + env(safe-area-inset-bottom,0px));
  padding:0 18px env(safe-area-inset-bottom,0px);font:600 12px/1 var(--sans);letter-spacing:.14em;text-transform:uppercase;
  white-space:nowrap;text-decoration:none}
.mtab-calc{color:var(--sand)}
.mtab-call{background:var(--accent);color:#fff}
.mtab a:active{opacity:.85}
.mtab a:focus-visible{outline:2px solid var(--sand);outline-offset:-6px}
/* at full tracking the two halves are 359px together: the call ran off the right edge under 360
   and sat 0.4px from both edges at 360. Under 375 a little less tracking and padding brings them
   to 312, whole on a 320 screen and clear of the edges at 360 */
@media (max-width:374.98px){.mtab a{padding-inline:12px;letter-spacing:.08em}}
/* 1024 and up the mast carries both (MACROS in its nav, and its own free-call button), so the tab
   is a phone's and a tablet's only: left on, its lone calculator half floated bottom-centre over
   whatever was under it on every desktop page */
@media (min-width:1024px){.mtab{display:none!important}}
html:not(.js) .mtab{display:none}
@media (prefers-reduced-motion:reduce){.mtab,.mtab.on{transition:none}}

/* 3. Hero: headline on solid teal, the glass explosion to the right over a teal/beige split */
.hero{position:relative;isolation:isolate;overflow:hidden;background:var(--hero);color:var(--on-dark)}
.hero-copy{position:relative;z-index:2;min-width:0;display:grid;gap:16px;justify-items:start;padding-top:28px;padding-bottom:12px}
.hero .label{color:var(--sand)}
.hero h1{color:var(--chalk);font-size:clamp(52px,17vw,72px)}
.hero h1 span{display:block;white-space:nowrap}
.hero .sub{max-width:34ch;color:var(--on-dark);font-size:16px;text-wrap:balance}
.hero .tlink{color:var(--sand)}
.hero-actions{display:flex;flex-wrap:wrap;align-items:center;gap:12px 28px;margin-top:6px}
.hero-actions{width:100%}
.hero-actions .btn{flex:1 1 100%}
.hero-copy{padding-bottom:28px}
/* phones: the subhead's two lines are paid for out of the copy's top padding and the gap
   above the buttons, so "Work out your macros" still sits whole on the first screen at
   375x812 after the curtain. Measured: the button's foot at 798, not 812. */
@media (max-width:767px){.hero-copy{padding-top:20px}.hero-actions{margin-top:0}}
/* phones: the label goes (the subhead already says what this is), the headline is a step smaller and
   the copy's top padding is 8, not 12. (Peter's picture and line used to sit beside the button here, as
   .hero-me; Tab 1's hero now carries them at its foot as .hh-me, below.) */
@media (max-width:767px){
  .hero-copy{gap:12px;padding-top:8px}
  .hero .label{display:none}
  .hero h1{font-size:clamp(46px,15vw,72px)}
}
/* the shop's hero on a phone (2026-10-04, Peter): the square film stays as it is, so the copy is what gives.
   The headline steps down to 44px on two lines ("Picked for how" / "you train.") and the lead comes in
   under the two ways on, so "Pick your goal" is whole on the first screen. */
@media (max-width:480px){
  .hero-shop h1{font-size:clamp(40px,12.5vw,44px)}
  .hero-shop h1 span:not(.hl-3d){display:inline}
  .hero-shop .sub{order:1;font-size:16px}   /* after the ways on: 715 -> 653 at 390x844, 662 -> 575 at 320x640 */
}
/* SHORT phones (2026-10-29, two critics): at 375x667 -- the iPhone SE, and every phone with its browser bars
   showing -- "Pick your goal" ended 14px below the screen. The film is fixed, so the headline gives the room:
   a smaller size on a short screen only, the same words on the same two lines. */
@media (max-width:480px) and (max-height:700px){
  .hero-shop h1{font-size:34px}
  .hero-shop .hero-copy{padding-top:4px}
}
.glass{position:relative;margin:0 calc(-1 * var(--pad));aspect-ratio:1;overflow:hidden}
.glass video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;background:linear-gradient(90deg,var(--teal) 50%,var(--beige) 50%)}
/* The film's play/pause, out of the way until it is wanted (Peter, 2026-10-09). At rest it is
   opacity:0 and pointer-events:none — NOT display:none or visibility:hidden, either of which would
   take it out of the Tab order, and this is the page's one way to stop motion that starts by itself
   (WCAG 2.2.2). It fades in on a hover anywhere over the film and on its own focus ring, so a mouse
   finds it by going to the film and a keyboard finds it by tabbing to it.
   ON A TOUCHSCREEN IT NEVER APPEARS (Peter, 2026-10-09: "remove the paly pause button on touchscreens as
   well"). There was a `@media (hover:none){...opacity:1}` rule here keeping it visible where there is no
   hover; he was told that removing it leaves a phone with no visible way to stop the film, and chose it
   anyway. It is HIS CALL ON HIS OWN SITE and it is recorded here — do not restore that rule without asking
   him. The button stays in the DOM and in the Tab order on purpose, so a tablet with a keyboard can still
   reach it, and prefers-reduced-motion still stops the film before it is ever fetched. */
.glass-toggle{position:absolute;z-index:3;left:14px;bottom:14px;width:40px;height:40px;border-radius:50%;
  background:var(--teal);color:var(--chalk);opacity:0;pointer-events:none;transition:opacity 180ms linear}
.glass-toggle:focus-visible{opacity:1;pointer-events:auto}
@media (hover:hover) and (pointer:fine){.glass:hover .glass-toggle,.glass-toggle:hover{opacity:1;pointer-events:auto}}
.glass-toggle:active{background:var(--teal);opacity:.8}
.glass-toggle .ic{width:18px;height:18px}
@media (prefers-reduced-motion:reduce){.glass-toggle{transition:none}}

/* Sections */
.sec{padding:var(--sec) 0}
/* Where two of them meet, each side lays a full --sec of ground on the join, so the boundary
   reads as 2 x --sec of nothing: 144px on a phone and 224px at 1440, over and over down the page
   (Peter, 2026-10-01: "it feels a little busy on the website... it feels like a freaking journey
   for them to actually get where they want to go"). A join keeps one full --sec and half of the
   other, so a band still stands clear of the one above it and nothing is cramped: 108px and 168px.
   Only the lower section gives, and only where two really touch — the first band under the hero
   keeps its own. .story was not a .sec while it was a stage and had to be named here; it is an
   ordinary .sec since 2026-10-01, so the first selector carries it. The second is the join
   #my-stack / #consult, which has the Amway <dialog> standing between them. The same idea as .how-sec's negative margin and
   .rack-sec's trimmed foot, which both already pulled one join in; they still win, being later. */
.sec + .sec,.sec + dialog + .sec{padding-top:calc(var(--sec) * .5)}
/* The game plan (#how): the path, four numbered steps and one thing to do. It sits on the page's
   own ground between the story and the shelves, closed off from each by a hairline. On a phone
   each step is a row (number, words, arrow); from 768 they stand in two columns, from 1024 in four. */
.how-sec{padding-bottom:0}
.how-sec>.wrap{padding-bottom:var(--sec);border-bottom:1px solid var(--line);
  width:calc(100% - 2 * var(--pad));max-width:1200px;padding-inline:0}
/* phones: the plan's close to the rack's heading was ~160px of empty field; the hairline now sits
   32px under the plan and the section gives back 40px of the rack's top padding */
@media (max-width:767px){.how-sec{margin-bottom:-40px}.how-sec>.wrap{padding-bottom:32px}}
/* the story sits straight under the hero now and the plan follows it (2026-10-02), both on the same
   field, so the turn from their story to the steps was only more empty ground under a centred ask. The
   plan takes a hairline over its head too, the same rule that closes it off from the rack below, so it
   reads as its own framed stretch between the story and the shelves. The join keeps its size: the
   section's half --sec moves inside, under the line, so the line sits a full --sec under the story's
   last link and half of one over "New here?". */
.story + .how-sec{padding-top:0}
.story + .how-sec>.wrap{border-top:1px solid var(--line);padding-top:calc(var(--sec) * .5)}
.how-head{display:grid;gap:10px;margin-bottom:24px}
.how-head h2{font-size:40px}
.how-steps{list-style:none;margin:0;padding:0;display:grid;border-top:1px solid var(--line)}
.how-steps li{border-bottom:1px solid var(--line)}
.how-step{display:grid;grid-template-columns:40px minmax(0,1fr) 18px;column-gap:14px;row-gap:4px;
  padding:16px 0;color:inherit;text-decoration:none}
.how-n{grid-row:1 / span 2;font:700 28px/1 var(--display);color:var(--teal)}
.how-t{grid-column:2;font:600 17px/1.3 var(--sans);color:var(--ink)}
.how-d{grid-column:2;font-size:15px;line-height:1.5;color:var(--text)}
.how-ic{grid-column:3;grid-row:1 / span 2;align-self:center;color:var(--teal)}
a.how-step:active{opacity:.7}
@media (hover:hover){a.how-step:hover .how-t{text-decoration:underline;text-decoration-thickness:1.5px;text-underline-offset:4px}}
.how-go{display:flex;flex-wrap:wrap;align-items:center;gap:6px 28px;margin-top:28px}
.how-go .btn{flex:1 1 100%}
/* the plan's trust line, over its button in ink and a step up from body copy: the strongest line here */
.how-fine{flex-basis:100%;margin-bottom:10px;font:600 18px/1.35 var(--sans);color:var(--ink);text-wrap:balance}
@media (min-width:768px){
  .how-head{margin-bottom:40px}
  .how-head h2{font-size:52px}
  .how-steps{grid-template-columns:repeat(2,minmax(0,1fr));column-gap:24px;border-top:0}
  .how-steps li{border-bottom:0;border-top:1px solid var(--line)}
  .how-step{grid-template-columns:minmax(0,1fr) 18px;row-gap:8px;padding:18px 0 28px}
  .how-n{grid-row:auto;grid-column:1;font-size:44px}
  .how-ic{grid-row:1;grid-column:2;align-self:start}
  .how-t,.how-d{grid-column:1 / -1}
  .how-go{margin-top:12px}
  .how-go .btn{flex:none}
}
@media (min-width:1024px){.how-steps{grid-template-columns:repeat(5,minmax(0,1fr))}}
/* The game plan in the bar theme (html.t-bar, with script): the steps hang on a steel shaft, each
   number on a small bumper plate seen face on, the rack's rubber and the bar's steel. Down the left
   on phones and tablets; from 1024 across the top of the four columns. As the section scrolls through
   (_script.html) the shaft lights from the first plate on, a glint at its front, and each plate
   slides on along the shaft as the light reaches it, overshooting a hair and settling back, as the
   bar's plates do; its title comes up from quiet to full ink. The newest plate is the blue one, as
   on the rack's guide. Until a plate is on, its place is an open ring with the number in it.
   Quiet is still readable: the title at .74 is 5.6:1 or more on the field's darkest glow, the ring's
   number the same, and the line under it never dims. Only transform and opacity change as it plays.
   Reduced motion (no html.motion) shows every plate on and the shaft lit; with no script, the plain
   list above. */
.how-pl,.how-sh{display:none}
.t-bar.js .how-steps{grid-template-columns:minmax(0,1fr);border-top:0;max-width:640px}
.t-bar.js .how-steps li{position:relative;border:0}
.t-bar.js .how-step{position:relative;grid-template-columns:44px minmax(0,1fr) 18px;column-gap:16px;row-gap:4px;padding:14px 0 22px}
/* the place for a plate: an open ring, its number in the teal at .74 (5.5:1 or more) */
.t-bar.js .how-n{position:relative;z-index:1;grid-row:1 / span 2;grid-column:1;align-self:start;display:grid;place-items:center;
  width:44px;height:44px;margin-top:-11px;border-radius:50%;font:700 15px/1 var(--display);letter-spacing:.01em;
  color:rgba(0,46,59,.74);box-shadow:inset 0 0 0 1.5px rgba(0,46,59,.4)}
.t-bar.js .how-t{grid-column:2}
.t-bar.js .how-d{grid-column:2}
.t-bar.js .how-ic{grid-column:3;grid-row:1 / span 2;align-self:center}
/* the plate: teal rubber under the rack's satin light and grain, its edge showing below it, the rim
   stepping down to the face, and a ring of turned steel round the number where the hub would be */
.t-bar.js .how-pl{display:block;position:absolute;inset:0;border-radius:50%;font-style:normal;
  background:var(--rubber),radial-gradient(120% 120% at 32% 16%,rgba(255,255,255,.16),rgba(255,255,255,.03) 40%,rgba(255,255,255,0) 58%),
    radial-gradient(80% 80% at 72% 98%,rgba(0,0,0,.18),rgba(0,0,0,0) 58%),var(--teal);
  background-size:120px 120px,auto,auto,auto;
  box-shadow:inset 0 1px 1px rgba(255,255,255,.22),inset 0 -1.5px 1.5px rgba(0,0,0,.4),inset 0 0 0 .5px rgba(0,0,0,.3),
    0 2px 0 #00161D,0 9px 12px -7px rgba(0,20,27,.55);
  will-change:transform,opacity}
/* the newest plate's face: the blue, over the teal */
.t-bar.js .how-pl::before{content:"";position:absolute;inset:0;border-radius:50%;opacity:0;
  background:var(--rubber),radial-gradient(120% 120% at 32% 16%,rgba(255,255,255,.18),rgba(255,255,255,.04) 40%,rgba(255,255,255,0) 58%),
    radial-gradient(80% 80% at 72% 98%,rgba(0,0,0,.2),rgba(0,0,0,0) 58%),var(--accent);
  background-size:120px 120px,auto,auto,auto}
.t-bar.js .how-pl::after{content:attr(data-n);position:absolute;inset:7%;display:grid;place-items:center;border-radius:50%;
  color:var(--chalk);text-shadow:0 -.75px 0 rgba(0,0,0,.45),0 .75px 0 rgba(255,255,255,.18);
  background:radial-gradient(circle closest-side,rgba(0,0,0,0) 0 71%,rgba(8,12,15,.5) 71% 73.5%,#F2F4F5 73.5% 77%,#B7BFC3 77% 83%,#7C858B 83% 88%,rgba(8,12,15,.45) 88% 90.5%,rgba(0,0,0,0) 90.5%);
  box-shadow:inset 0 1px 1px rgba(0,0,0,.35),inset 0 -1px 0 rgba(255,255,255,.14),0 -1px 0 rgba(0,0,0,.14),0 1px 0 rgba(255,255,255,.12)}
/* the shaft, one stretch from each plate to the next: a dim steel rod until the light reaches it. The
   lit steel (the bar's own gradient, turned) slides down inside it, and carries the glint at its front */
.t-bar.js .how-sh{--steel:linear-gradient(90deg,#5E676D 0,#7D868C 12%,#C2C9CD 30%,#F3F5F6 44%,#E2E6E8 54%,#9BA4A9 76%,#646D73 100%);
  display:block;position:absolute;z-index:0;left:6px;width:32px;top:51px;height:calc(100% - 52px);overflow:hidden;pointer-events:none}
.t-bar.js .how-sh::before,.t-bar.js .how-sh>i::before{content:"";position:absolute;left:12px;width:8px;top:0;bottom:0;border-radius:2px;
  background:repeating-linear-gradient(0deg,rgba(255,255,255,.08) 0 1px,transparent 1px 3px),var(--steel)}
.t-bar.js .how-sh::before{opacity:.3}
.t-bar.js .how-sh>i{position:absolute;inset:0;will-change:transform}
.t-bar.js .how-sh>i::before{box-shadow:0 0 0 .5px rgba(30,38,44,.35)}
.t-bar.js .how-sh>i::after{content:"";position:absolute;left:0;right:0;bottom:-10px;height:26px;opacity:0;
  background:radial-gradient(closest-side,#fff,rgba(255,255,255,.85) 22%,rgba(170,190,255,.45) 52%,rgba(170,190,255,0))}
.t-bar.motion .how-sh>i::after{will-change:opacity}
.t-bar.js .how-sh.run>i::after{opacity:1}
/* playing: plates wait above their places (the way the light comes), shafts dark, titles quiet */
.t-bar.motion .how-steps .grow{opacity:1;transform:none;transition:none}
.t-bar.motion .how-pl{opacity:0;transform:translate3d(0,-16px,0) scale(.94);
  transition:transform 360ms cubic-bezier(.22,1.2,.36,1.04),opacity 140ms linear}
.t-bar.motion .how-pl::before{transition:opacity 240ms linear;will-change:opacity}
.t-bar.motion .how-sh>i{transform:translate3d(0,-100%,0)}
.t-bar.motion .how-t,.t-bar.motion .how-ic{opacity:.74;transition:opacity 300ms linear;will-change:opacity}   /* each on its own layer from the start: fading it costs no layout */
.t-bar.motion .how-ic{opacity:.45}
.t-bar.motion .on .how-pl{opacity:1;transform:none}
.t-bar.motion .on .how-t,.t-bar.motion .on .how-ic{opacity:1}
.t-bar.motion .now .how-pl::before{opacity:1}
@media (prefers-reduced-motion:reduce){.t-bar.motion .how-pl,.t-bar.motion .how-pl::before,.t-bar.motion .how-t,.t-bar.motion .how-ic{transition:none}}
@media (min-width:768px){
  .t-bar.js .how-steps{column-gap:0}
  .t-bar.js .how-step{grid-template-columns:44px minmax(0,1fr) 18px;row-gap:6px;padding:16px 0 26px}
  .t-bar.js .how-n{grid-row:1 / span 2;grid-column:1;font-size:15px}
  .t-bar.js .how-ic{grid-row:1 / span 2;grid-column:3;align-self:center}
  .t-bar.js .how-t,.t-bar.js .how-d{grid-column:2}
  .t-bar.js .how-t{font-size:18px}
  .t-bar.js .how-sh{top:53px}
}
/* from 1024: one bar across the top of the five columns, the plates on it, the light running left to
   right. Five, not four, since the plan gained the macro-breakdown-or-a-call step: a fifth that wrapped
   to a second row would sit off the end of the shaft, with nothing running into its plate. */
@media (min-width:1024px){
  .t-bar.js .how-steps{grid-template-columns:repeat(5,minmax(0,1fr));column-gap:20px;max-width:none}
  .t-bar.js .how-step{grid-template-columns:minmax(0,1fr) 18px;row-gap:8px;padding:6px 0 28px}
  .t-bar.js .how-n{grid-row:1;grid-column:1;width:56px;height:56px;margin:0 0 10px;font-size:18px}
  .t-bar.js .how-t{grid-row:2;grid-column:1}
  .t-bar.js .how-d{grid-row:3;grid-column:1 / -1}
  .t-bar.js .how-ic{grid-row:2;grid-column:2;align-self:center}
  .t-bar.js .how-sh{--steel:linear-gradient(#E2E6E8 0,#F3F5F6 16%,#C2C9CD 36%,#9BA4A9 62%,#737C82 88%,#5E676D 100%);
    left:62px;top:18px;width:calc(100% - 44px);height:32px}
  .t-bar.js .how-sh::before,.t-bar.js .how-sh>i::before{left:0;right:0;top:12px;bottom:auto;width:auto;height:9px;
    background:repeating-linear-gradient(90deg,rgba(255,255,255,.07) 0 1px,transparent 1px 3px),var(--steel)}
  .t-bar.js .how-sh>i::after{left:auto;top:0;bottom:0;right:-12px;width:30px;height:auto}
  .t-bar.motion .how-pl{transform:translate3d(-20px,0,0) scale(.94)}
  .t-bar.motion .how-sh>i{transform:translate3d(-100%,0,0)}
}

/* Shelves: one tab per goal, one pack per panel */
.shelves-sec .sec-head{margin-bottom:22px}
.shelf-tabs{display:flex;gap:2px;overflow-x:auto;scrollbar-width:none;margin:0 calc(-1 * var(--pad));
  padding:0 var(--pad);border-bottom:1px solid var(--line)}
.shelf-tabs::-webkit-scrollbar{display:none}
.shelf-tab{flex:none;min-height:52px;padding:0 16px;border:0;background:transparent;color:var(--text);
  font:600 15px/1.2 var(--sans);white-space:nowrap;box-shadow:inset 0 -2px 0 transparent;transition:color .15s,box-shadow .15s}
.shelf-tab[aria-selected="true"]{color:var(--teal);box-shadow:inset 0 -2px 0 var(--teal)}
@media (hover:hover){.shelf-tab:hover{color:var(--teal)}}
.shelf-panel{padding-top:24px;min-height:300px}
.shelf-link{display:grid;gap:16px;align-items:center;color:inherit;text-decoration:none}
.shelf-art{display:block;width:min(240px,62%);justify-self:center}
.shelf-art img{display:block;width:100%;height:auto}
.shelf-copy{display:grid;gap:8px;justify-items:start}
.shelf-name{font:600 38px/1.06 var(--display);letter-spacing:-.018em;color:var(--teal)}
.shelf-desc{max-width:34ch}
.shelf-picks{font-size:14px;color:var(--text);max-width:40ch}
.shelf-go{margin-top:4px;font:600 16px/1.2 var(--sans);color:var(--teal);text-decoration:underline;
  text-decoration-thickness:1.5px;text-underline-offset:6px}
@media (hover:hover){.shelf-link:hover .shelf-go{text-decoration-thickness:2.5px}}
/* Generated backdrops: one image per band, masked so it dissolves into the ground */
.isles-sec,.results,.consult,.cat-shop{position:relative;isolation:isolate}
/* Dark bands. The trending band (off; TRENDING in build_homepage.py) is the only one left,
   and .podium-sec.no-pour below puts it back on the page's own field. */
.podium-sec{background:var(--teal)}
/* Category pages: the sand band that sends you to the calculator */
.cat-macros{background:var(--sand);color:var(--text)}
.goals-sec{padding-bottom:0}
.sec-head{display:flex;flex-wrap:wrap;align-items:baseline;justify-content:space-between;gap:6px 24px;margin-bottom:28px}
.sec-head>div{display:grid;gap:10px}
.sec-head h2,.split-text h2{font-size:40px}
.sec-head h2:focus{outline:none}
.sec-head .tlink{flex:none}
.sec-note{font-size:16px}

/* 4. Goals: a typographic index, one ruled row per goal */
.goal-index{list-style:none;margin:0;padding:0;border-top:1px solid var(--line)}
.goal-index li{border-bottom:1px solid var(--line)}
.goal{display:grid;grid-template-columns:minmax(0,1fr) 96px;grid-template-areas:"name img" "desc img" "n img";column-gap:16px;align-items:center;padding:18px 0;color:var(--teal);text-decoration:none}
.goal:active{opacity:.7}

@media (hover:hover){.goal:hover .goal-name{text-decoration:underline;text-decoration-thickness:2px;text-underline-offset:6px}.goal:hover .goal-n{text-decoration:underline;text-underline-offset:4px}.card-link:hover .p-name{text-decoration:underline;text-underline-offset:4px;text-decoration-thickness:1px}.tlink:hover{text-decoration-thickness:2.5px}}
.goal-name{grid-area:name;font:600 25px/1.1 var(--display);letter-spacing:-.014em}
.goal-index{counter-reset:goal}

.goal-desc{grid-area:desc;margin-top:8px;font-size:16px;line-height:1.35;color:var(--text)}
.goal-n{grid-area:n;margin-top:6px;font-size:15px;font-variant-numeric:tabular-nums;color:var(--text)}
.goal-img{grid-area:img;display:block;width:88px;aspect-ratio:1;justify-self:end;overflow:hidden}
.goal-island{grid-area:img;display:flex;align-items:center;justify-content:flex-end;width:96px;height:78px}
.goal-island img{display:block;max-width:100%;max-height:100%;width:auto;height:auto;filter:drop-shadow(0 10px 10px rgba(30,38,47,.25))}
.goal-img img{display:block;width:100%;height:100%;object-fit:contain}

/* 5. Products: one backdrop, no chrome */
.filter{display:flex;align-items:center;justify-content:space-between;gap:12px;margin:-8px 0 24px;padding:8px 0;border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
/* The filter line echoes whatever was typed into the search box, so its longest token is
   a stranger's, not Peter's: "Nothing matches “zzzz…”" is as wide as the reader cares to
   make it. As a flex item this p had min-width:auto, so it grew to the token's min-content
   width (403px at 320) and shoved the Close button off the page. min-width:0 lets it
   shrink, anywhere lets the token break, and Close keeps its own width. */
.filter p{min-width:0;overflow-wrap:anywhere;color:var(--ink)}
.filter .tlink{flex:none}
.grid{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:32px 12px}
.card{display:flex;flex-direction:column;min-width:0}
.card-link{display:block;color:inherit;text-decoration:none}
.shot{position:relative;display:block;aspect-ratio:6/5;padding:0 6% 4%}
.shot-studio{aspect-ratio:1;padding:0}
.shot img{position:relative;z-index:1;display:block;width:100%;height:100%;object-fit:contain;object-position:50% 100%}
.grid .shot,.slide .shot{isolation:isolate}
.grid .shot::before,.slide .shot::before{content:"";position:absolute;left:4%;right:4%;top:2%;bottom:6%;z-index:-2;border-radius:50%;
  background:radial-gradient(58% 52% at 50% 46%,rgba(255,255,255,.72),rgba(255,255,255,0) 78%)}
/* the re-lit studio packs carry their own contact shadow; everything else gets one here */
.grid .shot:not(.shot-studio)::after,.slide .shot:not(.shot-studio)::after{content:"";position:absolute;left:22%;right:22%;bottom:3%;height:7%;z-index:-1;border-radius:50%;
  background:radial-gradient(closest-side,rgba(30,38,47,.3),rgba(30,38,47,0))}
.card-link:active .shot{opacity:.85}
.ph{display:flex;align-items:center;justify-content:center;aspect-ratio:1;padding:10px;text-align:center;font-size:13px;line-height:1.35;color:var(--text);background:var(--tile);border-radius:var(--r)}
.ph-cap b{font-weight:600;letter-spacing:.14em;text-transform:uppercase}
.p-tag{margin-top:10px;font:400 14px/1.3 var(--sans);color:var(--text)}
.p-name{margin-top:4px;font:500 16px/1.3 var(--sans);color:var(--ink)}
.card-link{display:grid}
.p-desc{margin-top:3px;font-size:14px;line-height:1.45;color:var(--text)}
/* Product copy is Peter's, straight out of share-links.csv, and a flavour can arrive as one
   unbreakable token: "Strawberry/Watermelon" is 21 characters and no line-break opportunity,
   because a solidus is not one. At 320 that token is 160px wide in a 127px card and printed
   over its neighbour. `anywhere` lets it break mid-token as a last resort -- and, unlike
   break-word, it also drops the token out of the min-content width, so a card in a
   percentage or auto track cannot be forced wide by it either. Every place a product name
   or description is printed uses these three classes: both grids, the carousel slides, the
   and the podium. Guard the class, not the one row in the CSV. */
.p-tag,.p-name,.p-desc{overflow-wrap:anywhere}
/* rows share text heights: each card spans three subgrid rows. Both grids also need an
   explicit single column: with only grid-template-rows set, the card's one column is auto,
   and an auto track takes the min-content width of its item. .shot carries aspect-ratio, so
   when the subgrid row is taller than its ratio wants -- which happens in any row that also
   holds a square .shot-studio -- the ratio transfers that height back into a width and the
   track blows past the card. minmax(0,1fr) pins the column to the card instead. */
.shop .grid{row-gap:0}
.shop .grid .card{display:grid;grid-row:span 4;grid-template-rows:subgrid;grid-template-columns:minmax(0,1fr);padding-bottom:36px}
.shop .grid .card-link{grid-row:1 / 5;display:grid;grid-template-rows:subgrid;grid-template-columns:minmax(0,1fr)}
.more{margin-top:40px;padding-top:20px;border-top:1px solid var(--line)}
.shop .grid{column-gap:12px}

/* Dark bands and the two-column split */
.dark{background:var(--teal);color:var(--on-dark)}
.dark h2{color:var(--chalk)}
.cat-macros h2 span{display:block;white-space:nowrap}
.dark .label{color:var(--on-dark)}
.split{display:grid;grid-template-columns:minmax(0,1fr);gap:32px}
.split-text{display:grid;gap:14px;align-content:start;justify-items:start}
.split-text p:not(.label){max-width:42ch}

/* 7. Consult: four answers, then a time on the calendar */
.consult{overflow:hidden;overflow:clip;color:var(--text)}  /* clip, not hidden: hidden would make this a scroll box, and nothing sticky inside it could stick */
.consult .split-text p:not(.label){max-width:40ch}
/* the left column tightens up without losing a word of Peter's two lines: the offer and the
   Amway disclaimer under it read as one block rather than three spaced paragraphs, and the
   column sits closer to the card. 24px off the band at 390, and nothing is cramped — the
   disclaimer is a footnote to the offer, which is where it now sits. */
.consult .split-text{gap:10px}
.consult .split-text p:not(.label) + p:not(.label){margin-top:-4px}
.consult .wrap.split{row-gap:24px}
.c-fine{font-size:14px;color:var(--text)}
/* the homepage's call over the lake at dusk (.c-dusk): the copy beside the card turns chalk, the card itself
   is unchanged. The scrim darkens the sky behind the copy (top-left on a laptop, top on a phone) and leaves
   the afterglow on the horizon to show. Its own full top padding: a dark band needs room above its heading. */
.consult-dusk{background:#141A26;color:var(--chalk);padding-top:var(--sec)}
.c-dusk{position:absolute;inset:0;z-index:-1}
.c-dusk img{display:block;width:100%;height:100%;object-fit:cover;object-position:50% 58%}
/* the scrim's last 200px (the band's 112px foot and a little above it, clear of the copy) dissolve into the
   section's own dark, so the picture never stops on a hard line where the footer begins (2026-10-04) */
.c-dusk::after{content:"";position:absolute;inset:0;background:linear-gradient(180deg,rgba(8,14,24,.55),rgba(8,14,24,.2) 45%,rgba(8,14,24,.1) 70%,
  rgba(8,14,24,.45) calc(100% - 200px),#141A26 calc(100% - 24px))}
.consult-dusk .split-text,.consult-dusk .split-text h2{color:var(--chalk)}
.consult-dusk .split-text .label{color:var(--sand)}
.consult-dusk .split-text p:not(.label){opacity:.92}
/* from 768 the copy and the card stand side by side, and the afterglow (the frame's centre) fell right behind
   the card's left edge. The picture is drawn 140% wide and set 40% left, so the glow sits at about 30% of
   the band, under the copy's open sky, and the treeline still reaches the right edge. */
@media (min-width:768px){.c-dusk{overflow:hidden}.c-dusk img{width:140%;max-width:none;margin-left:-40%}}
/* phones: the card covers most of the band, so the dusk is its own strip above the heading, fading into the
   dark field the copy and the card sit on (a critic, 2026-10-03: "the dusk lake is invisible on a phone") */
/* 2026-10-04: at 390 "Book a free call" landed on ~316px of lake, so the strip is ~160px, and an arrival at
   #consult (a negative scroll-margin past the join's half --sec, the strip and its margin) puts the eyebrow just under the
   masthead with the heading and the card's first question on the first screen; scrolling past still shows it */
@media (max-width:767px){
  .consult-dusk{--dusk-h:clamp(140px,41vw,180px);padding-top:0;scroll-margin-top:calc(16px - var(--sec) * .5 - var(--dusk-h) - 28px)}
  .c-dusk{position:relative;inset:auto;z-index:auto;height:var(--dusk-h);margin-bottom:28px}
  .c-dusk img{object-position:50% 60%}
  .c-dusk::after{background:linear-gradient(180deg,rgba(20,26,38,.15),rgba(20,26,38,0) 40%,rgba(20,26,38,0) 60%,#141A26)}
}
/* and the footer's nightfall starts from the dusk's own dark instead of fading in over the page's light
   ground, which put a pale strip between the dusk and the night (a critic, 2026-10-03) */
body:has(.consult-dusk) .foot{background:linear-gradient(#141A26 0,rgb(6,11,14) var(--dusk),#000 calc(var(--dusk) + 1px))}
/* the calculator's numbers, carried into the consult after "See my numbers": the card's
   tiles and micro-labels, smaller, one row at every width. The script owns [hidden]. */
.c-nums{display:grid;gap:8px;width:100%;max-width:40ch;margin-bottom:10px}
.c-nums-list{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px}
.c-nums-list li{display:grid;gap:4px;justify-items:center;min-width:0;padding:10px 2px;background:var(--tile);text-align:center}
.c-nums-g{font:700 clamp(18px,5.6vw,24px)/1 var(--sans);font-variant-numeric:tabular-nums;letter-spacing:-.01em;color:var(--teal);white-space:nowrap}
.c-nums .mc-lab{font-size:11px;letter-spacing:.06em}
/* Peter's proof, which closes #story: the before and after, all three views stacked, nothing
   to swipe. Every img carries its width and height, so nothing jumps when the lazy files land. */
.c-proof{display:grid;gap:10px;width:100%;min-width:0;margin:4px 0 0}
/* the three files share one crop, so a 1fr 1fr row above the stack puts the two headings on
   the very 50% line every image splits on: one pair labels all three. */
.c-cols{display:grid;grid-template-columns:1fr 1fr;gap:0}
.c-cols span{font:600 11px/1 var(--sans);letter-spacing:.16em;text-transform:uppercase;
  color:var(--text);opacity:.62;text-align:center}
.c-stack{display:grid;gap:8px;min-width:0}
.c-stack img{display:block;width:100%;height:auto;background:var(--tile)}
.c-proof figcaption{font-size:14px;color:var(--text)}
.c-card{display:grid;gap:22px;padding:24px 20px 26px;background:rgba(244,242,236,.86);
  box-shadow:inset 0 0 0 1px rgba(30,38,47,.12),0 40px 60px -40px rgba(0,30,39,.55)}
@supports (backdrop-filter:blur(6px)){.c-card{backdrop-filter:blur(10px);background:rgba(244,242,236,.7)}}
.c-q{margin:0;padding:0;border:0;min-width:0}
.c-q legend{display:block;padding:0;margin-bottom:10px;font:600 15px/1.3 var(--sans);color:var(--ink)}
/* the macro calculator's move to the form focuses its first question (or the calendar, once it
   is up) so the reading position follows; a landing spot, not a control, so no ring, as .mc-q */
.c-q legend:focus{outline:none}
.chips{display:flex;flex-wrap:wrap;gap:8px}
/* the label wraps a hidden radio; the span is the pill, so :checked styles a sibling.
   max-width keeps the two long training answers inside the card at 320px: the pill shrinks
   and its text wraps to a second line rather than pushing the row wider than the screen. */
.chip{position:relative;display:inline-flex;max-width:100%;min-width:0;cursor:pointer}
.chip input{position:absolute;width:1px;height:1px;opacity:0;margin:0}
.chip span{position:relative;display:inline-flex;align-items:center;gap:9px;overflow:hidden;
  min-height:44px;padding:9px 13px;
  border:1px solid var(--line);background:rgba(255,255,255,.5);color:var(--ink);
  font:600 15px/1.25 var(--sans);
  --sheen:rgba(0,46,59,.14);                 /* the sweep, dark on the pale pill */
  transition:background .15s,color .15s,border-color .15s,box-shadow .18s,transform .18s cubic-bezier(.2,.7,.2,1)}
/* a selected chip is picked up off the card: it lifts, casts a shadow, and holds a lit inner
   edge along its top. All three survive greyscale, so selection never rests on colour alone. */
.chip input:checked + span{background:var(--teal);border-color:var(--teal);color:var(--chalk);
  transform:translateY(-2px);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.28),inset 0 0 0 1px rgba(255,255,255,.14),
             0 10px 16px -10px rgba(0,30,39,.85);
  --sheen:rgba(255,255,255,.5)}               /* and light on the teal one */
.chip input:focus-visible + span{outline:2px solid var(--teal);outline-offset:3px}
@media (hover:hover){
  .chip:hover span{border-color:var(--teal);transform:translateY(-1px)}
  .chip input:checked + span{transform:translateY(-2px)}
}
/* The emblems: 22px objects, forward when their chip is chosen. Decorative — the pill's own
   text is the accessible name, and each svg carries aria-hidden in the markup. */
.em{width:22px;height:22px;flex:none;overflow:visible;
  transition:transform .18s cubic-bezier(.2,.7,.2,1),filter .18s}
.chip input:checked + span .em{transform:translateY(-1px) scale(1.1);
  filter:drop-shadow(0 2px 2px rgba(0,0,0,.45))}
/* The shimmer: one specular sweep, fired by the act of choosing (and on hover, where there is
   a pointer to hover with). Not an idle loop — five pills glinting on their own next to a
   submit button is exactly the skeleton-loader look, and it would pull against the CTA.
   Tied to the choice instead, it reads as the chip acknowledging the tap, which is also the
   only version a phone ever gets to see. */
.chip span::after{content:"";position:absolute;inset:0;pointer-events:none;opacity:0;
  background:linear-gradient(104deg,transparent 38%,var(--sheen) 50%,transparent 62%)}
.chip input:checked + span::after{animation:chip-sheen 620ms cubic-bezier(.35,.6,.25,1)}
@media (hover:hover){.chip:hover span::after{animation:chip-sheen 760ms cubic-bezier(.35,.6,.25,1)}}
@keyframes chip-sheen{
  from{opacity:1;transform:translate3d(-120%,0,0)}
  to{opacity:1;transform:translate3d(120%,0,0)}
}
/* reduced motion: no sweep and nothing moves. The teal fill, the lit inner edge and the cast
   shadow stay, so a selected chip is still unmistakable. */
@media (prefers-reduced-motion:reduce){
  .chip span,.em{transition:none}
  .chip span::after{display:none}
  .chip:hover span,.chip input:checked + span{transform:none}
  .chip input:checked + span .em{transform:none}
}
.c-field{display:grid;gap:8px}
.c-field label{font:600 15px/1.3 var(--sans);color:var(--ink)}
.c-field label span{font-weight:400;color:var(--text)}
.c-field input{height:52px;padding:0 14px;border:1px solid var(--line);border-radius:var(--r);
  background:rgba(255,255,255,.62);color:var(--ink);font-size:16px;-webkit-appearance:none;appearance:none}
.c-field input:focus{outline:none;border-color:var(--teal);box-shadow:inset 0 0 0 1px var(--teal)}
.c-card .btn{width:100%}
.c-sum{font-size:14px;color:var(--text);margin-top:-12px}
/* nothing chosen yet, nothing to say: the line leaves the card's grid entirely rather than
   holding a blank row and its 22px gap open under the button */
.c-sum:empty{display:none}

/* Free sample (#sample): the consult's card, chips and fields, on the sand band. Only the
   checkboxes, the hints and the errors are its own. */
.sample-sec{background:var(--sand);color:var(--text)}
.s-hint{font-size:14px;color:var(--text);margin:0}
.s-mail-note{display:none;margin-top:10px}
#sample-form:has(input[name="delivery"][value^="Mail"]:checked) .s-mail-note{display:block}
.s-err{margin:0;font:600 14px/1.35 var(--sans);color:#9B2C1F}
.s-err:empty{display:none}
.c-field input[aria-invalid="true"]{border-color:#9B2C1F;box-shadow:inset 0 0 0 1px #9B2C1F}
.s-checks{display:grid;gap:12px}
.s-check{display:flex;gap:12px;align-items:flex-start;font:500 15px/1.4 var(--sans);color:var(--ink);cursor:pointer}
.s-check input{flex:none;width:22px;height:22px;margin:0;accent-color:var(--teal)}
.s-check em{font-style:normal;font-weight:400;color:var(--text)}
#sample-form[aria-busy="true"] .btn{opacity:.7;cursor:progress}
/* the thank-you: kept out of the layout until the script shows it (.on) or FormSubmit sends a
   no-script visitor back to #sample-sent, when :target shows it and :has puts the form away */
.s-done{display:none;gap:10px;align-content:start}
.s-done.on,.s-done:target{display:grid}
.s-done h3{font:600 29px/1.08 var(--display);letter-spacing:-.016em;color:var(--teal)}
.s-done h3:focus{outline:none}
.sample-sec:has(.s-done:target) #sample-form{display:none}
.consult-dusk:has(.s-done:target) #consult-form{display:none}
/* what happens after "Request my sample": three numbered lines under the button */
.s-next{list-style:none;margin:-8px 0 0;padding:0;display:grid;gap:8px;counter-reset:sn}
.s-next li{position:relative;padding-left:32px;font-size:14px;line-height:1.45;color:var(--ink);counter-increment:sn}
.s-next li::before{content:counter(sn);position:absolute;left:0;top:-1px;width:21px;height:21px;display:grid;place-items:center;
  font:700 11px/1 var(--sans);color:var(--teal);box-shadow:inset 0 0 0 1px var(--teal)}
/* the quick call: inside the thank-you, once a sample is sent (the card that stood under the form
   went on 2026-10-01: the calculator follows the sample now). Its button is built by quick_call(). */
.qc{display:grid;gap:12px;justify-items:start;padding:20px;box-shadow:inset 0 0 0 1px var(--line)}
.qc-ask{font:600 17px/1.35 var(--sans);color:var(--ink);max-width:36ch}
.qc .btn{width:100%}
.s-done .qc{margin-top:8px;padding:18px 0 0;box-shadow:none;border-top:1px solid var(--line)}
.s-step3{display:grid;gap:8px;justify-items:start;margin-top:8px}
/* From 768 the sample's words stand level with the card's middle, not at its top over an empty
   column: the second row they shared was for the quick-call card, which went on 2026-10-01. Phones
   keep the words above the card. */
@media (min-width:768px){
  .sample-sec .split{align-items:center}
  .sample-sec .split-text{grid-row:1}
  .sample-sec .c-card{grid-row:1}
  .qc .btn{width:auto}
}
/* The free sample (#sample) reads as a note to Peter: a fill-in-the-blank sentence in the display
   type, in two short steps with script. Every field keeps its real label, visually hidden, and the
   sentence around it is aria-hidden. The blanks grow as they fill (the script sizes them), the
   chips sit in the sentence as words. Without script nothing is hidden: one form.
   The card itself is no longer the sample's alone: the shell, the display face, the blanks and the
   pills are .nc below, which the consult form wears too. What stays under #sample here is only what
   the SENTENCE needs — the hidden legends, the inline chips, the separators, the growing blanks. */
#sample-form.s-two[data-step="1"] #s-step2,#sample-form.s-two[data-step="2"] #s-step1{display:none}
/* .nc is that note-card hand, lifted out of #sample so the consult form can wear it too: the shell,
   the heavy condensed display face, the underlined blanks and the dashed choice pills. --ncs is the
   face's size, set once per card and stepped at the breakpoints, so a card (or one fieldset) that
   needs smaller words only changes that one number. Nothing below is #sample's any more. */
.nc{--ncs:28px}
.c-card.nc,.c-embed.nc{position:relative;border-radius:30px;background:var(--chalk);
  box-shadow:inset 0 0 0 2px var(--ink),8px 8px 0 var(--teal);
  backdrop-filter:none;-webkit-backdrop-filter:none}
.c-card.nc{padding:40px 22px 22px}
.c-embed.nc{overflow:hidden}   /* the calendar fills the shell, clipped to its radius, and keeps its 700px */
#sample .btn,.nc .btn{border-radius:999px}
#sample .s-step{display:block;min-width:0;font:400 28px/1.62 var(--display);color:var(--ink)}
#sample .s-step:focus{outline:none}
#sample .s-say{font-weight:600;letter-spacing:-.012em}
#sample .c-q{display:contents}
#sample .s-ps{display:block}
#sample .c-q legend,#sample .c-field label{position:absolute;width:1px;height:1px;margin:-1px;padding:0;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
/* the choices, as words in the sentence: dashed until picked, then a teal pill knocked askew */
#sample .chips{display:inline}
#sample .chip{display:inline-flex;vertical-align:baseline}
.nc .chip span{min-height:44px;padding:0 .3em;border:2px dashed rgba(30,38,47,.34);border-radius:999px;
  background:transparent;font:600 var(--ncs)/1 var(--display);color:var(--text)}
.nc .chip input:checked + span{background:var(--teal);border:2px solid var(--ink);color:var(--chalk);
  transform:rotate(-2deg);box-shadow:3px 3px 0 var(--ink)}
@media (hover:hover){
  .nc .chip:hover span{transform:none;color:var(--ink);border-color:var(--ink)}
  .nc .chip:hover input:checked + span{transform:rotate(-2deg);color:var(--chalk)}
}
.nc .chip input:focus-visible + span{outline:3px solid var(--accent);outline-offset:3px}
#sample .s-by .chip + .chip::before,#sample .s-deliv .chip + .chip::before{content:"/" / "";padding:0 .12em;
  font:600 var(--ncs)/44px var(--display);color:rgba(30,38,47,.35)}
#sample .s-deliv .chip + .chip::before{content:"or" / "";padding:0 .22em;color:var(--ink)}
/* the full stop rides on the last choice, so a narrow line can never strand it on its own */
#sample .s-deliv .chip + .chip::after{content:"." / "";padding-left:.06em;font-weight:600;line-height:44px;color:var(--ink)}
/* the blanks: a field and its error stacked in one inline box, so the sentence runs on after it */
#sample .c-field{display:inline-flex;flex-direction:column;vertical-align:baseline;gap:4px;max-width:100%}
.nc .c-field input,.nc .c-field textarea{max-width:100%;border:0;border-radius:0;box-shadow:none;
  font:600 var(--ncs)/1 var(--display);color:var(--accent);-webkit-appearance:none;appearance:none}
.nc .c-field input{height:46px;padding:0 5px;border-bottom:3px solid var(--teal);background:transparent}
.nc .c-field input::placeholder,.nc .c-field textarea::placeholder{color:transparent}
/* the sample's blanks say what goes in them (2026-10-24, a Fable critic: on a phone each blank was a bare
   underline, its label visually hidden). Quiet sans on the line, gone the moment anything is typed. */
#sample .c-field input::placeholder,#sample .c-field textarea::placeholder{color:rgba(65,83,101,.5);font-family:var(--display);font-weight:400;font-size:inherit;letter-spacing:0}   /* the sentence's own face and size, paler, so the hint sits where the typing will */
/* the sentence's blanks grow with what is typed in them; a question's blank holds its row */
#sample .c-field input,#sample .c-field textarea{min-width:4.4em;field-sizing:content}
#sample .c-field[data-by] input,#sample .s-f-item textarea{min-width:6.4em}
.nc .c-field input:focus{outline:none;background:rgba(169,71,31,.08);border-bottom-color:var(--accent);box-shadow:0 3px 0 var(--accent)}
.nc .c-field input[aria-invalid="true"]{border-bottom-color:#9B2C1F;background:rgba(155,44,31,.07);box-shadow:none}
/* the product blank is a textarea so a long name wraps: every line gets its own underline */
#sample .c-field textarea,#consult-form .c-field textarea{--u:var(--teal);display:block;height:46px;padding:4px 5px 0;resize:none;overflow:hidden;
  line-height:42px;overflow-wrap:break-word;background:repeating-linear-gradient(transparent 0 39px,var(--u) 39px 42px) content-box}
#sample .c-field textarea:focus,#consult-form .c-field textarea:focus{--u:var(--accent);outline:none;background-color:rgba(169,71,31,.08)}
#sample .c-field textarea[aria-invalid="true"],#consult-form .c-field textarea[aria-invalid="true"]{--u:#9B2C1F;background-color:rgba(155,44,31,.07)}
#sample .s-full + .s-say{display:none}
/* small phones (a critic, 2026-10-03, at 320: "Text me" jumped right and "/ Email me" stood alone): the two
   choices keep to one line together, and the sentence's face steps down to 24px so they fit it */
#sample .s-by .chips{white-space:nowrap}
#sample-form{container-type:inline-size}
#sample .s-by .chip span,#sample .s-by .chip + .chip::before{font-size:min(var(--ncs),9cqi)}
#sample .s-keep{display:inline;white-space:nowrap}
#sample .s-keep .s-err{white-space:normal}
/* .s-unit is .s-keep's pair for the other two blanks: the blank and the full stop that belongs to it in
   one box, so the stop always travels with the words it ends. Inline, so the sentence reads exactly as
   it did; the two contact blanks share one, since only one of them is ever shown. */
#sample .s-unit{display:inline;white-space:nowrap}   /* the stop wrapped onto its own line at 1024 (a critic, 2026-10-21); a textarea keeps its own pre-wrap */
#sample .s-unit .s-err,#sample .s-unit .s-hint{white-space:normal}
html:not(.js) #sample .s-unit{display:block}   /* no script: both contact blanks stand, each on its own row */
/* PHONES: THE SENTENCE'S BLANKS EACH TAKE THEIR OWN ROW (2026-10-05). Up to 420 the blanks are wide
   next to words set at 28px, and the sentence broke mid-thought wherever a blank happened to land: the
   contact blank sat on the line before "I've had my eye on", "at" was left hanging on its own, and at
   320 the name's blank dropped to a line by itself. Each blank's box is block-level here, so it starts a
   line and the words that introduce it finish the line above: "Hey Peter, I'm / [name]. / Text me /
   Email me at / [contact]. / I've had my eye on / [item]." The stop stays on the blank's own row,
   because it is inside the box. Nothing is reworded; only where the lines break changes. 420 and not 480:
   the shop hero's own phone breakpoint is about the film, and 420 is where the 28px face stops holding a
   blank and a word together. */
@media (max-width:420px){
  #sample .s-keep,#sample .s-unit{display:block;white-space:normal}
  #sample .s-keep .c-field,#sample .s-unit .c-field{max-width:100%}
}
@media (max-width:359px){#sample .s-step{font-size:24px}#sample.nc,#sample .nc{--ncs:24px}}
/* no script: both contact blanks are there at once, so each shows its label above it */
html:not(.js) #sample .c-field[data-by]{display:flex;margin:6px 0}
html:not(.js) #sample .c-field[data-by] label{position:static;width:auto;height:auto;margin:0;overflow:visible;clip:auto;
  white-space:normal;font:600 13px/1.3 var(--sans);color:var(--text)}
.nc .c-field .s-err{contain:inline-size;font-size:14px;line-height:1.35}
#sample .s-hint{font:400 14px/1.4 var(--sans)}
#sample .s-step > .s-hint{margin-top:4px}
#sample .s-deliv .s-hint,#sample .s-deliv .s-err{margin:4px 0 6px}
/* what matches the product blank, from the datalist: tap one, or walk them with the arrow keys */
#sample .s-sugg{list-style:none;margin:10px 0 2px;padding:0;display:grid;gap:6px;font:600 15px/1.3 var(--sans)}
#sample .s-sugg li{display:flex;align-items:center;min-height:44px;padding:8px 16px;border-radius:22px;cursor:pointer;
  background:#fff;box-shadow:inset 0 0 0 1.5px rgba(30,38,47,.22);color:var(--ink)}
#sample .s-sugg li[aria-selected="true"]{background:var(--teal);color:var(--chalk);box-shadow:none}
@media (hover:hover){#sample .s-sugg li:hover{box-shadow:inset 0 0 0 2px var(--ink)}}
/* "Pick from the shelves" (_script.html): a pill under the product blank, and the chooser it opens in
   the card's own flow (it pushes Next down rather than covering anything): first the shelves as small
   plates in their rack colours, with the steel hub, then the tapped shelf's products, each with its
   picture, in a list that scrolls inside itself. Sans type, off the sentence's display face. Hidden
   ([hidden]) until the script shows it. #s-kept is the line that says a card's product went in the P.S. */
#sample .s-pick{margin:12px 0 4px;font:500 15px/1.3 var(--sans)}
#sample .s-pick[hidden],#sample .s-picker[hidden],#sample .sp-view[hidden],#sample .s-kept[hidden]{display:none}
#sample .s-kept{margin:8px 0 2px;color:var(--ink);font-weight:600}
.s-pick-go,.sp-back{display:inline-flex;align-items:center;gap:10px;min-height:44px;padding:0 18px 0 8px;border:0;border-radius:999px;cursor:pointer;
  background:#fff;box-shadow:inset 0 0 0 1.5px rgba(30,38,47,.22);color:var(--ink);font:600 15px/1.2 var(--sans);-webkit-tap-highlight-color:transparent}
.s-pick-go[aria-expanded="true"]{background:var(--teal);color:var(--chalk);box-shadow:none}
.sp-back{gap:6px;padding:0 16px 0 12px;font-size:14px}
.s-pick-go:focus-visible,.sp-back:focus-visible,.sp-plate:focus-visible,.sp-item:focus-visible{outline:3px solid var(--accent);outline-offset:2px}
@media (hover:hover){.s-pick-go:hover,.sp-back:hover,.sp-item:hover{box-shadow:inset 0 0 0 2px var(--ink)}}
/* the pill's mark: a plate, face on, with its hub */
.s-pick-pl{flex:none;width:28px;height:28px;border-radius:50%;
  background:radial-gradient(circle,var(--chalk) 0 13%,#8E979D 14% 17%,#E2E6E8 18% 27%,rgba(0,0,0,.25) 28% 31%,rgba(0,0,0,0) 32%),var(--pearl);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.22),inset 0 -1px 1px rgba(0,0,0,.4)}
.s-picker{margin-top:10px;padding:14px 12px 12px;border-radius:20px;background:color-mix(in srgb,var(--sand) 40%,var(--chalk));
  box-shadow:inset 0 0 0 2px var(--ink)}
.sp-t{margin:0 0 12px 4px;font:600 12px/1.3 var(--sans);letter-spacing:.16em;text-transform:uppercase;color:var(--text)}
/* ten shelves, laid out so none is left alone on a row (three a row left Everyday Health on a fourth):
   always two a row or five. Container queries, so it follows the picker's own width, not the
   window's: from 278px (a 390 phone) two a row with each plate beside its name, five short
   rows; under 278 (320 to 375, where "Foundations" no longer fits beside a plate) two a row with the
   name under the plate; from 440 (the desktop card) five a row, name under plate, two rows. */
.s-picker{container-type:inline-size}
.sp-plates{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px 6px}
.sp-plate{display:grid;justify-items:center;align-content:start;gap:7px;width:100%;min-height:44px;margin:0;padding:6px 2px 8px;border:0;border-radius:14px;
  background:none;cursor:pointer;color:var(--ink);font:700 13px/1.15 var(--sans);text-align:center;-webkit-tap-highlight-color:transparent}
.sp-name{max-width:100%;text-wrap:balance;overflow-wrap:anywhere}
@container (min-width:278px) and (max-width:439.98px){
  .sp-plates{gap:6px}
  .sp-plate{grid-template-columns:auto minmax(0,1fr);justify-items:start;align-items:center;align-content:center;gap:10px;padding:4px 4px 4px 2px;text-align:left}
  .sp-plate .sp-disc{width:40px;height:40px}
}
@container (min-width:440px){.sp-plates{grid-template-columns:repeat(5,minmax(0,1fr));gap:12px 6px}}
.sp-disc{position:relative;display:block;width:52px;height:52px;border-radius:50%;
  background:var(--rubber,none),radial-gradient(120% 120% at 32% 16%,rgba(255,255,255,.14),rgba(255,255,255,0) 58%),var(--c);
  background-size:120px 120px,auto,auto;
  box-shadow:inset 0 1px 1px rgba(255,255,255,.26),inset 0 -1.5px 1.5px rgba(0,0,0,.34),inset 0 0 0 1px rgba(0,0,0,.2),
    0 2px 0 color-mix(in srgb,var(--c) 55%,#0B1115),0 8px 12px -8px rgba(0,20,27,.5);
  transition:transform 200ms cubic-bezier(.2,.7,.2,1)}
.sp-disc::before{content:"";position:absolute;inset:8%;border-radius:50%;box-shadow:inset 0 1px 1px rgba(0,0,0,.3),inset 0 -1px 0 rgba(255,255,255,.16)}
.sp-hole{position:absolute;left:36%;top:36%;width:28%;height:28%;border-radius:50%;
  background:conic-gradient(from -24deg,#F1F3F4,#A9B1B6 9%,#E2E6E8 19%,#8E979D 31%,#CDD3D6 43%,#FBFCFC 51%,#9AA3A8 62%,#D8DDE0 74%,#7E878D 87%,#F1F3F4);
  box-shadow:0 0 0 1px rgba(10,14,17,.35)}
.sp-hole::before{content:"";position:absolute;inset:28%;border-radius:50%;background:var(--chalk);box-shadow:inset 0 1px 1px rgba(0,20,27,.6)}
@media (hover:hover){.sp-plate:hover .sp-disc{transform:translate3d(0,-2px,0)}.sp-plate:hover .sp-name{text-decoration:underline;text-underline-offset:3px}}
.sp-plate:active .sp-disc{transform:translate3d(0,1px,0)}
.sp-head{display:flex;flex-wrap:wrap;align-items:center;gap:6px 12px;margin:0 0 10px}
.sp-head .sp-t{margin:0;letter-spacing:.12em;font-size:13px;color:var(--ink)}
.sp-items{list-style:none;margin:0;padding:2px;display:grid;gap:6px;max-height:min(50vh,380px);overflow-y:auto;overscroll-behavior:contain}
.sp-item{display:flex;align-items:center;gap:12px;width:100%;min-height:56px;margin:0;padding:6px 12px 6px 6px;border:0;border-radius:14px;cursor:pointer;
  background:#fff;box-shadow:inset 0 0 0 1.5px rgba(30,38,47,.14);color:var(--ink);text-align:left;-webkit-tap-highlight-color:transparent}
.sp-th{flex:none;display:grid;place-items:center;width:44px;height:44px;border-radius:10px;overflow:hidden;background:color-mix(in srgb,var(--sand) 55%,var(--chalk))}
.sp-th img{display:block;width:100%;height:100%;object-fit:contain}
.sp-tx{display:grid;gap:2px;min-width:0}
.sp-n{font:600 15px/1.25 var(--sans)}
.sp-k{font:400 13px/1.3 var(--sans);color:var(--text)}
@media (prefers-reduced-motion:reduce){.sp-disc{transition:none}}
#sample .s-step > .btn{margin-top:16px}
#sample .s-checks,#sample .s-acts,#sample .s-step > .s-err{margin-top:22px}
#sample .s-next{margin-top:20px}
#sample .c-fine{margin-top:18px;line-height:1.5}
#sample .s-check input{width:24px;height:24px}
.s-next-btn .ic{margin-right:-4px}
#sample-form .s-acts{display:flex;gap:10px}
#sample-form .s-acts .btn{flex:1 1 auto;width:auto}
#sample-form .s-acts .s-back{flex:none;gap:6px;padding:0 18px}
.s-mir{position:absolute;left:-9999px;top:0;visibility:hidden;white-space:pre;pointer-events:none}
/* step 1, folded to a line at the top of step 2 */
.s-recap{display:flex;align-items:flex-start;gap:12px;margin-bottom:18px;padding:0 0 12px;border-bottom:2px dashed rgba(30,38,47,.22)}
.s-recap-t{flex:1;min-width:0;margin:0;font:400 15px/1.45 var(--sans);color:var(--ink);overflow-wrap:anywhere}
.s-recap-t b{font-weight:700}
.s-edit{flex:none;min-height:44px;margin:-12px -6px -12px 0;padding:0 6px;border:0;background:none;cursor:pointer;
  font:600 15px/1 var(--sans);color:var(--teal);text-decoration:underline;text-decoration-thickness:1.5px;text-underline-offset:4px}
/* "1 of 2": a sticker slapped on the card's corner, never the old outlined "Step n of 4" tag */
.s-prog{position:absolute;z-index:1;top:-32px;right:16px;display:grid;place-items:center;width:66px;height:66px;margin:0;
  border-radius:50%;background:var(--sand);box-shadow:inset 0 0 0 2px var(--ink),3px 3px 0 var(--ink);
  font:700 16px/1 var(--display);color:var(--ink);transform:rotate(-12deg)}
/* under 360px the note drops two pixels of type and four of margin a side, so a line holds a
   clause and a blank; it is still the heavy condensed cut, just a size down */
@media (max-width:359px){
  .nc{--ncs:26px}
  .c-card.nc{padding-left:18px;padding-right:18px}
  #sample .s-step{font-size:26px}
}
@media (min-width:768px){
  .nc{--ncs:34px}
  .c-card.nc{padding:52px 36px 34px}
  #sample .s-step{font-size:34px}
}

/* #consult wears the same note card (.nc above), so the two asks on the page read as one hand.
   Only the questions differ: the sample hides its legends because the sentence around its blanks
   says everything, while here the four questions ARE the card, so they keep the display face at a
   steady size of their own (--ncq) and stay visible. The six training answers are whole sentences
   rather than words, so that one fieldset steps its pills right down (--ncs on .c-q-long). */
#consult-form{--ncs:26px;--ncq:25px;--cgap:26px;gap:var(--cgap)}
#consult-form .c-q legend{margin-bottom:14px;font:600 var(--ncq)/1.16 var(--display);
  letter-spacing:-.005em;color:var(--ink)}
#consult-form .c-q-long{--ncs:18px}
/* the six answers wrap to two lines, and inside a 999px pill with .5em sides their first and last letters
   touched the curve of the dashed border (a Fable critic, 2026-10-21): a smaller radius and real padding */
#consult-form .c-q-long .chip span{padding:9px 16px;border-radius:22px;line-height:1.15;text-align:left}
#consult-form .chips{gap:10px 8px}
#consult-form .c-field{gap:6px}
#consult-form .c-field label{font:600 var(--ncq)/1.16 var(--display);letter-spacing:-.012em;color:var(--ink)}
#consult-form .c-field label span{font:400 14px/1.3 var(--sans);letter-spacing:0;color:var(--text)}
#consult-form .c-field input,#consult-form .c-field textarea{width:100%}
/* the note's blank is as tall as what is in it (2026-10-04: the calculator's macros line ran out of a one-line
   blank); _script.html grows it where field-sizing is not supported */
#consult-form .c-field textarea{height:auto;min-height:46px;field-sizing:content;background-clip:padding-box}   /* underlines as wide as the blank above */
/* the hint on a blank stays readable rather than hidden as it is in the sentence: small sans,
   sitting on the underline, so the blank still says what belongs in it */
#consult-form .c-field input::placeholder{color:rgba(65,83,101,.85);font:400 15px/46px var(--sans)}
#consult-form .c-field textarea::placeholder{color:rgba(65,83,101,.85);font:400 15px/42px var(--sans)}
#consult-form .c-sum{margin-top:-4px;font:500 16px/1.45 var(--sans);color:var(--text)}

/* One question at a time (cStep in _script.html), the macro calculator's furniture in this
   card's hand so the two cards read as siblings: the same sans counter, the same 3px teal
   pips, the same Back tlink beside the button, the same fade-up into each step. Three steps
   here, so the pip row is three. */
.c-quiz{display:grid;gap:16px}
.c-count{font-size:14px;color:var(--text)}
.c-prog{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:5px;margin-top:-6px}
.c-prog span{height:3px;background:rgba(0,46,59,.18)}
.c-prog span.is-on{background:var(--teal)}
/* a step is a fieldset and its legend is the question; the script owns [hidden] on the rest */
.c-step{display:block;margin:0;padding:0;border:0;min-width:0}
.c-in{animation:mc-in 260ms cubic-bezier(.2,.7,.2,1) both}   /* the calculator's own */
.c-nav{display:flex;flex-wrap:wrap;align-items:center;gap:12px}
.c-nav .btn{flex:1 1 150px;width:auto}
/* the error carries a rule and its own words, never colour alone, as .mc-err does */
.c-err{padding:12px 14px;background:rgba(169,71,31,.07);box-shadow:inset 2px 0 0 var(--accent);
  color:var(--ink);font:600 15px/1.55 var(--sans)}
/* the last step holds both blanks, so it keeps the gap the form's own grid used to give them */
#consult-form .c-step .c-field + .c-field{margin-top:var(--cgap)}
/* No script: every question is there at once and the button still reads "Pick a time", exactly
   as the card did before it was stepped. The furniture belongs to the script, so it goes away. */
html:not(.js) #consult-form .c-step[hidden]{display:block!important}   /* line 71's [hidden] is !important */
html:not(.js) #consult-form .c-step + .c-step{margin-top:var(--cgap)}
html:not(.js) #c-step-n,html:not(.js) #c-prog,html:not(.js) #c-back{display:none}
@media (prefers-reduced-motion:reduce){.c-in{animation:none}}

@media (max-width:359px){
  #consult-form{--ncs:23px;--ncq:22px}
  #consult-form .c-q-long{--ncs:17px}
}
@media (min-width:768px){
  #consult-form{--ncs:30px;--ncq:28px}
  #consult-form .c-q-long{--ncs:19px}
}
/* The five goals each took a whole row with half of it empty beside them ("Lose fat" on a line
   of its own): the 22px emblem and the display face put any pair 7px over the row at 390, so
   every one wrapped. Two even columns instead, the pill's own words allowed a second line, and
   --ncs stepped down to the largest size that never clips one of them at any width here —
   2-2-1 rows instead of 1-1-1-1-1, and 105px off that step at 390. Not a word changes.
   Below 1024 only: from 1024 the row already takes three and two, which is shorter still, so
   the block below is left exactly as it was measured. */
@media (max-width:1023.98px){
  #consult-form .c-q:not(.c-q-long){--ncs:21px}
  #consult-form .c-q:not(.c-q-long) .chips{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}
  #consult-form .c-q:not(.c-q-long) .chip,
  #consult-form .c-q:not(.c-q-long) .chip span{width:100%;max-width:none}
  #consult-form .c-q:not(.c-q-long) .chip span{gap:6px;padding:0 .28em;line-height:1.12}
}
/* from 1024 the card has to stand whole in a laptop's window under the masthead (1440x900: 824px
   under the 76px mast; it was 913px, so its first question and "Pick a time" were never on screen
   together). Every question and every answer stays, word for word: the six training answers go
   two to a row, each the same width (5 rows of pills down to 3), the five goals take the phone's
   size so they sit in two rows, not three (19px to spare at 1440), and the gaps close up a little.
   745px at 1440, with room under it for the summary line a pick brings. */
@media (min-width:1024px){
  #consult-form{--cgap:22px}
  .c-card.nc#consult-form{padding-top:42px;padding-bottom:30px}
  #consult-form .c-q:not(.c-q-long){--ncs:26px}
  #consult-form .c-q-long .chips{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}
  #consult-form .c-q-long .chip span{width:100%;min-height:52px;padding:0 .6em}
}

/* ===================================================================================
   THE BOOKING CARD AS GLASS, OVER THE LAKE AT DUSK (2026-10-08)
   -----------------------------------------------------------------------------------
   #consult is the one band on the site that stands on a photograph, and the note Peter
   fills in used to sit on it as an opaque chalk sheet: the lake stopped dead at the
   card's edge. Here the note becomes a frosted panel instead — the dusk still reads
   through it, out of focus, and the card is part of the picture rather than laid on it.

   It is a REAL frosted panel, which means two things together, and the second is what
   makes it safe:
     1. backdrop-filter: blur(24px) saturate(1.1) — the photo behind, softened.
     2. a TINT of Peter's own teal, rgba(0,46,59,.72), as the card's own background.
   The tint is not decoration. A no-fill panel only holds its text over an evenly-toned
   photograph, and the dusk lake is not one: it carries an afterglow on the horizon and
   a black treeline in the same frame. With the tint, every word inside sits on a colour
   we control, so the contrast is ours whatever the picture does.

   It is also the FALLBACK. backdrop-filter is still unsupported in places, and the
   blur is declared on its own inside @supports; without it the card is simply the solid
   teal tint over the photo and reads exactly as well (measured: no figure inside the
   card moves by more than a tenth of a point with the filter disabled).

   Below 768 there is no photograph behind the card at all — the dusk is its own strip
   above the heading and the card stands on the section's #141A26 — so a phone gets the
   fallback's look by construction, which is why the two measure the same.

   The card KEEPS ITS CHARACTER: it is still the note (the 2px rule all the way round,
   the hard offset shadow, the heavy condensed questions, the underlined blanks, the
   dashed choice pills that turn solid and askew when they are picked). Only the hand it
   is written in changes: ink on chalk becomes chalk on teal, and the pills invert — sand
   fill, teal lettering — because a teal pill on a teal panel would have no shape at all.
   Not one question, label, placeholder, validation line or button word is touched.
   The calculator's card (.mc-card) is deliberately NOT changed here; RAW 0 is deciding
   whether the glass goes site-wide, and the two are siblings by design (see CLAUDE.md).
=================================================================================== */
.consult-dusk #consult-form{
  background:rgba(0,46,59,.72);                 /* the tint: the fallback, and the contrast floor */
  color:var(--chalk);
  /* the note's own 2px rule and its hard offset, both turned to the dark side: a chalk
     edge so the panel has a rim against the picture, and the drop in the water's near-black
     rather than teal, which would disappear into the tint it is cast from */
  box-shadow:inset 0 0 0 2px rgba(230,211,197,.42),8px 8px 0 rgba(0,16,22,.45),
             0 40px 60px -40px rgba(0,16,22,.85);
}
@supports ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .consult-dusk #consult-form{
    -webkit-backdrop-filter:blur(24px) saturate(1.1);
            backdrop-filter:blur(24px) saturate(1.1);
  }
}
/* the questions, the field labels and the step's furniture */
.consult-dusk #consult-form .c-q legend,
.consult-dusk #consult-form .c-field label{color:var(--chalk)}
.consult-dusk #consult-form .c-field label span{color:var(--sand)}
.consult-dusk #consult-form .c-count,
.consult-dusk #consult-form .c-sum{color:var(--sand)}
.consult-dusk #consult-form .c-prog span{background:rgba(230,211,197,.26)}
.consult-dusk #consult-form .c-prog span.is-on{background:var(--sand)}
.consult-dusk #consult-form .tlink{color:var(--sand)}   /* Back */
/* the error keeps its rule and its words; only the side it is lit from changes */
.consult-dusk #consult-form .c-err{background:rgba(230,211,197,.10);
  box-shadow:inset 2px 0 0 var(--sand);color:var(--chalk)}

/* What the free sample lent this card when Calendly came out (2026-10-09): the consent ticks, the
   "what happens next" list, the privacy line and the send's own error. Every one of them was written
   for the LIGHT sample card and arrived here still set in --ink or --text, which on this teal panel is
   all but invisible — measured before the fix, the consent label was ink (30,38,47) on the glass. They
   take the same inversion as the rest of the panel: chalk for what must be read, sand for the quiet
   parts, and the numbered badges and the tick's accent go sand so they keep their shape. */
.consult-dusk #consult-form .s-check{color:var(--chalk)}
.consult-dusk #consult-form .s-check em{color:var(--sand)}
.consult-dusk #consult-form .s-check input{accent-color:var(--sand)}
.consult-dusk #consult-form .s-next li{color:var(--on-dark)}
.consult-dusk #consult-form .s-next li::before{color:var(--sand);box-shadow:inset 0 0 0 1px rgba(230,211,197,.6)}
.consult-dusk #consult-form .c-fine{color:var(--sand)}
.consult-dusk #consult-form .s-err{color:#FFC9BE}   /* the light-card red is a black mark on teal */

/* THE CHOICE PILLS. Dashed and empty until they are picked, exactly as the sample's are;
   picked, they invert instead of filling teal — a teal pill on a teal panel has no shape.
   Sand fill, teal lettering, the same -2deg knock and the same hard little shadow. */
.consult-dusk #consult-form .chip span{border-color:rgba(230,211,197,.55);color:var(--chalk);
  --sheen:rgba(255,255,255,.18)}          /* the sweep goes light; the dark one was invisible here */
.consult-dusk #consult-form .chip input:checked + span{background:var(--sand);
  border-color:var(--chalk);color:var(--teal);box-shadow:3px 3px 0 rgba(0,16,22,.55);
  --sheen:rgba(255,255,255,.5)}
@media (hover:hover){
  .consult-dusk #consult-form .chip:hover span{color:var(--chalk);border-color:var(--chalk)}
  .consult-dusk #consult-form .chip:hover input:checked + span{color:var(--teal)}
}
.consult-dusk #consult-form .chip input:focus-visible + span{outline-color:var(--sand)}

/* THE BLANKS. Written in chalk on a sand rule, which is the same gesture as blue ink on a
   teal rule; the hint that says what belongs in the blank stays legible rather than grey. */
.consult-dusk #consult-form .c-field input,
.consult-dusk #consult-form .c-field textarea{color:var(--chalk);--u:var(--sand)}
.consult-dusk #consult-form .c-field input{border-bottom-color:var(--sand)}
.consult-dusk #consult-form .c-field input::placeholder,
.consult-dusk #consult-form .c-field textarea::placeholder{color:rgba(230,211,197,.8)}
.consult-dusk #consult-form .c-field input:focus{background:rgba(230,211,197,.12);
  border-bottom-color:var(--chalk);box-shadow:0 3px 0 var(--chalk)}
.consult-dusk #consult-form .c-field textarea:focus{--u:var(--chalk);background-color:rgba(230,211,197,.12)}
/* invalid: the deep red of the light card would be a black mark here, so it is the same hue
   lifted to read on the tint. The words in .c-err still carry the error; colour never alone. */
.consult-dusk #consult-form .c-field input[aria-invalid="true"]{border-bottom-color:#E8A295;
  background:rgba(232,162,149,.12);box-shadow:none}
.consult-dusk #consult-form .c-field textarea[aria-invalid="true"]{--u:#E8A295;
  background-color:rgba(232,162,149,.12)}
/* STEP 3 IS A FORM, SO IT LOOKS LIKE ONE (2026-10-29, a phone critic: "headings over dividers"). Its four
   labels were 25px display type over bare underlines, so on a phone the step read as four headlines, ran to
   1,089px and set the consent tick flush against the last blank. Steps 1 and 2 keep the display face, because
   there the question IS the card; here the labels are field labels: Inter at 15px over boxed fields, as the
   membership and gift forms have them, and typed text in the body face. */
#consult-form [data-q="you"] .c-field label{font:600 15px/1.3 var(--sans);letter-spacing:0}
#consult-form [data-q="you"] .c-field + .c-field{margin-top:18px}
.consult-dusk #consult-form [data-q="you"] .c-field input,
.consult-dusk #consult-form [data-q="you"] .c-field textarea{height:48px;padding:0 12px;
  border:1px solid rgba(230,211,197,.55);border-radius:10px;background:rgba(255,255,255,.07);
  font:400 17px/1.4 var(--sans);letter-spacing:0;box-shadow:none}
.consult-dusk #consult-form [data-q="you"] .c-field textarea{height:auto;min-height:76px;padding:12px;line-height:1.45;
  background-image:none}
.consult-dusk #consult-form [data-q="you"] .c-field input::placeholder,
.consult-dusk #consult-form [data-q="you"] .c-field textarea::placeholder{font:400 15px/1.4 var(--sans)}
.consult-dusk #consult-form [data-q="you"] .c-field input:focus,
.consult-dusk #consult-form [data-q="you"] .c-field textarea:focus{border-color:var(--chalk);
  background:rgba(230,211,197,.12);box-shadow:inset 0 0 0 1px var(--chalk)}
.consult-dusk #consult-form [data-q="you"] .c-field input[aria-invalid="true"],
.consult-dusk #consult-form [data-q="you"] .c-field textarea[aria-invalid="true"]{border-color:#E8A295;
  background:rgba(232,162,149,.12);box-shadow:inset 0 0 0 1px #E8A295}
#consult-form [data-q="you"] .s-checks{margin-top:24px}
/* the button is unchanged: the copper accent on the teal tint is the one warm-cold edge in the
   card and it is what the eye should land on. Only its rim is drawn, so it never floats. */
.consult-dusk #consult-form .btn{box-shadow:0 0 0 1px rgba(230,211,197,.22)}


/* the category banner's way to it */
.cat-sample a{color:var(--sand);font-weight:600;text-decoration:underline;text-decoration-thickness:1.5px;text-underline-offset:5px}

/* 8. Footer */
.foot{background:#00222C;color:#C3CACD;padding:56px 0 calc(40px + env(safe-area-inset-bottom))}
.foot-h{margin-bottom:8px;font-weight:600;color:var(--sand)}
.foot .wordmark{justify-self:start;align-self:start;min-height:0;gap:0;font-size:13px;color:var(--sand);text-decoration:none;padding:8px 0;margin:-8px 0}
.foot .wordmark:active{opacity:.7}
@media (hover:hover){.foot .wordmark:hover{text-decoration:underline;text-underline-offset:5px}}
/* the lockup as type: the mark is already the horizon behind it, so it is not repeated here */
.foot-brand{display:grid;gap:7px;justify-self:start}
.foot-tag{margin:0;font:600 12px/1.3 var(--sans);letter-spacing:.30em;text-transform:uppercase;color:#51A8AA}
.foot-place{margin:0;font:500 11px/1.3 var(--sans);letter-spacing:.18em;text-transform:uppercase;color:var(--on-dark);opacity:.75}
.foot-top{display:grid;gap:14px;padding-bottom:28px;border-bottom:1px solid rgba(230,211,197,.18)}
.foot-links{display:grid;justify-items:start;gap:0}
.foot-links a{display:inline-flex;align-items:center;min-height:44px;color:var(--chalk);text-decoration:none}
.foot-links a:active{opacity:.7}
@media (hover:hover){.foot-links a:hover{text-decoration:underline;text-underline-offset:5px}}
.foot-meta{display:grid;gap:12px;margin-top:24px;max-width:70ch;font-size:14px;line-height:1.6}

/* 8b. Footer horizon. Peter's lit wave laid along the top edge of the footer, the light
   where the page ends. The shipped asset is the wave band cropped out of his artwork, so
   the lockup type that sits under the wave there can never enter the frame. The ground
   under it goes black, the image is screened onto it and its lower edge is masked away, so
   there is no rectangle where the picture stops. The band owns its own strip: the footer's
   top padding is the band's height plus its usual 36px, so no text ever sits on the glow.
   Kept as one block, after the footer's own, so it merges in one piece. */
.foot{--horizon:clamp(96px,22vw,260px);position:relative;isolation:isolate;
  background:#000;padding-top:calc(var(--horizon) + 36px)}
.foot-glow{position:absolute;left:0;top:0;width:100%;height:var(--horizon);pointer-events:none;
  mix-blend-mode:screen;
  -webkit-mask-image:linear-gradient(#000 50%,rgba(0,0,0,.4) 80%,transparent 100%);
          mask-image:linear-gradient(#000 50%,rgba(0,0,0,.4) 80%,transparent 100%)}
.foot-glow img{display:block;width:100%;height:100%;object-fit:cover;object-position:50% 0}
.foot .wrap{position:relative;z-index:1}

/* Full-screen nav panel */
dialog{color:var(--text)}
.menu{overscroll-behavior:contain;position:fixed;inset:0;width:100%;height:100%;max-width:none;max-height:none;margin:0;padding:0;border:0;background:var(--teal);color:var(--sand)}
.menu-in{display:flex;flex-direction:column;min-height:100%}
.menu-nav{margin-top:auto;padding-bottom:calc(32px + env(safe-area-inset-bottom))}
.menu-nav .label{color:var(--on-dark)}
.menu-list{list-style:none;margin:12px 0 0;padding:0}
.menu-list li{border-top:1px solid rgba(230,211,197,.2)}
.menu-list a,.menu-list button{display:flex;align-items:center;justify-content:space-between;width:100%;min-height:64px;padding:0;border:0;background:transparent;color:var(--chalk);font:600 34px/1.1 var(--display);letter-spacing:-.018em;text-align:left;text-decoration:none}
.menu-cta{width:100%;margin-top:28px}
/* the shelves: every category page, in the nav's small type, two to a row */
.menu-shelves-t{margin-top:24px}
.menu-shelves{list-style:none;margin:8px 0 0;padding:0;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));column-gap:16px}
.menu-shelves a{display:flex;align-items:center;min-height:44px;border-top:1px solid rgba(230,211,197,.2);color:var(--chalk);font:600 15px/1.2 var(--sans);text-decoration:none}
.menu-shelves a:active{opacity:.7}

/* without JS nothing can reveal the shelf, so it is simply open */
html:not(.js) #results[hidden]{display:block!important}
/* the shop's grid, grouped by shelf (2026-10-04): an h3 over each shelf's tiles, and the shelves' names as
   a row of links that holds under the masthead (and under the pinned bar, while it is up) for as long as
   the grid is on screen; it is sticky inside #results' .wrap, so it goes with the grid. On a phone the row
   is one line that scrolls sideways; from 768 it wraps. The shelf being read is lit (aria-current, set by
   the script). The plate's colour rides on each name as the edge-on sliver the stack's key uses. */
/* its chalk runs the full width of the window, as the pinned bar's does, by a shadow, which cannot widen
   the page; the second shadow is its hairline, clipped to the 1px under it */
.g-jump{position:sticky;top:calc(var(--mh) + var(--srch,0px));z-index:5;margin:-24px calc(-1 * var(--pad)) 0;background:var(--chalk);
  box-shadow:0 0 0 100vmax var(--chalk),0 1px 0 100vmax var(--line);clip-path:inset(0 -100vmax -1px)}
.t-bar.pin-you .g-jump{top:calc(var(--mh) + var(--srch,0px) + var(--pin))}
/* under 1024 the search opens as a 58px row in the masthead and stays open after a search, so the
   row of shelves (and the pinned bar, below) step down under it rather than slide behind it */
@media (max-width:1023px){html:has(.mast.s-open){--srch:58px}}
.g-jump ul{list-style:none;margin:0;padding:8px var(--pad);display:flex;gap:6px;overflow-x:auto;scrollbar-width:none;overscroll-behavior-x:contain}
.g-jump ul::-webkit-scrollbar{display:none}
.g-jump li{flex:none}
.g-jump li[hidden],.g-jump[hidden]{display:none}
.g-jump a::after{content:"";position:absolute;inset:-4px -3px}
.g-jump a{position:relative;display:inline-flex;align-items:center;gap:7px;min-height:36px;padding:0 13px;border-radius:999px;box-shadow:inset 0 0 0 1px var(--line);
  background:var(--chalk);color:var(--teal);font:600 13px/1 var(--sans);text-decoration:none;white-space:nowrap}
.g-jump a[aria-current]{background:var(--teal);color:var(--chalk);box-shadow:none}
.g-jump a:active{opacity:.7}
.g-jump i{flex:none;width:5px;height:14px;border-radius:2px/3px;background:linear-gradient(rgba(255,255,255,.45),rgba(255,255,255,0) 30%,rgba(0,0,0,0) 60%,rgba(0,0,0,.4)),var(--c);box-shadow:0 0 0 1px rgba(30,38,47,.18)}
@media (hover:hover){.g-jump a:not([aria-current]):hover{box-shadow:inset 0 0 0 1.5px var(--teal)}}
.g-shelf{scroll-margin-top:calc(var(--gj,52px) + 8px)}   /* --gj: the row's own height, kept by the script */
.g-shelf[hidden]{display:none}
.g-h{margin:28px 0 18px;font:600 31px/1.08 var(--display);letter-spacing:-.016em;color:var(--teal)}
/* a hairline between shelves, never over the first one showing (a search can hide the ones above it) */
.g-shelf:not([hidden]) ~ .g-shelf .g-h{margin-top:40px;padding-top:14px;border-top:1px solid var(--line)}
.g-shelf .p-name{margin-bottom:0}   /* an h4 there, under its shelf's h3 */
.g-back{margin-top:8px}
.g-back .ic{margin-right:8px}
@media (min-width:768px){
  .g-jump ul{flex-wrap:wrap;overflow:visible;padding-block:10px}
  .g-shelf{scroll-margin-top:calc(var(--gj,98px) + 8px)}
  .g-h{font-size:36px}
}
/* all ten on one line from 1200 */
@media (min-width:1200px){.g-jump ul{gap:5px}.g-jump a{padding:0 10px;gap:6px}.g-shelf{scroll-margin-top:calc(var(--gj,56px) + 8px)}}

/* ---------- 768px ---------- */
@media (min-width:768px){
  :root{--pad:max(40px,env(safe-area-inset-left,0px),env(safe-area-inset-right,0px));--sec:112px}

  /* 12 columns, 24px gutters; column 6 starts every second-column element */
  .hero,.goal,.split,.foot-top{--g:24px}
  .hero-in,.goal,.split,.foot-top{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));column-gap:24px}
  .hero-in{align-items:center;min-height:clamp(560px,calc(100vh - 76px),800px);padding-top:40px;padding-bottom:40px}   /* 40, not 56, with the 18px gap below: with Peter's row in, the hero keeps its 800px at 1440x900 */
  .hero-copy{grid-column:1 / 6;grid-row:1;padding:0;gap:18px}
  .hero h1{font-size:clamp(72px,7vw,104px)}
  .hero .sub{font-size:18px;max-width:30ch}
  .hero-actions{width:auto}
  .hero-actions .btn{flex:none}
  .hero-actions .tlink{display:inline-flex}
  /* the film sits in the right half; its own dark half meets the panel, so there is one edge */
  .glass-toggle{left:auto;right:24px;bottom:24px}
  .glass{position:absolute;top:0;bottom:0;right:0;margin:0;aspect-ratio:auto;
    left:calc((100% - min(100%, 1280px)) / 2 + 40px + 5 * ((min(100%, 1280px) - 80px - 264px) / 12 + 24px))}
  .hero-copy{padding-bottom:0}

  .shelf-panel{padding-top:36px;min-height:340px}
  .shelf-link{grid-template-columns:minmax(0,5fr) minmax(0,7fr);gap:48px}
  .shelf-art{width:min(320px,100%)}
  .shelf-name{font-size:52px}
  .sec-head{margin-bottom:48px}
  .sec-head h2,.split-text h2{font-size:52px}
  /* 'Keep looking' (a shelf page's other nine): tiles, not full-width rows. As rows each one was 140px
     with its pack ~1200px from its name, so on a four-product shelf the list was most of the page.
     Two across here, three from 1024 (a 3x3 of the nine), the pack beside its name. */
  .goal-index{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));column-gap:32px;border-top:0;border-bottom:1px solid var(--line)}
  .goal-index li{border-top:1px solid var(--line);border-bottom:0}
  @media (min-width:1024px){.goal-index{grid-template-columns:repeat(3,minmax(0,1fr))}}
  .goal{grid-template-columns:88px minmax(0,1fr);grid-template-areas:"img name" "img desc";align-content:center;column-gap:18px;padding:16px 0}
  .goal-name{grid-area:name;align-self:end;font-size:24px}
  .goal-desc{grid-area:desc;align-self:start;font-size:15px}
  .goal-n{grid-area:auto;grid-column:3}
  .goal-img{grid-area:auto;grid-column:4}
  .goal-desc{margin-top:6px}
  .goal-n{margin-top:0}
  .goal-img{width:120px}
  .goal-island{grid-area:img;align-self:center;justify-self:start;justify-content:center;width:88px;height:76px}

  .grid{grid-template-columns:repeat(3,minmax(0,1fr));gap:48px 20px}
  .shop .grid{row-gap:0}
  .shop .grid .card{padding-bottom:52px}

  .split{align-items:center}
  .split{align-items:start}
  .split-text{grid-column:1 / 6}
  .split-text h2{max-width:none}
  .ordering .split{align-items:start}

  .foot-top{align-items:center}
  .foot-top .foot-brand{grid-column:1 / 5}
  .foot-links{grid-column:5 / 13;grid-auto-flow:column;justify-content:flex-end;gap:0 36px}
  .c-card,.c-embed{grid-column:7 / 13}
  .c-card{padding:32px}
}

/* ---------- 1024px: the inline nav ----------
   wordmark + four nav items + the search field need ~990px of bar. Below that the
   compact bar keeps the menu and the search toggle, and the consult is the filled
   button at the foot of the menu panel instead. */
@media (min-width:1024px){
  :root{--mast:76px}
  /* the wordmark column may not shrink below its own width: with the wave in it the block
     is ~277px, and a minmax(0,1fr) track let it overflow into the nav at 1024 */
  .mast .wrap{display:grid;grid-template-columns:minmax(auto,1fr) auto minmax(0,1fr) auto;align-items:center;gap:24px;height:76px}
  .mast .search{justify-self:end;width:min(100%,300px);min-width:150px}
  .mast .bar{display:contents}
  .menu-btn,.search-toggle{display:none}
  .mast .sound-toggle{order:4;justify-self:end;margin-left:-6px}
  .mast .wordmark{justify-self:start;font-size:14px}
  .mast .wordmark .mark{width:120px;height:29px}
  .nav-inline{display:flex;align-items:center;justify-content:center;gap:4px;white-space:nowrap}
  .nav-inline a{display:inline-flex;align-items:center;min-height:44px;padding:0 12px;font:600 12px/1 var(--sans);letter-spacing:.16em;text-transform:uppercase;color:var(--sand);text-decoration:none}
  .nav-inline a:active{opacity:.7}
  /* the primary action: same micro-type as its neighbours, filled */
  .nav-inline .btn{margin-left:8px;font-size:12px;letter-spacing:.16em;text-transform:uppercase;color:#fff}
  .js .mast:not(.s-open) .search,.search{display:flex;padding:0}
}
/* the mast's call reads "Book a free call" (the same words as every way to the call); that is
   ~50px longer than the old "Free call", so under 1200 the nav items sit a little closer and
   the nav keeps clear of the search field at 1024 */
@media (min-width:1024px) and (max-width:1199px){
  .nav-inline{gap:0}
  .nav-inline a{padding:0 9px}
  .nav-inline .btn{margin-left:6px;padding:0 14px}
  .mast .search{min-width:138px}
}

/* ---------- 1200px ---------- */
@media (min-width:1200px){
  .goals{gap:20px}
  .grid{grid-template-columns:repeat(4,minmax(0,1fr));gap:56px 24px}
  .shop .grid{row-gap:0}
}

/* ---------- Category pages ---------- */
.cat-hero{position:relative;isolation:isolate;overflow:hidden;background:var(--teal);color:var(--chalk);min-height:58vh;display:grid;align-items:end}
.cat-bg{position:absolute;inset:0;z-index:-2;width:100%;height:100%;object-fit:cover;transform:scale(1.08);will-change:transform}
.cat-hero::after{content:"";position:absolute;inset:0;z-index:-1;background:linear-gradient(180deg,rgba(0,30,39,.62),rgba(0,30,39,.28) 45%,rgba(0,30,39,.82))}
.caustics{position:absolute;inset:0;z-index:-1;width:100%;height:100%;mix-blend-mode:screen;opacity:.5;pointer-events:none}
.cat-hero-in{padding-block:120px 40px;display:grid;gap:14px;justify-items:start}
.cat-hero .label a{position:relative;color:var(--sand);text-decoration:none;border-bottom:1px solid rgba(230,211,197,.5);padding-bottom:2px}
.cat-hero .label a::after{content:"";position:absolute;inset:-12px -4px}   /* a 44px target on an 18px link (2026-10-29) */
.cat-hero h1{color:var(--chalk);font-size:clamp(46px,14vw,68px)}
.cat-hero .sub{max-width:42ch;color:var(--on-dark);font-size:16px}
.cat-count{font-size:14px;color:var(--sand);font-variant-numeric:tabular-nums}
.cat-shop .grid{row-gap:0}
.cat-shop .card{display:grid;grid-row:span 4;grid-template-rows:subgrid;grid-template-columns:minmax(0,1fr);padding-bottom:36px}
.cat-shop .card-link{grid-row:1 / 5;display:grid;grid-template-rows:subgrid;grid-template-columns:minmax(0,1fr)}
.cat-more{padding-top:0}
/* the last card already carries its own 36-52px of padding below it, so a full --sec under the grid left
   ~250px of empty chalk before "Keep looking" on a laptop (a Fable critic, 2026-10-21): half is enough */
.cat-shop{padding-bottom:calc(var(--sec) * .5)}

/* Flavour carousel */
.carousel-sec .sec-head{align-items:center}
.sec-head>.car-nav{display:flex;gap:4px}
.car-nav .icon-btn{border:1px solid var(--line);color:var(--teal)}
.car-nav .icon-btn:active{background:var(--press)}
.carousel{list-style:none;display:grid;grid-auto-flow:column;grid-auto-columns:60%;gap:16px;margin:20px calc(-1 * var(--pad)) 0;padding:0 var(--pad);overflow-x:auto;contain:paint;scrollbar-width:none;overscroll-behavior-x:contain;-webkit-overflow-scrolling:touch}
.carousel::-webkit-scrollbar{display:none}
.slide{scroll-snap-align:none}
.slide .card-link{display:grid;color:inherit;text-decoration:none}
.slide .shot{aspect-ratio:1}
.slide .p-name{min-height:2.6em;margin-top:8px;font:600 15px/1.3 var(--sans);color:var(--ink)}
.carousel-sec .sec-note{margin-top:-14px}

@media (min-width:768px){
  .cat-hero{min-height:64vh}
  .cat-hero-in{padding-block:180px 56px;gap:18px}
  .cat-hero h1{font-size:clamp(64px,7vw,104px)}
  .cat-hero .sub{font-size:18px;max-width:46ch}
  .carousel{grid-auto-columns:24%;gap:24px;margin:24px 0 0;padding:0}
  .cat-shop .card{padding-bottom:52px}
  .cat-shop .grid{row-gap:0}
}

/* ---------- Trending: podium ---------- */
.podium-sec{position:relative;isolation:isolate;margin-top:56px;padding-top:0;overflow:visible}
.podium-sec .sec-head{padding-top:var(--sec);margin-bottom:0;align-items:baseline}
.podium{list-style:none;margin:56px 0 0;padding:0;display:grid;grid-template-columns:minmax(0,1fr);gap:44px;align-items:start}
.pod{position:relative;perspective:900px}
.pod .card-link{position:relative;display:grid;color:var(--chalk);text-decoration:none;transform-style:preserve-3d;transition:transform .35s cubic-bezier(.2,.7,.2,1)}
.pod .shot{margin-top:-30px;isolation:isolate}
.pod .shot::after{content:"";position:absolute;left:24%;right:24%;bottom:2%;height:6%;z-index:-1;border-radius:50%;
  background:radial-gradient(closest-side,rgba(0,12,18,.7),rgba(0,12,18,0))}
.pod-rank{order:-1;margin-bottom:6px;font:600 12px/1.3 var(--sans);letter-spacing:.16em;color:var(--sand);font-variant-numeric:tabular-nums}
.pod .p-tag{color:var(--sand)}
.pod .p-name{color:var(--chalk)}
.pod .p-desc{color:var(--on-dark)}
.pod .p-why{margin-top:4px;font-size:14px;line-height:1.4;color:var(--on-dark);overflow-wrap:anywhere}   /* its TAGLINES line: why it's worth a look */
.pod-count{margin-top:10px;font-size:14px;color:var(--sand);font-variant-numeric:tabular-nums}
.pod-num{font:700 22px/1 var(--display);display:inline-block;margin-right:4px}
@media (hover:hover){.pod .card-link:hover .p-name{text-decoration:underline;text-underline-offset:4px}}
@media (prefers-reduced-motion:reduce){.pod .card-link{transition:none}}

@media (min-width:768px){
  .podium-sec{margin-top:88px}
  .podium{grid-template-columns:repeat(3,minmax(0,1fr));gap:40px;align-items:start;margin-top:76px}
  .pod .shot{margin-top:-70px}

}

/* ---------- Our story: how the two of them got into this ---------- */
/* An ordinary section, on the chalk the band above it ends on: their lines, then their two
   before/after stacks, then the ask. It was a nine-beat sticky stage scrubbed by the scroll until
   2026-10-01 (Peter: "Instead of scrolling through it, lets just add before and after pictures of
   Yenni and I side by side"), and with the stage went .is-live and everything only it needed — the
   run and the stage, the beats and their three tones, the packs and their contact shadows, the
   before→after wipe and its tags, the caption strip and its fades, the case strip and the arc bar.
   Nothing here reads the scroll, so reduced motion and no script get exactly this. */
.story{position:relative;background:var(--chalk)}
/* its heading: the same label-over-h2 as #how, with "this" in the blue */
.st-head{display:grid;gap:10px}
.st-head h2{font-size:40px}
@media (min-width:768px){.st-head h2{font-size:52px}}
/* their lines, one under another, each with the shelf it is about under it. The type is the
   display face in sentence case, big enough to read as the section's own voice and small enough
   that five of them read as text rather than as five posters. */
.st-lines{display:grid;gap:34px;margin-top:clamp(28px,6vw,40px)}
.st-bit{display:grid;gap:10px;justify-items:start}
.st-bit p{max-width:34ch}
/* the label that opens a movement, in his words for it */
.st-mv{font:600 12px/1.3 var(--sans);letter-spacing:.14em;text-transform:uppercase;opacity:.85;margin:0 0 2px;color:var(--text)}
.st-line{margin:0;font:600 clamp(23px,6.4vw,31px)/1.14 var(--display);
  letter-spacing:-.012em;text-wrap:balance;color:var(--teal)}
/* what they changed (2026-10-21): what they DID, as a ruled list in the lines' own display face, and under
   it the five shelves as one quiet line of links (they were the list itself, big and ruled, until a Fable
   critic found that read as a product menu sitting right above the photographs). */
.st-did{list-style:none;margin:0;padding:0;width:100%;max-width:520px;border-top:1px solid var(--line)}
/* body size since 2026-10-29: in the display face they made six headline-sized lines before the first photograph
   (a phone critic), and they are a list of things done, not lines of the story. ~300px less before the pair. */
.st-did li{padding:10px 0;border-bottom:1px solid var(--line);font:500 17px/1.4 var(--sans);text-wrap:pretty;color:var(--ink)}
.st-shelf-line{margin:6px 0 0;font:400 16px/1.6 var(--sans);color:var(--text)}
.st-shelf-line .st-go{padding:12px 0;font-weight:600;color:var(--teal);text-decoration:underline;text-decoration-thickness:1.5px;text-underline-offset:3px}   /* inline padding: a taller tap target, the same line */
.st-shelf-line .st-go:active{opacity:.7}
@media (min-width:768px){.st-did li{font-size:18px}}
/* the third movement's label and its answer, Peter's side pair, out in the open (2026-10-02): a
   visitor who never opens the reveal below still sees one before and after. Under 1024 the heading
   stands straight over the pair, after the lines; the pair keeps proof_wall's own furniture (.c-proof,
   .c-cols on the 50% seam, .pf-who) and is capped at the 680px the wall's stacks are. */
.st-see{margin-top:clamp(44px,8vw,64px)}
.st-now{margin:0;max-width:34ch}
.st-see .c-proof{max-width:680px;margin-top:clamp(18px,4vw,24px)}
/* From 1024 the lines and the pair stand side by side: the lines on the left as before, and on the
   right the heading with the pair under it, so the half of the screen beside the lines carries the
   proof. The right column is centred against the lines (it is the shorter), the heading keeps its
   place over the picture it names, and the reveal and the ask run full width beneath both. */
@media (min-width:1024px){
  .st-top{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);align-items:center;
    gap:clamp(40px,5vw,80px);margin-top:clamp(28px,6vw,40px)}
  .st-top>.st-lines{margin-top:0}
  .st-see{margin-top:0}
  .st-see .c-proof{max-width:none}
}
/* The reveal: their photographs behind a control the visitor opens, in place on the page (Peter,
   2026-10-01: "it opens a drop down so it stays in the same page... if they don't want to see,
   they can just keep scrolling"). A native details/summary — no script, so reduced motion and no
   JavaScript get the same working control, and the keyboard and screen-reader behaviour is the
   browser's. Closed, it is one line on the chalk in a hairline box: an offer, quieter than the
   ask's filled button below it, and plainly a thing to press. */
.st-rev{margin-top:clamp(26px,5vw,36px)}
/* Peter, 2026-10-07: "we need to make the 'see the rest of our pictures' pop more. Maybe an entirely different
   colour." It was a 1px teal hairline on the page's own ground -- the quietest control on the page, holding the
   only other proof the visitor gets. It is a filled teal block now: the page is chalk and greige, so a solid dark
   reads at a glance, and it stays clear of the blue that every real button on the site wears (the ask's "Book a
   free call" sits a few hundred pixels below it, and two blues would compete). */
.st-rev>summary{display:flex;align-items:center;justify-content:space-between;gap:18px;
  max-width:42ch;padding:16px 18px;background:var(--teal);box-shadow:none;color:var(--chalk);
  font:600 16px/1.45 var(--sans);cursor:pointer;list-style:none;text-wrap:pretty}
.st-rev>summary::-webkit-details-marker{display:none}   /* the default triangle; the chevron says it instead */
.st-rev>summary::marker{content:""}
.st-rev>summary:active{opacity:.7}
@media (hover:hover){.st-rev>summary:hover{background:#013E4F}}   /* a step lighter, not the old tile: the block is dark now */
/* the chevron: down while it is closed, up once it is open, so the control says which way it goes */
.st-rev-ch{flex:none;width:10px;height:10px;margin-right:4px;border:solid currentColor;
  border-width:0 2px 2px 0;transform:translateY(-3px) rotate(45deg);
  transition:transform 200ms cubic-bezier(.2,.7,.2,1)}
.st-rev[open]>summary .st-rev-ch{transform:translateY(2px) rotate(-135deg)}
/* The nudge (Peter, 2026-10-01: "make the dropdown link wiggle... as people are going past it it
   sort of pops out at them tempting them to click"; 2026-10-02: "Nudge isn't bold enough, make it
   300% louder"). When the control is well into view the script (_script.html, beside the .grow
   reveal) gives the summary .nudge, and for 1000ms it jumps out at the visitor: it lifts 6px and
   swells 10%, shakes side to side the way a notification bell does (4deg either way, dying to 0),
   drops back through a smaller second swell, lights up sand with a blue ring round it, and the
   chevron dips hard three times the way it opens. Then it is still. It may play once more, 2.6s
   later, only if it is still on screen and still closed; never a third time, and never again once
   it has been opened on this page view. Transforms and opacity only, so nothing around it moves
   (layout shift 0, measured); the swell may overlap its neighbours for that second, which is the
   point. #story clips sideways overflow (overflow-x:clip, below) so the swell and the shake can never
   make a narrow phone scroll sideways. Reduced motion and no JavaScript: it never moves, and is the
   same hairline box. The light (::before, --sand) sits 1px in so the hairline stays drawn over it;
   the ring (::after, --accent) sits 2px out. Teal on sand is ~10:1, so the words stay readable at the
   peak. */
.st-rev>summary{position:relative;isolation:isolate}
.st-rev>summary::before,.st-rev>summary::after{content:"";position:absolute;z-index:-1;opacity:0;pointer-events:none}
.st-rev>summary::before{inset:1px;background:var(--accent)}
.st-rev>summary::after{inset:-2px;box-shadow:0 0 0 2px var(--sand)}
#story{overflow-x:clip}
@media (prefers-reduced-motion:no-preference){
  .motion .st-rev>summary.nudge{animation:st-lean 1000ms cubic-bezier(.3,.6,.3,1) 360ms both}
  .motion .st-rev>summary.nudge::before{animation:st-tint 1000ms ease-out 360ms both}
  .motion .st-rev>summary.nudge::after{animation:st-ring 1000ms ease-out 360ms both}
  .motion .st-rev>summary.nudge .st-rev-ch{animation:st-dip 1000ms ease-in-out 360ms both}
}
.st-rev[open]>summary,.st-rev[open]>summary::before,.st-rev[open]>summary::after,
.st-rev[open]>summary .st-rev-ch{animation:none}
@keyframes st-lean{
  0%{transform:none}
  12%{transform:translate3d(0,-6px,0) scale(1.1) rotate(0)}
  21%{transform:translate3d(0,-6px,0) scale(1.1) rotate(-4deg)}
  30%{transform:translate3d(0,-6px,0) scale(1.1) rotate(4deg)}
  39%{transform:translate3d(0,-5px,0) scale(1.09) rotate(-3deg)}
  48%{transform:translate3d(0,-4px,0) scale(1.08) rotate(2deg)}
  57%{transform:translate3d(0,-3px,0) scale(1.06) rotate(-1deg)}
  68%{transform:translate3d(0,0,0) scale(.985) rotate(0)}
  80%{transform:translate3d(0,-3px,0) scale(1.04) rotate(0)}
  92%,100%{transform:none}
}
@keyframes st-tint{0%{opacity:0}10%,62%{opacity:1}100%{opacity:0}}
@keyframes st-ring{0%{opacity:0}10%,50%{opacity:1}80%,100%{opacity:0}}
@keyframes st-dip{
  0%,92%,100%{transform:translateY(-3px) rotate(45deg)}
  14%{transform:translateY(6px) rotate(45deg) scale(1.3)}
  26%{transform:translateY(-3px) rotate(45deg)}
  40%{transform:translateY(6px) rotate(45deg) scale(1.3)}
  52%{transform:translateY(-3px) rotate(45deg)}
  66%{transform:translateY(4px) rotate(45deg) scale(1.15)}
  78%{transform:translateY(-3px) rotate(45deg)}
}
/* their two stacks: his three views, then her two, under one another on a phone. proof_wall()
   draws them; .pf-* and .c-* (the 50% seam's Before / After heads) are in the his-and-hers block
   below, shared with about.html, and nothing here changes how that page draws them. The reveal
   hands them in on a short rise, so the open reads as the pictures arriving rather than the page
   jumping; the control itself never moves, and the rise is vertical, so nothing can scroll
   sideways while it plays. */
.st-pf{margin-top:clamp(22px,4vw,30px)}
.st-rev[open] .st-pf{animation:st-rev-in 260ms cubic-bezier(.2,.7,.2,1) both}
@keyframes st-rev-in{from{opacity:0;transform:translate3d(0,10px,0)}}
@media (prefers-reduced-motion:reduce){
  .st-rev-ch{transition:none}
  .st-rev[open] .st-pf{animation:none}
}
/* the ask closes the section in the story's own voice: the lines' display type, centred */
.st-ask{display:grid;justify-items:center;text-align:center;gap:14px;margin-top:clamp(44px,8vw,64px)}
.st-say{margin:0;font:600 clamp(26px,6.8vw,34px)/1.14 var(--display);letter-spacing:-.018em;
  color:var(--teal);text-wrap:balance;max-width:28ch}
.st-book{margin-top:2px}
/* the proof the stage used to let go into; about.html's own proof section is this block (.ab-proof) */
.st-proof{padding-top:48px;padding-bottom:var(--sec)}
.st-proof .c-proof{max-width:680px;margin:0 auto}

@media (min-width:760px){
  /* side by side from 760, as Peter asked: his two 3:2 pairs (front and back; the side is out above
     the reveal) and her two much narrower, so the two columns end together (2 x 2/3 of his width =
     2 x 979/768 of hers, so hers is .523 of his), and each stack's caption at its foot so they sit
     on one line. Scoped to .st-pf, so .pf-duo's own 1000px breakpoint on about.html is untouched. */
  .st-pf .pf-duo{max-width:none;grid-template-columns:minmax(0,1fr) minmax(0,.523fr);
    align-items:stretch;gap:clamp(24px,3.4vw,48px)}
  .st-pf .pf-duo .c-proof{max-width:none;margin:0;grid-template-rows:auto auto 1fr auto}
  .st-pf .c-stack{align-content:start}
}
@media (min-width:768px){
  .st-lines{gap:40px}
  .st-line{font-size:clamp(30px,3.1vw,40px)}
  .st-say{font-size:clamp(32px,3.4vw,48px);line-height:1.08}
}

/* ---------- Archipelago: seven floating islands ---------- */
.isles-sec{overflow:hidden;padding-bottom:40px}
.isles-sec .sec-head{margin-bottom:20px}
.isle-caption{display:grid;justify-items:center;gap:3px;text-align:center;margin-top:10px;min-height:46px}
.isle-caption .isle-name,.isle-caption .isle-note{transition:opacity .25s}
.archipelago{contain:layout paint;touch-action:pan-y;cursor:grab}
.archipelago.dragging{cursor:grabbing}
.archipelago{position:relative;height:clamp(250px,58vw,300px);margin-top:4px}
.isles{list-style:none;margin:0;padding:0;position:absolute;inset:0}
.isle{position:absolute;left:50%;top:50%;width:var(--w,150px);margin-left:calc(var(--w,150px) / -2);will-change:transform,opacity;transform-origin:50% 45%}
.isle a{display:grid;justify-items:center;gap:6px;color:var(--ink);text-decoration:none}
.isle-art{position:relative;display:block;width:100%}
.isle-art img{display:block;width:100%;height:auto}
.isle-label{position:absolute;width:1px;height:1px;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.isle-name{font:600 17px/1.15 var(--display);letter-spacing:-.008em;color:var(--teal)}
.isle-note{font:600 12px/1.3 var(--sans);letter-spacing:.16em;text-transform:uppercase;color:var(--text)}
.isle a:focus-visible .isle-name{text-decoration:underline;text-underline-offset:4px}
@media (hover:hover){.isle a:hover .isle-name{text-decoration:underline;text-underline-offset:4px}}
.isles-toggle{position:absolute;right:0;bottom:0;width:40px;height:40px;border-radius:50%;background:var(--teal);color:var(--chalk)}
.isles-toggle .ic{width:18px;height:18px}
.isles-toggle:active{background:var(--teal);opacity:.8}
html:not(.js) .archipelago{height:auto}
html:not(.js) .isles{position:static;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:24px}
html:not(.js) .isle{position:static;width:auto;margin:0}
@media (min-width:768px){
  .archipelago{height:360px;margin-top:8px}
  .isle-name{font-size:19px}
  .isle-note{font-size:12px}
}

/* ---------- The stack case (#goals): the seven shelves as one case ---------- */
/* One object: a dark teal case with seven compartments, one per shelf. Each lid is a button
   (_script.html) with its shelf's name and line on it in small caps; it hinges up and away, and
   the sand inside shows a few of that shelf's packs and the way to the shelf. Phones and tablets
   hold the case upright, seven stacked; from 1024 it lies in one row of seven and the open
   compartment takes a wider column. The section's ground is the page's: the case keeps its edge
   on chalk and on deep teal alike (a sand hairline rim and a soft drop shadow). Without script
   every compartment stands open with no lids. */
.case{--lid:color-mix(in srgb,var(--teal) 87%,var(--chalk));--lid-lo:color-mix(in srgb,var(--teal) 95%,var(--chalk));
  --well:color-mix(in srgb,var(--sand) 50%,var(--chalk));--hinge:320ms cubic-bezier(.3,.7,.2,1);
  position:relative;max-width:520px;padding:10px;border-radius:24px;
  background:linear-gradient(165deg,color-mix(in srgb,var(--teal) 90%,var(--chalk)) 0%,color-mix(in srgb,var(--teal) 88%,#000) 40%,color-mix(in srgb,var(--teal) 70%,#000) 100%);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.16),inset 0 -1px 0 rgba(0,0,0,.4),0 0 0 1px rgba(230,211,197,.24),
    0 34px 60px -30px rgba(0,20,27,.65),0 14px 24px -18px rgba(0,20,27,.5)}
.case-bays{list-style:none;margin:0;padding:0;display:grid;gap:6px}
.bay{position:relative;display:grid;grid-template-rows:auto auto;border-radius:14px;overflow:hidden;
  background:linear-gradient(var(--well),var(--sand) 80%);
  box-shadow:inset 0 9px 14px -9px rgba(0,20,27,.55),inset 0 0 0 1px rgba(0,20,27,.14)}
.bay-lid{position:relative;z-index:1;display:grid;align-content:center;justify-items:start;gap:5px;width:100%;min-height:62px;
  padding:12px 52px 12px 18px;border:0;border-radius:0;background:none;text-align:left}
.bay-lid:focus-visible{outline:2px solid var(--sand);outline-offset:-6px}
.bay.is-open .bay-lid:focus-visible{outline-color:var(--teal)}
.bay-name,.bay-note{position:relative;z-index:1;text-transform:uppercase;transition:color var(--hinge)}
.bay-name{font:700 13px/1.15 var(--sans);letter-spacing:.2em;color:var(--chalk)}
.bay-note{font:600 10.5px/1.25 var(--sans);letter-spacing:.16em;color:var(--on-dark)}
.bay.is-open .bay-name{color:var(--teal)}
.bay.is-open .bay-note{color:var(--text)}
/* the lid: teal on the teal case, a lit top edge, one soft sheen running across all seven, and a
   thumb notch at its free edge. It hinges on its back edge and is gone by the time it is open. */
.lid{position:absolute;inset:0;z-index:0;border-radius:inherit;
  background:linear-gradient(172deg,transparent 30%,rgba(255,255,255,.075) 48%,transparent 64%) 0 calc(var(--i) * 100% / 6) / 100% 700% no-repeat,
    linear-gradient(var(--lid),var(--lid-lo));
  box-shadow:inset 0 1px 0 rgba(255,255,255,.2),inset 0 -2px 0 rgba(0,0,0,.3),0 0 0 1px rgba(0,12,16,.35);
  transform-origin:50% 0;transition:transform var(--hinge),opacity 260ms cubic-bezier(.4,0,.2,1) 60ms}
.lid::after{content:"";position:absolute;right:20px;top:50%;width:6px;height:24px;margin-top:-12px;border-radius:3px;
  background:rgba(0,16,22,.5);box-shadow:0 1px 0 rgba(255,255,255,.12),inset 0 1px 2px rgba(0,0,0,.45)}
.bay.is-open .lid{transform:perspective(640px) rotateX(-48deg) translate3d(0,-12px,0);opacity:0;pointer-events:none}
@media (hover:hover){.bay:not(.is-open) .bay-lid:hover .lid{transform:perspective(640px) rotateX(-7deg)}}
.bay-well{display:grid;grid-template-rows:0fr;transition:grid-template-rows var(--hinge)}
.bay.is-open .bay-well{grid-template-rows:1fr}
.bay-in{display:grid;align-content:start;justify-items:start;min-height:0;overflow:hidden;padding:0 18px}
.bay-packs{list-style:none;margin:0;padding:2px 0 0;display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:12px;width:100%}
.bay-pack{position:relative;z-index:0;text-align:center;font:500 12px/1.3 var(--sans);color:var(--ink)}
/* a pack: a link to Amway without script, a button that opens its product card with it */
.bay-go{display:grid;justify-items:center;align-content:start;gap:4px;width:100%;margin:0;padding:0;border:0;border-radius:12px;
  background:none;color:inherit;font:inherit;text-align:center;text-decoration:none;cursor:pointer;-webkit-tap-highlight-color:transparent}
.bay-go:focus-visible{outline:2px solid var(--teal);outline-offset:3px}
.rk-panel .bay-go:focus-visible{outline-color:var(--sand)}
/* a pack shot is its product on a square with room round it, standing at 91% down, drawn --s times
   the cell's width. It is grown by layout, not by a transform: the compartment has to clip to fold
   shut, and a scaled image paints outside its own box, so its top was cut (Peter, on his phone).
   Its transparent sides overlap the next cell's; on a phone it grows downward, so the compartment
   gains the headroom, and on a wide screen, where the compartment has a fixed height and free
   space above its packs, it reaches up into that space by the same 91%-down baseline as before */
.bay-go img{--w:min(100%,112px);--s:1.3;display:block;width:calc(var(--w) * var(--s));max-width:none;height:auto;
  margin:0 calc((100% - var(--w) * var(--s)) / 2);filter:drop-shadow(0 7px 6px rgba(0,20,27,.2));
  transition:transform 200ms cubic-bezier(.2,.7,.2,1),opacity 120ms linear}
@media (hover:hover){.bay-go:hover img{transform:translate3d(0,-3px,0)}}
.bay-go:active img{transform:translate3d(0,1px,0)}
.bay-go.is-out img{opacity:0}   /* its card is open and the pack is in it */
.bay-all{display:inline-flex;align-items:center;gap:8px;min-height:44px;margin:4px 0 8px;color:var(--teal);font:600 15px/1.2 var(--sans);
  text-decoration:underline;text-decoration-thickness:1.5px;text-underline-offset:5px}
@media (hover:hover){.bay-all:hover{text-decoration-thickness:2.5px}}
.motion .bay.is-open .bay-pack{animation:pack-in 420ms cubic-bezier(.2,.7,.2,1) calc(90ms + var(--k) * 55ms) backwards}
@keyframes pack-in{from{opacity:0;transform:translate3d(0,14px,0) scale(.94)}}
/* it arrives closed: the case rises in with the heading (.grow) and its lids settle into place */
.motion .case.in .lid{animation:lid-settle 560ms cubic-bezier(.2,.7,.2,1) calc(140ms + var(--i) * 45ms) backwards}
@keyframes lid-settle{from{transform:perspective(640px) rotateX(-9deg) translate3d(0,-3px,0)}}
/* no script: every compartment open, no lids. Keyed to html.js (set in the head), not to the case's
   own script, so with script the packs are never fetched before a lid is opened */
html:not(.js) .lid{display:none}
html:not(.js) .bay-in[hidden]{display:grid!important}
html:not(.js) .bay-well{grid-template-rows:1fr}
html:not(.js) .bay-lid{cursor:default}
html:not(.js) .bay-name{color:var(--teal)}
html:not(.js) .bay-note{color:var(--text)}
@media (prefers-reduced-motion:reduce){.lid,.bay-well,.case-bays,.bay-name,.bay-note,.bay-go img{transition:none}}
@media (min-width:768px){.case{margin-inline:auto}}
@media (min-width:1024px){
  .case{max-width:none;padding:12px;border-radius:28px}
  .case-bays{grid-template-columns:repeat(7,minmax(0,1fr));gap:8px;transition:grid-template-columns var(--hinge)}
  .bay{grid-template-rows:auto minmax(0,1fr);height:320px;border-radius:18px;container-type:inline-size}   /* not less: the tallest packs need it to stand whole */
  /* the lid covers the whole compartment, the button only its label: a tap on the lid is a tap on it */
  .bay-lid{position:static;align-content:start;min-height:0;padding:22px 14px 10px}
  .bay-name{font-size:clamp(9px,calc((100cqi - 28px) / 9.9),13px);letter-spacing:.18em}
  .bay-note{font-size:clamp(8.5px,calc((100cqi - 28px) / 7.8),10.5px);letter-spacing:.14em}
  .lid{background:linear-gradient(100deg,transparent 30%,rgba(255,255,255,.07) 48%,transparent 64%) calc(var(--i) * 100% / 6) 0 / 700% 100% no-repeat,
    linear-gradient(var(--lid),var(--lid-lo))}
  .lid::after{right:auto;left:50%;top:auto;bottom:18px;width:30px;height:6px;margin:0 0 0 -15px}
  .bay-well,.bay.is-open .bay-well{grid-template-rows:1fr}
  .bay-in{align-content:end;padding:0 14px 8px}
  .bay-packs{gap:10px}
  .bay-go img{--w:min(100%,124px);--s:1.42;margin-top:calc(var(--w) * (1 - var(--s)) * .91);margin-bottom:calc(var(--w) * (1 - var(--s)) * .09)}
  /* ...and the rack's panel takes that pull-up back as headroom. The pack is drawn 1.42x and hauled up by
     91% of the overflow so the row keeps its original height and the pack stands proud of it — but from
     1024 that pull is 47.4px and it was landing ON the heading. Measured 2026-10-09: the highest pack
     overlapped the line under the title by 31.4px on ALL TEN shelves at 1024, 1200, 1440 and 1920. Below
     1024 the pull is 0 and there is a 16px gap, so phones and tablets were never affected — what Peter
     saw ("the words are getting cut off") was the XS Energy can's silver top sitting over "BEFORE THE
     SESSION", which the dark bay made obvious and the light one had hidden. Giving the list the 47.4px
     back puts the desktop gap at the phone's own 16px. The numbers are the line above's; change both
     together, and re-measure the gap on energy-focus, whose can is the tallest pack on the rack. */
  .rk-panel .bay-packs{padding-top:calc(2px + 124px * (1.42 - 1) * .91)}
  .bay-all{margin-bottom:6px}
}

/* ---------- The product card (#pcard): a pack in an open compartment, up close ---------- */
/* The case in small: a teal rim round a sand well, the pack standing in it, its name in the
   display face, a line, a few facts as small-caps chips and the way to Amway. A modal <dialog>
   (_script.html): a bottom sheet on a phone, a card in the middle from 700. The pack flies into it
   from its compartment and a few sparks go off as it lands (transforms and opacity only, none of
   it under reduced motion). html.locked, as for the menu, keeps the page still and the tab away. */
.pcard{width:100%;max-width:none;max-height:none;margin:auto 0 0;padding:0;border:0;background:transparent;overflow:visible;color:var(--ink)}
.pcard::backdrop{background:rgba(0,16,22,.62)}
.motion .pcard[open]::backdrop{animation:pc-dim 240ms ease-out}
.pcard.is-closing::backdrop{animation:pc-undim 200ms cubic-bezier(.23,1,.32,1) forwards}
@keyframes pc-dim{from{opacity:0}}
@keyframes pc-undim{to{opacity:0}}
@media (prefers-reduced-motion:reduce){.pcard[open],.pcard[open]::backdrop{animation:pc-dim 150ms ease-out}}
.pcard-in{position:relative;max-height:calc(100dvh - 24px);overflow-y:auto;overscroll-behavior:contain;
  padding:8px 8px calc(8px + env(safe-area-inset-bottom,0px));border-radius:24px 24px 0 0;
  background:linear-gradient(165deg,color-mix(in srgb,var(--teal) 90%,var(--chalk)) 0%,color-mix(in srgb,var(--teal) 88%,#000) 40%,color-mix(in srgb,var(--teal) 70%,#000) 100%);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.16),0 0 0 1px rgba(230,211,197,.24),0 -20px 50px -20px rgba(0,20,27,.6)}
.pcard-art{position:relative;display:grid;place-items:center;padding:14px 0 0;border-radius:16px 16px 0 0;
  background:linear-gradient(color-mix(in srgb,var(--sand) 50%,var(--chalk)),color-mix(in srgb,var(--sand) 72%,var(--chalk)));
  box-shadow:inset 0 9px 14px -9px rgba(0,20,27,.55)}
.pcard-art img{display:block;width:min(56vw,220px);height:auto;filter:drop-shadow(0 10px 10px rgba(0,20,27,.22))}
.pcard-copy{display:grid;justify-items:start;gap:10px;padding:6px 20px 20px;border-radius:0 0 16px 16px;background:var(--sand)}
.pcard-kind{margin:0;font:600 11px/1.35 var(--sans);letter-spacing:.16em;text-transform:uppercase;color:var(--text)}
.pcard-name{margin:0;font:600 32px/1.06 var(--display);letter-spacing:-.018em;color:var(--teal);text-wrap:balance}
.pcard-line{margin:0;font:500 16px/1.4 var(--sans);color:var(--ink)}
.pcard-facts{list-style:none;display:flex;flex-wrap:wrap;gap:6px;margin:2px 0 4px;padding:0}
.pcard-facts li{display:inline-flex;align-items:center;min-height:28px;padding:0 11px;border-radius:999px;background:var(--teal);color:var(--sand);
  font:600 11px/1.2 var(--sans);letter-spacing:.12em;text-transform:uppercase}
.pcard-facts[hidden]{display:none}
.pcard-buy{width:100%}
/* a SHORT phone (2026-10-29, a critic at 320x568): the pack drawn smaller so "Buy on Amway" and the sample
   button are on the screen without a scroll nobody knows to make */
@media (max-width:699px) and (max-height:620px){.pcard-art img{width:min(42vw,150px)}.pcard-name{font-size:28px}}
.pcard-x{position:absolute;z-index:2;top:14px;right:14px;border-radius:50%;background:rgba(244,242,236,.7);color:var(--teal)}
.pcard-x:focus-visible{outline:2px solid var(--teal);outline-offset:2px}
/* the pack in flight, and the sparks: fixed in the top layer, never in the way of a tap */
.pcard-fly,.pcard-spark{position:fixed;left:0;top:0;pointer-events:none;will-change:transform,opacity}
.pcard-fly{z-index:3;transform-origin:0 0;filter:drop-shadow(0 10px 10px rgba(0,20,27,.22))}
.pcard-fly[hidden]{display:none}
.pcard-spark{z-index:1;width:7px;height:7px;margin:-3.5px 0 0 -3.5px;border-radius:50%}
@media (min-width:700px){
  .pcard{width:min(680px,calc(100% - 48px));margin:auto}
  .pcard-in{display:grid;grid-template-columns:minmax(0,5fr) minmax(0,6fr);max-height:calc(100dvh - 48px);padding:10px;border-radius:28px;
    box-shadow:inset 0 1px 0 rgba(255,255,255,.16),0 0 0 1px rgba(230,211,197,.24),0 34px 60px -30px rgba(0,20,27,.65)}
  .pcard-art{padding:24px 12px;border-radius:18px 0 0 18px}
  .pcard-art img{width:min(100%,260px)}
  .pcard-copy{align-content:center;padding:28px 28px 26px;border-radius:0 18px 18px 0}
  .pcard-name{font-size:38px}
}

/* ── Opening curtain ───────────────────────────────────────────────────────────
   The landing page only, every load -- shop.html since 2026-10-04, when Peter made the
   Shop the first tab and the page the site opens on. Nothing here paints on its own: site-src/_intro.html
   inserts .intro at run time, so there is no curtain in the markup and none without
   JS. The halves are SVG so the seam can follow the wave's own centre line; only their
   transform ever changes. The guard at the bottom is a second lock on reduced motion,
   after the one in the script. */
.intro{position:fixed;inset:0;z-index:100;overflow:hidden;contain:layout paint;
  font-family:var(--sans);color:var(--chalk);--curtain:#000}   /* black, not the teal: the lit
     build of the wave was drawn on black, and on teal its bloom flattens and its outer
     edges melt into the ground. The page it parts to reveal is the page, unchanged. */
.intro-sheet{position:absolute;inset:0;background:var(--curtain)}
.intro-half{position:absolute;inset:0;display:block;width:100%;height:100%;fill:var(--curtain);
  will-change:transform}
.intro-stage{position:absolute;inset:0;display:grid;align-content:center;justify-items:center;
  padding:0 var(--pad);text-align:center}
.intro-word{display:flex;justify-content:center;margin-right:-.14em;font-weight:800;
  font-size:clamp(21px,7vw,58px);line-height:1;letter-spacing:.14em;text-transform:uppercase;white-space:nowrap}
.intro-l{display:block;overflow:hidden;padding:.05em 0 .1em}      /* the mask the letters rise out of */
.intro-l > span{display:block;transform:translateY(118%)}
.intro-sp{display:block;width:.5em}
.intro-tag{margin:1.4em 0 0;opacity:0;color:var(--sand);
  font:600 clamp(9px,2.4vw,12px)/1 var(--sans);letter-spacing:.34em;text-transform:uppercase}
/* The wave, in layers. Only the divs ever move: .intro-wave carries the flight into the
   masthead and .intro-sweep the arrival, while .intro-lit and .intro-flat only ever swap,
   on one frame, under that movement. Neither build is transformed itself. */
.intro-wave{position:absolute;transform-origin:0 0;will-change:transform}
.intro-sweep{position:absolute;inset:0;opacity:0;transform-origin:50% 50%;
  will-change:transform,opacity}
.intro-lit,.intro-flat{position:absolute;inset:0;will-change:opacity}
/* the flat mark is what shows by default, so a render that has not arrived costs the
   curtain its lighting and nothing else; the script raises .intro-lit only once the
   render has decoded */
.intro-lit{opacity:0}
.intro-flat{opacity:1}
.intro-wave svg{position:absolute;inset:0;display:block;width:100%;height:100%}
.intro-flat svg{fill:var(--sand);stroke:none}   /* the masthead's own colour, so it lands into it */
/* Peter's render is a different wave from the drawn mark — best fit over its centre line
   leaves a mean of 0.38 and a worst of 1.21 of the mark's 100 units. These four numbers
   are that fit, as percentages of the mark's own box, so the lit wave sits as nearly on
   the flat one as it can; the rest is why the swap is a cut and not a dissolve. */
.intro-lit img{position:absolute;left:.686%;top:-27.116%;width:102.820%;height:141.954%;
  display:block;max-width:none}
@media (prefers-reduced-motion:reduce){.intro{display:none}}

/* the FDA sentence sits under the vendor line, quieter but still legible */
.foot-fda{margin:10px 0 0;font-size:12px;line-height:1.5;color:var(--on-dark);opacity:.72;max-width:66ch}

/* ---------- Macros: seven questions, one per screen, then the numbers ----------
   A sand band between the drained glass's chalk above it and the consult's chalk below,
   so the calculator reads as its own step rather than more of the page. The card is
   opaque chalk rather than the consult's translucent glass: every number in it is
   measured for contrast, and a backdrop that changes underneath would make those
   measurements a guess. Without script the quiz and the results are both removed and
   .mc-nojs says so, so the band is never a dead husk. */
.macros-sec{background:var(--sand)}
.macros-sec h2 span{display:block}
.mc-card{display:grid;gap:20px;padding:24px 20px 26px;background:var(--chalk);
  box-shadow:inset 0 0 0 1px rgba(30,38,47,.12),0 40px 60px -40px rgba(0,30,39,.55)}
.mc-nojs{font-size:15px;line-height:1.55;color:var(--ink)}
.mc-nojs .tlink{min-height:0;font-size:15px}
html.js .mc-nojs{display:none}
html:not(.js) .mc-quiz,html:not(.js) .mc-res{display:none}

.mc-quiz{display:grid;gap:16px}
.mc-count{font-size:14px;color:var(--text)}
.mc-prog{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:5px;margin-top:-8px}
.mc-prog span{height:3px;background:rgba(0,46,59,.18)}
.mc-prog span.is-on{background:var(--teal)}
/* one step per screen; the script hides the rest, and the legend is the question */
.mc-step{margin:0;padding:0;border:0;min-width:0}
.mc-q{display:block;width:100%;padding:0;margin:0 0 12px;font:600 22px/1.25 var(--sans);color:var(--teal)}
.mc-q:focus{outline:none}
.mc-help{margin:0 0 14px;font-size:14px;line-height:1.55;color:var(--text)}
.mc-in{animation:mc-in 260ms cubic-bezier(.2,.7,.2,1) both}
@keyframes mc-in{from{opacity:0;transform:translate3d(0,8px,0)}}

/* the options are the consult's chip, stacked: a real radio under a pill */
.mc-opts{display:grid;grid-template-columns:minmax(0,1fr);gap:8px}
.mc-opts.cols{grid-template-columns:repeat(2,minmax(0,1fr))}
.mc-opts.cols3{grid-template-columns:repeat(3,minmax(0,1fr))}
.mc-opt{position:relative;display:block;cursor:pointer}
.mc-opt input{position:absolute;width:1px;height:1px;opacity:0;margin:0}
.mc-opt span{display:flex;align-items:center;height:100%;min-height:56px;padding:12px 15px;
  border:1px solid var(--line);background:rgba(255,255,255,.6);color:var(--ink);
  font:600 15px/1.25 var(--sans);transition:background .15s,color .15s,border-color .15s}
.mc-opt input:checked + span{background:var(--teal);border-color:var(--teal);color:var(--chalk)}
.mc-opt input:focus-visible + span{outline:2px solid var(--teal);outline-offset:3px}
@media (hover:hover){.mc-opt:hover span{border-color:var(--teal)}}

/* the follow-up a single answer opens: frame size, training history, how hard a deficit */
.mc-sub{margin:16px 0 0;padding:16px 0 0;border:0;border-top:1px solid var(--line);min-width:0}
/* a real top border, not an inset shadow: the browser cuts the gap the legend sits in, and a
   shadow would be painted straight through the words instead */
.mc-sub legend{padding:0 10px 0 0;margin-bottom:10px;font:600 15px/1.3 var(--sans);color:var(--ink)}

.mc-field{display:grid;gap:8px}
.mc-field label{font:600 15px/1.3 var(--sans);color:var(--ink)}
.mc-field input{width:100%;min-width:0;height:52px;padding:0 14px;border:1px solid var(--line);
  border-radius:var(--r);background:rgba(255,255,255,.7);color:var(--ink);font-size:16px;
  -webkit-appearance:none;appearance:none}
.mc-field input:focus{outline:none;border-color:var(--teal);box-shadow:inset 0 0 0 1px var(--teal)}
/* the spinners cost width the 320px card has not got, and nobody nudges their height by 1in */
.mc-field input::-webkit-outer-spin-button,.mc-field input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}
.mc-field input[type=number]{-moz-appearance:textfield}
.mc-pair{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}

.mc-nav{display:flex;flex-wrap:wrap;align-items:center;gap:12px}
.mc-nav .btn{flex:1 1 140px}
/* errors and warnings carry a rule and their own words, never colour alone */
.mc-err,.mc-warn{padding:12px 14px;background:rgba(169,71,31,.07);box-shadow:inset 2px 0 0 var(--accent);
  color:var(--ink);font-size:14px;line-height:1.55}
.mc-err{font-weight:600;font-size:15px}

.mc-res{display:grid;gap:18px}
.mc-res-t{font:600 30px/1.08 var(--display);letter-spacing:-.016em;color:var(--teal)}
.mc-res-t:focus{outline:none}
.mc-cals{margin:0;border-top:1px solid var(--line)}
.mc-cals > div{display:flex;flex-wrap:wrap;align-items:baseline;justify-content:space-between;
  gap:2px 16px;padding:12px 0;border-bottom:1px solid var(--line)}
.mc-cals dt{font:600 15px/1.3 var(--sans);color:var(--text)}
.mc-cals dd{margin:0;font:600 17px/1.3 var(--sans);color:var(--ink)}
.mc-cals > div:last-child dd{font-size:22px;color:var(--teal)}
.mc-macros{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}
.mc-macros li{display:grid;gap:3px;justify-items:center;padding:14px 6px;background:var(--tile);text-align:center}
.mc-g{font:700 28px/1 var(--sans);font-variant-numeric:tabular-nums;letter-spacing:-.012em;color:var(--teal)}
/* break-ui: a four-digit gram figure ("1,267g") at 28px touched the tile edge on a 320px phone */
@media (max-width:399px){.mc-g{font-size:min(28px,7.4vw)}}
.mc-lab{font:600 12px/1.3 var(--sans);letter-spacing:.12em;text-transform:uppercase;color:var(--text)}
.mc-kc{font-size:13px;color:var(--text)}
.mc-notes{display:grid;gap:10px}
.mc-note{font-size:14px;line-height:1.55;color:var(--text)}
.mc-res .btn{width:100%}
.mc-foot{display:flex;flex-wrap:wrap;align-items:center;gap:0 20px}
@media (prefers-reduced-motion:reduce){
  .mc-in{animation:none}
  .mc-opt span{transition:none}
}
@media (min-width:768px){
  .macros-sec .mc-card{grid-column:7 / 13}
  .mc-card{padding:32px;gap:24px}
  .mc-q{font-size:24px}
  .mc-opt span{min-height:60px;padding:14px 18px;font-size:16px}
  .mc-res-t{font-size:38px}
  .mc-macros{gap:12px}
  .mc-g{font-size:34px}
}

/* ---------- Load the bar (SHELF_VIEW 'bar'): the barbell, the plate rack, the pinned bar ---------- */
/* The barbell, side on, drawn from its font-size: 1em is a tenth of the biggest plate. Two sleeves
   either side of the collars, and the shaft between. Its proportions are a competition bar's, as far
   as nine plates a side allow: a 28mm shaft and a 50mm sleeve on a 450mm plate are .62em and 1.1em
   here, far too thin to see at 3-9px, so the bar is drawn thick (--shaft 1.45em, sleeve 2.35em) and
   the length is what carries the proportion instead. A plate is 1.4em of sleeve (--st), which is a
   real bumper's 65mm on 450mm, so nine of them take 13.6em rather than the 19.65em they took when a
   plate was 2.05em; that alone turns the shaft from a quarter of a sleeve into about twice one. The
   em budgets below (100cqi / 52 and friends) set how much of each box is left to the shaft. It is drawn as the real thing, all in gradients:
   a brushed shaft with its knurling (the centre patch and the two grips, a fine crosshatch that goes
   to a matte grey tone when the bar is small), polished sleeves that catch a harder light, and
   collars with their clamp. A plate is a bumper seen edge on: a thick rubber disc in its shelf's
   colour with rounded edges, lit along its top edge and darker to its foot, the steel of its hub
   showing where the sleeve goes through. It is as tall as its rank allows (--s) and sits --o steps
   out from the collar: larger plates nearest it. An unloaded plate waits just past the end of its
   sleeve, clipped, and slides on in 360ms, overshooting a hair onto the one before and settling
   back, as a heavy thing does; under reduced motion it is simply there. Only transform and opacity
   ever change. */
/* rubber grain: a speckle of dark and light in about equal measure, so it leaves a plate's colour (and
   the contrast of the words on it) where it was; laid over the rack's faces and the bar's plates */
.t-bar{--rubber:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='d'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.95' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -2.4 1.4'/%3E%3C/filter%3E%3Cfilter id='l'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.95' numOctaves='2' seed='9' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 2.4 -1'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23d)' opacity='.12'/%3E%3Crect width='120' height='120' filter='url(%23l)' opacity='.08'/%3E%3C/svg%3E");--rubber-soft:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='d'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.95' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -1.3 0.72'/%3E%3C/filter%3E%3Cfilter id='l'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.95' numOctaves='2' seed='9' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1.3 -0.5'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23d)' opacity='.12'/%3E%3Crect width='120' height='120' filter='url(%23l)' opacity='.08'/%3E%3C/svg%3E")}
.bbx{container-type:inline-size;min-width:0}
.bb{--st:1.4em;--pw:1.22em;--off:.85;--steel:linear-gradient(#EEF1F2,#D5DADD 22%,#A9B1B6 50%,#7D868C 78%,#646D73);
  display:flex;align-items:center;height:10em;font-size:4px;line-height:0;overflow:clip visible}
/* the sleeves: polished, a hard specular line a fifth of the way down, a chamfer at the outer end */
.bb-sl{position:relative;flex:none;width:calc(var(--n,7) * var(--st) + 1em);height:2.35em;
  background:linear-gradient(#F4F6F7 0,#FFFFFF 14%,#DDE2E4 26%,#B3BBC0 48%,#8A9399 70%,#A3ABB0 86%,#5F686E 100%)}
.bb-l{border-radius:.75em .16em .16em .75em;box-shadow:inset .3em 0 .16em -.14em rgba(40,48,54,.55)}
.bb-r{border-radius:.16em .75em .75em .16em;box-shadow:inset -.3em 0 .16em -.14em rgba(40,48,54,.55)}
/* the collars: a turned steel ring, split, with the bolt that clamps it standing up at the top */
.bb-co{position:relative;flex:none;width:1.35em;height:3.9em;border-radius:.36em/.3em;
  background:linear-gradient(90deg,rgba(255,255,255,.3),rgba(255,255,255,0) 28%,rgba(0,0,0,0) 72%,rgba(0,0,0,.26)),
    linear-gradient(#F4F6F7,#DCE1E3 16%,#A7B0B5 46%,#7B848A 76%,#5A636A);
  box-shadow:inset 0 0 0 max(.5px,.06em) rgba(30,38,44,.45)}
.bb-co::before{content:"";position:absolute;left:50%;width:max(.5px,.12em);margin-left:max(-.25px,-.06em);top:.24em;bottom:.24em;background:rgba(24,30,34,.6)}
.bb-co::after{content:"";position:absolute;left:.32em;right:.32em;bottom:calc(100% - .15em);height:.7em;border-radius:.12em .12em 0 0;
  background:linear-gradient(90deg,#5F686E,#D5DADD 40%,#8A9399 75%,#5F686E);box-shadow:inset 0 max(.5px,.06em) 0 rgba(255,255,255,.5)}
/* the shaft: brushed, a softer light than the sleeves */
.bb-sh{position:relative;flex:1 1 auto;min-width:3em;height:1.45em;
  background:repeating-linear-gradient(90deg,rgba(255,255,255,.07) 0 .05em,transparent .05em .13em),
    linear-gradient(#E2E6E8 0,#F3F5F6 16%,#C2C9CD 36%,#9BA4A9 62%,#737C82 88%,#5E676D 100%)}
/* the knurling: a diamond crosshatch cut into the steel, over the same light */
.bb-kn,.bb-sh::before,.bb-sh::after{position:absolute;top:0;bottom:0;border-radius:.05em;
  background:repeating-linear-gradient(62deg,rgba(28,34,38,.5) 0 .075em,transparent .075em .21em),
    repeating-linear-gradient(-62deg,rgba(28,34,38,.5) 0 .075em,transparent .075em .21em),
    linear-gradient(rgba(255,255,255,.22),transparent 40%,rgba(0,0,0,.14))}
.bb-kn{left:45%;right:45%}
/* under 4px a crosshatch only shimmers: the knurling is a matte, darker steel instead */
.lbpin-bars .bb-kn,.lbpin-bars .bb-sh::before,.lbpin-bars .bb-sh::after{background:linear-gradient(#B4BBBF,#8D969B 45%,#646D73)}
.bb-sh::before,.bb-sh::after{content:"";width:31%}
.bb-sh::before{left:5%}
.bb-sh::after{right:5%}
/* a plate, edge on */
/* a plate rides on and off the sleeve: parked, it sits (--n + --off) steps out, past the sleeve's outer
   end, where .bb's `overflow:clip visible` cuts it off; loaded, it slides in to its own step (--o) with
   a little overshoot at the stop. The clip is what reveals it, so the opacity is only there to stop a
   hard edge appearing at the bar's end — it was 140ms, which left the plate half transparent for the
   first 40% of a 360ms slide (the travel is 48.6px at 390 and 59.2px at 1440, measured 2026-10-09). */
.bb-p{position:absolute;top:50%;width:var(--pw);height:calc(var(--s) * 10em);margin-top:calc(var(--s) * -5em);border-radius:.3em/.55em;
  opacity:0;will-change:transform,opacity;
  transition:transform 360ms cubic-bezier(.22,1.2,.36,1.04),opacity 70ms linear}
/* the rubber: drawn over the hub (below), so the steel shows only where it stands proud of the faces */
.bb-p::after{content:"";position:absolute;inset:0;border-radius:inherit;
  background:var(--rubber),linear-gradient(90deg,rgba(0,0,0,.36),rgba(0,0,0,.08) 10%,rgba(0,0,0,0) 18%,rgba(0,0,0,0) 82%,rgba(0,0,0,.1) 90%,rgba(0,0,0,.42)),
    linear-gradient(rgba(0,0,0,.12) 0,rgba(255,255,255,.4) 2.5%,rgba(255,255,255,.2) 9%,rgba(255,255,255,.07) 22%,rgba(255,255,255,0) 38%,
      rgba(0,0,0,0) 50%,rgba(0,0,0,.16) 74%,rgba(0,0,0,.4) 93%,rgba(0,0,0,.3) 100%),
    var(--c);
  background-size:48px 48px,auto,auto,auto;
  box-shadow:inset 0 0 0 max(.5px,.05em) rgba(0,0,0,.28),.18em .35em .55em -.2em rgba(0,15,20,.45)}
/* its hub: the steel insert the sleeve goes through, standing just proud of the rubber on each face,
   so it shows only as a sliver of steel between one plate and the next */
.bb-p::before{content:"";position:absolute;left:-.1em;right:-.1em;top:50%;height:2.75em;margin-top:-1.375em;border-radius:.18em;
  background:linear-gradient(90deg,rgba(0,0,0,.25),transparent 30%,transparent 70%,rgba(0,0,0,.3)),
    linear-gradient(#F4F6F7,#C9CFD3 30%,#8C959B 70%,#646D73);box-shadow:0 0 0 max(.4px,.04em) rgba(20,26,30,.35)}
.bb-l .bb-p{right:.15em;transform:translate3d(calc((var(--n,7) + var(--off)) * -1 * var(--st)),0,0)}
.bb-r .bb-p{left:.15em;transform:translate3d(calc((var(--n,7) + var(--off)) * var(--st)),0,0)}
.bb-l .bb-p.on{opacity:1;transform:translate3d(calc(var(--o) * -1 * var(--st)),0,0)}
.bb-r .bb-p.on{opacity:1;transform:translate3d(calc(var(--o) * var(--st)),0,0)}
.bb-dk .bb-p::after{box-shadow:inset 0 0 0 max(.5px,.06em) rgba(244,242,236,.22),.18em .35em .55em -.2em rgba(0,0,0,.5)}   /* the dark plates keep an edge on teal */
/* the newest plate's outline: flashed by the script, never left on */
.bb-ring{position:absolute;inset:calc(-1 * max(3px,.4em));border:max(1.5px,.2em) solid var(--teal);border-radius:max(3px,.8em)/max(3px,1em);opacity:0}
.bb-dk .bb-ring{border-color:var(--sand)}
@media (prefers-reduced-motion:reduce){.bb-p{transition:none}}

/* the pinned bar: under the masthead once the hero has gone, on phones and desktop. The visitor's
   own stack, or gone if they have none. It carried Peter's five through the story's scroll-scrubbed
   stage until 2026-10-01, on a second bar and a second caption set that cross-faded with theirs;
   the stage went and so did both. As slim as it can be and still be read: a 31px bar and one 10px
   caption row. */
.t-bar{--pin:52px;scroll-padding-top:calc(var(--mh) + var(--pin) + var(--srch,0px))}
.lbpin{position:fixed;left:0;right:0;top:calc(env(safe-area-inset-top,0px) + var(--mh) + var(--srch,0px));z-index:18;background:var(--chalk);
  box-shadow:0 1px 0 var(--line),0 12px 18px -16px rgba(0,20,27,.55);
  transform:translate3d(0,-100%,0);visibility:hidden;transition:transform 280ms cubic-bezier(.2,.7,.2,1),visibility 0s linear 280ms}
.lbpin.on{transform:none;visibility:visible;transition:transform 280ms cubic-bezier(.2,.7,.2,1),visibility 0s}
html.locked .lbpin{visibility:hidden}
html:not(.js) .lbpin{display:none}
.lbpin-in{display:grid;align-content:center;gap:3px;height:var(--pin);padding-top:1px}
.lbpin-bars{display:grid}
.lbpin-bars .bb{grid-area:1 / 1;font-size:3.3px;transition:opacity 220ms linear;will-change:opacity}
.lbpin-cap{display:grid;font:600 10px/1.1 var(--sans);letter-spacing:.14em;text-transform:uppercase;color:var(--text);white-space:nowrap}
.lbc-set{grid-area:1 / 1;display:flex;justify-content:space-between;gap:12px;min-width:0;transition:opacity 220ms linear;will-change:opacity}
.lbc-who,.lbc-new{display:grid;min-width:0}
.lbc-new{justify-items:end;color:var(--teal)}
.lbc{grid-area:1 / 1;overflow:hidden;text-overflow:ellipsis;opacity:0;will-change:opacity}
.lbc-you{opacity:1}
@media (prefers-reduced-motion:reduce){.lbpin,.lbpin.on,.lbpin-bars .bb,.lbc-set{transition:none}}
/* "Bring it to a call" (2026-10-04): the strip's one way on, at its right end, the call button's blue
   a size down. While the strip is away it is hidden with it (visibility), so it is never tabbed to. */
.lbpin-in{grid-template-columns:minmax(0,1fr) auto;column-gap:16px}
.lbpin-bars,.lbpin-cap{grid-column:1}
.lbpin-go{grid-column:2;grid-row:1 / 3;align-self:center;display:inline-flex;align-items:center;gap:6px;min-height:44px;padding:0 14px;
  border-radius:var(--r);background:var(--accent);color:#fff;font:600 13px/1.15 var(--sans);text-decoration:none;white-space:nowrap}
.lbpin-go .ic{flex:none;width:14px;height:14px}
.lbpin-go:active{opacity:.8}
/* a phone's strip is one 36px row: the caption on the left ("Your stack · 2"), the bar on the
   right, a 30px bar. "+ name" comes up over the caption for a moment, on the strip's own chalk,
   and goes. With the masthead that is 96px; while the strip is up the bottom tab steps aside
   (html.pin-you, set by the script), so the fixed chrome is never more than 96px. */
/* phones land a jump to the rack with its heading just under the chrome, not 72px of padding further down, and
   Top 9 starts its heading half a section higher, so more of the first pack shows (2026-10-24, a critic) */
@media (max-width:767px){.rack-sec{scroll-margin-top:calc(12px - var(--sec))}.start-sec{padding-top:calc(var(--sec) * .5)}}
@media (max-width:767px){
  .t-bar{--pin:36px}
  .lbpin-in{grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:0 12px;padding-top:0}
  .lbpin-cap{grid-row:1;grid-column:1;font-size:10px;letter-spacing:.1em}
  .lbpin-bars{grid-row:1;grid-column:2}
  .lbpin-go{grid-column:3;grid-row:1;min-height:30px;padding:0 10px;font-size:12px;gap:4px;position:relative}
  .lbpin-go::after{content:"";position:absolute;inset:-7px -4px}   /* a 44px tap target inside a 36px strip (2026-10-24) */
  .lbpin-go .ic{width:12px;height:12px}
  .lbpin-bars .bb{font-size:min(3.2px,calc(100cqi / 36))}   /* the bar gives way to the call link (2026-10-04) rather than run under it */
  .lbc-lg{display:none}
  .lbc-set{display:grid}
  .lbc-who,.lbc-new{grid-area:1 / 1}
  .lbc-who{will-change:opacity}   /* its own layer from the start: fading it for "+ name" then costs no layout */
  .lbc-new{justify-items:stretch}
  .lbc-new .lbc{background:var(--chalk)}
  html.pin-you .mtab{transform:translateY(calc(100% + 2px));visibility:hidden}
}
/* under 375 the link says "Book a call" on ONE line with no arrow, so the bar keeps ~100px of the 280 (2.8px a
   plate step). It wrapped "Bring it to a call" onto two 11px lines until 2026-10-29, which a critic caught at 360,
   the commonest Android width. The ::after above still makes it a 44px target. */
.lbpin-s{display:none}
@media (max-width:374.98px){
  .lbpin-in{column-gap:8px}
  .lbpin-go{padding:0 9px;font-size:12px}
  .lbpin-l,.lbpin-go .ic{display:none}
  .lbpin-s{display:inline}
}
@media (min-width:768px){
  .t-bar{--pin:60px}
  .lbpin-in{max-width:780px;row-gap:4px}
  .lbpin-bars .bb{font-size:3.9px}
  .lbpin-cap{font-size:10.5px}
}

/* #goals as a plate rack: ten plates, front on, all on show. Phones two a row (five even rows), each
   about 163px at 390 and 131px at 320, so the line under a plate's name is 11px or more (it was 7.9px on
   a phone with three a row); 768 to 1023 three rows of three and the tenth centred, ~175px each; from
   1024 two rows of five, ~162px each (one row was 86-123px a plate at 768-1199, its line 7.5-9px). A plate is a button, drawn as a competition bumper standing on the page:
   a matte rubber face in its shelf's colour with a fine grain, a raised rim (lit on top, in shade
   underneath), a machined steel hub bolted through it on a six-bolt circle, a dark bore, a side wall
   showing under the face so it reads as a thick disc, and a soft contact shadow under it. It used to
   carry a second, recessed ring round the hub and a small bright hole in the middle: face on, that is
   a record, so the ring is gone, the hub is bolted steel and the bore is a dark tube. Its name is moulded into the rubber above the hub (a light top edge, a dark
   bottom edge) and its shelf's line under it, which reads "On the bar" once it is loaded. The one whose
   panel is open wears an outline ring. */
.rack-sec .sec-head{margin-bottom:22px}
.rk-hint{font:500 16px/1.4 var(--sans);color:var(--text)}
/* the plates and the panels wrap in one row: the list steps aside (display:contents, its role kept by
   role="list"), so a panel can go in under the row of the plate that opened it. The script sets
   `order` (the open panel 1, the plates after its row 2); without it every panel follows the ten. */
.rack{--cols:2;--gap:18px;display:flex;flex-wrap:wrap;justify-content:center;gap:20px var(--gap);max-width:344px;margin:0 auto}
.rk-plates{display:contents;list-style:none}
.rk-plates li{flex:0 0 calc((100% - (var(--cols) - 1) * var(--gap)) / var(--cols));min-width:0}
.rk-plate{position:relative;display:block;width:100%;aspect-ratio:1;margin:0;padding:0;border:0;border-radius:50%;background:none;
  color:var(--t);container-type:inline-size;-webkit-tap-highlight-color:transparent}
.rk-plate:focus-visible{outline:2px solid var(--teal);outline-offset:4px}
/* the contact shadow: on the page, under the plate, drawn before it */
.rk-plate::before{content:"";position:absolute;left:9%;right:9%;bottom:-6.5%;height:13%;border-radius:50%;
  background:radial-gradient(closest-side,rgba(0,20,27,.42),rgba(0,20,27,.16) 55%,rgba(0,20,27,0));transition:opacity 200ms,transform 200ms cubic-bezier(.2,.7,.2,1)}
/* the face: the colour under a broad satin light from the top left, a fine rubber grain, and the rim's
   curve in its edge (a highlight on top, shade underneath) */
/* the face uses the gentler grain (--rubber-soft): at full strength a single dark speckle under a
   letter dropped the measured contrast under 4.5 even though the face around it is 8:1. */
.rk-disc{position:absolute;inset:0;border-radius:50%;
  background:var(--rubber-soft,var(--rubber)),
    radial-gradient(120% 120% at 32% 16%,rgba(255,255,255,.1),rgba(255,255,255,.02) 40%,rgba(255,255,255,0) 58%),
    radial-gradient(80% 80% at 72% 98%,rgba(0,0,0,.1),rgba(0,0,0,0) 58%),
    var(--c);
  background-size:120px 120px,auto,auto,auto;
  box-shadow:inset 0 max(1px,1.1cqi) max(1px,.9cqi) rgba(255,255,255,.26),inset 0 min(-1.5px,-1.6cqi) max(1.5px,1.6cqi) rgba(0,0,0,.34),
    inset 0 0 0 max(.5px,.5cqi) rgba(0,0,0,.2),0 max(3px,3.4cqi) 0 color-mix(in srgb,var(--c) 50%,#0B1115),0 12px 18px -10px rgba(0,20,27,.5);
  transition:transform 200ms cubic-bezier(.2,.7,.2,1),box-shadow 200ms}
/* the rim: a raised band round the face, the way a bumper's moulded shoulder stands proud of it.
   The step shades the face under the top of the rim and catches the light at the bottom. It is the
   only ring on the plate: the recessed one that used to sit round the hub read as a record's groove. */
.rk-disc::before{content:"";position:absolute;inset:8.5%;border-radius:50%;background:rgba(0,0,0,.05);
  box-shadow:inset 0 max(1.5px,1.7cqi) max(1.5px,1.5cqi) rgba(0,0,0,.36),inset 0 min(-1.5px,-1.2cqi) 0 rgba(255,255,255,.2),
    0 min(-1px,-1cqi) 0 rgba(0,0,0,.18),0 max(1.5px,1cqi) 0 rgba(255,255,255,.2)}
/* A light plate carries its name in INK, and the rim's top shade falls exactly where the name sits, so
   the one thing that gives a dark plate its margin takes it away from a light one. Measured under the
   glyphs themselves (2026-10-09): hydration went 7.12:1 flat to 3.00:1 rendered, a ratio of 0.42, where
   every white-text plate held 0.62-1.02. That is a pre-existing failure, not a new one — it is why the
   rack could never carry a saturated light plate. On the ink plates only (.is-light, set by the build
   from plate_ink) the top shade is halved and the face keeps a touch of its own colour; the rest of the
   rim — the bottom highlight, the outer step — is untouched, so the plate still reads as a moulded
   bumper. Re-measure the whole rack if this number moves. */
.rk-plate.is-light .rk-disc::before{background:rgba(255,255,255,.04);
  box-shadow:inset 0 max(1.5px,1.7cqi) max(1.5px,1.5cqi) rgba(0,0,0,.17),inset 0 min(-1.5px,-1.2cqi) 0 rgba(255,255,255,.22),
    0 min(-1px,-1cqi) 0 rgba(0,0,0,.12),0 max(1.5px,1cqi) 0 rgba(255,255,255,.22)}
/* the hub: the machined steel insert standing proud of the rubber, with its six bolt heads on a
   circle. It is the one thing a record has not got, and it is what tells the two apart at a glance;
   the bore through it is a dark steel tube now, not the bright spindle hole it used to be. */
.rk-disc::after{content:"";position:absolute;inset:35%;border-radius:50%;
  background:radial-gradient(circle,rgba(255,255,255,.55) 0 10%,#D2D8DB 10% 34%,#98A1A7 34% 52%,rgba(0,0,0,.22) 52% 62%,rgba(0,0,0,.45) 62% 74%,rgba(0,0,0,0) 76%),radial-gradient(circle,rgba(255,255,255,.55) 0 10%,#D2D8DB 10% 34%,#98A1A7 34% 52%,rgba(0,0,0,.22) 52% 62%,rgba(0,0,0,.45) 62% 74%,rgba(0,0,0,0) 76%),radial-gradient(circle,rgba(255,255,255,.55) 0 10%,#D2D8DB 10% 34%,#98A1A7 34% 52%,rgba(0,0,0,.22) 52% 62%,rgba(0,0,0,.45) 62% 74%,rgba(0,0,0,0) 76%),radial-gradient(circle,rgba(255,255,255,.55) 0 10%,#D2D8DB 10% 34%,#98A1A7 34% 52%,rgba(0,0,0,.22) 52% 62%,rgba(0,0,0,.45) 62% 74%,rgba(0,0,0,0) 76%),radial-gradient(circle,rgba(255,255,255,.55) 0 10%,#D2D8DB 10% 34%,#98A1A7 34% 52%,rgba(0,0,0,.22) 52% 62%,rgba(0,0,0,.45) 62% 74%,rgba(0,0,0,0) 76%),radial-gradient(circle,rgba(255,255,255,.55) 0 10%,#D2D8DB 10% 34%,#98A1A7 34% 52%,rgba(0,0,0,.22) 52% 62%,rgba(0,0,0,.45) 62% 74%,rgba(0,0,0,0) 76%),
    conic-gradient(from -28deg,#E9ECED,#A8B0B5 11%,#DCE1E3 23%,#909A9F 36%,#CED4D7 48%,#F2F4F5 57%,#9EA7AC 69%,#D4D9DC 81%,#889197 91%,#E9ECED);
  background-size:17% 17%,17% 17%,17% 17%,17% 17%,17% 17%,17% 17%,auto;
  background-position:50% 7.8%,86.5% 28.9%,86.5% 71.1%,50% 92.2%,13.5% 71.1%,13.5% 28.9%,50% 50%;background-repeat:no-repeat;
  box-shadow:0 0 0 max(.5px,.5cqi) rgba(10,14,17,.42),inset 0 max(1px,.8cqi) 0 rgba(255,255,255,.7),
    inset 0 min(-1px,-.8cqi) max(1px,.7cqi) rgba(0,0,0,.35),0 max(1px,1cqi) max(1.5px,1.4cqi) -1px rgba(0,0,0,.45)}
/* the bore */
.rk-hole{position:absolute;z-index:1;left:44%;top:44%;width:12%;height:12%;border-radius:50%;
  background:radial-gradient(circle,#232B31 0 62%,#39434A 80%,#1A2126 100%);
  box-shadow:inset 0 max(1px,1.2cqi) max(1px,1cqi) rgba(0,0,0,.8),inset 0 min(-1px,-.5cqi) 0 rgba(255,255,255,.14),
    0 0 0 max(.5px,.45cqi) rgba(255,255,255,.55),0 0 0 max(1px,.9cqi) rgba(56,64,70,.6)}
/* the name, moulded in: a light top edge and a dark bottom edge */
.rk-name{position:absolute;left:14%;right:14%;bottom:67.5%;text-align:center;font:700 clamp(11px,8.6cqi,12.5px)/1.04 var(--sans);
  letter-spacing:.03em;text-transform:uppercase;text-wrap:balance;
  text-shadow:0 -.75px 0 rgba(255,255,255,.3),0 .75px 0 rgba(0,0,0,.34)}
.rk-line,.rk-on{position:absolute;left:15%;right:15%;top:69%;text-align:center;font:700 clamp(11px,7.4cqi,12px)/1.1 var(--sans);letter-spacing:.07em;
  text-transform:uppercase;text-wrap:balance;text-shadow:0 -.75px 0 rgba(255,255,255,.26),0 .75px 0 rgba(0,0,0,.3)}
.rk-on{display:none}
.rk-plate.is-on .rk-line{display:none}
.rk-plate.is-on .rk-on{display:block}
.rk-plate[aria-pressed="true"] .rk-disc{box-shadow:inset 0 max(1px,1.1cqi) max(1px,.9cqi) rgba(255,255,255,.26),inset 0 min(-1.5px,-1.6cqi) max(1.5px,1.6cqi) rgba(0,0,0,.34),
  inset 0 0 0 max(.5px,.5cqi) rgba(0,0,0,.2),0 max(3px,3.4cqi) 0 color-mix(in srgb,var(--c) 50%,#0B1115),0 0 0 calc(max(3px,3.4cqi) + 3px) var(--chalk),0 0 0 calc(max(3px,3.4cqi) + 5.5px) var(--teal),0 16px 22px -12px rgba(0,20,27,.6)}
@media (hover:hover){.rk-plate:hover .rk-disc{transform:translate3d(0,-3px,0)}.rk-plate:hover::before{opacity:.7;transform:scale(.94)}}
.rk-plate:active .rk-disc{transform:translate3d(0,1px,0)}
/* The open bay is a DARK panel (Peter, 2026-10-09: "when we open a plate, I think the background should be
   different than the surrounding areas, they're both basically tan right now" — then, shown four, "lets go b").
   It was sand-mixed-with-chalk standing on the chalk field: two tans a few percent apart, so it read as the page
   with a border drawn on it rather than as a surface. Deep teal separates it outright and the cut-out packs, which
   are the content, pop hardest against it. This is NOT glass and must not become it: there is no picture behind the
   rack to look through (see "The glass" above) — it is a flat dark fill, which is also why every figure below can
   be computed rather than sampled. The copy inverts to chalk-on-teal, the "See all" link and the load button take
   sand, and the plate-colour strip along the top edge and the notch above it are untouched, so the bay still
   belongs to the plate that opened it. Measured against the lighter of the two gradient stops (#002B37): the
   heading and the pack names 13.39:1, the line under the heading 9.65:1, "See all" 10.34:1, and the button's teal
   on sand 9.96:1. Focus rings inside it go sand at the top of this file, with .dark and the masthead. */
/* ...and it is TEAL GLASS, not a flat slab (Peter, 2026-10-09: "could we do a glass colored teal? it has
   that glassy/transparent feel"). It follows the house recipe exactly: a tint of Peter's own teal that is
   itself the contrast floor, with the blur declared on its own inside @supports so the tint alone is the
   fallback and nothing depends on backdrop-filter landing. The alpha was chosen by measurement, not by eye
   — composited over the chalk field, 0.90 is the lowest that keeps every piece of copy at 7:1 or better
   (0.86 drops the line under the title to 6.26, 0.74 breaks 4.5). So ~10% of the warm field comes through,
   which is what makes it read as glass rather than as paint. BE HONEST ABOUT WHAT THE BLUR DOES HERE: there
   is no photograph behind the rack, only the field's grain and its two drifting glows, so the blur is a
   faint thing and most of the glassiness is the translucency, the lit top edge and the sand rim. That is
   also why this does not break the "glass goes where there is a picture" rule in the way a bare
   backdrop-filter would: the tint, not the blur, is doing the work. Re-measure on rendered pixels with
   backdrop-filter forced OFF if the alpha ever moves. */
.rk-panel{position:relative;flex:0 0 100%;min-width:0;margin:4px 0;padding:18px 18px 6px;border-radius:18px;
  background:linear-gradient(rgba(0,46,59,.93),rgba(0,46,59,.90));
  box-shadow:inset 0 5px 0 var(--c),inset 0 1px 0 rgba(255,255,255,.20),
    inset 0 0 0 1px rgba(230,211,197,.26),0 18px 34px -24px rgba(0,20,27,.6)}
@supports (backdrop-filter:blur(2px)){.rk-panel{backdrop-filter:blur(20px) saturate(1.12)}}
.rk-panel .rk-title{color:var(--chalk)}
.rk-panel .rk-sub{color:var(--on-dark)}
.rk-panel .bay-pack{color:var(--chalk)}
.rk-panel .bay-all{color:var(--sand)}
.rk-panel .rk-load{background:var(--sand);color:var(--teal)}
.rk-panel .rk-load[aria-pressed="true"]{background:transparent;color:var(--sand);box-shadow:inset 0 0 0 1px var(--sand)}
/* a notch in the plate's colour on the panel's top edge, under the plate it belongs to (--x, set by
   the script as it places the panel) */
.rk-panel.is-at::before{content:"";position:absolute;top:-9px;left:calc(var(--x) - 10px);border:solid transparent;border-width:0 10px 10px;border-bottom-color:var(--c)}
.rk-head{display:grid;gap:5px;margin:4px 0 14px}
.rk-title{font:600 29px/1.06 var(--display);letter-spacing:-.016em;color:var(--teal)}
.rk-sub{font:600 12px/1.3 var(--sans);letter-spacing:.16em;text-transform:uppercase;color:var(--text)}
.rk-hint{margin:12px 0 0;font:500 14px/1.4 var(--sans);color:var(--on-dark)}
.rk-after{margin:22px 0 0;text-align:center;font-size:16px}
.rk-acts{display:flex;flex-wrap:wrap;align-items:center;gap:4px 24px;margin-top:14px}
.rk-load{flex:1 1 100%}
.rk-load[aria-pressed="true"]{background:transparent;color:var(--teal);box-shadow:inset 0 0 0 1px var(--teal)}
.motion .rk-panel .bay-pack{animation:pack-in 420ms cubic-bezier(.2,.7,.2,1) calc(60ms + var(--k) * 55ms) backwards}
html:not(.js) .rk-panel[hidden]{display:block!important}
@media (prefers-reduced-motion:reduce){.rk-disc,.rk-plate::before{transition:none}}
@media (min-width:768px){
  .rack{--cols:3;max-width:560px;gap:22px var(--gap)}
  .rk-panel{padding:24px 28px 10px}
  .rk-load{flex:none}
  .rk-panel .bay-packs{max-width:560px}
}
@media (min-width:1024px){.rack{--cols:5;max-width:880px}}
/* LAPTOP SHOP (2026-10-21, a Fable critic): the heading, the guide and both links stood in one column at the
   left with the right 60% of the screen empty, and the two links sat in separate paragraphs 60px apart.
   The links share one row now, and from 1024 the guide and links stand beside the heading, the pair framed
   to the rack's own 880px so the header sits over what it introduces. */
.rk-links{display:flex;flex-wrap:wrap;gap:8px 24px;margin-top:12px}
@media (max-width:1023px){.rk-panel .bay-pack:nth-child(n+4){display:none}}
@media (min-width:1024px){
  .rack-head{max-width:880px;margin-left:auto;margin-right:auto;align-items:flex-end;flex-wrap:nowrap;gap:24px 48px}
  .rack-head .rack-side{max-width:420px}
  .rk-panel .bay-packs{grid-template-columns:repeat(5,minmax(0,1fr));max-width:none}
}
/* from 768 --sec goes 72 -> 112, so this padding and the next section's top one grow 40px each and left a
   ~250px void under the last row. The rack's bottom padding gives back both (32px), so the gap under the
   last row is the phone's again: 174px from the plates to the next heading at every width */
@media (min-width:768px){.rack-sec{padding-bottom:max(24px,calc(var(--sec) - 80px))}}

/* his stack, the five shelves the story names, drawn loaded, on teal */
.mys-in{display:grid;justify-items:center;gap:20px;text-align:center}
.mys h2{color:var(--chalk);font-size:clamp(46px,14vw,96px)}
.mys-bar{width:100%;max-width:900px;margin:8px 0 4px}
.mys-bar .bb{font-size:clamp(4px,calc(100cqi / 46),15px)}
.mys-key{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;justify-content:center;gap:14px 6px;max-width:720px;
  font:600 11px/1.25 var(--sans);letter-spacing:.12em;text-transform:uppercase;color:var(--on-dark)}
/* the key: each plate's pack from the story, standing on a soft pool of light, and its shelf under it
   with a sliver of the plate's own colour, edge on */
.mys-key li{display:grid;justify-items:center;align-content:start;gap:6px;width:108px}
.mys-th{position:relative;display:block;width:76px;height:76px}
.mys-th::before{content:"";position:absolute;left:12%;right:12%;bottom:4%;height:16%;border-radius:50%;background:radial-gradient(closest-side,rgba(0,0,0,.45),rgba(0,0,0,0))}
.mys-th img{position:relative;display:block;width:100%;height:100%;object-fit:contain;transform:scale(1.32);transform-origin:50% 62%}
.mys-n{display:flex;align-items:flex-start;justify-content:center;gap:6px;text-align:left;text-wrap:balance}
/* each of his packs is its product's tile (2026-10-04): the picture, the product's name in the page's own
   type, then the shelf as before. A tap opens the product's card (#pcard); without script it is the link */
.mys-go{display:grid;justify-items:center;align-content:start;gap:6px;width:100%;color:inherit;text-decoration:none}
.mys-p{font:600 12.5px/1.3 var(--sans);letter-spacing:0;text-transform:none;color:var(--chalk);text-wrap:balance}
.mys-go:active{opacity:.7}
@media (hover:hover){.mys-go:hover .mys-p{text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:3px}}
.mys-key i{flex:none;width:5px;height:15px;margin-top:-1px;border-radius:2px/3px;
  background:linear-gradient(rgba(255,255,255,.45),rgba(255,255,255,0) 30%,rgba(0,0,0,0) 60%,rgba(0,0,0,.4)),var(--c);box-shadow:0 0 0 1px rgba(230,211,197,.35)}
.mys-build{margin-top:18px;font:600 clamp(38px,10vw,66px)/1 var(--display);letter-spacing:-.022em;color:var(--sand)}
.mys-sub{max-width:38ch;font-size:17px;line-height:1.5;color:var(--on-dark);text-wrap:balance}
.mys-acts{display:flex;flex-wrap:wrap;justify-content:center;gap:12px;width:100%;max-width:560px;margin-top:6px}
.mys-acts .btn{flex:1 1 100%}
.mys .btn-line{color:var(--sand);box-shadow:inset 0 0 0 1px var(--sand)}
/* the way back to the story (2026-10-05): its own centred row under the two buttons at every width, so
   neither of them gives up any of its box. .tlink's own teal would vanish on this teal, so it is the sand
   the rest of the section's quiet type uses (10:1 on the teal) */
.mys-acts .tlink{flex:1 1 100%;justify-content:center;color:var(--sand)}
/* the plates go on as the bar comes up, collar out */
.motion .mys-bar:not(.in) .bb-l .bb-p{opacity:0;transform:translate3d(calc((var(--n,7) + var(--off)) * -1 * var(--st)),0,0)}
.motion .mys-bar:not(.in) .bb-r .bb-p{opacity:0;transform:translate3d(calc((var(--n,7) + var(--off)) * var(--st)),0,0)}
.motion .mys-bar .bb-p{transition-duration:420ms,240ms;transition-delay:calc(260ms + var(--o) * 110ms)}
@media (min-width:768px){.mys-acts .btn{flex:1 1 0}}

/* ---------- Headline treatments: two-tone and extruded, for a few moments only ----------
   (a) .hl-k: one word in the button blue inside a teal headline ("plan", "free"). .hl-2: a headline in
   two lines of two sizes, a small teal lead over its keyword set large in the blue ("What are we /
   MAXIMIZING?"). On teal (.hl-dk) the lead is the on-dark grey and the keyword chalk.
   (b) .hl-3d: a solid extrusion for the hero line and the payoff. The face is blue on chalk (sand on
   teal); seven hairline steps of text-shadow run down and right, the first a lit chamfer a shade
   lighter than the face, then the side, darkening toward the back (deep teal on chalk; on teal, where
   teal would vanish, the blue into indigo), and a soft cast shadow under it all. Everything is in em,
   so the depth scales with the type (about 5px at 390, 9px at 1440); text-shadow only, so it costs
   no layout and reads with no script and no motion. Contrast of the faces: blue on chalk 7.3:1 (5.1:1
   on the field's warmest glow), sand on teal 10:1, chalk on teal 12.9:1; the leads, teal on chalk
   12.9:1 and on-dark on teal 9.3:1. */
.hl-k{color:var(--accent)}
.hl-2 .hl-lead{display:block;margin-bottom:.1em;font-size:.5em;font-weight:700;line-height:1;letter-spacing:.04em;color:var(--teal)}
.hl-2 .hl-k{display:block;font-size:min(1.3em,14.5vw);line-height:.9}
.hl-2.hl-dk .hl-lead{color:var(--on-dark)}
.hl-2.hl-dk .hl-k{color:var(--chalk)}
.hl-3d{--u:.012em;--h:#C9703F;--s1:#0A3A48;--s2:#042A35;--s3:#001E27;--cast:rgba(0,20,27,.26);color:var(--accent);letter-spacing:.012em;
  text-shadow:var(--u) var(--u) 0 var(--h),
    calc(2 * var(--u)) calc(2 * var(--u)) 0 var(--s1),calc(3 * var(--u)) calc(3 * var(--u)) 0 var(--s1),
    calc(4 * var(--u)) calc(4 * var(--u)) 0 var(--s2),calc(5 * var(--u)) calc(5 * var(--u)) 0 var(--s2),
    calc(6 * var(--u)) calc(6 * var(--u)) 0 var(--s3),calc(7 * var(--u)) calc(7 * var(--u)) 0 var(--s3),
    calc(7 * var(--u) + .03em) calc(7 * var(--u) + .07em) .1em var(--cast)}
.hl-3d.hl-dk{--h:#FFF7EF;--s1:#A9471F;--s2:#8C3A19;--s3:#712F14;--cast:rgba(0,0,0,.42);color:var(--sand)}
/* where they are used: the hero's last line, a step larger; the payoff's "Build yours.", larger still */
.hero h1 .hl-3d{font-size:1.1em;margin-top:.02em;padding-bottom:.08em}
.mys h2.hl-2{font-size:clamp(40px,12vw,80px)}
.mys-build.hl-3d{font-size:clamp(50px,15vw,104px);margin-top:12px}
/* the rack's three-step guide, under its heading: one line a step on a phone, each numbered on a
   small plate. The step the visitor is on is the blue plate and the dark line; the steps behind them
   are teal plates; the ones ahead are open rings. Colour only, so there is nothing to move under
   reduced motion. Text is --text on chalk, 7.1:1, and ink for the step they are on. */
.rk-guide{list-style:none;margin:6px 0 0;padding:0;display:grid;gap:7px;counter-reset:none}
.rk-guide li{display:flex;align-items:center;gap:10px;min-height:22px;font:500 15px/1.3 var(--sans);color:var(--text)}
.rk-guide li.is-now{color:var(--ink);font-weight:650}
.rg-n{position:relative;flex:none;display:grid;place-items:center;width:22px;height:22px;border-radius:50%;
  font:800 11px/1 var(--sans);color:var(--teal);box-shadow:inset 0 0 0 1.5px rgba(0,46,59,.62);
  transition:background-color 200ms,color 200ms,box-shadow 200ms}
.rg-n::after{content:"";position:absolute;inset:3px;border-radius:50%;border:1px solid transparent}
.is-done .rg-n{background:var(--teal);color:var(--chalk);box-shadow:none}
.is-now .rg-n{background:var(--accent);color:#fff;box-shadow:0 0 0 3px rgba(169,71,31,.18)}
.is-done .rg-n::after,.is-now .rg-n::after{border-color:rgba(255,255,255,.28)}
.rk-guide a{color:var(--teal);font-weight:650;text-decoration:underline;text-decoration-thickness:1.5px;text-underline-offset:3px}
.rk-guide .is-now a{color:var(--accent-ink)}
@media (prefers-reduced-motion:reduce){.rg-n{transition:none}}
html:not(.js) .rk-guide{display:none}
.rk-all{margin:8px 0 0}   /* without script every panel stands open and nothing loads: no steps to follow */
@media (max-width:359px){.rk-guide li{font-size:14px;align-items:flex-start}.rk-guide .rg-t{padding-top:2px}}
@media (min-width:768px){.rk-guide{margin-top:10px;gap:8px}.rk-guide li{font-size:16px}}

/* the pinned strip only counts in the anchors' offset once there is a stack to show (html.has-stack,
   set by the script); without one it is away outside the story, and the story pads for it itself.
   .snap: when it comes up its contents are set at once, so it never arrives mid-fade. */
.t-bar{scroll-padding-top:calc(var(--mh) + var(--srch,0px))}   /* --srch: the phone search row, when open (2026-10-24) */
.t-bar.has-stack{scroll-padding-top:calc(var(--mh) + var(--pin) + var(--srch,0px))}
.lbpin.snap .lbpin-bars .bb,.lbpin.snap .lbc-set{transition:none}

/* the product card: "Load this plate" beside "Buy on Amway", and "On your bar" once it is on */
.pcard-acts{display:flex;flex-wrap:wrap;gap:10px;width:100%}
.pcard-acts .btn{flex:1 1 100%}
.pcard-load[aria-disabled="true"]{color:var(--teal);box-shadow:inset 0 0 0 1px rgba(0,46,59,.35);cursor:default}
.pcard-load[aria-disabled="true"]::before{content:"";width:14px;height:8px;margin:-4px 2px 0 0;border:solid currentColor;border-width:0 0 2px 2px;transform:rotate(-45deg)}
.pcard-load[aria-disabled="true"]:active{opacity:1}
@media (min-width:768px){.pcard-acts .btn{flex:1 1 auto}}
/* every product tile opens the card too; the buy button has a row to itself, the other one or two
   ("Ask for a free sample", "Load this plate") share the next from 768 */
.pcard-acts .pcard-buy{flex-basis:100%}
.card-link.is-out img{opacity:0}   /* its card is open and its picture is in it */

/* under "Build yours.": the visitor's stack, drawn like his a size down, with its key and a way back
   to the rack; or, with none yet, one line inviting them to load one */
.mys-you{display:grid;justify-items:center;gap:10px;width:100%;max-width:640px}
html:not(.js) .mys-you{display:none}
.mys-has{display:grid;justify-items:center;gap:10px;width:100%}
.mys-has[hidden],.mys-none[hidden]{display:none}
.mys-cap{display:flex;flex-wrap:wrap;align-items:baseline;justify-content:center;gap:4px 14px;margin:0;
  font:600 12px/1.3 var(--sans);letter-spacing:.16em;text-transform:uppercase;color:var(--sand)}
.mys-edit{display:inline-flex;align-items:center;min-height:44px;margin:-12px 0;color:var(--chalk);letter-spacing:.08em;
  text-decoration:underline;text-decoration-thickness:1.5px;text-underline-offset:4px}
.mys-ybar{width:100%;max-width:560px}
.mys-ybar .bb{font-size:clamp(3px,calc(100cqi / 56),10px)}
.mys-none{max-width:34ch;margin:0;font:500 17px/1.5 var(--sans);color:var(--on-dark);text-wrap:balance}
.mys-none a{color:var(--chalk);font-weight:650;text-decoration:underline;text-decoration-thickness:1.5px;text-underline-offset:4px}
.mys :focus-visible{outline-color:var(--sand)}
/* ===================================================================================
   The field: one ground for the whole site, "warm chalk" (Peter's pick, B of the three mockups
   on raw24/bg-mockups). Kept as one block, after everything it overrides, so it merges in one piece.

   One fixed layer (.field, straight after <body> on every page) carries it all: the chalk base, a
   still slanted band of warm light low down (the story's own 14-degree sweep, laid across the
   page), two soft glows (sand high left, pale teal right) that drift over ~50s, and a fine grain
   over them. The glows are pre-blurred radial gradients, each on its own layer, with no filter;
   only their transform animates, so the drift costs no layout and no paint, and reduced motion
   stops it. Every band that painted its own ground (the hero's copy, the sample, the trending
   band, the story's grounds, the calculator's sand) goes transparent, so the one field runs all
   the way down. Cards and panels keep a surface where reading needs one. The only break is the
   footer, whose horizon is black-native artwork: it keeps its black, and the field darkens into
   it over its first 120px, so the page ends at nightfall rather than at a ruled line.
   =================================================================================== */
:root{
  /* palette B, warm sand (Peter, 2026-10-29: the old chalk ground #F4F2EC read "a touch too pale ... or too
     bland"). The ground went a step warmer and deeper, the glows stronger, and cards (--chalk) stay a step
     LIGHTER than it, so a card now lifts off the page instead of sitting flush with it. */
  --fb:#EEE3D4;                                   /* the ground: warm sand */
  --fg1:222,183,140;--fg1a:.55;                   /* high glow: toasted sand */
  --fg2:140,192,192;--fg2a:.42;                   /* second glow: sea teal */
  --lo:226,200,174;--loa:.38;                     /* the low slanted band: sand, so the low light is warm where it meets the teal glow */
  --grain:.07;                                    /* registers on a phone; past .08 it greys the chalk */
  --hollow-hi:#F4EBDF;--hollow:#E9DCCB;           /* inside a compartment: a step lighter than the sand glow, so it stays a hollow */
}
.field{position:fixed;left:0;top:0;z-index:-1;display:block;width:100%;height:100vh;overflow:hidden;pointer-events:none;contain:strict;
  background:linear-gradient(166deg,rgba(var(--lo),0) 52%,rgba(var(--lo),var(--loa)) 74%,rgba(var(--lo),0) 96%),var(--fb)}
@supports (height:100lvh){.field{height:100lvh}}
.fg{position:absolute;display:block;width:120vmax;height:120vmax;will-change:transform;
  background:radial-gradient(closest-side,rgba(var(--c),var(--a)) 0,rgba(var(--c),calc(var(--a) * .55)) 38%,rgba(var(--c),calc(var(--a) * .18)) 70%,rgba(var(--c),0) 100%)}
.fg1{--c:var(--fg1);--a:var(--fg1a);left:-58vmax;top:-66vmax;animation:fg-drift1 52s ease-in-out infinite alternate}
.fg2{--c:var(--fg2);--a:var(--fg2a);right:-70vmax;top:8vh;width:110vmax;height:110vmax;animation:fg-drift2 44s ease-in-out infinite alternate}
@keyframes fg-drift1{from{transform:translate3d(0,0,0) scale(1)}50%{transform:translate3d(22vw,6vh,0) scale(1.08)}to{transform:translate3d(38vw,-2vh,0) scale(.96)}}
@keyframes fg-drift2{from{transform:translate3d(0,0,0) scale(1)}50%{transform:translate3d(-18vw,14vh,0) scale(1.1)}to{transform:translate3d(-6vw,30vh,0) scale(1)}}
/* the grain: the fractal noise the page used as its paper overlay, moved under the content and over
   the glows, so it breaks up their banding while cards and type stay clean. The raw noise is half
   transparent and low in contrast, which at .07 barely showed on a phone; the tile is made opaque,
   centred light (about 74% grey) and stretched 2x, so at .07 the grain is twice as strong as the raw
   tile's while it darkens the chalk less (measured: 1.3 levels on average, against 1.9) */
.field::after{content:"";position:absolute;inset:0;opacity:var(--grain);
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3CfeComponentTransfer%3E%3CfeFuncR type='linear' slope='2' intercept='-.26'/%3E%3CfeFuncG type='linear' slope='2' intercept='-.26'/%3E%3CfeFuncB type='linear' slope='2' intercept='-.26'/%3E%3CfeFuncA type='linear' slope='0' intercept='1'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size:180px 180px}
@media (prefers-reduced-motion:reduce){.fg{animation:none}}
/* the field's grain replaces the old paper overlay; body lets the field through. html keeps its
   teal-over-black canvas for the overscroll past the teal mast and the black footer. */
body::before{display:none}
body{background:transparent}

/* the hero: its copy stands on the field in the page's dark type; the square film is untouched */
.hero{background:transparent;color:var(--text)}
.hero .label,.hero .sub{color:var(--text)}
.hero h1{color:var(--teal)}
.hero .tlink{color:var(--teal)}

/* the bands that painted their own ground */
.sample-sec,.macros-sec,.cat-macros,.story{background:transparent}
.c-card.nc,.c-embed.nc{background:#FAF9F5}   /* the note: a sheet a shade whiter than the chalk it lies on */

/* #trending is a plain band: on the page's own field, in dark type. The .no-pour name is the
   film that used to be able to run behind it; the band is always built with it now. */
.podium-sec.no-pour{background:transparent;color:var(--text)}
.no-pour h2{color:var(--teal)}
.no-pour :focus-visible{outline-color:var(--teal)}
.no-pour .pod .card-link,.no-pour .pod .p-name{color:var(--ink)}
.no-pour .pod-rank,.no-pour .pod-count{color:var(--teal)}
.no-pour .pod .p-tag,.no-pour .pod .p-desc,.no-pour .pod .p-why{color:var(--text)}
.no-pour .pod .shot::after{background:radial-gradient(closest-side,rgba(30,38,47,.3),rgba(30,38,47,0))}
/* ...and it is a compact band, not a podium: the three are cards like the shop's (the same glow
   behind the pack and shadow under it), each rank on its pack's corner. It is one row of three at
   every width — Peter, 2026-09-28: "I wonder if it's better if we show all three in one quick
   snapshot. Like smaller on the same page." It used to be a swipe row below 560px, which was the
   one thing on the page you had to scrub sideways. Nothing scrolls horizontally now: below 560px
   the same three columns simply run small — square packs, the rank half the size, the type a
   couple of steps down, and the descriptor dropped (the name, the shelf and the count carry the
   card, and the whole line of it is 88px wide at 320). The descriptor and the full sizes come
   back at 560px, where there is room for them. */
/* no padding of its own on top: the band before it (the calculator) already ends in a full --sec
   of ground, and the two together stood ~150px of empty field over the heading on a phone */
.podium-sec.no-pour{margin-top:0;padding-top:0}
.no-pour .sec-head{padding-top:0;margin-bottom:18px}
.no-pour .podium{grid-auto-flow:row;grid-template-columns:repeat(3,minmax(0,1fr));
  gap:clamp(8px,2.6vw,16px);margin:0;padding:0;align-items:start}
.no-pour .pod{perspective:none;min-width:0}
.no-pour .pod .shot{margin-top:0;aspect-ratio:1;padding:0 4% 4%}
.no-pour .pod .shot::before{content:"";position:absolute;left:4%;right:4%;top:2%;bottom:6%;z-index:-2;border-radius:50%;
  background:radial-gradient(58% 52% at 50% 46%,rgba(255,255,255,.72),rgba(255,255,255,0) 78%)}
.no-pour .pod .shot::after{left:22%;right:22%;bottom:3%;height:7%}
.no-pour .pod-rank{position:absolute;top:0;left:0;z-index:2;margin:0;font:700 18px/1 var(--display)}
/* two lines' room for the shelf name, so the three product names start on the same line however
   the shelf names above them wrap (one of the three is usually "Daily Foundations") */
.no-pour .pod .p-tag{margin-top:6px;font-size:11px;line-height:1.25;min-height:2.5em}
.no-pour .pod .p-name{margin-top:2px;font-size:13px;line-height:1.25;text-wrap:balance}
.no-pour .pod .p-desc{display:none}
/* the why stays at every width: on a phone it is the card's one line under the name, in place of
   the descriptor, at the shelf tag's size (it wraps to three or four short lines in an 88px column) */
.no-pour .pod .p-why{margin-top:4px;font-size:11.5px;line-height:1.3;text-wrap:pretty}
.no-pour .pod-count{margin-top:4px;font-size:11px}
.no-pour .pod-num{font-size:15px;margin-right:3px}
@media (min-width:560px){
  .no-pour .podium{gap:24px}
  .no-pour .pod .shot{aspect-ratio:6/5;padding:0 6% 4%}
  .no-pour .pod-rank{font-size:28px}
  .no-pour .pod .p-tag{margin-top:10px;font-size:14px;line-height:1.3;min-height:0}
  .no-pour .pod .p-name{margin-top:4px;font-size:16px;line-height:1.3}
  .no-pour .pod .p-desc{display:block}
  .no-pour .pod .p-why{margin-top:6px;font-size:14px;line-height:1.4;color:var(--ink)}
  .no-pour .pod-count{margin-top:6px;font-size:14px}
  .no-pour .pod-num{font-size:22px;margin-right:4px}
}
@media (min-width:768px){
  .no-pour .podium{gap:40px}
  .no-pour .pod .shot{aspect-ratio:4/3}
  .no-pour .pod-rank{font-size:34px}
}

/* the stack case and the product card: the sand inside a compartment sat within a hair of the sand
   glow over chalk, so it goes a step lighter and takes an inset shadow on every side, and reads as a
   hollow whatever the field behind the case is doing */
.bay{background:linear-gradient(var(--hollow-hi),var(--hollow) 80%);
  box-shadow:inset 0 10px 16px -9px rgba(0,20,27,.55),inset 0 -8px 12px -10px rgba(0,20,27,.22),inset 0 0 0 1px rgba(0,20,27,.16)}
/* The card's art panel takes the product's own shelf colour, set as --tint by _script.html from the
   data-tint the build puts on every pack and tile (2026-10-09). The pack is a cut-out with its own drop
   shadow, so a field of colour behind it reads as a shot rather than as a sticker on paper — which is
   what Peter liked on aspirehealth.pro. The tint is mixed well back toward the hollow so a near-black
   plate like Protein gives a cool grey rather than a hole, and the fallback is the hollow itself, so a
   product on no shelf looks exactly as it always did. Nothing is written on this panel, so there is no
   contrast to hold here — only the pack to light. */
.pcard-art{background:linear-gradient(color-mix(in srgb,var(--tint,var(--hollow)) 16%,var(--hollow-hi)),
  color-mix(in srgb,var(--tint,var(--hollow)) 30%,var(--hollow)))}

/* cards and panels: a translucent surface with a hairline, so forms still read as forms */
.c-card,.c-embed{background:rgba(255,255,255,.5);backdrop-filter:none;-webkit-backdrop-filter:none;
  box-shadow:inset 0 0 0 1px rgba(30,38,47,.12),0 40px 60px -40px rgba(0,30,39,.45)}
.mc-card{background:rgba(250,249,245,.82)}   /* its numbers stay on a near-solid ground */

/* the footer: nightfall. Its first 120px carry the field down through the teal's own dark into
   black, and the horizon and the type start below that, on black as before. The fade ends on the
   horizon image's own darkest blue, so the picture starts without a seam. */
.foot{--dusk:120px;padding-top:calc(var(--dusk) + var(--horizon) + 36px);
  background:linear-gradient(rgba(0,46,59,0) 0,rgba(0,46,59,.12) 24px,rgba(0,42,54,.45) 54px,rgba(0,26,34,.8) 86px,rgb(6,11,14) var(--dusk),#000 calc(var(--dusk) + 1px))}
.foot-glow{top:var(--dusk)}
/* THE SHOP (2026-10-21, a Fable critic): its last section on show is "That's my stack", dark teal, and the
   nightfall above started transparent, so the light field showed through as a ~110px pale stripe between
   two dark bands. While the catalogue is hidden the footer starts from that band's own teal instead, as
   the homepage's does from its dusk. Once "Browse all" opens the catalogue, the chalk grid sits between
   them again and the ordinary fade comes back. */
html.js body:has(.mys):has(#results[hidden]) .foot{background:linear-gradient(rgb(3,40,51) 0,rgb(6,11,14) var(--dusk),#000 calc(var(--dusk) + 1px))}
/* the proof's Before / After heads were --text at .62 on chalk; over the field's glow that fell to
   about 2.5:1, so they take the full --text (5.3:1 at the field's darkest) */
.c-cols span{opacity:1}

/* ===================================================================================
   HIS AND HERS: the proof after #story, his wife's story on Women's Health, and the DEXA cards
   (build_homepage.py: HER_NAME, PETER_TRANSFORM, HER_DEXA, SHELF_EXTRA, SHELF_PORTRAIT). Her photos
   are the hand-placed files in assets/her/, cut to one spec like Peter's, so the same 50% line
   carries each stack's Before / After heads.
   =================================================================================== */
.pf-title{margin:0 0 26px;font:600 clamp(34px,9vw,56px)/1 var(--display);letter-spacing:-.02em;
  color:var(--teal);text-align:center;text-wrap:balance}
.pf-k{color:var(--accent)}
.pf-duo{display:grid;gap:44px;max-width:680px;margin:0 auto}
.pf-who{display:flex;flex-wrap:wrap;align-items:baseline;justify-content:space-between;gap:4px 12px;margin:0}
.pf-name{font:600 24px/1.1 var(--display);letter-spacing:-.012em;color:var(--teal)}
.pf-when{font:600 13px/1.2 var(--sans);letter-spacing:.06em;color:var(--text);font-variant-numeric:tabular-nums}
.dx-duo{display:grid;gap:20px;max-width:680px;margin:52px auto 0}   /* the gap the photos' captions keep from the DEXA cards */
/* wide: his three pairs and her two side by side, hers a little narrower so the columns end together
   (three 3:2 pairs against two 0.78:1 pairs), and the two cards side by side under them */
@media (min-width:1000px){
  .pf-duo{max-width:none;grid-template-columns:minmax(0,1fr) minmax(0,.78fr);align-items:start;gap:48px}
  .st-proof .pf-duo .c-proof{max-width:none;margin:0}
  .dx-duo{max-width:none;grid-template-columns:repeat(2,minmax(0,1fr));align-items:start}
}

/* the DEXA card: numbers first, the two trends under them, the source last. The trends are zero-based
   and time-true (dexa_chart); text in them is the page's text, never the line's colour. */
.dx-card{container-type:inline-size;display:grid;gap:16px;min-width:0;padding:22px 18px 20px;background:#FAF9F5;
  box-shadow:inset 0 0 0 1px rgba(30,38,47,.12),0 30px 50px -36px rgba(0,30,39,.45)}
.dx-head{display:grid;gap:6px}
.dx-t{margin:0;font:600 27px/1.08 var(--display);letter-spacing:-.015em;color:var(--teal)}
.dx-span{margin:0;font:600 13px/1.3 var(--sans);letter-spacing:.04em;color:var(--text);font-variant-numeric:tabular-nums}
.dx-nums{display:grid;margin:0}
.dx-n{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:baseline;gap:2px 12px;padding:10px 0;border-top:1px solid var(--line)}
.dx-n dt{font:600 12px/1.2 var(--sans);letter-spacing:.12em;text-transform:uppercase;color:var(--text)}
.dx-v{grid-column:2;grid-row:1 / span 2;align-self:center;margin:0;font:700 clamp(16px,5vw,20px)/1.1 var(--sans);color:var(--ink);
  font-variant-numeric:tabular-nums;white-space:nowrap}
.dx-d{grid-column:1;margin:0;font-size:14px;color:var(--text);font-variant-numeric:tabular-nums}
@container (min-width:520px){
  .dx-nums{grid-template-columns:repeat(3,minmax(0,1fr));column-gap:16px}
  /* Peter's card carries four rows — weight and body fat, then the fat and lean worked out from
     them — so it goes two by two rather than three across with one orphan underneath */
  .dx-nums.dx-four{grid-template-columns:repeat(2,minmax(0,1fr))}
  .dx-n{grid-template-columns:minmax(0,1fr);align-content:start}
  .dx-v,.dx-d{grid-column:auto;grid-row:auto}
  .dx-v{align-self:start;font-size:19px}
}
.dx-gapnote{margin:0;padding:10px 12px;font-size:14px;line-height:1.45;color:var(--text);background:rgba(65,83,101,.07)}
.dx-charts{display:grid;gap:16px 22px;grid-template-columns:repeat(auto-fit,minmax(min(100%,240px),1fr))}
.dx-chart{margin:0;min-width:0}
.dx-ct{display:flex;align-items:center;gap:8px;margin-bottom:6px;font:600 12px/1.2 var(--sans);letter-spacing:.1em;
  text-transform:uppercase;color:var(--text)}
.dx-ct i{flex:none;width:16px;height:2px;background:var(--c)}
.dx-chart svg{display:block;width:100%;max-width:300px;height:auto;overflow:visible}
.dx-grid{stroke:rgba(30,38,47,.14);stroke-width:1}
.dx-base,.dx-tick{stroke:rgba(30,38,47,.45);stroke-width:1}
.dx-yl,.dx-xl{font:500 13px var(--sans);fill:var(--text)}
.dx-vl{font:700 14px var(--sans);fill:var(--ink);paint-order:stroke;stroke:#FAF9F5;stroke-width:4px;stroke-linejoin:round}
.dx-line{fill:none;stroke-width:2;stroke-linejoin:round;stroke-linecap:round}
.dx-pt{stroke:#FAF9F5;stroke-width:2}
.dx-gap{fill:rgba(65,83,101,.08)}
.dx-gapl{font:600 13px var(--sans);letter-spacing:.04em;fill:var(--text)}
.dx-src{display:grid;gap:4px;padding-top:12px;border-top:1px solid var(--line)}
.dx-src p{margin:0;font-size:13px;line-height:1.45;color:var(--text)}
/* on a shelf page the card stands alone, as wide as a reading column */
.dx-one .dx-card{max-width:720px}
.dx-sec{padding-bottom:0}

/* Women's Health: her story, her two pairs, then her card, before the shelf's products */
.her-sec{padding-bottom:0}
.her-in{display:grid;gap:40px;align-items:start}
.her-text{display:grid;gap:14px;justify-items:start}
.her-text h2{font-size:clamp(42px,12vw,72px)}
.her-text p:not(.label){max-width:46ch;margin:0;font-size:16px;line-height:1.55;color:var(--text)}
.her-text .her-lead{font-size:18px;color:var(--ink)}
.her-h{margin-top:10px}
.her-text .c-list{margin:0}
.her-text .her-fine{font-size:14px}
.her-in .pf-hers{max-width:520px}
.her-in .dx-card{max-width:720px}
/* wide: the story and her card down the left, her two pairs down the right */
@media (min-width:900px){
  .her-in{grid-template-columns:minmax(0,1fr) minmax(0,.9fr);grid-template-rows:auto 1fr;gap:48px 56px}
  .her-in .her-text{grid-area:1 / 1}   /* the shelf's own three-cell layout; about.html lays its two out itself */
  .her-in .pf-hers{grid-area:1 / 2 / 3 / 3}
  .her-in .dx-card{grid-area:2 / 1;align-self:start}
}

/* her portrait with their daughter is Women's Health's hero: a real picture, shown whole, above the
   name on a phone and beside it on wider screens (a banner's cover crop would cut into their faces) */
.cat-hero-photo{min-height:0;align-items:end}
.cat-pic{padding-top:calc(var(--mast) + 20px)}
.cat-portrait{margin:0;width:100%;max-width:min(440px,56svh)}
.cat-portrait img{display:block;width:100%;height:auto;box-shadow:0 34px 60px -34px rgba(0,0,0,.7)}
.cat-hero-photo .cat-hero-in{padding-block:26px 40px}
@media (min-width:760px){
  .cat-hero-photo{min-height:64vh}
  .cat-hero-photo>.wrap{grid-area:1 / 1}
  .cat-pic{display:grid;justify-items:end;align-self:start;padding-block:calc(var(--mast) + 36px) 56px}
  .cat-portrait{width:min(38vw,440px)}
  .cat-hero-photo .cat-hero-in{align-self:end;padding-block:180px 56px;padding-right:calc(var(--pad) + min(38vw,440px) + 40px)}
}

/* ---- about.html --------------------------------------------------------------------------------
   Its own page off the menu: who we are, then what changed (the proof wall), then the numbers
   (the DEXA cards), then the way on. Everything here is a variation on a pattern the site already
   has — the shelf hero, .her-text, .pf-duo, .dx-duo, .split — so nothing new is invented for it. */
/* the hero carries two portraits, his and hers, where a shelf's carries one */
.ab-pics{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;width:100%}
.ab-pics .cat-portrait{width:100%;max-width:none}
.ab-hero .cat-hero-in{padding-block:26px 40px}
/* who we are: one title over the two of them, then his words beside hers, each under its name, in
   the block the Women's Health shelf uses (her_text, peter_text: the names are h3, "What changed" h4) */
.ab-who .pf-title{margin-bottom:clamp(36px,5vw,56px)}
.ab-two{display:grid;gap:52px;align-items:start}
.ab-two .her-text>h3{font:600 clamp(29px,7.4vw,44px)/1.02 var(--display);letter-spacing:-.02em;
  color:var(--teal)}
.ab-two .her-h{margin:10px 0 0;font:600 17px/1.3 var(--sans);color:var(--ink)}
/* the numbers, under the photos rather than after a caption, so .dx-duo's own top gap is too much */
.ab-nums{padding-bottom:var(--sec)}
.ab-nums .dx-duo{margin-top:26px}
/* the way on: centred, like the section titles above it, so the page's last screen is one whole
   block rather than a left column beside an empty one; the numbers' own foot is the gap above it */
.ab-next{padding-top:0}
.ab-next .split-text{justify-items:center;text-align:center}
.ab-next .split-text p{text-wrap:balance}
.ab-acts{display:flex;flex-wrap:wrap;justify-content:center;gap:12px;margin-top:6px}
@media (min-width:760px){
  /* the two portraits set the hero's height, and the title stands at their foot: the hero is
     their height plus its padding, not a 64vh box they float in */
  .ab-hero{--abw:min(54vw,780px);min-height:0}
  .ab-hero .cat-pic{align-self:center;padding-block:48px}
  .ab-pics{width:var(--abw);gap:18px}
  .ab-hero .cat-hero-in{padding-block:48px;padding-right:calc(var(--pad) + var(--abw) + 40px)}
}
@media (min-width:768px){.ab-next .split-text{grid-column:1 / -1}}
@media (min-width:900px){.ab-two{grid-template-columns:repeat(2,minmax(0,1fr));gap:56px}}
@media (min-width:1000px){
  /* the proof wall: each stack's caption at its foot, so his and hers sit on one line */
  .ab-proof .pf-duo{align-items:stretch}
  .ab-proof .c-proof{grid-template-rows:auto auto 1fr auto}
  .ab-proof .c-stack{align-content:start}
}
/* below 1220 a card in the pair is too narrow for its numbers to run across, and hers would stack its
   two trends, so the cards stand one above the other there, as they do on a tablet */
@media (min-width:1000px) and (max-width:1219px){.ab-nums .dx-duo{max-width:680px;grid-template-columns:minmax(0,1fr)}}
@media (min-width:1220px){
  /* the two DEXA cards as equals: one height, the heads on one line, and the sources on one line at
     the foot. His card has no trends, so its four numbers take that room as a list, one to a row,
     each figure set larger on the right; the figures themselves are peter_card()'s, unchanged. */
  .ab-nums .dx-duo{align-items:stretch}
  .ab-nums .dx-card{display:flex;flex-direction:column}
  .ab-nums .dx-src{margin-top:auto}
  .ab-nums .dx-nums.dx-four{flex:1;grid-template-columns:minmax(0,1fr);align-content:stretch}
  .ab-nums .dx-four .dx-n{grid-template-columns:minmax(0,1fr) auto;align-content:center}
  .ab-nums .dx-four .dx-v{grid-column:2;grid-row:1 / span 2;align-self:center;font-size:26px}
  .ab-nums .dx-four .dx-d{grid-column:1}
}

/* under the story's call, a quiet text link over to about.html, so the call stays the one button on
   the block. The story carries their before/afters itself now; what is only over there is the scans. */
.st-more{margin:0;line-height:1.75}
.st-more .tlink{display:inline;min-height:0;padding:12px 0}   /* inline padding: a 44px tap target that moves nothing (2026-10-29) */   /* inline, so a line that wraps takes its arrow with its last word */
.st-more .ic{margin-left:6px;vertical-align:-3px}
.st-nw{white-space:nowrap}   /* the arrow never stands alone on a line */

/* =====================================================================================================
   Two tabs (2026-10-03). Peter: "this just feels too busy. Maybe we split the tabs. 1 tab is for
   products, 1 tab is to bring people through the story and book a call." homepage.html is "Our
   approach" (the hero, the story, "Understand why", the calculator, the plan, the call) and shop.html
   is "Shop" (the curtain, the film hero, the rack, the sample, "That's my stack", the grid).
   Shop is the FIRST tab and the landing page (Peter, 2026-10-04: "Can we swap it so my shop appears
   first, and then the, our approach is actually the second tab?"); the curtain moved to it with that,
   so it still plays on arrival.
   ===================================================================================================== */

/* ---- the tab switch, in every page's masthead (_header.html). Under 1024 it is the masthead's second
   row: two halves of the width, 40px tall (--tabh), the current page lit sand with a sand foot. From 1024
   it stands in the bar between the wordmark and the nav as a two-part pill, the current half filled. */
/* THREE columns since the "Start here" tab (2026-10-09). It was 1fr 1fr, and the third tab simply
   wrapped onto a second row that the fixed --tabh had no room for. Below 420 the labels are stepped
   down a little so "Our approach" still fits its third of a 320px window on one line. */
.tabs{display:grid;grid-template-columns:repeat(3,1fr);height:var(--tabh);margin:0 calc(-1 * var(--pad));border-top:1px solid rgba(230,211,197,.16)}
.tab{display:flex;align-items:center;justify-content:center;min-width:0;font:600 12px/1 var(--sans);letter-spacing:.16em;text-transform:uppercase;
  color:rgba(230,211,197,.78);text-decoration:none;white-space:nowrap;overflow:hidden}
.tab[aria-current]{color:var(--sand);background:rgba(230,211,197,.07);box-shadow:inset 0 -3px 0 var(--sand)}
@media (max-width:479px){.tab{font-size:11px;letter-spacing:.08em}}
@media (max-width:359px){.tab{font-size:10px;letter-spacing:.04em}}
.tab:active{opacity:.7}
.tab:focus-visible{outline-offset:-4px}
@media (hover:hover){.tab:not([aria-current]):hover{color:var(--sand);text-decoration:underline;text-underline-offset:5px}}
@media (min-width:1024px){
  :root{--tabh:0px}
  .mast .wrap{grid-template-columns:minmax(auto,1fr) auto auto minmax(0,1fr) auto}
  .mast .wordmark{order:0}
  .mast .tabs{order:1;display:flex;height:auto;margin:0;border:0;box-shadow:inset 0 0 0 1px rgba(230,211,197,.4)}
  .nav-inline{order:2}
  .mast .search{order:3}
  .tab{min-height:40px;padding:0 16px}
  .tab[aria-current]{background:var(--sand);color:var(--teal);box-shadow:none}
  .mast .tab:focus-visible{outline-color:var(--sand);outline-offset:2px}
}
/* 1024-1279: the switch costs the bar ~220px, so the wordmark keeps the wave and lets its name go, as a
   phone's does (the name stays in the accessibility tree and the page title). It was 1024-1279 while the
   nav carried "Products" too; with that gone (2026-10-04) the name fitted from 1080 and showed from 1100.
   THE THIRD TAB (2026-10-09, "Start here") put it back where it was: the extra tab costs the pill about
   what "Products" cost the nav, and at 1100 "Book a free call" ran straight over the search field —
   measured, and visible in a screenshot. Hiding the name again through 1279 gives it back. Re-measure
   this pair of ranges if a tab is ever added, removed or renamed; the test is the gap between
   .nav-inline's right edge and #search's left. */
@media (min-width:1024px) and (max-width:1279px){
  .mast .wordmark .wm-name{position:absolute;width:1px;height:1px;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
  .tab{padding:0 12px;letter-spacing:.12em}
}

/* ---- Tab 1's hero (.hh): "Feel your best. Understand why." over a full-bleed photograph (HOME_BG in
   build_homepage.py) or, until one is chosen, a ground drawn from the palette (.hh-ph). The photograph
   is decoration and is cropped by object-fit: a wide crop on the desktop, a tall one on phones, each
   steered by its own object-position (HOME_BG_FOCUS -> --hh-pos, --hh-pos-m).
   READABILITY WITH ANY PHOTOGRAPH: the text never relies on the picture. .hh-bg::after lays a light
   tint over all of it (mood only), and the copy carries its own scrim (.hero-copy::before): rgba(0,24,32,.76)
   under every line, fading out above the copy on phones and to its right from 768. Over a pure-white
   picture the lowest is 6.4:1 (the sand "Understand why." at 768, where its end nears the fade), and
   otherwise chalk 9.0:1 and sand 6.9:1 at 320, 390, 1440 and 1920 (measured 2026-10-03 on the rendered
   page, a white test image in the slot, the text's own colour against the brightest pixel behind it);
   any darker picture only raises them. Over the palette ground the lowest is 10.5:1. */
.hero.hh{position:relative;isolation:isolate;overflow:hidden;display:grid;align-items:end;background:var(--teal);color:var(--chalk);
  min-height:min(calc(100svh - var(--mh)),640px)}
.hh-bg{position:absolute;inset:0;z-index:-2}
.hh-bg picture{display:contents}
.hh-bg img{display:block;width:100%;height:100%;object-fit:cover;object-position:var(--hh-pos-m,50% 50%)}
.hh-bg::after{content:"";position:absolute;inset:0;background:rgba(0,24,32,.04)}
.hh-ph{background:
  radial-gradient(60% 50% at 78% 22%,rgba(230,211,197,.62),rgba(226,200,174,.18) 55%,rgba(226,200,174,0) 75%),
  radial-gradient(45% 40% at 96% 92%,rgba(81,168,170,.42),rgba(81,168,170,0) 70%),
  linear-gradient(165deg,#0E5466 0%,#063D4D 45%,var(--teal) 75%,#001E28 100%)}
.hh-in{position:relative}
.hh .hero-copy{position:relative;z-index:1;gap:14px;padding-top:28px;padding-bottom:22px}
.hh .hero-copy::before{content:"";position:absolute;z-index:-1;left:calc(-1 * var(--pad));right:calc(-1 * var(--pad));top:-120px;bottom:0;
  background:linear-gradient(180deg,rgba(0,24,32,0) 0,rgba(0,24,32,.64) 104px,rgba(0,24,32,.68) 220px)}
.hh .label{display:block;color:var(--sand)}
.hh .sub{color:var(--chalk);opacity:.92;max-width:34ch}
.hh h1{color:var(--chalk);font-size:min(11.4vw,64px)}
.hh h1 .hh-k{color:var(--sand)}
.hh .tlink{color:var(--sand)}
.hh .hero-actions{margin-top:4px}
/* Peter at the hero's foot (Peter, 2026-10-03: "my photo should actually be more towards the bottom...
   lets the lake speak for itself more"): small, under a hairline, like a signature, so the photograph
   carries the top and the headline and its two links read first. On phones it runs on under the copy and
   carries the copy's scrim down to the hero's edge (::before, the same .68); from 768 the copy's own
   scrim already covers it, and it drops to the hero's bottom edge while the copy stays centred. */
.hh-me{position:relative;z-index:1;display:flex;align-items:center;gap:14px;padding:14px 0 18px;border-top:1px solid rgba(244,241,234,.2)}
.hh-me::before{content:"";position:absolute;z-index:-1;left:calc(-1 * var(--pad));right:calc(-1 * var(--pad));top:0;bottom:0;background:rgba(0,24,32,.68)}
.hh-me img{flex:none;display:block;width:60px;height:auto;aspect-ratio:4/5;border-radius:10px;object-fit:cover;box-shadow:0 0 0 2px var(--chalk),0 12px 22px -14px rgba(0,0,0,.6)}
.hh-me-line{max-width:30ch;font-size:15px;line-height:1.4;color:var(--chalk);text-wrap:balance}
@media (min-width:768px){
  .hero.hh{min-height:clamp(560px,calc(100vh - var(--mh)),760px);align-items:center}
  .hh-bg img{object-position:var(--hh-pos,50% 50%)}
  .hh-in{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));column-gap:24px}
  .hh .hero-copy{grid-column:1 / 8;padding-block:56px;gap:20px}
  .hh .hero-copy::before{left:-100vw;right:-360px;top:-100vh;bottom:-100vh;
    background:linear-gradient(90deg,rgba(0,24,32,.7) calc(100% - 420px),rgba(0,24,32,.34) calc(100% - 200px),rgba(0,24,32,0))}
  .hh h1{font-size:clamp(64px,7vw,100px)}
  .hh-in{align-self:stretch;grid-template-rows:1fr auto}
  .hh .hero-copy{align-self:center}
  .hh-me{grid-column:1 / 8;align-self:end;max-width:440px;padding:16px 0 28px}
  .hh-me::before{display:none}
  .hh-me img{width:68px}
}
@media (min-width:1024px){.hh .hero-copy,.hh-me{grid-column:1 / 7}}
/* The same block at the SHOP hero's foot (.sh-me, 2026-10-05): the front page never said whose shop
   it was, so Peter's photograph and his line sign it, as they sign Tab 1. Everything above borrows
   .hh-me, so the shape, the photograph's size and the line are one piece of CSS in both places; all
   .sh-me changes is what the colours have to be, because this hero stands on the page's chalk field
   in dark type (see "the hero" in the field block) where Tab 1's stands on a photograph: the hairline
   is the page's own --line, the words are ink, the photograph's ring is a teal hairline instead of a
   chalk one (chalk on chalk is nothing), and there is no scrim, since there is no picture to read
   over. One link beside it, in the hero's teal; it wraps to its own row when the line needs the width.
   Measured on the rendered pixels: the line 12.4:1, the link 12.0:1.
   It sits after .hero-copy in the markup, so it cannot move the film or the two ways on above it. */
.hh-me.sh-me{flex-wrap:wrap;border-top-color:var(--line)}
.hh-me.sh-me::before{display:none}
.sh-me img{box-shadow:0 0 0 1.5px rgba(0,46,59,.35),0 12px 22px -14px rgba(0,20,27,.45)}
/* the line gives before the photograph does, so the shape stays Tab 1's at every width: the
   photograph and the words always share the first row, and the link takes the row under them when
   the column is too narrow to hold it beside (every width up to 1279, as it happens) */
.sh-me .hh-me-line{flex:1 1 160px;min-width:0;color:var(--ink)}
.sh-me .sh-me-go{flex:0 1 auto;color:var(--teal)}
@media (min-width:768px){
  /* a grid item of .hero-in like the copy above it, in the copy's own columns, at the hero's foot;
     the film is absolutely positioned on the right from here, so nothing is beside it */
  .hero-shop .hero-in{grid-template-rows:1fr auto}   /* the copy keeps the slack and stays centred; his row is content-sized under it */
  .hero-shop .hero-copy{align-self:center}
  .hh-me.sh-me{grid-column:1 / 6;grid-row:2;align-self:end;max-width:560px;padding:16px 0 0}
  .sh-me .sh-me-go{margin-left:auto}
}
@media (min-width:1024px){.hh-me.sh-me{grid-column:1 / 6}}

/* ---- The fact row under each hero (.hfacts, 2026-10-08): three countable facts, Peter's own wording
   on each tab ("100 options · 10 goals · 1 free sample" on the Shop, "1 blood panel · 10 goals ·
   1 free call" on Our approach). It is a list, not a row of buttons: nothing in it is a link, because
   the hero already carries its two ways on and one ask per screen stands. Peter's middle dots are the
   separator, drawn by CSS between the cells rather than typed into the copy, so a screen reader meets
   three list items and not punctuation.
   It takes NO colour of its own: as the last row of .hero-copy it inherits whatever the hero it stands
   in sets -- the page's own --text on the Shop's chalk field, chalk inside Tab 1's scrim -- so each row
   suits its own ground and neither can drift from the copy above it. Quiet by size and weight next to
   the button: 14px, 500, the numbers tabular so the three cells sit on one rhythm.
   It wraps cell by cell, so at 320 it can take two lines rather than widen the page; each cell holds
   its own number and word together (white-space:nowrap), which is why a cell never breaks mid-fact. */
.hfacts{display:flex;flex-wrap:wrap;align-items:baseline;gap:2px 10px;margin:2px 0 0;padding:0;list-style:none;
  font:500 14px/1.5 var(--sans);font-variant-numeric:tabular-nums}
.hfacts li{display:flex;align-items:baseline;gap:10px;white-space:nowrap}
.hfacts li + li::before{content:"\00B7"}   /* Peter's middle dot, between the cells and nowhere else */
@media (min-width:768px){.hfacts{gap:4px 14px;font-size:15px}.hfacts li{gap:14px}}
/* below 480 the Shop's lead already moves under the two ways on (order:1 on .sub), so the row takes
   the step after it and stays the copy's last line at every width */
@media (max-width:480px){.hero-shop .hfacts{order:2}}

/* ---- "Understand why" (#why, why_section() in build_homepage.py): a lead, four pillars, who does what */
/* THE SECTION'S HEADER, on the morning lake (2026-10-08). Peter: "this feels too light. We should swap it for
   a darker photo or different option. Or we can skip it altogether and go straight into it."
   It was a picture strip with nothing written on it, above the copy: 420px, then clamp(220px,17vw,300px) after
   a critic called it dead space, of pale sky between the cream story above and the cream pillars below. Three
   ways out were tried -- cut it, swap the frame for the dusk one, or keep the frame and put the head ON it --
   and the third is what shipped, because it is the only one that turns the space into something. The morning
   shore stays (dawn in the hero, morning here, dusk behind the call is Peter's own idea and still reads), the
   band is framed on the water instead of the sky, and his argument now has a ground of its own instead of
   being the third thing on a cream page. It did NOT fix the two critics' other finding -- the h2 and the
   argument still read as two stacked headings -- but it contains it: the pair is now one title block over a
   picture, with the four pillars clearly below it, rather than two competing headings in the same column.
   Contrast is the scrim's job and never the picture's. The copy is chalk over a gradient that is deepest
   where the words are; the band keeps a solid dark floor, so a webp that never lands changes no measurement. */
.sec.why{padding-top:0}
.why-top{position:relative;isolation:isolate;overflow:hidden;overflow:clip;background:#0A1D28;color:var(--chalk);
  padding:clamp(40px,9vw,72px) 0 clamp(44px,9vw,72px);margin-bottom:clamp(36px,7vw,64px)}
.why-band{position:absolute;inset:0;z-index:-1;background:#0A1D28}
.why-band img{display:block;width:100%;height:100%;object-fit:cover;object-position:50% 72%}
/* the scrim. The morning frame runs to 255 in the sun and chalk on that is 1.1:1, so this is structural:
   .80 over the copy at the top, easing to .72 across the water and back to .84 at the foot. */
.why-band::after{content:"";position:absolute;inset:0;
  background:linear-gradient(180deg,rgba(5,14,22,.82) 0,rgba(5,14,22,.78) 48%,rgba(5,14,22,.72) 72%,rgba(5,14,22,.86) 100%)}
.why-top .why-head{margin-bottom:0}
.why-top .label{color:var(--sand)}
.why-top h2{color:var(--chalk)}
.why-top .hl-k{color:var(--sand)}        /* the copper accent is a black mark on this band */
.why-top .why-lead{color:var(--chalk)}
.why-top .why-lead + .why-lead{color:rgba(244,242,236,.92)}
.why-top .btn{box-shadow:0 0 0 1px rgba(230,211,197,.22)}
.why-top :focus-visible{outline-color:var(--sand)}
/* from 768 the frame is wide enough to show the far shore, so it is steered a little higher */
@media (min-width:768px){.why-band img{object-position:50% 76%}}
.why-head{display:grid;gap:12px;justify-items:start;margin-bottom:28px}
.why-head h2{font-size:40px}
.why-head h2 span{display:block}
.why-lead{max-width:44ch;font-size:17px;line-height:1.5;color:var(--ink)}
.why-lead + .why-lead{color:var(--text)}
/* Peter's argument (2026-10-06) leads the section and still has to stand out from the two explaining lines
   under it — but NOT in the display face. It was set in display type from 2026-10-06, which read correctly
   while ONE family did both jobs and differed only by weight, width and case. The moment Fraunces arrived
   (2026-10-10) it became a second heading: an h2 and an argument, same face, stacked, told apart only by
   size. Two critics had called that pair out on the old type and the new pairing made it plain, so Peter:
   "fix the two stacked headings on #why".
   IT IS A LEAD PARAGRAPH NOW — the body face, one clear step up in size and weight from the paragraphs it
   leads — so the section has ONE heading and one speaking voice beneath it. Do not put it back on
   var(--display); that is the bug, not the style. Its measure widened with the smaller type (22ch was set
   for 32px display and strands two or three words a line at 21px). On the band .why-top's own rule paints
   it chalk; the teal here is what it would take anywhere else. */
.why-arg{font:500 clamp(18.5px,4.6vw,21px)/1.45 var(--sans);letter-spacing:-.008em;
  color:var(--teal);max-width:38ch;margin-bottom:2px}
@media (min-width:768px){.why-arg{font-size:clamp(20px,1.5vw,22px);max-width:40ch}}
.why-list{list-style:none;margin:0;padding:0;display:grid;gap:12px}
/* content sits at the top of each card; the links follow their text rather than pinning to a foot that left
   90-150px of empty card above them at 1440 (2026-10-04) */
.why-card{display:grid;align-content:start;gap:8px;padding:22px 20px 14px;background:#FAF9F5;border:1px solid var(--line)}
.why-n{font:700 28px/1 var(--display);color:var(--accent)}
.why-t{font:600 19px/1.25 var(--sans);color:var(--ink)}
.why-card p:not(.why-n){font-size:15px;line-height:1.5}
.why-gos{display:flex;flex-wrap:wrap;column-gap:22px}
/* a link that wraps (1024: "See both our DEXA / scans") keeps its arrow on its last word: inline, not flex,
   with the word and the arrow in one unbreakable .why-end (why_section() in build_homepage.py) */
.why-go{display:inline-block;justify-self:start;padding-block:11px;font-size:15px;line-height:1.5;min-height:0;text-underline-offset:4px;text-wrap:balance}
.why-end{white-space:nowrap}
.why-go .ic{display:inline-block;margin-left:4px;vertical-align:-.2em}
.why-status{font-size:14px!important;color:var(--text)}
.why-status a{color:var(--teal);font-weight:600;text-decoration:underline;text-decoration-thickness:1.5px;text-underline-offset:3px}
.why-soon{display:inline-block;margin-left:8px;padding:1px 8px;border:1px dashed var(--teal);font:600 11px/1.5 var(--sans);letter-spacing:.12em;
  text-transform:uppercase;color:var(--teal);white-space:nowrap;vertical-align:1px}
.why-roles{margin-top:28px;max-width:62ch;padding-left:16px;border-left:3px solid var(--accent);font-size:16px;line-height:1.5;color:var(--ink)}
.why-fine{margin-top:12px;max-width:62ch;padding-left:19px;font-size:14px;line-height:1.5;color:var(--text)}
@media (min-width:768px){
  .why-head{margin-bottom:40px}
  .why-head h2{font-size:52px}
  .why-list{grid-template-columns:repeat(2,minmax(0,1fr));gap:16px}
  .why-card{padding:26px 24px 16px}
}
@media (min-width:1024px){.why-list{grid-template-columns:repeat(4,minmax(0,1fr))}}

/* ---- a provider button with no link yet (soon_button() in build_homepage.py): a button's shape, dashed,
   and nothing to tap. Not a link and not focusable, so it can never go nowhere. */
.soon{margin-top:4px}
.soon-tag{display:inline-flex;align-items:center;justify-content:center;min-height:54px;padding:0 28px;border:1px dashed var(--teal);
  color:var(--teal);font:600 16px/1.2 var(--sans)}

/* the plan follows the calculator on the homepage now (2026-10-03): the same hairline over its head
   that it had under the story */
.macros-sec + .how-sec{padding-top:0}
.macros-sec + .how-sec>.wrap{border-top:1px solid var(--line);padding-top:calc(var(--sec) * .5)}

/* the footer carries FIVE links in both copies now ("About us" joined the row on 2026-10-05, after the
   bloodwork route joined the plain site on 2026-10-03), and up to 1279 the column has no room for them:
   with four, "Book a free call" broke over two or three lines up to 1199, and the fifth needs 756px of
   row where 1200 offers 739. There the links take their own full-width row under the brand, each on one
   line. At 1440 the five measure 756 in a 792px column, so they stay on the brand's row -- re-measure
   this the next time a link is added or renamed. */
@media (min-width:768px) and (max-width:1279px){
  .foot-top .foot-brand{grid-column:1 / 13}
  /* a wrapping flex row, not a single grid row: at 768 the five measure 738px of a 688px column, and
     grid-auto-flow:column cannot break, so the last link ran 10px past the window's right edge and the
     page scrolled sideways. Flex lets it drop to a second line with every link still whole; from about
     900 the five fit on one line again. Wrapping instead of tightening the gaps also means a link that
     is renamed or added later finds its own room rather than pushing the row off the page. */
  .foot-links{grid-column:1 / 13;display:flex;flex-wrap:wrap;column-gap:36px;justify-content:flex-start;margin-top:8px}
  .foot-links a{white-space:nowrap}
}
/* phones: the plan's -40px foot was set for the rack's heading, which followed it until the split; the
   call follows it on the homepage now, and its label sat 4px under the hairline, so it takes the 40px back */
@media (max-width:767px){.how-sec + .consult{margin-top:40px}}

/* ===================================================================================
   THE GLASS, SITE-WIDE — PART 1: THE CALCULATOR'S BAND (2026-10-08)
   -----------------------------------------------------------------------------------
   Peter, 2026-10-08: "I think the glass should go site-wide."

   What glass actually is here, so the next person does not spread it where it does
   nothing: it is a TINTED PANEL OVER A PICTURE. The tint is the contrast floor and the
   blur is what makes the picture behind read as depth instead of noise. Over this
   site's own ground — .field, one fixed sheet of chalk with two soft glows and a grain
   — there is no detail to refract, so a blurred panel there is an invisible change with
   a drifting backdrop underneath, which is worse than no glass at all. GLASS GOES WHERE
   THERE IS A PICTURE. Everywhere else the page keeps its flat surfaces, on purpose.

   #consult got the first one because it stands on the lake at dusk. #macros is the pair
   Peter noticed: CLAUDE.md calls the two cards siblings (the booking card was built on
   the calculator's own machinery, step counter, pips, Back, Continue and all), and they
   had ended up a near-solid chalk sheet and a dark frosted panel side by side on the
   same page. So the calculator gets a picture of its own to stand on — tex-water, the
   brand teal, already in the repo and until now unused — and the same glass over it.

   THE BAND. The water is a CSS background on ::before, not an <img>: it costs no markup,
   it reaches the plus/ copy and the templates untouched, and a CSS background is fetched
   off the layout pass rather than blocking the first paint. #macros starts about 4,000px
   down the homepage, so it is never in the first screen anyway. url(assets/…) resolves
   against the STYLESHEET, which sits at the repo root, so plus/homepage.html's ../style.css
   finds the same one file (CLAUDE.md, "Absolute URLs").
   The band keeps a solid dark floor under the picture, so a webp that never lands leaves
   a dark teal band and every measurement below still holds.

   THE SCRIM is not decoration either. tex-water carries specular ripples up to 202/255,
   and chalk on one of those is 1.5:1. Over the scrim the brightest pixel in the frame
   lands near 48/255 and the band reads from about #06 to #30 — a dark teal that still
   visibly ripples, with every word on it measured (see the table in the commit).
   It is deepest where the copy is (the top on a phone, the left from 768) and lightest
   under the card, which carries its own tint: the dusk's logic exactly.
=================================================================================== */
.macros-sec{position:relative;isolation:isolate;background:#061C24;color:var(--chalk)}
.macros-sec::before{
  content:"";position:absolute;inset:0;z-index:-1;
  background-image:linear-gradient(180deg,rgba(3,16,22,.88) 0,rgba(3,16,22,.86) 30%,rgba(3,16,22,.58) 58%,rgba(3,16,22,.62) 100%),
                   url("assets/home/tex-water.webp");
  background-size:auto,cover;
  background-position:center,center 38%;
  background-repeat:no-repeat,no-repeat;
}
@media (min-width:768px){
  /* the copy is columns 1-6 and the card 7-12, so the deep end of the scrim goes left */
  .macros-sec::before{
    background-image:linear-gradient(96deg,rgba(3,16,22,.9) 0,rgba(3,16,22,.86) 44%,rgba(3,16,22,.62) 66%,rgba(3,16,22,.68) 100%),
                     url("assets/home/tex-water.webp");
  }
}
/* the band's copy, in the dusk's hand */
.macros-sec .split-text,.macros-sec .split-text h2{color:var(--chalk)}
.macros-sec .split-text .label{color:var(--sand)}
.macros-sec .split-text p:not(.label){opacity:.92}
.macros-sec :focus-visible{outline-color:var(--sand)}
/* the plan's hairline was a rule between two chalk sections; the band's own bottom edge
   is the rule now, and a 1px --line drawn on a colour change reads as a mistake */
.macros-sec + .how-sec>.wrap{border-top:0}

/* THE CARD. The same two things as #consult-form, in the same order and the same values:
   the teal tint first (the fallback, and the floor every figure below is measured on),
   the blur second and only inside @supports. What is NOT copied is the note card's hand —
   .mc-card is not .nc and never was: it keeps its own plain 1px rim and its soft drop, so
   the calculator still reads as the plain sheet and the booking card as the written note.
   Same material, same tint, different shape. That was always the intended difference. */
.macros-sec .mc-card{
  background:rgba(0,46,59,.72);
  color:var(--chalk);
  box-shadow:inset 0 0 0 1px rgba(230,211,197,.42),0 40px 60px -40px rgba(0,16,22,.85);
}
@supports ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .macros-sec .mc-card{
    -webkit-backdrop-filter:blur(24px) saturate(1.1);
            backdrop-filter:blur(24px) saturate(1.1);
  }
}
/* the step's furniture */
.macros-sec .mc-count{color:var(--sand)}
.macros-sec .mc-prog span{background:rgba(230,211,197,.26)}
.macros-sec .mc-prog span.is-on{background:var(--sand)}
.macros-sec .tlink{color:var(--sand)}
.macros-sec .mc-nojs{color:var(--chalk)}
/* the question and its help line */
.macros-sec .mc-q{color:var(--chalk)}
.macros-sec .mc-help,.macros-sec .mc-note{color:rgba(230,211,197,.92)}
/* THE OPTIONS. Outlined and empty until they are picked, then they invert — sand fill,
   teal lettering — for the reason the consult's pills invert: a teal pill on a teal panel
   has no shape. The lift, the rim and the shadow are untouched, so selection never rests
   on colour alone. */
.macros-sec .mc-opt span{border-color:rgba(230,211,197,.5);background:rgba(255,255,255,.07);color:var(--chalk)}
.macros-sec .mc-opt input:checked + span{background:var(--sand);border-color:var(--chalk);color:var(--teal)}
.macros-sec .mc-opt input:focus-visible + span{outline-color:var(--sand)}
@media (hover:hover){.macros-sec .mc-opt:hover span{border-color:var(--chalk)}}
/* the follow-up fieldset's rule and its legend */
.macros-sec .mc-sub{border-top-color:rgba(230,211,197,.3)}
.macros-sec .mc-sub legend{color:var(--chalk)}
/* THE BLANKS: age, weight, height. Chalk in a lit well on a sand rim, which is the dark
   side of the same gesture as ink in a white box on a hairline. */
.macros-sec .mc-field label{color:var(--chalk)}
.macros-sec .mc-field input{border-color:rgba(230,211,197,.5);background:rgba(255,255,255,.1);color:var(--chalk)}
.macros-sec .mc-field input::placeholder{color:rgba(230,211,197,.8)}
.macros-sec .mc-field input:focus{border-color:var(--sand);box-shadow:inset 0 0 0 1px var(--sand);background:rgba(255,255,255,.14)}
/* the error and the warning keep their rule and every word; the copper accent would be a black
   mark on the tint, so the rule is lit instead. Colour is never what carries them. */
.macros-sec .mc-err,.macros-sec .mc-warn{background:rgba(230,211,197,.1);box-shadow:inset 2px 0 0 var(--sand);color:var(--chalk)}
/* THE NUMBERS. The one part of this card that is read rather than filled in, and the
   reason the old comment here said an opaque sheet: a backdrop that changes underneath
   makes a contrast measurement a guess. The tint is what answers that — every figure
   below sits on rgba(0,46,59,.72) over a scrimmed band, not on the picture. */
.macros-sec .mc-res-t{color:var(--chalk)}
.macros-sec .mc-cals{border-top-color:rgba(230,211,197,.24)}
.macros-sec .mc-cals > div{border-bottom-color:rgba(230,211,197,.24)}
.macros-sec .mc-cals dt{color:rgba(230,211,197,.92)}
.macros-sec .mc-cals dd{color:var(--chalk)}
.macros-sec .mc-cals > div:last-child dd{color:var(--sand)}
.macros-sec .mc-macros li{background:rgba(230,211,197,.12)}
.macros-sec .mc-g{color:var(--sand)}
.macros-sec .mc-lab,.macros-sec .mc-kc{color:rgba(230,211,197,.92)}
/* the button is unchanged, for the reason it is unchanged on the booking card: the copper accent
   on the teal tint is the one warm-cold edge in the card. Only its rim is drawn. */
.macros-sec .mc-card .btn{box-shadow:0 0 0 1px rgba(230,211,197,.22)}

/* ===================================================================================
   THE GLASS, SITE-WIDE — PART 2: THE SHOP'S DARK BAND (2026-10-08)
   -----------------------------------------------------------------------------------
   #my-stack was the one band on Tab 1 with any depth and it had none: a flat sheet of
   --teal with a barbell drawn on it, about 2,200px of it at 1440. It is also the only
   place the Shop could carry the same material as the approach tab without touching the
   square film or the rack, so the water goes behind it. Same one file as #macros, so the
   Shop pays for one texture and the browser has it cached by the time a visitor crosses
   to the other tab (and the other way round).

   NO GLASS PANEL HERE, because there is no panel: the band's content is a barbell, five
   packs and a heading, all of which stand directly on the ground. So this is the ground
   half of the recipe only — a picture under a tint of Peter's own teal, deep enough that
   the band still reads as the brand's teal and every word on it keeps the contrast it
   had. Measured on the rendered pixels at 320/390/768/1024/1440, with backdrop-filter forced
   off as well: the band's palest type (--on-dark, the shelf names under his five packs) bottoms
   out at 6.74:1 over the brightest ripple any letter of it sits on, and nothing in the band is
   under that except the outlined button, which gets its own floor just below.
=================================================================================== */
.sec.dark.mys{position:relative;isolation:isolate;overflow:hidden;overflow:clip}
.sec.dark.mys::before{
  content:"";position:absolute;inset:0;z-index:-1;
  background-image:linear-gradient(rgba(0,38,49,.86),rgba(0,38,49,.8) 42%,rgba(0,38,49,.88)),
                   url("assets/home/tex-water.webp");
  background-size:auto,cover;
  background-position:center,center 42%;
  background-repeat:no-repeat,no-repeat;
}
/* the outlined button is the one thing in the band with no fill, so over a picture its label
   stood on whatever ripple was behind it: sand on a highlight measured 4.90:1 at 320, the
   thinnest figure on the site. It takes a tint of the band's own teal, which is the same answer
   the cards give -- a floor we control -- and keeps reading as the outlined one beside the blue. */
.mys .btn-line{background:rgba(0,30,40,.55)}

/* ============================================================================================
   START HERE — the third tab (2026-10-09). Peter, after Eric Elizes called the current home "a
   normal general store": "I'm wondering if that means really we want a third tab with products
   demonstrated a little more cleanly... I only have six products up, but they look really clean."
   The Shop tab is the whole catalogue and stays that way; this is the handful, with air.
   Each pack stands on a FIELD OF ITS OWN SHELF'S COLOUR — the same --tint the product card takes
   since the same day, so the card a tap opens is lit like the tile it came from. Every word sits
   BELOW the field, on the chalk, so nothing is ever read off a colour that changes per product and
   there is only one thing to measure. No prices: the site has never carried one.
   ============================================================================================ */
.start-sec .sec-head{max-width:34ch}
.start-lead{margin:14px 0 0;font:400 17px/1.5 var(--sans);color:var(--text);max-width:48ch}
.start-grid{list-style:none;margin:30px 0 0;padding:0;display:grid;gap:22px}
.sc{min-width:0}
/* a COLUMN, not a grid: the cards in a row stretch to the tallest, and with a grid the extra height
   landed on the art panel, so a 1:1 field became a taller one and that card's words started lower than
   its neighbours'. As a flex column the art keeps its square and `margin-top:auto` on .sc-go pushes the
   slack to the bottom, so the "See what's in it" line sits on one baseline across the row. */
.sc-link{display:flex;flex-direction:column;height:100%;padding:0 0 20px;border-radius:18px;background:var(--chalk);
  box-shadow:0 0 0 1px var(--line),0 18px 30px -26px rgba(0,20,27,.5);text-decoration:none;color:var(--ink);
  overflow:hidden;transition:transform 200ms cubic-bezier(.2,.7,.2,1),box-shadow 200ms}
.sc-art{flex:none;display:grid;place-items:center;padding:26px 18px;aspect-ratio:1;overflow:hidden;
  background:linear-gradient(color-mix(in srgb,var(--tint,var(--hollow)) 14%,var(--hollow-hi)),
    color-mix(in srgb,var(--tint,var(--hollow)) 28%,var(--hollow)))}
/* the shot carries aspect-ratio:1 of its own (.shot-studio), and a grid item's automatic minimum size
   refuses to go below its content — so the square shot plus the panel's padding made the panel 16px
   taller than its own aspect-ratio asked, and only on the cards whose shot is a studio one. min-height:0
   lets the panel keep its square and the shot fit inside it. */
.sc-art{overflow:hidden}
.sc-art .shot{display:block;min-width:0;min-height:0;width:100%;height:100%;aspect-ratio:auto;padding:0}
/* THE SECOND PHOTOGRAPH (2026-10-09). Peter, of aspirehealth.pro: "add to the prodcuts on teh main page
   the option to hover (on desktop) or tap (on mobile) to change teh screen". Their cards swap the pack
   shot for a different picture; ours swaps the catalogue cut-out for the same pack PHOTOGRAPHED on a real
   surface (assets/lit/, see lit_shot()). It is a cross-fade of two stacked images, so nothing moves and
   the card's height never changes. A product with no relit photograph has no .sc-lit and simply does not
   flip — which is why the toggle below is only drawn when there is one.
   On a pointer device the whole card does it on hover. ON A TOUCHSCREEN THERE IS NO BUTTON (Peter,
   2026-10-10: "it shouldn't have like a photo button on it... when you click anywhere on the side of the
   product, it goes there"): a tap on the PICTURE flips it, handled in _script.html's capture phase, and a
   tap on the words below still opens the product card. The .sc-flip chip that used to sit over the art is
   gone, markup and all. KEYBOARD FOCUS FLIPS IT AT ANY POINTER TYPE -- the :focus-visible rules below are
   deliberately OUTSIDE the hover media query, which is what the button was also doing for a keyboard on a
   touch device. The cost of dropping the chip is discoverability: nothing on a phone now says the picture
   can be tapped. That is Peter's call, made knowing it. Reduced motion swaps without the fade. */
.sc-art{position:relative}
.sc-art .shot{grid-area:1 / 1}
/* a TRUE cross-fade: the cut-out fades out as the photograph fades in. Fading only the photograph in is
   not enough — .shot is positioned (its own contact-shadow ::after needs that), so it paints ABOVE a
   static sibling and the cut-out stayed visible on top of the new picture. The photograph also takes a
   z-index of its own rather than relying on source order. */
/* absolutely filling the art panel, not a grid item with negative margins: the panel is padded for the
   cut-out, and pulling a 100%-wide image out with margins left it short on two sides and offset. */
.sc-lit{position:absolute;z-index:1;inset:0;display:block;width:100%;height:100%;object-fit:cover;
  opacity:0;transition:opacity 320ms cubic-bezier(.3,.7,.2,1)}
.sc-art .shot{transition:opacity 0s}
@media (hover:hover){.sc-link:hover .sc-art .shot{opacity:0}}
.sc-link:focus-visible .sc-art .shot{opacity:0}
.sc.is-lit .sc-art .shot{opacity:0}
.sc-link:hover .sc-art .shot,.sc-link:focus-visible .sc-art .shot,.sc.is-lit .sc-art .shot{transition:opacity 0s linear 320ms}
.sc-art{display:grid;place-items:stretch}
.sc-art .shot{place-self:center}
@media (hover:hover){.sc-link:hover .sc-lit{opacity:1}}
.sc-link:focus-visible .sc-lit{opacity:1}
.sc.is-lit .sc-lit{opacity:1}
@media (prefers-reduced-motion:reduce){.sc-lit,.sc-art .shot,.sc-link:hover .sc-art .shot,.sc-link:focus-visible .sc-art .shot,.sc.is-lit .sc-art .shot{transition:none}}
.sc-art img{display:block;width:100%;height:100%;object-fit:contain;
  filter:drop-shadow(0 14px 14px rgba(0,20,27,.22))}
.sc-tag{margin:18px 20px 0;font:600 11px/1 var(--sans);letter-spacing:.18em;text-transform:uppercase;color:var(--text)}
.sc-name{margin:9px 20px 0;font:600 clamp(20px,2.4vw,24px)/1.14 var(--display);letter-spacing:-.014em;
  color:var(--teal)}
.sc-desc{margin:8px 20px 0;font:400 15px/1.45 var(--sans);color:var(--text)}
/* the card's foot: the price on the left, the button on the right (Peter, 2026-10-10: "lets add the
   price and the option to view product"). margin-top:auto lives HERE now, not on .sc-go -- it is what
   pushes the foot to the bottom so every card in a row lines its price and button up, whatever the
   name wraps to. EVERY PRICE IS BLANK TODAY and .sc-price is then not drawn at all, so the button sits
   where the old text link did and the row does not reserve an empty gap. */
/* IT WRAPS, and it has to: with both prices in it the row outgrew the card at 1024, the tightest the
   three-column grid ever gets, and the pill broke its own label across two lines and ran into the price.
   The pill keeps its words together (white-space:nowrap) and the FOOT breaks instead, dropping the pill
   to its own line. Every card in a row carries the same shape, so they all wrap together and the heights
   stay level. Re-check this at 1024 if the label or either price gets longer. */
.sc-foot{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:10px 12px;
  margin:14px 20px 0;margin-top:auto;padding-top:16px}
/* Amway's retail struck through, then Peter's price (2026-10-11: "put the amway retial pricing, then
   cross it out and put what my pricing is"). The struck one is deliberately quiet and SMALLER -- it is
   context, not the number you pay -- and the one you pay keeps the display face. Both are labelled for a
   screen reader in the markup, because two numbers in a row say nothing about which is which. */
.sc-price{display:inline-flex;align-items:baseline;gap:8px;font-variant-numeric:tabular-nums;min-width:0}
.sc-was{font:400 14px/1 var(--sans);color:var(--text);opacity:.75;text-decoration-thickness:1.5px}
.sc-now{font:600 21px/1 var(--display);letter-spacing:-.01em;color:var(--teal)}
.sc-go{display:inline-flex;align-items:center;gap:7px;min-height:40px;padding:0 15px;border-radius:999px;
  white-space:nowrap;background:var(--teal);color:var(--chalk);font:600 13px/1 var(--sans);
  letter-spacing:.01em;text-decoration:none}
.sc-link:focus-visible{outline:2px solid var(--teal);outline-offset:3px}
@media (hover:hover){
  .sc-link:hover{transform:translate3d(0,-3px,0);box-shadow:0 0 0 1px var(--line),0 24px 34px -24px rgba(0,20,27,.55)}
  .sc-link:hover .sc-go{background:var(--accent)}
}
.sc-link:active{transform:translate3d(0,1px,0)}
@media (prefers-reduced-motion:reduce){.sc-link{transition:none}}
.start-more{margin:34px 0 0;display:grid;gap:12px;justify-items:start}
.start-more-ask{margin:0;font:600 17px/1.35 var(--sans);color:var(--ink)}
.start-more-acts{display:flex;flex-wrap:wrap;align-items:center;gap:10px 22px}
@media (min-width:640px){
  .start-grid{grid-template-columns:1fr 1fr;gap:24px}
}
@media (min-width:1024px){
  .start-grid{grid-template-columns:repeat(3,1fr);gap:28px;margin-top:38px}
  .start-lead{font-size:18px}
}

/* ---- BUILD YOUR GOALS: the first-time funnel's own head (2026-10-09). The two halves below it are the
   site's own rack and its own call and bring their own styling; this is only the page's opening and the
   way out of it. */
.fn-top .sec-head{max-width:30ch}
.fn-lead{margin:14px 0 0;font:400 17px/1.5 var(--sans);color:var(--text);max-width:46ch}
.fn-out{display:inline-flex;align-items:center;gap:8px;margin:18px 0 0;min-height:44px;
  font:600 14px/1.2 var(--sans);color:var(--text);text-decoration:underline;text-underline-offset:4px}
@media (hover:hover){.fn-out:hover{color:var(--teal);text-decoration-thickness:2.5px}}
@media (min-width:1024px){.fn-lead{font-size:18px}}

/* "Stacks well with" on the product card (2026-10-09, STACKS_WITH). One quiet line under the facts; it
   is a pointer to another product, never a claim about the two together. */
.pcard-with{margin:10px 0 0;font:500 15px/1.45 var(--sans);color:var(--text)}
/* the price in the product card (2026-10-21), on Top 9 only: the tile showed it and the card that holds the
   only Buy button used to drop it. Same two classes as the tile's, so the two read as one number. */
.pcard-price{display:flex;flex-wrap:wrap;align-items:baseline;gap:4px 8px;margin:14px 0 0;font-variant-numeric:tabular-nums}
.pcard-price-note{font:400 14px/1.3 var(--sans);color:var(--text)}
.pcard-with[hidden]{display:none}
.pcard-with-go{font-weight:600;display:inline;text-align:left}   /* a <button> when the partner is on the page: inline, so it reads on as part of the sentence */

/* ---- Buy, repeat, earn (2026-10-12) --------------------------------------------------------------
   On the Top 9 page, under the grid. THE TERMS COME BEFORE THE BUTTON and are the largest thing in the
   block after the heading: the 16% has a condition on it ($150 a month) and the condition is the part a
   visitor has to agree to. See the long note in start.template.html for what the page deliberately does
   NOT claim. The reveal is a native <details>, like the story's: opening it is the browser's job, it
   works with no JavaScript, and the form inside is a plain POST for the same reason. */
/* THE TEXT ASK, INSIDE THE A+ MEMBERSHIP BLOCK (2026-10-24). It used to be its own panel at the top of Top 9
   (beside the intro on a laptop, a one-line link on a phone). Four phone critics found that: the link jumped
   past all nine products; it took a small phone's first screen before any product; the panel and this block
   said the same terms 233px apart with an exit between them; and "VIP account" and "A+ membership" read as
   two things. Peter approved moving it here, so the offer is one block with two ways in: text him (the
   primary button), or leave details in the form (the outline one under it). */
.repeat-ask{display:grid;justify-items:start;gap:12px;margin-top:4px;padding-top:16px;border-top:1px solid var(--line);width:100%}
.repeat-ask-line{margin:0;max-width:52ch;font:400 clamp(16px,4vw,18px)/1.5 var(--sans);color:var(--ink)}
.repeat-ask-line b{font-weight:700;color:var(--teal)}
.repeat-num{padding:12px 0;font-weight:700;color:var(--teal);white-space:nowrap;text-decoration:underline;text-underline-offset:3px}
/* ============================================================================================
   THE A+ MEMBERSHIP, REBUILT (2026-10-29) in the structure Peter liked on his family's site: the price and the
   headline value side by side, then the benefits on a $150 order and the extra perks as two rows of three. Our
   palette: the price on Peter's teal, the value on the panel's own sand. Every figure is Amway's (the block's
   comment in start.template.html). Three across from 640; one column below, each line icon, figure, words.
   ============================================================================================ */
.mb-top{display:grid;grid-template-columns:1fr;gap:0;width:100%;border:1px solid var(--line);overflow:hidden}
.mb-price,.mb-unlock{margin:0;display:grid;align-content:center;gap:2px;padding:18px 20px}
.mb-price{background:var(--teal);color:var(--chalk)}
.mb-price b{font:600 clamp(48px,14vw,64px)/1 var(--display);letter-spacing:-.02em}
.mb-price span{font:500 16px/1.3 var(--sans);color:var(--on-dark)}
.mb-unlock{background:color-mix(in srgb,var(--chalk) 70%,transparent)}
.mb-unlock span{font:600 12px/1.35 var(--sans);letter-spacing:.14em;text-transform:uppercase;color:var(--text)}
.mb-unlock span:last-child{font:500 15px/1.4 var(--sans);letter-spacing:0;text-transform:none;color:var(--ink)}
.mb-unlock b{font:600 clamp(44px,12vw,58px)/1 var(--display);letter-spacing:-.02em;color:var(--teal)}
.mb-h{margin:6px 0 0;font:600 12px/1.35 var(--sans);letter-spacing:.14em;text-transform:uppercase;color:var(--text)}
.mb-grid{list-style:none;margin:0;padding:0;width:100%;display:grid;gap:10px}
.mb-grid li{display:grid;grid-template-columns:40px 1fr;column-gap:12px;align-items:center;padding:12px 14px;
  background:color-mix(in srgb,var(--chalk) 70%,transparent);border:1px solid var(--line)}
.mb-ic{grid-row:1 / 3;width:40px;height:40px;padding:8px;border-radius:50%;background:color-mix(in srgb,var(--teal) 10%,var(--chalk));color:var(--teal)}
.mb-grid b{font:600 20px/1.15 var(--display);color:var(--ink)}
.mb-grid span{font:400 15px/1.35 var(--sans);color:var(--text)}
@media (min-width:640px){
  .mb-top{grid-template-columns:1fr 1.25fr}
  .mb-grid{grid-template-columns:repeat(3,minmax(0,1fr))}
  .mb-grid li{grid-template-columns:1fr;justify-items:center;text-align:center;row-gap:4px;padding:18px 14px}
  .mb-ic{grid-row:auto;margin-bottom:4px;width:48px;height:48px;padding:10px}
}

/* ============================================================================================
   THE ANNOUNCEMENT BAR (2026-10-29): above the masthead on every page, scrolls away with the page (only the
   masthead is sticky). One message at a time, the next event or the A+ membership (announce_bar()); the script
   re-picks on the visitor's clock and remembers a close per message.
   ============================================================================================ */
.ann{position:relative;background:#001E27;color:var(--sand);font:500 13px/1.4 var(--sans)}
.ann[hidden]{display:none}
.ann-in{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:2px 12px;margin:0 auto;
  padding-top:9px;padding-bottom:9px;padding-right:calc(var(--pad) + 32px);text-align:center}
.ann b{font-weight:700;color:var(--chalk)}
/* phones get one line, so the bar never pushes the Shop's "Pick your goal" off a small screen (it took three
   lines and 75px at 390 with the full sentence) */
.ann-short{display:none}
@media (max-width:639px){.ann-long{display:none}.ann-short{display:inline}.ann-in{flex-wrap:nowrap;gap:10px;padding-top:7px;padding-bottom:7px;font-size:12.5px;white-space:nowrap}
  /* on a phone the WHOLE bar is the link (a critic measured the link alone at 112x18): the link's ::after
     stretches over the bar, and the close button sits above it so it still closes rather than navigates */
  .ann a::after{content:"";position:absolute;inset:0}
  .ann-x{z-index:1}}
@media (max-width:379px){.ann-in{font-size:12px;gap:8px;padding-right:calc(var(--pad) + 24px)}}
.ann a{display:inline-flex;align-items:center;gap:4px;color:var(--sand);font-weight:600;text-decoration:underline;
  text-decoration-thickness:1px;text-underline-offset:3px;white-space:nowrap}
.ann a:focus-visible,.ann-x:focus-visible{outline:2px solid var(--sand);outline-offset:2px}
.ann-x{position:absolute;right:calc(var(--pad) - 12px);top:50%;transform:translateY(-50%);width:44px;height:44px;border:0;background:transparent;
  color:var(--sand);font:400 22px/1 var(--sans);cursor:pointer}

/* ============================================================================================
   GIFTS (2026-10-29). Chelsea's photographs in square frames (the set mixes 4:3 and 3:4, and a square crops both
   by the same quarter), each card the site's own chalk card; the order form is the membership's sand panel.
   ============================================================================================ */
.gifts-sec .sec-head,.events-sec .sec-head{max-width:40ch}
.gifts-lead{margin:14px 0 0;font:400 17px/1.5 var(--sans);color:var(--text);max-width:48ch}
.gifts-note{margin:10px 0 0;font:400 15px/1.5 var(--sans);color:var(--text);max-width:48ch}
.gf-grid{list-style:none;margin:30px 0 0;padding:0;display:grid;gap:22px}
.gf{display:flex;flex-direction:column;border-radius:18px;overflow:hidden;background:var(--chalk);
  box-shadow:0 0 0 1px var(--line),0 18px 30px -26px rgba(0,20,27,.5)}
.gf-art{margin:0;aspect-ratio:1;overflow:hidden;background:var(--hollow)}
.gf-art img{display:block;width:100%;height:100%;object-fit:cover;object-position:50% 55%}
.gf-body{display:flex;flex-direction:column;gap:8px;padding:18px 20px 20px;flex:1}
.gf-name{margin:0;font:600 24px/1.15 var(--display);letter-spacing:-.01em;color:var(--ink)}
.gf-line{margin:0;font:400 16px/1.45 var(--sans);color:var(--text)}
.gf-items{list-style:none;margin:4px 0 0;padding:0;display:grid;gap:4px;font:500 14px/1.4 var(--sans);color:var(--ink)}
.gf-items li{position:relative;padding-left:14px}
.gf-items li::before{content:"";position:absolute;left:0;top:.6em;width:5px;height:5px;border-radius:50%;background:var(--teal)}
.gf-go{margin-top:auto;align-self:flex-start}
.gf-body .gf-go{margin-top:12px}
.gift-how{list-style:none;margin:20px 0 0;padding:0;display:grid;gap:16px;counter-reset:gh}
.gift-how li{display:grid;gap:4px;padding-left:44px;position:relative;counter-increment:gh}
.gift-how li::before{content:counter(gh,decimal-leading-zero);position:absolute;left:0;top:0;font:600 22px/1.1 var(--display);color:var(--teal)}
.gift-how b{font:600 18px/1.3 var(--sans);color:var(--ink)}
.gift-how span{font:400 16px/1.45 var(--sans);color:var(--text)}
.repeat-field select{width:100%;min-height:46px;padding:11px 12px;border:1px solid var(--line);border-radius:0;background:#fff;
  font:400 16px/1.4 var(--sans);color:var(--ink)}
.gift-order-sec:has(.s-done:target) .gift-form{display:none}
@media (min-width:640px){.gf-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (min-width:1024px){.gf-grid{grid-template-columns:repeat(3,minmax(0,1fr));gap:28px}.gift-how{grid-template-columns:repeat(3,1fr);gap:28px}}

/* ============================================================================================
   EVENTS (2026-10-29): a date block beside each event, its sign-up a native <details> like the membership's.
   ============================================================================================ */
.ev-list{list-style:none;margin:30px 0 0;padding:0;display:grid;gap:22px}
.ev{display:grid;grid-template-columns:64px 1fr;gap:16px;padding:20px;background:var(--chalk);border-radius:18px;
  box-shadow:0 0 0 1px var(--line),0 18px 30px -26px rgba(0,20,27,.5);scroll-margin-top:calc(var(--mh) + 16px)}
.ev[hidden]{display:none}
.ev-date{margin:0;display:grid;justify-items:center;align-content:start;padding:10px 0;border-radius:12px;background:var(--teal);color:var(--chalk);height:max-content}
.ev-date span{font:700 12px/1.2 var(--sans);letter-spacing:.14em;text-transform:uppercase;color:var(--sand)}
.ev-date b{font:600 30px/1.05 var(--display)}
.ev-body{display:grid;gap:8px;justify-items:start;min-width:0}
.ev-kind{margin:0}
.ev-title{margin:0;font:600 clamp(24px,6vw,32px)/1.12 var(--display);letter-spacing:-.01em;color:var(--ink)}
.ev-when{margin:0;font:600 16px/1.45 var(--sans);color:var(--teal)}
.ev-text{margin:0;font:400 16px/1.5 var(--sans);color:var(--text);max-width:56ch}
.ev-form{width:100%}
.ev-form{display:grid;gap:14px;margin-top:16px;max-width:30rem}
.ev-none{margin:24px 0 0;font:400 17px/1.5 var(--sans);color:var(--text)}
.ev-done{margin-top:22px}
.gifts-jump{margin:14px 0 0;font-size:16px}
/* a page that opens on a plain section (About, Gifts, Events, Top 9) starts half a section down on a phone, not a
   whole one: ~70px of empty ground sat under the tab bar (2026-10-29, a critic) */
@media (max-width:767px){main > .sec:first-child{padding-top:calc(var(--sec) * .5)}}
/* the list's own form only when nothing is on the calendar: while an event is up, its sign-up carries a
   "next one too" tick instead. Its thank-you still shows on a return to #list-sent. */
.events-sec:has(.ev:not([hidden])) + .list-sec:not(:has(:target)){display:none}
.repeat-field label .repeat-hint{display:block;margin-top:2px;font-weight:400;font-size:13.5px;color:var(--text)}
.events-sec:has(.ev-done:target) .ev-list{display:none}
.list-sec:has(.s-done:target) #list-form{display:none}
.ev-when span{display:block;font-weight:400;color:var(--text)}
/* phones: the date is a small badge over the title, so the words get the card's whole width */
@media (max-width:519px){.ev{grid-template-columns:1fr;gap:12px}
  .ev-date{display:inline-flex;align-items:baseline;gap:8px;justify-self:start;padding:6px 12px;border-radius:999px}
  .ev-date b{font-size:20px}}
@media (min-width:768px){.ev{grid-template-columns:88px 1fr;gap:24px;padding:28px}.ev-date b{font-size:38px}}

.repeat-sec{padding-top:calc(var(--sec) * .5)}
.repeat{display:grid;justify-items:start;gap:14px;padding:28px 24px 30px;
  background:color-mix(in srgb,var(--sand) 42%,var(--chalk));border:1px solid var(--line)}
.repeat h2{font-size:clamp(27px,6.6vw,34px)}
.repeat-terms{margin:0;max-width:46ch;font:400 clamp(17px,4.2vw,19px)/1.5 var(--sans);color:var(--ink)}
.repeat-terms b{font-weight:700;color:var(--teal)}
/* the one comparison the page makes, and it is the conservative one: $40 against the $20 fee, with
   nothing said about the free product, whose worth varies. Between the terms and the fine print in
   size, because it is neither. */
.repeat-more{margin:0;max-width:50ch;font:500 16px/1.5 var(--sans);color:var(--ink)}
.repeat-fine{margin:0;max-width:52ch;font:400 15px/1.5 var(--sans);color:var(--text)}
.repeat-rev{width:100%;margin-top:4px}
.repeat-go{display:inline-flex;align-items:center;gap:10px;max-width:100%;cursor:pointer;list-style:none;
  text-align:left;text-wrap:balance}
.repeat-go::-webkit-details-marker{display:none}
.repeat-go::after{content:"";flex:none;width:9px;height:9px;border-right:2px solid currentColor;
  border-bottom:2px solid currentColor;transform:translateY(-2px) rotate(45deg);transition:transform 200ms cubic-bezier(.23,1,.32,1)}
@media (prefers-reduced-motion:reduce){.repeat-go::after{transition:none}}
.repeat-rev[open] .repeat-go::after{transform:translateY(1px) rotate(-135deg)}
.repeat-go:focus-visible{outline:2px solid var(--teal);outline-offset:3px}
@media (max-width:419px){.repeat{padding:24px 16px 26px}.repeat-form{padding:18px 14px 20px}}
.repeat-form{display:grid;gap:16px;max-width:38rem;margin-top:20px;padding:22px 20px 24px;
  background:var(--chalk);border:1px solid var(--line)}
.repeat-field{display:grid;gap:6px}
.repeat-field label{font:600 14px/1.3 var(--sans);color:var(--ink)}
.repeat-opt{font-weight:400;color:var(--text)}
.repeat-field input,.repeat-field textarea{width:100%;min-height:46px;padding:11px 12px;border:1px solid var(--line);
  border-radius:0;background:#fff;font:400 16px/1.4 var(--sans);color:var(--ink)}
.repeat-field textarea{min-height:84px;resize:vertical}
.repeat-field input:focus-visible,.repeat-field textarea:focus-visible{outline:2px solid var(--accent);outline-offset:1px}
.repeat-consent{display:grid;grid-template-columns:auto 1fr;gap:10px;align-items:start;
  font:400 15px/1.4 var(--sans);color:var(--ink)}
.repeat-consent input{width:20px;height:20px;margin:1px 0 0;accent-color:var(--accent)}
.repeat-send{justify-self:start}
.repeat-priv{margin:0;font:400 13px/1.4 var(--sans);color:var(--text)}
.repeat-done{margin-top:20px;padding:22px 20px;background:var(--chalk);border:1px solid var(--line)}
/* the form steps aside once the thank-you is the target, exactly as the sample's does */
.repeat-sec:has(.s-done:target) .repeat-rev{display:none}
@media (min-width:768px){
  .repeat{padding:34px 34px 38px;gap:16px}
  .repeat-form{margin-top:24px;padding:26px 26px 28px}
}
