/* ==========================================================================
   Feral Strength Club — layout and components
   Zero build step. Load order: tokens.css then this.
   ========================================================================== */

/* ---- reset ------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  background: var(--ground);
  color: var(--ink);
  font: 400 var(--t-body)/var(--lh-body) var(--body);
  letter-spacing: var(--ls-body);
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img, svg, video { display: block; max-width: 100%; }
button, input, textarea, select { font: inherit; color: inherit; }
a { color: inherit; }

::selection { background: var(--accent); color: var(--ink-on-accent); }

:focus-visible {
  outline: 2px solid var(--focus-on-dark);
  outline-offset: 3px;
  border-radius: 1px;
}

.sr {
  position: absolute; width: 1px; height: 1px;
  padding: 0; overflow: hidden; clip: rect(0 0 0 0);
  white-space: nowrap; border: 0;
}

.skip {
  position: absolute; left: var(--gut); top: -100px; z-index: 200;
  background: var(--accent); color: var(--ink-on-accent);
  padding: 12px 20px; border-radius: var(--r-btn);
  font: 500 var(--t-small)/1 var(--body);
  letter-spacing: var(--ls-caps); text-transform: uppercase;
  text-decoration: none; transition: top var(--dur-fast) var(--ease);
}
.skip:focus { top: var(--gut); }

/* ---- type -------------------------------------------------------------- */
.display, .head { font-family: var(--display); font-weight: 400;
                  line-height: var(--lh-display); letter-spacing: var(--ls-display); }
.display { font-size: var(--t-display); }
.head    { font-size: var(--t-head); }

.sub {
  font: 400 var(--t-sub)/var(--lh-sub) var(--sub);
  letter-spacing: var(--ls-sub);
}

.caps {
  font: 500 var(--t-caps)/1.2 var(--body);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
}

.lede  { font-size: clamp(17px, 1.5vw, 21px); color: var(--ink-dim); max-width: var(--measure); }
.small { font-size: var(--t-small); color: var(--ink-faint); letter-spacing: -.01em; }

p { max-width: var(--measure); }
p + p { margin-top: 1em; }

/* Headlines are sentence case. All-caps is for small titles only:
   the date stamp, eyebrows and buttons. Never body copy. */

/* ---- layout ------------------------------------------------------------ */
/* Full bleed: no centred container. The gutter is the only inset and
   --measure keeps line length sane on very wide screens. */
.wrap { width: 100%; padding-inline: var(--gut); }

.section {
  position: relative;
  background: var(--surface, var(--ground));
  color: var(--on-surface, var(--ink));
  padding-block: var(--sp-5);
  overflow: hidden;
  isolation: isolate;
}
.section > .wrap { position: relative; z-index: var(--z-content); }

.eyebrow {
  display: flex; align-items: center; gap: 10px;
  margin-bottom: var(--sp-2); color: var(--ink-faint);
}
.eyebrow::before {
  content: ""; width: 24px; height: 2px;
  background: var(--accent); flex: 0 0 auto;
}

/* ---- pattern ------------------------------------------------------------
   Wall scale: ONE marking spans the surface. Never the middle size.
   One patterned surface in view at a time. Dark grounds only — Bone
   markings on a Bone ground are invisible, and tinting them to Evergreen
   costs body-copy contrast.                                               */
.hide {
  position: absolute; inset: -8% -8% -8% -8%;
  background: url("../assets/pattern-hide.svg") center / cover no-repeat;
  opacity: var(--hide-opacity);
  z-index: var(--z-pattern);
  pointer-events: none;
}
.on-bone .hide { display: none; }

/* ---- buttons ------------------------------------------------------------
   One button shape, one label, one destination. Secondary routes are text
   links, never buttons. Sun is the only filled colour on the site.        */
.btn {
  display: inline-flex; align-items: center; justify-content: center;
  gap: 10px; min-height: 52px; padding: 0 28px;
  border: 0; border-radius: var(--r-btn);
  font: 500 var(--t-caps)/1 var(--body);
  letter-spacing: var(--ls-caps); text-transform: uppercase;
  text-decoration: none; cursor: pointer;
  transition: background var(--dur-fast) var(--ease),
              transform var(--dur-fast) var(--ease),
              font-variation-settings var(--dur) var(--ease-out),
              letter-spacing var(--dur) var(--ease-out);
}

/* Only .btn-primary may set --accent as a background, and it must always
   pair it with --ink-on-accent. This is a greppable rule. */
.btn-primary { background: var(--accent); color: var(--ink-on-accent); }
.btn-primary:hover { background: var(--accent-hover); transform: translateY(-1px); }
.btn-primary:active { background: var(--accent-press); transform: none; }
.btn-primary:focus-visible { outline-color: var(--focus-on-accent); }

.btn-quiet {
  background: transparent; color: var(--on-surface);
  box-shadow: inset 0 0 0 1px var(--rule-strong);
}
.btn-quiet:hover { box-shadow: inset 0 0 0 1px var(--on-surface); }

/* Variable-axis hover, Phive-style. Hanken Grotesk is the only variable
   face in the brand — Young Serif and Spectral are static, so headlines
   cannot do this. Buttons and labels can. */
@supports (font-variation-settings: "wght" 600) {
  .btn { font-variation-settings: "wght" 500; }
  .btn:hover { font-variation-settings: "wght" 700; letter-spacing: .22em; }
}

.btn-row { display: flex; flex-wrap: wrap; gap: var(--sp-2); align-items: center; }

.link-quiet {
  color: var(--ink-dim); text-decoration: none;
  border-bottom: 1px solid var(--rule);
  padding-bottom: 2px; transition: color var(--dur-fast) var(--ease),
                                   border-color var(--dur-fast) var(--ease);
}
.link-quiet:hover { color: var(--on-surface); border-color: currentColor; }

/* ---- header -------------------------------------------------------------
   The MARK, not the logotype, at its 84px minimum — which is what sets the
   116px bar height. The CTA is a flush-right full-height block, edge to
   edge, per the Studio6 reference.                                        */
.site-header {
  position: sticky; top: 0; z-index: var(--z-header);
  background: rgba(1, 43, 33, .86);
  border-bottom: 1px solid var(--rule);
}
@supports (backdrop-filter: blur(14px)) {
  .site-header { backdrop-filter: blur(14px); }
}

.site-header .bar {
  display: flex; align-items: stretch;
  min-height: var(--header-h);
  width: 100%;
  padding-left: var(--gut);       /* no right padding: the CTA is flush */
}
.site-header .brand {
  margin-right: auto; display: flex; align-items: center;
}
.site-header .brand img {
  /* The mark's artwork is 509 x 541 — it is NOT square. Setting both axes to
     the same value stretches it ~6% horizontally, which guideline 1.8
     forbids outright ("do not disproportionately stretch or warp"). Width is
     the dimension the 84px minimum refers to; height follows the ratio. */
  width: var(--mark-w); height: var(--mark-h);
}
.site-header nav { display: flex; align-items: stretch; gap: 0; }
.site-header nav a:not(.btn) {
  display: flex; align-items: center;
  padding-inline: clamp(18px, 2.4vw, 34px);
  text-decoration: none; color: var(--ink-dim);
  font: 500 var(--t-caps)/1 var(--body);
  letter-spacing: var(--ls-caps); text-transform: uppercase;
  transition: color var(--dur-fast) var(--ease);
}
.site-header nav a:not(.btn):hover { color: var(--ink); }

/* Flush-right block, full bar height, square. */
.site-header .btn {
  align-self: stretch; min-height: 0; border-radius: 0;
  padding-inline: clamp(24px, 3.2vw, 56px);
}

@media (max-width: 760px) {
  :root { --header-h: 112px; }   /* mark stays at its 84px minimum width */
  .site-header nav a:not(.btn) { display: none; }
  .site-header .btn { padding-inline: 20px; font-size: 10px; }
}

/* ---- desktop nav: the Lassie capsules (29 Sept 2026) ---------------------
   Replaces the 124px full-width bar above 760px. Two frosted capsules
   floating over the page, as on Lassie: the mark, About and Find us
   centred, and Book a call alone on the right (Lassie's Login/Demo spot).
   All chips Bone, no Sun. Same build as the phone pill, so the two read
   as one system. The header leaves the flow, so each page's first section
   keeps its own top padding and the capsules sit over it.
   NB the mark here is 26px, below the 84px minimum (guideline 1.1), as
   on the phone pill. /join has its own header and is left alone.       */
.nav-pill { display: contents; }         /* phone: the wrappers vanish */
@media (max-width: 760px) { .nav-cta { display: none; } }

@media (min-width: 761px) {
  .site-header[data-site-header] {
    position: fixed; inset: 0 0 auto 0;
    background: transparent; border-bottom: 0;
    backdrop-filter: none; -webkit-backdrop-filter: none;
    pointer-events: none;                 /* only the capsules take clicks */
  }
  .site-header[data-site-header] .bar {
    position: relative; min-height: 0;
    display: flex; align-items: center; justify-content: center;
    padding: 20px var(--gut);
  }
  .site-header[data-site-header] .nav-pill {
    display: flex; align-items: center; gap: 4px;
    padding: 4px;
    border-radius: 18px;
    /* Lassie's build: white chips in a warm beige rim, so the capsule
       holds its edge over the Bone sections as well as the Evergreen */
    background: rgba(232, 226, 212, .72);
    backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
    box-shadow: 0 6px 20px rgba(0, 21, 16, .14);
    pointer-events: auto;
  }
  .site-header[data-site-header] .nav-cta { position: absolute; right: var(--gut); }
  .site-header[data-site-header] .brand { margin: 0; padding-inline: 13px; }
  .site-header[data-site-header] nav { display: flex; align-items: center; gap: 4px; }
  .site-header[data-site-header] .brand,
  .site-header[data-site-header] .nav-pill a {
    display: flex; align-items: center; justify-content: center;
    height: 44px; min-height: 44px;
    border-radius: 14px;
    background: #fff; color: var(--ground);
    font: 500 15px/1 var(--body); letter-spacing: 0; text-transform: none;
    text-decoration: none;
    transition: background-color var(--dur-fast) var(--ease);
  }
  .site-header[data-site-header] .nav-pill a:not(.brand) { padding-inline: 16px; }
  .site-header[data-site-header] .brand img { display: none; }
  /* the mark, recoloured Evergreen by masking the bone artwork */
  .site-header[data-site-header] .brand::before {
    content: ""; display: block;
    width: 26px; height: calc(26px * 541 / 509);
    background: var(--ground);
    -webkit-mask: url("../assets/logomark-bone.svg") center / contain no-repeat;
            mask: url("../assets/logomark-bone.svg") center / contain no-repeat;
  }
  .site-header[data-site-header] .nav-pill a:hover { background: var(--bone); }
  .site-header[data-site-header] nav a[aria-current="page"] { background: transparent; }
  .site-header[data-site-header] .nav-pill a:focus-visible { outline: 2px solid var(--bone); outline-offset: 3px; }
}

/* ---- hero ---------------------------------------------------------------
   No photograph. Type, ground and one accent carry it — the Metrix move,
   and the only hero that is buildable with no image library.              */
.hero { padding-block: clamp(var(--sp-5), 14vh, 180px) var(--sp-5); }
.hero .display { max-width: 16ch; text-wrap: balance; }
/* Two-line headline: upright Young Serif, then a light Spectral italic turn.
   Each line holds on one line; the italic is sized up because Spectral sits
   smaller than Young Serif at the same size. */
.hero .hero-head { max-width: none; line-height: 1.04; letter-spacing: -.015em; }
.hero-head .l1, .hero-head .l2 { display: block; white-space: nowrap; }
.hero-head .l2 { font-family: var(--sub); font-style: italic; font-weight: 300;
                 font-size: .62em; line-height: 1.3; margin-top: .12em; letter-spacing: -.01em; }   /* a step down from line one, so the pair has a hierarchy */
.hero .sub { margin-top: var(--sp-2); max-width: 46ch; color: var(--ink-dim); }
.hero .btn-row { margin-top: var(--sp-3); }
.hero .terms { margin-top: var(--sp-2); color: var(--ink-faint); }

.stamp {
  display: flex; flex-wrap: wrap; gap: 8px 18px;
  margin-top: var(--sp-4); padding-top: var(--sp-2);
  border-top: 1px solid var(--rule);
  color: var(--ink-faint);
}
.stamp b { color: var(--ink-dim); font-weight: 500; }

/* Desktop hero, centred (29 Sept 2026): every line of the fold on one
   centre axis, Lassie-style. The phone fold is already centred.          */
@media (min-width: 761px) {
  .hero .wrap { text-align: center; }
  .hero .eyebrow { justify-content: center; }
  .hero .wrap > * { margin-inline: auto; }
  .hero .ticker li { inset: 0 0 auto 0; justify-content: center; }
  .hero .btn-row, .hero .stamp { justify-content: center; }
}

/* ---- the return: one sentence, one ground ------------------------------ */
.statement { text-align: center; }
.statement .head { max-width: 18ch; margin-inline: auto; text-wrap: balance; }
.statement .mark { width: var(--mark-w); height: auto; margin: 0 auto var(--sp-3); opacity: .9; }
/* Lassie's beat: mark, name, one short line, lots of air. */
.statement { padding-block: clamp(120px, 18vw, 220px) clamp(40px, 5vw, 80px); }
.statement .statement-name { color: var(--ink-faint); margin: 0 auto var(--sp-2); max-width: none; }
.statement .statement-pitch { max-width: 22ch; margin-inline: auto; text-wrap: balance; color: var(--ink); }

/* ---- image slots --------------------------------------------------------
   Phive's [data-aspect-ratio] + [data-lazy-figure], adapted.

   The ratio is reserved NOW, so dropping an <img> in later causes zero
   layout shift. Empty, the slot renders a pattern panel with a cropped
   outline mark — deliberate, brand-correct, and the one device no
   competitor in Canterbury has. No grey boxes. No "photo coming soon".   */
.slot {
  position: relative; display: block; width: 100%;
  border-radius: var(--r-card); overflow: hidden;
  background: var(--ground-deep);
  aspect-ratio: var(--ratio, 16 / 9);
}
.slot[data-ratio="16x9"] { --ratio: 16 / 9; }
.slot[data-ratio="4x5"]  { --ratio: 4 / 5; }
.slot[data-ratio="3x4"]  { --ratio: 3 / 4; }
.slot[data-ratio="1x1"]  { --ratio: 1 / 1; }

.slot > img { width: 100%; height: 100%; object-fit: cover; }

/* the empty state */
.slot::before {
  content: "";
  position: absolute; inset: -10%;
  /* Wall scale, per guideline 5.1: ONE marking spans the surface. `cover`
     on a box this small showed the whole hide at middle scale, which the
     guidelines forbid outright — hence the deliberate 380% zoom. */
  background: url("../assets/pattern-hide.svg") 32% 42% / 380% auto no-repeat;
  opacity: .04;
}
.slot::after {
  content: "";
  position: absolute; right: -14%; bottom: -22%;
  width: 62%; aspect-ratio: 1;
  background: var(--slot-accent, var(--graphic-pine));
  -webkit-mask: url("../assets/outline-mark-bone.svg") center / contain no-repeat;
          mask: url("../assets/outline-mark-bone.svg") center / contain no-repeat;
  opacity: .5;
}
/* once a real image is in the slot, the placeholder furniture goes */
.slot:has(> img)::before,
.slot:has(> img)::after { display: none; }

/* Where masks are unsupported the accent fill would paint as a solid
   block, so hide it outright rather than ship a coloured rectangle. */
@supports not ((-webkit-mask: url("")) or (mask: url(""))) {
  .slot::after { display: none; }
}

/* Draft scaffolding: marks where a photograph will go. Readable on purpose
   (it measured 1.08:1 as plain faint text). Delete the span when the real
   image lands — see images/README.md. */
.slot-note {
  position: absolute; left: 12px; bottom: 12px;
  background: rgba(0, 12, 9, .72);
  color: var(--bone); font-size: 11px;
  padding: 5px 9px; border-radius: 3px;
  letter-spacing: var(--ls-caps); text-transform: uppercase;
}

/* ---- sticky stack: the four formats -------------------------------------
   Phive's club-slider. Each card is position:sticky so the cards pile over
   one another as you scroll. This is the signature moment of the site and
   the reason the formats do not need a carousel.                          */
.stack { position: relative; }

.stack-card {
  position: sticky; top: 0;
  min-height: 100vh; min-height: 100svh;
  display: flex; align-items: center;
  background: var(--ground-deep);
  border-top: 1px solid var(--rule-strong);
  /* the incoming card casts onto the one it covers, so the stack reads
     as layers rather than as one continuous surface */
  box-shadow: 0 -24px 48px rgba(0, 0, 0, .45);
  overflow: hidden;
  isolation: isolate;
}
/* All four cards share ONE ground. They used to step down the Evergreen
   ramp (700 -> 800 -> 900 -> near-black), but adjacent steps measured
   1.03-1.07:1 against each other — "the same colour with the lights
   dimmed", which 3.11 calls out directly. The stack was relying on a
   difference nobody can see. Separation now comes from the top rule and
   the shadow the incoming card casts; identity comes from the accent,
   one per card, which is the rule anyway. */
.stack-card:nth-child(1) { --accent-c: var(--graphic-sun);  }
.stack-card:nth-child(2) { --accent-c: var(--graphic-amar); }
.stack-card:nth-child(3) { --accent-c: var(--graphic-pine); }
.stack-card:nth-child(4) { --accent-c: var(--graphic-crim); }

.stack-card .inner {
  position: relative; z-index: 2;
  width: 100%; padding-inline: var(--gut);
  display: grid; grid-template-columns: 1.15fr .85fr;
  gap: var(--sp-4); align-items: center;
}
@media (max-width: 860px) {
  .stack-card .inner { grid-template-columns: 1fr; gap: var(--sp-3); }
  .stack-card { min-height: auto; padding-block: var(--sp-5); }
}

.stack-card .num {
  /* The card's accent is a GRAPHIC here, not the text colour. Setting
     `color: var(--accent-c)` measured 3.50:1 (Pine) and 3.82:1 (Amaranth)
     at 12px, and broke the rule that graphic tokens never carry type.
     The accent is now the bar; the label is Bone. */
  display: flex; align-items: center; gap: 10px;
  color: var(--ink-dim);
  font: 500 var(--t-caps)/1 var(--body);
  letter-spacing: var(--ls-caps); text-transform: uppercase;
  margin-bottom: var(--sp-1);
}
.stack-card .num::before {
  content: ""; width: 22px; height: 2px;
  background: var(--accent-c); flex: 0 0 auto;
}
.stack-card .head { margin-bottom: var(--sp-2); }
.stack-card .one-line { color: var(--ink-dim); margin-bottom: var(--sp-2); }
.stack-card .facts { list-style: none; padding: 0; margin-top: var(--sp-2); }
.stack-card .facts li {
  padding: 10px 0; border-top: 1px solid var(--rule);
  color: var(--ink-dim); font-size: var(--t-small);
}
.stack-card .slot { --slot-accent: var(--accent-c); }

/* the marquee running behind each card */
.stack-card .marquee {
  position: absolute; left: 0; right: 0; bottom: 4%;
  z-index: 1; opacity: .07; pointer-events: none;
}
.stack-card .marquee span {
  font-family: var(--display);
  font-size: clamp(90px, 18vw, 260px);
  line-height: .9; white-space: nowrap;
  color: var(--accent-c);
}

/* ---- marquee -----------------------------------------------------------
   Two identical runs. Translating exactly -50% lands run two where run one
   began, so the loop has no seam.                                        */
.marquee { overflow: hidden; }
.marquee-track {
  display: flex; width: max-content;
  animation: marquee 32s linear infinite;
}
.marquee-track > * { padding-right: .35em; }
@keyframes marquee { to { transform: translate3d(-50%, 0, 0); } }

/* ---- steps -------------------------------------------------------------- */
.steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-3); margin-top: var(--sp-4); }
@media (max-width: 760px) { .steps { grid-template-columns: 1fr; } }

.step { padding-top: var(--sp-2); border-top: 2px solid var(--rule-strong); }
.step .n { color: var(--accent-text); font-family: var(--display); font-size: 28px; line-height: 1; }
.step h3 { font-family: var(--display); font-weight: 400; font-size: clamp(20px, 2vw, 26px);
           line-height: 1.1; margin: 12px 0 8px; }
.step p { color: var(--ink-dim); font-size: var(--t-small); }

/* ---- values row ---------------------------------------------------------
   Studio6's principles row: each word hovers to its own colour. Ours are
   the brand values. Colour on hover only — the word itself stays Bone, so
   no accent is ever carrying text.                                        */
.values { display: grid; gap: 0; margin-top: var(--sp-4); }
.value {
  position: relative; display: flex; align-items: baseline; gap: var(--sp-2);
  padding: clamp(18px, 2.4vw, 30px) 0;
  border-top: 1px solid var(--rule);
  transition: padding-left var(--dur) var(--ease);
}
.value:last-child { border-bottom: 1px solid var(--rule); }
.value::before {
  content: ""; position: absolute; left: 0; top: 0; bottom: 0;
  width: 3px; background: var(--value-c, var(--accent));
  transform: scaleY(0); transform-origin: top;
  transition: transform var(--dur) var(--ease);
}
.value:hover::before { transform: scaleY(1); }
.value:hover { padding-left: 18px; }
.value h3 { font-family: var(--display); font-weight: 400;
            font-size: clamp(24px, 3.4vw, 44px); line-height: 1;
            /* fixed basis, not auto: with `auto` each name sets its own width
               and the paragraphs never line up down the column */
            flex: 0 0 clamp(170px, 24vw, 330px); }
.value p { color: var(--ink-dim); font-size: var(--t-small); max-width: 52ch; }
@media (max-width: 680px) {
  .value { flex-direction: column; gap: 8px; }
}

/* ---- bento --------------------------------------------------------------
   Studio6's move: flat colour tiles and image slots share one grid, so a
   page with no photography still reads as designed rather than as gaps.  */
.bento { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--sp-2); margin-top: var(--sp-4); }
.bento > * { grid-column: span 2; }
.bento .tile {
  display: flex; flex-direction: column; justify-content: flex-end;
  padding: var(--sp-3); border-radius: var(--r-card);
  background: var(--ground-deep); aspect-ratio: 16 / 9;
}
.bento .tile .caps { color: var(--ink-faint); margin-bottom: 8px; }
.bento .tile h3 { font-family: var(--display); font-weight: 400;
                  font-size: clamp(22px, 2.6vw, 34px); line-height: 1; }
@media (max-width: 760px) { .bento { grid-template-columns: 1fr; } .bento > * { grid-column: 1; } }

/* ---- membership --------------------------------------------------------- */
.includes { list-style: none; padding: 0; margin-top: var(--sp-3);
            display: grid; grid-template-columns: repeat(2, 1fr); gap: 0 var(--sp-3); }
.includes li { padding: 12px 0 12px 26px; border-top: 1px solid var(--rule); position: relative; }
.includes li::before {
  content: ""; position: absolute; left: 0; top: 19px;
  width: 10px; height: 2px; background: var(--accent);
}
@media (max-width: 680px) { .includes { grid-template-columns: 1fr; } }

/* ---- find us ------------------------------------------------------------ */
.find { display: grid; grid-template-columns: .9fr 1.1fr; gap: var(--sp-4); align-items: start; }
@media (max-width: 860px) { .find { grid-template-columns: 1fr; } }
.find address { font-style: normal; color: var(--ink-dim); margin-bottom: var(--sp-2); }
/* No map embed. The OpenStreetMap iframe needs WebGL and falls back to a
   bright cyan error panel when it is missing — off-brand and broken-looking
   on exactly the low-end phones most likely to see it. A third-party frame
   also drags in a privacy notice for no real gain. This panel is built from
   the brand instead: it cannot fail, costs nothing to load, and the button
   hands off to whichever map app the visitor actually uses. */
.find .locate {
  position: relative; overflow: hidden;
  border-radius: var(--r-card);
  background: var(--evergreen-500);
  color: var(--bone);
  padding: var(--sp-3);
  display: flex; flex-direction: column; gap: var(--sp-2);
  min-height: 340px; isolation: isolate;
}
.find .locate > * { position: relative; z-index: 1; }
.find .locate::before {
  content: ""; position: absolute; inset: -10%;
  background: url("../assets/pattern-hide.svg") 32% 42% / 380% auto no-repeat;
  opacity: .05; z-index: 0;
}
.find .locate .what3words { color: rgba(251,247,239,.72); font-size: var(--t-small); }
.find .locate .rows { display: grid; gap: 0; margin-top: auto; }
.find .locate .row {
  display: flex; gap: var(--sp-2); justify-content: space-between;
  padding: 11px 0; border-top: 1px solid rgba(251,247,239,.16);
  font-size: var(--t-small);
}
.find .locate .row span:first-child { color: rgba(251,247,239,.55); }

/* ---- close -------------------------------------------------------------- */
.close { text-align: center; }
.close .head { max-width: 16ch; margin: 0 auto var(--sp-3); text-wrap: balance; }

/* ---- footer -------------------------------------------------------------
   Lassie's footer. A Bone card that carries straight on from the last
   section, its two lower corners rounded over Evergreen. Small faint labels,
   links in Evergreen, two columns on phones; then the mark and a two-line
   sign-off. Type follows guidelines 2.5/2.6: group labels are the small
   all-caps titles (the only caps the brand allows), links are Spectral as
   sub-heads, and the sign-off is Hanken body at about 60% of the link size.
   The inner column matches .return-close (760px). */
.site-footer { background: var(--evergreen-500); }
.foot-card {
  background: var(--bone); color: var(--evergreen-500);
  border-radius: 0 0 24px 24px;
  padding: 40px var(--gut) 30px;
}
.foot-in { max-width: 760px; margin-inline: auto; }
.foot-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 0 24px; }
.foot-group + .foot-group { margin-top: 28px; }
.site-footer h2 {
  margin: 0 0 14px; font: 500 11px/1.2 var(--body); letter-spacing: .2em;
  text-transform: uppercase; color: rgba(1, 43, 33, .72);
}
.site-footer ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.site-footer li { line-height: 1.2; }
.site-footer a { font: 400 22px/1.2 var(--sub); letter-spacing: -.02em; color: var(--evergreen-500); text-decoration: none; }
.site-footer a:hover { text-decoration: underline; text-underline-offset: 3px; }
.site-footer a:focus-visible { outline: 2px solid var(--evergreen-500); outline-offset: 3px; border-radius: 2px; }
.foot-base { display: flex; align-items: center; gap: 18px; margin-top: 84px; }
.foot-base img { width: 32px; height: auto; flex: none; }
.foot-base p {
  margin: 0; font: 400 13px/1.4 var(--body);
  color: var(--evergreen-500);
}
/* The studio credit: pushed to the right of the copyright line on desktop,
   dropping to its own line on phones. Same small body type as the address. */
.foot-base { flex-wrap: wrap; }
.site-footer a.foot-credit {
  margin-left: auto; font: 400 13px/1.4 var(--body); letter-spacing: 0;
  color: #000;
}
/* hiihop lockup, Brand Pack v3 (30 Sep 2026): five-bead mark beside the
   "hiihop" wordmark (Space Grotesk 600, outlined), all in black here with
   the "Built by" text. The arrow after it says it's a link out. On hover
   the beads hop, smallest first, and the arrow nudges up and right. */
.site-footer a.foot-credit { display: inline-flex; align-items: center; gap: 7px; }
.site-footer a.foot-credit:hover { color: #000; text-decoration: none; }
.site-footer a.foot-credit:hover span { text-decoration: underline; text-underline-offset: 3px; }
.hh-logo { height: 22px; width: auto; aspect-ratio: 400 / 94; overflow: visible; }
.hh-dot { transform-box: fill-box; transform-origin: center; }
.foot-credit:hover .hh-dot { animation: hh-hop .5s cubic-bezier(.3, 0, .3, 1) calc(var(--i) * 60ms); }
@keyframes hh-hop { 40% { transform: translateY(-30%); } }
.hh-arrow { width: 11px; height: 11px; flex: none; margin-left: -1px; transition: transform .2s cubic-bezier(.3, 0, .3, 1); }
.foot-credit:hover .hh-arrow { transform: translate(2px, -2px); }
@media (prefers-reduced-motion: reduce) { .foot-credit:hover .hh-dot { animation: none; } .foot-credit:hover .hh-arrow { transform: none; } }
@media (max-width: 760px) {
  .site-footer a.foot-credit { flex-basis: 100%; margin-left: 50px; }
}
/* The reveal (Lassie's big wordmark under the footer). The logotype is
   position: fixed to the bottom of the screen, and its box's clip-path
   shows it only while that box is on screen, so the card appears to lift
   up off it. */
.foot-card { position: relative; z-index: 1; }
.foot-reveal {
  --lw: min(100vw - 2 * var(--gut), 1320px);
  --pad: 40px;
  position: relative; height: calc(var(--lw) * 103 / 364 + 2 * var(--pad));
  clip-path: inset(0);
}
.foot-reveal-in {
  position: fixed; left: 0; right: 0; bottom: 0;
  height: calc(var(--lw) * 103 / 364 + 2 * var(--pad));
  display: flex; align-items: center; justify-content: center;
}
.foot-reveal img { width: var(--lw); height: auto; display: block; }
@media (min-width: 761px) {
  .foot-card { padding: 64px var(--gut) 40px; border-radius: 0 0 32px 32px; }
  .foot-cols { grid-template-columns: repeat(4, 1fr); }
  .foot-col { display: contents; }
  .foot-group + .foot-group { margin-top: 0; }
  .foot-base { margin-top: 120px; }
  .site-footer a { font-size: 24px; }
  .foot-base p { font-size: 14px; }
  .site-footer a.foot-credit { font-size: 14px; }
  .foot-reveal { --pad: 72px; }
}

/* ---- join page ---------------------------------------------------------- */
.join-intro { max-width: 60ch; }
.join-steps { list-style: none; padding: 0; margin: var(--sp-3) 0 0;
              display: grid; gap: 12px; }
.join-steps li { padding-left: 28px; position: relative; color: var(--ink-dim); }
.join-steps li::before { content: ""; position: absolute; left: 0; top: .6em;
                          width: 12px; height: 2px; background: var(--accent); }

/* The widget box reserves its height so the third-party iframe cannot
   shift the page when it loads. CLS risk lives here and nowhere else. */
.widget-host {
  margin-top: var(--sp-4); min-height: 700px;
  border-radius: var(--r-card); background: var(--ground-deep);
  padding: var(--sp-2); position: relative;
}
.widget-skeleton {
  position: absolute; inset: var(--sp-2);
  border-radius: 10px;
  background: linear-gradient(-20deg,
              rgba(251,247,239,.05) 10%,
              rgba(251,247,239,.02) 70%,
              rgba(251,247,239,.05) 100%);
  background-size: 400% 400%;
  animation: shimmer 1.4s var(--ease) infinite alternate;
}
@keyframes shimmer { to { background-position: 0 100%; } }
/* The GymOS form, written straight into the page. It sits above the
   skeleton so it covers it as soon as it paints. 600px is the height
   GymOS's own loader gave it; the form's height message resizes it. */
.gymos-frame {
  position: relative; z-index: 1; display: block;
  width: 100%; min-width: 300px; height: 600px; border: 0;
}

.fallback {
  margin-top: var(--sp-3); padding: var(--sp-3);
  border: 1px solid var(--rule); border-radius: var(--r-card);
}
.fallback[hidden] { display: none; }

/* ---- prose (about, privacy) --------------------------------------------- */
.prose { max-width: var(--measure); }
.prose p + p { margin-top: 1.1em; }
.prose h2 { font-family: var(--display); font-weight: 400;
            font-size: clamp(24px, 3vw, 38px); line-height: 1.05;
            margin: var(--sp-4) 0 var(--sp-2); }
.prose h3 { font-family: var(--sub); font-weight: 400; font-size: var(--t-sub);
            letter-spacing: var(--ls-sub); margin: var(--sp-3) 0 10px; }
.prose ul { padding-left: 20px; margin-top: 1em; color: var(--ink-dim); }
.prose li { margin-bottom: 8px; }

.split { display: grid; grid-template-columns: 1fr .8fr; gap: var(--sp-4); align-items: start; }
@media (max-width: 860px) { .split { grid-template-columns: 1fr; } }

/* ---- entrances -----------------------------------------------------------
   Scoped to .js deliberately. If these were hidden unconditionally, then
   with scripting off every headline on the site would be invisible forever.
   The `js` class is set by an inline script in <head>, so there is no flash
   of un-hidden content either. */
.js .rise { opacity: 0; transform: translateY(18px);
            transition: opacity .7s var(--ease), transform .7s var(--ease); }
.js .rise.in { opacity: 1; transform: none; }

/* ---- curtain -------------------------------------------------------------
   Phive's page transition: two panels scaleY from zero with a hairline
   between them. Three pages, and it makes them feel like one thing.      */
.curtain {
  position: fixed; inset: 0; z-index: var(--z-curtain);
  display: flex; flex-direction: column; pointer-events: none;
}
.curtain .panel { flex: 1; background: var(--ground-dark); transform: scaleY(0); }
.curtain .panel.t { transform-origin: top; }
.curtain .panel.b { transform-origin: bottom; }
.curtain .hair { height: 1px; background: var(--accent); transform: scaleX(0); }
.curtain.out .panel { transform: scaleY(1); transition: transform .45s var(--ease-out); }
.curtain.out .hair  { transform: scaleX(1); transition: transform .45s var(--ease-out); }

/* ==========================================================================
   Reduced motion.
   Verified, not assumed: no marquee, no entrances, no curtain, and the
   sticky stack becomes plain stacked blocks that scroll normally.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .marquee-track { animation: none; transform: none; }
  .js .rise { opacity: 1; transform: none; }
  .curtain { display: none; }
  .stack-card {
    position: static;
    min-height: auto;
    padding-block: var(--sp-5);
  }
  .widget-skeleton { animation: none; }
}

/* ==========================================================================
   Trial modal — the GymOS campaign form, opened from any CTA.

   Matches the Studio6 pattern: the form arrives over the page rather than
   navigating away, so the CTA costs nothing. /join still exists as a real
   URL for Google Business Profile, ads and the Instagram bio — both use
   the same GymOS embed, and the modal is progressive enhancement, so with
   scripting off every CTA is a plain link to /join.
   ========================================================================== */
.trial-modal {
  position: fixed; inset: 0; z-index: 120;
  display: none; align-items: flex-start; justify-content: center;
  padding: clamp(12px, 4vh, 56px) var(--gut);
  overflow-y: auto; overscroll-behavior: contain;
}
.trial-modal[open], .trial-modal.is-open { display: flex; }

.trial-modal .veil {
  position: fixed; inset: 0;
  background: rgba(0, 12, 9, .82);
  cursor: pointer;
}
@supports (backdrop-filter: blur(6px)) {
  .trial-modal .veil { backdrop-filter: blur(6px); }
}

.trial-modal .panel {
  position: relative;
  width: min(760px, 100%);
  margin: auto;
  background: var(--evergreen-500);
  border: 1px solid var(--rule);
  border-radius: var(--r-card);
  padding: clamp(24px, 3.4vw, 44px);
  isolation: isolate; overflow: hidden;
}
.trial-modal .panel::before {
  content: ""; position: absolute; inset: -10%;
  background: url("../assets/pattern-hide.svg") 32% 42% / 380% auto no-repeat;
  opacity: .025; z-index: 0;   /* quieter than a section: a form is here */
}
.trial-modal .panel > * { position: relative; z-index: 1; }

.trial-modal h2 {
  font-family: var(--display); font-weight: 400;
  font-size: clamp(26px, 3.4vw, 40px); line-height: .98;
  color: var(--ink); margin-bottom: 10px; max-width: 16ch;
}
.trial-modal .intro { color: var(--ink-dim); margin-bottom: var(--sp-2); }

.trial-modal .close {
  position: absolute; top: 12px; right: 12px; z-index: 2;
  width: 44px; height: 44px;            /* 44px hit area, not a 16px × */
  display: grid; place-items: center;
  background: transparent; border: 1px solid var(--rule);
  border-radius: 50%; color: var(--ink); cursor: pointer;
  font-size: 18px; line-height: 1;
  transition: border-color var(--dur-fast) var(--ease);
}
.trial-modal .close:hover { border-color: var(--ink); }

/* Reserve the height so the iframe cannot shift the panel as it loads. */
.trial-modal .host { min-height: 620px; position: relative; }

@media (max-width: 560px) {
  .trial-modal { padding: 0; }
  .trial-modal .panel { border-radius: 0; min-height: 100%; border: 0; }
}

body.modal-open { overflow: hidden; }

@media (prefers-reduced-motion: reduce) {
  .trial-modal .panel { animation: none !important; }
}

/* ---- visually hidden ---------------------------------------------------- */
.vh {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}

/* ---- hero film ----------------------------------------------------------
   Phone only. The cut is portrait 9:16 and only suits a phone, so below
   760px it takes the whole fold and the header floats over it. Above that
   the type-only hero stands untouched.                                    */
.hero-media   { display: none; }
.mark-outline { display: none; }
.fold-sentinel{ display: none; }
.burger      { display: none; }
.menu        { display: none; }
.cta-short   { display: none; }

@media (max-width: 760px) {

  /* ---- every page: the nav collapses to a hamburger ------------------- */
  .site-header nav  { display: none; }
  .site-header .bar { padding-right: var(--gut); align-items: center; }
  /* The claw. Same width as the mark opposite it and on the same centre
     line, so the two sit parallel across the bar. The tap target is padded
     out to 44px min without changing the drawn size.                     */
  .burger {
    display: flex; align-items: center; justify-content: flex-end;
    width: var(--fold-mark-w); min-height: 44px;
    padding: 0; margin-left: auto;
    background: none; border: 0; cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  /* ---- the claw, cut into the screen ----------------------------------
     Two copies of each slash inside one clip. The GOUGE sits underneath,
     dark and offset down-right and softened — the shadow inside the cut.
     The EDGE sits on top in bone — the lit lip of the gouge. Together
     they read as a scratch through the surface rather than a mark on it.
     Each slash is then wiped in by its own clip rect, staggered, fast in
     and hard out, so it rakes rather than fades.                        */
  .burger .claw {
    display: block; width: 100%; height: auto; overflow: visible;
    transition: transform var(--dur) var(--ease);
  }
  /* The claw is not painted on — it is cut through. The span carries a
     backdrop-filter that inverts whatever sits behind it, then the claw
     artwork masks that down to three slashes. Unlike mix-blend-mode, a
     backdrop-filter is not trapped by the fixed header's stacking
     context, so the slashes really do pick up the film and the sections
     scrolling under them, and change as they pass.                     */
  .burger .claw {
    /* the supplied scratch artwork is wide and short — match its ratio
       so the inverted backdrop is cut exactly to the marks */
    display: block; width: 100%; aspect-ratio: 2.7427;
    /* invert, then bias light and push contrast: a straight inversion
       turns mid-tones back into mid-tones, which made the claw vanish
       over the grey-green sky. The drop-shadow below guarantees an edge
       whatever the backdrop does.                                      */
    backdrop-filter: grayscale(1) invert(1) contrast(1.45) brightness(1.3);
    -webkit-backdrop-filter: grayscale(1) invert(1) contrast(1.45) brightness(1.3);
    filter: drop-shadow(0 1px 1.5px rgba(0, 12, 9, .55));
    -webkit-mask: url("../assets/claw-menu.svg") center / contain no-repeat;
            mask: url("../assets/claw-menu.svg") center / contain no-repeat;
    transition: transform var(--dur) var(--ease);
  }

  /* No backdrop-filter (older Safari, Firefox default): paint it bone so
     the control is never invisible. */
  @supports not ((backdrop-filter: invert(1)) or (-webkit-backdrop-filter: invert(1))) {
    .burger .claw { background: var(--ink); }
  }

  /* the rake — one sweep left to right, revealing all three */
  .burger .claw.rake {
    animation: claw-rake 300ms cubic-bezier(.16, .84, .32, 1) forwards;
  }
  @keyframes claw-rake {
    from { clip-path: inset(0 100% 0 0); }
    to   { clip-path: inset(0 0 0 0); }
  }

  .burger[aria-expanded="true"] .claw { transform: rotate(90deg); }

  html.menu-open, html.menu-open body { overflow: hidden; }

  /* ---- the nav pill (every page) -------------------------------------
     Lassie-style: one frosted capsule, centred, holding two bone pills —
     the mark (home) and Menu. The header itself goes transparent, so the
     film and the sections scroll under it. It keeps its sticky place in
     the flow on inner pages; on the home fold it floats over the film.
     NB the mark here is 26px — below the 84px minimum (guideline 1.1). */
  .site-header {
    display: flex; justify-content: center;
    background: transparent; border-bottom: 0;
    backdrop-filter: none; -webkit-backdrop-filter: none;
    padding-top: calc(14px + env(safe-area-inset-top, 0px));
    pointer-events: none;                 /* only the pill takes taps */
  }
  .site-header .bar {
    width: auto; min-height: 0;
    display: flex; align-items: center; gap: 4px;
    padding: 4px;
    border-radius: 999px;
    background: rgba(251, 247, 239, .18);
    backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
    /* the drop shadow keeps the pill's edge over the Bone sections */
    box-shadow: inset 0 0 0 1px rgba(251, 247, 239, .22), 0 6px 20px rgba(0, 21, 16, .22);
    pointer-events: auto;
  }
  .site-header .brand,
  .site-header .burger {
    display: flex; align-items: center; justify-content: center;
    height: 44px; min-height: 44px; margin: 0;
    padding-inline: 16px;
    border-radius: 999px;
    background: var(--bone); color: var(--ground);
    -webkit-tap-highlight-color: transparent;
  }
  .site-header .brand { position: static; }
  .site-header .brand img { display: none; }
  /* the mark, recoloured Evergreen by masking the bone artwork */
  .site-header .brand::before {
    content: ""; display: block;
    width: 26px; height: calc(26px * 541 / 509);
    background: var(--ground);
    -webkit-mask: url("../assets/logomark-bone.svg") center / contain no-repeat;
            mask: url("../assets/logomark-bone.svg") center / contain no-repeat;
  }
  .site-header .burger { width: auto; border: 0; font: 500 15px/1 var(--body); }
  .site-header .burger .claw { display: none; }
  .site-header .burger .burger-label { position: static; width: auto; height: auto;
                                       clip-path: none; overflow: visible; margin: 0; }
  .site-header .brand:focus-visible,
  .site-header .burger:focus-visible { outline: 2px solid var(--bone); outline-offset: 3px; }

  body[data-page="home"] .site-header { position: fixed; inset: 0 0 auto 0; }

  /* ---- the fold itself ------------------------------------------------- */
  body[data-page="home"] .hero {
    display: flex; align-items: flex-end;
    min-height: 100svh;
    padding-block: 0 calc(var(--gut) * 1.6);
  }
  body[data-page="home"] .hero .hide,
  body[data-page="home"] .hero .eyebrow,
  body[data-page="home"] .hero .terms,
  body[data-page="home"] .hero .stamp,
  body[data-page="home"] .hero .link-quiet { display: none; }
  /* Lassie-style fold: the headline alone, dead centre on the film. The
     trial button lives in the header and straight after the fold. */
  body[data-page="home"] .hero { align-items: center; justify-content: center;
                                 text-align: center; padding-block: 0; }
  body[data-page="home"] .hero .wrap { padding-bottom: 0; }
  body[data-page="home"] .hero .hero-head { font-size: 7.9vw; margin-inline: auto;
                                             text-shadow: 0 2px 24px rgba(0, 21, 16, .35); }
  /* the one-line pitch sits under the headline, as on Lassie */
  /* Lassie spacing: a wide gap under the headline, then the pitch line
     and the ticker held close together as one caption. */
  body[data-page="home"] .hero .sub { margin: 36px auto 0;
                                      font: 400 var(--t-small)/1.4 var(--body); letter-spacing: .01em;
                                      white-space: nowrap; color: var(--ink);
                                      text-shadow: 0 1px 12px rgba(0, 21, 16, .45); }
  body[data-page="home"] .hero .btn-row { display: none; }
  body[data-page="home"] .cta-full  { display: none; }
  body[data-page="home"] .cta-short { display: inline; }

  .fold-sentinel {
    display: block;                    /* a display:none element never intersects */
    position: absolute; left: 0; bottom: 2px;
    width: 1px; height: 2px; pointer-events: none;
  }

  .hero-media {
    display: block; position: absolute; inset: 0;
    z-index: var(--z-pattern); overflow: hidden;
  }
  .hero-video { width: 100%; height: 100%; object-fit: cover; display: block; }
  .hero-scrim {
    position: absolute; inset: 0;
    background: linear-gradient(180deg,
      rgba(1, 43, 33, var(--hero-scrim-top))      0%,
      rgba(1, 43, 33, var(--hero-scrim-top-fade)) 18%,
      rgba(1, 43, 33, 0)                          38%,
      rgba(1, 43, 33, var(--hero-scrim-mid))      60%,
      rgba(1, 43, 33, var(--hero-scrim-bottom))  100%);
  }
  /* centred type: a soft pool behind the headline band on top of the ramp */
  body[data-page="home"] .hero-scrim {
    background:
      radial-gradient(120% 38% at 50% 50%, rgba(0, 21, 16, .42), transparent 70%),
      linear-gradient(180deg,
        rgba(1, 43, 33, var(--hero-scrim-top))      0%,
        rgba(1, 43, 33, var(--hero-scrim-top-fade)) 18%,
        rgba(1, 43, 33, .12)                        40%,
        rgba(1, 43, 33, .12)                        70%,
        rgba(1, 43, 33, .4)                        100%);
  }
}

/* Reduced motion: hold the poster frame, never play. */
@media (max-width: 760px) and (prefers-reduced-motion: reduce) {
  .hero-video { display: none; }
  .hero-media { background: url("/media/hero-poster.webp") center / cover no-repeat; }
}

@media (prefers-reduced-motion: reduce) {
  .burger .claw.rake { animation: none; clip-path: none; }
}

/* ---- benefit ticker -----------------------------------------------------
   Four one-line benefits rolling through a one-line slot (js/site.js):
   the next line rises in from below as the current one rises out of the
   top, both clipped by the slot. The Lassie move — 1s, expo-out.
   Deliberately quiet: slightly transparent, no box.                      */
.ticker {
  position: relative; list-style: none; margin: var(--sp-2) 0 0; padding: 0;
  height: 32px; overflow: hidden;
}
.ticker li {
  position: absolute; inset: 0 auto auto 0; height: 32px;
  display: flex; align-items: center; gap: 10px; white-space: nowrap;
  font: 400 var(--t-small)/32px var(--body); letter-spacing: .01em;
  color: var(--ink); opacity: 0; transform: translateY(100%);
  transition: transform 1s cubic-bezier(.16, 1, .3, 1),
              opacity   1s cubic-bezier(.16, 1, .3, 1);
}
.ticker li.on  { opacity: .8; transform: translateY(0); }
.ticker li.out { opacity: .8; transform: translateY(-100%); }
.ticker li.snap { transition: none; }   /* reset below the slot, unseen */
.ticker svg { width: 18px; height: 18px; flex: none; }

@media (max-width: 760px) {
  /* centred under the pitch line, as on the Lassie fold */
  body[data-page="home"] .hero .ticker { margin: 4px auto 0; width: 100%; }
  body[data-page="home"] .hero .ticker li { right: 0; justify-content: center;
                                            text-shadow: 0 1px 12px rgba(0, 21, 16, .45); }
}

/* Reduced motion: no roll. The first line holds. */
@media (prefers-reduced-motion: reduce) {
  .ticker li { transition: none; }
}

/* ---- hero bar -----------------------------------------------------------
   Phone only. A frosted strip at the foot of the film, in the same glass
   as the nav pill: a short line on the left, one bone button on the right.
   Opens the GymOS form like every other data-trial link.                 */
.hero-bar { display: none; }
@media (max-width: 760px) {
  body[data-page="home"] .hero-bar {
    position: absolute; z-index: var(--z-content);
    left: 50%; transform: translateX(-50%);
    bottom: calc(var(--gut) + env(safe-area-inset-bottom, 0px));
    width: min(calc(100% - var(--gut) * 2), 420px);
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    padding: 6px 6px 6px 18px;
    border-radius: 16px;
    background: rgba(251, 247, 239, .18);
    backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
    box-shadow: inset 0 0 0 1px rgba(251, 247, 239, .22), 0 6px 20px rgba(0, 21, 16, .22);
  }
  .hero-bar-note { font: 400 15px/1.2 var(--body); color: var(--ink-dim); }
  .hero-bar-btn {
    display: inline-flex; align-items: center; justify-content: center;
    min-height: 44px; padding: 0 20px;
    border-radius: 11px;
    background: var(--bone); color: var(--ground);
    font: 500 15px/1 var(--body); text-decoration: none;
    -webkit-tap-highlight-color: transparent;
    transition: transform var(--dur-fast) var(--ease);
  }
  .hero-bar-btn:active { transform: scale(.97); }
  .hero-bar-btn:focus-visible { outline: 2px solid var(--bone); outline-offset: 3px; }
}

/* ---- phone menu: the square opens into a card ---------------------------
   Lassie's menu in Feral colours. Closed, it is one frosted Evergreen
   square holding the Bone mark, centred at the top. Open, the square widens
   to the screen (js/site.js pins the width) and a Bone card grows down
   inside its frosted edge: the mark top left, "Close" top right,
   Young Serif links, a rule, Instagram, one Sun button with black ink.
   The whole top row is the toggle, so the mark never jumps.              */
@media (max-width: 760px) {
  /* the header keeps its height, so the card opens over the page instead
     of pushing it down on the inner pages */
  .site-header { height: calc(72px + env(safe-area-inset-top, 0px)); align-items: flex-start; }

  .site-header .bar {
    position: relative; flex-wrap: wrap; gap: 0;
    padding: 4px;
    border-radius: 18px;
    /* Evergreen glass: the Bone mark reads over the film AND the Bone sections */
    background: rgba(1, 43, 33, .58);
    backdrop-filter: blur(16px) saturate(1.2); -webkit-backdrop-filter: blur(16px) saturate(1.2);
    box-shadow: inset 0 0 0 1px rgba(251, 247, 239, .2), 0 6px 20px rgba(0, 21, 16, .22);
    transition: width .5s cubic-bezier(.85, .05, .09, .91) .22s,
                border-radius .3s ease .3s;
  }
  html.menu-open .site-header .bar {
    border-radius: 26px;
    transition: width .5s cubic-bezier(.85, .05, .09, .91), border-radius .3s ease;
  }

  /* the Bone card, inset inside the frosted edge */
  .site-header .bar::before {
    content: ""; position: absolute; inset: 4px; border-radius: 22px;
    background: var(--bone); opacity: 0;
    transition: opacity .2s ease .3s;
  }
  html.menu-open .site-header .bar::before { opacity: 1; transition-delay: 0s; }

  /* Home lives in the menu list; the mark in the square stands for it */
  .site-header .brand { display: none; }

  /* ---- the toggle: a 48px square closed, the card's top row open ---- */
  .site-header .burger {
    position: relative; z-index: 1;
    flex: 1 1 auto; justify-content: space-between;
    width: auto; min-width: 48px; height: 48px; min-height: 48px;
    margin: 0; padding: 0 11px;
    background: transparent; border-radius: 14px;
    font: 500 15px/1 var(--body); color: var(--ground);
    transition: padding .3s ease .3s;
  }
  html.menu-open .site-header .burger { padding: 0 16px; transition-delay: 0s; }
  .site-header .burger:focus-visible { outline: 2px solid var(--bone); outline-offset: 2px; }
  html.menu-open .site-header .burger:focus-visible { outline-color: var(--ground); outline-offset: -2px; }

  .burger-id { display: flex; align-items: center; }
  .burger-id i { display: block; flex: none; }
  .burger-mark {
    width: 26px; height: calc(26px * 541 / 509);
    background: var(--bone);
    -webkit-mask: url("../assets/logomark-bone.svg") center / contain no-repeat;
            mask: url("../assets/logomark-bone.svg") center / contain no-repeat;
    transition: background-color .2s ease .3s;
  }
  .site-header .burger .burger-label {
    position: static; width: auto; height: auto; clip-path: none; overflow: visible; margin: 0;
    opacity: 0; transition: opacity .15s ease;
  }
  html.menu-open .burger-mark { background: var(--ground); transition-delay: 0s; }
  html.menu-open .site-header .burger .burger-label { opacity: 1; transition: opacity .3s ease .35s; }
  /* closed, the label takes no room so the mark sits dead centre */
  html:not(.menu-open) .site-header .burger .burger-label { position: absolute; }
  html:not(.menu-open) .site-header .burger { justify-content: center; }

  /* ---- the list ---------------------------------------------------------- */
  .site-header .menu {
    display: grid; grid-template-rows: 0fr;
    position: relative; z-index: 1;
    flex: 0 0 100%; min-width: 0; contain: inline-size;
    visibility: hidden;
    transition: grid-template-rows .26s cubic-bezier(.65, 0, .35, 1),
                visibility 0s linear .26s;
  }
  html.menu-open .site-header .menu {
    grid-template-rows: 1fr; visibility: visible;
    transition: grid-template-rows .45s cubic-bezier(.16, 1, .3, 1) .42s,
                visibility 0s;
  }
  .site-header .menu-inner {
    overflow: hidden; min-height: 0;
    display: flex; flex-direction: column;
    padding: 0 16px;
  }
  .site-header .menu-inner > :first-child { margin-top: 56px; }
  .site-header .menu a:not(.btn) {
    font: 400 clamp(34px, 10vw, 44px)/1.18 var(--display);
    color: var(--ground); text-decoration: none;
  }
  .site-header .menu a[aria-current="page"] { opacity: .45; }
  .site-header .menu .menu-2 {
    margin-top: 20px; padding-top: 20px;
    border-top: 1px solid rgba(1, 43, 33, .12);
  }
  .site-header .menu .btn {
    width: 100%; min-height: 54px; margin: 26px 0 12px;
    padding-inline: 16px; border-radius: 14px;
    font-size: var(--t-caps);
  }
  .site-header .menu a:focus-visible { outline: 2px solid var(--ground); outline-offset: 3px; }
}

@media (max-width: 760px) and (prefers-reduced-motion: reduce) {
  .site-header .bar, .site-header .bar::before, .site-header .menu,
  .site-header .burger, .burger-mark, .site-header .burger .burger-label,
  html.menu-open .site-header .bar, html.menu-open .site-header .bar::before,
  html.menu-open .site-header .menu,
  html.menu-open .site-header .burger .burger-label { transition: none; }
}

/* ---- film card: the room ------------------------------------------------
   Lassie's second film. It rises in from below and grows to size as it
   comes up the screen, then holds with the ground showing round it: a
   padded, rounded frame, not full bleed. js/site.js sets --in from 0 (card
   top at the bottom of the screen) to 1 (card settled). Portrait on phones,
   16:9 above 760px.                                                       */
.film-card {
  --in: 0;
  position: relative;
  background: var(--surface, var(--ground));
  padding: 0 12px 12px;
  overflow: hidden;              /* the scaled-down start never spills */
}
.film-frame {
  position: relative; overflow: hidden;
  width: 100%;
  aspect-ratio: 9 / 16;
  max-height: calc(100svh - 24px);
  margin-inline: auto;
  border-radius: 24px;
  background: var(--ground-dark);
  /* start 10% smaller and 14% of its height lower; land flat */
  transform: translate3d(0, calc((1 - var(--in)) * 14%), 0)
             scale(calc(.9 + var(--in) * .1));
  transform-origin: 50% 0;
  will-change: transform;
}
.film-video { width: 100%; height: 100%; object-fit: cover; }

@media (min-width: 761px) {
  .film-card  { padding: 0 var(--gut) var(--gut); }
  .film-frame { aspect-ratio: 16 / 9; max-height: calc(100vh - var(--gut) * 2); }
}

@media (prefers-reduced-motion: reduce) {
  .film-frame { transform: none; will-change: auto; }
}

/* ---- hero shrink ----------------------------------------------------------
   Phone only (the film only shows below 760px). As you scroll off the fold
   the film pulls in off the sides and bottom and its lower corners round,
   so it lands as a card on the same ground as the statement below it.
   js/site.js sets --out from 0 (at rest) to 1 (hero scrolled away).       */
@media (max-width: 760px) {
  body[data-page="home"] .hero { --out: 0; background: var(--ground-deep); }
  body[data-page="home"] .hero-media {
    clip-path: inset(0 calc(var(--out) * 12px) calc(var(--out) * 12px)
                     round 0 0 calc(var(--out) * 24px) calc(var(--out) * 24px));
  }
}
@media (max-width: 760px) and (prefers-reduced-motion: reduce) {
  body[data-page="home"] .hero-media { clip-path: none; }
}

/* ---- statement mark --------------------------------------------------------
   The logomark on its own, bigger than the 84px minimum: Lassie's move,
   the mark as the whole of the beat above one short line.              */
.statement .mark { width: 88px; opacity: 1; margin-bottom: 64px; }
@media (min-width: 761px) { .statement .mark { width: 108px; margin-bottom: 114px; } }

/* ---- statement: phone spacing ---------------------------------------------
   Matched to the reference: a long quiet run in, a 92px mark, the line at
   30px, and a longer run out before the film card (whose own rise adds
   roughly another 70px of ground under the text as it comes up).        */
@media (max-width: 760px) {
  .statement { padding-block: 150px 40px; }
  .statement .mark { width: 76px; margin-bottom: 90px; }
  .statement .statement-pitch { font-size: 30px; line-height: 1.2; max-width: 11em; }
}

/* ---- statement: mark reveal ------------------------------------------------
   The mark draws itself: a hairline traces the whole outline (pathLength=1,
   so the dash maths is 0 to 1), then the Bone fill comes up inside it and
   the line fades. Starts when .rise gets .in (same IntersectionObserver).  */
.statement .mark-draw { display: block; overflow: visible; }
.statement .mark-draw .mark-solid, .statement .mark-draw .mark-stroke path { fill: var(--bone); }
.statement .mark-draw .mark-stroke { opacity: 0; }   /* no JS: solid only */
.statement .mark-draw .mark-trace { fill: none; stroke: #fff; stroke-width: 46; stroke-linecap: round; stroke-linejoin: round; }
.js .statement .mark-draw.rise { opacity: 1; transform: none; filter: none; transition: none; }
.js .statement .mark-draw.rise .mark-stroke { opacity: 1; }
.js .statement .mark-draw.rise .mark-solid { fill-opacity: 0; }
/* the trace itself is SMIL (inline script by the svg); then the solid fills
   over the stroke variant and the stroke variant fades */
.js .statement .mark-draw.rise.in .mark-solid   { animation: mark-fill 1s cubic-bezier(.22, 1, .36, 1) 2.1s both; }
.js .statement .mark-draw.rise.in .mark-stroke { animation: mark-line-out .8s ease 2.6s both; }
@keyframes mark-fill     { to { fill-opacity: 1; } }
@keyframes mark-line-out { to { opacity: 0; } }
.js .statement .statement-pitch.rise { transition-delay: .25s; }
@media (prefers-reduced-motion: reduce) {
  .js .statement .mark.rise { opacity: 1; transform: none; filter: none; }
  .js .statement .mark-draw.rise .mark-solid { animation: none; fill-opacity: 1; }
  .js .statement .mark-draw.rise .mark-stroke { display: none; }
}

/* ---- feature card: the programme -------------------------------------------
   Lassie's three-step feature run, card one. Serif head, one line, then a
   motion-blurred still with a Bone panel floating on it. The rows tick
   through when the panel is in view (js/site.js, "tick list"): .run spins
   the ring, .done fills it with a check. Mark colours are graphic only.   */
.feature { padding-block: 72px 96px; }
.feature .wrap { max-width: 720px; margin-inline: auto; }
.feature-head { font: 400 30px/1.15 var(--display); letter-spacing: var(--ls-display); }
.feature-line { margin-top: 12px; color: var(--ink-dim); font-size: 17px; line-height: 1.45; max-width: 34ch; }
.feature-frame {
  position: relative; overflow: hidden;
  margin-top: 32px;
  aspect-ratio: 9 / 16;
  border-radius: 24px;
  background: var(--ground-dark);
  display: grid; grid-template: 1fr / 1fr; place-items: start center;
  padding-top: 16px;
}
.feature-bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* darkens the photo so the panel leads; heaviest where the panel sits */
.feature-scrim {
  position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(0, 21, 16, .55) 0%, rgba(0, 21, 16, .3) 55%, rgba(0, 21, 16, .45) 100%);
}

.feature-panel {
  position: relative;
  grid-area: 1 / 1;              /* one cell: nothing else can push it down */
  width: calc(100% - 40px); max-width: 360px;
  padding: 16px 14px 14px;
  border-radius: 14px;
  background: var(--bone);
  color: var(--evergreen-500);
  font-family: var(--body);
  box-shadow: 0 18px 40px rgba(0, 21, 16, .35);
}
.panel-title { display: flex; align-items: center; gap: 8px; font-size: 14px; font-weight: 500; margin-bottom: 12px; }
.panel-mark {
  width: 16px; height: 17px; flex: 0 0 auto; background: currentColor;
  -webkit-mask: url("../assets/logomark-bone.svg") center / contain no-repeat;
          mask: url("../assets/logomark-bone.svg") center / contain no-repeat;
}
.panel-rows { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.panel-row {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px;
  border-radius: 10px;
  background: #fff;
  border: 1px solid rgba(1, 43, 33, .08);
  font-size: 14px;
  transition: opacity .4s var(--ease);
}
.row-what { flex: 1; }
.row-class {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12px; color: rgba(1, 43, 33, .62);
}
/* each format's solid mark, in its own colour.
   Function uses Sun 600: full Sun on white is too faint to read. */
.row-class::before {
  content: ""; width: 18px; height: 19px; flex: 0 0 auto; background: var(--dot);
  -webkit-mask: url("../assets/logomark-bone.svg") center / contain no-repeat;
          mask: url("../assets/logomark-bone.svg") center / contain no-repeat;
}

/* the ring: dashed while waiting, spinning while running, filled when done */
.tick {
  position: relative; width: 18px; height: 18px; flex: 0 0 auto;
  border-radius: 50%;
  border: 1.5px dashed rgba(1, 43, 33, .35);
  transition: background-color .3s var(--ease), border-color .3s var(--ease);
}
.tick::after {                    /* the check, drawn as two borders */
  content: ""; position: absolute; left: 5.5px; top: 2.5px;
  width: 4px; height: 8px;
  border: solid var(--bone); border-width: 0 1.8px 1.8px 0;
  transform: rotate(45deg) scale(0); transition: transform .35s var(--ease) .05s;
}
.js .panel-row { opacity: .55; }
.js .panel-row.run, .js .panel-row.done { opacity: 1; }
.panel-row.run .tick {
  border: 1.5px solid rgba(1, 43, 33, .15);
  border-top-color: var(--evergreen-500);
  animation: tick-spin .7s linear infinite;
}
.panel-row.done .tick { border: 1.5px solid var(--evergreen-500); background: var(--evergreen-500); animation: none; }
.panel-row.done .tick::after { transform: rotate(45deg) scale(1); }
@keyframes tick-spin { to { transform: rotate(360deg); } }

.panel-foot {
  position: relative;
  margin-top: 12px; padding-top: 10px;
  border-top: 2px solid rgba(1, 43, 33, .1);
  font-size: 12px; color: rgba(1, 43, 33, .62);
}
.panel-foot::before {             /* the bar: fills as the rows tick */
  content: ""; position: absolute; left: 0; right: 0; top: -2px; height: 2px;
  background: var(--evergreen-500);
  transform-origin: 0 50%; transform: scaleX(var(--fill, 1));
  transition: transform .9s var(--ease);
}
.panel-foot span { transition: opacity .5s var(--ease); }
.js .feature-panel { --fill: 0; }
.js .panel-foot span { opacity: 0; }
.js .feature-panel.done .panel-foot span { opacity: 1; }

@media (min-width: 761px) {
  .feature { padding-block: 120px 160px; }
  .feature-head { font-size: 40px; }
  .feature-line { font-size: 19px; }
  .feature .wrap { max-width: 880px; }
  .feature-frame { aspect-ratio: 16 / 10; place-items: center end; padding: 0 40px 0 0; }
  .feature-scrim { background: linear-gradient(90deg, rgba(0, 21, 16, .2) 0%, rgba(0, 21, 16, .35) 45%, rgba(0, 21, 16, .6) 100%); }
  .feature-panel { max-width: 440px; padding: 20px 18px 18px; }
}

/* ---- feature card: the coach -----------------------------------------------
   Card two. The still stays sharp; the panel drops to the foot of the frame
   so the coach's back ("COACH" and the mark) stays clear above it. A soft
   shade under the panel keeps its edge against the black leggings. The
   coach's note has no ring: it slides in as a dark row when its turn comes. */
.feature--coach .feature-frame { aspect-ratio: 3 / 5; place-items: end center; padding-bottom: 20px; }
.feature--coach .feature-bg { object-position: 50% 90%; }
.feature--coach .feature-frame::after {
  content: ""; position: absolute; inset: 50% 0 0;
  background: linear-gradient(to bottom, rgba(0, 21, 16, 0), rgba(0, 21, 16, .55));
  pointer-events: none;
}
.feature--coach .feature-panel { z-index: 1; }
.panel-note {
  align-items: flex-start;
  background: var(--evergreen-500); border-color: transparent;
  color: var(--bone); font-size: 13px; line-height: 1.35;
}
.note-icon {                      /* ⤷ drawn as an L with an arrowhead */
  position: relative; width: 18px; height: 18px; flex: 0 0 auto;
}
.note-icon::before {
  content: ""; position: absolute; left: 4px; top: 2px; width: 9px; height: 8px;
  border: solid currentColor; border-width: 0 0 1.6px 1.6px; border-bottom-left-radius: 3px;
}
.note-icon::after {
  content: ""; position: absolute; left: 10px; top: 6.5px; width: 5px; height: 5px;
  border: solid currentColor; border-width: 1.6px 1.6px 0 0; transform: rotate(45deg);
}
.note-who { display: block; font-size: 11px; opacity: .7; margin-bottom: 2px; }
.row-count { font-size: 12px; color: rgba(1, 43, 33, .62); font-variant-numeric: tabular-nums; }
.js .panel-note { opacity: 0; transform: translateY(6px); transition: opacity .4s var(--ease), transform .4s var(--ease); }
.js .panel-note.run, .js .panel-note.done { opacity: 1; transform: none; }

@media (min-width: 761px) {
  /* panel bottom-left over the member's shorts, so the coach's back stays clear */
  .feature--coach .feature-frame { aspect-ratio: 16 / 10; place-items: end start; padding: 0 0 28px 28px; }
  .feature--coach .feature-bg { object-position: 50% 22%; }
  .feature--coach .feature-frame::after { inset: 0 55% 0 0; background: linear-gradient(to left, rgba(0, 21, 16, 0), rgba(0, 21, 16, .5)); }
  .feature--coach .feature-panel { max-width: 380px; }
}

/* ---- feature card: the club ------------------------------------------------
   Card three rides on .feature--coach's frame. The roster row wraps a line
   of seats under its label: taken seats fill in colour one per count (.on,
   js/site.js); the three free ones stay as dashed rings.                  */
.feature--club .feature-bg { object-position: 50% 30%; }
.panel-roster { flex-wrap: wrap; row-gap: 10px; }
.seats { flex-basis: 100%; display: flex; padding-left: 28px; }
.seat + .seat { margin-left: -4px; }
.seat:not(.taken) { margin-left: 3px; }
.seat {
  width: 22px; height: 22px; flex: 0 0 auto; border-radius: 50%;
  border: 1.5px dashed rgba(1, 43, 33, .3);
  background: #fff;
}

.seat.taken { border: 2px solid #fff; background: var(--dot); }
.js .seat.taken { transition: background-color .3s var(--ease), transform .35s var(--ease); }
.js .seat.taken.on { animation: seat-pop .4s var(--ease); }
.js .seat.taken:not(.on) { border: 1.5px dashed rgba(1, 43, 33, .3); background: #fff; }
@keyframes seat-pop { 40% { transform: scale(1.2); } }

@media (min-width: 761px) {
  .feature--club .feature-bg { object-position: 50% 38%; }
}

@media (prefers-reduced-motion: reduce) {
  .js .seat.taken.on { animation: none; }
  .js .panel-note { opacity: 1; transform: none; }
  .js .panel-row, .js .panel-foot span { opacity: 1; }
  .js .feature-panel { --fill: 1; }
  .panel-row.run .tick { animation: none; }
}

/* ---- feature cards: Lassie format (all three) -------------------------------
   Matched to Lassie's feature run. Heading in the sub face (Spectral), one
   line; a small grey line under it. The frame is square and the panel sits
   in its centre, small and tight. It opens as a bar holding only its title,
   so the photo reads first; then it grows into the full panel (.open) and
   the photo fades back behind it, and only then do the rows play.
   js/site.js wraps everything under the title in .panel-body > div.       */
.feature { padding-block: 64px 72px; }
.feature .wrap { max-width: 560px; }
.feature-head {
  font: 400 21px/1.25 var(--sub); letter-spacing: -.01em;
  white-space: nowrap;
}
.feature-line { margin-top: 8px; font-size: 14px; line-height: 1.5; max-width: 38ch; color: var(--ink-dim); }

.feature .feature-frame {
  aspect-ratio: 1 / 1; margin-top: 28px;
  place-items: center; padding: 0;
}
.feature .feature-frame::after { display: none; }
.feature .feature-bg { transition: opacity 1.1s var(--ease); }
.feature .feature-scrim { background: rgba(0, 21, 16, .25); }
.feature-frame.open .feature-bg { opacity: .35; }
.feature--coach .feature-bg { object-position: 50% 40%; }
.feature--club .feature-bg { object-position: 50% 40%; }

.feature .feature-panel {
  width: calc(100% - 48px); max-width: 300px;
  padding: 10px;
  border-radius: 12px;
  box-shadow: 0 12px 30px rgba(0, 21, 16, .3);
}
.feature .panel-title { margin: 0; padding: 2px 2px; font-size: 12px; white-space: nowrap; }
.feature .panel-mark { width: 13px; height: 14px; }
.feature .panel-rows { margin-top: 8px; gap: 5px; }
.feature .panel-row { padding: 7px 9px; gap: 8px; font-size: 12px; border-radius: 8px; }
.feature .row-class, .feature .row-count { font-size: 11px; }
.feature .row-class::before { width: 15px; height: 16px; }
.feature .tick { width: 15px; height: 15px; }
.feature .tick::after { left: 4.3px; top: 1.8px; width: 3.5px; height: 7px; }
.feature .panel-note { font-size: 12px; }
.feature .note-who { font-size: 10px; }
.feature .seat { width: 18px; height: 18px; }
.feature .seats { padding-left: 23px; }
.feature .panel-foot { margin-top: 8px; padding-top: 6px; font-size: 11px; }

/* closed: a title-only bar; open: the full panel */
.panel-body { display: grid; grid-template-rows: 1fr; }
.panel-body > div { min-height: 0; overflow: hidden; }
.js .feature .feature-panel {
  max-width: 220px; border-radius: 22px;
  transition: max-width .9s var(--ease), border-radius .9s var(--ease);
}
.js .feature .panel-body { grid-template-rows: 0fr; transition: grid-template-rows .9s var(--ease); }
.js .feature .feature-panel.open { max-width: 300px; border-radius: 12px; }
.js .feature .feature-panel.open .panel-body { grid-template-rows: 1fr; }

@media (min-width: 761px) {
  .feature { padding-block: 96px 112px; }
  .feature .wrap { max-width: 640px; }
  .feature-head { font-size: 28px; }
  .feature-line { font-size: 16px; }
  .feature .feature-frame { aspect-ratio: 5 / 4; }
  .feature--coach .feature-bg { object-position: 50% 30%; }
  .js .feature .feature-panel.open, .feature .feature-panel { max-width: 340px; }
  .js .feature .feature-panel:not(.open) { max-width: 240px; }
}
@media (prefers-reduced-motion: reduce) {
  .js .feature .panel-body { grid-template-rows: 1fr; }
  .js .feature .feature-panel { max-width: 300px; border-radius: 12px; }
}

/* panel title: mark and text share one 14px line so they sit level */
.feature .panel-title { line-height: 14px; align-items: center; }
.feature .panel-title .panel-mark { display: block; width: 14px; height: 14px; }

/* ---- outside the gym: floating statement -------------------------------
   Lassie's "98% of posting" beat, photos only. Every photo is anchored at
   the stage's centre (.orbit) and js/site.js moves it onto an ellipse with
   a transform, so all positions live in the script, as they do on Lassie.
   Sizes follow Lassie's three steps: phone, tablet (1024) and desktop
   (1280). .live pins the stage over a taller section; .still (reduced
   motion) shows it at rest; with neither (no JS) the photos stay hidden. */
.outside { padding: 0; overflow: clip; }
.outside-stage {
  position: relative;
  min-height: 100svh;
  display: grid; place-items: center;
  padding-block: var(--sp-5);
}
.outside-lines {
  position: relative; z-index: 2;
  width: 100%; box-sizing: border-box;
  display: grid; justify-items: center; gap: 16px;
  padding-inline: var(--gut);
  font: 400 34px/1.12 var(--display); letter-spacing: var(--ls-display);
  text-align: center; color: var(--evergreen-500);
}
.outside-line { max-width: 9.5em; text-wrap: balance; }

.orbit { position: absolute; inset: 0; pointer-events: none; display: none; }
.float {
  position: absolute; left: 50%; top: 50%; margin: 0;
  width: var(--w); height: var(--h);
  border-radius: 12px; overflow: hidden;
  background: var(--evergreen-100);
  opacity: 0; will-change: transform;
}
.float img { display: block; width: 100%; height: 100%; object-fit: cover; will-change: transform; }

/* phone sizes, then Lassie's tablet and desktop steps */
.o1 { --w: 113px; --h: 125px; }
.o2 { --w: 96px;  --h: 96px;  }
.o3 { --w: 121px; --h: 123px; }
.o4 { --w: 104px; --h: 128px; }
.o5 { --w: 100px; --h: 124px; }
.o6 { --w: 112px; --h: 112px; }
@media (min-width: 1024px) {
  .outside-lines { font-size: clamp(44px, 4.4vw, 64px); }
  .outside-line { max-width: 11em; }
  .float { border-radius: 16px; }
  .o1 { --w: 170px; --h: 208px; }
  .o2 { --w: 150px; --h: 150px; }
  .o3 { --w: 191px; --h: 191px; }
  .o4 { --w: 160px; --h: 196px; }
  .o5 { --w: 156px; --h: 192px; }
  .o6 { --w: 170px; --h: 170px; }
}
@media (min-width: 1280px) {
  .o1 { --w: 236px; --h: 261px; }
  .o2 { --w: 190px; --h: 190px; }
  .o3 { --w: 273px; --h: 277px; }
  .o4 { --w: 210px; --h: 258px; }
  .o5 { --w: 204px; --h: 250px; }
  .o6 { --w: 230px; --h: 230px; }
}

/* live: pinned stage, the lines share one cell and JS fades them */
.outside.live, .outside.still { --pin: 120svh; }
.outside.live .orbit, .outside.still .orbit { display: block; }
.outside.live { height: calc(100svh + var(--pin)); }
.outside.live .outside-stage { position: sticky; top: 0; height: 100svh; min-height: 0; padding: 0; }
.outside.live .outside-line { grid-area: 1 / 1; opacity: 0; will-change: opacity, transform; }
@media (min-width: 1280px) { .outside.live { --pin: 220svh; } }
.outside.still .outside-stage { height: 100svh; min-height: 640px; padding: 0; }

/* ---- how it works: Lassie's "How Lassie works" ------------------------------
   A centred heading in the sub face, then a row of tiles: swiped on phones
   (scroll-snap, the next tile peeking in), four across on desktop. Each tile
   is a shade darker than the bone ground and holds a small white mock-up
   that plays once when it comes into view (.play, js/site.js "how tiles").
   Title and line sit under the tile. Mark colours are graphic only.        */
.how { padding-block: 88px 96px; }
/* Two Bone sections meeting over the Evergreen body can leave a hairline of
   green at the join when the one above ends on a fractional pixel (the
   pinned photo section is 220svh). Overlapping by 1px closes it. */
.on-bone + .on-bone { margin-top: -1px; }
.how-head { font: 400 30px/1.1 var(--display); letter-spacing: var(--ls-display); text-align: center; color: var(--ink); }

.how-track {
  list-style: none; margin: 32px 0 0; padding: 0 var(--gut) 4px;
  display: grid; grid-auto-flow: column; grid-auto-columns: 80%;
  gap: 14px;
  overflow-x: auto; overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory; scroll-padding-inline: var(--gut);
  scrollbar-width: none;
}
.how-track::-webkit-scrollbar { display: none; }
.how-card { scroll-snap-align: start; min-width: 0; }

.how-art {
  position: relative; aspect-ratio: 1 / 1;
  border-radius: 18px;
  background: #EFE8DA;                     /* bone, one step down */
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 0; padding: 20px;
  overflow: hidden;
}
.how-title { margin-top: 14px; font: 500 16px/1.3 var(--body); color: var(--ink); }
.how-line  { margin-top: 4px; font-size: 14px; line-height: 1.45; color: var(--ink-dim); max-width: 30ch; }

/* the mock-ups: small white panels in the panel type of the feature cards */
.mock {
  width: 100%; max-width: 230px;
  padding: 10px; border-radius: 10px;
  background: #fff; color: var(--evergreen-500);
  font: 400 11px/1.3 var(--body);
  box-shadow: 0 1px 2px rgba(1, 43, 33, .06), 0 8px 20px rgba(1, 43, 33, .06);
  display: grid; gap: 6px;
}
.mock-title { display: flex; align-items: center; gap: 6px; font-size: 11.5px; font-weight: 500; line-height: 13px; margin: 0 0 2px; max-width: none; }
.mock-title .panel-mark { display: block; width: 13px; height: 13px; }
.mock-field {
  padding: 6px 8px; border-radius: 6px;
  border: 1px solid rgba(1, 43, 33, .12); color: rgba(1, 43, 33, .65);
}
.mock-btn {
  padding: 7px 8px; border-radius: 999px; text-align: center;
  background: var(--evergreen-500); color: var(--bone); font-weight: 500;
}
.mock-link { width: 1px; height: 16px; background: rgba(1, 43, 33, .2); }
.mock-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 10px 5px 6px; border-radius: 999px;
  background: #fff; color: var(--evergreen-500);
  font: 500 11px/1 var(--body);
  box-shadow: 0 1px 2px rgba(1, 43, 33, .06);
}
.chip-tick {
  position: relative; width: 14px; height: 14px; flex: 0 0 auto;
  border-radius: 50%; background: var(--evergreen-500);
}
.chip-tick::after {
  content: ""; position: absolute; left: 4.6px; top: 2.2px; width: 3px; height: 6px;
  border: solid var(--bone); border-width: 0 1.6px 1.6px 0; transform: rotate(45deg);
}

.mock-row {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 8px; border-radius: 6px;
  border: 1px solid rgba(1, 43, 33, .08);
}
.mock-row .mk {
  width: 13px; height: 14px; flex: 0 0 auto; background: var(--dot);
  -webkit-mask: url("../assets/logomark-bone.svg") center / contain no-repeat;
          mask: url("../assets/logomark-bone.svg") center / contain no-repeat;
}
.mock-row .chip-tick { margin-left: auto; }

.week { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
.day {
  display: flex; flex-direction: column; align-items: center; gap: 5px;
  padding: 6px 0 7px; border-radius: 6px;
  background: rgba(1, 43, 33, .04); color: rgba(1, 43, 33, .6); font-size: 10px;
}
.day i { width: 8px; height: 8px; border-radius: 50%; background: var(--dot); }
.day:not(:has(i))::after { content: ""; width: 8px; height: 8px; }  /* keeps rows level */
.mock-note { margin: 2px 0 0; font-size: 10.5px; color: rgba(1, 43, 33, .65); max-width: none; }

.mock-member { background: var(--evergreen-500); color: var(--bone); }
.mock-member .mock-title { color: var(--bone); }
.member-block { margin: 6px 0 0; font-size: 12px; max-width: none; }
.member-bar { position: relative; height: 4px; border-radius: 2px; background: rgba(251, 247, 239, .18); overflow: hidden; }
.member-bar i { position: absolute; inset: 0; background: var(--tuskan-sun); transform-origin: 0 50%; transform: scaleX(calc(1 / 12)); }

/* play: each tile's pieces arrive in turn once it is in view */
.js [data-how] .mock-chip,
.js [data-how] .mock-link { opacity: 0; transform: translateY(6px); transition: opacity .5s var(--ease), transform .5s var(--ease); }
.js [data-how].play .mock-link { opacity: 1; transform: none; transition-delay: .5s; }
.js [data-how].play .mock-chip { opacity: 1; transform: none; transition-delay: .8s; }
.js [data-how] .mock-btn { transition: transform .2s var(--ease); }
.js [data-how].play .mock-btn { animation: how-press .5s var(--ease) .15s; }
@keyframes how-press { 50% { transform: scale(.95); } }

.js [data-how] .mock-row .chip-tick { transform: scale(0); transition: transform .35s var(--ease); }
.js [data-how].play .mock-row:nth-of-type(1) .chip-tick { transform: none; transition-delay: .3s; }
.js [data-how].play .mock-row:nth-of-type(2) .chip-tick { transform: none; transition-delay: .7s; }
.js [data-how].play .mock-row:nth-of-type(3) .chip-tick { transform: none; transition-delay: 1.1s; }
.js [data-how].play .mock-row:nth-of-type(4) .chip-tick { transform: none; transition-delay: 1.5s; }

.js [data-how] .day i { transform: scale(0); transition: transform .35s var(--ease); }
.js [data-how].play .day:nth-child(1) i { transform: none; transition-delay: .3s; }
.js [data-how].play .day:nth-child(3) i { transform: none; transition-delay: .6s; }
.js [data-how].play .day:nth-child(5) i { transform: none; transition-delay: .9s; }
.js [data-how].play .day:nth-child(6) i { transform: none; transition-delay: 1.2s; }

.js [data-how] .member-bar i { transform: scaleX(0); transition: transform 1s var(--ease) .3s; }
.js [data-how].play .member-bar i { transform: scaleX(calc(1 / 12)); }

@media (min-width: 761px) {
  .how { padding-block: 120px 128px; }
  .how-head { font-size: 44px; }
  .how-track {
    grid-auto-flow: row; grid-template-columns: repeat(4, 1fr); grid-auto-columns: auto;
    gap: 20px; max-width: 1240px; margin-inline: auto; margin-top: 48px; overflow: visible;
  }
}
@media (prefers-reduced-motion: reduce) {
  .js [data-how] .mock-chip, .js [data-how] .mock-link,
  .js [data-how] .mock-row .chip-tick, .js [data-how] .day i { opacity: 1; transform: none; transition: none; }
  .js [data-how] .member-bar i { transform: scaleX(calc(1 / 12)); transition: none; }
  .js [data-how].play .mock-btn { animation: none; }
}

/* ---- FAQ: Lassie's accordion ---------------------------------------------
   Centred heading in the sub face, then white rounded rows on bone, each a
   native <details> with a drawn chevron that turns when it opens.          */
.faq { padding-block: 24px 96px; }
.faq-head { font: 400 30px/1.1 var(--display); letter-spacing: var(--ls-display); text-align: center; color: var(--ink); }
.faq-list { display: grid; gap: 8px; max-width: 760px; margin: 28px auto 0; }
.faq-item { background: #fff; border-radius: 16px; color: var(--evergreen-500); }
.faq-item summary {
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
  min-height: 64px; padding: 16px 20px;
  font: 400 15px/1.35 var(--body); cursor: pointer; list-style: none;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after {
  content: ""; flex: 0 0 auto; width: 8px; height: 8px; margin: -4px 4px 0 0;
  border: solid currentColor; border-width: 0 1.6px 1.6px 0;
  transform: rotate(45deg); transition: transform .3s var(--ease);
}
.faq-item[open] summary::after { transform: translateY(4px) rotate(-135deg); }
.faq-item summary:focus-visible { outline: 2px solid var(--evergreen-500); outline-offset: 2px; border-radius: 16px; }
.faq-item p { margin: -4px 0 0; padding: 0 20px 20px; font-size: 14px; line-height: 1.55; color: rgba(1, 43, 33, .72); max-width: 60ch; }
.faq-item a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }

@media (min-width: 761px) {
  .faq { padding-block: 32px 128px; }
  .faq-head { font-size: 44px; }
  .faq-list { margin-top: 40px; gap: 10px; }
  .faq-item summary { padding: 18px 28px; font-size: 16px; }
  .faq-item p { padding: 0 28px 24px; }
}
@media (prefers-reduced-motion: reduce) { .faq-item summary::after { transition: none; } }

/* ---- The return: closing photo card ---------------------------------------
   After the FAQ, on bone. Square on every width, 24px corners, the group
   photo darkened, more so at the foot where the line sits, so the Bone
   type reads. Outline mark, then the line.                               */
.return-card { padding-block: 0; }
.return-frame {
  position: relative; overflow: hidden; isolation: isolate;
  aspect-ratio: 1 / 1; max-width: 760px; margin: 0 auto;
  border-radius: 24px; background: var(--evergreen-800);
  display: grid; place-items: center;
}
.return-bg { position: absolute; inset: 0; z-index: -2; width: 100%; height: 100%; object-fit: cover; }
.return-frame::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(to top, rgba(0, 21, 16, .6), rgba(0, 21, 16, 0) 38%),
    radial-gradient(ellipse 40% 22% at 50% 19%, rgba(0, 21, 16, .3), rgba(0, 21, 16, 0) 100%),
    rgba(0, 21, 16, .34);
}
/* The photo was extended (Adobe generative expand) so the whole group fits
   the square: the mark sits on the empty wall above them, the line on the
   floor below, so no face is covered. */
.return-lockup { position: absolute; inset: 0; padding: 0 20px; text-align: center; }
.return-mark {
  position: absolute; left: 50%; top: 19%; transform: translate(-50%, -50%);
  width: 46px; height: auto;
}
.return-line {
  position: absolute; left: 0; right: 0; bottom: 7%; margin: 0;
  font: 400 27px/1.15 var(--sub); letter-spacing: -.015em; color: var(--bone);
}
.return-line span { display: block; white-space: nowrap; }
/* Under the photo, left-aligned to its edge. */
.return-close { max-width: 760px; margin: 32px auto 0; }
.return-head { margin: 0; font: 400 30px/1.08 var(--display); letter-spacing: -.015em; color: var(--ink); }
.return-head .l1, .return-head .l2 { display: block; }
.return-head .l2 { font-family: var(--sub); font-style: italic; font-weight: 300; font-size: .62em; line-height: 1.3; margin-top: .12em; letter-spacing: -.01em; }   /* same step down as the hero */
.return-cta { display: flex; gap: 2px; margin-top: 20px; }
.return-btn, .return-arrow {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 44px; border-radius: 11px;
  background: var(--evergreen-500); color: var(--bone);
  text-decoration: none; -webkit-tap-highlight-color: transparent;
  transition: transform var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
}
.return-btn { padding: 0 20px; font: 500 15px/1 var(--body); }
.return-arrow { width: 44px; }
.return-arrow::before {
  content: ""; width: 7px; height: 7px; margin-left: -3px;
  border: solid currentColor; border-width: 1.6px 1.6px 0 0; transform: rotate(45deg);
}
.return-btn:hover, .return-arrow:hover { background: var(--evergreen-400); }
.return-btn:active, .return-arrow:active { transform: scale(.97); }
.return-btn:focus-visible, .return-arrow:focus-visible { outline: 2px solid var(--evergreen-500); outline-offset: 3px; }
@media (min-width: 761px) {
  /* desktop shows the original photo, so the frame takes its 16:9 */
  .return-frame { aspect-ratio: 16 / 9; max-width: 1080px; }
  .return-mark { display: none; }   /* on the uncropped photo it lands on a face */
  .return-line { font-size: 40px; bottom: 6%; }
  .return-close { max-width: 1080px; margin-top: 40px; }
  .return-head { font-size: 44px; }
  .return-cta { margin-top: 28px; }
}

/* ---- about: the title ---------------------------------------------------
   Lassie's /company fold: a full screen of Bone, the heading centred at
   Lassie's scale (0.95 leading, -.02em), then the line under it in light
   Spectral italic, the homepage hero's second voice. */
.about-title {
  min-height: 100svh;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  padding: 96px var(--gut) 64px;
  background: var(--surface); color: var(--ink);
  text-align: center;
}
.about-title-head {
  margin: 0 auto 24px; max-width: none;
  font: 400 clamp(30px, 8.4vw, 64px)/.98 var(--display);
  letter-spacing: -.02em; text-wrap: balance;
}
.about-title-head span { display: block; white-space: nowrap; }
.about-title-sub {
  margin: 0; max-width: none;
  font: 300 italic clamp(24px, 6.1vw, 32px)/1.1 var(--sub);
  color: var(--ink);
}
@media (min-width: 1024px) {
  .about-title-head { margin-bottom: 40px; font-size: clamp(74px, 6vw, 104px); }
  .about-title-sub  { font-size: clamp(30px, 2.4vw, 40px); }
}
@media (max-width: 760px) {
  body[data-page="about"] .site-header,
  body[data-page="find-us"] .site-header,
  body[data-page="book-a-call"] .site-header { position: fixed; inset: 0 0 auto 0; }
}

/* ---- Find us: the illustrated map -------------------------------------
   Its own page, /find-us. Canterbury as an Evergreen blob of real roads,
   the Stour and hand-drawn landmarks (inline SVG, js/find-map.js starts
   it), the logomark as the pin, Scrum Kitchen and Soak House popping out
   beside it. Then the address and the three things next door. The art is
   a fixed square, so the pin is a fixed % of it: the rugby club.        */
.find-us { padding-block: 112px 96px; color: var(--evergreen-500); }
.find-grid { display: grid; gap: 28px; max-width: 1180px; margin: 0 auto; }
.find-head { margin: 0; font: 400 30px/1.08 var(--display); letter-spacing: -.015em; color: var(--evergreen-500); }
.find-head .l1, .find-head .l2 { display: block; }
.find-head .l2 { font-family: var(--sub); font-style: italic; font-weight: 300; font-size: .62em; line-height: 1.3; margin-top: .12em; letter-spacing: -.01em; }   /* same step down as the hero */
.find-lede { margin-top: 14px; font-size: 15px; line-height: 1.55; color: rgba(1, 43, 33, .72); max-width: 44ch; }
.find-address { margin-top: 20px; font: 400 15px/1.5 var(--body); font-style: normal; }
.find-facts { list-style: none; margin: 20px 0 0; padding: 16px 0 0; border-top: 1px solid rgba(1, 43, 33, .12); display: grid; gap: 10px; }
.find-facts li { display: flex; align-items: center; gap: 10px; font-size: 15px; }
.find-facts svg { width: 20px; height: 20px; flex: 0 0 auto; }
.find-facts strong { font-weight: 700; }
.find-cta { margin-top: 24px; }

.find-map {
  position: relative; margin: 0; isolation: isolate;
  aspect-ratio: 1 / 1; width: 100%; max-width: 720px; justify-self: center;
  --pin-x: 52.06%; --pin-y: 78.03%;   /* Canterbury Rugby Club, in the art's square */
}
.map-art { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }
.lm-label {
  font: 700 13px/1 var(--body); letter-spacing: .14em; text-transform: uppercase;
  fill: var(--bone);
}

/* The entrance: the blob settles, then the landmarks pop up from their
   feet one by one (--i), before the pin drops. */
.js .map-art { opacity: 0; transform: scale(.94); transition: opacity .6s var(--ease), transform .9s var(--ease); }
.js .map-art .lm { opacity: 0; }
.js .map-art .lm-art { transform: scale(.4) translateY(12px); transform-box: fill-box; transform-origin: 50% 100%;
  transition: transform .6s cubic-bezier(.34, 1.56, .64, 1); transition-delay: inherit; }
.js .map-art .lm { transition: opacity .3s ease; transition-delay: calc(.35s + var(--i) * 45ms); }
.js .map-art .lm-label { opacity: 0; transition: opacity .5s var(--ease) .9s; }
.find-map.play .map-art { opacity: 1; transform: none; }
.find-map.play .map-art .lm { opacity: 1; }
.find-map.play .map-art .lm-art { transform: none; }
.find-map.play .map-art .lm-label { opacity: 1; }

/* The pin: the phone menu's Evergreen square, holding the Bone mark, with
   a tail and a slow Sun pulse on the spot. */
.map-pin { position: absolute; left: var(--pin-x, 50%); top: var(--pin-y, 71%); width: 0; height: 0; }
.map-badge {
  position: absolute; left: -24px; bottom: 10px; width: 48px; height: 48px;
  display: grid; place-items: center; border-radius: 13px;
  background: var(--evergreen-500); box-shadow: 0 10px 24px rgba(0, 21, 16, .28);
  transform-origin: 50% calc(100% + 10px);
  opacity: 0; transform: translateY(-40px) scale(.6);
  transition: opacity .3s ease .55s, transform .8s cubic-bezier(.34, 1.56, .64, 1) .55s;
}
.map-badge::after {
  content: ""; position: absolute; left: 50%; bottom: -5px; width: 12px; height: 12px;
  background: inherit; border-radius: 2px; transform: translateX(-50%) rotate(45deg);
}
.map-badge img { position: relative; z-index: 1; width: 27px; height: auto; }
.map-pulse {
  position: absolute; left: -7px; top: -7px; width: 14px; height: 14px; border-radius: 50%;
  background: var(--tuskan-sun); box-shadow: 0 0 0 2px var(--evergreen-500);
  opacity: 0; transition: opacity .3s ease .5s;
}
.map-pulse::before {
  content: ""; position: absolute; inset: -2px; border-radius: 50%;
  background: var(--tuskan-sun); opacity: 0;
}
.map-label {
  position: absolute; left: 0; top: 14px; transform: translate(-50%, 6px);
  padding: 6px 10px; border-radius: 8px; white-space: nowrap;
  background: var(--evergreen-500); color: var(--bone);
  font: 500 12px/1 var(--body); letter-spacing: -.01em;
  opacity: 0; transition: opacity .4s var(--ease) 1.05s, transform .6s var(--ease) 1.05s;
}

/* Neighbours: white chips either side of the pin, just above it. */
.map-chip {
  position: absolute; bottom: 30px;
  display: flex; align-items: center; gap: 8px;
  padding: 7px 11px 7px 8px; border-radius: 12px; white-space: nowrap;
  background: #fff; box-shadow: 0 6px 18px rgba(0, 21, 16, .14), 0 0 0 1px rgba(1, 43, 33, .06);
  opacity: 0; transform: translate(0, 8px) scale(.85);
  transition: opacity .35s ease, transform .6s cubic-bezier(.34, 1.56, .64, 1);
}
.map-chip svg {
  width: 26px; height: 26px; padding: 5px; flex: 0 0 auto; border-radius: 8px;
  background: var(--bone); color: var(--evergreen-500);
}
.map-chip b, .map-chip i { display: block; }
.map-chip b { font: 700 12px/1.15 var(--body); letter-spacing: -.01em; }
.map-chip i { font: 400 11px/1.2 var(--body); font-style: normal; color: rgba(1, 43, 33, .66); }
.map-chip--l { right: 34px; transform-origin: 100% 100%; transition-delay: 1.35s; }
.map-chip--r { left: 34px; transform-origin: 0 100%; transition-delay: 1.55s; }

.map-credit {
  position: absolute; right: 0; bottom: -18px;
  font: 400 10px/1 var(--body); color: rgba(1, 43, 33, .5);
}
.map-credit a { color: inherit; }

/* Played: everything lands in order after the ripple starts. */
.find-map.play .map-pulse,
.find-map.play .map-badge,
.find-map.play .map-chip { opacity: 1; transform: none; }
.find-map.play .map-label { opacity: 1; transform: translate(-50%, 0); }
.find-map.play .map-pulse::before { animation: map-pulse 2.4s ease-out 1.4s infinite; }
@keyframes map-pulse {
  0%   { transform: scale(1); opacity: .6; }
  100% { transform: scale(4.2); opacity: 0; }
}

/* Next door: three cards. The membership perk is the dark one. */
.find-next-head {
  max-width: 1180px; margin: 56px auto 0;
  font: 400 26px/1.2 var(--sub); letter-spacing: -.01em; color: var(--evergreen-500);
}
/* Phones: the How it works swipe. One row, 80% cards, the next peeking
   in, snapping to the gutter. The row runs to the screen edges. */
.find-next {
  list-style: none; margin: 20px calc(var(--gut) * -1) 0; padding: 0 var(--gut) 4px;
  display: grid; grid-auto-flow: column; grid-auto-columns: 80%; gap: 10px;
  overflow-x: auto; overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory; scroll-padding-inline: var(--gut);
  scrollbar-width: none;
}
.find-next::-webkit-scrollbar { display: none; }
.find-next .next-card { scroll-snap-align: start; min-width: 0; }
.next-card { padding: 22px 22px 24px; border-radius: 16px; background: #fff; }
.next-card svg { width: 30px; height: 30px; color: var(--evergreen-500); }
.next-tag {
  margin: 18px 0 0; font: 500 10.5px/1.2 var(--body); letter-spacing: .18em; text-transform: uppercase;
  color: rgba(1, 43, 33, .62);
}
.next-card h3 { margin: 6px 0 0; font: 400 22px/1.15 var(--display); letter-spacing: -.01em; }
.next-card p:last-child { margin: 8px 0 0; font-size: 14px; line-height: 1.55; color: rgba(1, 43, 33, .72); }
.next-card--member { background: var(--evergreen-500); color: var(--bone); }
.next-card--member svg { color: var(--tuskan-sun); }
.next-card--member .next-tag { color: var(--tuskan-sun); }
.next-card--member p:last-child { color: rgba(251, 247, 239, .72); }

@media (min-width: 761px) {
  .find-us { padding-block: 80px 128px; }
  .find-grid { grid-template-columns: minmax(300px, 5fr) 7fr; gap: 56px; align-items: center; }
  .find-head { font-size: 44px; }
  .find-lede, .find-address, .find-facts li { font-size: 16px; }
  .map-badge { left: -28px; width: 56px; height: 56px; border-radius: 15px; }
  .map-badge img { width: 32px; }
  .map-chip { bottom: 36px; padding: 9px 14px 9px 9px; gap: 10px; }
  .map-chip svg { width: 30px; height: 30px; }
  .map-chip b { font-size: 13.5px; }
  .map-chip i { font-size: 12px; }
  .map-chip--l { right: 44px; }
  .map-chip--r { left: 44px; }
  .find-next-head { margin-top: 88px; font-size: 34px; }
  .find-next {
    grid-auto-flow: row; grid-template-columns: repeat(3, 1fr); gap: 12px;
    max-width: 1180px; margin: 28px auto 0; padding: 0; overflow: visible;
  }
  .next-card { padding: 28px 28px 32px; }
}
@media (prefers-reduced-motion: reduce) {
  .map-pulse, .map-badge, .map-chip, .map-label,
  .js .map-art, .js .map-art .lm, .js .map-art .lm-art, .js .map-art .lm-label { transition: none; }
  .find-map.play .map-pulse::before { animation: none; }
}

/* ---- about: the mission lines -------------------------------------------
   Lassie's three centred lines under the title, at their heading-md scale
   (24px phone, up to 40px desktop, 1.1 leading) in light Spectral upright.
   The belief's key phrase is underlined and links down to Tash's story. */
.about-mission {
  background: var(--surface); color: var(--ink);
  padding: 0 16px 40px;
  text-align: center;
}
.about-mission p {
  max-width: 400px; margin: 0 auto; padding-bottom: 40px;
  font: 300 clamp(24px, 6.1vw, 32px)/1.1 var(--sub);
  text-wrap: balance;
}
.about-mission p + p { margin-top: 0; }
.about-mission p:last-child { padding-bottom: 0; }
.about-mission a {
  color: inherit; text-decoration: underline;
  text-decoration-thickness: 1.5px; text-underline-offset: 3px;
  border-radius: 4px;
}
.about-mission a:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
@media (min-width: 761px)  { .about-mission { padding-bottom: 64px; } .about-mission p { max-width: 55vw; } }
@media (min-width: 1024px) {
  .about-mission { padding: 64px 0 80px; }
  .about-mission p { max-width: 41vw; font-size: clamp(30px, 2.4vw, 40px); }
}
/* the title and these lines share one Bone ground, so drop the band edge */
.about-title + .about-mission { margin-top: 0; }

/* ---- about: Tash in orbit, the quote -------------------------------------
   The homepage's floating photos (.outside) with the Gene Tunney quote held
   in the middle, where Lassie's /company puts its logo and "trusted by"
   line. An oversized Crimson Violet mark stands in for Lassie's flower
   (Crimson Violet is the accent on Bone; Sun never sits on Bone). */
.orbit-quote { margin: 0; display: grid; justify-items: center; }
.orbit-mark {
  display: block; height: .5em; margin-bottom: 12px;
  font: 400 96px/1 var(--display); color: var(--accent-text);
}
.orbit-quote blockquote { margin: 0; }
.orbit-quote blockquote p {
  max-width: 11em; margin: 0 auto;
  font: 400 28px/1.1 var(--display); letter-spacing: var(--ls-display);
  text-wrap: balance; color: var(--evergreen-500);
}
.orbit-quote figcaption {
  margin-top: 14px;
  font: 500 11px/1.6 var(--body); letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-dim);
}
.orbit-quote figcaption b { display: block; font-weight: 700; color: var(--ink); }
@media (min-width: 1024px) {
  .orbit-mark { font-size: 140px; margin-bottom: 20px; }
  .orbit-quote blockquote p { font-size: clamp(38px, 3.3vw, 48px); }
  .orbit-quote figcaption { font-size: 12px; margin-top: 20px; }
}
/* the quote always reads over the photos */
.about-orbit .orbit { z-index: 1; }
.about-orbit .outside-lines { z-index: 3; }

/* ---- feature run: stacked cards -----------------------------------------
   Lassie's stacked feature cards. The three .feature cards share one
   section; js/feature-stack.js adds .is-stacked and drives each card from
   custom properties: --fs/--fy move and scale the frame, --dim shades the
   photo (Lassie fades theirs to .3 and .1 while it waits behind), --ps
   zooms it, --do/--dy fade and lift the head. The stage is sticky for 1.8
   screens (the section is 2.8 screens tall; the clock in
   js/feature-stack.js ends exactly there). The frame's top sits 42% down the
   screen, as on Lassie, so the head has room above it. overflow: clip, not hidden,
   or sticky would stick to the section instead of the page.
   Without .is-stacked (reduced motion) the cards simply follow each other. */
.feature-stack { padding-block: 0; }
.feature-stack.is-stacked { height: 280svh; overflow: clip; }
.is-stacked .stack-stage {
  position: sticky; top: 0; height: 100svh;
  display: grid; grid-template: 1fr / 1fr;
}
.is-stacked .run-card {
  grid-area: 1 / 1;
  display: flex; align-items: flex-start; justify-content: center;
  padding-top: 42svh;
  pointer-events: none;
}
.is-stacked .run-card.front { pointer-events: auto; }
/* No z-index on the cards themselves, so the frames and heads share one
   stacking layer: the frames stack front to back, and every head sits
   above every frame, so a card sliding away never covers the next head. */
.is-stacked .run-card:nth-of-type(1) .feature-frame { z-index: 3; }
.is-stacked .run-card:nth-of-type(2) .feature-frame { z-index: 2; }
.is-stacked .run-card:nth-of-type(3) .feature-frame { z-index: 1; }
/* the frame is as big as the screen allows, square on phones */
.is-stacked .run-card .wrap {
  position: relative; width: 100%;
  max-width: min(560px, calc(58svh - 64px + 2 * var(--gut)));
}
.is-stacked .feature-frame {
  margin-top: 0;
  transform: translateY(var(--fy, 0px)) scale(var(--fs, 1));
  will-change: transform;
}
.is-stacked .feature-bg { transform: scale(var(--ps, 1)); }
.is-stacked .feature-frame::after {
  content: ""; display: block; position: absolute; inset: 0; z-index: 2;
  background: var(--evergreen-900); opacity: var(--dim, 0);
  pointer-events: none;
}
/* the head sits above the frame, so every card's frame lands in one place */
.is-stacked .feature-desc {
  position: absolute; left: var(--gut); right: var(--gut); bottom: 100%;
  padding-bottom: 24px;
  opacity: var(--do, 1); transform: translateY(var(--dy, 0px));
  will-change: transform, opacity;
  z-index: 10; pointer-events: none;
}
.is-stacked .run-card.front .feature-desc { pointer-events: auto; }
@media (min-width: 761px) {
  .is-stacked .run-card { padding-top: 38svh; }
  .is-stacked .run-card .wrap { max-width: min(640px, calc((62svh - 80px) * 1.25 + 2 * var(--gut))); }
  .is-stacked .feature-desc { padding-bottom: 28px; }
}

/* ---- about: the join card ------------------------------------------------
   Lassie's /company careers card. A 24px-rounded photo card; the heading
   sits at the top in Bone over a darkening scrim, and the rows sit at the
   foot as white pills with a pill button (Lassie's "See job", set in Hanken
   Grotesk: brand fonts only). Portrait on phones (9:16), 4:5 on wider screens. */
.about-join { background: var(--surface); padding: 8px 16px 96px; }
.join-card {
  position: relative; isolation: isolate; overflow: hidden;
  max-width: 640px; margin: 0 auto;
  aspect-ratio: 9 / 16;
  display: flex; flex-direction: column;
  padding: 56px 16px 16px;
  border-radius: 24px;
  background: var(--evergreen-500);
}
.join-photo, .join-photo img {
  position: absolute; inset: 0; z-index: -2;
  width: 100%; height: 100%; object-fit: cover; object-position: 50% 45%;
}
.join-card::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(to bottom, rgba(0, 21, 16, .72) 0%, rgba(0, 21, 16, .25) 32%,
              rgba(0, 21, 16, 0) 55%, rgba(0, 21, 16, .35) 100%);
}
.join-head {
  margin: 0 auto; text-align: center;
  font: 400 clamp(28px, 7.6vw, 52px)/1.1 var(--display); letter-spacing: var(--ls-display);
  color: var(--bone);
}
.join-head span { display: block; white-space: nowrap; }
.join-rows { list-style: none; margin: auto 0 0; padding: 0; display: grid; gap: 4px; }
.join-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  min-height: 64px; padding: 10px 10px 10px 18px;
  border-radius: 14px;
  background: #fff; color: var(--evergreen-500);
  font: 500 15px/1.3 var(--body);
}
.join-btn {
  flex: none;
  display: inline-flex; align-items: center; min-height: 44px; padding: 0 16px;
  border-radius: 999px;
  background: var(--bone); color: var(--evergreen-500);
  font: 500 14px/1 var(--body);
  text-decoration: none;
  transition: background .2s ease, transform .2s ease;
}
.join-row:first-child .join-btn { background: var(--evergreen-500); color: var(--bone); }
.join-btn:hover { background: #EFE8DA; }
.join-row:first-child .join-btn:hover { background: var(--evergreen-400); }
.join-btn:active { transform: scale(.97); }
.join-btn:focus-visible { outline: 2px solid var(--evergreen-500); outline-offset: 3px; }
@media (min-width: 761px) {
  .join-card { aspect-ratio: 4 / 5; padding: 72px 24px 24px; }
  .join-row { padding-left: 24px; font-size: 16px; }
}
@media (min-width: 1024px) { .about-join { padding: 24px 0 128px; } }
/* the mission lines now follow the orbit, not the title */
.about-orbit + .about-mission { padding-top: 64px; }
@media (min-width: 1024px) { .about-orbit + .about-mission { padding-top: 96px; } }

/* ---- about: title tweaks (24 Sept) ---------------------------------------
   Less air between the title and the photos: the fold is 82% of the screen,
   not all of it. The quote's caption is now the sub face, small, in title
   case. */
.about-title { min-height: 82svh; }
.orbit-quote figcaption {
  margin-top: 12px;
  font: 400 17px/1.3 var(--sub); letter-spacing: 0; text-transform: none;
  color: var(--ink-dim);
}
@media (min-width: 1024px) {
  .about-title { min-height: 80svh; }
  .orbit-quote figcaption { font-size: 20px; margin-top: 16px; }
}

/* homepage statement: the pitch on three set lines (Strength, functional
   movement, / cardio and mobility, / coached in one place.) */
.statement .statement-pitch { max-width: none; }
.statement .statement-pitch span { display: block; white-space: nowrap; }
/* the pitch's first line is "Strength, functional movement,": on phones the
   size follows the width (capped at 30px) so it holds on one line */
@media (max-width: 760px) { .statement .statement-pitch { font-size: min(30px, 6.8vw); } }

/* ---- loader: the curtain arriving --------------------------------------
   Every page starts behind the closed curtain (only with JS, so no-JS
   visitors never see it) and js/site.js opens it: the two panels fold back
   to the top and bottom edges from the Sun hairline. The first page of a
   visit adds .first: the mark traces and fills, the name comes up, then
   .lift sends them away while the hairline draws, before .open. Leaving
   removes .open and adds .out (the curtain rules above). Failsafe: if the
   script never runs, the panels open by themselves after 6s.            */
.js .curtain .panel { transform: scaleY(1); }
/* the hairline takes no height, so the two panels meet with no seam of page
   showing between them while the line is still undrawn */
.curtain .hair { position: relative; z-index: 1; margin-bottom: -1px; }
.js .curtain .hair  { transform: scaleX(1); }
.js .curtain.first .hair { transform: scaleX(0); }
.js .curtain.first.lift .hair { transform: scaleX(1); transition: transform .55s cubic-bezier(.76, 0, .24, 1) .1s; }
.js .curtain.open .panel { transform: scaleY(0); animation: loader-open .9s cubic-bezier(.76, 0, .24, 1) both; }
.js .curtain.open .hair  { transform: scaleX(0); animation: loader-open-hair .7s cubic-bezier(.76, 0, .24, 1) .15s both; }
@keyframes loader-open      { from { transform: scaleY(1); } to { transform: scaleY(0); } }
@keyframes loader-open-hair { from { transform: scaleX(1); } to { transform: scaleX(0); } }
.js .curtain:not(.open):not(.out) .panel { animation: loader-safety .9s cubic-bezier(.76, 0, .24, 1) 6s forwards; }
.js .curtain:not(.open):not(.out) .hair  { animation: loader-safety-hair .4s ease 6s forwards; }
@keyframes loader-safety      { to { transform: scaleY(0); } }
@keyframes loader-safety-hair { to { opacity: 0; } }

.loader-id {
  position: absolute; inset: 0;
  display: grid; place-content: center; justify-items: center; gap: 22px;
  color: var(--bone);
  transition: opacity .35s ease, transform .6s var(--ease);
}
.curtain.lift .loader-id { opacity: 0; transform: translateY(-14px); }
/* The drawn outline mark (assets/outline-mark-*.svg, the textured one from
   guideline 1.6, not a stroked solid mark) sits faint, and three copies of
   it are lit through masks. Each mask is the solid mark's path (it runs
   down the middle of the outline) drawn as one wide dash of length L;
   animating the offset from L to L-1 puts every dash's head at the same
   point, so the Bone head rides the front of the Sun tail as one streak. */
.loader-mark { display: block; width: 140px; height: auto; overflow: visible; }
.loader-mark .lo-base { opacity: .16; }
.loader-mark .lm { fill: none; stroke: #fff; stroke-width: 64px; stroke-linecap: round; stroke-linejoin: round; }
.loader-mark .lm-tail { stroke-dasharray: .34 .66; filter: blur(14px); animation: loader-run-tail 2.2s linear infinite; }
.loader-mark .lm-mid  { stroke-dasharray: .16 .84; animation: loader-run-mid 2.2s linear infinite; }
.loader-mark .lm-head { stroke-dasharray: .05 .95; animation: loader-run-head 2.2s linear infinite; }
.loader-mark .lo-tail { opacity: .55; }
.loader-mark .lo-glow { filter: drop-shadow(0 0 5px rgba(255, 220, 77, .7)); }
@keyframes loader-run-tail { from { stroke-dashoffset: .34; } to { stroke-dashoffset: -.66; } }
@keyframes loader-run-mid  { from { stroke-dashoffset: .16; } to { stroke-dashoffset: -.84; } }
@keyframes loader-run-head { from { stroke-dashoffset: .05; } to { stroke-dashoffset: -.95; } }
@media (min-width: 761px) {
  .loader-mark { width: 170px; }
}

/* Hold the page's own entrances until the curtain opens, so the hero
   rises in as the panels part instead of finishing unseen behind them. */
.js.loading .rise.in { opacity: 0; transform: translateY(18px); }

/* ---- statement to the stacked cards: closer --------------------------------
   The pinned stage keeps empty room above the first card's head, so the
   stack is pulled up under the statement: the statement sits above it,
   covering only that empty room, and its line clears the head by the time
   the stage pins.                                                         */
.statement { position: relative; z-index: 1; }
/* in svh, because the first card's head sits a share of the screen down
   (42svh / 38svh): a fixed pull let the line touch it on short phones */
.statement + .feature-stack.is-stacked { margin-top: -24svh; }
/* phones: the card's line runs the full width of the frame, not 38ch */
@media (max-width: 760px) { .feature .feature-line { max-width: none; } }
@media (min-width: 761px) { .statement + .feature-stack.is-stacked { margin-top: -22svh; } }

/* ---- the offer: the six-week trial (29 Sept 2026) ------------------------
   The primary offer, one Evergreen card on bone after the floating photos
   and before How it works. Photo on top on phones, beside the text from
   761px. Same two-line head as the hero (Young Serif, then light Spectral
   italic at .62em). Sun ticks are graphic only; the button is the one Sun
   object that carries type (black on Sun). */
.offer { padding-block: 88px 8px; }
.offer-card {
  display: grid; max-width: 1180px; margin: 0 auto; overflow: hidden;
  border-radius: 24px; background: var(--evergreen-500); color: var(--bone);
  /* an Evergreen card inside a bone section: flip the ink back */
  --ink: var(--bone); --ink-dim: rgba(251, 247, 239, .72); --ink-faint: rgba(251, 247, 239, .62);
  --rule: rgba(251, 247, 239, .16); --focus-on-dark: var(--bone);
}
.offer-photo { aspect-ratio: 4 / 3; overflow: hidden; }
.offer-photo img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 30%; }
.offer-body { padding: 28px 22px 30px; }
.offer-tag {
  font: 500 10.5px/1.2 var(--body); letter-spacing: .18em; text-transform: uppercase;
  color: var(--tuskan-sun);
}
.offer-head { margin-top: 12px; font: 400 32px/1.05 var(--display); letter-spacing: -.015em; }
.offer-head .l1, .offer-head .l2 { display: block; }
.offer-head .l2 {
  font-family: var(--sub); font-style: italic; font-weight: 300; font-size: .62em;
  line-height: 1.3; margin-top: .12em; letter-spacing: -.01em; color: var(--ink-dim);
}
.offer-line { margin-top: 14px; font-size: 15px; line-height: 1.55; color: var(--ink-dim); max-width: 46ch; }
.offer-list {
  list-style: none; margin: 20px 0 0; padding: 18px 0 0; border-top: 1px solid var(--rule);
  display: grid; gap: 12px;
}
.offer-list li { display: flex; align-items: flex-start; gap: 12px; font-size: 15px; line-height: 1.4; }
.offer-tick {
  flex: 0 0 auto; width: 20px; height: 20px; margin-top: 0; border-radius: 50%;
  background: var(--tuskan-sun); position: relative;
}
.offer-tick::after {
  content: ""; position: absolute; left: 7px; top: 4px; width: 5px; height: 9px;
  border: solid var(--evergreen-500); border-width: 0 2px 2px 0; transform: rotate(45deg);
}
.offer-cta { margin-top: 26px; display: grid; gap: 12px; justify-items: start; }
.offer-note { font-size: 13px; line-height: 1.45; color: var(--ink-faint); }
.offer + .how { padding-top: 72px; }

@media (min-width: 761px) {
  .offer { padding-block: 128px 16px; }
  .offer-card { grid-template-columns: 5fr 6fr; align-items: stretch; }
  .offer-photo { aspect-ratio: auto; min-height: 100%; }
  .offer-body { padding: 56px 56px 56px 52px; align-self: center; }
  .offer-head { font-size: 48px; }
  .offer-line, .offer-list li { font-size: 16px; }
  .offer-cta { grid-auto-flow: column; align-items: center; gap: 20px; }
  .offer + .how { padding-top: 104px; }
}

/* ---- book a call (29 Sept 2026) -----------------------------------------
   Where every button lands. Same build as /find-us: the two-line head and
   lede on the left, a white card on the right that holds Tash's calendar
   (or, until the link is in, an email fallback). */
.call { padding-block: 112px 96px; color: var(--evergreen-500); }
.call-grid { display: grid; gap: 28px; max-width: 1180px; margin: 0 auto; }
/* Both columns still slide up after the loader, but never fade from 0:
   hidden text cannot count as painted, which held this page's largest
   paint (the lede) back until the curtain opened, ~4 s (2 Oct 2026). */
.js .call .rise { opacity: 1; }
.call-tag {
  margin-bottom: 14px; font: 500 10.5px/1.2 var(--body); letter-spacing: .18em;
  text-transform: uppercase; color: var(--crimson-violet);
}
.call-steps {
  list-style: none; margin: 22px 0 0; padding: 18px 0 0; border-top: 1px solid var(--rule);
  display: grid; gap: 12px;
}
.call-steps li { display: flex; align-items: center; gap: 12px; font-size: 15px; line-height: 1.4; }
.call-steps strong { font-weight: 700; }
.call-n {
  flex: 0 0 auto; display: grid; place-items: center; width: 28px; height: 28px; border-radius: 9px;
  background: var(--evergreen-500); color: var(--bone); font: 500 13px/1 var(--body);
}
.call-tash { display: flex; align-items: center; gap: 12px; margin-top: 24px; }
.call-tash img { width: 48px; height: 48px; border-radius: 50%; object-fit: cover; object-position: 50% 25%; }
.call-tash strong, .call-tash span { display: block; }
.call-tash strong { font: 400 18px/1.2 var(--display); }
.call-tash span { font-size: 13px; color: var(--ink-dim); }

.call-card { border-radius: 24px; background: #fff; overflow: hidden; }
.cal-host { position: relative; min-height: 360px; }
.cal-frame { display: block; width: 100%; height: 720px; border: 0; }
.cal-host:not(.has-cal) .cal-frame { position: absolute; inset: 0; opacity: 0; pointer-events: none; }
/* Tash's calendar, written straight into the page. The spinner sits under
   it, so the calendar covers it the moment it paints. */
.dropslot-frame { position: relative; z-index: 1; display: block;
                  width: 100%; min-width: 300px; height: 700px; border: 0; }
/* the deferred frame has no src until JS gives it one; without JS the
   <noscript> copy shows instead, so hide the empty one */
html:not(.js) .dropslot-frame[data-src] { display: none; }
.cal-wait { position: absolute; top: 120px; left: 50%; width: 36px; height: 36px;
            margin-left: -18px; border-radius: 50%;
            border: 3px solid rgba(1,43,33,.12); border-top-color: var(--evergreen-500);
            animation: cal-spin .9s linear infinite; }
@keyframes cal-spin { to { transform: rotate(360deg); } }
.cal-pending { padding: 36px 24px 32px; }
.cal-pending svg { width: 36px; height: 36px; color: var(--evergreen-500); }
.cal-pending h2 { margin-top: 18px; font: 400 26px/1.15 var(--display); letter-spacing: -.01em; }
.cal-pending p { margin-top: 10px; font-size: 15px; line-height: 1.55; color: var(--ink-dim); max-width: 40ch; }
.cal-pending .return-cta { margin-top: 22px; }

@media (min-width: 761px) {
  .call { padding-block: 128px 128px; }
  .call-grid { grid-template-columns: minmax(300px, 5fr) 7fr; gap: 56px; align-items: start; }
  .call-steps li { font-size: 16px; }
  .cal-pending { padding: 56px 52px 52px; }
  .cal-pending h2 { font-size: 34px; }
}

/* ---- desktop: centred heads, bigger feature cards (29 Sept 2026) -------
   The frame starts higher (30svh, not 38) so it can run wider, up to
   1080px at 16:10, still fitting the screen height. The panel scales with
   it (zoom keeps its inner spacing in proportion). js/feature-stack.js
   reads the frames' real heights, so it follows the new size.          */
@media (min-width: 1024px) {
  .feature-desc { text-align: center; }
  .feature-head { font-size: 34px; white-space: normal; }
  .feature-line { margin-inline: auto; font-size: 18px; max-width: 46ch; }
  .feature .wrap { max-width: min(1080px, 100%); }
  .feature .feature-frame { aspect-ratio: 16 / 10; border-radius: 28px; }
  .feature .feature-panel { zoom: 1.35; }
  .is-stacked .run-card { padding-top: 30svh; }
  .is-stacked .run-card .wrap { max-width: min(1080px, calc((70svh - 48px) * 1.6 + 2 * var(--gut))); }
}

/* ---- desktop hero film (29 Sept 2026) -----------------------------------
   The landscape cut (media/hero-desktop.mp4, 1600x900, 16:9 bands of the
   portrait 4K footage) fills the fold behind the centred type. An even
   Evergreen wash plus a soft pool behind the headline keeps the Bone type
   readable on every shot.                                               */
@media (min-width: 761px) {
  body[data-page="home"] .hero {
    position: relative; min-height: 100svh;
    display: flex; flex-direction: column; justify-content: center;
    padding-block: 120px 48px;
    background: var(--ground-deep);
  }
  body[data-page="home"] .hero .hide { display: none; }
  body[data-page="home"] .hero-media {
    display: block; position: absolute; inset: 0;
    z-index: var(--z-pattern); overflow: hidden;
    background: url("/media/hero-desktop-poster.webp") center / cover no-repeat;
  }
  body[data-page="home"] .hero-video { width: 100%; height: 100%; object-fit: cover; display: block; }
  body[data-page="home"] .hero-scrim {
    position: absolute; inset: 0;
    background:
      radial-gradient(60% 45% at 50% 48%, rgba(0, 21, 16, .5), transparent 75%),
      linear-gradient(180deg, rgba(1, 43, 33, .55) 0%, rgba(1, 43, 33, .38) 30%,
                              rgba(1, 43, 33, .38) 70%, rgba(1, 43, 33, .8) 100%);
  }
  body[data-page="home"] .hero .hero-head { text-shadow: 0 2px 24px rgba(0, 21, 16, .35); }

  /* Same fold as the phone: the headline, then the pitch line and the
     ticker as one small caption, then the frosted bar at the foot. The
     eyebrow, button, note and address stamp are phone-hidden, so here too. */
  body[data-page="home"] .hero { padding-block: 96px; }
  body[data-page="home"] .hero .eyebrow,
  body[data-page="home"] .hero .btn-row,
  body[data-page="home"] .hero .terms,
  body[data-page="home"] .hero .stamp,
  body[data-page="home"] .hero .link-quiet { display: none; }
  body[data-page="home"] .hero .sub {
    margin: 44px auto 0;
    font: 400 17px/1.4 var(--body); letter-spacing: .01em;
    white-space: nowrap; color: var(--ink);
    text-shadow: 0 1px 12px rgba(0, 21, 16, .45);
  }
  body[data-page="home"] .hero .ticker { margin-top: 6px; }
  body[data-page="home"] .hero .ticker li { font-size: 15px; }

  body[data-page="home"] .hero-bar {
    position: absolute; z-index: var(--z-content);
    left: 50%; transform: translateX(-50%);
    bottom: 32px;
    width: 420px;
    display: flex; align-items: center; justify-content: space-between; gap: 12px;
    padding: 6px 6px 6px 18px;
    border-radius: 16px;
    background: rgba(251, 247, 239, .18);
    backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
    box-shadow: inset 0 0 0 1px rgba(251, 247, 239, .22), 0 6px 20px rgba(0, 21, 16, .22);
  }
  .hero-bar-note { font: 400 15px/1.2 var(--body); color: var(--ink-dim); }
  .hero-bar-btn {
    display: inline-flex; align-items: center; justify-content: center;
    min-height: 44px; padding: 0 20px;
    border-radius: 11px;
    background: var(--bone); color: var(--ground);
    font: 500 15px/1 var(--body); text-decoration: none;
    transition: background-color var(--dur-fast) var(--ease);
  }
  .hero-bar-btn:hover { background: #fff; }
  .hero-bar-btn:focus-visible { outline: 2px solid var(--bone); outline-offset: 3px; }
}
@media (min-width: 761px) and (prefers-reduced-motion: reduce) {
  body[data-page="home"] .hero-video { display: none; }
}

/* ---- email copied toast (js/site.js "email links") --------------------- */
.copy-toast {
  position: fixed; left: 50%; bottom: 24px; z-index: var(--z-curtain);
  transform: translate(-50%, 12px); opacity: 0; pointer-events: none;
  max-width: calc(100vw - 32px);
  padding: 12px 20px; border-radius: var(--r-btn);
  background: var(--bone); color: var(--evergreen-500);
  font: 500 var(--t-small)/1.2 var(--body);
  box-shadow: 0 8px 24px rgba(0,0,0,.25);
  transition: opacity .25s, transform .25s;
}
.copy-toast.show { opacity: 1; transform: translate(-50%, 0); }
@media (prefers-reduced-motion: reduce) { .copy-toast { transition: none; } }

/* ---- cookie consent (js/site.js "cookie consent") -----------------------
   Deliberately quiet: a small Evergreen-900 card in the corner, Bone type,
   one Sun word. Accept and Reject are the SAME outlined button, so it
   never shouts and never nudges. Sun stays reserved for the real CTA.   */
.consent {
  position: fixed; z-index: calc(var(--z-header) + 1);
  left: var(--gut); bottom: calc(var(--gut) * .6 + env(safe-area-inset-bottom, 0px));
  width: min(360px, calc(100vw - var(--gut) * 2));
  padding: 16px 16px 16px 18px;
  border-radius: 12px;
  background: var(--ground-dark); color: var(--ink);
  box-shadow: inset 0 0 0 1px var(--rule-strong), 0 12px 32px rgba(0, 12, 9, .35);
  opacity: 0; transform: translateY(14px);
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.consent.in { opacity: 1; transform: none; }
.consent[hidden] { display: none; }
.consent-text {
  margin: 0; font: 400 14px/1.45 var(--body); letter-spacing: -.01em;
  color: var(--ink-dim);
}
.consent-label {
  display: block; margin-bottom: 6px;
  font: 500 10.5px/1 var(--body); letter-spacing: var(--ls-caps); text-transform: uppercase;
  color: var(--accent-text);
}
.consent-text a { color: var(--ink); text-underline-offset: 3px; }
.consent-text a:hover { text-decoration-thickness: 2px; }
.consent-actions { display: flex; gap: 8px; margin-top: 14px; }
.consent-btn {
  flex: 1; min-height: 40px; padding: 0 16px;
  border: 0; border-radius: var(--r-btn); cursor: pointer;
  background: transparent; color: var(--ink);
  box-shadow: inset 0 0 0 1px var(--rule-strong);
  font: 500 11px/1 var(--body); letter-spacing: var(--ls-caps); text-transform: uppercase;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease),
              box-shadow var(--dur-fast) var(--ease);
}
.consent-btn:hover { background: var(--bone); color: var(--evergreen-500); box-shadow: none; }
/* Weighted on Will's instruction (2 Oct 2026), after the ICO risk of
   unequal buttons was flagged: Accept is filled Bone, Reject stays an
   outline with dimmer ink. Reject keeps the same size and position and
   stays above 4.5:1 so it is still plainly readable. Do not push it
   further (smaller, hidden, lower contrast) without revisiting that.  */
.consent-btn[data-consent="granted"] { background: var(--bone); color: var(--evergreen-500); box-shadow: none; }
.consent-btn[data-consent="granted"]:hover { background: #fff; }
.consent-btn[data-consent="denied"] { color: var(--ink-dim); box-shadow: inset 0 0 0 1px var(--rule); }
.consent-btn[data-consent="denied"]:hover { background: transparent; color: var(--ink); box-shadow: inset 0 0 0 1px var(--rule-strong); }
.consent-btn:focus-visible { outline: 2px solid var(--focus-on-dark); outline-offset: 2px; }
@media (max-width: 760px) {
  .consent { left: 12px; right: 12px; width: auto; bottom: calc(12px + env(safe-area-inset-bottom, 0px)); }
  .consent-btn { min-height: 44px; }
}
@media (prefers-reduced-motion: reduce) { .consent { transition: none; transform: none; } }

/* "Cookie settings" in the footer: a button dressed as the links beside it. */
.site-footer .foot-link {
  padding: 0; border: 0; background: none; cursor: pointer;
  font: 400 22px/1.2 var(--sub); letter-spacing: -.02em; color: var(--evergreen-500);
}
.site-footer .foot-link:hover { text-decoration: underline; text-underline-offset: 3px; }
.site-footer .foot-link:focus-visible { outline: 2px solid var(--evergreen-500); outline-offset: 3px; border-radius: 2px; }
@media (min-width: 761px) { .site-footer .foot-link { font-size: 24px; } }
