
:root{
  --ink:#16171A;
  --ink-2:#1F2126;
  --ink-3:#2C2F35;
  --paper:#F2F1EE;
  --paper-2:#FFFFFF;
  --accent:#3AA6D6;
  /* Was #1E88B8. White text on that measured 3.99:1 — just under the 4.5:1 normal-size text
     needs, and this token is the background of every "Book a Gait Analysis" button on the
     site. #19729B is the same hue stepped down: 5.35:1 under white, and 5.35:1 as text on
     the white cards, so it fixes the buttons and the .sec-link/.eyebrow labels at once.
     (The GREEN labels are a separate, deliberate call — see the settled note ~line 2652.) */
  --accent-deep:#19729B;
  --sky:#63B7DE;
  --green:#8CC63F;
  --green-deep:#6EA82E;
  --green-ink:#4A7A16;   /* text/button weight green — see .rx notes */
  --muted:#635F5A;
  --muted-d:rgba(255,255,255,.56);
  --line-l:rgba(22,23,26,.13);
  --line-d:rgba(255,255,255,.14);
  --display:'Archivo Black','Archivo',system-ui,sans-serif;
  --body:'Archivo',system-ui,-apple-system,sans-serif;
  --mono:'Inter',system-ui,-apple-system,sans-serif;
  --maxw:1240px;
  /* spacing scale — everything snaps to this */
  --s-1:8px; --s-2:16px; --s-3:24px; --s-4:32px; --s-5:48px;
  --s-6:64px; --s-7:88px; --s-8:112px;
  --sec:104px;        /* standard section rhythm */
  --sec-sm:72px;
  /* radius scale */
  --r-sm:4px; --r-md:8px; --r-lg:14px; --r-pill:999px;
}
*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth}
body{font-family:var(--body);background:var(--paper);color:var(--ink);-webkit-font-smoothing:antialiased;line-height:1.62;font-size:17px;overflow-x:hidden}
a{color:inherit;text-decoration:none}
img{max-width:100%;display:block}
.wrap{max-width:var(--maxw);margin:0 auto;padding:0 32px}
.eyebrow{font-family:var(--mono);font-size:12px;letter-spacing:0.14em;text-transform:uppercase;font-weight:500;color:var(--accent-deep);display:inline-flex;align-items:center;gap:10px}
.eyebrow::before{content:"";width:26px;height:1px;background:currentColor}
/* Dark backgrounds get the light sky blue (7.99:1). The base --accent-deep is meant for
   light backgrounds and only manages 4.5:1 on the dark ink, so any dark panel must be listed
   here or two different blues end up on identical backgrounds. .data-bg covers the dark
   sections and the dark half of the split. */
.hero .eyebrow,.page-hero .eyebrow,.method .eyebrow,.section-d .eyebrow,.proof .eyebrow,
.data-bg .eyebrow{color:var(--sky)}
.display{font-family:var(--display);font-weight:400;text-transform:uppercase;line-height:.98;letter-spacing:-.01em}

/* NAV */
header.nav{position:sticky;top:0;z-index:60;background:linear-gradient(180deg,rgba(16,17,20,.98),rgba(22,23,26,.94));backdrop-filter:blur(14px) saturate(1.2);border-bottom:1px solid rgba(255,255,255,.1);box-shadow:0 10px 34px -20px rgba(0,0,0,.9)}
header.nav::after{content:"";position:absolute;left:0;right:0;bottom:-1px;height:2px;background:linear-gradient(90deg,var(--sky) 0%,var(--green) 52%,transparent 92%);opacity:.95}
.nav-inner{display:flex;align-items:center;justify-content:space-between;height:80px;color:#fff}
.brand{display:flex;align-items:center;gap:12px}
.brand-mark{display:grid;place-items:center;color:#fff}
.brand-logo{height:46px;width:auto;display:block;transition:transform .25s}
.brand:hover .brand-logo{transform:scale(1.04)}
.foot-logo{height:52px;width:auto;display:block;margin-bottom:20px}
.emblem{display:block}
.brand-txt{line-height:1}
.brand-txt b{font-family:var(--display);font-size:19px;letter-spacing:.04em;display:block}
.brand-txt span{font-family:var(--mono);font-size:11px;letter-spacing:0.14em;color:var(--muted-d);text-transform:uppercase}
/* gap 2 / padding 10, NOT 6 / 15. .nav-inner is capped at --maxw (1240px) on every
   desktop width, and a seventh link (Antepes, Sept 8) pushed the row to 1330px there —
   which did not overflow visibly, it wrapped "Book a Gait Analysis" onto two lines and
   grew the header on EVERY desktop screen. The tighter figures buy back 94px and put the
   CTA back on one line with room to spare. ::after must track the horizontal padding or
   the hover underline stops matching the label. */
.nav-links{display:flex;gap:2px;align-items:center}
.nav-links a{position:relative;font-size:13px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:rgba(255,255,255,.8);transition:color .2s;padding:10px 10px;border-radius:var(--r-md)}
.nav-links a::after{content:"";position:absolute;left:10px;right:10px;bottom:4px;height:2px;background:var(--green);transform:scaleX(0);transform-origin:left;transition:transform .26s cubic-bezier(.16,1,.3,1)}
.nav-links a:hover::after,.nav-links a.active::after{transform:scaleX(1)}
.nav-links a:hover{color:#fff;background:rgba(255,255,255,.05)}
.nav-links a.active{color:#fff}
.nav-cta{display:flex;gap:14px;align-items:center}
.btn{display:inline-flex;align-items:center;gap:9px;font-weight:700;font-size:14px;letter-spacing:.01em;padding:12px 20px;border-radius:var(--r-md);transition:transform .15s,background .2s,color .2s;cursor:pointer;border:none;font-family:var(--body)}
.btn-accent{background:var(--accent-deep);color:#fff}
.nav-cta .btn-accent{box-shadow:0 6px 20px -8px rgba(58,166,214,.9);font-size:13px;letter-spacing:.06em;text-transform:uppercase}
.btn-accent:hover{background:#17708F;transform:translateY(-1px)}
.btn-ghost-d{background:transparent;color:#fff;border:1px solid rgba(255,255,255,.35)}
.btn-ghost-d:hover{border-color:#fff}
.btn-ghost-l{background:transparent;color:var(--ink);border:1px solid var(--line-l)}
.btn-ghost-l:hover{border-color:var(--ink)}
.btn .arw{transition:transform .2s}
.btn:hover .arw{transform:translateX(3px)}
.sign-in{font-size:11px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:var(--muted-d);padding:9px 13px;border:1px solid rgba(255,255,255,.2);border-radius:var(--r-md);transition:border-color .2s,color .2s}
.sign-in:hover{color:#fff;border-color:rgba(255,255,255,.55)}
.menu-toggle{display:none;background:none;border:none;color:#fff;cursor:pointer;font-size:20px}

/* SHARED HERO BITS */
.hero-lanes{position:absolute;inset:0;background:repeating-linear-gradient(90deg,transparent 0 calc(100%/6 - 1px),rgba(255,255,255,.035) calc(100%/6 - 1px) calc(100%/6));pointer-events:none;mask-image:linear-gradient(180deg,transparent,#000 30%,#000 70%,transparent);-webkit-mask-image:linear-gradient(180deg,transparent,#000 30%,#000 70%,transparent)}

/* HOME HERO */
.hero{position:relative;background:var(--ink);color:#fff;overflow:hidden;padding:var(--sec) 0 0}
.hero-inner{position:relative;z-index:2}
.hero-eyebrow{margin-bottom:30px;opacity:0;animation:fadeUp .7s .1s forwards}
.hero h1{font-family:var(--display);text-transform:uppercase;line-height:.98;letter-spacing:-.015em;font-size:clamp(40px,7.4vw,96px);margin-bottom:26px}
.hero h1 .l{display:block;overflow:hidden}
.hero h1 .l i{display:block;font-style:normal;transform:translateY(102%);animation:reveal .9s cubic-bezier(.16,1,.3,1) forwards}
.hero h1 .l:nth-child(1) i{animation-delay:.18s}
.hero h1 .l:nth-child(2) i{animation-delay:.30s}
.hero h1 .l:nth-child(3) i{animation-delay:.42s;color:var(--sky)}
/* Width in em, not px, and deliberately not the original 520px. The line is two sentences; at
   520px the first line ended "...training. Every", orphaning "Every" from "sprint timed" so the
   wrap fell mid-sentence. 24.5em is wider than sentence one (~23.4em) but too narrow to also fit
   "Every " (~2.5em), which forces the break onto the sentence boundary. It has to be em because
   font-size is a vw clamp — a fixed px cap holds at 1440 but lets the smaller tablet type pull
   "Every" back up onto line one. Re-measure both numbers if this copy changes. */
.hero-sub{max-width:24.5em;font-size:clamp(16px,1.7vw,19px);color:rgba(255,255,255,.72);margin-bottom:38px;opacity:0;animation:fadeUp .7s .6s forwards}
.hero-actions{display:flex;gap:14px;flex-wrap:wrap;opacity:0;animation:fadeUp .7s .74s forwards}
.hero-actions .btn{padding:16px 26px;font-size:15px}
.statrail{position:relative;z-index:2;margin-top:72px;border-top:1px solid var(--line-d);display:grid;grid-template-columns:repeat(4,1fr)}
.stat{padding:26px 0 30px;border-right:1px solid var(--line-d);position:relative}
.stat:last-child{border-right:none}
.stat .k{font-family:var(--display);font-size:clamp(30px,4vw,46px);line-height:1;letter-spacing:.01em}
.stat .k b{color:var(--accent);font-weight:400}
.stat .u{font-family:var(--mono);font-size:11px;letter-spacing:0.14em;text-transform:uppercase;color:var(--muted-d);margin-top:10px}
.stat::after{content:"";position:absolute;top:-1px;left:0;width:0;height:2px;background:var(--accent);transition:width .8s ease}
.statrail.in .stat::after{width:34px}

/* PAGE HERO (inner pages) */
.page-hero{position:relative;background:var(--ink);color:#fff;overflow:hidden;padding:78px 0 66px}
.page-hero .inner{position:relative;z-index:2}
.page-hero h1{font-family:var(--display);text-transform:uppercase;font-size:clamp(36px,6vw,72px);line-height:.9;margin:24px 0 20px;letter-spacing:.01em}
.page-hero p{max-width:560px;font-size:clamp(16px,1.7vw,18px);color:rgba(255,255,255,.72)}
.crumb{font-family:var(--mono);font-size:11px;letter-spacing:0.14em;text-transform:uppercase;color:var(--muted-d)}
.crumb b{color:var(--accent);font-weight:500}

/* MANIFESTO */
.manifesto{background:var(--paper);padding:var(--sec) 0}
.man-grid{display:grid;grid-template-columns:1.15fr .85fr;gap:70px;align-items:end}
.man-eyebrow{margin-bottom:26px}
.man-lead{font-family:var(--display);text-transform:uppercase;font-size:clamp(28px,4vw,48px);line-height:.96;letter-spacing:.006em}
.man-lead em{font-style:normal;color:var(--accent)}
.man-body{margin-top:26px;font-size:17px;color:#41454E;max-width:520px}
.man-figure{border-left:2px solid var(--accent);padding-left:26px}
.man-figure .big{font-family:var(--display);font-size:clamp(48px,7vw,92px);line-height:.86;letter-spacing:.01em}
.man-figure .cap{font-family:var(--mono);font-size:12px;letter-spacing:.14em;text-transform:uppercase;color:var(--muted);margin-top:12px;max-width:240px;line-height:1.6}

/* METHOD */
.method{background:var(--ink);color:#fff;padding:var(--sec) 0}
.method-head{display:flex;justify-content:space-between;align-items:flex-end;gap:40px;margin-bottom:20px;flex-wrap:wrap}
.method-head h2{font-family:var(--display);text-transform:uppercase;font-size:clamp(30px,4.4vw,54px);line-height:.92}
.method-head p{max-width:340px;color:var(--muted-d);font-size:15px;padding-bottom:8px}
.curve{width:100%;height:70px;margin:14px 0 46px}
.curve path{stroke:var(--green);stroke-width:2.5;fill:none;stroke-dasharray:1400;stroke-dashoffset:1400}
.method.in .curve path{animation:draw 1.6s .2s ease forwards}

/* PROGRAMS */
.programs{background:var(--paper);padding:var(--sec) 0}
.prog-head{margin-bottom:52px;max-width:640px}
.prog-head h2{font-family:var(--display);text-transform:uppercase;font-size:clamp(30px,4.4vw,54px);line-height:.92;margin-top:22px}
.prog-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:22px}
.prog{background:var(--paper-2);border:1px solid var(--line-l);padding:36px 30px 30px;display:flex;flex-direction:column;min-height:340px;transition:transform .2s,box-shadow .2s;position:relative;overflow:hidden}
.prog::before{content:"";position:absolute;top:0;left:0;width:100%;height:4px;background:var(--accent);transform:scaleX(0);transform-origin:left;transition:transform .3s}
.prog:hover{transform:translateY(-4px);box-shadow:0 22px 50px -24px rgba(22,23,26,.4)}
.prog:hover::before{transform:scaleX(1)}
.prog .age{font-family:var(--mono);font-size:11px;letter-spacing:0.14em;text-transform:uppercase;color:var(--accent)}
.prog h3{font-family:var(--display);text-transform:uppercase;font-size:34px;line-height:.96;margin:16px 0 16px}
.prog p{font-size:15px;color:#4A4E57;flex:1}
.prog .go{margin-top:24px;font-weight:700;font-size:14px;display:inline-flex;align-items:center;gap:9px;color:var(--ink)}
.prog .go .arw{color:var(--accent);transition:transform .2s}
.prog:hover .go .arw{transform:translateX(4px)}

/* PROOF */
.proof{background:var(--ink);color:#fff;padding:var(--sec) 0 90px}
.proof-head{text-align:center;margin-bottom:56px}
.proof-head h2{font-family:var(--display);text-transform:uppercase;font-size:clamp(30px,4.4vw,54px);line-height:.92;margin-top:20px}
.proof-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:22px}
.quote{border:1px solid var(--line-d);padding:34px 30px;display:flex;flex-direction:column}
.quote .mark{font-family:var(--display);font-size:60px;line-height:.5;color:var(--accent);height:26px}
.quote p{font-size:15.5px;color:rgba(255,255,255,.82);line-height:1.6;flex:1;margin-bottom:26px}
.quote .who b{font-family:var(--display);text-transform:uppercase;font-size:18px;letter-spacing:.02em;display:block}
.quote .who span{font-family:var(--mono);font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--muted-d);margin-top:6px;display:block}
.affil{margin-top:64px;border-top:1px solid var(--line-d);padding-top:32px;display:flex;gap:46px;justify-content:center;flex-wrap:wrap;align-items:center}
.affil span{font-family:var(--mono);font-size:12px;letter-spacing:0.14em;text-transform:uppercase;color:rgba(255,255,255,.42)}

/* CTA */
.cta{position:relative;background:var(--green);color:var(--ink);padding:var(--sec) 0;overflow:hidden}
.cta::before{content:"";position:absolute;inset:0;background:repeating-linear-gradient(90deg,transparent 0 calc(100%/6 - 1px),rgba(22,23,26,.07) calc(100%/6 - 1px) calc(100%/6));pointer-events:none}
.cta-inner{position:relative;z-index:2;text-align:center}
.cta h2{font-family:var(--display);text-transform:uppercase;font-size:clamp(32px,5.2vw,64px);line-height:.9}
.cta p{max-width:520px;margin:22px auto 34px;font-size:17px;color:rgba(22,23,26,.78)}
.cta .btn-invert{background:var(--accent-deep);color:#fff;padding:18px 34px;font-size:16px}
.cta .btn-invert:hover{background:var(--ink);color:#fff;transform:translateY(-1px)}
.cta .addr{margin-top:30px;font-family:var(--mono);font-size:12px;letter-spacing:0.14em;text-transform:uppercase;color:rgba(22,23,26,.72)}

/* FOOTER */
footer{background:var(--ink);color:#fff;padding:70px 0 40px}
/* 1.2/1.2 rather than the original 1.4/1: the Connect column now carries a 32-character email
   address, which measures 268px at 14px/700 and so wrapped mid-domain ("…performancemethod." /
   "com") in a 240px track. Moving 48px from the brand column to Connect makes it 288px and the
   address sits on one line. The brand blurb is capped at max-width:280px, so it loses nothing. */
.foot-top{display:grid;grid-template-columns:1.2fr 1fr 1fr 1.2fr;gap:40px;padding-bottom:46px;border-bottom:1px solid var(--line-d)}
.foot-brand b{font-family:var(--display);font-size:26px;letter-spacing:.04em;text-transform:uppercase}
.foot-brand p{font-size:14px;color:var(--muted-d);margin-top:14px;max-width:280px}
.foot-col h4{font-family:var(--mono);font-size:11px;letter-spacing:0.14em;text-transform:uppercase;color:var(--accent);margin-bottom:16px}
.foot-col a{display:block;font-size:14px;color:rgba(255,255,255,.72);margin-bottom:11px;transition:color .2s}
.foot-col a:hover{color:#fff}
/* The contact point is the single most-wanted item in the footer, so it reads brighter than
   the nav links around it. word-break stays as the safety net for the narrower breakpoints
   below, where the column is far tighter than the 288px desktop track. */
.foot-col a.foot-contact{color:#fff;font-weight:700;word-break:break-word}
.foot-bottom{display:flex;justify-content:space-between;align-items:center;padding-top:26px;flex-wrap:wrap;gap:14px}
.foot-bottom span{font-family:var(--mono);font-size:11px;letter-spacing:.1em;color:var(--muted-d)}

/* ===== INNER-PAGE COMPONENTS ===== */
.section{padding:var(--sec) 0}
.section-l{background:var(--paper);color:var(--ink)}
.section-d{background:var(--ink);color:#fff}
.section-p2{background:var(--paper-2)}
.sec-head{max-width:680px;margin-bottom:52px}
.sec-head h2{font-family:var(--display);text-transform:uppercase;font-size:clamp(28px,4vw,48px);line-height:.94;margin-top:20px}
.sec-head p{margin-top:20px;font-size:17px;color:#4A4E57}
.section-d .sec-head p{color:var(--muted-d)}

/* method detail rows */
.mrow{display:grid;grid-template-columns:auto 1fr auto;gap:40px;padding:44px 0;border-top:1px solid var(--line-d);align-items:start}
.mrow:last-child{border-bottom:1px solid var(--line-d)}
.mrow .mno{font-family:var(--display);font-size:clamp(40px,5.5vw,72px);line-height:.8;color:var(--accent);min-width:120px}
.mrow h3{font-family:var(--display);text-transform:uppercase;font-size:clamp(24px,3vw,34px);line-height:1.02;margin-bottom:16px}
.mrow .lead{font-size:17px;color:rgba(255,255,255,.82);max-width:640px;margin-bottom:14px}
.mrow .tag{font-family:var(--mono);font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--muted-d)}
/* Pillar photo. All four sources are portrait and two (03, 04) are exactly 1280x1600, so a
   4/5 box crops those not at all; 01 and 02 carry an object-position in the markup because
   their subject sits high in a taller frame. On mobile the figure goes square — a full-width
   4/5 photo is 437px tall on a 390px phone and would push the next pillar off screen. */
.mrow-fig{margin:0;width:300px;aspect-ratio:4/5;overflow:hidden;border-radius:var(--r-lg);background:#1B1E24;box-shadow:0 22px 48px -30px rgba(0,0,0,.8)}
.mrow-fig img{width:100%;height:100%;object-fit:cover;display:block;transition:transform .6s cubic-bezier(.16,1,.3,1)}
.mrow:hover .mrow-fig img{transform:scale(1.04)}

/* cycle steps */
.cycle{display:grid;grid-template-columns:repeat(3,1fr);gap:22px;margin-top:12px}
.cyc{background:var(--paper-2);border:1px solid var(--line-l);padding:32px 28px}
/* --accent-deep, not --accent: .cyc sits on --paper-2 (#FFF) where the lighter
   blue measures 2.76:1. Same fix, same reason, as .mr-card .cn above. */
.cyc .cn{font-family:var(--mono);font-size:12px;letter-spacing:0.14em;color:var(--accent-deep)}
.cyc h4{font-family:var(--display);text-transform:uppercase;font-size:22px;margin:18px 0 12px;line-height:1.02}
.cyc p{font-size:14.5px;color:#4A4E57}

/* program detail block */
.pblock{display:grid;grid-template-columns:.9fr 1.1fr;gap:56px;padding:64px 0;border-top:1px solid var(--line-l);align-items:center}
.pblock:first-of-type{border-top:none;padding-top:16px}
/* 1/1, not the original 4/3. Every program photo on disk is a 4:5 portrait of a full-body
   athlete, and a 4:3 landscape crop of one cuts the head off no matter where you put the
   object-position — there is simply no 4:3 window containing a standing person. A square
   drops only 20% of the height. .pblock is used on programs.html and nowhere else, so this
   is safe; the "credibility band uses .pblock" comment below refers to a section that no
   longer exists. */
.pblock .media{aspect-ratio:1/1;background:linear-gradient(135deg,var(--ink),var(--ink-3));border:1px solid var(--line-l);position:relative;overflow:hidden;display:grid;place-items:center}
.pblock .media::before{content:"";position:absolute;inset:0;background:repeating-linear-gradient(90deg,transparent 0 calc(100%/5 - 1px),rgba(255,255,255,.06) calc(100%/5 - 1px) calc(100%/5))}
.pblock .media .ph{position:relative;font-family:var(--mono);font-size:11px;letter-spacing:0.14em;text-transform:uppercase;color:rgba(255,255,255,.4)}
/* Same trick the .photo-slot cards use: the img is layered OVER the .ph label and the ::before
   stripes, so `onerror="this.remove()"` falls back to the labelled placeholder instead of a
   blank box. z-index:2 is required — .ph is position:relative and would otherwise paint on top. */
.pblock .media img{position:absolute;inset:0;z-index:2;width:100%;height:100%;object-fit:cover;display:block}
.pblock.rev{direction:rtl}
.pblock.rev>*{direction:ltr}
/* --accent-deep, not --accent: at 11px on --paper the lighter blue measured 2.44:1, well
   under the 4.5:1 minimum, and these age labels are the one thing a parent scans this page
   for. --accent-deep measures 4.74:1. */
.pblock .age{font-family:var(--mono);font-size:11px;letter-spacing:0.14em;text-transform:uppercase;color:var(--accent-deep)}
.pblock h3{font-family:var(--display);text-transform:uppercase;font-size:clamp(28px,3.8vw,46px);line-height:.94;margin:14px 0 18px}
.pblock .desc{font-size:17px;color:#41454E;margin-bottom:24px}
.plist{list-style:none;margin-bottom:28px}
.plist li{font-size:15px;color:#3A3E47;padding:11px 0 11px 28px;border-top:1px solid var(--line-l);position:relative}
.plist li::before{content:"→";position:absolute;left:0;color:var(--accent);font-weight:700}

/* ============================================================================
   COACHES PAGE
   Josh asked (Aug 18) for this to be the best-looking page on the site. The whole
   page runs dark so it reads cinematic and so it contrasts with the now-light
   alumni wall. Three ideas carry it:
     1. .ticker    — a seamless marquee of credentials under the hero
     2. .cx        — full-width alternating "dossier" panels, one per coach
     3. .ptc       — a smaller card grid for the private-training bench
   Every motion effect here is additive: if JS is off or the visitor has asked for
   reduced motion, the page still lays out and reads correctly.
   ========================================================================== */

/* ---- lighting rig ------------------------------------------------------------
   Josh's note (Aug 18): "the page feels very dark ... better ambient type of lighting".
   The fix is not less black, it is LIT black. A flat fill reads as a switched-off
   screen; what makes a dark layout look expensive is a visible light source, a fill
   from the opposite corner, and grain over the top. Three parts:
     .rig   — coloured pools that slowly drift
     .grain — film noise, which also kills the banding big soft gradients cause
     per-section base tones that step up in luminance as you scroll, so the page
     never shows three identical near-blacks in a row.
   -------------------------------------------------------------------------- */
.rig{position:absolute;inset:0;z-index:0;pointer-events:none;overflow:hidden}
.rig span{position:absolute;display:block;border-radius:50%;filter:blur(40px);will-change:transform}
/* cool key light, upper left */
.rig-key{width:78vw;height:70vh;left:-24vw;top:-30vh;
  background:radial-gradient(circle,rgba(58,166,214,.30),rgba(58,166,214,.09) 45%,transparent 70%);
  animation:drift1 37s ease-in-out infinite alternate}
/* green fill, lower right — opposite corner from the key so the scene has direction */
.rig-fill{width:64vw;height:60vh;right:-18vw;bottom:-26vh;
  background:radial-gradient(circle,rgba(140,198,63,.22),rgba(140,198,63,.06) 46%,transparent 72%);
  animation:drift2 43s ease-in-out infinite alternate}
/* soft warm pool sitting behind the portraits so the faces are lit, not floating */
.rig-pool{width:52vw;height:56vh;right:2vw;top:6vh;
  background:radial-gradient(circle,rgba(255,236,205,.11),rgba(255,214,160,.04) 44%,transparent 70%);
  animation:drift3 53s ease-in-out infinite alternate}
@keyframes drift1{to{transform:translate3d(9vw,7vh,0) scale(1.14)}}
@keyframes drift2{to{transform:translate3d(-8vw,-6vh,0) scale(1.18)}}
@keyframes drift3{to{transform:translate3d(-5vw,5vh,0) scale(1.1)}}

/* Film grain. Inline SVG fractal noise — no network request, no image file, and it
   tiles seamlessly at 160px. Kept very low opacity: it should be felt, not seen.
   NOT called .grain: that name is already taken further down the file by the homepage
   hero's much heavier animated grain (opacity .16, flickering on a .5s step loop over
   the video). Because that rule comes later it would win here on equal specificity, so
   the coaches hero would silently get the homepage's flicker instead of this. */
.grain-soft{position:absolute;inset:0;z-index:1;pointer-events:none;opacity:.05;mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size:160px 160px}

/* ---- hero ---- */
.coach-hero{padding:52px 0 0;overflow:hidden;
  background:radial-gradient(115% 78% at 50% 0%,#1D2027 0%,#15171B 52%,#101114 100%)}
.coach-hero>.wrap{position:relative;z-index:2}
.ch-crest{display:flex;flex-direction:column;align-items:center;text-align:center}
.ch-crest .crumb{margin-bottom:20px}

/* ---- the KPM emblem -------------------------------------------------------------
   Josh (Aug 19): "a KPM logo rendered to be almost 3d line like an emblem and lit with
   cool ambient lighting". The trick is the logo's white silhouette used as a CSS mask:
   a mask lets us paint light THROUGH the logo shape rather than just displaying a flat
   picture of it, which is what makes the depth, the rim light and the sheen possible
   from a plain PNG. The face layer stays the real full-colour artwork — this is his
   brand mark, so it does not get repainted as chrome.
   Layer order back-to-front: glow, depth x3, rim, face, sheen.
   ------------------------------------------------------------------------------- */
.emblem{position:relative;z-index:1;width:clamp(230px,29vw,392px);aspect-ratio:750/300}
/* Slow conic halo turning behind the mark, so the emblem always sits in moving light. */
.emblem::before{content:"";position:absolute;left:50%;top:50%;width:165%;aspect-ratio:1;
  transform:translate(-50%,-50%);border-radius:50%;z-index:0;pointer-events:none;
  background:conic-gradient(from 0deg,transparent 0deg,rgba(58,166,214,.30) 55deg,transparent 125deg,
             rgba(140,198,63,.20) 215deg,transparent 295deg);
  filter:blur(34px);animation:emorbit 19s linear infinite}
@keyframes emorbit{to{transform:translate(-50%,-50%) rotate(360deg)}}

.em-l,.em-face{position:absolute;inset:0;display:block;width:100%;height:100%}
/* Every decorative layer is hidden by default and only switched on where CSS masking
   actually works. Without the mask these are plain rectangles, so an unsupported browser
   would get four coloured boxes stacked behind the logo. Hidden-by-default means the
   fallback is the bare full-colour artwork with its drop-shadows, which still looks right. */
.em-l{display:none}
@supports ((-webkit-mask-image:url("#")) or (mask-image:url("#"))){
  .em-l{display:block;
    -webkit-mask-image:url("photos/brand/kpm-logo-stencil-750.png");
            mask-image:url("photos/brand/kpm-logo-stencil-750.png");
    -webkit-mask-size:contain;        mask-size:contain;
    -webkit-mask-repeat:no-repeat;    mask-repeat:no-repeat;
    -webkit-mask-position:center;     mask-position:center}
}
/* coloured bloom, clipped to the logo shape so the light comes off the mark itself.
   Deliberately restrained: turned up, it stops reading as a lit solid object and starts
   reading as a soft glowing sticker, which is the opposite of an emblem. */
.em-glow{z-index:0;opacity:.34;transform:scale(1.02);filter:blur(22px);
  background:radial-gradient(circle at 50% 45%,rgba(58,166,214,.95),rgba(140,198,63,.5) 58%,transparent 76%)}
/* Extruded thickness — five copies stepped down and right, away from the upper-left key
   light so the extrusion falls where the shadow would. Stepping every ~2px keeps the
   side wall continuous rather than showing as separate stacked outlines. */
.em-depth{z-index:1;background:linear-gradient(180deg,#22505F,#060F15)}
.em-depth.d1{transform:translate(1px,2px);opacity:1}
.em-depth.d2{transform:translate(2.5px,5px);opacity:.8}
.em-depth.d3{transform:translate(4px,8px);opacity:.5}
/* nudged UP so only a lit sliver shows along every top edge = the bevel */
.em-rim{z-index:2;transform:translate(-1px,-2.5px);
  background:linear-gradient(180deg,#FFFFFF 0%,#D8F0FC 34%,transparent 62%)}
/* The real artwork. The tight near-white halo is what gives the etched "line" edge;
   the cast shadow below sells it as an object sitting off the page. Kept the coloured
   bloom small here — .em-glow already supplies the ambient colour. */
.em-face{z-index:3;object-fit:contain;
  filter:drop-shadow(0 0 .5px rgba(228,246,255,1))
         drop-shadow(0 1px 4px rgba(58,166,214,.4))
         drop-shadow(0 14px 22px rgba(0,0,0,.7))}
/* specular highlight travelling across the mark */
.em-sheen{z-index:4;mix-blend-mode:screen;background-size:260% 100%;
  background-image:linear-gradient(105deg,transparent 36%,rgba(255,255,255,.9) 47%,transparent 60%);
  animation:emsheen 6.5s ease-in-out infinite}
@keyframes emsheen{0%,14%{background-position:132% 0}64%,100%{background-position:-42% 0}}

/* Rules flank the title out to the edges of the wrap. A centred composition leaves big
   empty bands either side of the headline — Josh flagged dead space — and this fills
   them without costing a single pixel of height. The .t wrapper matters: without it the
   text node "The" and the <span class="sweep"> would each become their own flex item and
   the flex gap would push the two words apart. */
.ch-title{display:flex;align-items:center;justify-content:center;width:100%;
          gap:clamp(14px,3vw,40px);
          font-family:var(--display);text-transform:uppercase;line-height:.9;letter-spacing:.005em;
          font-size:clamp(38px,5.8vw,80px);margin:18px 0 12px}
/* flex:0 1 auto, NOT 0 0 auto. As a non-shrinking flex item the title could not
   wrap: on a 375px phone "Speed and Performance Programs" simply ran past the
   edge and the hero's overflow:hidden sliced both ends off it — the page showed
   no horizontal scroll, so nothing flagged it. min-width:0 is the other half;
   without it a flex item refuses to shrink below its content's intrinsic width
   even when it is allowed to. The flanking rules are flex:1 1 0 and collapse
   first, so the text gets the room. */
.ch-title>.t{flex:0 1 auto;min-width:0}
.ch-title::before,.ch-title::after{content:"";flex:1 1 0;height:1px;max-width:270px;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.26))}
.ch-title::after{background:linear-gradient(90deg,rgba(255,255,255,.26),transparent)}
.ch-sub{color:var(--muted-d);font-size:16.5px;max-width:58ch;margin:0 auto}
/* Specular sweep across the word "Coaches". Guarded by @supports because without
   background-clip:text the transparent fill would render the word invisible. */
@supports ((-webkit-background-clip:text) or (background-clip:text)){
  .ch-title .sweep{background:linear-gradient(100deg,#fff 0%,#fff 38%,#BEE6F8 47%,#fff 56%,#fff 100%);
    background-size:280% 100%;-webkit-background-clip:text;background-clip:text;
    color:transparent;-webkit-text-fill-color:transparent;
    animation:sweep 7s ease-in-out infinite}
}
@keyframes sweep{0%,18%{background-position:118% 0}68%,100%{background-position:-18% 0}}
.ch-actions{display:flex;flex-wrap:wrap;gap:12px;margin-top:26px;justify-content:center}
.btn-ghost-d{background:transparent;color:#fff;border:1px solid rgba(255,255,255,.24)}
.btn-ghost-d:hover{border-color:var(--accent);background:rgba(58,166,214,.12)}

/* ---- stat medallions -------------------------------------------------------------
   Josh asked for the combined-experience numbers "in an emblem like format too", then
   (Aug 19) that they looked blurry and like an afterthought. Rebuilt around three rules:

   1. NOTHING BLURRY BEHIND A NUMBER. The old version had a text-shadow glow under every
      digit and, worse, scaled the headline disc with transform:scale(). Transform scales
      the already-rendered pixels, so that number was genuinely resampled and soft — a
      real defect, not a matter of taste. Every size here is now a real font-size and a
      real width, so the text is rasterised once at its final size.
   2. CRISP RINGS. Concentric rings are drawn with zero-blur box-shadow spread, which
      lands on exact pixel edges, instead of soft inset shadows that feather into mush.
   3. THE RING IS THE LOADER. Instead of decoration spinning forever with no relationship
      to the content, each medallion has an SVG progress ring that draws itself once,
      from 12 o'clock, over the same 1.5s the number counts up in app.js. It arrives,
      completes, and stops — which is what makes it read as deliberate rather than
      as filler pinned on afterwards.
   ------------------------------------------------------------------------------- */
.crest-rail{position:relative;display:grid;grid-template-columns:repeat(4,1fr);
            gap:18px;margin:46px 0 42px;
            --ring:clamp(94px,10.4vw,126px);
            --ringbig:clamp(122px,13.4vw,162px);
            --num:clamp(22px,2.35vw,30px);
            --numbig:clamp(29px,3.15vw,41px)}
/* Every crest reserves the FULL height of the big disc in its first row and centres the
   disc inside it. That is what keeps all four centres on one axis — and it does it as
   pure layout, so the labels underneath line up on the same baseline for free. The old
   transform trick achieved the alignment but at the cost of the blur above. */
.crest{position:relative;z-index:1;display:grid;grid-template-rows:var(--ringbig) auto;
       align-items:center;justify-items:center;gap:15px;text-align:center}
/* Hairline through all four centres — ties the rail into one crest bar, not four islands */
.crest-rail::before{content:"";position:absolute;z-index:0;left:8%;right:8%;
  top:calc(var(--ringbig) / 2);height:1px;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.18) 14%,
             rgba(255,255,255,.18) 86%,transparent)}

.crest-ring{position:relative;width:var(--ring);aspect-ratio:1;border-radius:50%;
  display:grid;place-items:center;
  background:radial-gradient(circle at 50% 28%,#20262E 0%,#141920 58%,#0D1116 100%);
  box-shadow:0 0 0 1px rgba(255,255,255,.10),
             inset 0 0 0 1px rgba(255,255,255,.045),
             0 18px 34px -24px rgba(0,0,0,.95),
             0 0 40px -20px rgba(58,166,214,.55)}

/* The loader. rotate(-90deg) starts the draw at 12 o'clock; r=45 gives a circumference
   of 2*PI*45 = 282.743, which is the dasharray/dashoffset both halves key off.
   non-scaling-stroke keeps the stroke an exact pixel width at any medallion size. */
/* width/height are set explicitly rather than left to inset:0. An <svg> is a replaced
   element, and replaced elements size to their INTRINSIC size when width/height are
   auto — insets alone only position them. Being explicit keeps this predictable. */
.crest-arc{position:absolute;left:0;top:0;width:100%;height:100%;
           transform:rotate(-90deg);pointer-events:none;overflow:visible}
.crest-arc circle{fill:none;stroke-linecap:round;vector-effect:non-scaling-stroke}
.crest-arc .trk{stroke:rgba(255,255,255,.13);stroke-width:1}
/* The glow lives on the ring, never on the number — that separation is the whole point
   of the rebuild. drop-shadow on the stroke keeps the medallion feeling lit without
   putting anything soft behind a digit. */
.crest-arc .prg{stroke:var(--accent);stroke-width:2;
  filter:drop-shadow(0 0 6px rgba(58,166,214,.6));
  stroke-dasharray:282.743;stroke-dashoffset:282.743;
  transition:stroke-dashoffset 1.5s cubic-bezier(.22,1,.36,1)}
.crest-rail.in .crest-arc .prg{stroke-dashoffset:0}
/* Staggered so the four rings fill left-to-right rather than firing as one block */
.crest:nth-child(2) .crest-arc .prg{transition-delay:.09s}
.crest:nth-child(3) .crest-arc .prg{transition-delay:.18s}
.crest:nth-child(4) .crest-arc .prg{transition-delay:.27s}

/* tabular-nums stops the digits changing width mid count-up, which reads as jitter */
.crest-ring b{position:relative;z-index:1;font-family:var(--display);line-height:1;
  font-size:var(--num);letter-spacing:.005em;color:#fff;
  font-variant-numeric:tabular-nums;font-feature-settings:"tnum" 1}
.crest-u{font-family:var(--mono);font-size:11px;letter-spacing:0.14em;text-transform:uppercase;
         color:rgba(255,255,255,.68);transition:color .3s}

/* The headline figure — genuinely larger, not a scaled copy of a smaller one. */
.crest.is-big .crest-ring{width:var(--ringbig);
  background:radial-gradient(circle at 50% 28%,#24303A 0%,#161C24 58%,#0D1116 100%);
  box-shadow:0 0 0 1px rgba(255,255,255,.16),
             inset 0 0 0 1px rgba(255,255,255,.06),
             0 22px 44px -24px rgba(0,0,0,.95),
             0 0 58px -18px rgba(140,198,63,.55)}
.crest.is-big .crest-ring b{font-size:var(--numbig)}
.crest.is-big .crest-arc .prg{stroke:var(--green);stroke-width:2.5;
  filter:drop-shadow(0 0 9px rgba(140,198,63,.55))}
.crest.is-big .crest-arc .trk{stroke:rgba(255,255,255,.17)}
.crest.is-big .crest-u{color:#fff;font-weight:600}

/* Portrait podium — staggered heights so it reads as a podium rather than a row.
   Capped well inside the wrap: at full 1240px width three 3:4 portraits become huge
   slabs that bury the emblem they are supposed to sit underneath. */
.ch-stack{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;align-items:end;
          max-width:1000px;margin:0 auto}
/* Gentle bob. Uses the standalone `translate` property, NOT transform — the cards
   already use transform for the podium stagger and again on hover, and an animation
   on the same property would fight both. `translate` composes with transform instead. */
@keyframes chfloat{0%,100%{translate:0 0}50%{translate:0 -9px}}
.ch-card{animation:chfloat 7.5s ease-in-out infinite}
.ch-card:nth-child(2){animation-delay:-2.4s}
.ch-card:nth-child(3){animation-delay:-4.9s}
.ch-stack:hover .ch-card{animation-play-state:paused}
.ch-card{position:relative;border-radius:var(--r-lg);overflow:hidden;
  border:1px solid rgba(255,255,255,.14);background:var(--ink-2);
  box-shadow:0 26px 60px -26px rgba(0,0,0,.9),0 0 42px -14px rgba(58,166,214,.28);
  transition:transform .45s cubic-bezier(.16,1,.3,1),box-shadow .45s,border-color .45s}
.ch-card:nth-child(1){transform:translateY(26px) rotate(-1.4deg)}
.ch-card:nth-child(2){transform:translateY(-6px) rotate(.5deg);z-index:2}
.ch-card:nth-child(3){transform:translateY(38px) rotate(1.6deg)}
.ch-stack:hover .ch-card{opacity:.62}
.ch-stack .ch-card:hover{opacity:1;border-color:rgba(58,166,214,.5);
  box-shadow:0 30px 70px -24px rgba(0,0,0,.9),0 0 60px -10px rgba(58,166,214,.5)}
.ch-card:nth-child(1):hover{transform:translateY(16px) rotate(-1.4deg) scale(1.03)}
.ch-card:nth-child(2):hover{transform:translateY(-16px) rotate(.5deg) scale(1.03)}
.ch-card:nth-child(3):hover{transform:translateY(28px) rotate(1.6deg) scale(1.03)}
/* height:auto is load-bearing, not tidiness. The width/height attributes on the <img>
   are presentational hints, so without it the browser uses the literal 1125px from the
   markup and aspect-ratio is ignored — the cards rendered 200px wide and 1130px tall. */
.ch-card img{width:100%;height:auto;aspect-ratio:3/4;object-fit:cover;display:block;
             filter:saturate(1.05) contrast(1.03)}
/* scrim so the caption stays legible over any photo we drop in later */
.ch-card figcaption{position:absolute;left:0;right:0;bottom:0;padding:34px 14px 12px;
  background:linear-gradient(transparent,rgba(10,11,13,.9))}
.ch-card figcaption b{display:block;font-family:var(--display);text-transform:uppercase;
  font-size:14px;letter-spacing:.02em;line-height:1;color:#fff}
.ch-card figcaption span{display:block;font-family:var(--mono);font-size:11px;letter-spacing:0.14em;
  text-transform:uppercase;color:rgba(255,255,255,.6);margin-top:5px}

.coach-hero .statrail{margin-top:44px;margin-bottom:46px;border-top-color:rgba(255,255,255,.16)}

/* Credential marquee. The track holds the list TWICE and the keyframe travels
   exactly -50%, so the second copy lands where the first started and the seam is
   invisible. Edit one copy in the HTML, edit both. */
.ticker{position:relative;z-index:2;border-top:1px solid var(--line-d);border-bottom:1px solid var(--line-d);
        overflow:hidden;padding:14px 0;background:rgba(0,0,0,.24);
        /* fade the ends so words don't get chopped mid-letter at the edges */
        mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent);
        -webkit-mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent)}
.ticker-track{display:flex;align-items:center;gap:0;width:max-content;animation:tick 42s linear infinite}
.ticker:hover .ticker-track{animation-play-state:paused}
.tk{font-family:var(--mono);font-size:11.5px;letter-spacing:0.14em;text-transform:uppercase;
    color:rgba(255,255,255,.62);white-space:nowrap;padding:0 26px}
.tk-d{width:5px;height:5px;border-radius:50%;background:var(--accent);flex:none;opacity:.8}
@keyframes tick{to{transform:translate3d(-50%,0,0)}}

/* ---- the staff panels ---- */
/* The base tone LIFTS as you scroll (#131519 -> #1B1E24). Three sections of identical
   near-black was the real reason the page read as a tunnel; a few percent of luminance
   travel is enough to give it depth without going light. */
.cx-section{position:relative;isolation:isolate;color:#fff;padding-bottom:var(--sec);overflow:hidden;
  background:linear-gradient(180deg,#131519 0%,#171A1F 55%,#1B1E24 100%)}
.cx-section::before{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;opacity:.045;
  mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size:160px 160px}
.cx-section>*{position:relative;z-index:1}
.cx-head{margin-bottom:8px}
.cx-head h2{color:#fff}
.cx-head p{color:var(--muted-d);max-width:560px}

.cx{position:relative;padding:72px 0;border-top:1px solid rgba(255,255,255,.08)}
.cx:first-of-type{border-top:none}
/* Pointer spotlight. app.js writes --mx/--my as percentages; the fallback centre
   keeps it invisible-but-valid on touch devices where the pointer never moves. */
.cx::before{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;opacity:0;
  transition:opacity .45s ease;
  background:radial-gradient(560px circle at var(--mx,50%) var(--my,50%),rgba(58,166,214,.10),transparent 62%)}
.cx.lit::before{opacity:1}
/* Ambient pool behind each coach, always on (the ::before spotlight only appears when
   a mouse is actually over the panel — on a phone it never fires at all). Sitting it
   behind the portrait rather than the text means each coach reads as individually lit
   instead of three people in the same dark room. The colour alternates and the side
   follows the panel's flip, so the light always comes from behind the face. */
.cx::after{content:"";position:absolute;z-index:0;pointer-events:none;
  width:70%;height:120%;top:-10%;left:-14%;border-radius:50%;filter:blur(60px);
  background:radial-gradient(circle,rgba(58,166,214,.16),rgba(58,166,214,.05) 46%,transparent 70%)}
.cx:nth-of-type(even)::after{
  background:radial-gradient(circle,rgba(140,198,63,.14),rgba(140,198,63,.04) 46%,transparent 70%)}
.cx-flip::after{left:auto;right:-14%}
.cx-inner{position:relative;z-index:1;display:grid;grid-template-columns:minmax(0,0.92fr) minmax(0,1.08fr);
          gap:clamp(32px,5vw,80px);align-items:center}
.cx-flip .cx-media{order:2}

/* media */
.cx-media{position:relative;perspective:1100px}
.cx-no{position:absolute;top:-34px;left:-14px;z-index:2;font-family:var(--display);font-size:clamp(72px,9vw,132px);
       line-height:1;letter-spacing:.02em;color:transparent;-webkit-text-stroke:1.5px rgba(255,255,255,.17);
       pointer-events:none;user-select:none}
.cx-flip .cx-no{left:auto;right:-14px}
.cx-frame{position:relative;border-radius:var(--r-lg);overflow:hidden;border:1px solid rgba(255,255,255,.12);
          background:var(--ink-2);box-shadow:0 30px 70px -30px rgba(0,0,0,.85);
          transform-style:preserve-3d;transition:transform .5s cubic-bezier(.16,1,.3,1),border-color .4s}
.cx.tilting .cx-frame{transition:transform .12s linear}
.cx:hover .cx-frame{border-color:rgba(58,166,214,.4)}
.cx-ph{aspect-ratio:4/5;overflow:hidden}
/* Photos arrive desaturated and resolve to full colour as the panel reveals — the
   same "before/after" idea the rest of the site runs on, applied to the portraits. */
/* Resting desaturation is deliberately mild (.42, was .72). At .72 the three largest
   images on the page were pushed to near-grey, which drained most of the light back
   out of a page Josh already said was too dark. Brightness is nudged up alongside it
   so the "before" state still reads as treated rather than just dim. */
.cx-ph img{width:100%;height:100%;object-fit:cover;display:block;
           filter:grayscale(.42) contrast(1.04) brightness(1.04);transform:scale(1.06);
           transition:filter 1.1s ease,transform .7s cubic-bezier(.16,1,.3,1)}
.cx.in .cx-ph img{filter:grayscale(0) contrast(1.02) brightness(1.06) saturate(1.05)}
.cx:hover .cx-ph img{transform:scale(1.11)}
/* single accent line that sweeps down the portrait once on reveal */
.cx-scan{position:absolute;left:0;right:0;top:0;height:2px;pointer-events:none;opacity:0;
         background:linear-gradient(90deg,transparent,var(--accent),transparent)}
.cx.in .cx-scan{animation:cxscan 1.5s .25s cubic-bezier(.4,0,.2,1) 1}
@keyframes cxscan{0%{opacity:0;top:0}12%{opacity:.9}88%{opacity:.9}100%{opacity:0;top:100%}}

/* body — the copy column stages in line by line as the panel reveals.
   The hidden start state is inside :where(.js) so it only ever applies when the
   script that clears it is actually running (see the head script in coaches.html). */
.cx-body>*{transition:opacity .6s ease,transform .6s cubic-bezier(.16,1,.3,1)}
:where(.js) .cx-body>*{opacity:0;transform:translateY(18px)}
.cx.in .cx-body>*{opacity:1;transform:none}
.cx.in .cx-body>*:nth-child(2){transition-delay:.07s}
.cx.in .cx-body>*:nth-child(3){transition-delay:.14s}
.cx.in .cx-body>*:nth-child(4){transition-delay:.21s}
.cx.in .cx-body>*:nth-child(5){transition-delay:.28s}
.cx.in .cx-body>*:nth-child(6){transition-delay:.35s}
.cx.in .cx-body>*:nth-child(7){transition-delay:.35s}

.cx-role{font-family:var(--mono);font-size:11px;letter-spacing:0.14em;text-transform:uppercase;color:var(--accent)}
.cx-name{font-family:var(--display);text-transform:uppercase;font-size:clamp(40px,5.6vw,76px);
         line-height:.88;letter-spacing:.005em;margin:14px 0 18px}
.cx-kick{font-size:clamp(17px,1.6vw,21px);line-height:1.42;color:#fff;font-weight:600;max-width:30ch;margin-bottom:22px}
.cx-chips{list-style:none;display:flex;flex-wrap:wrap;gap:8px;margin-bottom:24px}
.cx-chips li{font-family:var(--mono);font-size:11px;letter-spacing:.14em;text-transform:uppercase;
             color:rgba(255,255,255,.82);border:1px solid rgba(255,255,255,.18);
             border-radius:var(--r-pill);padding:7px 14px;background:rgba(255,255,255,.04)}
.cx-lead{font-size:15.5px;line-height:1.7;color:rgba(255,255,255,.74);max-width:60ch}
.cx-more{max-width:60ch}
.cx-more p{font-size:15.5px;line-height:1.7;color:rgba(255,255,255,.74);margin-top:16px}

/* Expandable bio. [hidden] is removed by JS before measuring, so the panel still
   reads to search engines and to a no-JS visitor as plain visible text. */
.cx-more[hidden]{display:none}
.cx-more.anim{overflow:hidden;transition:height .45s cubic-bezier(.16,1,.3,1),opacity .35s ease}
.cx-toggle{margin-top:22px;display:inline-flex;align-items:center;gap:11px;background:transparent;
           border:1px solid rgba(255,255,255,.24);border-radius:var(--r-pill);padding:11px 20px;
           color:#fff;font-family:var(--body);font-weight:700;font-size:13px;letter-spacing:.04em;
           cursor:pointer;transition:border-color .25s,background .25s}
.cx-toggle:hover{border-color:var(--accent);background:rgba(58,166,214,.12)}
.cx-toggle .ico{position:relative;width:11px;height:11px;flex:none}
.cx-toggle .ico::before,.cx-toggle .ico::after{content:"";position:absolute;background:var(--accent);
  transition:transform .3s cubic-bezier(.16,1,.3,1)}
.cx-toggle .ico::before{left:0;top:5px;width:11px;height:1.5px}
.cx-toggle .ico::after{left:5px;top:0;width:1.5px;height:11px}
.cx-toggle[aria-expanded="true"] .ico::after{transform:scaleY(0)}

/* ---- private training bench ---- */
/* Continues the ladder: this section starts where .cx-section finished (#1B1E24) and
   climbs again, so the bottom of the page is the lightest point rather than dropping
   back to the flat --ink-2 it used to sit on. Same grain treatment for continuity. */
.ptc-section{position:relative;isolation:isolate;color:#fff;overflow:hidden;
  background:linear-gradient(180deg,#1B1E24 0%,#20242B 60%,#23272F 100%)}
.ptc-section::before{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;opacity:.045;
  mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size:160px 160px}
.ptc-section>*{position:relative;z-index:1}
.ptc-section .sec-head h2{color:#fff}
.ptc-section .sec-head p{color:var(--muted-d);max-width:620px}
.ptc-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:20px;margin-top:40px}
.ptc{border:1px solid rgba(255,255,255,.12);border-radius:var(--r-md);overflow:hidden;
     background:rgba(255,255,255,.035);display:flex;flex-direction:column;
     transition:transform .3s cubic-bezier(.16,1,.3,1),border-color .3s,background .3s}
.ptc:hover{transform:translateY(-5px);border-color:rgba(58,166,214,.42);background:rgba(255,255,255,.06)}
.ptc-ph{aspect-ratio:4/5;overflow:hidden;background:var(--ink-3)}
.ptc-ph img{width:100%;height:100%;object-fit:cover;display:block;transition:transform .5s cubic-bezier(.16,1,.3,1)}
.ptc:hover .ptc-ph img{transform:scale(1.05)}
.ptc-ph.none{display:flex;align-items:center;justify-content:center;
             background:linear-gradient(155deg,var(--ink-3),var(--ink))}
.ptc-ph.none i{font-family:var(--display);font-style:normal;font-size:44px;
               color:rgba(255,255,255,.2);letter-spacing:.03em}
.ptc-body{padding:24px 24px 28px}
.ptc-role{font-family:var(--mono);font-size:11px;letter-spacing:0.14em;text-transform:uppercase;color:var(--accent)}
.ptc-body h3{font-family:var(--display);text-transform:uppercase;font-size:26px;line-height:1;margin:12px 0 14px}
.ptc-body p{font-size:14.5px;line-height:1.68;color:rgba(255,255,255,.7)}
.ptc-cta{margin-top:40px}

/* Panels stack on narrow screens: photo first, then the words. The tilt and the
   spotlight are switched off in JS below this width, not just visually hidden. */
@media(max-width:900px){
  .cx{padding:52px 0}
  .cx-inner{grid-template-columns:1fr;gap:30px}
  .cx-flip .cx-media{order:0}
  .cx-media{max-width:440px}
  .cx-no{top:-26px;font-size:64px}
  .cx-flip .cx-no{left:-10px;right:auto}
  .ptc-grid{grid-template-columns:1fr 1fr}
  /* Rotations get flattened here. They read as intentional at desktop size, but at
     phone widths the tilt on a 110px card just looks like something is broken. */
  .ch-card:nth-child(1),
  .ch-card:nth-child(2),
  .ch-card:nth-child(3){transform:none}
  .ch-stack{gap:9px;align-items:stretch}
  .crest-rail{gap:14px}
  .crest-rail::before{left:12%;right:12%}
}
@media(max-width:620px){
  .ptc-grid{grid-template-columns:1fr}
  .cx-name{font-size:clamp(34px,10vw,46px)}
  .tk{font-size:11px;padding:0 18px}
  .coach-hero{padding-top:34px}
  .ch-actions .btn{flex:1 1 100%;justify-content:center}
  /* Medallions go 2x2. The connecting hairline is switched off — it only makes sense
     as a single horizontal bar through four centres, and across two rows it would cut
     the second row in half. */
  .crest-rail{grid-template-columns:1fr 1fr;gap:26px 14px;margin:34px 0 30px}
  .crest-rail::before{display:none}
  .emblem{width:min(76vw,300px)}
  /* Captions shrink with the cards. Below this width the plate is ~110px across, so
     the name goes to two lines unless it comes down with it. */
  .ch-card figcaption{padding:26px 8px 9px}
  .ch-card figcaption b{font-size:11px}
  .ch-card figcaption span{font-size:11px;letter-spacing:.12em;margin-top:3px}
  /* Big blurred pools are the most expensive thing on the page to composite and the
     least visible on a small screen. Trim to the key light plus a smaller fill. */
  .rig span{filter:blur(30px)}
  .rig-pool{display:none}
}

/* Anyone who has asked their device to reduce motion gets the page with no
   marquee, no scan line, no tilt, and photos already in full colour. */
@media(prefers-reduced-motion:reduce){
  .ticker-track{animation:none}
  .cx-scan{display:none}
  .cx-ph img{filter:none;transform:none;transition:none}
  .cx-more.anim{transition:none}
  :where(.js) .cx-body>*{opacity:1;transform:none}
  .cx-body>*{transition:none}
  /* The lighting stays, the movement goes. Killing the drift entirely would flatten
     the hero back to the look Josh just asked me to fix, so the pools keep their
     colour and position and simply stop travelling. Same principle for the emblem and
     the medallions: every glow, bevel and ring is still drawn, nothing revolves. */
  .rig span{animation:none}
  .ch-title .sweep{animation:none}
  .ch-card{transition:none;animation:none}
  .emblem::before{animation:none}
  .em-sheen{animation:none;opacity:.35;background-position:40% 0}
  /* The loader rings are drawn complete rather than animating in, so the medallions
     still read as finished objects instead of half-empty circles. */
  .crest-arc .prg{transition:none;stroke-dashoffset:0}
}

/* alumni wall */
.wall{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;margin-top:8px}
.tile{background:var(--ink-2);border:1px solid var(--line-d);padding:26px 22px;min-height:150px;display:flex;flex-direction:column;justify-content:flex-end;transition:background .25s}
.tile:hover{background:var(--ink-3)}
.tile b{font-family:var(--display);text-transform:uppercase;font-size:21px;line-height:.98;letter-spacing:.01em}
.tile span{font-family:var(--mono);font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--muted-d);margin-top:9px}
.tile.accent{background:var(--accent)}
.tile.accent:hover{background:var(--accent-deep)}
.tile.accent span{color:rgba(255,255,255,.85)}

/* animation */
@keyframes reveal{to{transform:translateY(0)}}
@keyframes fadeUp{from{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}
@keyframes draw{to{stroke-dashoffset:0}}
.reveal-on{transition:opacity .7s,transform .7s}
/* :where(.js) adds no specificity, so this still weighs exactly what a bare
   .reveal-on did and every existing override keeps winning. No .js class
   (JavaScript off, or the script failed) means content is never hidden. */
:where(.js) .reveal-on{opacity:0;transform:translateY(26px)}
.reveal-on.in{opacity:1;transform:none}

/* responsive */
@media(max-width:1000px){
  .man-grid{grid-template-columns:1fr;gap:44px}
  .pillars,.prog-grid,.proof-grid,.coach-grid{grid-template-columns:1fr 1fr}
  .foot-top{grid-template-columns:1fr 1fr}
  .cycle{grid-template-columns:1fr}
  .wall{grid-template-columns:repeat(2,1fr)}
  .pblock,.pblock.rev{grid-template-columns:1fr;direction:ltr;gap:28px;padding:48px 0}
  .mrow{gap:28px}
  .mrow-fig{width:220px}
}
@media(max-width:860px){
  .nav-links,.sign-in{display:none}
  .menu-toggle{display:block}
  /* On a 390px phone the full-size "Book a Gait Analysis" pill is 213px wide, which leaves
     literally 0px between it and the logo and forces the label onto two lines. Dropping the
     type a step, tightening the padding and hiding the arrow gets it onto one line with room
     to breathe, without removing the CTA from the bar. */
  .nav-cta{gap:8px}
  .nav-cta .btn-accent{font-size:11px;letter-spacing:.04em;padding:10px 14px}
  .nav-cta .btn-accent .arw{display:none}
  .statrail{grid-template-columns:1fr 1fr}
  .stat:nth-child(2){border-right:none}
  .stat{border-bottom:1px solid var(--line-d)}
  .mrow{grid-template-columns:1fr;gap:12px}
  /* Capped: uncapped, width:100% made this a 693px square at 768px wide, which ate two
     thirds of a tablet screen. 420 keeps it a photo rather than a takeover, and phones
     under 420 still get the full-bleed square. */
  .mrow-fig{width:100%;max-width:420px;aspect-ratio:1/1;margin-top:var(--s-2)}
}
@media(max-width:640px){
  .wrap{padding:0 20px}
  .hero{padding:70px 0 0}
  .pillars,.prog-grid,.proof-grid,.coach-grid,.wall{grid-template-columns:1fr}
  .foot-top{grid-template-columns:1fr}
    .man-lead,.method-head h2,.prog-head h2,.proof-head h2,.sec-head h2{font-size:clamp(34px,10vw,48px)}
  .affil{gap:24px}
}
@media(prefers-reduced-motion:reduce){
  *{animation:none!important;transition:none!important}
  .hero h1 .l i{transform:none}
  .hero-eyebrow,.hero-sub,.hero-actions{opacity:1}
  .reveal-on{opacity:1;transform:none}
  .curve path{stroke-dashoffset:0}
}
/* superseded by the measured focus ring further down — see the note there */
:focus-visible{outline:2px solid var(--ink);outline-offset:3px}

/* ===== MARKETING COMPONENTS ===== */
.stamp{display:inline-flex;align-items:center;gap:8px;font-family:var(--mono);font-size:11px;letter-spacing:0.14em;text-transform:uppercase;color:var(--green-deep);border:1px solid var(--green);padding:6px 11px;border-radius:var(--r-md)}
.section-d .stamp{color:var(--green)}
.stamp::before{content:"";width:6px;height:6px;background:var(--green);border-radius:50%}

/* hero hook substat note */
.hooknote{font-family:var(--mono);font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--muted-d);margin-top:18px;position:relative;z-index:2}
.hooknote b{color:var(--green)}

/* credibility band uses .pblock; add client list */
.clients{list-style:none;margin-top:8px}
.clients li{font-size:16px;color:#2C313A;padding:15px 0 15px 30px;border-top:1px solid var(--line-l);position:relative;font-weight:600}
.clients li:last-child{border-bottom:1px solid var(--line-l)}
.clients li::before{content:"✓";position:absolute;left:0;color:var(--green-deep);font-weight:800}
.clients li span{display:block;font-weight:400;font-size:13.5px;color:var(--muted);margin-top:3px;font-family:var(--mono);letter-spacing:.04em}
.section-d .clients li{color:#fff;border-color:var(--line-d)}
.section-d .clients li span{color:var(--muted-d)}

/* transformations */
.xgrid{display:grid;grid-template-columns:repeat(3,1fr);gap:20px}
.xform{background:var(--paper-2);border:1px solid var(--line-l);border-radius:var(--r-lg);
  padding:30px 28px;position:relative;overflow:hidden;
  box-shadow:0 1px 2px rgba(22,23,26,.04),0 10px 24px -18px rgba(22,23,26,.3);
  transition:transform .22s,box-shadow .22s,border-color .22s}
.xform:hover{transform:translateY(-4px);border-color:rgba(110,168,46,.4);
  box-shadow:0 2px 4px rgba(22,23,26,.05),0 26px 54px -26px rgba(22,23,26,.42)}
/* The accent bar used to appear only on hover, which meant it did not exist at all on a
   phone. It is always there now, and grows on hover instead of arriving. */
.xform::before{content:"";position:absolute;top:0;left:0;width:100%;height:3px;
  background:linear-gradient(90deg,var(--green),var(--sky));
  transform:scaleX(.18);transform-origin:left;transition:transform .4s cubic-bezier(.16,1,.3,1)}
.xform:hover::before{transform:scaleX(1)}
.xform.feature{grid-column:1 / -1;display:grid;grid-template-columns:1fr 1fr;gap:44px;align-items:center;padding:0;overflow:hidden}
.xform.feature .fmedia{align-self:stretch;min-height:340px;background:linear-gradient(150deg,var(--ink-2),var(--ink));position:relative;display:grid;place-items:center}
.xform.feature .fmedia::before{content:"";position:absolute;inset:0;background:repeating-linear-gradient(90deg,transparent 0 calc(100%/5 - 1px),rgba(255,255,255,.05) calc(100%/5 - 1px) calc(100%/5))}
.xform.feature .fmedia .ph{position:relative;font-family:var(--mono);font-size:11px;letter-spacing:0.14em;text-transform:uppercase;color:rgba(255,255,255,.4)}
.xform.feature .fbody{padding:40px 44px 40px 0}
/* `.xform .badge` and `.xform .dest` used to sit here. Both matched ZERO elements — the
   markup calls them `.badge-tag` and the destination line was folded into `.note`. They
   were removed because they looked like live rules and hid a real bug: `.badge-tag` had no
   styling at all. See "RESULTS: THE HEADLINE CASE, IN BLACK" at the end of this file. */
.xform h3{font-family:var(--display);text-transform:uppercase;font-size:30px;margin:0 0 6px;line-height:1}
.xform.feature h3{font-size:clamp(26px,3.4vw,40px)}
.xform .note{font-size:14.5px;color:#41454E;margin-top:20px;max-width:440px}
/* Josh, Sept 4: "the font isn't great ... I don't like the way it all looks."
   The diagnosis was the typeface doing the wrong job. These numbers were Bebas at 21px —
   Bebas is condensed all-caps display type, right for a 100px headline and wrong for
   "19″ → 27.4″", where the digits crowd together and the prime marks disappear. Numbers are
   Inter now, tabular so the columns line up, and the BEFORE and AFTER are no longer the same
   size: the before is small and grey, the after is the hero. That hierarchy is the whole
   point of the card — a reader should get the improvement without reading the label.
   Headlines stay Bebas. Anything a visitor has to actually READ is Inter.
   The after number was also --green-deep, which measures 2.87:1 on white and failed AA —
   the single most important number on the card was the hardest to read. --green-ink is
   5.14:1 and still unmistakably the brand green. */
.xstats{display:flex;flex-wrap:wrap;gap:10px}
.xstat{border:1px solid var(--line-l);border-radius:var(--r-md);padding:12px 16px;
  background:linear-gradient(180deg,#fff,#FBFBFA);min-width:118px;
  transition:border-color .2s,transform .2s}
.xform:hover .xstat{border-color:rgba(110,168,46,.34)}
.xstat .lab{font-family:var(--body);font-size:10px;font-weight:700;letter-spacing:.12em;
  text-transform:uppercase;color:#6A6E77}
.xstat .val{font-family:var(--body);font-weight:600;font-size:14px;line-height:1.1;
  margin-top:8px;white-space:nowrap;color:#71767F;
  display:flex;align-items:baseline;gap:5px;
  font-variant-numeric:tabular-nums;font-feature-settings:"tnum"}
/* The arrow is decoration between two numbers, not content, so it is exempt from the
   4.5:1 text floor. The BEFORE number is not — it is #71767F, 4.57:1. */
.xstat .val .to{color:#C3C7CD;margin:0;font-size:12px;font-weight:700}
.xstat .val .aft{font-size:26px;font-weight:800;letter-spacing:-.02em;color:var(--green-ink)}

/* by-the-numbers wall cues */
.tile .cue{font-family:var(--mono);font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--green);margin-top:12px;line-height:1.5}
.tile .stat-big{font-family:var(--display);font-size:30px;line-height:.9;color:var(--sky);margin-bottom:4px}

/* trained-here names strip */
.names{display:flex;gap:14px;flex-wrap:wrap;margin-top:10px}
.name-chip{border:1px solid var(--line-d);padding:16px 20px;flex:1;min-width:200px}
.name-chip b{font-family:var(--display);text-transform:uppercase;font-size:20px;letter-spacing:.01em;display:block;line-height:1}
.name-chip span{font-family:var(--mono);font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--muted-d);margin-top:9px;display:block}

@media(max-width:1000px){
  .xgrid{grid-template-columns:1fr 1fr}
  .xform.feature{grid-template-columns:1fr}
  .xform.feature .fbody{padding:32px 28px}
  .xform.feature .fmedia{min-height:220px}
}
@media(max-width:640px){
  .xgrid{grid-template-columns:1fr}
}

/* ===== HERO MOTION LAYER ===== */
/* Drop hero.mp4 (or .webm) next to the html and it plays automatically.
   Until then, the animated fallback below shows through. */
.hero-video{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:0;opacity:.85;filter:saturate(.95) contrast(1.02) brightness(.92)}
/* directional scrim: dark under the headline, clearing toward the footage */
.hero-scrim{position:absolute;inset:0;z-index:1;pointer-events:none;background:linear-gradient(100deg,rgba(22,23,26,.94) 0%,rgba(22,23,26,.88) 34%,rgba(22,23,26,.62) 62%,rgba(22,23,26,.42) 100%)}
.hero-scrim::after{content:"";position:absolute;inset:0;background:linear-gradient(180deg,rgba(22,23,26,.55) 0%,transparent 26%,transparent 62%,rgba(22,23,26,.75) 100%)}
.has-video .has-video .hero-lanes{opacity:.5}
@keyframes drift2{from{transform:translate3d(0,0,0) scale(1.05)}to{transform:translate3d(9%,-8%,0) scale(.92)}}
@keyframes drift3{from{transform:translate3d(0,0,0)}to{transform:translate3d(-11%,-6%,0)}}
@keyframes sweep{0%{left:-30%}55%{left:118%}100%{left:118%}}
/* film grain — the single biggest cure for "cold and digital" */
.grain{position:absolute;inset:0;z-index:2;pointer-events:none;opacity:.16;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.82' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");animation:grainshift .5s steps(3) infinite}
@keyframes grainshift{0%{transform:translate(0,0)}33%{transform:translate(-3%,2%)}66%{transform:translate(2%,-3%)}100%{transform:translate(0,0)}}
.hero .wrap{position:relative;z-index:4}
/* warm vignette so photos/video sit in the page instead of floating */
.hero::after{content:"";position:absolute;inset:0;z-index:2;pointer-events:none;background:radial-gradient(ellipse at 50% 40%,transparent 40%,rgba(22,23,26,.55) 100%)}

/* ===== PHOTO COMPONENTS ===== */
.photo-slot img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:3;background:var(--ink-2)}

/* life strip — the "real people" band */
.lifestrip{background:var(--ink);padding:0}
.life-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:2px}
.life-grid .life-grid .photo-slot.tall{aspect-ratio:1/1}
.life-cap{text-align:center;padding:34px 0 0}
.life-cap p{font-size:15px;color:var(--muted-d);max-width:560px;margin:0 auto}

/* wide photo band */
.photoband{position:relative;height:clamp(300px,44vw,520px);overflow:hidden}
.photoband .photoband .overlay{position:absolute;inset:0;z-index:3;display:grid;place-items:center;text-align:center;background:linear-gradient(180deg,rgba(22,23,26,.35),rgba(22,23,26,.72))}
.photoband .overlay h2{font-family:var(--display);text-transform:uppercase;color:#fff;font-size:clamp(28px,4.6vw,58px);line-height:.94;max-width:900px;padding:0 24px}
.photoband .overlay .sub{font-family:var(--mono);font-size:11px;letter-spacing:0.14em;text-transform:uppercase;color:var(--green);margin-top:18px}

@media(max-width:860px){.life-grid{grid-template-columns:1fr 1fr}}

/* ===== APP SECTION ===== */
.app{background:var(--ink);color:#fff;padding:var(--sec) 0;position:relative;overflow:hidden}
.app-grid{display:grid;grid-template-columns:1.05fr .95fr;gap:64px;align-items:center;position:relative;z-index:2}
.app h2{font-family:var(--display);text-transform:uppercase;font-size:clamp(28px,4vw,50px);line-height:.94;margin:20px 0 18px}
.app .lead{font-size:17px;color:rgba(255,255,255,.76);max-width:520px;margin-bottom:28px}
.app-feats{list-style:none;margin-bottom:32px}
.app-feats li{padding:14px 0 14px 32px;border-top:1px solid var(--line-d);position:relative;font-size:15.5px;color:rgba(255,255,255,.86)}
.app-feats li:last-child{border-bottom:1px solid var(--line-d)}
.app-feats li::before{content:"";position:absolute;left:0;top:20px;width:14px;height:2px;background:var(--green)}
.app-feats li b{display:block;font-family:var(--display);text-transform:uppercase;font-size:17px;letter-spacing:.02em;margin-bottom:3px}
.app-cta{display:flex;gap:12px;flex-wrap:wrap}
.store-btn{display:inline-flex;align-items:center;gap:11px;border:1px solid rgba(255,255,255,.28);padding:12px 20px;border-radius:var(--r-md);transition:border-color .2s,background .2s}
.store-btn:hover{border-color:#fff;background:rgba(255,255,255,.06)}
.store-btn .sb-ico{font-size:22px;line-height:1}
.store-btn .sb-txt{line-height:1.15}
.store-btn .sb-txt span{display:block;font-family:var(--mono);font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--muted-d)}
.store-btn .sb-txt b{font-size:15px;font-weight:700}
/* phone mockup */
.phone-wrap{display:grid;place-items:center;position:relative}
.phone{width:min(280px,78%);aspect-ratio:9/19;background:linear-gradient(165deg,#2A2D33,#17181C);border:2px solid rgba(255,255,255,.16);border-radius:34px;padding:11px;box-shadow:0 40px 80px -30px rgba(0,0,0,.85);position:relative}
.phone::before{content:"";position:absolute;top:14px;left:50%;transform:translateX(-50%);width:78px;height:5px;background:rgba(255,255,255,.22);border-radius:var(--r-sm)}
.phone-screen{width:100%;height:100%;border-radius:var(--r-lg);background:linear-gradient(180deg,#1B1E24,#101216);overflow:hidden;position:relative;display:flex;flex-direction:column;padding:30px 16px 16px}
.phone-screen .ps-top{font-family:var(--mono);font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--sky);margin-bottom:14px}
.phone-screen .ps-title{font-family:var(--display);text-transform:uppercase;font-size:20px;line-height:.98;margin-bottom:16px}
.ps-card{background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.09);border-radius:var(--r-lg);padding:11px 12px;margin-bottom:9px}
.ps-card .l{font-family:var(--mono);font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--muted-d)}
.ps-card .v{font-family:var(--display);font-size:19px;line-height:1;margin-top:5px}
.ps-card .v em{font-style:normal;color:var(--green)}
.ps-bar{height:5px;border-radius:var(--r-sm);background:rgba(255,255,255,.1);margin-top:9px;overflow:hidden}
.ps-bar i{display:block;height:100%;background:var(--sky);width:72%}
.ps-bar.g i{background:var(--green);width:88%}
@media(max-width:1000px){.app-grid{grid-template-columns:1fr;gap:44px}.phone-wrap{order:-1}}

/* ===== MOBILE REFINEMENTS ===== */
@media(max-width:860px){
  /* scrim goes vertical on mobile — text sits over the top, footage shows below */
  .hero-scrim{background:linear-gradient(180deg,rgba(22,23,26,.92) 0%,rgba(22,23,26,.86) 45%,rgba(22,23,26,.68) 100%)}
  .hero-video{opacity:.8}
  /* comfortable tap targets (Apple/Google min 44px) */
  .btn{padding:15px 22px;min-height:48px}
  .nav-links.open a{padding:16px 0}
  .store-btn{min-height:52px}
  .prog .go,.foot-col a{padding:6px 0;display:inline-block;min-height:34px}
  /* inline-block makes the footer links flow as a wrapping run rather than a stack. With four
     Train links that read fine; at six they ran together into one sentence ("Young Guns (5–11)
     New Athletes Veteran Athletes Private Training"). The right margin re-separates them. */
  .foot-col a{margin-right:20px}
}
@media(max-width:640px){
  .hero{padding:56px 0 0}
  .hero h1{font-size:clamp(46px,13vw,72px)}
  .hero-sub{font-size:16px}
  .hooknote{font-size:11px;letter-spacing:.08em;line-height:1.9}
  .hero-actions{flex-direction:column;align-items:stretch}
  .hero-actions .btn{justify-content:center;width:100%}
  .section,.manifesto,.method,.programs,.proof,.app{padding:var(--sec-sm) 0}
  .cta{padding:var(--sec-sm) 0}
  .statrail{margin-top:48px}
  .xform.feature .fbody{padding:26px 22px}
  .xform{padding:24px 22px}
  .xstats{gap:8px}
  .xstat{flex:1;min-width:calc(50% - 4px)}
  .life-grid{grid-template-columns:1fr 1fr;gap:1px}
  .photoband{height:clamp(240px,60vw,340px)}
  .phone{width:min(240px,80%)}
  .name-chip{min-width:100%}
  .foot-top{gap:30px}
}
/* never let anything blow out the viewport */
img,video,svg,table{max-width:100%}

/* ===== HOMETOWN HERO ===== */
.hometown{background:var(--paper-2);padding:var(--sec) 0;position:relative}
.ht-grid{display:grid;grid-template-columns:.92fr 1.08fr;gap:56px;align-items:center}
.ht-photo{aspect-ratio:4/5;position:relative;overflow:hidden;border-radius:var(--r-md)}
.ht-photo .ht-badge{position:absolute;left:0;bottom:0;z-index:4;background:var(--green);color:var(--ink);padding:13px 18px;border-radius:0 6px 0 6px}
.ht-badge b{display:block;font-family:var(--display);text-transform:uppercase;font-size:16px;line-height:1}
.ht-badge span{display:block;font-size:11px;letter-spacing:.14em;text-transform:uppercase;margin-top:4px;font-weight:600}
.ht-eyebrow{color:var(--green-deep)!important}
.ht-arc{display:flex;align-items:center;gap:14px;flex-wrap:wrap;margin:22px 0 26px}
.ht-arc .from,.ht-arc .to{padding:12px 18px;border:1px solid var(--line-l);border-radius:var(--r-md)}
.ht-arc .from{background:transparent}
.ht-arc .to{background:var(--ink);color:#fff;border-color:var(--ink)}
.ht-arc .lab{font-size:11px;letter-spacing:0.14em;text-transform:uppercase;color:var(--muted);font-weight:600}
.ht-arc .to .lab{color:var(--sky)}
.ht-arc .val{font-family:var(--display);text-transform:uppercase;font-size:19px;line-height:1.05;margin-top:6px}
.ht-arc .sep{font-size:22px;color:var(--green-deep);font-weight:800}
.ht h2{font-family:var(--display);text-transform:uppercase;font-size:clamp(28px,4vw,50px);line-height:1;margin:18px 0 0}
.ht .quote-line{font-size:18px;color:#3A3E47;max-width:560px;margin-bottom:22px}
.ht .record{display:inline-flex;align-items:baseline;gap:12px;border-top:2px solid var(--green);padding-top:16px;margin-top:6px}
.ht .record .t{font-family:var(--display);font-size:clamp(30px,4.4vw,50px);line-height:1}
.ht .record .d{font-size:12px;letter-spacing:.14em;text-transform:uppercase;color:var(--muted);font-weight:600}
@media(max-width:1000px){.ht-grid{grid-template-columns:1fr;gap:36px}.ht-photo{aspect-ratio:16/10}}

/* ===== TOP SPLIT: HOMETOWN | NAVY ===== */
.split{background:var(--paper);padding:0}
.split-grid{display:grid;grid-template-columns:1fr 1fr;gap:0}
.split-col{padding:72px 48px}
.split-col.local{background:var(--paper-2)}
.split-col.navy{background:var(--ink);color:#fff;position:relative;overflow:hidden}
.split-col h2{font-family:var(--display);text-transform:uppercase;font-size:clamp(26px,2.9vw,40px);line-height:1.02;margin:18px 0 10px}
.split-col .blurb{font-size:16px;color:#4A4E57;margin-bottom:26px;max-width:460px}
.split-col.navy .blurb{color:rgba(255,255,255,.74)}

/* navy col */
.navy-photo{position:relative;aspect-ratio:16/10;border-radius:var(--r-md);overflow:hidden;margin-bottom:24px}
.navy-photo img{width:100%;height:100%;object-fit:cover;display:block}
.navy-list{list-style:none}
.navy-list li{padding:13px 0 13px 28px;border-top:1px solid var(--line-d);position:relative;font-size:15px;color:rgba(255,255,255,.88);font-weight:600}
.navy-list li:last-child{border-bottom:1px solid var(--line-d)}
.navy-list li::before{content:"✓";position:absolute;left:0;color:var(--green)}
.navy-list li span{display:block;font-weight:400;font-size:12.5px;color:var(--muted-d);margin-top:3px;letter-spacing:.04em}

/* ===== PHYSICAL THERAPY ===== */
.pt{background:var(--paper-2);padding:var(--sec) 0}
.pt-grid{display:grid;grid-template-columns:1fr 1fr;gap:44px;align-items:center}
.pt h2{font-family:var(--display);text-transform:uppercase;font-size:clamp(28px,4vw,48px);line-height:1;margin:18px 0 16px}
.pt .lead{font-size:17px;color:#41454E;margin-bottom:26px}
.pt-partners{display:grid;gap:14px;margin-bottom:28px}
.pt-partner{border:1px solid var(--line-l);border-left:3px solid var(--green);border-radius:var(--r-md);padding:20px 22px}
.pt-partner b{font-family:var(--display);text-transform:uppercase;font-size:19px;display:block;line-height:1.05}
.pt-partner span{font-size:13px;letter-spacing:.1em;text-transform:uppercase;color:var(--muted);font-weight:600;display:block;margin-top:5px}
.pt-partner p{font-size:14.5px;color:#4A4E57;margin-top:10px}
.pt-media{aspect-ratio:4/3;border-radius:var(--r-md);overflow:hidden;position:relative}
/* NOTE: there was a dangling `.pt-media` selector here with no declaration block. CSS parses
   the @media below as part of that broken selector and discards the whole thing, so none of
   these rules had ever applied — .split-grid stayed two-column at every width. Do not
   reintroduce a bare selector above an @media. */
@media(max-width:1000px){
  .split-grid{grid-template-columns:1fr}
  .split-col{padding:56px 32px}
  .pros-grid{grid-template-columns:1fr}
  .pt-grid{grid-template-columns:1fr;gap:32px}
  .pt-media{order:-1;aspect-ratio:16/9}
}
@media(max-width:640px){
  .split-col{padding:48px 20px}
  /* No .hh/.hh-photo overrides here. A 66px square photo assumed .hh was a horizontal row on
     mobile, but .hh is flex-direction:column at every width — so the photo shrank to a thumbnail
     in the corner of a full-width card, the .hh-town pill (92px) spilled past its edge, and the
     rest of the card was empty paper. Letting .hh-photo keep its base full-width 4/3 gives the
     same photo-over-text stack the cards use on desktop. */
}

/* ===== AFFILIATION / BADGE MARQUEE ===== */
@media(max-width:640px){
  .badges{padding:20px 0}
  .mtrack{gap:34px;padding-right:34px}
  .badge .bmark{width:32px;height:32px;font-size:11px}
  .badge .btxt b{font-size:12.5px}
}
@media(prefers-reduced-motion:reduce){.marquee{animation:none}}

/* ===== HOMETOWN HERO CARDS ===== */
.hh-grid{display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-top:6px}
.hh{position:relative;background:var(--paper);border:1px solid var(--line-l);border-radius:var(--r-md);overflow:hidden;display:flex;flex-direction:column;transition:transform .3s cubic-bezier(.16,1,.3,1),box-shadow .3s,border-color .3s;cursor:default}
.hh::before{content:"";position:absolute;top:0;left:0;right:0;height:4px;background:linear-gradient(90deg,var(--sky),var(--green));transform:scaleX(0);transform-origin:left;transition:transform .38s cubic-bezier(.16,1,.3,1);z-index:5}
.hh:hover{transform:translateY(-7px);box-shadow:0 26px 54px -26px rgba(22,23,26,.55);border-color:transparent}
.hh:hover::before{transform:scaleX(1)}
.hh-photo{position:relative;aspect-ratio:4/3;overflow:hidden;background:linear-gradient(150deg,#2A2D33,#17181C)}
.hh-photo .hh:hover .hh-photo .hh-photo::after{content:"";position:absolute;inset:0;background:linear-gradient(180deg,transparent 40%,rgba(22,23,26,.88));z-index:2}
.hh-town{position:absolute;left:12px;bottom:11px;z-index:3;display:inline-flex;align-items:center;gap:5px;font-size:11px;letter-spacing:.13em;text-transform:uppercase;color:#fff;font-weight:700;background:rgba(22,23,26,.62);border:1px solid rgba(255,255,255,.22);padding:5px 9px;border-radius:var(--r-pill);backdrop-filter:blur(4px)}
.hh-town i{width:5px;height:5px;border-radius:50%;background:var(--green);display:block}
.hh-body{padding:18px 18px 20px;display:flex;flex-direction:column;flex:1}
.hh-name{font-family:var(--display);text-transform:uppercase;font-size:19px;line-height:1.02;letter-spacing:-.01em}
@media(max-width:1200px){.hh-grid{grid-template-columns:1fr 1fr}}
@media(max-width:640px){.hh-grid{grid-template-columns:1fr}}

/* THE ACCOLADE — the hero element of each card */
.hh-accolade{font-family:var(--display);text-transform:uppercase;font-size:clamp(19px,2.1vw,26px);line-height:1.02;letter-spacing:-.015em;color:var(--accent-deep);margin:9px 0 10px;transition:color .3s}
.hh:hover .hh-accolade{color:var(--green-ink)}  /* --green-deep is 2.55:1 on --paper */
.hh-name{font-family:var(--body);text-transform:uppercase;font-size:12px;font-weight:800;letter-spacing:0.14em;color:var(--muted);line-height:1}
.hh-desc{font-size:13.5px;color:#4A4E57;line-height:1.55;margin-bottom:14px}
.hh-desc em{font-style:normal;font-weight:700;color:var(--ink)}
/* wide card for an odd last item */
.hh.wide{grid-column:1 / -1;flex-direction:row}
.hh.wide .hh-photo{aspect-ratio:1/1;width:190px;flex:none}
.hh.wide .hh-body{flex:1}
@media(max-width:640px){.hh.wide{flex-direction:column}.hh.wide .hh-photo{width:100%;aspect-ratio:4/3}}

/* ===== PROFESSIONAL RECOGNITION ===== */
.pros{background:var(--ink);color:#fff;padding:var(--sec) 0}
.pros-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:24px}
.pro-card{border:1px solid var(--line-d);border-radius:var(--r-lg);overflow:hidden;display:flex;flex-direction:column;background:var(--ink-2);transition:transform .3s cubic-bezier(.16,1,.3,1),box-shadow .3s,border-color .3s;position:relative}
.pro-card::before{content:"";position:absolute;top:0;left:0;right:0;height:4px;background:linear-gradient(90deg,var(--sky),var(--green));transform:scaleX(0);transform-origin:left;transition:transform .38s cubic-bezier(.16,1,.3,1);z-index:6}
.pro-card:hover{transform:translateY(-7px);box-shadow:0 30px 60px -28px rgba(0,0,0,.9);border-color:rgba(255,255,255,.28)}
.pro-card:hover::before{transform:scaleX(1)}
/* LARGE portrait */
.pro-photo{position:relative;aspect-ratio:4/5;overflow:hidden;background:linear-gradient(155deg,#2E3138,#15171B)}
.pro-photo .pro-card:hover .pro-photo .pro-photo::after{content:"";position:absolute;inset:0;z-index:2;background:linear-gradient(180deg,transparent 38%,rgba(18,19,22,.94) 92%)}
.pro-cred{position:absolute;top:14px;left:14px;z-index:4;font-size:11px;letter-spacing:0.14em;text-transform:uppercase;font-weight:800;color:var(--ink);background:var(--green);padding:6px 10px;border-radius:var(--r-sm)}
.pro-id{position:absolute;left:20px;right:20px;bottom:18px;z-index:4}
.pro-id b{display:block;font-family:var(--display);text-transform:uppercase;font-size:clamp(21px,2.3vw,28px);line-height:1;letter-spacing:-.015em}
.pro-id span{display:block;font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--sky);font-weight:700;margin-top:8px}
.pro-body{padding:24px 24px 26px;display:flex;flex-direction:column;flex:1}
.pro-mark{font-family:var(--display);font-size:42px;line-height:.4;color:var(--green);height:22px}
.pro-body p{font-size:15px;color:rgba(255,255,255,.84);line-height:1.62;flex:1}
@media(max-width:1000px){.pros-grid{grid-template-columns:1fr;max-width:460px;margin:0 auto}}

/* ===== SIGNATURE MOTIF: ACCELERATION FIELD ===== */
.data-bg{position:relative;isolation:isolate}
.data-bg > .accel-canvas{position:absolute;inset:0;width:100%;height:100%;z-index:0;pointer-events:none;opacity:.5}
.data-bg > *:not(.accel-canvas){position:relative;z-index:1}
/* faint measurement grid on light sections — graph-paper, not tech-y */
.grid-bg{position:relative}
.grid-bg::before{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background-image:linear-gradient(rgba(22,23,26,.045) 1px,transparent 1px),linear-gradient(90deg,rgba(22,23,26,.045) 1px,transparent 1px);
  background-size:64px 64px;
  mask-image:radial-gradient(ellipse 70% 60% at 50% 45%,#000 20%,transparent 78%);
  -webkit-mask-image:radial-gradient(ellipse 70% 60% at 50% 45%,#000 20%,transparent 78%)}
.grid-bg > *{position:relative;z-index:1}
@media(prefers-reduced-motion:reduce){.data-bg > .accel-canvas{display:none}}

/* ===== ASCENSION CUES ===== */
/* light gathers toward the top of dark sections — the eye is pulled up */
.data-bg::after{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background:linear-gradient(0deg,rgba(0,0,0,.22) 0%,transparent 38%,rgba(99,183,222,.05) 100%)}
/* every reveal enters from below and settles upward */
.reveal-on{transition:opacity .75s cubic-bezier(.16,1,.3,1),transform .75s cubic-bezier(.16,1,.3,1)}
:where(.js) .reveal-on{opacity:0;transform:translateY(34px)}
.reveal-on.in{opacity:1;transform:none}
/* stagger so groups climb in sequence, like steps */
.proof-grid .reveal-on:nth-child(2),.cycle .reveal-on:nth-child(2){transition-delay:.09s}
.proof-grid .reveal-on:nth-child(3),.cycle .reveal-on:nth-child(3){transition-delay:.18s}
/* .xgrid used to be in the two rules above, keyed to :nth-child(2/3/4). That cannot work
   here: .xgrid also contains three full-width .xgroup headings, so :nth-child counts the
   headings and the stagger lands on the wrong cards — and it stopped at 4 while the grid
   holds 11 children. app.js sets --rd per card instead, counting position within each
   group so every row of three climbs 0 / 80 / 160ms regardless of where the headings fall. */
.xgrid .reveal-on{transition-delay:calc(var(--rd,0) * 1ms)}
/* pillar bars grow upward from the floor instead of sideways */
/* cards lift on hover — never sink */
.hh:hover,.pro-card:hover,.xform:hover,.prog:hover{transform:translateY(-7px)}
/* the big closing statement rises in */
.cta h2{transition:transform .9s cubic-bezier(.16,1,.3,1),opacity .9s}
:where(.js) .cta h2{transform:translateY(18px);opacity:0}
.cta.in h2{transform:none;opacity:1}
@media(prefers-reduced-motion:reduce){
  .cta h2{transform:none;opacity:1}
  .reveal-on{opacity:1;transform:none}
}

/* ===== PILLARS — aligned measurement chart ===== */
@media(max-width:1000px){.pillars{grid-template-columns:1fr 1fr}}
@media(max-width:640px){.pillars{grid-template-columns:1fr}}

/* ================= PROFESSIONAL POLISH ================= */

/* 1. Sticky nav was covering anchored headings on jump-links — nearly always missed */
[id]{scroll-margin-top:104px}

/* 2. Skip link for keyboard + screen-reader users */
.skip{position:absolute;left:-9999px;top:0;z-index:200;background:var(--green);color:var(--ink);padding:12px 20px;font-weight:800;border-radius:0 0 var(--r-md) 0}
.skip:focus{left:0}

/* 3. Brand-consistent selection + scrollbar */
::selection{background:var(--green);color:var(--ink)}
::-webkit-scrollbar{width:11px;height:11px}
::-webkit-scrollbar-track{background:var(--ink)}
::-webkit-scrollbar-thumb{background:#3A3F47;border-radius:var(--r-pill);border:3px solid var(--ink)}
::-webkit-scrollbar-thumb:hover{background:var(--accent-deep)}
html{scrollbar-color:#3A3F47 var(--ink);scrollbar-width:thin}

/* 4. No orphaned words in headlines */
h1,h2,h3,.hh-accolade,.man-lead,.cta h2{text-wrap:balance}
p,.hh-desc,.blurb{text-wrap:pretty}

/* 5. Numbers align in columns instead of jittering */
.stat .k,.xstat .val,.ht .record .t,.tile .stat-big,.ps-card .v{font-variant-numeric:tabular-nums;font-feature-settings:"tnum"}

/* 6. Visible, on-brand focus ring */
/* FOCUS RING — audit fix, Sept 1. The old rule drew this in --green, which is the exact
   background colour of the .cta band on every page: 1.00:1, literally invisible on the
   site's most important button. It also failed on the light sections (1.81:1).
   --ink measures 8.76:1 on the green band and 15.87:1 on --paper, so it carries every
   light surface. No single colour clears green, paper AND ink, so dark surfaces get an
   explicit white override below. */
:focus-visible{outline:3px solid var(--ink);outline-offset:3px;border-radius:2px}
.section-d :focus-visible,
.data-bg :focus-visible,
.page-hero :focus-visible,
.coach-hero :focus-visible,
.hero :focus-visible,
.mtn :focus-visible,
.contact :focus-visible,
.rx :focus-visible,
.apx :focus-visible,
.floor :focus-visible,
.pros :focus-visible,
.founder :focus-visible,
.lifestrip :focus-visible,
.nav :focus-visible,
footer :focus-visible{outline-color:#fff}
.btn:focus-visible,.store-btn:focus-visible{outline-offset:4px}

/* 7. Unified elevation — one shadow language */
:root{--sh-1:0 2px 8px -2px rgba(22,23,26,.14);--sh-2:0 18px 40px -22px rgba(22,23,26,.45);--sh-3:0 30px 64px -30px rgba(22,23,26,.6)}
.hh:hover,.xform:hover,.prog:hover{box-shadow:var(--sh-3)}
.pro-card:hover{box-shadow:0 30px 64px -28px rgba(0,0,0,.9)}

/* 8. Scroll progress — thin, brand-colored, top of viewport */
.progress{position:fixed;top:0;left:0;height:3px;width:100%;transform:scaleX(0);transform-origin:left;background:linear-gradient(90deg,var(--sky),var(--green));z-index:100;pointer-events:none;transition:transform .08s linear}

/* 9. Nav condenses once you start scrolling */
header.nav{transition:height .3s,background .3s}
.nav-inner{transition:height .32s cubic-bezier(.16,1,.3,1)}
header.nav.small .nav-inner{height:64px}
header.nav.small .brand-logo{height:38px}
.brand-logo{transition:height .32s cubic-bezier(.16,1,.3,1),transform .25s}

/* 10. Photos wipe upward into place instead of popping */
.photo-slot img{clip-path:inset(100% 0 0 0);transition:clip-path 1s cubic-bezier(.16,1,.3,1),transform .6s}
.in-view .photo-slot img,.photo-slot.in-view img{clip-path:inset(0 0 0 0)}

/* 11. Back to top — appears after the fold, reinforces "up" */
.totop{position:fixed;right:22px;bottom:22px;z-index:90;width:46px;height:46px;border-radius:var(--r-pill);background:var(--ink);color:#fff;border:1px solid rgba(255,255,255,.22);display:grid;place-items:center;cursor:pointer;opacity:0;transform:translateY(14px);pointer-events:none;transition:opacity .3s,transform .3s,background .2s;box-shadow:var(--sh-2)}
.totop.on{opacity:1;transform:none;pointer-events:auto}
.totop:hover{background:var(--accent-deep);transform:translateY(-3px)}
.totop svg{width:17px;height:17px}

/* 12. Optical type refinements */
.display,h1,h2,.hh-accolade{letter-spacing:-.018em}
.eyebrow{font-weight:700}
.btn{letter-spacing:.02em}

/* 13. Buttons get a subtle press state */
.btn:active,.store-btn:active{transform:translateY(1px) scale(.995)}

/* 14. Consistent internal spacing on cards */
.hh-body{padding:var(--s-3) var(--s-3) var(--s-3)}
.pro-body{padding:var(--s-3) var(--s-3) var(--s-4)}
.xform{padding:var(--s-4) var(--s-3)}

/* 15. Section heads breathe consistently */
.sec-head{margin-bottom:var(--s-6)}
.sec-head h2{margin-top:var(--s-2)}
.sec-head p{margin-top:var(--s-2)}

/* 16. Print — people do print pages */
@media print{
  header.nav,.progress,.totop,.badges,.accel-canvas,.hero-video,video{display:none!important}
  body{background:#fff;color:#000}
  .section-d,.pros,.method,.app,.cta,.hero{background:#fff!important;color:#000!important}
  a{text-decoration:underline}
}

/* 17. Honour reduced motion across every new behaviour */
@media(prefers-reduced-motion:reduce){
  .photo-slot img{clip-path:none}
  .progress{display:none}
    }

/* ===== SCROLL CHOREOGRAPHY ===== */
/* headings rise + unmask as they arrive */
.sec-head h2,.method-head h2,.split-col h2,.pt h2,.app h2,.prog-head h2,.proof-head h2{
  transition:opacity .8s cubic-bezier(.16,1,.3,1),transform .8s cubic-bezier(.16,1,.3,1)}
:where(.js) .sec-head h2,:where(.js) .method-head h2,:where(.js) .split-col h2,:where(.js) .pt h2,:where(.js) .app h2,:where(.js) .prog-head h2,:where(.js) .proof-head h2{
  opacity:0;transform:translateY(26px)}
.sec-head h2.lift,.method-head h2.lift,.split-col h2.lift,.pt h2.lift,.app h2.lift,.prog-head h2.lift,.proof-head h2.lift{opacity:1;transform:none}
/* the eyebrow leads the heading in */
.sec-head .eyebrow,.split-col .eyebrow{transition:opacity .6s,transform .6s}
/* parallax layers need a transform origin that won't clip */
[data-parallax]{will-change:transform;transform:translate3d(0,0,0) scale(1.06)}
@media(prefers-reduced-motion:reduce){
  .sec-head h2,.method-head h2,.split-col h2,.pt h2,.app h2,.prog-head h2,.proof-head h2{opacity:1;transform:none}
  [data-parallax]{transform:none!important}
}

/* ===== PILLAR ICONS — minimal line marks ===== */
.p-ico{width:34px;height:34px;color:var(--sky);margin-bottom:var(--s-3);
  transition:opacity .55s cubic-bezier(.16,1,.3,1),transform .55s cubic-bezier(.16,1,.3,1),color .3s}
:where(.js) .p-ico{opacity:0;transform:translateY(8px)}
.pillar.viz-on .p-ico{opacity:1;transform:none}
.pillar:nth-child(2).viz-on .p-ico{transition-delay:.08s}
.pillar:nth-child(3).viz-on .p-ico{transition-delay:.16s}
.pillar:nth-child(4).viz-on .p-ico{transition-delay:.24s}
.pillar:nth-child(4) .p-ico{color:var(--green)}
.p-ico svg{width:100%;height:100%;display:block}
.p-ico path,.p-ico line,.p-ico polyline,.p-ico circle{
  stroke:currentColor;stroke-width:1.75;fill:none;stroke-linecap:round;stroke-linejoin:round;
  stroke-dasharray:var(--d,60);stroke-dashoffset:var(--d,60)}
.pillar.viz-on .p-ico path,.pillar.viz-on .p-ico line,
.pillar.viz-on .p-ico polyline,.pillar.viz-on .p-ico circle{
  animation:icodraw .9s cubic-bezier(.16,1,.3,1) forwards;animation-delay:.15s}
@keyframes icodraw{to{stroke-dashoffset:0}}
.pillar:hover .p-ico{color:var(--green);transform:translateY(-2px)}
@media(prefers-reduced-motion:reduce){
  .p-ico{opacity:1;transform:none}
  .p-ico path,.p-ico line,.p-ico polyline,.p-ico circle{stroke-dashoffset:0;animation:none}
}

/* ===== START HERE / ENTRY OFFER ===== */
.entry{background:var(--paper-2);padding:var(--sec) 0}
.entry-card{border:1px solid var(--line-l);border-radius:var(--r-lg);overflow:hidden;display:grid;grid-template-columns:1.15fr .85fr;box-shadow:var(--sh-2)}
.entry-main{padding:var(--s-6) var(--s-5)}
.entry-side{background:var(--ink);color:#fff;padding:var(--s-6) var(--s-5);display:flex;flex-direction:column;justify-content:center}
.entry-tag{display:inline-block;font-size:11px;letter-spacing:0.14em;text-transform:uppercase;font-weight:800;color:var(--ink);background:var(--green);padding:6px 11px;border-radius:var(--r-sm);margin-bottom:var(--s-3)}
.entry h2{font-family:var(--display);text-transform:uppercase;font-size:clamp(28px,3.8vw,46px);line-height:1;margin-bottom:var(--s-2)}
.entry .sub{font-size:17px;color:#41454E;margin-bottom:var(--s-4)}
.entry-steps{list-style:none;counter-reset:st}
.entry-steps li{counter-increment:st;position:relative;padding:16px 0 16px 46px;border-top:1px solid var(--line-l);font-size:15.5px;color:#3A3E47}
.entry-steps li:last-child{border-bottom:1px solid var(--line-l)}
.entry-steps li::before{content:counter(st,decimal-leading-zero);position:absolute;left:0;top:16px;font-family:var(--display);font-size:14px;color:var(--sky);letter-spacing:-.01em}
.entry-steps li b{display:block;font-family:var(--display);text-transform:uppercase;font-size:16px;margin-bottom:3px;letter-spacing:-.01em}
.price{font-family:var(--display);font-size:clamp(44px,6vw,68px);line-height:1;letter-spacing:-.02em;font-variant-numeric:tabular-nums}
.price-lab{font-size:11px;letter-spacing:0.14em;text-transform:uppercase;color:var(--sky);font-weight:800;margin-bottom:var(--s-2)}
.price-note{font-size:14px;color:var(--muted-d);margin-top:var(--s-3);line-height:1.6}
.entry-side .btn{margin-top:var(--s-4);justify-content:center}
/* FAQ */
.faq{max-width:820px;margin:0 auto}
.faq details{border-top:1px solid var(--line-l);padding:0}
.faq details:last-of-type{border-bottom:1px solid var(--line-l)}
.faq summary{cursor:pointer;padding:22px 40px 22px 0;font-family:var(--display);text-transform:uppercase;font-size:17px;letter-spacing:-.01em;position:relative;list-style:none}
.faq summary::-webkit-details-marker{display:none}
/* --accent-deep, not --sky: the "+" is the only affordance telling a parent these rows
   open, and --sky measured 1.99:1 on --paper — under the 3:1 minimum for a UI control.
   --accent-deep measures 4.74:1. */
.faq summary::after{content:"+";position:absolute;right:6px;top:19px;font-size:24px;color:var(--accent-deep);font-weight:400;transition:transform .28s}
.faq details[open] summary::after{transform:rotate(45deg)}
.faq .ans{padding:0 40px 24px 0;font-size:15.5px;color:#4A4E57;line-height:1.68}
@media(max-width:1000px){.entry-card{grid-template-columns:1fr}.entry-main,.entry-side{padding:var(--s-5) var(--s-4)}}

/* ===== HERO STAT RAIL — results first ===== */
.statrail{margin-top:var(--s-7);border-top:1px solid var(--line-d);display:grid;grid-template-columns:repeat(4,1fr)}
.stat{padding:var(--s-4) var(--s-3) var(--s-4) 0;border-right:1px solid var(--line-d);position:relative;transition:background .3s}
.stat:last-child{border-right:none}
.stat:hover{background:rgba(255,255,255,.03)}
.stat .k{font-family:var(--display);font-size:clamp(34px,4.4vw,54px);line-height:1;letter-spacing:-.025em;display:flex;align-items:baseline;gap:3px}
.stat.hi .k{color:var(--sky)}
.stat .k .unit{font-size:.44em;letter-spacing:0;color:rgba(255,255,255,.65)}
.stat .k b{color:var(--green);font-weight:400}
.stat .u{font-size:12px;letter-spacing:.1em;text-transform:uppercase;color:rgba(255,255,255,.9);margin-top:12px;font-weight:700}
.stat .cyc{font-size:11px;letter-spacing:.13em;text-transform:uppercase;color:var(--muted-d);margin-top:5px;font-weight:600}
.stat::after{content:"";position:absolute;top:-1px;left:0;width:0;height:2px;background:var(--green);transition:width .8s ease}
.statrail.in .stat::after{width:38px}
.statrail.in .stat:nth-child(2)::after{transition-delay:.1s}
.statrail.in .stat:nth-child(3)::after{transition-delay:.2s}
.statrail.in .stat:nth-child(4)::after{transition-delay:.3s}
@media(max-width:860px){
  .statrail{grid-template-columns:1fr 1fr}
  .stat{padding:var(--s-3) var(--s-3) var(--s-3) 0;border-bottom:1px solid var(--line-d)}
  .stat:nth-child(2){border-right:none}
}
@media(max-width:480px){.statrail{grid-template-columns:1fr}.stat{border-right:none}}

/* ===== FOUR PILLARS — the climb ===== */
.pillars{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--s-2);align-items:end;margin-top:var(--s-5);position:relative}
/* connecting ascent line behind the cards */
.pillars::before{content:"";position:absolute;left:6%;right:6%;bottom:0;height:1px;background:linear-gradient(90deg,rgba(255,255,255,.1),rgba(140,198,63,.4));z-index:0}
.pillar{position:relative;z-index:1;background:var(--ink-2);border:1px solid var(--line-d);border-radius:var(--r-lg);padding:var(--s-4) var(--s-3) var(--s-4);
  display:flex;flex-direction:column;transition:transform .4s cubic-bezier(.16,1,.3,1),box-shadow .4s,border-color .3s,background .3s}
/* each step sits higher than the one before it */
.pillar:nth-child(1){margin-bottom:0}
.pillar:nth-child(2){margin-bottom:26px}
.pillar:nth-child(3){margin-bottom:52px}
.pillar:nth-child(4){margin-bottom:78px;background:linear-gradient(165deg,rgba(140,198,63,.09),var(--ink-2));border-color:rgba(140,198,63,.32)}
.pillar:hover{transform:translateY(-8px);box-shadow:0 30px 60px -28px rgba(0,0,0,.9);border-color:rgba(255,255,255,.3);background:var(--ink-3)}
.pillar:nth-child(4):hover{border-color:var(--green)}
/* step marker */
.pillar .no{display:inline-flex;align-items:center;gap:8px;font-size:11px;letter-spacing:0.14em;font-weight:800;color:var(--sky);margin-bottom:var(--s-3)}
.pillar:nth-child(4) .no{color:var(--green)}
.pillar .no::before{content:"";width:22px;height:2px;background:currentColor;border-radius:2px;transition:width .35s}
.pillar:hover .no::before{width:34px}
.pillar h3{font-family:var(--display);text-transform:uppercase;font-size:20px;line-height:1.04;margin:0 0 10px;letter-spacing:-.015em}
.pillar p{font-size:14px;color:var(--muted-d);line-height:1.62;margin-bottom:var(--s-3)}
/* the payoff — what this pillar actually gives the athlete */
.pillar .gives{margin-top:auto;padding-top:14px;border-top:1px solid var(--line-d)}
.pillar .gives span{display:block;font-size:11px;letter-spacing:0.14em;text-transform:uppercase;color:var(--muted-d);font-weight:700;margin-bottom:5px}
.pillar .gives b{font-family:var(--display);text-transform:uppercase;font-size:14px;line-height:1.15;color:#fff;letter-spacing:-.01em}
.pillar:nth-child(4) .gives b{color:var(--green)}
.p-ico{width:30px;height:30px}
/* summary line under the climb */
.climb-note{margin-top:var(--s-5);padding-top:var(--s-3);border-top:1px solid var(--line-d);display:flex;justify-content:space-between;gap:var(--s-4);flex-wrap:wrap;align-items:center}
.climb-note p{font-size:15px;color:var(--muted-d);max-width:560px}
.climb-note p b{color:#fff;font-weight:700}
@media(max-width:1000px){
  .pillars{grid-template-columns:1fr 1fr}
  .pillar:nth-child(1),.pillar:nth-child(3){margin-bottom:0}
  .pillar:nth-child(2),.pillar:nth-child(4){margin-bottom:32px}
  .pillars::before{display:none}
}
@media(max-width:640px){
  .pillars{grid-template-columns:1fr}
  .pillar{margin-bottom:0!important}
}

/* ================= COMPLETE HOVER PASS ================= */
/* By-the-numbers tiles */
.tile{transition:background .3s,transform .3s cubic-bezier(.16,1,.3,1),border-color .3s;border:1px solid transparent;border-radius:var(--r-md)}
.tile:hover{background:var(--ink-3);transform:translateY(-5px);border-color:rgba(255,255,255,.2)}
.tile .stat-big{transition:color .3s}
.tile:hover .stat-big{color:var(--green)}
.tile.accent:hover{background:var(--green-deep);transform:translateY(-5px)}

/* Ceiling name chips */
.name-chip{border-radius:var(--r-md);transition:border-color .3s,background .3s,transform .3s cubic-bezier(.16,1,.3,1)}
.name-chip:hover{border-color:var(--sky);background:rgba(99,183,222,.07);transform:translateY(-4px)}
.name-chip b{transition:color .3s}
.name-chip:hover b{color:var(--sky)}

/* Checklists — Navy col, app features, PT, entry steps */
.navy-list li,.clients li,.app-feats li,.entry-steps li{transition:color .25s,padding-left .28s cubic-bezier(.16,1,.3,1)}
.navy-list li:hover,.clients li:hover{color:#fff;padding-left:34px}
.app-feats li:hover{color:#fff;padding-left:38px}
.entry-steps li:hover{color:var(--ink);padding-left:52px}
.app-feats li::before{transition:width .28s,background .28s}
.app-feats li:hover::before{width:22px;background:var(--sky)}

/* PT partner cards */
.pt-partner{transition:transform .3s cubic-bezier(.16,1,.3,1),box-shadow .3s,border-left-color .3s}
.pt-partner:hover{transform:translateX(5px);box-shadow:var(--sh-2);border-left-color:var(--accent-deep)}

/* Testimonial / quote cards */
.quote{border-radius:var(--r-md);transition:border-color .3s,background .3s,transform .3s cubic-bezier(.16,1,.3,1)}
.quote:hover{border-color:rgba(255,255,255,.3);background:rgba(255,255,255,.03);transform:translateY(-5px)}
.quote .mark{transition:color .3s}
.quote:hover .mark{color:var(--sky)}

/* Inside-the-room photo strip */
.life-grid .life-grid .photo-slot::after{content:"";position:absolute;inset:0;z-index:4;background:rgba(99,183,222,0);transition:background .35s;pointer-events:none}
.life-grid .photo-slot:hover::after{background:rgba(99,183,222,.13)}
.life-grid .photo-slot:hover{transform:scale(1.02);z-index:5}

/* Wide photo band */
.photoband .overlay{transition:background .5s}
.photoband:hover .overlay{background:linear-gradient(180deg,rgba(22,23,26,.28),rgba(22,23,26,.66))}

/* Hometown tags */
.hh-tag{transition:background .3s,transform .3s}
.hh:hover .hh-tag{background:var(--sky);transform:translateX(3px)}

/* Program cards — arrow + border */
.prog{transition:transform .3s cubic-bezier(.16,1,.3,1),box-shadow .3s,border-color .3s}
.prog:hover{border-color:transparent}

/* Transformation cards — stat emphasis on hover */
.xstat{transition:border-color .3s,background .3s}
.xform:hover .xstat{border-color:rgba(140,198,63,.5);background:rgba(140,198,63,.05)}

/* Pro credential badge */
.pro-cred{transition:transform .3s}
.pro-card:hover .pro-cred{transform:translateY(-2px)}

/* Footer links slide */
.foot-col a{transition:color .2s,padding-left .25s cubic-bezier(.16,1,.3,1)}
.foot-col a:hover{color:#fff;padding-left:7px}

/* Badge marquee items */

/* FAQ rows */
.faq summary{transition:color .25s,padding-left .25s}
.faq summary:hover{color:var(--accent-deep);padding-left:6px}

/* Nav CTA lift */
.nav-cta .btn-accent{transition:transform .2s,background .2s,box-shadow .3s}
.nav-cta .btn-accent:hover{box-shadow:0 10px 26px -8px rgba(58,166,214,1)}

/* Anything clickable gets a pointer + never a dead state */
a,button,summary,.store-btn{cursor:pointer}
@media(hover:none){
  .hh:hover,.pillar:hover,.tile:hover,.quote:hover,.pro-card:hover,.xform:hover,.name-chip:hover{transform:none}
}

/* ===== PRO ROSTER ===== */
.roster{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-top:var(--s-2)}
.rcard{position:relative;border:1px solid var(--line-d);border-radius:var(--r-md);padding:24px 22px 22px;background:var(--ink-2);overflow:hidden;
  transition:transform .32s cubic-bezier(.16,1,.3,1),border-color .3s,background .3s}
.rcard::before{content:"";position:absolute;top:0;left:0;right:0;height:3px;background:linear-gradient(90deg,var(--sky),var(--green));transform:scaleX(0);transform-origin:left;transition:transform .36s cubic-bezier(.16,1,.3,1)}
.rcard:hover{transform:translateY(-6px);border-color:rgba(255,255,255,.28);background:var(--ink-3)}
.rcard:hover::before{transform:scaleX(1)}
.rcard .sport{font-size:11px;letter-spacing:0.14em;text-transform:uppercase;font-weight:800;color:var(--green);margin-bottom:12px;display:block}
.rcard b{display:block;font-family:var(--display);text-transform:uppercase;font-size:21px;line-height:1.02;letter-spacing:-.015em;margin-bottom:8px}
.rcard .acc{font-size:14px;color:rgba(255,255,255,.86);line-height:1.5;font-weight:600}
.rcard .tie{margin-top:14px;padding-top:12px;border-top:1px solid var(--line-d);font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--muted-d);font-weight:700;display:flex;align-items:center;gap:6px}
.rcard .tie i{width:5px;height:5px;border-radius:50%;background:var(--sky);display:block;flex:none}
@media(max-width:1000px){.roster{grid-template-columns:1fr 1fr}}
@media(max-width:640px){.roster{grid-template-columns:1fr}}

/* ===== FIX: pro recognition now 2-up, centered ===== */
.pros-grid{grid-template-columns:repeat(2,1fr);max-width:840px;margin:0 auto}
@media(max-width:1000px){.pros-grid{grid-template-columns:1fr;max-width:460px}}
/* ===== FIX: by-the-numbers 3-up ===== */
.wall.three{grid-template-columns:repeat(3,1fr)}
@media(max-width:1000px){.wall.three{grid-template-columns:1fr 1fr}}
@media(max-width:640px){.wall.three{grid-template-columns:1fr}}

/* ===== FOUNDER ===== */
.founder{background:var(--ink);color:#fff;padding:var(--sec) 0;position:relative;overflow:hidden}
.founder-grid{display:grid;grid-template-columns:.82fr 1.18fr;gap:var(--s-6);align-items:center;position:relative;z-index:2}
.founder-photo{position:relative;aspect-ratio:4/5;border-radius:var(--r-lg);overflow:hidden;background:linear-gradient(155deg,#2E3138,#15171B)}
.founder-photo .founder-photo::after{content:"";position:absolute;inset:0;z-index:2;background:linear-gradient(180deg,transparent 55%,rgba(18,19,22,.82));pointer-events:none}
.founder-badge{position:absolute;left:20px;bottom:18px;z-index:4}
.founder-badge b{display:block;font-family:var(--display);text-transform:uppercase;font-size:22px;line-height:1;letter-spacing:-.015em}
.founder-badge span{display:block;font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--sky);font-weight:700;margin-top:8px}
.founder h2{font-family:var(--display);text-transform:uppercase;font-size:clamp(28px,3.8vw,50px);line-height:1;letter-spacing:-.018em;margin:var(--s-2) 0 var(--s-3)}
.founder h2 em{font-style:normal;color:var(--sky)}
.founder .story{font-size:17px;color:rgba(255,255,255,.8);line-height:1.68;max-width:600px;margin-bottom:var(--s-3)}
.founder .story b{color:#fff;font-weight:700}
@media(max-width:1000px){
  .founder-grid{grid-template-columns:1fr;gap:var(--s-4)}
  .founder-photo{max-width:360px;margin:0 auto;aspect-ratio:4/5}
}

/* hometown cards: accolade-led, no trailing stat block */
.hh-desc{margin-top:10px;margin-bottom:0}
.hh-body{padding:var(--s-3)}
.hh-accolade{margin:9px 0 0}

/* ===== PROGRAMS — five tiers ===== */
.progs{background:var(--paper-2);padding:var(--sec) 0}
.prog-tiers{display:grid;grid-template-columns:repeat(5,1fr);gap:14px;margin-top:var(--s-2)}
.tier{position:relative;background:var(--paper);border:1px solid var(--line-l);border-radius:var(--r-lg);padding:26px 22px 24px;display:flex;flex-direction:column;overflow:hidden;
  transition:transform .32s cubic-bezier(.16,1,.3,1),box-shadow .32s,border-color .3s}
.tier::before{content:"";position:absolute;top:0;left:0;right:0;height:4px;background:linear-gradient(90deg,var(--sky),var(--green));transform:scaleX(0);transform-origin:left;transition:transform .36s cubic-bezier(.16,1,.3,1)}
.tier:hover{transform:translateY(-7px);box-shadow:var(--sh-3);border-color:transparent}
.tier:hover::before{transform:scaleX(1)}
.tier .t-ico{width:28px;height:28px;color:var(--accent-deep);margin-bottom:16px;transition:color .3s,transform .3s}
.tier:hover .t-ico{color:var(--green-deep);transform:translateY(-2px)}
.tier .t-ico svg{width:100%;height:100%}
.tier .t-ico path,.tier .t-ico circle,.tier .t-ico line,.tier .t-ico polyline{stroke:currentColor;stroke-width:1.75;fill:none;stroke-linecap:round;stroke-linejoin:round}
.tier .age{font-size:11px;letter-spacing:0.14em;text-transform:uppercase;color:var(--muted);font-weight:800}
.tier h3{font-family:var(--display);text-transform:uppercase;font-size:22px;line-height:1.02;letter-spacing:-.018em;margin:9px 0 11px}
.tier p{font-size:14px;color:#4A4E57;line-height:1.6;margin-bottom:var(--s-3)}
.tier .go{margin-top:auto;padding-top:14px;border-top:1px solid var(--line-l);font-size:13px;font-weight:800;letter-spacing:.04em;text-transform:uppercase;display:inline-flex;align-items:center;gap:8px;color:var(--ink)}
.tier .go .arw{color:var(--accent-deep);transition:transform .25s}
.tier:hover .go .arw{transform:translateX(5px)}
/* Five cards, not four. `.prog-tiers` is declared once and never overridden later in this file,
   so unlike `.xgrid` (which IS silently re-declared further down) these three lines are the whole
   story for the tier grid — change the count here and nowhere else.
   5 -> 3 -> 2 -> 1, the top count set on the base rule above. Five is an awkward number and only
   the 3-across band divides cleanly (3 + 2, which reads as a row). The 2-across band leaves Team
   Testing alone on row three; that is deliberate rather than unavoidable — it is the one offering
   here that is not an individual path, so it standing apart reads as intent. Do not "fix" it by
   spanning that card full width: `.tcover` is aspect-ratio 3/4, so a full-width card at 720px
   would carry a 960px-tall photo.
   1160px is where 5-across would drop below ~200px per card (measured: 224px at 1440px viewport).
   820px is where 3-across would; 560px where 2-across would. */
@media(max-width:1160px){.prog-tiers{grid-template-columns:repeat(3,1fr);gap:16px}}
@media(max-width:820px){.prog-tiers{grid-template-columns:1fr 1fr}}
@media(max-width:560px){.prog-tiers{grid-template-columns:1fr}}


/* ===== PROGRAM TILES ======================================================
   Josh asked for "the sameish style that you did for the pillars". Same
   vocabulary as the Method lanes: full-bleed photograph, outlined number, copy
   anchored to the floor, a coloured bar that runs on hover, and the picture
   switching on underneath it.
   What is deliberately NOT the same is the rhythm. This section sits directly
   above the Method, and two edge-to-edge dark bands back to back would read as
   one very long section. So these are gapped, rounded cards standing on the
   light paper ground, three across -- same family, different sentence, and the
   Method still gets to be the bigger moment.
   Everything above (.tier, .prog-tiers) is now unreferenced by any page. Left
   in place only because .tier is still named in the shared .photo-slot rule
   further down; nothing here depends on it. */
.pgm-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;margin-top:var(--s-4)}

.pgm{position:relative;isolation:isolate;overflow:hidden;
  border-radius:var(--r-lg);text-decoration:none;color:#fff;
  min-height:clamp(400px,33vw,460px);
  display:flex;flex-direction:column;justify-content:flex-end;
  padding:30px 26px 30px;
  transition:transform .34s cubic-bezier(.16,1,.3,1),box-shadow .34s}
.pgm:hover{transform:translateY(-6px);box-shadow:0 24px 52px -20px rgba(22,23,26,.55)}

/* Same odd/even split as the Method lanes. Across three columns that lands as a
   checkerboard rather than stripes, which is the point -- row two does not
   repeat row one. It survives the 2-across and 1-across breakpoints unchanged
   because nth-child counts source order, not grid position. */
.pgm:nth-child(odd){--lane:#8CC63F;--lane-hot:#B4F53F;--lane-wash:rgba(160,229,60,.55)}
.pgm:nth-child(even){--lane:#63B7DE;--lane-hot:#4FD8FF;--lane-wash:rgba(79,216,255,.55)}

/* Gradient on the wrapper, not the image, so it is also the empty state: if a
   photo 404s, onerror deletes the <img> and this is what is left. */
.pgm-shot{position:absolute;inset:0;z-index:0;
  background:linear-gradient(178deg,#242830 0%,#191C21 55%,#0F1114 100%)}
.pgm-shot img{width:100%;height:100%;object-fit:cover;object-position:50% 32%;
  filter:grayscale(.55) contrast(1.06) brightness(.78) saturate(.9);
  transform:scale(1.05);
  transition:filter .6s,transform .7s cubic-bezier(.16,1,.3,1)}
.pgm:hover .pgm-shot img{filter:grayscale(0) contrast(1.1) brightness(1) saturate(1.4);
  transform:scale(1)}
/* 06 is a composited handset on a dark ground, not a photograph of a person.
   Scaling and desaturating it makes it look broken rather than moody, so it
   holds still and only brightens. */
.pgm:nth-child(6) .pgm-shot img{object-position:50% 42%;
  filter:contrast(1.02) brightness(.86) saturate(1);transform:none}
.pgm:nth-child(6):hover .pgm-shot img{filter:contrast(1.04) brightness(1.06) saturate(1.15);
  transform:none}

.pgm-shot::after{content:"";position:absolute;inset:0;z-index:1;pointer-events:none;
  background:linear-gradient(180deg,rgba(0,0,0,0) 46%,var(--lane-hot) 100%);
  mix-blend-mode:soft-light;opacity:0;transition:opacity .55s}
.pgm:hover .pgm-shot::after{opacity:.95}

/* These tiles carry four lines of copy where the Method lanes carry two, so the
   scrim has to come up higher and harder than the Method's does. */
.pgm::before{content:"";position:absolute;inset:0;z-index:1;pointer-events:none;
  background:linear-gradient(180deg,
    rgba(15,17,20,.34) 0%,
    rgba(15,17,20,.20) 20%,
    rgba(15,17,20,.56) 42%,
    rgba(15,17,20,.88) 64%,
    rgba(15,17,20,.97) 100%)}

.pgm::after{content:"";position:absolute;left:0;right:0;bottom:0;height:3px;z-index:5;
  background:var(--lane);transform:scaleX(.22);transform-origin:left;
  transition:transform .55s cubic-bezier(.16,1,.3,1),
             background .4s,height .35s,box-shadow .45s}
.pgm:hover::after{transform:scaleX(1);height:5px;
  background:var(--lane-hot);box-shadow:0 -2px 26px 1px var(--lane-wash)}

.pgm-no{position:absolute;top:16px;left:22px;z-index:3;pointer-events:none;
  font-family:var(--display);font-weight:400;
  font-size:clamp(50px,4.6vw,74px);line-height:.78;letter-spacing:-.02em;
  color:transparent;-webkit-text-stroke:1.5px rgba(255,255,255,.34);
  transition:-webkit-text-stroke-color .5s,filter .5s}
.pgm:hover .pgm-no{-webkit-text-stroke-color:var(--lane-hot);
  filter:drop-shadow(0 0 16px var(--lane-wash))}

/* Floor light, same trick as the Method: z-index -1 inside .pgm-inner's own
   stacking context puts it above the scrim but behind the words, so the copy
   gets a coloured pool under it rather than a coloured film over it. */
.pgm-inner{position:relative;z-index:3;display:block}
.pgm-inner::before{content:"";position:absolute;left:-40px;right:-40px;bottom:-46px;
  height:220px;z-index:-1;pointer-events:none;
  background:linear-gradient(0deg,var(--lane-wash) 0%,rgba(0,0,0,0) 76%);
  opacity:0;transition:opacity .5s}
.pgm:hover .pgm-inner::before{opacity:.8}

.pgm-who{display:block;font-size:11px;letter-spacing:0.14em;text-transform:uppercase;
  font-weight:800;color:var(--lane);transition:color .4s}
.pgm:hover .pgm-who{color:var(--lane-hot)}
/* Two lines reserved: "Team Testing & Training" wraps and the other five do not,
   which without this puts the descriptions on six different baselines. Released
   at 640px where the tiles stack. */
.pgm h3{font-family:var(--display);font-weight:400;text-transform:uppercase;
  font-size:clamp(21px,1.9vw,27px);line-height:.98;letter-spacing:.02em;
  margin:10px 0 11px;color:#fff;min-height:1.96em}
/* Three lines reserved for the same reason the heading reserves two: the tiles
   are bottom-anchored, and Veterans' description runs to two lines where the
   other five run to three, which dropped its whole block 11px below the row. */
.pgm-desc{display:block;font-size:13.5px;line-height:1.55;color:rgba(255,255,255,.76);
  min-height:4.65em}
.pgm-entry{display:block;margin-top:15px;padding-top:13px;
  border-top:1px solid rgba(255,255,255,.22);
  font-size:12.5px;line-height:1.45;color:#fff;font-weight:700;
  transition:border-color .45s}
.pgm:hover .pgm-entry{border-top-color:var(--lane-hot)}
.pgm-entry i{display:block;font-style:normal;font-size:11px;letter-spacing:0.14em;
  text-transform:uppercase;font-weight:800;color:var(--muted-d);margin-bottom:5px}
.pgm-go{display:inline-flex;align-items:center;gap:8px;margin-top:16px;
  font-size:11.5px;letter-spacing:.14em;text-transform:uppercase;font-weight:800;color:#fff}
.pgm-go .arw{color:var(--lane);transition:transform .3s,color .4s}
.pgm:hover .pgm-go .arw{transform:translateX(5px);color:var(--lane-hot)}

/* 3 -> 2 -> 1. Six divides cleanly into all three, so unlike the old five-card
   grid there is no orphan row to design around. */
@media(max-width:1040px){.pgm-grid{grid-template-columns:1fr 1fr;gap:16px}}
@media(max-width:640px){
  .pgm-grid{grid-template-columns:1fr}
  .pgm{min-height:340px;padding:24px 22px 26px}
  .pgm h3{min-height:0}
  .pgm-desc{min-height:0}
  .pgm-no{font-size:52px;top:14px;left:18px}
}

@media(prefers-reduced-motion:reduce){
  .pgm,.pgm-shot img,.pgm-shot::after,.pgm::after,.pgm-no,
  .pgm-inner::before,.pgm-entry,.pgm-go .arw{transition:none}
  .pgm:hover{transform:none}
  .pgm::after{transform:scaleX(1)}
}

/* ===== INLINE CTA STRIP ===== */
.ctastrip{background:var(--ink);color:#fff;padding:var(--s-5) 0;border-top:1px solid var(--line-d);border-bottom:1px solid var(--line-d);position:relative;overflow:hidden}
.ctastrip.light{background:var(--paper);color:var(--ink);border-color:var(--line-l)}
.cs-inner{display:flex;align-items:center;justify-content:space-between;gap:var(--s-4);flex-wrap:wrap;position:relative;z-index:2}
.cs-txt b{display:block;font-family:var(--display);text-transform:uppercase;font-size:clamp(20px,2.5vw,30px);line-height:1.04;letter-spacing:-.018em}
.cs-txt span{display:block;font-size:14.5px;color:var(--muted-d);margin-top:8px}
.ctastrip.light .cs-txt span{color:var(--muted)}
.cs-act{display:flex;gap:12px;align-items:center;flex-wrap:wrap}
.cs-price{font-size:11px;letter-spacing:.14em;text-transform:uppercase;color:var(--green);font-weight:800}
.ctastrip.light .cs-price{color:var(--green-deep)}
@media(max-width:640px){.cs-inner{flex-direction:column;align-items:flex-start}.cs-act .btn{width:100%;justify-content:center}}

/* ===== PARENT VOICES ===== */
.parents{background:var(--paper-2);padding:var(--sec) 0}
.pv-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:18px}
.pv{border:1px solid var(--line-l);border-radius:var(--r-md);padding:28px 26px;background:var(--paper);display:flex;flex-direction:column;
  transition:transform .3s cubic-bezier(.16,1,.3,1),box-shadow .3s,border-color .3s}
.pv:hover{transform:translateY(-5px);box-shadow:var(--sh-2);border-color:var(--sky)}
.pv .stars{color:var(--green-deep);font-size:14px;letter-spacing:3px;margin-bottom:14px}
.pv p{font-size:15.5px;color:#3A3E47;line-height:1.66;flex:1;margin-bottom:20px}
.pv .by{display:flex;align-items:center;gap:12px;padding-top:16px;border-top:1px solid var(--line-l)}
.pv .av{width:40px;height:40px;border-radius:50%;background:linear-gradient(150deg,var(--sky),var(--green));flex:none;display:grid;place-items:center;font-family:var(--display);font-size:15px;color:#fff}
.pv .by b{display:block;font-family:var(--display);text-transform:uppercase;font-size:15px;line-height:1;letter-spacing:-.01em}
.pv .by span{display:block;font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--muted);font-weight:700;margin-top:5px}
.pv.placeholder{border-style:dashed;background:transparent}
.pv.placeholder p{color:var(--muted);font-style:italic}
.pv.placeholder .av{background:var(--line-l);color:var(--muted)}
@media(max-width:1000px){.pv-grid{grid-template-columns:1fr}}

/* ===== PHOTO PLACEHOLDERS — scaled frames, unmistakably "photo goes here" ===== */
.photo-slot{position:relative;overflow:hidden;display:grid;place-items:center;
  background:
    repeating-linear-gradient(45deg,rgba(255,255,255,.022) 0 10px,transparent 10px 20px),
    linear-gradient(160deg,#23262B,#16181C);
  border:1px dashed rgba(255,255,255,.14)}
.photo-slot img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:3;background:var(--ink-2)}
/* person silhouette so a portrait slot reads instantly as a portrait */
.photo-slot .ph{position:relative;z-index:2;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:9px;
  font-size:11px;letter-spacing:0.14em;text-transform:uppercase;color:rgba(255,255,255,.4);text-align:center;padding:12px;font-weight:700;line-height:1.6}
.photo-slot .ph::before{content:"";width:38px;height:38px;opacity:.5;
  background:currentColor;
  -webkit-mask:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='8' r='4'/><path d='M4 21c0-4.4 3.6-8 8-8s8 3.6 8 8z'/></svg>") center/contain no-repeat;
  mask:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='8' r='4'/><path d='M4 21c0-4.4 3.6-8 8-8s8 3.6 8 8z'/></svg>") center/contain no-repeat}
.photo-slot .ph em{display:block;font-style:normal;color:rgba(255,255,255,.25);font-size:11px;letter-spacing:.1em;margin-top:2px}
/* action/scene slots get a landscape frame mark instead of a person */
.life-grid .photo-slot .ph::before,.photoband .photo-slot .ph::before,.pt-media .photo-slot .ph::before,.fmedia .ph::before{
  -webkit-mask:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><rect x='2.5' y='4.5' width='19' height='15' rx='2' fill='none' stroke='black' stroke-width='2'/><circle cx='8.5' cy='10' r='1.8'/><path d='M3 17l5-4.5 4 3.5 3.5-3L21 17'/></svg>") center/contain no-repeat;
  mask:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><rect x='2.5' y='4.5' width='19' height='15' rx='2' fill='none' stroke='black' stroke-width='2'/><circle cx='8.5' cy='10' r='1.8'/><path d='M3 17l5-4.5 4 3.5 3.5-3L21 17'/></svg>") center/contain no-repeat;
  width:44px;height:44px}
/* on light sections invert the frame so it doesn't look like a hole */
.pv .photo-slot,.tier .photo-slot{background:repeating-linear-gradient(45deg,rgba(22,23,26,.03) 0 10px,transparent 10px 20px),#E9E8E5;border-color:rgba(22,23,26,.16)}
.pv .photo-slot .ph,.tier .photo-slot .ph{color:rgba(22,23,26,.42)}

/* ===== TIGHTER PROGRAMS ===== */
.progs{padding:var(--sec-sm) 0}
.prog-head-row{display:flex;justify-content:space-between;align-items:flex-end;gap:var(--s-4);flex-wrap:wrap;margin-bottom:var(--s-4)}
.prog-head-row h2{font-family:var(--display);text-transform:uppercase;font-size:clamp(26px,3.4vw,42px);line-height:1;letter-spacing:-.02em;margin-top:var(--s-2)}
.prog-head-row p{font-size:15px;color:#4A4E57;max-width:360px;padding-bottom:6px}
.tier{padding:22px 20px 20px;min-height:0}
.tier h3{font-size:20px;margin:7px 0 8px}
.tier p{font-size:13.5px;margin-bottom:var(--s-2)}
.tier .go{padding-top:12px;font-size:12px}

/* ===== NAVY CAPTION ===== */
.navy-cap{font-size:14.5px;color:rgba(255,255,255,.62);font-style:italic;margin:14px 0 20px;line-height:1.6}

/* ===== CHIP QUOTE IN FOUNDER ===== */
.chipquote{margin-top:var(--s-4);padding:20px 22px;border-left:3px solid var(--green);background:rgba(255,255,255,.04);border-radius:0 var(--r-md) var(--r-md) 0}
.chipquote p{font-size:15px;color:rgba(255,255,255,.86);line-height:1.6;margin-bottom:12px}
.chipquote p b{color:var(--green)}
.chipquote cite{font-style:normal;display:block}
.chipquote cite b{font-family:var(--display);text-transform:uppercase;font-size:14px;letter-spacing:-.01em}
.chipquote cite span{display:block;font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--muted-d);font-weight:700;margin-top:4px}

/* ===== RESULTS: number row ===== */
.numrow{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;margin-top:var(--s-4);padding-top:var(--s-4);border-top:1px solid var(--line-l)}
.nr{text-align:center;padding:16px 10px;border:1px solid var(--line-l);border-radius:var(--r-md);background:var(--paper);transition:transform .3s cubic-bezier(.16,1,.3,1),border-color .3s}
.nr:hover{transform:translateY(-4px);border-color:var(--sky)}
.nr b{display:block;font-family:var(--display);font-size:clamp(24px,3vw,34px);line-height:1;letter-spacing:-.02em;color:var(--accent-deep)}
.nr b i{font-style:normal;font-size:.45em;color:var(--muted)}
.nr span{display:block;font-size:11px;letter-spacing:.06em;color:var(--muted);font-weight:700;margin-top:9px;line-height:1.45}
@media(max-width:860px){.numrow{grid-template-columns:1fr 1fr}}

/* ===== VOICES ===== */
.voices{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-top:var(--s-4)}
.voice{border:1px solid var(--line-d);border-radius:var(--r-md);padding:24px 22px;display:flex;flex-direction:column;transition:transform .3s cubic-bezier(.16,1,.3,1),border-color .3s,background .3s}
.voice:hover{transform:translateY(-5px);border-color:rgba(255,255,255,.3);background:rgba(255,255,255,.03)}
.voice .stars{color:var(--green);font-size:13px;letter-spacing:3px;margin-bottom:12px}
.voice p{font-size:14.5px;color:rgba(255,255,255,.82);line-height:1.62;flex:1;margin-bottom:18px}
.voice .by{display:flex;align-items:center;gap:11px;padding-top:14px;border-top:1px solid var(--line-d)}
.voice .av{width:36px;height:36px;border-radius:50%;background:linear-gradient(150deg,var(--sky),var(--green));flex:none;display:grid;place-items:center;font-family:var(--display);font-size:12px;color:#fff}
.voice .by b{display:block;font-family:var(--display);text-transform:uppercase;font-size:14px;line-height:1;letter-spacing:-.01em}
.voice .by span{display:block;font-size:11px;letter-spacing:.1em;text-transform:uppercase;color:var(--muted-d);font-weight:700;margin-top:5px}
.voice.placeholder{border-style:dashed}
.voice.placeholder p{color:var(--muted-d);font-style:italic}
.voice.placeholder .av{background:rgba(255,255,255,.1);color:var(--muted-d)}
@media(max-width:1000px){.voices{grid-template-columns:1fr}}

/* ===== DUO: PT + APP ===== */
/* The .duo two-card block was split into the standalone .rx and .apx sections; see the
   end of this file. All .duo* rules were removed with it. */

/* life caption tighter */
.life-cap{padding:26px 0 var(--sec-sm)}
.life-cap p{font-size:15px;color:var(--muted-d);max-width:620px;margin:0 auto;text-align:center}
.life-cap p b{color:#fff}

/* ================= PILLARS: MUCH SMALLER ================= */
.method{padding:var(--sec-sm) 0}
.method-head{margin-bottom:var(--s-2)}
.curve{height:40px;margin:6px 0 var(--s-3)}
.pillars{gap:12px;margin-top:var(--s-3)}
.pillars::before{display:none}
/* far shallower staircase — was 0/26/52/78 */
.pillar:nth-child(1){margin-bottom:0}
.pillar:nth-child(2){margin-bottom:12px}
.pillar:nth-child(3){margin-bottom:24px}
.pillar:nth-child(4){margin-bottom:36px}
.pillar{padding:18px 16px 18px;border-radius:var(--r-md)}
.pillar .p-ico{width:22px;height:22px;margin-bottom:12px}
.pillar .no{font-size:11px;letter-spacing:.14em;margin-bottom:9px}
.pillar .no::before{width:14px;height:2px}
.pillar:hover .no::before{width:22px}
.pillar h3{font-size:16px;line-height:1.08;margin:0 0 7px}
.pillar p{font-size:12.5px;line-height:1.55;margin-bottom:14px}
.pillar .gives{padding-top:10px}
.pillar .gives span{font-size:11px;letter-spacing:.13em;margin-bottom:3px}
.pillar .gives b{font-size:12px;line-height:1.2}
.pillar:hover{transform:translateY(-5px)}
.climb-note{margin-top:var(--s-4);padding-top:var(--s-3)}
.climb-note p{font-size:14px}
@media(max-width:1000px){
  .pillar:nth-child(2),.pillar:nth-child(4){margin-bottom:14px}
  .pillar:nth-child(1),.pillar:nth-child(3){margin-bottom:0}
}
@media(max-width:640px){.pillar{margin-bottom:0!important}}

/* ================= TYPE SYSTEM v3 — BEBAS NEUE + INTER =================
   Bebas: tall, condensed, athletic — the Spellman-tier look. Display only.
   Inter: clean, modern UI/body. All labels, paragraphs, small headings. */
:root{
  --display:'Bebas Neue',Impact,sans-serif;
  --display-2:'Bebas Neue',Impact,sans-serif;
  --body:'Inter',system-ui,-apple-system,sans-serif;
  /* v3 overrode --display and --body but left --mono on the v2 Archivo stack, which no page
     ever loads — so every var(--mono) label fell through to system-ui. Inter matches the
     "everything small = Inter" rule below. Do NOT reintroduce Archivo. */
  --mono:'Inter',system-ui,-apple-system,sans-serif;
}
body{font-family:var(--body);font-size:17px;line-height:1.65}

/* Bebas wants slight positive tracking and tight leading — kill all the
   negative tracking set for Archivo Black */
.hero h1,.cta h2,.sec-head h2,.method-head h2,.split-col h2,.prog-head-row h2,
.founder h2,.rx-panel .rx-partner b,.photoband .overlay h2,.page-hero h1,.man-lead,
.hh-accolade,.tier h3,.pillar h3,.rcard b,.pro-id b,.founder-badge b,
.xform h3,.hh-name,.nr b,.stat .k,.price,.fcred b,.foot-brand b,
.voice .by b,.chipquote cite b,.pillar .gives b{
  font-family:var(--display);font-weight:400;letter-spacing:.015em;line-height:.94}

/* display sizes — Bebas is condensed, so it can run larger */
.hero h1{font-size:clamp(64px,11vw,150px);line-height:.88}
.sec-head h2,.split-col h2,.founder h2,.prog-head-row h2,.method-head h2{font-size:clamp(38px,5vw,64px)}
.cta h2{font-size:clamp(52px,8vw,110px);line-height:.88}
.hh-accolade{font-size:clamp(24px,2.4vw,30px);line-height:.95;margin-top:8px}
.tier h3{font-size:26px}
.pillar h3{font-size:19px}
.rcard b{font-size:24px}
.pro-id b{font-size:clamp(24px,2.4vw,30px)}

.hh-name{font-size:13px;font-family:var(--body);font-weight:700;letter-spacing:.14em;line-height:1.2}
.nr b{font-size:clamp(30px,3.4vw,42px)}
.stat .k{font-size:clamp(40px,5vw,62px)}
.xform h3{font-size:26px}
.founder-badge b{font-size:24px}
.voice .by b,.chipquote cite b{font-size:16px;letter-spacing:.03em}
.pillar .gives b{font-size:15px;letter-spacing:.02em}
.fcred b{font-size:26px}

/* everything small = Inter, bold, tracked */
.eyebrow,.tie,.sport,.age,.no,.lab,.cyc,.u,.dest,.badge-tag,.pro-cred,
.hh-town,.entry-tag,.price-lab,.crumb,.badge-label,.cs-price,.nav-links a,
.sign-in,.stat .cyc,.logo-ph,.go,.hh-desc,.navy-list li span,.rcard .tie{
  font-family:var(--body)}
.eyebrow{font-size:11px;font-weight:700;letter-spacing:0.14em}
.nav-links a{font-size:12.5px;font-weight:700;letter-spacing:.12em}
p,.blurb,.story,.hh-desc,.acc,.note,.lead{font-family:var(--body);font-weight:400}
.btn{font-family:var(--body);font-weight:700;letter-spacing:.04em;text-transform:uppercase;font-size:13px}

/* units inside big numerals */
.stat .k .unit,.nr b i{font-family:var(--body);font-weight:700;font-size:.34em;letter-spacing:.04em}

/* ================= PLACEHOLDERS v3 — clean blank boxes, true scale ======= */
.photo-slot{position:relative;overflow:hidden;display:grid;place-items:center;
  background:#22252B;border:1px solid rgba(255,255,255,.1)}
.photo-slot .ph{position:relative;z-index:2;font-family:var(--body);font-size:11px;font-weight:700;
  letter-spacing:.14em;text-transform:uppercase;color:rgba(255,255,255,.34);text-align:center;
  line-height:1.7;padding:10px}
.photo-slot .ph::before{display:none}
.photo-slot .ph em{display:block;font-style:normal;color:rgba(255,255,255,.2);font-size:11px;margin-top:2px}
.photo-slot img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:3}
/* transparent-cutout portraits sit on a gradient, not cover-cropped */
.photo-slot img.cutout{object-fit:contain;object-position:center bottom;
  background:radial-gradient(120% 90% at 50% 15%,#2E3340,#171A1F)}
/* light-section boxes */
.pv .photo-slot,.tier .photo-slot{background:#E9E8E5;border-color:rgba(22,23,26,.14)}
.pv .photo-slot .ph,.tier .photo-slot .ph{color:rgba(22,23,26,.38)}

/* logo bar: real files + true-proportion blanks */

/* ================= SECTION LINKS — buttons only where action lives ====== */
.sec-link{display:inline-flex;align-items:center;gap:8px;font-family:var(--body);font-size:12px;
  font-weight:800;letter-spacing:.14em;text-transform:uppercase;color:var(--accent-deep)}
.section-d .sec-link,.pros .sec-link,.founder .sec-link,.method .sec-link{color:var(--sky)}
.sec-link .arw{transition:transform .25s}
.sec-link:hover .arw{transform:translateX(4px)}
.head-row{display:flex;justify-content:space-between;align-items:flex-end;gap:var(--s-4);flex-wrap:wrap;margin-bottom:var(--s-4)}
.head-row .sec-head{margin-bottom:0}
.head-row .sec-link{padding-bottom:10px}

/* tighter global rhythm for the punchy layout */
.sec-head p,.blurb{font-size:15px}
.sec-head{max-width:none}

/* ===== FINAL TIGHTEN (v3 layout) ===== */
/* hometown cards: photo + name + accolade only */
.hh-body{padding:16px 16px 18px}
.hh-accolade{color:var(--accent-deep)}
.hh:hover .hh-accolade{color:var(--green-ink)}  /* --green-deep is 2.55:1 on --paper */
.split-col{padding:60px 44px}
.split-col .blurb{margin-bottom:20px}
/* founder tighter */
.founder{padding:var(--sec-sm) 0}
.founder .story{font-size:16.5px;margin-bottom:var(--s-3)}
.founder .story b{font-family:var(--display);font-size:1.25em;letter-spacing:.02em;color:var(--sky)}
.founder h2 em{font-style:normal;color:var(--sky)}
/* pillars: icon + name + payoff only */
.pillar p{display:none}
.pillar .gives{margin-top:14px;padding-top:10px}
/* tiers: name-forward, minimal */
.tier{min-height:0;padding:22px 20px 18px}
.tier p{display:none}
.tier .go{margin-top:14px}
/* section paddings — punchier rhythm */
.pros{padding:var(--sec-sm) 0}
.section-p2{padding:var(--sec-sm) 0}
.section-d{padding:var(--sec-sm) 0}
.split{padding:0}
/* xform cards tighter */
.xform{padding:22px 20px}
.xform .note{font-size:13.5px;margin-top:14px;max-width:none}
.xform.feature .fbody{padding:28px 30px 28px 0}
.xstats{gap:8px}
.xstat{padding:9px 12px}
.xstat .lab{font-size:11px}
/* voices tighter */
.voices{margin-top:var(--s-3)}
.voice{padding:20px 20px}
.voice p{font-size:14px}
/* duo tighter */
/* roster cards tighter */
.rcard{padding:20px 20px 18px}
.rcard .acc{font-size:13px}
.rcard .tie{margin-top:12px;padding-top:10px;font-size:11px}
/* cta strip type */
.cs-txt b{font-size:clamp(24px,2.8vw,34px)}
.cs-txt span{font-size:13.5px}
/* final cta */
.cta{padding:var(--sec-sm) 0}
.cta p{font-size:16px;margin:16px auto 26px}
/* hh wide photo ratio on the full-width card */
.hh.wide .hh-photo{width:220px;aspect-ratio:4/3}
@media(max-width:640px){.hh.wide .hh-photo{width:100%}}
/* navy col heading spacing */
.split-col.navy h2{margin-bottom:6px}
.navy-photo{aspect-ratio:16/10}

/* ================= TYPE — FINAL, ONE RULE SET =================
   Bebas Neue ships in ONE weight (400). Never bold it. */
.hero h1,.cta h2,.sec-head h2,.method-head h2,.split-col h2,.founder h2,
.duo-card h3,.photoband .overlay h2,.page-hero h1,.man-lead,.hh-accolade,
.tier h3,.pillar h3,.rcard b,.pro-id b,.founder-badge b,.xform h3,.nr b,
.stat .k,.stat .k b,.price,.fcred b,.foot-brand b,.pillar .gives b,
.cs-txt b,.tile b,.prog h3,.quote .who b,.faq summary,
.pt-partner b,.entry-steps li b,.entry h2,.man-figure .big,.mrow h3,
.mrow .mno,.cyc h4,.coach h3,.ht .record .t,.pblock h3,.brand-txt b,
.tile .stat-big,.name-chip b,.hh-tag{
  font-family:var(--display)!important;font-weight:400!important;
  letter-spacing:.025em;line-height:.94}

/* small Bebas needs a touch more air */
.rcard b,.xform h3,.tier h3,.pillar h3,.fcred b,.pillar .gives b,.faq summary{letter-spacing:.04em}

/* names & bylines are NOT display type — Inter, small, tracked */
.hh-name,.voice .by b,.chipquote cite b,.pv .by b,.founder-badge span,
.pro-id span,.rcard .tie,.who span{
  font-family:var(--body)!important;font-weight:800!important;
  letter-spacing:.12em;text-transform:uppercase}
.voice .by b,.chipquote cite b{font-size:12.5px}
.hh-name{font-size:12px;color:var(--muted)}
.founder .story b{font-family:var(--body)!important;font-weight:800!important;color:var(--sky);font-size:1em;letter-spacing:0;text-transform:none}

/* sane defaults everywhere else */
b,strong{font-weight:700}
p,li,.blurb,.story,.acc,.note{font-family:var(--body)}

/* ================= AFFILIATION BAR — FINAL =================
   Real logos float free; placeholders are quiet outlined chips. */
.badges{background:var(--paper-2);border-top:1px solid var(--line-l);border-bottom:1px solid var(--line-l);padding:20px 0 18px;overflow:hidden;position:relative}
.badges::before,.badges::after{content:"";position:absolute;top:0;bottom:0;width:120px;z-index:3;pointer-events:none}
.badges::before{left:0;background:linear-gradient(90deg,var(--paper-2),transparent)}
.badges::after{right:0;background:linear-gradient(270deg,var(--paper-2),transparent)}
.badge-label{text-align:center;font-family:var(--body);font-size:11px;letter-spacing:0.14em;text-transform:uppercase;color:var(--muted);font-weight:700;margin-bottom:16px}
.marquee{display:flex;width:max-content;animation:marquee 58s linear infinite}
.badges:hover .marquee{animation-play-state:paused}
@keyframes marquee{from{transform:translateX(0)}to{transform:translateX(-50%)}}
.mtrack{display:flex;align-items:center;gap:64px;padding-right:64px}
.badge{flex:none;display:flex;align-items:center}
.logo-real{display:flex;align-items:center}
.logo-real img{height:34px;width:auto;object-fit:contain;filter:grayscale(1);opacity:.7;transition:filter .25s,opacity .25s}
.badge:hover .logo-real img{filter:none;opacity:1}
.logo-ph{display:inline-flex;align-items:center;height:34px;padding:0 16px;border:1px solid rgba(22,23,26,.16);border-radius:4px;
  font-family:var(--body);font-weight:700;font-size:11px;letter-spacing:.14em;text-transform:uppercase;
  color:rgba(22,23,26,.42);white-space:nowrap;background:transparent}
@media(max-width:640px){.mtrack{gap:40px;padding-right:40px}.logo-real img,.logo-ph{height:30px}}
@media(prefers-reduced-motion:reduce){.marquee{animation:none}}

/* stat rail under hero — cleaner on mobile */
@media(max-width:860px){.stat{border-right:none}.stat:nth-child(2){border-right:none}}

/* SCOPED to the mobile breakpoint on purpose. These were unscoped, so .open kept
   styling the nav as an absolute drop-down panel at EVERY width — while the
   hamburger that closes it is display:none above 860px. Open the menu on an iPad
   in portrait, rotate to landscape, and a 1013x269 panel sat over the hero with
   no control anywhere on the page to dismiss it. Same for any window resize
   across the breakpoint. If these rules ever move, they move together. */
@media(max-width:860px){
  /* max-height + overflow-y are LOAD-BEARING. The panel is position:absolute under a
     sticky header, so it cannot grow past the viewport and cannot be scrolled into view —
     scrolling the page does not move it. With Programs expanded it is ~764px tall, so on an
     iPhone 13/14 (703px of Safari viewport) App, Coaches and FAQ sat below the fold with no
     scrollbar and no way to reach them; on an SE, six items did. The desktop dropdown has
     had exactly this guard since it was built (.nd-menu, ~line 5377) and the mobile rule
     that deliberately removes it never replaced it with one of its own. */
  .nav-links.open{display:flex;position:absolute;top:70px;left:0;right:0;flex-direction:column;gap:0;background:var(--ink);padding:8px 32px 20px;border-bottom:1px solid var(--line-d);max-height:calc(100vh - 70px);overflow-y:auto;-webkit-overflow-scrolling:touch;overscroll-behavior:contain}
  .nav-links.open a{padding:14px 0;border-bottom:1px solid var(--line-d)}
}

/* ================= HOMEPAGE REWORK ===================================== */

/* The hero stat rail reuses the class name .cyc, which the Programs page
   styles as a white card — that painted white boxes under each stat. */
.stat .cyc{background:none;border:0;padding:0}

/* Photo frames set an aspect ratio, but the .photo-slot inside them was
   sizing to its caption text, so images collapsed to a sliver. */
.hh-photo>.photo-slot,
.founder-photo>.photo-slot,
.floor-photo>.photo-slot,
.pro-photo>.photo-slot,
.xform.feature .fmedia>.photo-slot{position:absolute;inset:0}

.life-grid .photo-slot{aspect-ratio:1/1;position:relative;transition:transform .35s}
.life-grid .photo-slot.tall{aspect-ratio:3/4}
.life-grid .photo-slot::after{content:"";position:absolute;inset:0;z-index:4;
  background:rgba(99,183,222,0);transition:background .35s;pointer-events:none}

/* Scrims that make overlaid names readable. */
.hh-photo::after{content:"";position:absolute;inset:0;z-index:4;pointer-events:none;
  background:linear-gradient(180deg,transparent 42%,rgba(22,23,26,.88))}
.founder-photo::after{content:"";position:absolute;inset:0;z-index:3;pointer-events:none;
  background:linear-gradient(180deg,transparent 52%,rgba(18,19,22,.86))}
.pro-photo::after{content:"";position:absolute;inset:0;z-index:3;pointer-events:none;
  background:linear-gradient(180deg,transparent 38%,rgba(18,19,22,.94) 92%)}
.hh-town,.founder-badge,.pro-id,.pro-cred{z-index:5}

/* ---- Trusted By Programs: logo + accolade per team ---- */
.navy-list li{display:flex;align-items:center;gap:16px;padding:16px 0}
.navy-list li::before{display:none}
.navy-list li:hover{padding-left:0}
.team-logo{flex:none;width:52px;height:52px;border-radius:10px;display:grid;place-items:center;
  position:relative;overflow:hidden;background:rgba(255,255,255,.07);
  border:1px solid rgba(255,255,255,.16)}
.team-logo img{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;padding:7px;z-index:2}
.team-logo i{font-style:normal;font-family:var(--body);font-size:11px;font-weight:800;
  letter-spacing:.08em;color:rgba(255,255,255,.5)}
.team-txt{display:block;min-width:0}
.team-txt b{display:block;font-size:15.5px;font-weight:700;color:#fff;line-height:1.3}
.team-role{display:block;font-size:12.5px;color:var(--muted-d);margin-top:4px;letter-spacing:.04em}
.team-acc{display:inline-block;font-family:var(--body);font-size:11px;font-weight:800;
  letter-spacing:.13em;text-transform:uppercase;color:var(--green);margin-top:7px}
.navy-list li.team-todo{opacity:.5}
.navy-list li.team-todo .team-logo{border-style:dashed;background:transparent}
.navy-list li.team-todo .team-logo i{font-size:17px;color:rgba(255,255,255,.4)}

/* ---- Founder: smaller portrait, larger and easier body copy ---- */
.founder-grid{grid-template-columns:minmax(0,.72fr) minmax(0,1.28fr);align-items:center}
.founder-photo{max-width:360px;width:100%;margin-inline:auto}
/* was clamp(28px,3.2vw,44px) -- that made the founder headline the only section heading
   on the page below 64px. It fits its narrower column in 2 lines at 64, so it now matches. */
.founder h2{font-size:clamp(34px,4.4vw,64px);line-height:1.02}
.founder .story{font-size:19px;line-height:1.72;color:rgba(255,255,255,.9);max-width:60ch}
.founder .chipquote p{font-size:16px;line-height:1.7;color:rgba(255,255,255,.86)}
@media(max-width:900px){
  .founder-grid{grid-template-columns:1fr}
  .founder-photo{max-width:300px}
  .founder .story{font-size:17px}
}

/* ---- What They Say: roomier cards, larger quotes ---- */
.pros-grid{grid-template-columns:repeat(3,1fr);gap:28px;max-width:1180px}
.pro-photo{aspect-ratio:1/1}
.pro-body p{font-size:16.5px;line-height:1.7;color:rgba(255,255,255,.88)}
.voice p{font-size:15.5px;line-height:1.7;color:rgba(255,255,255,.86)}
@media(max-width:1000px){.pros-grid{grid-template-columns:1fr;max-width:560px}}
@media(max-width:900px){
  .pros-grid{grid-template-columns:1fr;max-width:560px}
  .voices{grid-template-columns:1fr}
}

/* ================= HOMEPAGE REVISION 2 ================= */

/* ---- Marquee: bigger logos, in their own colors ---- */
/* Height-matched, but capped in width: very wide wordmarks (PhillyMan is ~4.7:1) would
   otherwise render 264px against a 56px badge and swamp the row. width:auto keeps the
   cap from squashing anything narrower than the cap. */
.logo-real img{height:56px;width:auto;max-width:150px;object-fit:contain;filter:none;opacity:1}
.badge:hover .logo-real img{transform:scale(1.06)}
.logo-real img{transition:transform .25s}
.mtrack{gap:56px;padding-right:56px}
@media(max-width:640px){.logo-real img{height:42px;max-width:120px}.mtrack{gap:36px;padding-right:36px}}

/* Team logos ship with white backgrounds baked in, so the tile is white
   too — a transparent tile would frame each one in a pale square. */
.team-logo{width:60px;height:60px;background:#fff;border-color:rgba(255,255,255,.9)}
.team-logo img{padding:6px}
.team-logo i{color:var(--ink);font-size:11px}
.navy-list li{gap:18px}

/* ---- Testimonial avatars carry a face instead of initials ---- */
.voice .av{position:relative;overflow:hidden}
.voice .av img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:2}
.voices{grid-template-columns:repeat(2,1fr);max-width:840px}
@media(max-width:1000px){.voices{grid-template-columns:1fr;max-width:560px}}

/* ---- Pros roster: a face on every card ---- */
.rcard{display:flex;flex-direction:column;padding:0}
.rphoto{position:relative;aspect-ratio:4/3;overflow:hidden;background:linear-gradient(150deg,var(--ink-3),var(--ink))}
.rphoto .photo-slot{position:absolute;inset:0}
.rphoto img{width:100%;height:100%;object-fit:cover;object-position:50% 22%;
  transition:transform .45s cubic-bezier(.16,1,.3,1)}
.rcard:hover .rphoto img{transform:scale(1.05)}
.rphoto::after{content:"";position:absolute;inset:0;z-index:2;pointer-events:none;
  background:linear-gradient(180deg,transparent 55%,rgba(18,19,22,.92))}
.rtxt{padding:20px 22px 22px;display:flex;flex-direction:column;flex:1}
.rtxt .tie{margin-top:auto}

/* ---- Program tiers: vertical covers, not letterbox strips ---- */
.tier{display:flex;flex-direction:column;padding:0;overflow:hidden}
.tcover{display:block;position:relative;aspect-ratio:3/4;overflow:hidden;
  background:linear-gradient(150deg,var(--ink-3),var(--ink))}
.tcover img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  transition:transform .5s cubic-bezier(.16,1,.3,1)}
.tier:hover .tcover img{transform:scale(1.06)}
.tcover::after{content:"";position:absolute;inset:0;
  background:linear-gradient(180deg,transparent 45%,rgba(18,19,22,.55))}
.tbody{display:flex;flex-direction:column;flex:1;padding:22px 22px 24px}
.tbody .go{margin-top:auto;padding-top:18px}

/* ---- Hometown Heroes: 8 cards, achievement over program ---- */
.hh-school{font-family:var(--body);font-size:11.5px;font-weight:700;
  letter-spacing:.13em;text-transform:uppercase;color:var(--muted);
  line-height:1.4;margin-top:7px}
.hh-accolade{font-size:clamp(20px,1.9vw,25px)}

/* ---- Results: two-across photo cards ---- */
.xgrid{grid-template-columns:1fr 1fr}
.xform.xphoto{padding:0;display:flex;flex-direction:column;overflow:hidden}
.xphoto .xmedia{position:relative;aspect-ratio:4/3;overflow:hidden;
  background:linear-gradient(150deg,#2A2D33,#17181C)}
.xphoto .xmedia>.photo-slot{position:absolute;inset:0}
.xphoto .xmedia img{object-position:50% 16%}
.xphoto .xbody{padding:24px 26px 26px;display:flex;flex-direction:column;flex:1}
.xphoto .xbody h3{margin:7px 0 15px}
.xphoto .note{margin-top:auto;padding-top:15px;font-size:13px;color:var(--muted)}
.xform.feature .fmedia img{object-position:50% 14%}
@media(max-width:640px){.xgrid{grid-template-columns:1fr}}

/* ---- Results: drifting glow across the grid intersections ---- */
#results{overflow:hidden}
#results::after{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background-image:linear-gradient(rgba(58,166,214,.42) 1px,transparent 1px),
                   linear-gradient(90deg,rgba(58,166,214,.42) 1px,transparent 1px);
  background-size:64px 64px;
  -webkit-mask-image:radial-gradient(circle,#000 0%,rgba(0,0,0,.45) 38%,transparent 68%);
  mask-image:radial-gradient(circle,#000 0%,rgba(0,0,0,.45) 38%,transparent 68%);
  -webkit-mask-size:820px 820px;mask-size:820px 820px;
  -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
  animation:gridGlow 12s ease-in-out infinite alternate}
@keyframes gridGlow{
  0%{-webkit-mask-position:6% 8%;mask-position:6% 8%}
  50%{-webkit-mask-position:88% 52%;mask-position:88% 52%}
  100%{-webkit-mask-position:18% 94%;mask-position:18% 94%}}
@media(prefers-reduced-motion:reduce){
  #results::after{animation:none;-webkit-mask-position:50% 40%;mask-position:50% 40%}}

/* ---- Programs: descriptions + entry requirements ---- */
.sec-note{font-size:14.5px;color:var(--muted);line-height:1.6;margin-top:10px;max-width:46ch}
.tier .tdesc{display:block;font-size:14px;color:#4A4E57;line-height:1.6;margin:0 0 16px}
.tier .entry{display:flex;flex-direction:column;gap:3px;margin-top:auto;
  padding:11px 13px;border-radius:8px;background:rgba(58,166,214,.07);
  border:1px solid rgba(58,166,214,.2);font-size:13px;font-weight:600;color:var(--ink)}
.tier .entry i{font-style:normal;font-family:var(--mono);font-size:11px;font-weight:700;
  letter-spacing:0.14em;text-transform:uppercase;color:var(--accent-deep)}
.tbody .go{margin-top:16px}
@media(max-width:640px){.tier .tdesc{margin-bottom:14px}}

/* ---- Programs page: two entry points into the Athletes room ---- */
.entry-ways{margin:26px 0 28px;padding:20px 22px;border-radius:var(--r-lg);
  background:rgba(58,166,214,.06);border:1px solid rgba(58,166,214,.22)}
.ew-head{font-family:var(--mono);font-size:11px;font-weight:700;letter-spacing:0.14em;
  text-transform:uppercase;color:var(--accent-deep);margin-bottom:16px}
.ew-grid{display:grid;grid-template-columns:1fr 1fr;gap:20px}
.ew{display:flex;flex-direction:column;gap:6px}
.ew b{font-family:var(--display);text-transform:uppercase;font-size:19px;letter-spacing:-.01em}
.ew-test{font-size:13.5px;font-weight:700;color:var(--ink)}
.ew-note{font-size:13px;color:#4A4E57;line-height:1.55}
@media(max-width:640px){.ew-grid{grid-template-columns:1fr;gap:18px}}

/* ---- Programs: measurement grid with a travelling scan band ----
   Two animations on the one layer, which is legal because they drive different
   properties: progScan moves the background, gridCreep scales the whole thing.
   Josh asked for the line grid to be "slowly zooming in".

   gridCreep runs `alternate` rather than looping. A looping zoom has to snap
   back to scale 1 at the end of every cycle, and on a regular grid that snap is
   the only thing anyone sees; hiding it needs a second cross-fading layer, and
   this pseudo-element is already carrying the scan band. Ping-ponging removes
   the seam outright -- there is no reset, only a change of direction, and at
   68s a leg it is far too slow to read as reversing. It just never sits still.
   #programs already clips (overflow:hidden), so the oversized layer at full
   scale never escapes the section. */
#programs{overflow:hidden}
#programs::after{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background-image:
    linear-gradient(180deg,transparent 0%,rgba(58,166,214,.13) 45%,transparent 90%),
    linear-gradient(rgba(58,166,214,.22) 1px,transparent 1px),
    linear-gradient(90deg,rgba(58,166,214,.22) 1px,transparent 1px);
  background-size:100% 46%, 80px 80px, 80px 80px;
  background-repeat:no-repeat, repeat, repeat;
  transform-origin:50% 50%;will-change:transform;
  animation:progScan 9s ease-in-out infinite alternate,
            gridCreep 68s linear infinite alternate}
@keyframes progScan{
  0%{background-position:0 -20%, 0 0, 0 0}
  100%{background-position:0 105%, 0 0, 0 0}}
/* 1.3 is about as far as this goes before the 80px grid reads as a 104px grid
   and stops matching the other measurement grids on the page. */
@keyframes gridCreep{
  from{transform:scale(1)}
  to{transform:scale(1.3)}}
@media(prefers-reduced-motion:reduce){
  #programs::after{animation:none;background-position:0 40%, 0 0, 0 0;transform:none}}

/* ---- Results: before/after readouts as instrument panels ---- */
.xstats{gap:12px}
/* THREE separate .xstat blocks exist in this file — ~886, ~1984 and here. This is the last
   one, so its background and padding are the ones that render; the block at 886 only wins on
   properties this one does not set (which is why the new border-radius applied and the new
   background did not, until this rule was updated too). Change the surface HERE. */
.xstat{position:relative;border:1px solid var(--line-l);
  background:linear-gradient(180deg,#FFFFFF,#FAFAF9);
  padding:12px 16px 14px;overflow:hidden;
  transition:border-color .3s,transform .3s,box-shadow .3s}
.xstat:hover{border-color:rgba(58,166,214,.55);transform:translateY(-2px);
  box-shadow:0 10px 24px -14px rgba(22,23,26,.45)}
.xstat .val{font-variant-numeric:tabular-nums}
.xstat .val .to{display:inline-block;transition:transform .3s}
.xstat:hover .val .to{transform:translateX(3px)}
/* The gain is the whole point of the card, so it gets its own line and real size.
   Was: a 9.5px percent squeezed next to the bar, quieter than the label above it. */
/* Gain and percent hug each other on the left rather than being pushed to opposite edges.
   At phone width the stat card goes full-bleed, and a "1fr auto" split threw them ~250px
   apart, which read as two unrelated numbers instead of one reading. */
.xstat .dlt{display:grid;grid-template-columns:auto auto 1fr;align-items:baseline;
  gap:3px 8px;margin-top:10px}
.xstat .dbar{grid-column:1/-1;position:relative;height:3px;
  background:rgba(22,23,26,.10);overflow:hidden;border-radius:2px}
.xstat .dbar i{position:absolute;inset:0 auto 0 0;width:0;border-radius:2px;
  background:linear-gradient(90deg,var(--sky),var(--green));
  transition:width 1.1s cubic-bezier(.16,1,.3,1);transition-delay:calc(var(--i,0) * 90ms)}
.xstat.stat-in .dbar i{width:calc(var(--p,0) * 1%)}
/* Real-world change: "+12″", "−0.40s". The number people actually feel. */
.xstat .dgain{font-family:var(--display);font-size:17px;line-height:1;letter-spacing:-.01em;
  color:var(--green-deep);font-variant-numeric:tabular-nums;white-space:nowrap}
/* Percent, demoted to support. "18.8% faster" on sprints so a minus never reads as a loss. */
.xstat .dpct{font-family:var(--mono);font-size:11px;font-weight:700;
  letter-spacing:.06em;color:var(--muted);white-space:nowrap;
  font-variant-numeric:tabular-nums}
/* Sprints improve by going DOWN, so they get blue instead of green. This is not decoration:
   the hero sets "Jump Higher." in white and "Run Faster." in sky blue, so blue already means
   speed on this site. Green = jumps, blue = speed, all the way down the page.
   Contrast on white: blue 3.98:1, which clears AA for text this size and weight. */
.xstat .dlt.is-time .dgain{color:var(--accent-deep)}
.xstat .dlt.is-time .dbar i{background:linear-gradient(90deg,var(--green),var(--sky))}
/* A genuine regression would be the one case that should look like one. */
.xstat .dlt.is-down .dgain{color:var(--muted)}
.xstat .dlt.is-down .dbar i{background:rgba(22,23,26,.28)}
/* Stats with no "before" (Damari's IDS score, Ty's 4.44) draw no delta row. Pad them so they
   sit level with their neighbours instead of ending short. */
.xstat.solo{padding-bottom:34px}
.section-d .xstat{background:rgba(255,255,255,.04);border-color:var(--line-d)}
.section-d .xstat .dbar{background:rgba(255,255,255,.12)}
.section-d .xstat .dpct{color:var(--muted-d)}
@media(max-width:640px){
  .xstat .dgain{font-size:15.5px}
  .xstat.solo{padding-bottom:30px}
}

/* ---- Hero: facility video behind the headline ---- */
.hero-video{opacity:.68;object-position:center center}
.hero-scrim{background:linear-gradient(100deg,rgba(22,23,26,.92) 0%,rgba(22,23,26,.86) 34%,rgba(22,23,26,.62) 62%,rgba(22,23,26,.44) 100%)}
@media(max-width:720px){.hero-video{opacity:.55}}

.xform{background:linear-gradient(180deg,#FFFFFF 0%,var(--paper-2) 100%)}
.xform:hover{border-color:rgba(58,166,214,.42)}

/* ---- Results: viewfinder brackets on the athlete photos ---- */
.xphoto .xmedia::before,.xphoto .xmedia::after{content:"";position:absolute;
  width:26px;height:26px;z-index:4;pointer-events:none;opacity:.55;
  transition:opacity .3s,top .3s,left .3s,bottom .3s,right .3s}
.xphoto .xmedia::before{top:12px;left:12px;
  border-top:2px solid rgba(255,255,255,.75);border-left:2px solid rgba(255,255,255,.75)}
.xphoto .xmedia::after{bottom:12px;right:12px;
  border-bottom:2px solid rgba(255,255,255,.75);border-right:2px solid rgba(255,255,255,.75)}
.xform:hover .xmedia::before{top:8px;left:8px;opacity:.9}
.xform:hover .xmedia::after{bottom:8px;right:8px;opacity:.9}

/* ---- Founder: bigger portrait, pull-out credential, timeline ---- */
/* every other section on the page sits at 72/72; 104/108 made this one the odd one out
   and the mismatched top/bottom was just sloppy */
#founder{padding:var(--sec-sm) 0}
.founder-grid{align-items:center;gap:var(--s-6)}
#founder .founder-grid{grid-template-columns:minmax(0,.88fr) minmax(0,1.12fr)}
#founder .founder-photo{max-width:500px;aspect-ratio:4/5;border-radius:var(--r-lg);
  /* the key light has to be a shadow: the frame clips its own children */
  box-shadow:0 40px 90px -40px rgba(0,0,0,.9),
             0 0 0 1px rgba(255,255,255,.07),
             0 30px 90px -34px rgba(58,166,214,.55)}
#founder .founder-photo img{object-fit:cover;object-position:50% 22%}

/* viewfinder brackets, same language as the results photos */
.fbrk{position:absolute;inset:0;z-index:6;pointer-events:none}
.fbrk i{position:absolute;width:30px;height:30px;opacity:.6;
  border-color:rgba(255,255,255,.8);transition:inset .35s,opacity .35s}
.fbrk i:nth-child(1){top:14px;left:14px;border-top:2px solid;border-left:2px solid}
.fbrk i:nth-child(2){top:14px;right:14px;border-top:2px solid;border-right:2px solid}
.fbrk i:nth-child(3){bottom:14px;left:14px;border-bottom:2px solid;border-left:2px solid}
.fbrk i:nth-child(4){bottom:14px;right:14px;border-bottom:2px solid;border-right:2px solid}
.founder-photo:hover .fbrk i{opacity:.95}

/* the single best fact, pulled out of the paragraph */
.fastest{display:inline-flex;flex-direction:column;gap:2px;margin:22px 0 6px;
  padding:13px 20px 14px;border-left:3px solid var(--sky);
  background:linear-gradient(90deg,rgba(58,166,214,.16),transparent)}
.fastest i{font-style:normal;font-family:var(--mono);font-size:11px;font-weight:700;
  letter-spacing:0.14em;text-transform:uppercase;color:var(--sky)}
.fastest b{font-family:var(--display);text-transform:uppercase;font-size:clamp(26px,2.6vw,36px);
  line-height:1;letter-spacing:-.01em;color:#fff}
.fastest span{font-size:11.5px;letter-spacing:.12em;text-transform:uppercase;
  color:var(--muted-d);font-weight:700;margin-top:4px}

/* combine lanes receding behind the whole section */
#founder::before{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background:repeating-linear-gradient(90deg,transparent 0 118px,rgba(255,255,255,.05) 118px 120px);
  -webkit-mask-image:linear-gradient(180deg,transparent,#000 42%,#000 68%,transparent);
  mask-image:linear-gradient(180deg,transparent,#000 42%,#000 68%,transparent)}

@media(max-width:1000px){
  #founder{padding:var(--sec-sm) 0}
  /* the two-column rule above is #id + .class, so the plain .founder-grid
     stack rule cannot beat it — repeat it at the same specificity here */
  #founder .founder-grid{grid-template-columns:1fr}
  #founder .founder-photo{max-width:400px;margin:0 auto}
  .fastest{margin-top:18px}
}

/* ---- Founder timeline: high school -> Northeastern -> draft -> Chiefs -> KPM ---- */
.ftl{list-style:none;margin:56px 0 0;padding:0;position:relative;
  display:grid;grid-template-columns:repeat(5,1fr);gap:0}
/* the rail runs mark-centre to mark-centre, not edge to edge: 35px is half a mark,
   20% is one of the five columns */
.ftl::before{content:"";position:absolute;left:35px;right:calc(20% - 35px);top:34px;height:2px;
  background:linear-gradient(90deg,rgba(255,255,255,.14) 0%,rgba(255,255,255,.22) 55%,var(--sky) 100%)}
.ftl li{position:relative;padding:0 18px 0 0;text-align:left}
.ftl-mark{position:relative;z-index:2;display:grid;place-items:center;
  width:70px;height:70px;border-radius:50%;background:var(--ink);
  border:2px solid rgba(255,255,255,.16);
  transition:border-color .35s,transform .35s cubic-bezier(.16,1,.3,1),background .35s}
/* Held at grayscale so the rail reads as one material and the KPM mark at the
   end is the only lit thing -- but .62 was low enough that Mainland and
   Northeastern were guesswork at a glance. .8 keeps the hierarchy and makes
   the crests actually readable. */
.ftl-mark img{width:40px;height:40px;object-fit:contain;
  filter:grayscale(1) brightness(1.8) contrast(.92);opacity:.8;transition:filter .35s,opacity .35s}
/* the combine badge is a dense lockup with two lines of type, so at 40px it turns
   to mush -- it needs more room and harder contrast than the simple crests */
.ftl-badge img{width:54px;height:54px;
  filter:grayscale(1) brightness(1.35) contrast(1.45)}
.ftl li:hover .ftl-mark{border-color:var(--sky);transform:translateY(-4px);background:var(--ink-2)}
.ftl li:hover .ftl-mark img{filter:none;opacity:1}
.ftl b{display:block;margin-top:20px;font-family:var(--display);text-transform:uppercase;
  font-size:20px;line-height:1.05;letter-spacing:-.01em;color:#fff}
.ftl-sub{display:block;margin-top:7px;font-size:12px;line-height:1.5;
  letter-spacing:.06em;text-transform:uppercase;color:var(--muted-d);font-weight:700}
/* the last stop is the present day, so it stays lit */
.ftl-now .ftl-mark{border-color:var(--sky);background:var(--ink-2);
  box-shadow:0 0 0 5px rgba(58,166,214,.10)}
/* the KPM mark is a wide wordmark, not a round crest: contain in a 40px box
   would render it 16px tall, so give it its own ratio */
.ftl-now .ftl-mark img{filter:none;opacity:1;width:48px;height:30px}
.ftl-now b{color:var(--sky)}

@media(max-width:900px){
  .ftl{grid-template-columns:1fr 1fr;gap:34px 0;margin-top:44px}
  .ftl::before{display:none}
  .ftl-mark{width:58px;height:58px}
  .ftl-mark img{width:32px;height:32px}
  .ftl-badge img{width:44px;height:44px}
  .ftl-now .ftl-mark img{width:38px;height:24px}
  .ftl b{margin-top:14px;font-size:18px}
}
@media(max-width:520px){.ftl{grid-template-columns:1fr;gap:26px}}


/* ===== SECTION NUMBERS 01-08 ===== */
/* .man-eyebrow was a plain block with only a margin-bottom, so turning it into a flex
   row is safe -- nothing else styled it. The number sits to the LEFT of the eyebrow,
   which already carries its own ::before rule. */
.man-eyebrow{display:flex;align-items:center;gap:14px;flex-wrap:wrap}
.sec-no{font-family:var(--mono);font-size:11px;font-weight:700;letter-spacing:.1em;
  line-height:1;padding:5px 8px;border-radius:var(--r-sm);
  color:var(--muted);border:1px solid var(--line-l);
  font-variant-numeric:tabular-nums}
/* dark panels need the light pair or the number nearly disappears */
.data-bg .sec-no,.method .sec-no,.section-d .sec-no{
  color:var(--muted-d);border-color:var(--line-d)}
/* anchor targets have to clear the fixed header when the rail jumps to them */
section[id]{scroll-margin-top:92px}
@media(max-width:640px){
  .sec-no{font-size:11px;padding:4px 6px}
  .man-eyebrow{gap:10px}
}

/* ===== RESULTS SUB-GROUPS ===== */
/* full-bleed row inside the 3-col .xgrid, so the wall of cards reads as three
   deliberate groups instead of one undifferentiated block */
.xgroup{grid-column:1/-1;display:flex;align-items:baseline;gap:16px;flex-wrap:wrap;
  margin-top:var(--s-4);padding-bottom:12px;border-bottom:1px solid var(--line-l)}
.xgroup:first-child{margin-top:0}
.xgroup h3{font-family:var(--mono);font-size:12px;font-weight:700;letter-spacing:0.14em;
  text-transform:uppercase;color:var(--ink);margin:0}
.xgroup span{font-size:14px;color:var(--muted)}
@media(max-width:640px){
  .xgroup{gap:6px;flex-direction:column;align-items:flex-start}
  .xgroup span{font-size:13px}
}

/* ===== 08 PHYSICAL THERAPY (.rx) ===== */
/* The one section on this page that is neither paper nor ink. Green is already the site's
   "recovery" accent, so the section sits on a pale green wash with a hairline chart grid and
   the content in a floating white panel — a treatment chart, not another marketing card.
   Josh asked specifically for the PT to stand out; this is that. */
.rx{position:relative;padding:var(--sec) 0;
  background:linear-gradient(168deg,#EEF5E4 0%,#F6F9F0 46%,#F2F1EE 100%)}
/* Chart grid. 28px squares, green at 7% — visible on the wash, gone by the time it reaches
   the white panel above it. Masked at the edges so it fades rather than hitting a hard stop. */
.rx::before{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background-image:linear-gradient(rgba(110,168,46,.09) 1px,transparent 1px),
                   linear-gradient(90deg,rgba(110,168,46,.09) 1px,transparent 1px);
  background-size:28px 28px;
  -webkit-mask-image:radial-gradient(ellipse 70% 60% at 50% 40%,#000 40%,transparent 100%);
  mask-image:radial-gradient(ellipse 70% 60% at 50% 40%,#000 40%,transparent 100%)}
.rx > *{position:relative;z-index:1}
.rx-head{max-width:660px}
/* --green-deep (#6EA82E) is a fill colour, not a text colour: on this pale green wash it only
   manages 2.58:1, and white on it as a button is 2.88:1. --green-ink is the darkened version
   used wherever green carries text — 4.60:1 on the wash, 5.14:1 behind white. */
.rx .eyebrow{color:var(--green-ink)}

/* Photos left, panel right. 1.05fr/1fr rather than 1fr/1fr: the panel holds three protocol
   rows and a button, and at a true half it ran taller than the photo stack. */
.rx-grid{display:grid;grid-template-columns:1.05fr 1fr;gap:var(--s-5);align-items:start}

.rx-media{display:grid;gap:var(--s-2)}
.rx-shot{margin:0;overflow:hidden;border-radius:var(--r-lg);
  box-shadow:0 22px 48px -30px rgba(22,23,26,.55)}
.rx-shot img{width:100%;display:block;object-fit:cover;
  transition:transform .5s cubic-bezier(.16,1,.3,1)}
.rx-shot:hover img{transform:scale(1.03)}
/* The group shot is the wider frame and carries the partner banner, so it leads and gets the
   taller box. 38% vertical bias keeps heads in — the same crop the old two-up needed. */
.rx-shot-a img{height:300px;object-position:50% 38%}
/* 260/14%, not the original 210/40%. Both sources are 1200x800 (3:2). At 578px wide — the
   desktop column — a 210px box is 2.75:1, so cover scales to width and shows only 54% of the
   frame's height; 40% then pushed that window down past both PTs' heads, leaving two torsos.
   Simulated in PIL: at 260px the window is 65% of the height and 14% puts the faces just under
   the top edge with the partner banner still legible behind them. Mobile and tablet were never
   broken — at 390 the box is 1.78:1 and at 768 it is 1.41:1, which scales to height instead and
   crops sideways. Re-simulate if either photo is ever replaced. */
.rx-shot-b img{height:260px;object-position:50% 14%}

/* Floating white panel — the "chart". Lifted off the wash with a shadow and a green top rule
   so it reads as a separate object rather than a tinted area of the section. */
.rx-panel{background:var(--paper-2);border:1px solid rgba(110,168,46,.22);
  border-radius:var(--r-lg);padding:var(--s-5) var(--s-4) var(--s-4);
  box-shadow:0 26px 60px -34px rgba(22,23,26,.5);position:relative;overflow:hidden}
.rx-panel::before{content:"";position:absolute;top:0;left:0;right:0;height:4px;
  background:linear-gradient(90deg,var(--green),var(--sky))}

.rx-partner{padding-bottom:var(--s-3);margin-bottom:var(--s-3);
  border-bottom:1px solid var(--line-l)}
.rx-partner-lab{font-family:var(--mono);font-size:11px;letter-spacing:0.14em;
  text-transform:uppercase;color:var(--muted);font-weight:700;display:block;margin-bottom:8px}
.rx-partner b{font-size:clamp(20px,2.2vw,26px);text-transform:uppercase;display:block;
  color:var(--ink)}

/* Numbered protocol. The count is the point — assess, treat, return — so the numerals are
   set in mono at panel weight rather than hidden in a bullet. */
.rx-proto{list-style:none;margin:0 0 var(--s-4);padding:0;counter-reset:rx}
.rx-proto li{display:grid;grid-template-columns:auto 1fr;gap:var(--s-2);
  padding:var(--s-2) 0;border-bottom:1px solid var(--line-l)}
.rx-proto li:last-child{border-bottom:none;padding-bottom:0}
.rx-step{font-family:var(--mono);font-size:12px;font-weight:700;letter-spacing:.08em;
  color:var(--green-ink);background:rgba(140,198,63,.14);
  border-radius:var(--r-sm);padding:4px 7px;height:max-content;line-height:1}
.rx-proto b{display:block;font-size:15px;font-weight:800;letter-spacing:.02em;
  text-transform:uppercase;color:var(--ink);margin-bottom:4px}
.rx-proto p{font-size:14.5px;line-height:1.6;color:#4A4E57}

.btn-green{background:var(--green-ink);color:#fff}
.btn-green:hover{background:#3E6812;transform:translateY(-1px)}
.rx-cta{width:100%;justify-content:center;padding:15px 20px}

@media(max-width:960px){
  /* Panel first: the protocol is the substance, the photos are support. */
  .rx-grid{grid-template-columns:1fr;gap:var(--s-4)}
  .rx-media{order:2;grid-template-columns:1fr 1fr}
  .rx-shot-a img,.rx-shot-b img{height:240px}
}
@media(max-width:620px){
  .rx{padding:var(--sec-sm) 0}
  .rx-panel{padding:var(--s-4) var(--s-3) var(--s-3)}
  /* Side by side these land near 140px each and both crops lose their subject. */
  .rx-media{grid-template-columns:1fr}
  .rx-shot-a img{height:220px}
  .rx-shot-b img{height:190px}
  .rx-proto li{grid-template-columns:auto 1fr;gap:var(--s-2)}
}

/* ===== 09 THE KPM APP (.apx) ===== */
/* Dark, so it separates the green PT panel above from the floor section below, and so the
   phone's own black bezel sits in the section instead of on top of it. */
.apx{position:relative;background:var(--ink);color:#fff;padding:var(--sec) 0;overflow:hidden}
.apx-grid{display:grid;grid-template-columns:1fr .92fr;gap:var(--s-6);align-items:center}
.apx .sec-head{margin-bottom:var(--s-4)}
.apx .sec-head h2{color:#fff}
.apx .sec-note{color:rgba(255,255,255,.7)}

.apx-list{list-style:none;margin:0 0 var(--s-4);padding:0;border-top:1px solid var(--line-d)}
.apx-list li{padding:var(--s-2) 0 var(--s-2) 26px;border-bottom:1px solid var(--line-d);
  position:relative}
.apx-list li::before{content:"";position:absolute;left:0;top:26px;width:12px;height:1px;
  background:var(--sky)}
.apx-list b{display:block;font-size:15px;font-weight:800;letter-spacing:.01em;color:#fff}
.apx-list span{display:block;font-size:14px;color:rgba(255,255,255,.62);margin-top:3px}

.apx-actions{display:flex;align-items:center;gap:var(--s-3);flex-wrap:wrap}
.btn-sky{background:var(--sky);color:var(--ink)}
.btn-sky:hover{background:#7FC6E6;transform:translateY(-1px)}
.apx-alt{font-size:14px;font-weight:700;color:rgba(255,255,255,.7);
  border-bottom:1px solid rgba(255,255,255,.25);padding-bottom:2px;transition:color .2s}
.apx-alt:hover{color:#fff}
.apx-alt .arw{display:inline-block;transition:transform .2s}
.apx-alt:hover .arw{transform:translateX(3px)}

/* The PNG is a bezel with its own rounded alpha corners, so the glow has to be a separate
   layer behind it — a box-shadow on the img would trace the rectangle, not the phone. */
.apx-device{position:relative;display:flex;justify-content:center}
.apx-device::before{content:"";position:absolute;top:8%;left:50%;transform:translateX(-50%);
  width:78%;height:70%;border-radius:50%;z-index:0;
  background:radial-gradient(ellipse at center,rgba(99,183,222,.34),transparent 70%);
  filter:blur(38px)}
.apx-device img{position:relative;z-index:1;width:100%;max-width:300px;height:auto}

/* ----- two screenshots instead of one bezel PNG ----- */
/* The old photos/app-phone.png carried its own phone frame in the image. These are raw
   captures out of the app, so the phone edge — radius, hairline, shadow — is drawn here.
   .apx-duo still carries .apx-device, so the blue glow behind it comes for free. */
.apx-duo{align-items:flex-start}
.apx-duo img{max-width:none}
.apx-ph{position:relative;z-index:1;margin:0;width:54%;max-width:224px;
  border-radius:20px;overflow:hidden;border:1px solid rgba(255,255,255,.18);
  box-shadow:0 26px 48px -18px rgba(0,0,0,.78)}
.apx-ph img{display:block;width:100%;height:auto}
/* Overlapped and offset so they read as two screens of one app rather than two pictures.
   B sits on top because the leaderboard is the thing Josh wants noticed. */
.apx-ph-a{transform:translateY(30px);margin-right:-4%}
.apx-ph-b{z-index:2}

@media(max-width:960px){
  .apx-duo img{max-width:none}
  .apx-ph{max-width:196px}
}
@media(max-width:620px){
  .apx-ph{max-width:150px}
  .apx-ph-a{transform:translateY(20px);margin-right:-8%}
}


@media(max-width:960px){
  .apx-grid{grid-template-columns:1fr;gap:var(--s-5)}
  /* Phone above the copy — it is the thing being sold, and on a phone a picture of a phone
     reads instantly. */
  .apx-device{order:-1}
  .apx-device img{max-width:236px}
}
@media(max-width:620px){
  .apx{padding:var(--sec-sm) 0}
  .apx-device img{max-width:210px}
  .apx-actions{gap:var(--s-2)}
  .apx-actions .btn{width:100%;justify-content:center}
}

/* ===== PROGRESS RAIL ===== */
/* Fixed over sections of every colour, so it carries its own dark pill rather than
   trying to invert against whatever is behind it. Built by app.js from the .sec-no
   markers. Hidden under 1200px, where there is no free gutter to sit in. */
.rail{position:fixed;right:20px;top:50%;transform:translateY(-50%);z-index:60;
  display:none;opacity:0;transition:opacity .3s}
.rail.rail-lit{opacity:1}
@media(min-width:1200px){.rail{display:block}}
/* NOT --r-pill: expanded, this box is ~230px wide and a 999px radius carves a bite out of
   the first and last labels. 22px still reads as a capsule at the 43px collapsed width.
   The fill is nearly opaque because the expanded flyout sits over page content. */
.rail ol{list-style:none;margin:0;padding:10px 12px;display:flex;flex-direction:column;gap:2px;
  background:rgba(22,23,26,.93);border:1px solid rgba(255,255,255,.10);
  border-radius:22px;backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);
  box-shadow:0 10px 34px rgba(0,0,0,.28)}
.rail a{display:flex;align-items:center;justify-content:flex-end;gap:10px;
  padding:5px 6px;border-radius:var(--r-pill);text-decoration:none}
.r-dot{order:3;flex:none;width:9px;height:9px;border-radius:50%;
  background:rgba(255,255,255,.26);transition:background .25s,box-shadow .25s,transform .25s}
.r-no{order:1;font-family:var(--mono);font-size:11px;font-weight:700;letter-spacing:.1em;
  color:rgba(255,255,255,.45);font-variant-numeric:tabular-nums}
.r-lab{order:2;font-family:var(--mono);font-size:11px;font-weight:700;letter-spacing:.14em;
  text-transform:uppercase;color:rgba(255,255,255,.8);white-space:nowrap}
/* labels stay collapsed until you reach for the rail */
.r-no,.r-lab{max-width:0;overflow:hidden;opacity:0;
  transition:max-width .3s cubic-bezier(.16,1,.3,1),opacity .25s}
.rail:hover .r-no,.rail:focus-within .r-no{max-width:30px;opacity:1}
.rail:hover .r-lab,.rail:focus-within .r-lab{max-width:220px;opacity:1}
.rail a:hover .r-dot{background:rgba(255,255,255,.6)}
.rail a.on .r-dot{background:var(--sky);box-shadow:0 0 0 4px rgba(58,166,214,.18);transform:scale(1.1)}
.rail a.on .r-lab{color:#fff}
.rail a.on .r-no{color:var(--sky)}
.rail a:focus-visible{outline:2px solid var(--sky);outline-offset:2px}
@media(prefers-reduced-motion:reduce){
  .rail,.rail *{transition:none!important}
}



/* ===== 10 ANTEPES — THE OFFICIAL SHOE (.ant) ===== */
/* Sits between two dark sections (.apx above, .floor below) and both of those are --ink.
   This one is --ink-2 so there is a visible seam instead of one 2,000px black slab.
   Like .floor, .data-bg does NOT paint the background — the rule below has to. */
.ant{background:var(--ink-2);color:#fff;padding:var(--sec) 0;position:relative;overflow:hidden}
/* .data-bg > *:not(.accel-canvas) lifts every direct child to z-index 1, which would put
   the photo on top of the copy. Same specificity, declared later, so this wins. */
.ant .ant-bg{position:absolute;inset:0;z-index:0;pointer-events:none;
  background:
    radial-gradient(118% 88% at 76% 44%,transparent 0%,rgba(31,33,38,.58) 52%,var(--ink-2) 86%),
    linear-gradient(102deg,var(--ink-2) 6%,rgba(31,33,38,.92) 46%,rgba(31,33,38,.70) 100%),
    url(photos/antepes-track.jpg) center/cover no-repeat}
.ant-grid{display:grid;grid-template-columns:1fr .84fr;gap:var(--s-6);align-items:center;
  position:relative;z-index:2}
.ant .sec-head{margin-bottom:var(--s-3)}
.ant .sec-head h2{color:#fff}
.ant .sec-note{font-size:16px;color:rgba(255,255,255,.78);max-width:42ch}
.ant .sec-note b{color:#fff;font-weight:800}
.ant-why{margin:0 0 var(--s-4);max-width:54ch;font-size:15.5px;line-height:1.65;
  color:var(--muted-d)}
.ant-why b{color:rgba(255,255,255,.86);font-weight:700}

.ant-list{list-style:none;margin:0 0 var(--s-4);padding:0;border-top:1px solid var(--line-d)}
.ant-list li{padding:var(--s-2) 0;border-bottom:1px solid var(--line-d);
  padding-left:26px;position:relative}
.ant-list li::before{content:"";position:absolute;left:0;top:25px;width:12px;height:1px;
  background:var(--sky)}
/* The trademarks are Antepes's, so they are set as labels in the mono face rather than
   restyled into KPM's own heading voice. */
.ant-list b{display:block;font-family:var(--mono);font-size:12px;font-weight:700;
  letter-spacing:.12em;text-transform:uppercase;color:var(--sky)}
.ant-list span{display:block;margin-top:5px;font-size:14px;line-height:1.55;
  color:rgba(255,255,255,.62)}

/* The code is the one thing a visitor has to carry off this section, so it gets a box of
   its own instead of a sentence inside the paragraph above. */
.ant-code{display:flex;flex-wrap:wrap;align-items:center;gap:6px var(--s-2);
  margin:0;padding:14px 18px;border-radius:var(--r-md);
  border:1px solid rgba(99,183,222,.42);background:rgba(99,183,222,.08)}
.ant-code-lab{font-family:var(--mono);font-size:11px;font-weight:700;letter-spacing:.14em;
  text-transform:uppercase;color:var(--sky)}
.ant-code b{font-size:15px;font-weight:700;color:#fff}
.ant-chip{display:inline-block;margin:0 3px;padding:3px 10px;border-radius:var(--r-sm);
  background:var(--sky);color:var(--ink);font-family:var(--mono);font-weight:800;
  letter-spacing:.1em}
/* Small on purpose, per Josh — but directly under the code and in plain words. Proximity to
   the offer is the part that carries the disclosure, not the type size. Do not move this
   away from .ant-code or drop it below 12px. */
.ant-disc{margin:9px 0 var(--s-4);font-size:12px;line-height:1.5;color:rgba(255,255,255,.6)}

.ant-actions{display:flex;align-items:center;gap:var(--s-3);flex-wrap:wrap}
.ant-alt{font-family:var(--mono);font-size:12px;font-weight:700;letter-spacing:.08em;
  text-transform:uppercase;color:rgba(255,255,255,.7);
  border-bottom:1px solid rgba(255,255,255,.25);padding-bottom:2px;transition:color .2s}
.ant-alt:hover{color:#fff}
.ant-alt .arw{display:inline-block;transition:transform .2s}
.ant-alt:hover .arw{transform:translateX(3px)}

.ant-media{display:flex;flex-direction:column;align-items:center;gap:var(--s-4)}
.ant-mark{width:100%;max-width:190px;height:auto;opacity:.9}
/* Same problem as .apx-device: the image carries its own alpha silhouette, so a box-shadow
   would trace the bounding rectangle instead of the shoe. The glow is a separate blurred
   layer behind it and the contact shadow is a drop-shadow filter, which follows alpha. */
.ant-shoe{position:relative;display:flex;justify-content:center;width:100%}
.ant-shoe::before{content:"";position:absolute;left:50%;top:50%;
  transform:translate(-50%,-50%);width:92%;height:150%;border-radius:50%;z-index:0;
  background:radial-gradient(ellipse at center,rgba(99,183,222,.34),transparent 70%);
  filter:blur(40px)}
/* 1200x624 native, so 520 is a downscale — it can grow if the layout ever wants it to. */
.ant-shoe img{position:relative;z-index:1;width:100%;max-width:520px;height:auto;
  filter:drop-shadow(0 24px 28px rgba(0,0,0,.55))}

/* ----- Antepes's own figures, fenced off from KPM's ----- */
.ant-foot{position:relative;z-index:2;margin-top:var(--s-6);padding-top:var(--s-4);
  border-top:1px solid var(--line-d)}
.ant-stats-head{font-family:var(--mono);font-size:11px;font-weight:700;letter-spacing:.14em;
  text-transform:uppercase;color:rgba(255,255,255,.55)}
.ant-stats{list-style:none;display:grid;grid-template-columns:repeat(4,minmax(0,1fr));
  gap:var(--s-4);margin:var(--s-3) 0 0;padding:0}
.ant-stats b{display:block;font-family:var(--display);font-size:clamp(28px,3.4vw,40px);
  line-height:1;color:var(--sky);font-variant-numeric:tabular-nums}
.ant-stats b i{font-style:normal;font-size:.5em;margin-left:1px}
.ant-stats span{display:block;margin-top:8px;font-family:var(--mono);font-size:11px;
  font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  color:rgba(255,255,255,.62);line-height:1.5}
.ant-note{margin:var(--s-4) 0 0;max-width:78ch;font-size:13.5px;line-height:1.6;
  color:rgba(255,255,255,.58)}

@media(max-width:960px){
  .ant-grid{grid-template-columns:1fr;gap:var(--s-5)}
  /* Shoe first: it is the subject, and a photo of it reads faster than the headline does. */
  .ant-media{order:-1}
  .ant-shoe img{max-width:420px}
  .ant-stats{grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s-3) var(--s-4)}
}
@media(max-width:620px){
  .ant{padding:var(--sec-sm) 0}
  .ant-mark{max-width:150px}
  .ant-shoe img{max-width:320px}
  .ant-actions{gap:var(--s-2)}
  .ant-actions .btn{width:100%;justify-content:center}
  /* The photo is nearly gone behind the scrim at this width anyway, and on a phone the
     gradient is doing all the work — so simplify to a straight vertical fade. */
  .ant .ant-bg{background:
    radial-gradient(120% 42% at 50% 22%,transparent 0%,rgba(31,33,38,.60) 55%,var(--ink-2) 88%),
    linear-gradient(180deg,rgba(31,33,38,.70) 0%,rgba(31,33,38,.93) 46%,var(--ink-2) 100%),
    url(photos/antepes-track.jpg) center/cover no-repeat}
}






/* ===== ATHLETE EDUCATION (.edu) — method.html, and .edux on programs.html ===== */
/* Light ground on purpose: it follows #session, which is --ink, and the gym photo is dark
   enough that it needs something bright around it to read as a photograph rather than as a
   hole. Body copy is #4A4E57, NOT --muted-d — that token is white and belongs on dark
   sections only. */
.edu-steps{list-style:none;counter-reset:edu;margin:var(--s-5) 0 0;padding:0;
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s-5)}
.edu-steps li{counter-increment:edu;position:relative;padding-top:var(--s-3);
  border-top:2px solid var(--ink)}
.edu-steps li::before{content:counter(edu,decimal-leading-zero);
  font-family:var(--mono);font-size:11px;font-weight:700;letter-spacing:.14em;
  color:var(--accent-deep);display:block;margin-bottom:6px}
.edu-when{display:block;font-family:var(--mono);font-size:11px;font-weight:700;
  letter-spacing:.14em;text-transform:uppercase;color:#5A5F68}
.edu-steps h3{margin:8px 0 10px;font-family:var(--display);text-transform:uppercase;
  font-size:clamp(20px,2.4vw,27px);line-height:1;color:var(--ink)}
.edu-steps p{margin:0;font-size:15.5px;line-height:1.65;color:#4A4E57}
.edu-steps b{color:var(--ink);font-weight:800}

.edu-media{margin-top:var(--s-6);display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  gap:var(--s-4)}
.edu-shot{margin:0}
/* The photo is 4:3 and the video is 16:9. Forcing both into the same box and cropping is
   what keeps the row from looking like two unrelated pictures dropped side by side. */
.edu-shot img,.edu-shot video{display:block;width:100%;height:auto;aspect-ratio:16/10;
  object-fit:cover;border-radius:var(--r-lg);border:1px solid var(--line-l);
  background:var(--ink);box-shadow:var(--sh-2)}
/* height:auto above is load-bearing, not tidiness. The <img> carries width/height attributes
   (correctly — they reserve layout space), and that height wins over aspect-ratio unless it
   is explicitly released. Without it the photo rendered at its full 888px against a 354px
   video and the row looked broken. */
.edu-shot figcaption{margin-top:10px;font-family:var(--mono);font-size:11px;font-weight:700;
  letter-spacing:.1em;text-transform:uppercase;color:#5A5F68}

@media(max-width:820px){
  .edu-steps{grid-template-columns:1fr;gap:var(--s-4)}
  .edu-media{grid-template-columns:1fr;gap:var(--s-3);margin-top:var(--s-5)}
}


/* ----- the compact version, programs.html ----- */
.edux-in{display:grid;grid-template-columns:1fr .95fr;gap:var(--s-6);align-items:center}
.edux-copy h2{margin:0;font-family:var(--display);text-transform:uppercase;color:#fff;
  font-size:clamp(24px,3vw,38px);line-height:1}
.edux-copy p{margin:var(--s-3) 0 var(--s-3);max-width:56ch;font-size:15.5px;line-height:1.65;
  color:var(--muted-d)}
.edux-copy b{color:#fff;font-weight:800}
.edux-shot{margin:0}
.edux-shot img{display:block;width:100%;height:auto;border-radius:var(--r-lg);
  border:1px solid var(--line-d);box-shadow:var(--sh-3)}
@media(max-width:900px){
  .edux-in{grid-template-columns:1fr;gap:var(--s-4)}
  .edux-shot{order:-1}
}

/* ===== SCHOOL YEAR HOURS (.hours) — index.html and programs.html ===== */
/* Heading above the row, buttons below it, and the row itself is ONLY the poster and the two
   cards. That is the whole trick here, and it took two wrong goes to find:
   the poster is 4:5, so every 100px of width costs 125px of height — but widening it also
   narrows the cards, which makes them TALLER. Width can therefore never close a height gap;
   it widens it. First attempt: poster 610 with the cards stacked to make room — right column
   ran 475px past the bottom of the poster and the section hit 1381px. Second: poster 490
   with the heading and buttons still in the right column — still 210px out.
   Pulling the heading and the actions out leaves a column whose height is set by the cards
   alone, and that lands within ~40px of the poster. Do not put anything else back into that
   column without re-measuring BOTH sides. */
.hours{background:var(--paper);padding:var(--sec-sm) 0;position:relative}
.hours-head{margin-bottom:var(--s-4)}
.hours-head h2{margin:0;font-family:var(--display);text-transform:uppercase;color:var(--ink);
  font-size:clamp(28px,3.4vw,44px);line-height:.98}
.hours-head .sec-note{margin:12px 0 0}

.hours-grid{display:grid;grid-template-columns:minmax(0,490px) minmax(0,1fr);
  gap:var(--s-4) var(--s-5);align-items:start}
/* If the poster file is missing the <img> deletes its own figure — without this the cards
   would be left sitting in the 490px column meant for the picture. */
.hours-grid.hours-noposter{grid-template-columns:1fr}
.hours-poster{margin:0;border-radius:var(--r-lg);overflow:hidden;
  border:1px solid var(--line-l);background:var(--paper-2);
  box-shadow:0 2px 5px rgba(22,23,26,.07),
             0 16px 30px -12px rgba(22,23,26,.26),
             0 44px 80px -34px rgba(22,23,26,.5)}
.hours-poster img{display:block;width:100%;height:auto}
/* .sched is centred and capped at 820 on the questions page; in this column it fills. */
.hours .sched{max-width:none;margin:0}

.hours-actions{display:flex;align-items:center;gap:var(--s-3) var(--s-4);flex-wrap:wrap;
  margin-top:var(--s-4)}

@media(max-width:1080px){
  .hours-grid{grid-template-columns:1fr}
  /* Cards first: they are the accessible, skimmable version. A 4:5 image at the top of a
     phone screen buries everything under it. */
  .hours-poster{order:2;max-width:520px;margin:0 auto}
}
@media(max-width:620px){
  .hours-actions .btn{width:100%;justify-content:center}
}

/* ===== THE SCHEDULE (.sched) — top of faq.html and of index.html#questions ===== */
/* Josh: the most-asked question of the lot, so it is a block a parent can read at a glance
   rather than an accordion they have to open. Two cards, because there are exactly two
   answers: under 11, and 11 and up. */
.sched{max-width:820px;margin:0 auto var(--s-6);display:grid;
  grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s-3)}
.sched-card{background:var(--paper-2);border:1px solid var(--line-l);border-radius:var(--r-lg);
  padding:var(--s-4) var(--s-3);box-shadow:var(--sh-1);scroll-margin-top:96px}
.sched-age{display:inline-block;font-family:var(--mono);font-size:11px;font-weight:700;
  letter-spacing:.14em;text-transform:uppercase;color:var(--accent-deep)}
.sched-card h3{margin:10px 0 0;font-family:var(--display);text-transform:uppercase;
  font-size:clamp(20px,2.3vw,26px);line-height:1;color:var(--ink)}
.sched-req{margin:8px 0 var(--s-3);font-size:14px;line-height:1.5;color:#4A4E57}
.sched-req b{color:var(--ink);font-weight:800}

.sched-days{list-style:none;margin:0;padding:0;border-top:1px solid var(--line-l)}
.sched-days li{padding:12px 0;border-bottom:1px solid var(--line-l)}
.sched-days b{display:block;font-size:14.5px;font-weight:800;color:var(--ink)}
.sched-days span{display:block;margin-top:3px;font-family:var(--mono);font-size:11.5px;
  font-weight:700;letter-spacing:.03em;text-transform:uppercase;color:#5A5F68}
/* "optional" has to survive a skim — a parent who reads the Saturday session as required
   and cannot make it will rule the whole programme out on the spot. */
.sched-days b i{display:inline-block;margin-left:8px;padding:2px 8px;border-radius:var(--r-pill);
  background:rgba(25,114,155,.1);color:var(--accent-deep);font-style:normal;
  font-family:var(--mono);font-size:9.5px;font-weight:700;letter-spacing:.12em;
  text-transform:uppercase;vertical-align:2px}
.sched-tracks b{font-family:var(--mono);font-size:11px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--accent-deep)}
.sched-tracks span{font-family:var(--body);font-size:14.5px;font-weight:700;
  letter-spacing:0;text-transform:none;color:var(--ink)}

.sched-slot{margin-top:var(--s-3);padding:14px 16px;border-radius:var(--r-md);
  background:var(--paper);border:1px solid var(--line-l)}
.sched-slot-lab{display:block;font-family:var(--mono);font-size:10.5px;font-weight:700;
  letter-spacing:.14em;text-transform:uppercase;color:#5A5F68}
.sched-slot b{display:block;margin-top:6px;font-family:var(--display);font-size:19px;
  line-height:1.1;color:var(--ink)}
.sched-slot p{margin:8px 0 0;font-size:13px;line-height:1.5;color:#4A4E57}

@media(max-width:760px){
  .sched{grid-template-columns:1fr;gap:var(--s-2);margin-bottom:var(--s-5)}
}

/* ===== FAQ: topic nav, groups, and the home-page tail ===== */
/* The questions page went from 7 accordions to 33. Seven can be a single list; thirty-three
   cannot — so they are grouped, and the nav below lets someone land on the one topic they
   came for instead of scrolling past six they did not. */
.faq-jump{display:flex;flex-wrap:wrap;gap:8px;justify-content:center;
  max-width:820px;margin:0 auto var(--s-6)}
.faq-jump a{font-family:var(--mono);font-size:11px;font-weight:700;letter-spacing:.1em;
  text-transform:uppercase;color:var(--accent-deep);padding:9px 16px;
  border:1px solid var(--line-l);border-radius:var(--r-pill);
  transition:background .2s,color .2s,border-color .2s}
.faq-jump a:hover,.faq-jump a:focus-visible{background:var(--accent-deep);color:#fff;
  border-color:var(--accent-deep)}
/* The header is fixed, so an anchor landing flush with the viewport top puts the group
   heading underneath it. */
.faq-set{max-width:820px;margin:0 auto;scroll-margin-top:96px}
.faq-set+.faq-set{margin-top:var(--s-6)}
.faq-group{margin:0 0 var(--s-2);font-family:var(--display);text-transform:uppercase;
  font-size:clamp(19px,2.2vw,25px);line-height:1;color:var(--ink)}

/* Home page only: the six-question tail, and the way out to the full set. */
.faq-more{max-width:820px;margin:var(--s-5) auto 0;display:flex;align-items:center;
  gap:var(--s-3) var(--s-4);flex-wrap:wrap}
#questions .sec-head{max-width:820px;margin:0 auto var(--s-4)}
@media(max-width:620px){
  .faq-more{gap:var(--s-3)}
  .faq-more .btn{width:100%;justify-content:center}
  .faq-jump{gap:6px;margin-bottom:var(--s-5)}
  .faq-jump a{font-size:10px;padding:8px 12px}
}

/* ===== ANTEPES, COMPACT (.antx) — method.html, programs.html ===== */
/* The short version of #gear. It shares .ant-code, .ant-chip, .ant-disc, .ant-alt and the
   two images with the home page; only the layout is its own. The shoe sits on the LEFT so
   the two are not the same block twice, which is also why the photo's glow is centred at
   24% here instead of 76%. */
.antx{position:relative;overflow:hidden;background:var(--ink-2);color:#fff;
  padding:var(--sec-sm) 0}
.antx .ant-bg{position:absolute;inset:0;z-index:0;pointer-events:none;
  background:
    radial-gradient(112% 88% at 24% 46%,transparent 0%,rgba(31,33,38,.58) 52%,var(--ink-2) 86%),
    linear-gradient(258deg,var(--ink-2) 6%,rgba(31,33,38,.92) 46%,rgba(31,33,38,.70) 100%),
    url(photos/antepes-track.jpg) center/cover no-repeat}
.antx-in{position:relative;z-index:2;display:grid;grid-template-columns:.85fr 1fr;
  gap:var(--s-6);align-items:center}

.antx-media{display:flex;flex-direction:column;align-items:center;gap:var(--s-1)}
.antx-shoe{position:relative;display:flex;justify-content:center;width:100%}
.antx-shoe::before{content:"";position:absolute;left:50%;top:50%;
  transform:translate(-50%,-50%);width:92%;height:150%;border-radius:50%;z-index:0;
  background:radial-gradient(ellipse at center,rgba(99,183,222,.32),transparent 70%);
  filter:blur(38px)}
.antx-shoe img{position:relative;z-index:1;width:100%;max-width:440px;height:auto;
  filter:drop-shadow(0 22px 26px rgba(0,0,0,.55))}
.antx-mark{width:100%;max-width:132px;height:auto;opacity:.85}

/* Not a .data-bg section, so the sky eyebrow and the white heading have to be set here. */
.antx .eyebrow{color:var(--sky)}
.antx h2{margin:0;font-family:var(--display);text-transform:uppercase;color:#fff;
  font-size:clamp(26px,3.1vw,40px);line-height:.98}
.antx-copy>p{margin:var(--s-3) 0 var(--s-4);max-width:54ch;font-size:15.5px;line-height:1.65;
  color:var(--muted-d)}
.antx-copy>p b{color:#fff;font-weight:800}
.antx-actions{display:flex;align-items:center;gap:var(--s-3);flex-wrap:wrap}

@media(max-width:960px){
  /* .antx-media is already first in the markup, so this stacks shoe-then-copy with no
     order juggling — the opposite of .ant, where the copy comes first. */
  .antx-in{grid-template-columns:1fr;gap:var(--s-4)}
  .antx-shoe img{max-width:400px}
}
@media(max-width:620px){
  .antx-shoe img{max-width:300px}
  .antx-mark{max-width:118px}
  .antx-actions{gap:var(--s-2)}
  .antx-actions .btn{width:100%;justify-content:center}
  .antx .ant-bg{background:
    radial-gradient(120% 40% at 50% 20%,transparent 0%,rgba(31,33,38,.60) 55%,var(--ink-2) 88%),
    linear-gradient(180deg,rgba(31,33,38,.70) 0%,rgba(31,33,38,.93) 46%,var(--ink-2) 100%),
    url(photos/antepes-track.jpg) center/cover no-repeat}
}

/* ===== THE FLOOR (#floor) ===== */
/* Mirrors the founder two-column, but the photo sits on the LEFT so it does not stack two
   identical photo-left/text-right bands next to each other down the page. */
/* .data-bg only sets up positioning + the grid overlay — it does NOT paint a dark
   background. That comes from the section's own rule, the way .founder does it. Without
   this, the --muted-d text and --line-d borders below land on white and vanish. */
.floor{background:var(--ink);color:#fff;padding:var(--sec-sm) 0;
  position:relative;overflow:hidden}
.floor-grid{display:grid;grid-template-columns:minmax(0,.86fr) minmax(0,1.14fr);
  gap:var(--s-6);align-items:center;position:relative;z-index:2}
/* The 400px cap lives on the WRAPPER, not the frame, so the caption wraps to exactly the
   width of the photo above it instead of running the full width of the grid cell. */
.floor-media{max-width:400px;width:100%}
/* .fbrk is position:absolute;inset:0 — it needs a positioned parent or the brackets escape */
.floor-photo{position:relative;aspect-ratio:4/5;width:100%;
  border-radius:var(--r-lg);overflow:hidden;
  background:linear-gradient(155deg,#2E3138,#15171B);
  box-shadow:0 0 0 1px rgba(255,255,255,.06),0 26px 60px rgba(0,0,0,.42)}
.floor-photo img{width:100%;height:100%;object-fit:cover;display:block}
/* the bracket hover rule is scoped to .founder-photo, so repeat it for this parent */
.floor-photo:hover .fbrk i{opacity:.95}

/* Names the three people in the photo. Muted body at 6.2:1 on --ink, names pushed to
   solid #fff so the eye lands on them first. */
.floor-cap{margin-top:var(--s-3);font-size:13px;line-height:1.5;color:var(--muted-d)}
.floor-cap b{color:#fff;font-weight:700}

.floor-txt h2{font-family:var(--display);text-transform:uppercase;
  font-size:clamp(34px,4.4vw,64px);line-height:1.02;margin-top:var(--s-2)}
.floor-txt .story{margin-top:var(--s-3);max-width:46ch;color:var(--muted-d);font-size:16px}

.floor-specs{list-style:none;display:flex;flex-wrap:wrap;gap:var(--s-5);
  margin:var(--s-4) 0 var(--s-4);padding:var(--s-3) 0 0;border-top:1px solid var(--line-d)}
.floor-specs b{display:block;font-family:var(--display);font-size:40px;line-height:1;
  color:var(--sky);font-variant-numeric:tabular-nums}
.floor-specs span{display:block;margin-top:8px;font-family:var(--mono);font-size:11px;
  letter-spacing:0.14em;text-transform:uppercase;color:var(--muted-d)}

@media(max-width:1000px){
  /* single-class selectors here, so no specificity fight — unlike #founder .founder-grid */
  .floor-grid{grid-template-columns:1fr;gap:var(--s-4)}
  /* centre the WRAPPER — centring .floor-photo alone would leave the caption off to the side */
  .floor-media{max-width:340px;margin:0 auto}
  .floor-specs{gap:var(--s-4)}
}
@media(max-width:520px){
  .floor-specs{gap:var(--s-3)}
  .floor-specs b{font-size:32px}
}

/* ===== RESULTS: THE HEADLINE CASE, IN BLACK ===== */

/* BUG, not taste: `.badge-tag` had NO styling anywhere in this file. All eight of them
   ("Ohio State", "Alabama Rowing", "Kentucky", "Our Own Coach") rendered as plain 16px
   body text in the same ink as the paragraph under them — measured fw:400, ls:normal,
   text-transform:none, no background, no border, no margin. The destination is the whole
   payoff of a before/after card and it was the quietest thing on it.
   The styling it was clearly meant to get is sitting at line ~313 as `.xform .badge`,
   which matches ZERO elements — the markup was renamed to badge-tag and the selector was
   never updated. `.dest` (line ~316) is dead the same way, 0 uses site-wide.
   Rather than just re-point the old rule, these get real presence: a bordered chip, because
   a school name is a credential and should look stamped on rather than typed in.
   COLOUR — SETTLED, Josh Aug 17, do not quietly change it back. I first shipped these with
   ink text and the green on the border/fill only, because --green-deep is 2.88:1 at 10.5px
   on white. I showed him the trade and he asked for the green text. So the text is green.
   One thing I did adjust: on the WHITE cards the fill is now `transparent`, an outline chip.
   Any green tint behind green text darkens the backdrop and drops the ratio below the site's
   existing green-on-white — measured 2.76:1 at .06 alpha and worse at .13, which would have
   made these the single worst contrast on the page. At transparent they land on exactly
   2.88:1, identical to the .ht-eyebrows and the .aft values that are already everywhere.
   So: green text costs nothing here, as long as nothing sits behind it. The border carries
   the chip shape, and the tint only appears on hover.
   The BLACK cards keep their fill — light green on ink is 7.05:1, miles clear either way. */
/* `align-self` is doing real work, do not drop it. The six photo cards style .xbody as
   `display:flex;flex-direction:column`, which BLOCKIFIES its children — `display:inline-block`
   is silently computed to `block` and the chip stretches the full column. Measured: 524px
   wide in a 576px card, a full-width green band instead of a chip. The two feature cards
   looked right the whole time because .fbody is `display:block`, so the bug only showed on
   six of the eight. align-self:flex-start makes it shrink-wrap, and is simply ignored in the
   non-flex case, so one declaration covers both. */
.xform .badge-tag{display:inline-block;align-self:flex-start;margin-bottom:14px;
  font-family:var(--body);font-size:11px;font-weight:700;letter-spacing:0.14em;
  text-transform:uppercase;line-height:1;color:var(--green-deep);
  padding:7px 11px;border:1px solid rgba(110,168,46,.62);border-radius:var(--r-sm);
  background:transparent;
  transition:border-color .3s,background .3s}
.xform:hover .badge-tag{border-color:rgba(110,168,46,.9);background:rgba(140,198,63,.08)}

/* THE BLACK CARD. Josh asked for the section to "pop more"; the headline is literally
   "Before & after. In black & white." and nothing on the section was black.
   Deliberately ONLY this one card, not the section. Two reasons, both measured:
   1. #results is 2998px tall — 4x the next-biggest section (#more, 791px). A black field
      that size stops being an accent and becomes a second page.
   2. It already sits between two dark sections (.ctastrip above, .lifestrip below), so a
      black #results would fuse all three into one long dark run and kill the rhythm.
   One black card does the job the headline promises: the headline case is the black, the
   six commits are the white. The left half of this card was ALREADY a dark gradient
   (.fmedia), so this doesn't introduce a new colour — it finishes a card that was
   previously half-dark/half-white and read as two glued-together pieces. */
.xform.feature{background:var(--ink);border-color:rgba(255,255,255,.13);color:#fff;
  box-shadow:0 30px 70px -34px rgba(22,23,26,.6)}
.xform.feature:hover{border-color:rgba(99,183,222,.42);
  box-shadow:0 38px 84px -32px rgba(22,23,26,.72)}
/* The media half loses its own border-radius seam and blends into the card body. */
.xform.feature .fmedia{background:linear-gradient(150deg,#23262C,#101114)}

/* On ink, the light-background palette inverts. These are the documented pairs:
   --sky #63B7DE is 7.99:1 on --ink (the base --accent-deep only manages 4.5), and
   --green #8CC63F is 8.44:1 where --green-deep is 4.66. Small text must use the light pair. */
.xform.feature h3{color:#fff}
.xform.feature .note{color:var(--muted-d)}
.xform.feature .note b{color:#fff}
.xform.feature .badge-tag{color:var(--green);border-color:rgba(140,198,63,.42);
  background:rgba(140,198,63,.12)}
.xform.feature:hover .badge-tag{border-color:rgba(140,198,63,.7);
  background:rgba(140,198,63,.2)}

/* Stat cards on ink. Same values the existing .section-d overrides use, so the dark
   treatment stays consistent with the rest of the site rather than being a one-off. */
.xform.feature .xstat{background:rgba(255,255,255,.04);border-color:var(--line-d)}
.xform.feature .xstat:hover{border-color:rgba(99,183,222,.6);
  background:rgba(255,255,255,.07);box-shadow:0 12px 26px -14px rgba(0,0,0,.7)}
.xform.feature .xstat .lab{color:var(--muted-d)}
.xform.feature .xstat .val{color:#fff}
.xform.feature .xstat .val .to{color:rgba(255,255,255,.4)}
.xform.feature .xstat .val .aft{color:var(--green)}
.xform.feature .xstat .dbar{background:rgba(255,255,255,.12)}
.xform.feature .xstat .dgain{color:var(--green)}
.xform.feature .xstat .dpct{color:var(--muted-d)}
/* Green = jumps, blue = speed still holds; just the light end of each pair. */
.xform.feature .xstat .dlt.is-time .dgain{color:var(--sky)}
.xform.feature .xstat .dlt.is-down .dgain{color:var(--muted-d)}
.xform.feature .xstat .dlt.is-down .dbar i{background:rgba(255,255,255,.3)}

/* STACKED FEATURE CARD — padding-left was 0 and the text sat 1px off the card edge.
   `.fbody` is `padding:40px 44px 40px 0` on purpose: side by side, the grid's 44px gap is
   the text's left margin, so its own left padding would double it. Once the card stacks to
   one column that gap disappears and the text runs into the edge.
   Someone already fixed this at the 1000px and 640px breakpoints (lines ~340 and ~437) —
   but a later UNCONDITIONAL rule in the "xform cards tighter" pass (line ~1228) re-set
   `padding:28px 30px 28px 0`, which outranks both by source order at every width and quietly
   undid them. Measured on a 375px viewport before this rule: text left edge 21px vs card
   left edge 20px.
   It was survivable while the card was white on a white page. On black it is a hard edge
   against the headline, so it has to be right. Restated here at the end of the file so it
   wins, and left as two breakpoints to match the padding scale already in use. */
@media(max-width:1000px){
  .xform.feature .fbody{padding:32px 28px}
}
@media(max-width:640px){
  .xform.feature .fbody{padding:26px 22px}
}


/* ============================================================================
   HERO: FEATHER THE VIDEO'S SIDE EDGES INTO BLACK
   ----------------------------------------------------------------------------
   The video is `inset:0; object-fit:cover`, so it runs edge to edge and stops
   dead at the left and right of the viewport. On a wide monitor that hard
   vertical cut is the giveaway that it's a video pasted behind the type rather
   than light in a room.

   Done with `mask-image` rather than an overlay gradient on purpose. An overlay
   would lay a translucent black sheet ON TOP of the video, which mutes the whole
   edge including its highlights and never quite reaches the same black as the
   section behind it. A mask fades the video's own alpha out instead, so the edge
   dissolves into `.hero{background:var(--ink)}` — the exact same black the nav
   and the statrail sit on. There is nothing left to mismatch.

   The stops are not a straight ramp. A two-stop linear mask puts the whole fade
   at a constant rate, and the eye picks out both ends of it as faint vertical
   lines. These stops ease in and out (slow, fast, slow), which reads as falloff.

   `-webkit-mask-image` is listed first and separately: Safari still needs the
   prefix here, and it must not be folded into a shorthand.
   ============================================================================ */
.hero-video{
  -webkit-mask-image:linear-gradient(90deg,
    rgba(0,0,0,0) 0%, rgba(0,0,0,.10) 3%, rgba(0,0,0,.40) 7.5%,
    rgba(0,0,0,.76) 12.5%, rgba(0,0,0,.95) 16%, #000 20%,
    #000 80%, rgba(0,0,0,.95) 84%, rgba(0,0,0,.76) 87.5%,
    rgba(0,0,0,.40) 92.5%, rgba(0,0,0,.10) 97%, rgba(0,0,0,0) 100%);
  mask-image:linear-gradient(90deg,
    rgba(0,0,0,0) 0%, rgba(0,0,0,.10) 3%, rgba(0,0,0,.40) 7.5%,
    rgba(0,0,0,.76) 12.5%, rgba(0,0,0,.95) 16%, #000 20%,
    #000 80%, rgba(0,0,0,.95) 84%, rgba(0,0,0,.76) 87.5%,
    rgba(0,0,0,.40) 92.5%, rgba(0,0,0,.10) 97%, rgba(0,0,0,0) 100%);
}

/* On a phone the feather has to shrink, and not by a little. The stops are
   percentages, so 20% of a 1440px monitor is a 288px falloff — cinematic — but
   20% of a 375px phone is 75px a side, which eats 40% of the frame and leaves a
   letterboxed sliver. Pulled in to 8% so the fade still softens the edge without
   swallowing the shot. */
@media(max-width:720px){
  .hero-video{
    -webkit-mask-image:linear-gradient(90deg,
      rgba(0,0,0,0) 0%, rgba(0,0,0,.45) 3%, rgba(0,0,0,.85) 5.5%, #000 8%,
      #000 92%, rgba(0,0,0,.85) 94.5%, rgba(0,0,0,.45) 97%, rgba(0,0,0,0) 100%);
    mask-image:linear-gradient(90deg,
      rgba(0,0,0,0) 0%, rgba(0,0,0,.45) 3%, rgba(0,0,0,.85) 5.5%, #000 8%,
      #000 92%, rgba(0,0,0,.85) 94.5%, rgba(0,0,0,.45) 97%, rgba(0,0,0,0) 100%);
  }
}


/* ============================================================================
   HOMETOWN HEROES: THE CARDS ARE LINKS NOW
   ----------------------------------------------------------------------------
   Seven of the eight cards became <a> elements pointing at the athlete's
   official roster page (Elaina Styer is still a <div> — see index.html).

   This is as much a bug fix as a feature. `.hh` already had `:hover` lift, a
   shadow, and the sky-to-green bar wiping across the top — the full vocabulary
   this site uses for "clickable" — while also carrying `cursor:default`. It
   promised a click and had nowhere to send you. Now it does.

   `color:inherit` and `text-decoration:none` are required, not cosmetic: the
   card holds three different text colours (muted name, accent accolade, white
   town chip) and the UA stylesheet would flatten all of them to link blue and
   underline the lot.
   ============================================================================ */
a.hh{color:inherit;text-decoration:none;cursor:pointer}

/* `.hh` sets cursor:default at its own specificity (0,1,0) and appears earlier
   in the file, so `a.hh` (0,1,1) wins on both counts. Stated anyway, above, so
   the intent survives someone reordering this file. */

/* The out-arrow. Sits in the top-right of the photo, hidden until hover, so the
   resting card stays as clean as it was before the links went in. Scoped to
   a.hh so Styer's card never grows one. */
a.hh .hh-photo::before{content:"\2197";position:absolute;top:10px;right:10px;z-index:6;
  width:26px;height:26px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;
  font-family:var(--body);font-size:14px;font-weight:700;line-height:1;
  color:#fff;background:rgba(22,23,26,.66);border:1px solid rgba(255,255,255,.24);
  -webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);
  opacity:0;transform:translateY(-3px) scale(.9);
  transition:opacity .28s,transform .28s cubic-bezier(.16,1,.3,1)}
a.hh:hover .hh-photo::before,
a.hh:focus-visible .hh-photo::before{opacity:1;transform:none}

/* Keyboard users get the same lift the mouse gets, plus a real focus ring.
   The ring goes on the card rather than inset on the photo because the card is
   what receives focus. */
a.hh:focus-visible{outline:2px solid var(--sky);outline-offset:3px;
  transform:translateY(-7px);box-shadow:0 26px 54px -26px rgba(22,23,26,.55)}

/* Styer's card is the odd one out: still a <div>, so it must NOT pretend to be
   clickable. Killing the lift and the top-bar wipe is the whole point — a card
   that rises under the cursor and then does nothing is worse than a flat one. */
div.hh{cursor:default}
div.hh:hover{transform:none;box-shadow:none;border-color:var(--line-l)}
div.hh:hover::before{transform:scaleX(0)}

@media(prefers-reduced-motion:reduce){
  a.hh:focus-visible{transform:none}
  a.hh .hh-photo::before{transition:none}
}


/* ============================================================================
   "DOCTORS. PROS. FAMILIES." (#recognition) — LIGHT IN THE ROOM
   ----------------------------------------------------------------------------
   This section was a flat --ink rectangle. The signature .accel-canvas motif is
   there, but at opacity .5 over pure black it reads as nothing, and the content
   only fills the middle of the band — the left gutter, the right gutter and the
   whole area under the two review cards were dead space.

   Three layers now, cheapest first:

   1. `.pros::before` — a photograph, but not one you are meant to look at.
      photos/pros-wash.jpg is 44x30 pixels and 975 bytes: a frame of the KPM gym
      squeezed down until only the large shapes of light and shadow survive.
      Scaled back up by `background-size:cover`, the browser's own bilinear
      interpolation does the blurring. That matters — the obvious way to write
      this is a full-size photo under `filter:blur(60px)`, which forces the
      compositor to blur a 1600px image across the full width of the section on
      every scroll frame. This costs one 975-byte request and nothing else.

   2. `.pros::after` — two pools of coloured light, sky from the upper left and
      green from the lower right, the same two brand colours the .hh cards wipe
      between. Very low alpha; they are there to keep the black from going dead,
      not to be seen as colour.

   3. The existing .data-bg::after ascension gradient stays on top of both.

   Deliberately NOT applied to .data-bg generally. That class is also on
   #pros, #method and #founder, and putting a photo wash behind all four would
   turn a signature into wallpaper.
   ============================================================================ */
.pros{position:relative;overflow:hidden}

.pros::before{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background-image:url("photos/pros-wash.jpg");
  background-size:cover;background-position:50% 42%;
  opacity:.30;
  filter:saturate(.55) contrast(1.08);
  /* Held away from all four edges so the section still meets .split above it and
     #pros below it in clean --ink, with no seam where the wash stops. */
  -webkit-mask-image:radial-gradient(ellipse 78% 66% at 52% 46%,#000 12%,rgba(0,0,0,.55) 52%,transparent 82%);
  mask-image:radial-gradient(ellipse 78% 66% at 52% 46%,#000 12%,rgba(0,0,0,.55) 52%,transparent 82%)}

/* Layer order in a CSS `background` list is FIRST = TOPMOST, so the two guards
   below sit over the two light pools, and all four sit over the wash.

   The guards are the important part and they are not decorative. The heading row
   ("02 / WHAT THEY SAY / Doctors. Pros. Families." plus the All Testimonials
   link) is the only text in this section that sits directly on the section
   background rather than on a card — and the eyebrow and the link are both
   --sky, which is a mid-tone. --sky on plain --ink is fine; --sky on the bright
   part of the wash measured 2.25:1, which is not. The top guard pins the first
   fifth of the section back to essentially pure --ink so that row keeps the
   contrast it has everywhere else on the site. The bottom guard does the same
   favour for the seam against #pros below. */
.pros::after{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background:
    linear-gradient(180deg,var(--ink) 0%,rgba(22,23,26,.92) 7%,rgba(22,23,26,.45) 15%,transparent 24%),
    linear-gradient(0deg,var(--ink) 0%,rgba(22,23,26,.6) 5%,transparent 13%),
    radial-gradient(ellipse 52% 46% at 12% 6%,rgba(99,183,222,.14),transparent 68%),
    radial-gradient(ellipse 60% 52% at 92% 96%,rgba(140,198,63,.10),transparent 66%)}

/* .data-bg already promotes direct children above its own ::after, but .pros now
   has two pseudo-elements of its own at z-index 0, and .accel-canvas is a real
   child sitting at z-index 0 too. Lift the canvas clear of the wash so the motif
   still reads, and keep everything else above all of it. */
.pros > .accel-canvas{z-index:1;opacity:.62}
.pros > *:not(.accel-canvas){position:relative;z-index:2}

/* The three .pro-card testimonials already paint `background:var(--ink-2)`, so
   they are opaque and the wash cannot reach their text. The two .voice review
   cards are the exception: they were drawn as border-only, which worked over
   flat --ink and does not work over a photograph. Their quote text is
   rgba(255,255,255,.82) and it would be compositing straight onto whatever the
   wash happens to be doing behind it.

   .72 rather than 1: enough of the wash still shows through the card to keep it
   part of the scene, while the text always has a known dark floor beneath it.
   The hover has to be restated because `.voice:hover` sets `background` outright
   — left alone it would drop this backing at exactly the moment someone is
   reading the card. */
.pros .voice{background:rgba(22,23,26,.72)}
.pros .voice:hover{background:rgba(42,46,53,.82)}

/* .voices is a grandchild, not a child, so the `.pros > *` rule above does not
   reach it. It inherits a stacking context from .wrap and would be fine either
   way, but it is stated so that the two review cards can never end up sharing a
   layer with the wash if .wrap's own positioning is ever changed. */
.pros .voices{position:relative;z-index:2}


/* ==========================================================================
   THE FOUNDER (#founder) — CUT-OUT PORTRAIT, NOT A FRAMED PHOTO
   ==========================================================================
   Before: a 4:5 rounded box holding david-klemic-stage.jpg (David on a stage
   with a microphone). It was tidy and completely inert — the same card shape
   the Hometown Heroes and Results cards already use, so the founder read as
   one more tile on a page full of tiles.

   After: photos/david-klemic.png, a transparent-background cut-out that was
   sitting unused in the folder (1100x1100, ~410k opaque pixels). He now stands
   IN the section instead of inside a box — no frame, no border radius, no card.
   That is the whole idea: the one person on this page who is not a tile.

   Everything below exists to make a PNG with no background look deliberate
   rather than like a broken image:
     .fdr-glow          the key light behind him, so he is lit from somewhere
     .founder-photo::before  the floor pool, so he is standing on something
     mask-image on img  dissolves his torso into the section instead of
                        ending it on the hard 1100px edge of the source file
     .fdr-word          an oversized watermark filling the dead space the old
                        layout left to the right of the paragraph

   Scoped to `#founder.fdr-cut` throughout. The plain `.founder-photo` rules
   further up this file are still used by `.floor-photo` and by the coaches
   page, so they are overridden here, never edited there. */

/* The frame is gone. aspect-ratio stays so the column still reserves height
   before the PNG decodes — without it the text column jumps on load. */
#founder.fdr-cut .founder-photo{
  background:none;
  border-radius:0;
  overflow:visible;
  box-shadow:none;
  max-width:500px}

/* .founder-photo::after (line ~1354) is a bottom scrim for the badge. Over a
   photo that fills its box it is invisible; over a cut-out it paints a grey
   rectangle in mid-air around his legs. The badge gets its own backing below. */
#founder.fdr-cut .founder-photo::after{display:none}
/* .photo-slot carries a 1px rgba(255,255,255,.1) hairline everywhere on the
   site — the frame edge for every photo card. On a cut-out it is the one thing
   that keeps redrawing the box, and it is easy to miss because at .1 alpha on
   --ink it looks like a rendering artefact rather than a border. */
#founder.fdr-cut .founder-photo>.photo-slot{background:none;overflow:visible;border:0}

/* object-fit:cover, not contain. The figure only occupies the middle ~56% of
   the source square (alpha bbox x=242..858 of 1100), so contain would render
   him small with transparent margins either side. cover crops those empty
   margins and he fills the column. */
#founder.fdr-cut .founder-photo img{
  object-fit:cover;
  object-position:50% 45%;
  filter:drop-shadow(0 0 2px rgba(99,183,222,.6)) drop-shadow(0 34px 44px rgba(0,0,0,.7)) contrast(1.05);
  /* Two jobs. It dissolves the bottom edge so he emerges from the dark rather
     than being guillotined at the source file's border, and it takes out the
     one artefact in the cut-out — a stray dark shape (someone else's head) in
     the bottom ~6% that the original masking pass left behind.
     Masks multiply with existing alpha, so the PNG's own transparency survives. */
  -webkit-mask-image:linear-gradient(180deg,#000 80%,rgba(0,0,0,.72) 91%,rgba(0,0,0,.18) 97%,transparent 100%);
  mask-image:linear-gradient(180deg,#000 80%,rgba(0,0,0,.72) 91%,rgba(0,0,0,.18) 97%,transparent 100%)}

/* THE ONE THAT MATTERED. Site-wide, photo <img> elements carry an opaque
   background-color (computed rgb(31,33,38)) so a photo that has not decoded yet
   shows as a dark plate instead of a hole. Behind a transparent PNG that plate
   never goes away — it painted a hard-edged charcoal rectangle around him and
   put the framed card straight back, which is exactly what this whole treatment
   was removing. Every other change here is cosmetic; this one is load-bearing. */
#founder.fdr-cut .founder-photo img{background:none;background-color:transparent}

/* With the plate gone, the .ph fallback caption ("David Klemic 4:5") shows
   through the transparent parts of the PNG. It is only meant to appear when
   there is no image, so say exactly that. Browsers without :has() get it
   hidden unconditionally, which is what they render today anyway. */
#founder.fdr-cut .photo-slot .ph{display:none}
#founder.fdr-cut .photo-slot:not(:has(img)) .ph{display:flex}

/* Key light. A cut-out with no glow behind it reads as a mistake — the eye
   needs a reason for the figure to be brighter than the section. Sized larger
   than the column and clipped by nothing, so it spills into the text side the
   way a real light would. */
#founder.fdr-cut .fdr-glow{
  position:absolute;left:50%;top:36%;transform:translate(-50%,-50%);
  width:118%;aspect-ratio:1/1;border-radius:50%;
  z-index:0;pointer-events:none;
  background:radial-gradient(circle at 50% 50%,
    rgba(58,166,214,.55) 0%,
    rgba(58,166,214,.28) 30%,
    rgba(58,166,214,.10) 50%,
    rgba(58,166,214,0) 70%)}

/* Floor pool. Without it he hovers. */
#founder.fdr-cut .founder-photo::before{
  content:"";position:absolute;left:50%;bottom:2px;transform:translateX(-50%);
  width:82%;height:52px;border-radius:50%;z-index:0;pointer-events:none;
  background:radial-gradient(ellipse at 50% 50%,rgba(58,166,214,.20),rgba(58,166,214,0) 70%)}

/* Brackets kept, but re-read. On the old framed photo they were a border
   decoration; on a frameless figure they are the gait-analysis viewfinder the
   rest of the site already uses — the same framing marks that sit on the
   Results photos. Pulled outward and tinted so they mark HIM, not a box edge. */
#founder.fdr-cut .fbrk i{
  width:46px;height:46px;opacity:.5;
  border-width:2px;border-color:rgba(99,183,222,.9)}
/* Two corners, not four. All four redraw exactly the rectangle the cut-out
   exists to escape — I tried it and it read as the old framed card with the
   background knocked out. One corner top-left and one bottom-right is the
   camera-framing mark instead of a border. */
#founder.fdr-cut .fbrk i:nth-child(1){top:-4px;left:-10px}
#founder.fdr-cut .fbrk i:nth-child(2){display:none}
#founder.fdr-cut .fbrk i:nth-child(3){display:none}
#founder.fdr-cut .fbrk i:nth-child(4){bottom:-2px;right:-10px}
#founder.fdr-cut .founder-photo:hover .fbrk i{opacity:.9}

/* The badge used to sit on an opaque photo. It now sits on his faded-out
   torso and on the section behind it, so it carries its own plate. */
#founder.fdr-cut .founder-badge{
  left:0;bottom:22px;
  padding:12px 18px 13px;
  border-left:3px solid var(--sky);
  background:linear-gradient(90deg,rgba(22,23,26,.88),rgba(22,23,26,.42) 78%,transparent);
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px)}

/* ---- Watermark ----------------------------------------------------------
   The old layout ended at "Since 2002, he's taught it." and left roughly a
   third of the right column empty. Outlined display type at this size fills it
   without adding a claim that has to be fact-checked. Stroke only, no fill:
   a filled version at any opacity that is readable behind the headline is also
   opaque enough to muddy it. */
#founder .fdr-word{
  position:absolute;z-index:0;pointer-events:none;user-select:none;
  right:5vw;top:2%;
  font-family:var(--display);text-transform:uppercase;white-space:nowrap;
  font-size:clamp(96px,20vw,320px);line-height:.78;letter-spacing:-.035em;
  color:transparent;-webkit-text-stroke:1.5px rgba(255,255,255,.085)}
/* Firefox has no -webkit-text-stroke on this property in older builds; the
   fallback is simply an invisible element, which is the correct failure mode
   for decoration. */

/* The headline is the best line of copy on the site and it was set smaller
   than the Programs heading directly below it. */
#founder.fdr-cut h2{font-size:clamp(36px,5.2vw,76px);line-height:.98}

/* ---- The credential pull-out ---- */
/* Same content, more weight. This is the only NFL fact on the home page that
   is about David rather than about an alumnus. */
#founder.fdr-cut .fastest{
  padding:16px 26px 17px;
  border-left:3px solid var(--sky);
  background:linear-gradient(90deg,rgba(58,166,214,.22),rgba(58,166,214,.02) 76%,transparent);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.07)}
#founder.fdr-cut .fastest b{font-size:clamp(30px,3.2vw,44px)}

/* ---- Combine lanes ---- */
/* #founder::before already draws receding lane lines at rgba(255,255,255,.05),
   which measured as invisible against --ink. Lifted, and given a horizon fade
   from the left so the lanes appear to run toward him. */
#founder.fdr-cut::before{
  background:repeating-linear-gradient(90deg,transparent 0 118px,rgba(255,255,255,.085) 118px 120px);
  -webkit-mask-image:linear-gradient(180deg,transparent,#000 38%,#000 72%,transparent),
                     linear-gradient(90deg,#000 0%,#000 34%,rgba(0,0,0,.25) 62%,transparent 88%);
  mask-image:linear-gradient(180deg,transparent,#000 38%,#000 72%,transparent),
             linear-gradient(90deg,#000 0%,#000 34%,rgba(0,0,0,.25) 62%,transparent 88%);
  -webkit-mask-composite:source-in;mask-composite:intersect}

@media(max-width:1000px){
  /* Stacked. The photo column is a grid item that was inheriting justify-self
     from the two-column layout, which parked the figure hard against the right
     edge of a full-width row — it read as a mistake. Centre it explicitly. */
  #founder.fdr-cut .founder-grid{justify-items:center}
  #founder.fdr-cut .founder-photo{max-width:340px;width:100%;margin-inline:auto;justify-self:center}
  #founder.fdr-cut .founder-grid>*:not(.founder-photo){width:100%}
  /* The watermark exists to fill the dead space to the right of the paragraph
     in the two-column layout. Stacked, there is no dead space and it lands on
     top of the portrait instead. Nothing is lost by dropping it. */
  #founder .fdr-word{display:none}
}
@media(max-width:640px){
  #founder.fdr-cut .founder-photo{max-width:280px}
}

@media(prefers-reduced-motion:reduce){
  #founder.fdr-cut .fbrk i{transition:none}
}





/* Vince Papale's card carries one fact the other testimonial cards do not:
   the 2006 Disney film is about him. It does not belong in .pro-cred (a 9.5px
   uppercase badge) or in .pro-id span (also uppercase, tracked out at .14em) —
   at those sizes a sentence turns into a ransom note. It gets its own line
   under the quote, set as a caption: quieter than the quote, so it reads as a
   footnote to the person rather than as more of what he said. */
.pro-note{margin-top:14px;padding-top:13px;border-top:1px solid var(--line-d,rgba(255,255,255,.1));
  font-size:12.5px;line-height:1.55;letter-spacing:.01em;color:var(--muted-d);font-weight:600}
.pro-note i{font-style:italic;color:#fff;font-weight:700}


/* ==========================================================================
   THE METHOD (#method) — FOUR LANES
   ==========================================================================
   Brief was "make this look different than any other section on the home page
   ... almost like another hero section where it completely stands out and makes
   everyone scrolling stop and look."

   Every other band on this page is the same shape: left-aligned head-row, then
   a grid of rounded cards inside .wrap. The old .pillars row was exactly that,
   so the four pillars — the actual product — read as one more list of tiles.

   What is deliberately different here, and why each one:
     centred heading      nothing else on the page centres a section head, so
                          the change of axis registers before you read a word
     full-bleed           the lanes run edge to edge with no .wrap and no gap,
                          so there is no card gutter and no page margin
     no border-radius     every other tile on the site is rounded; these are not
     floor-to-ceiling     min-height ~57vw, roughly a half screen, versus the
                          ~300px the old cards occupied
     photographic         each lane is a photo, not an icon on a flat panel
     hairline separators  four columns divided by 1px rules reads as track lanes,
                          which is the metaphor the hero and the founder section
                          already use

   Old .pillar / .pillars CSS is untouched above — method.html still uses it.
   This section is entirely in its own .mtn-* namespace.

   The four photos do not exist yet. .mtn-shot carries a gradient of its own, so
   a lane with no image is a graded dark panel rather than a hole, and the
   section is shippable today. Expected files, portrait, ~900x1400:
     photos/pillar-01-acceleration.jpg
     photos/pillar-02-force.jpg
     photos/pillar-03-center-of-mass.jpg
     photos/pillar-04-max-velocity.jpg   */

.mtn{position:relative;background:var(--ink);color:#fff;overflow:hidden;
  padding:var(--sec) 0 0}

/* One soft pool of brand light behind the heading. The section is otherwise
   flat --ink, and a hero needs a light source. */
.mtn-glow{position:absolute;left:50%;top:-14%;transform:translateX(-50%);
  width:130vw;height:74vh;z-index:0;pointer-events:none;
  background:radial-gradient(ellipse 46% 50% at 50% 50%,rgba(58,166,214,.17),rgba(58,166,214,0) 68%)}

/* ---- Head ---- */
.mtn-head{position:relative;z-index:2;text-align:center;max-width:820px}
.mtn-head .man-eyebrow{justify-content:center}
/* .sec-head h2 is capped at 64px site-wide (and app.js watches that exact
   selector for the entrance lift, which is why the wrapper stays .sec-head
   rather than becoming a new class). Hero scale needs roughly double. */
.mtn-head .sec-head h2{font-size:clamp(46px,8.4vw,120px);line-height:.84;letter-spacing:-.028em}
.mtn-lead{margin:24px auto 0;max-width:600px;font-size:17px;line-height:1.7;
  color:var(--muted-d)}

/* ---- Lanes ----
   The row used to open with a 1px white rule and a hard margin, which is what
   made the blue head and the photographs read as two unrelated blocks. Both are
   gone: the gap is tighter, there is no rule, and the head's light is carried
   down over the top of the photos by .mtn-lanes::before below. */
.mtn-lanes{position:relative;z-index:2;margin-top:clamp(30px,3.8vw,58px);
  display:grid;grid-template-columns:repeat(4,1fr);gap:0}

/* The head's glow continued over the lanes. This is the join: the blue does not
   stop at an edge, it washes down across the first fifth of the photographs and
   fades out inside them. Sits above the lanes (z 3) but below the type (z 3 in
   .mtn-inner, which comes later in paint order) and ignores the pointer. */
.mtn-lanes::before{content:"";position:absolute;left:0;right:0;top:0;
  height:clamp(150px,20vw,280px);z-index:3;pointer-events:none;
  background:linear-gradient(180deg,
    rgba(58,166,214,.20) 0%,
    rgba(58,166,214,.09) 38%,
    rgba(58,166,214,0) 100%)}

.mtn-lane{position:relative;isolation:isolate;overflow:hidden;
  min-height:clamp(430px,57vw,660px);
  display:flex;flex-direction:column;justify-content:flex-end;
  padding:34px 26px 40px;
  border-right:1px solid rgba(255,255,255,.10)}
.mtn-lane:last-child{border-right:0}

/* Josh's call: 01 green, 02 blue, 03 green, 04 blue -- so odd/even, which also
   survives the 2-column and 1-column breakpoints unchanged.
   Three variables per lane rather than one:
     --lane      the resting accent, pulled back so the row is calm at rest
     --lane-hot  the hover colour, pushed well past the brand swatch on purpose
     --lane-wash the same hue as a soft alpha, for glows and floor light
   The gap between --lane and --lane-hot is the whole "come to life" effect. */
.mtn-lane:nth-child(odd){--lane:#8CC63F;--lane-hot:#B4F53F;--lane-wash:rgba(160,229,60,.55)}
.mtn-lane:nth-child(even){--lane:#63B7DE;--lane-hot:#4FD8FF;--lane-wash:rgba(79,216,255,.55)}

/* The gradient is on the wrapper, not the image, so it IS the empty state:
   when a photo is missing, onerror deletes the <img> and this is what remains. */
.mtn-shot{position:absolute;inset:0;z-index:0;
  background:linear-gradient(178deg,#242830 0%,#191C21 55%,#0F1114 100%)}
.mtn-shot img{width:100%;height:100%;object-fit:cover;object-position:50% 32%;
  filter:grayscale(.55) contrast(1.06) brightness(.76) saturate(.9);
  transform:scale(1.05);
  transition:filter .6s,transform .7s cubic-bezier(.16,1,.3,1)}
/* Hover is where the colour is supposed to arrive. saturate(1.4) is deliberately
   past "correct" -- the resting state is desaturated and dim, so the jump has to
   be big enough to read as the photograph switching on. */
.mtn-lane:hover .mtn-shot img{filter:grayscale(0) contrast(1.1) brightness(1) saturate(1.4);
  transform:scale(1)}

/* The lane's own colour laid into the photograph on hover, in soft-light so it
   tints rather than paints over. This is what stops the effect being "a green
   line got brighter" and makes the whole tile change temperature.
   Weighted to the bottom two-fifths rather than the whole frame: at full-frame
   the tint turned the athletes themselves green and blue, which is the one
   thing it must not do. Low down it reads as coloured light on the ground. */
.mtn-shot::after{content:"";position:absolute;inset:0;z-index:1;pointer-events:none;
  background:linear-gradient(180deg,rgba(0,0,0,0) 46%,var(--lane-hot) 100%);
  mix-blend-mode:soft-light;opacity:0;transition:opacity .55s}
.mtn-lane:hover .mtn-shot::after{opacity:.95}

/* Framing is per lane because the four frames are not interchangeable: three
   are portrait with the athlete roughly centred, and 01 is a wide forward lean
   whose canvas was extended vertically so a tall crop would stop amputating
   him. One shared object-position cut somebody out of frame in every
   combination I tried. */
.mtn-lane:nth-child(1) .mtn-shot img{object-position:50% 30%}
.mtn-lane:nth-child(2) .mtn-shot img{object-position:50% 38%}
.mtn-lane:nth-child(3) .mtn-shot img{object-position:64% 40%}
.mtn-lane:nth-child(4) .mtn-shot img{object-position:44% 34%}

/* Readability scrim, and the other half of the flow fix. It now opens at full
   --ink and clears within the first tenth, so the top of every photograph
   dissolves into the section background instead of starting on a hard edge
   under the heading. The bottom half is unchanged -- it still has to hold the
   type over a bright action photo. */
.mtn-lane::before{content:"";position:absolute;inset:0;z-index:1;pointer-events:none;
  background:linear-gradient(180deg,
    rgba(15,17,20,1)    0%,
    rgba(15,17,20,.72)  6%,
    rgba(15,17,20,.34)  15%,
    rgba(15,17,20,.20)  26%,
    rgba(15,17,20,.44)  40%,
    rgba(15,17,20,.80)  62%,
    rgba(15,17,20,.95)  82%,
    rgba(15,17,20,.985) 100%)}

/* Lane accent along the floor. Parked at 18% so the row reads as a set of
   staggered start marks at rest, then runs the full width on hover -- thicker,
   in the hot colour, throwing light back up into the tile. */
.mtn-lane::after{content:"";position:absolute;left:0;right:0;bottom:0;height:3px;z-index:5;
  background:var(--lane);transform:scaleX(.18);transform-origin:left;
  transition:transform .55s cubic-bezier(.16,1,.3,1),
             background .4s,height .35s,box-shadow .45s}
.mtn-lane:hover::after{transform:scaleX(1);height:5px;
  background:var(--lane-hot);box-shadow:0 -2px 26px 1px var(--lane-wash)}

/* Floor light. Sits inside .mtn-inner's stacking context at z-index -1, which
   puts it above the scrim but behind the words, so the copy gets a coloured
   pool under it rather than a coloured film over it. The negative insets
   overrun the lane padding on purpose; .mtn-lane clips them. */
.mtn-inner::before{content:"";position:absolute;left:-60px;right:-60px;bottom:-70px;
  height:260px;z-index:-1;pointer-events:none;
  background:linear-gradient(0deg,var(--lane-wash) 0%,rgba(0,0,0,0) 76%);
  opacity:0;transition:opacity .5s}
.mtn-lane:hover .mtn-inner::before{opacity:.85}

/* Outlined, not filled. A solid number this size competes with the pillar name;
   an outline reads as a lane marker painted on the surface. */
.mtn-no{position:absolute;top:18px;left:24px;z-index:3;pointer-events:none;
  font-family:var(--display);font-weight:400;
  font-size:clamp(62px,7.4vw,108px);line-height:.78;letter-spacing:-.02em;
  color:transparent;-webkit-text-stroke:1.6px rgba(255,255,255,.32);
  transition:-webkit-text-stroke-color .5s,filter .5s}
/* drop-shadow rather than a box-shadow: the number is an outline, so the glow
   has to follow the strokes, not the box around them. */
.mtn-lane:hover .mtn-no{-webkit-text-stroke-color:var(--lane-hot);
  filter:drop-shadow(0 0 16px var(--lane-wash))}

.mtn-inner{position:relative;z-index:3}
/* Both min-heights exist for one reason: the lanes are bottom-anchored and the
   four blocks are not the same size -- two headings wrap to a second line, one
   list has two items, one carries a note. Left alone, the headings and the
   hairline rules landed at four different heights and the row read as sloppy
   rather than staggered. Reserving two lines for every heading and matching
   every "gives you" block to the tallest puts all four rules on one line
   across the section. Both are released at 600px, where the lanes stack and
   the reserved space would just be a hole. */
.mtn-lane h3{font-family:var(--display);font-weight:400;text-transform:uppercase;
  font-size:clamp(23px,2.2vw,32px);line-height:.98;letter-spacing:.02em;margin:0 0 18px;
  min-height:1.96em}

.mtn-give{padding-top:16px;border-top:1px solid rgba(255,255,255,.2);min-height:100px;
  transition:border-color .45s}
.mtn-lane:hover .mtn-give{border-top-color:var(--lane-hot)}
.mtn-lab{display:block;font-family:var(--body);font-size:11px;letter-spacing:0.14em;
  text-transform:uppercase;color:var(--muted-d);font-weight:800;margin-bottom:10px}
.mtn-give ul{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:9px}
/* Pillar 02 pays out twice ("a higher vertical" AND "more separation in your
   first step"), so the payoff is a list in every lane, not a single line. One
   item looks identical to the old single line; two do not have to be crammed
   into one sentence. */
.mtn-give li{position:relative;padding-left:17px;
  font-family:var(--display);font-weight:400;text-transform:uppercase;
  font-size:clamp(16px,1.4vw,20px);line-height:1.1;letter-spacing:.03em;color:#fff}
.mtn-give li::before{content:"";position:absolute;left:0;top:.42em;
  width:8px;height:2px;background:var(--lane);
  transition:background .4s,width .4s cubic-bezier(.16,1,.3,1),box-shadow .4s}
.mtn-lane:hover .mtn-give li::before{width:12px;background:var(--lane-hot);
  box-shadow:0 0 10px var(--lane-wash)}
.mtn-note{margin-top:14px;font-family:var(--body);font-size:12px;line-height:1.5;
  color:var(--muted-d);font-weight:600;letter-spacing:.01em}

/* ---- Foot ---- */
.mtn-foot{display:flex;align-items:center;justify-content:center;gap:14px 30px;
  flex-wrap:wrap;padding:clamp(36px,4.4vw,58px) 0 var(--sec)}
.mtn-alt{font-size:12px;letter-spacing:.14em;text-transform:uppercase;font-weight:800;
  color:var(--sky);text-decoration:none;transition:color .3s}
.mtn-alt:hover{color:var(--green)}

/* ---- Responsive ----
   4 -> 2 -> 1. Four lanes stop working around 1040px, where each is under
   ~250px and "Center of Mass Management" can no longer set on two lines. */
@media(max-width:1040px){
  .mtn-lanes{grid-template-columns:1fr 1fr}
  .mtn-lane{min-height:clamp(360px,46vw,460px)}
  /* with two columns the right-hand lane's border is the page edge */
  .mtn-lane:nth-child(2n){border-right:0}
  .mtn-lane:nth-child(-n+2){border-bottom:1px solid rgba(255,255,255,.10)}
}
@media(max-width:600px){
  .mtn-lanes{grid-template-columns:1fr}
  /* Stacked, a half-screen lane means four full screens of scrolling to get
     through one section. Bands instead. */
  .mtn-lane{min-height:300px;border-right:0;
    border-bottom:1px solid rgba(255,255,255,.10);padding:26px 22px 30px}
  .mtn-lane:last-child{border-bottom:0}
  .mtn-lane h3{min-height:0}
  .mtn-give{min-height:0}
  .mtn-no{font-size:66px;top:14px;left:20px}
  .mtn-head .sec-head h2{font-size:clamp(42px,13vw,60px)}
  .mtn-lead{font-size:15.5px}
}

@media(prefers-reduced-motion:reduce){
  .mtn-shot img,.mtn-shot::after,.mtn-lane::after,.mtn-no,
  .mtn-inner::before,.mtn-give,.mtn-give li::before{transition:none}
  .mtn-lane::after{transform:scaleX(1)}
}


/* ---- The record, under the portrait -------------------------------------
   Replaces the five-crest logo strip. Five small grey badges asked the reader
   to already know what Mainland and Northeastern mean; the numbers do not.
   Three tiers, deliberately unequal in weight: the Hall of Fame line and the
   pull quote set the frame, four record numbers carry the section, and the
   honours list is scannable detail for anyone who wants it. Everything here
   is sourced from Northeastern's own Hall of Fame page. */
.fdr-rec{position:relative;z-index:2;margin-top:clamp(48px,6vw,86px);
  padding-top:clamp(34px,4vw,52px);border-top:1px solid rgba(255,255,255,.14)}

/* Label left, quote right. The quote is the louder element, so it takes the
   larger share and the label sits against it as a caption would. */
.fdr-rec-top{display:grid;grid-template-columns:minmax(190px,.62fr) 1.38fr;
  gap:clamp(24px,3.4vw,56px);align-items:start}
.fdr-hof{display:block;font-size:11px;letter-spacing:0.14em;text-transform:uppercase;
  font-weight:800;line-height:1.7;color:var(--sky);
  padding-left:15px;border-left:2px solid var(--sky)}

/* text-wrap:balance because at full size the quote ran to within a word of the
   column edge and dropped "time." onto a line by itself. Balancing splits it
   into two even lines instead of one long one and an orphan. */
.fdr-pull{margin:0;font-family:var(--display);font-weight:400;text-transform:uppercase;
  font-size:clamp(24px,2.9vw,41px);line-height:1.04;letter-spacing:.005em;color:#fff;
  text-wrap:balance}
.fdr-pull cite{display:block;margin-top:14px;font-family:var(--body);font-style:normal;
  font-size:11px;letter-spacing:0.14em;text-transform:uppercase;
  font-weight:800;color:var(--muted-d)}

/* Four numbers on one rail. The dividers are between cells rather than around
   them so the row reads as one instrument panel, not four cards. */
.fdr-nums{list-style:none;margin:clamp(34px,4.4vw,60px) 0 0;padding:0;
  display:grid;grid-template-columns:repeat(4,1fr);
  border-top:1px solid rgba(255,255,255,.12);
  border-bottom:1px solid rgba(255,255,255,.12)}
.fdr-nums li{position:relative;padding:clamp(22px,2.6vw,32px) clamp(14px,1.8vw,26px);
  border-right:1px solid rgba(255,255,255,.09)}
.fdr-nums li:last-child{border-right:0}
.fdr-nums b{display:block;font-family:var(--display);font-weight:400;
  font-size:clamp(44px,5.6vw,82px);line-height:.86;letter-spacing:-.02em;color:#fff}
.fdr-nums span{display:block;margin-top:12px;font-size:12.5px;line-height:1.4;
  font-weight:700;color:#fff;letter-spacing:.01em}
/* "School record" is the payload of the whole row — it is what turns 217 from
   a number into an argument — so it gets the accent, not the grey. */
.fdr-nums i{display:block;margin-top:5px;font-style:normal;
  font-size:11px;letter-spacing:0.14em;text-transform:uppercase;
  font-weight:800;color:var(--sky)}
.fdr-nums li:last-child i{color:var(--green)}

.fdr-hon{list-style:none;margin:clamp(30px,3.6vw,46px) 0 0;padding:0;
  display:grid;grid-template-columns:1fr 1fr;gap:2px clamp(28px,3.6vw,60px)}
.fdr-hon li{padding:15px 0 16px;border-top:1px solid rgba(255,255,255,.08)}
.fdr-hon b{display:block;font-size:13.5px;line-height:1.35;font-weight:800;
  color:#fff;letter-spacing:.005em}
.fdr-hon span{display:block;margin-top:5px;font-size:12.5px;line-height:1.55;
  color:var(--muted-d);font-weight:500}

@media(max-width:900px){
  .fdr-rec-top{grid-template-columns:1fr;gap:20px}
  .fdr-nums{grid-template-columns:1fr 1fr}
  .fdr-nums li:nth-child(2n){border-right:0}
  .fdr-nums li:nth-child(-n+2){border-bottom:1px solid rgba(255,255,255,.09)}
  .fdr-hon{grid-template-columns:1fr}
}
@media(max-width:520px){
  .fdr-nums li{padding:18px 14px}
  .fdr-nums b{font-size:40px}
}

/* ===== CONTACT POINT =====
   Josh supplied a phone and an email but NOT the purchase/booking URLs — those live on an
   existing booking page he'll hand over separately. So this block is the interim destination
   for every "sign up / inquire" button on the site: a real human to call, text or email,
   rather than an href="#" that does nothing. When the real links arrive, repoint the buttons
   and leave this section alone — it stands on its own. */
/* --ink-2, not --ink: the footer is --ink and sits directly below this, so the two would read
   as one undifferentiated dark slab. The lighter grade plus the glow keeps them separate. */
.contact{position:relative;background:var(--ink-2);color:#fff;padding:var(--sec) 0;overflow:hidden}
.contact::before{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background:radial-gradient(ellipse 60% 70% at 82% 30%,rgba(99,183,222,.20),transparent 70%)}
.contact > *{position:relative;z-index:1}
.contact-grid{display:grid;grid-template-columns:1fr .9fr;gap:var(--s-6);align-items:center}
.contact h2{font-family:var(--display);text-transform:uppercase;
  font-size:clamp(30px,4.4vw,54px);line-height:.96;margin-top:var(--s-2)}
.contact-lead{margin-top:var(--s-3);font-size:17px;color:var(--muted-d);max-width:460px}
.contact-card{background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.14);
  border-radius:var(--r-lg);padding:var(--s-4)}
.contact-who{padding-bottom:var(--s-3);margin-bottom:var(--s-3);
  border-bottom:1px solid rgba(255,255,255,.14)}
.contact-who b{display:block;font-family:var(--display);text-transform:uppercase;
  font-size:26px;line-height:1;letter-spacing:.02em}
.contact-who span{display:block;margin-top:8px;font-family:var(--mono);font-size:11px;
  letter-spacing:.14em;text-transform:uppercase;color:var(--sky)}
.contact-line{display:flex;align-items:center;gap:13px;padding:11px 0;
  color:#fff;font-size:17px;font-weight:700;word-break:break-word}
.contact-line:hover .cl-val{color:var(--sky)}
.cl-lab{flex:none;width:74px;font-family:var(--mono);font-size:11px;letter-spacing:0.14em;
  text-transform:uppercase;color:var(--muted-d);font-weight:400}
.cl-val{transition:color .2s}
.contact-note{margin-top:var(--s-3);font-family:var(--mono);font-size:11px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--muted-d)}
.contact-actions{display:flex;gap:12px;flex-wrap:wrap;margin-top:var(--s-4)}
@media(max-width:960px){
  .contact-grid{grid-template-columns:1fr;gap:var(--s-4)}
}
@media(max-width:620px){
  .contact{padding:var(--sec-sm) 0}
  .contact-card{padding:var(--s-3)}
  /* Stack the label above the value — side by side, a 74px label plus a 33-character email
     cannot fit in a 350px phone column without breaking mid-word. */
  .contact-line{flex-direction:column;align-items:flex-start;gap:4px;font-size:16px}
  .cl-lab{width:auto}
  .contact-actions .btn{width:100%;justify-content:center}
}

/* Entry requirement badge. Josh's rule: a new athlete starts with a Gait Analysis, an
   athlete who has already been through a cycle starts with Effective Range Measurements.
   Young Guns shows both in an .entry-ways block because that program contains both cases;
   New Athletes and Veteran Athletes are separate programs, so each states its one test. */
.preq{display:inline-flex;align-items:center;gap:13px;margin:0 0 26px;padding:11px 16px;
  border-radius:var(--r-md);background:rgba(58,166,214,.09);border:1px solid rgba(58,166,214,.26)}
.preq span{font-family:var(--mono);font-size:11px;letter-spacing:0.14em;text-transform:uppercase;
  color:var(--muted);flex:none}
.preq b{font-size:15px;color:var(--ink);line-height:1.3}
@media(max-width:520px){
  .preq{align-items:flex-start;flex-direction:column;gap:5px;width:100%}
}

/* ============================================================
   ALUMNI WALL  (alumni.html)
   ============================================================
   Replaces the placeholder .wall tiles with real athlete cards. Every source photo is
   pre-cropped to exactly 4:5 by the build script, so object-fit:cover here is a no-op
   safety net rather than the thing doing the framing — if a photo is ever swapped in at a
   different ratio the layout still holds instead of stretching. */
/* Josh asked (Aug 18) for this page to run light instead of the site's dark treatment,
   then asked for "something more going on" than flat white. Four stacked layers, all very
   low contrast, so the background gets depth without competing with 65 faces:
     1. base wash        — white cooling to a faint blue-grey toward the bottom
     2. brand glows      — one accent-blue, one green, placed off-centre so it isn't symmetrical
     3. speed lanes      — the same 1/6-width vertical rhythm as the dark hero's .hero-lanes
     4. measurement grid — the existing .grid-bg graph-paper motif at 64px
   Grid and lanes are masked at top and bottom so the section fades into its neighbours
   instead of ending on a hard seam.
   Cards flip to pure white here: against a tinted, textured field a white tile reads as an
   object sitting on top, which is a cleaner hierarchy than a grey tile on white. */
.aw-section{position:relative;isolation:isolate;color:var(--ink);padding-top:var(--sec);
  background:linear-gradient(178deg,#FFFFFF 0%,#FBFCFD 42%,#F4F7F9 100%)}
.aw-section::before{content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background-image:
    radial-gradient(ellipse 55% 42% at 12% 4%,rgba(58,166,214,.13),transparent 68%),
    radial-gradient(ellipse 48% 38% at 92% 82%,rgba(140,198,63,.11),transparent 70%),
    repeating-linear-gradient(90deg,transparent 0 calc(100%/6 - 1px),rgba(22,23,26,.05) calc(100%/6 - 1px) calc(100%/6)),
    linear-gradient(rgba(22,23,26,.038) 1px,transparent 1px),
    linear-gradient(90deg,rgba(22,23,26,.038) 1px,transparent 1px);
  background-size:auto,auto,auto,64px 64px,64px 64px;
  mask-image:linear-gradient(180deg,transparent 0,#000 9%,#000 88%,transparent 100%);
  -webkit-mask-image:linear-gradient(180deg,transparent 0,#000 9%,#000 88%,transparent 100%)}
.aw-section > *{position:relative;z-index:1}
/* --accent-deep (#1E88B8) only hits 3.99:1 on white, and the eyebrow is 11px uppercase,
   which WCAG treats as small text needing 4.5:1. #17719C is the same blue a shade darker
   and clears it at 5.4:1. */
.aw-section .eyebrow{color:#17719C}
.aw-section .sec-head p{color:var(--muted)}
.aw-section .man-eyebrow::before{background:var(--line-l)}

.aw-grid{display:grid;grid-template-columns:repeat(6,1fr);gap:14px;margin-top:8px}
.aw{border-radius:var(--r-md);overflow:hidden;background:var(--paper-2);border:1px solid rgba(22,23,26,.10);
    box-shadow:0 1px 2px rgba(22,23,26,.05),0 4px 14px -6px rgba(22,23,26,.10);
    transition:transform .3s cubic-bezier(.16,1,.3,1),border-color .3s,box-shadow .3s}
.aw:hover{transform:translateY(-5px);border-color:rgba(22,23,26,.2);
          box-shadow:0 2px 4px rgba(22,23,26,.06),0 16px 34px -10px rgba(22,23,26,.22)}
.aw-ph{position:relative;aspect-ratio:4/5;overflow:hidden;background:#E4E2DE}
.aw-ph img{width:100%;height:100%;object-fit:cover;display:block;
           transition:transform .5s cubic-bezier(.16,1,.3,1)}
.aw:hover .aw-ph img{transform:scale(1.045)}

/* Caption sits under the photo rather than overlaid on it. An overlay reads well on the
   studio headshots but these cards are only ~180px wide on desktop, and a third of the
   set are action shots with bright crowds behind the athlete's shoulders — white text on
   those needs a scrim heavy enough that it hides the photo it is sitting on. Below the
   image the name is legible on every card at every width. */
/* min-height reserves two lines of school/accolade text on every card. Six of the 56 captions
   wrap ("McDonald's All-American · Villanova", "Patriot League MVP · Holy Cross"), and because
   grid rows stretch to their tallest item, a single wrapped caption was padding out its whole
   row and leaving dead space under the five cards beside it. Reserving the second line
   everywhere costs 26px per card and makes all 102 identical height.
   76px = 24 padding + 13.7 name + 6 gap + 30.8 for two 11px/1.4 lines.
   The subtitle used to be 9.5px, which is too small to read; at the 11px floor two lines
   are 30.8px instead of 26.6, so this reserve grew from 70px to 76px to match. If you
   change the subtitle size again, re-derive this number or the cards go ragged. */
.aw-meta{padding:11px 12px 13px;min-height:76px}
.aw-meta b{font-family:var(--display);text-transform:uppercase;font-size:13px;line-height:1.05;
           letter-spacing:.01em;display:block}
/* .06em, not .1em: at 11px the longest subtitles ("East Stroudsburg Football") need a third
   line at wider tracking, and a third line breaks the uniform card height. */
.aw-meta span{font-family:var(--mono);font-size:11px;letter-spacing:.06em;text-transform:uppercase;
              color:var(--muted);margin-top:6px;display:block;line-height:1.4}

/* Athletes we do not have a photo for yet get an initials plate instead of being dropped
   from the wall. A missing tile would leave a hole in the grid; a plate keeps the rhythm
   and still counts the athlete. Swap in a real photo and delete the .none class. */
.aw-ph.none{display:flex;align-items:center;justify-content:center;
            background:linear-gradient(155deg,#E8E6E2,#DCDAD5)}
.aw-ph.none i{font-family:var(--display);font-style:normal;font-size:32px;
              color:rgba(22,23,26,.24);letter-spacing:.03em}


/* ---- school-coloured cards ------------------------------------------------------
   Josh (Aug 19): "make all of these Cards in school colors ... and a link to all of
   their profiles."

   Every figure carries a data-school slug; the rules at the bottom of this block set
   three custom properties per school, and the card design below reads only those. So
   adding an athlete is a one-line change and never touches the design.

     --sc      the school's primary colour, used as the caption band
     --sc2     an accent that is guaranteed to be visible ON that band
     --sc-ink  text colour, chosen per school rather than assumed to be white

   The ink is the part worth explaining. Most school colours are dark and take white
   text fine, but Carolina blue, Clemson orange and Princeton orange are light: white
   on them measures about 3:1, well under the 4.5:1 minimum for small text. Those three
   flip to dark ink, which measures ~6:1. Generated by measuring contrast, not by eye.

   "kpm" is the house style for the 15 athletes with no school on their card -- the
   NFL/NHL players, the Olympic and Stanley Cup medallists, the national champion.
   Without it they would be the only plain white cards in a wall of 90 coloured ones.
   ------------------------------------------------------------------------------- */
.aw{position:relative;--sc:#20242B;--sc2:rgba(255,255,255,.55);--sc-ink:#fff}
.aw-meta{position:relative;background:var(--sc);color:var(--sc-ink);
         box-shadow:inset 0 2px 0 var(--sc2)}
.aw-meta b{color:inherit}
/* No opacity. Each --sc-ink was picked to clear 4.5:1 on its school colour;
   fading it to .78 dropped 10 of the 63 palettes below that (dickinson 3.18,
   east-stroudsburg 3.47, rutgers 3.86 ...). The name stays distinct from the
   credential by weight — <b> vs <span> — not by fading the credential out. */
.aw-meta span{color:inherit}
.aw-ph{background:var(--sc)}
.aw-ph.none{background:linear-gradient(155deg,var(--sc),color-mix(in srgb,var(--sc) 74%,#000))}
.aw-ph.none i{color:var(--sc-ink);opacity:.42}
@supports not (color: color-mix(in srgb,red,blue)){
  .aw-ph.none{background:var(--sc)}
}
.aw:hover{border-color:var(--sc)}

/* KPM house style for the no-school cards -- brand navy with the accent blue hairline */
[data-school="kpm"]{--sc:#151A21;--sc2:var(--accent);--sc-ink:#fff}

/* Stretched link: the anchor is a transparent overlay across the whole card, so the
   entire tile is clickable while <figcaption> stays a direct child of <figure>, which
   the HTML spec requires. Wrapping the caption in an <a> instead would be invalid. */
.aw-link{position:absolute;inset:0;z-index:3;border-radius:var(--r-md)}
.aw-link:focus-visible{outline:3px solid var(--accent);outline-offset:3px}
.aw:has(.aw-link){cursor:pointer}
.aw:has(.aw-link) .aw-meta::after{content:"\2197";position:absolute;right:10px;bottom:11px;
  font-family:var(--mono);font-size:11px;line-height:1;opacity:0;transform:translate(-2px,2px);
  transition:opacity .28s,transform .28s}
.aw:has(.aw-link):hover .aw-meta::after{opacity:.85;transform:none}
/* room for the arrow so it never collides with a two-line credential */
.aw:has(.aw-link) .aw-meta span{padding-right:16px}

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

/* ---- logo chip --------------------------------------------------------------------
   Josh (Aug 19): "add all of the logos ... use the official school logos and for the pro
   guys use all of the pro team logos ... even the NFL logos."

   The chip rides in the top-right of the PHOTO, not the caption band. Three reasons:
   the band already owns the bottom-right corner (the ↗ affordance lives there), the
   band is painted in the school's own colour so a school logo on it would sit colour-
   on-colour, and the top-right of a 4:5 sports photo is nearly always sky/wall/crowd.

   White disc behind every mark. School logos are drawn for white backgrounds and many
   of them are dark navy or black outlines that would vanish against a dark action shot;
   a couple (Navy, Penn State) are near-white and would vanish against a bright one. One
   consistent white disc makes all 91 legible without special-casing any of them.

   Selector is .aw-ph img.aw-logo, not .aw-logo, because .aw-ph img already sets
   object-fit:cover and a hover scale — a bare class would lose on specificity and the
   logo would crop to a circle and grow on hover with the photo.

   Josh (later, Aug 19): "for the college kids please put their highschool logos too" and
   "for the pros put the team logos they played for highschool college and pro."

   So a card can now carry up to three marks. They stack DOWN the right edge rather than
   across the top: these cards are only ~170px wide on a phone but the photo above the
   caption is ~212px tall, so the vertical axis is the one with room to spare. Three
   chips in a row would eat 56% of the card's width; stacked they use the right margin,
   which on a 4:5 sports photo is the emptiest part of the frame.

   Size carries the hierarchy. The top chip is the affiliation the caption names — the
   school or team this athlete is on the wall FOR — at full size. Everything below it is
   where he came from, at 26px. That keeps the original one-chip design intact for the
   cards that only have one, and means the big chip always agrees with the text. */
.aw-logos{position:absolute;top:8px;right:8px;z-index:2;
  display:flex;flex-direction:column;align-items:flex-end;gap:5px}
.aw-ph .aw-logos img{display:block;
  width:34px;height:34px;padding:5px;border-radius:50%;
  background:#fff;object-fit:contain;transform:none;transition:none;
  box-shadow:0 1px 3px rgba(22,23,26,.30),0 0 0 1px rgba(22,23,26,.07)}
/* everything after the first is a "where he came from" mark, so it steps down a size */
.aw-ph .aw-logos img + img{width:26px;height:26px;padding:4px}
.aw:hover .aw-ph .aw-logos img{transform:none}
/* The Olympic rings are the only non-square mark in the set (960x444). Fitted to a
   circle by width they render about 24x11 and read as a smudge, so that one gets a
   pill instead. */
.aw-ph .aw-logos img.wide{width:48px;border-radius:17px;padding:5px 6px}
.aw-ph .aw-logos img + img.wide{width:38px;border-radius:13px;padding:4px 5px}

[data-school="alabama"]{--sc:#9E1B32;--sc2:#828A8F;--sc-ink:#fff}
[data-school="arcadia"]{--sc:#B20D35;--sc2:rgba(255,255,255,.55);--sc-ink:#fff}
[data-school="boston-college"]{--sc:#98002E;--sc2:#BC9B6A;--sc-ink:#fff}
[data-school="bridgeport"]{--sc:#613393;--sc2:#FFFFFF;--sc-ink:#fff}
[data-school="bucknell"]{--sc:#003865;--sc2:#E87722;--sc-ink:#fff}
[data-school="charlotte"]{--sc:#046A38;--sc2:#B9975B;--sc-ink:#fff}
[data-school="clemson"]{--sc:#F66733;--sc2:#522D80;--sc-ink:#10141A}
[data-school="colorado-state"]{--sc:#1E4D2B;--sc2:#C8C372;--sc-ink:#fff}
[data-school="csu-pueblo"]{--sc:#00205B;--sc2:#CC0033;--sc-ink:#fff}
[data-school="delaware"]{--sc:#00539F;--sc2:#FFD200;--sc-ink:#fff}
[data-school="east-stroudsburg"]{--sc:#DB0436;--sc2:#000000;--sc-ink:#fff}
[data-school="florida-southern"]{--sc:#D50C22;--sc2:#FFFFFF;--sc-ink:#fff}
[data-school="holy-cross"]{--sc:#602D89;--sc2:#FFFFFF;--sc-ink:#fff}
[data-school="indiana-state"]{--sc:#0142BC;--sc2:#FFFFFF;--sc-ink:#fff}
[data-school="kean"]{--sc:#15293F;--sc2:#FFFFFF;--sc-ink:#fff}
[data-school="kutztown"]{--sc:#6F1A31;--sc2:#9C9B65;--sc-ink:#fff}
[data-school="la-salle"]{--sc:#003366;--sc2:#FFCC00;--sc-ink:#fff}
[data-school="liberty"]{--sc:#002D62;--sc2:#C41230;--sc-ink:#fff}
[data-school="dickinson"]{--sc:#E8182C;--sc2:#000000;--sc-ink:#fff}
[data-school="fdu"]{--sc:#272F44;--sc2:#7D2B3F;--sc-ink:#fff}
[data-school="delaware-state"]{--sc:#C8102E;--sc2:#9BCBEB;--sc-ink:#fff}
[data-school="millersville"]{--sc:#000000;--sc2:#FFC72C;--sc-ink:#fff}
[data-school="york-college"]{--sc:#006747;--sc2:#FFFFFF;--sc-ink:#fff}
[data-school="william-mary"]{--sc:#115740;--sc2:#B9975B;--sc-ink:#fff}
[data-school="lsu"]{--sc:#461D7C;--sc2:#FDD023;--sc-ink:#fff}
[data-school="lycoming"]{--sc:#193050;--sc2:#F3A00F;--sc-ink:#fff}
[data-school="maine"]{--sc:#003263;--sc2:#B0D7FF;--sc-ink:#fff}
[data-school="marist"]{--sc:#C8102E;--sc2:#FFFFFF;--sc-ink:#fff}
[data-school="mcdaniel"]{--sc:#17412E;--sc2:#F2CF0E;--sc-ink:#fff}
[data-school="merrimack"]{--sc:#003768;--sc2:#FDB813;--sc-ink:#fff}
[data-school="miami"]{--sc:#005030;--sc2:#F47321;--sc-ink:#fff}
[data-school="michigan"]{--sc:#00274C;--sc2:#FFCB05;--sc-ink:#fff}
[data-school="michigan-state"]{--sc:#18453B;--sc2:#FFFFFF;--sc-ink:#fff}
/* Missouri State — maroon. Added Sept 2 with Keith Palek; worth a glance from Josh
   to confirm the shade, since every other slug here was sourced deliberately. */
[data-school="missouri-state"]{--sc:#5E0009;--sc2:#FFFFFF;--sc-ink:#fff}
[data-school="monmouth"]{--sc:#041E42;--sc2:#53565A;--sc-ink:#fff}
[data-school="montclair-state"]{--sc:#CE1141;--sc2:#000000;--sc-ink:#fff}
[data-school="moravian"]{--sc:#00267A;--sc2:#CCCCCC;--sc-ink:#fff}
[data-school="navy"]{--sc:#00205B;--sc2:#C5B783;--sc-ink:#fff}
[data-school="new-hampshire"]{--sc:#041E42;--sc2:#BBBCBC;--sc-ink:#fff}
[data-school="new-haven"]{--sc:#004B8D;--sc2:#FFC423;--sc-ink:#fff}
[data-school="notre-dame"]{--sc:#0C2340;--sc2:#C99700;--sc-ink:#fff}
[data-school="ohio-state"]{--sc:#BB0000;--sc2:rgba(255,255,255,.55);--sc-ink:#fff}
[data-school="penn"]{--sc:#011F5B;--sc2:#990000;--sc-ink:#fff}
[data-school="penn-state"]{--sc:#041E42;--sc2:#FFFFFF;--sc-ink:#fff}
[data-school="princeton"]{--sc:#E77500;--sc2:#000000;--sc-ink:#10141A}
[data-school="rider"]{--sc:#981E32;--sc2:#6C6F70;--sc-ink:#fff}
[data-school="rowan"]{--sc:#57150B;--sc2:#FFCC00;--sc-ink:#fff}
[data-school="rutgers"]{--sc:#CC0033;--sc2:#000000;--sc-ink:#fff}
[data-school="shepherd"]{--sc:#081F3F;--sc2:#C1B45E;--sc-ink:#fff}
[data-school="shippensburg"]{--sc:#0D223F;--sc2:#EE3A43;--sc-ink:#fff}
[data-school="stockton"]{--sc:#231F20;--sc2:#83C2EC;--sc-ink:#fff}
[data-school="susquehanna"]{--sc:#651C32;--sc2:#FF6A14;--sc-ink:#fff}
[data-school="swarthmore"]{--sc:#9D2235;--sc2:#A2AAAD;--sc-ink:#fff}
[data-school="tcnj"]{--sc:#164B7C;--sc2:#FDBD15;--sc-ink:#fff}
[data-school="unc"]{--sc:#4B9CD3;--sc2:#13294B;--sc-ink:#10141A}
[data-school="unc-pembroke"]{--sc:#101820;--sc2:#856C41;--sc-ink:#fff}
[data-school="vanderbilt"]{--sc:#1F1F1F;--sc2:#866D4B;--sc-ink:#fff}
[data-school="villanova"]{--sc:#00205B;--sc2:#13B5EA;--sc-ink:#fff}
[data-school="wagner"]{--sc:#00483A;--sc2:#FFFFFF;--sc-ink:#fff}
[data-school="west-chester"]{--sc:#621B7B;--sc2:#F9B118;--sc-ink:#fff}
[data-school="western-carolina"]{--sc:#592C88;--sc2:#C1A875;--sc-ink:#fff}
[data-school="widener"]{--sc:#264F91;--sc2:#F6C34A;--sc-ink:#fff}

@media(max-width:1200px){.aw-grid{grid-template-columns:repeat(5,1fr)}}
@media(max-width:1000px){.aw-grid{grid-template-columns:repeat(4,1fr)}}
/* Drop to 3 across at 900, not 760. Four columns on a portrait-ish tablet leaves each card
   only ~163px wide, and at that width the longer names ("Gabby Piantadosi") wrap to a second
   line while most do not -- so the row heights go ragged. Three columns gives ~222px, every
   name fits on one line, and the wall stays flush. */
@media(max-width:900px){.aw-grid{grid-template-columns:repeat(3,1fr)}}
@media(max-width:760px){.aw-grid{grid-template-columns:repeat(3,1fr);gap:11px}
  /* 2px less padding and a 1px smaller name than desktop, so the two-line reserve
     comes down to match -- see the min-height note on .aw-meta above. */
  .aw-meta{padding:10px 10px 12px;min-height:73px}.aw-meta b{font-size:12px}
  .aw-logos{top:6px;right:6px;gap:4px}
  .aw-ph .aw-logos img{width:30px;height:30px;padding:4px}
  .aw-ph .aw-logos img + img{width:23px;height:23px;padding:3px}
  .aw-ph .aw-logos img.wide{width:42px;padding:4px 5px}
  .aw-ph .aw-logos img + img.wide{width:34px;padding:3px 4px}}
/* Two across rather than one on phones: these are portrait cards, so a single column
   makes each one nearly a full screen tall and the wall stops reading as a wall.
   600 rather than 460: three columns below that leaves each card under ~165px, and at that
   width the longest subtitles ("UNC Field Hockey / Team USA") take a third line while most
   take two — which is what makes a row go ragged. */
@media(max-width:600px){.aw-grid{grid-template-columns:repeat(2,1fr)}}
/* Under ~385px (iPhone SE, older Androids) even two columns only yields ~150px cards, and a
   few subtitles genuinely need three lines there — no amount of tracking fixes it. Reserve
   the third line for everyone so the wall stays flush instead of letting those cards stand
   proud of their neighbours. */
@media(max-width:385px){.aw-meta{min-height:88px}}
@media(max-width:460px){.aw-ph.none i{font-size:26px}
  /* cards are ~170px wide here, so the chips go back up — proportionally the same as on
     a 180px desktop card, and any smaller stops being identifiable at arm's length */
  .aw-logos{top:7px;right:7px;gap:5px}
  .aw-ph .aw-logos img{width:34px;height:34px;padding:5px}
  .aw-ph .aw-logos img + img{width:26px;height:26px;padding:4px}
  .aw-ph .aw-logos img.wide{width:48px;padding:5px 6px}
  .aw-ph .aw-logos img + img.wide{width:38px;padding:4px 5px}}

/* ============================================================
   TEST IN — two entry tests, side by side
   Josh, Aug 19: "Step one Reuired should be Test in. New ahtletes do a gait analysis and
   veteran (returnng) athletes do effective range test ins, show a booking link for both."
   Replaces the single .entry-card (main + dark price panel), which could only ever describe
   one route. That block's CSS at ~1288 is now unused by any page.

   The two cards carry different amounts of copy, so .ti-foot uses margin-top:auto to pin
   both buttons to the bottom edge — without it the shorter card's button floats mid-card
   and the pair reads as misaligned.

   .price-lab is declared sky (#63B7DE) for use on the old DARK panel. On these white cards
   that is 2.3:1 at 11px/800, so it is re-pointed to #17719C here — the same value the alumni
   eyebrow needed when that page went white.
   ============================================================ */
.ti-grid{display:grid;grid-template-columns:1fr 1fr;gap:var(--s-4);align-items:stretch}
.ti{display:flex;flex-direction:column;background:var(--paper-2);
    border:1px solid var(--line-l);border-radius:var(--r-lg);
    box-shadow:var(--sh-2);padding:var(--s-5) var(--s-4)}
.ti .entry-tag{align-self:flex-start}
.ti h3{font-family:var(--display);text-transform:uppercase;letter-spacing:-.01em;
    font-size:clamp(28px,3vw,38px);line-height:1;margin:0 0 var(--s-2)}
.ti .sub{font-size:15.5px;line-height:1.65;color:#3A3E47;margin:0 0 var(--s-3)}
.ti .entry-steps{margin:0 0 var(--s-4)}
.ti-foot{margin-top:auto;padding-top:var(--s-3);border-top:1px solid var(--line-l);
    display:flex;align-items:flex-end;justify-content:space-between;gap:var(--s-3);flex-wrap:wrap}
.ti-price{display:flex;flex-direction:column;gap:3px}
.ti-price .price-lab{color:#17719C;margin:0}
.ti-price b{font-family:var(--display);font-size:38px;line-height:1;letter-spacing:-.02em;
    font-variant-numeric:tabular-nums}
.ti-note{margin:var(--s-4) 0 0;font-size:14.5px;color:#4A4E57;line-height:1.6;max-width:640px}
@media(max-width:900px){
  .ti-grid{grid-template-columns:1fr;gap:var(--s-3)}
  .ti{padding:var(--s-4) var(--s-3)}
  .ti-foot .btn{width:100%;justify-content:center}
}

/* ============================================================================
   THE CURRENCY / FIRST CYCLE / BY SPORT  (programs.html)
   Josh, Aug 19: "the currency of an athlete is the amount of space you can cover
   or create ... build it out by sport so parents can see exactly how what we do
   can change their kids performance in each sport."
   ========================================================================== */

/* --- The currency (dark) ------------------------------------------------- */
.cur-grid{display:grid;grid-template-columns:1.35fr .65fr;gap:var(--s-6);align-items:start}
.cur-h2{font-family:var(--display);font-weight:400;letter-spacing:.015em;line-height:.94;
  text-transform:uppercase;font-size:clamp(38px,5vw,64px);margin-top:var(--s-2)}
.cur-h2 em{font-style:normal;color:var(--green)}
.cur-lead{font-size:clamp(19px,1.7vw,23px);line-height:1.5;margin-top:var(--s-3)}
.cur-body{color:var(--muted-d);margin-top:var(--s-2);max-width:62ch}
/* The figure is the same claim as method.html's --- keep the two in step if the number moves. */
.cur-fig{border-left:2px solid var(--green);padding-left:var(--s-3)}
.cur-big{font-family:var(--display);font-weight:400;font-size:clamp(64px,7vw,104px);
  line-height:.88;letter-spacing:.01em;font-variant-numeric:tabular-nums}
.cur-big span{font-size:.5em}
.cur-cap{color:var(--muted-d);font-size:15px;line-height:1.55;margin-top:var(--s-2)}

.cur-tiles{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s-3);margin-top:var(--s-6)}
.cur-tile{background:var(--ink-2);border:1px solid var(--line-d);border-radius:var(--r-lg);
  padding:var(--s-4) var(--s-3);display:flex;flex-direction:column}
.cur-t-val{font-family:var(--display);font-weight:400;font-size:46px;line-height:1;
  letter-spacing:.015em;color:var(--green);font-variant-numeric:tabular-nums}
.cur-t-lab{font-family:var(--body);font-size:11px;font-weight:700;letter-spacing:.14em;
  text-transform:uppercase;color:var(--sky);margin-top:10px}
.cur-tile p{color:#fff;font-size:15.5px;line-height:1.6;margin-top:var(--s-2)}
.cur-t-who{margin-top:auto;padding-top:var(--s-3);color:var(--muted-d);font-size:12.5px;
  letter-spacing:.02em}
.cur-note{margin-top:var(--s-4);color:var(--muted-d);font-size:13px;max-width:80ch}
.cur-note a{color:var(--sky);text-decoration:underline;text-underline-offset:3px}

/* --- First cycle (light) ------------------------------------------------- */
.fc-grid{display:grid;grid-template-columns:1fr 1fr;gap:var(--s-4);align-items:stretch}
.fc{display:flex;flex-direction:column;background:var(--paper);border:1px solid var(--line-l);
  border-radius:var(--r-lg);box-shadow:var(--sh-2);padding:var(--s-5) var(--s-4)}
.fc-head{border-bottom:1px solid var(--line-l);padding-bottom:var(--s-3)}
.fc-tag{display:inline-block;font-family:var(--body);font-size:11px;font-weight:700;
  letter-spacing:.14em;text-transform:uppercase;color:var(--accent-deep)}
.fc-head h3{font-family:var(--display);font-weight:400;text-transform:uppercase;
  font-size:38px;line-height:.94;letter-spacing:.015em;margin-top:6px}
.fc-rows{margin-top:var(--s-3)}
/* Label left / number right on one baseline. Tabular figures so the decimals stack,
   which is the whole point of showing before-and-afters as a column. */
.fc-row{display:flex;align-items:baseline;justify-content:space-between;gap:var(--s-2);
  padding:11px 0;border-bottom:1px dashed var(--line-l)}
.fc-k{font-family:var(--body);font-size:13px;font-weight:700;letter-spacing:.06em;
  text-transform:uppercase;color:var(--muted)}
.fc-v{font-family:var(--display);font-weight:400;font-size:26px;line-height:1;
  letter-spacing:.015em;font-variant-numeric:tabular-nums;white-space:nowrap}
.fc-space{margin-top:var(--s-3);font-size:15.5px;line-height:1.6;
  background:rgba(140,198,63,.13);border-left:3px solid var(--green-ink);
  border-radius:0 var(--r-md) var(--r-md) 0;padding:var(--s-2)}
.fc-src{margin-top:auto;padding-top:var(--s-3)}
.fc-src-lab{display:block;font-family:var(--body);font-size:11px;font-weight:700;
  letter-spacing:.14em;text-transform:uppercase;color:var(--muted);margin-bottom:10px}
.fc-src ul{list-style:none}
.fc-src li{font-size:14px;line-height:1.55;color:var(--muted);padding:9px 0;
  border-top:1px solid var(--line-l)}
.fc-src li b{color:var(--ink)}
.fc-src li em{font-style:normal;font-weight:700;color:var(--accent-deep)}
.fc-note{margin-top:var(--s-4);font-size:14px;line-height:1.6;color:var(--muted);max-width:90ch}
.fc-note em{font-style:italic}

/* --- By sport ------------------------------------------------------------ */
.sp-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s-3)}
.sp{background:var(--paper-2);border:1px solid var(--line-l);border-radius:var(--r-lg);
  padding:var(--s-4) var(--s-3);display:flex;flex-direction:column;
  transition:box-shadow .25s,transform .25s}
.sp:hover{box-shadow:var(--sh-2);transform:translateY(-3px)}
.sp h3{font-family:var(--display);font-weight:400;text-transform:uppercase;font-size:28px;
  line-height:.96;letter-spacing:.015em}
.sp-space{font-size:15px;line-height:1.6;color:var(--ink);margin-top:10px}
.sp-pillar{margin-top:auto;padding-top:var(--s-3)}
.sp-pillar span{display:block;font-family:var(--body);font-size:10.5px;font-weight:700;
  letter-spacing:.14em;text-transform:uppercase;color:var(--muted)}
.sp-pillar b{display:block;font-size:14px;font-weight:700;color:var(--accent-deep);margin-top:4px}
.sp-proof{margin-top:12px;padding-top:12px;border-top:1px solid var(--line-l);
  font-size:13px;line-height:1.5;color:var(--muted)}
.sp-proof b{color:var(--ink)}

@media(max-width:1000px){
  .sp-grid{grid-template-columns:repeat(2,1fr)}
  .cur-tiles{grid-template-columns:1fr}
}
@media(max-width:900px){
  .cur-grid{grid-template-columns:1fr;gap:var(--s-4)}
  .cur-fig{border-left:0;border-top:2px solid var(--green);padding-left:0;padding-top:var(--s-3)}
  .fc-grid{grid-template-columns:1fr;gap:var(--s-3)}
  .fc{padding:var(--s-4) var(--s-3)}
}
@media(max-width:620px){
  .sp-grid{grid-template-columns:1fr}
  .fc-v{font-size:22px}
  .fc-head h3{font-size:32px}
}

/* --- Expanded program blocks (programs.html) ----------------------------- */
/* Josh, Aug 19: "we need more information about each program especially young guns."
   .pmore is the extra prose, .psess the Young Guns session walk-through, .pnot the
   "what it isn't" reassurance, .pfacts the scannable strip for a parent who won't
   read any of it. Muted so .desc still reads as the lead paragraph. */
.pmore{color:var(--muted);font-size:16px;line-height:1.65;margin-top:var(--s-2);max-width:62ch}
.psess{margin-top:var(--s-3);background:var(--paper-2);border:1px solid var(--line-l);
  border-radius:var(--r-lg);padding:var(--s-3)}
.psess-head{font-family:var(--body);font-size:11px;font-weight:700;letter-spacing:.14em;
  text-transform:uppercase;color:var(--accent-deep)}
.psess ol{margin:12px 0 0;padding-left:1.15em}
.psess li{font-size:15px;line-height:1.55;color:var(--muted);padding:6px 0}
.psess li::marker{font-weight:700;color:var(--accent-deep)}
.psess li b{color:var(--ink)}
.pnot{margin-top:var(--s-3);font-size:15px;line-height:1.6;color:var(--muted);
  border-left:3px solid var(--green-ink);padding-left:var(--s-2)}
.pnot b{color:var(--ink)}
.pfacts{display:flex;flex-wrap:wrap;gap:var(--s-3) var(--s-4);margin-top:var(--s-3);
  padding-top:var(--s-3);border-top:1px solid var(--line-l)}
.pfacts span{display:block;font-family:var(--body);font-size:10.5px;font-weight:700;
  letter-spacing:.14em;text-transform:uppercase;color:var(--muted)}
.pfacts b{display:block;font-size:15px;font-weight:700;margin-top:3px}
@media(max-width:620px){
  .pfacts{gap:var(--s-2) var(--s-3)}
  .pmore{font-size:15.5px}
}

/* ===== METHOD HERO ========================================================
   Josh, Sept 1: "I want it to look more like the coaches hero please not like
   the main home page hero." So this page borrows .coach-hero wholesale — same
   lighting rig, same centred crest, same medallion rail — rather than defining
   a second bespoke hero. Every component it uses (.ch-crest, .ch-title,
   .emblem, .crest-rail, .crest) is already global in this file, and only
   .coach-hero .statrail is ancestor-scoped, which this hero does not use.

   The medallion rail must carry id="statrail": app.js observes that id to add
   .in, and .crest-rail.in is what drives the SVG rings from dashoffset to 0.
   Without the id the numbers still count but the rings never draw.
   ========================================================================== */
.method-hero .ch-sub{margin-top:8px}

/* ===== FOUR PILLARS — combined claim + pillars ==============================
   Josh, Sept 1: "Lets combine the four pillars and 25-30% increase into one
   section... I would also like that section to be revised and look much much
   better and more unique to the eye."

   So the old .man-grid intro and the old stacked .mrow list are merged into one
   dark band: the claim and its number sit across the top, the four pillars run
   underneath as photo cards in a 2x2.

   The device that makes it specific to KPM rather than a generic card grid is
   .fp-tier — four segments per card, N filled, so each pillar shows how deep in
   the stack it sits. That is the page's own argument ("each pillar builds on the
   one before it") drawn rather than asserted.
   ========================================================================== */
.fp-head{display:grid;grid-template-columns:1.25fr .75fr;gap:var(--s-6);
  align-items:end;padding-bottom:var(--s-6);border-bottom:1px solid var(--line-d)}
.fp-head h2{font-family:var(--display);text-transform:uppercase;
  font-size:clamp(36px,6vw,76px);line-height:.92;letter-spacing:.01em;margin:var(--s-2) 0 var(--s-3)}
.fp-head p{color:rgba(255,255,255,.76);font-size:17px;max-width:56ch}
.fp-head p + p{margin-top:15px}
.fp-claim{text-align:right}
.fp-claim .big{font-family:var(--display);font-size:clamp(58px,8.5vw,118px);line-height:.86;
  letter-spacing:-.02em;color:var(--accent);font-variant-numeric:tabular-nums}
.fp-claim .cap{color:var(--muted-d);font-size:13.5px;line-height:1.55;margin-top:var(--s-2);
  margin-left:auto;max-width:34ch}

.fp-grid{display:grid;grid-template-columns:1fr 1fr;gap:var(--s-4);margin-top:var(--s-6)}
.fp{position:relative;display:flex;flex-direction:column;overflow:hidden;
  border:1px solid var(--line-d);border-radius:var(--r-lg);background:rgba(255,255,255,.032);
  transition:background .35s ease,transform .45s cubic-bezier(.16,1,.3,1),border-color .35s}
.fp:hover{background:rgba(255,255,255,.06);border-color:rgba(255,255,255,.22);transform:translateY(-4px)}
.fp-ph{position:relative;aspect-ratio:16/10;overflow:hidden;background:#1B1E24}
.fp-ph img{width:100%;height:100%;object-fit:cover;display:block;
  transition:transform .7s cubic-bezier(.16,1,.3,1)}
.fp:hover .fp-ph img{transform:scale(1.05)}
/* the number sits inside the photo, over the gradient — .fp-ph clips (it has
   overflow:hidden for the hover zoom), so this cannot use a negative offset */
.fp-no{position:absolute;left:20px;bottom:12px;z-index:2;font-family:var(--display);
  font-size:clamp(54px,7vw,86px);line-height:.8;color:#fff;letter-spacing:-.02em;
  text-shadow:0 6px 26px rgba(0,0,0,.75)}
.fp-ph::after{content:"";position:absolute;inset:0;
  background:linear-gradient(180deg,transparent 45%,rgba(11,13,16,.82) 100%)}
.fp-body{padding:26px 24px 24px;display:flex;flex-direction:column;flex:1}
.fp-body h3{font-family:var(--display);text-transform:uppercase;
  font-size:clamp(21px,2.2vw,28px);line-height:1.02;margin-bottom:12px}
.fp-body p{color:rgba(255,255,255,.78);font-size:15.5px;line-height:1.62}
.fp-foot{margin-top:auto;padding-top:20px}
.fp-tag{font-family:var(--mono);font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--muted-d);display:block;margin-bottom:12px}
/* depth-in-the-stack indicator — N of 4 segments lit */
.fp-tier{display:flex;gap:5px;align-items:center}
.fp-tier i{flex:1 1 0;height:3px;border-radius:2px;background:rgba(255,255,255,.13);
  transition:background .4s ease}
.fp-tier i.on{background:var(--accent)}
.fp:hover .fp-tier i.on{background:var(--sky)}
.fp-tier b{font-family:var(--mono);font-size:10px;letter-spacing:.1em;color:var(--muted-d);
  font-weight:500;margin-left:8px;white-space:nowrap}

@media(max-width:980px){
  .fp-head{grid-template-columns:1fr;gap:var(--s-4);align-items:start}
  .fp-claim{text-align:left}
  .fp-claim .cap{margin-left:0}
}
@media(max-width:720px){
  .fp-grid{grid-template-columns:1fr}
}

/* ===== MEASURED RESISTANCE, MEASURED REPS =================================
   Josh, Sept 1: this section "should read Measured resistance, Measured Reps"
   and "look more alive too". The lift comes from breaking the three equal cards
   into one bold feature band plus two supporting cards — asymmetry reads as
   designed rather than tabulated — and from setting the term Josh gave us,
   Short Term Fast Twitch Potentiation, as the loudest type on the page.
   ========================================================================== */
.mr-feature{position:relative;overflow:hidden;border-radius:var(--r-lg);
  background:var(--ink);color:#fff;padding:clamp(30px,4.4vw,54px);margin-top:var(--s-5);
  display:grid;grid-template-columns:1.05fr .95fr;gap:clamp(24px,3.6vw,52px);align-items:center}
.mr-feature::before{content:"";position:absolute;z-index:0;width:62%;aspect-ratio:1;
  right:-16%;top:-42%;border-radius:50%;pointer-events:none;
  background:radial-gradient(circle,rgba(42,157,214,.42),transparent 66%)}
.mr-feature::after{content:"";position:absolute;z-index:0;width:46%;aspect-ratio:1;
  left:-14%;bottom:-56%;border-radius:50%;pointer-events:none;
  background:radial-gradient(circle,rgba(139,197,63,.30),transparent 68%)}
.mr-feature > *{position:relative;z-index:1}
.mr-lab{font-family:var(--mono);font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--sky);margin-bottom:16px}
.mr-term{font-family:var(--display);text-transform:uppercase;line-height:.9;
  font-size:clamp(34px,5.2vw,66px);letter-spacing:.005em}
.mr-term em{font-style:normal;color:var(--accent);display:block}
.mr-feature p{color:rgba(255,255,255,.82);font-size:16.5px;line-height:1.65}
.mr-feature p + p{margin-top:14px}

.mr-grid{display:grid;grid-template-columns:1fr 1fr;gap:var(--s-4);margin-top:var(--s-4)}
.mr-card{background:var(--paper-2);border:1px solid var(--line-l);border-radius:var(--r-lg);
  padding:30px 28px;position:relative;overflow:hidden;
  transition:box-shadow .3s,transform .3s}
.mr-card:hover{box-shadow:var(--sh-2);transform:translateY(-3px)}
.mr-card::before{content:"";position:absolute;left:0;top:0;height:3px;width:0;
  background:var(--accent);transition:width .45s cubic-bezier(.16,1,.3,1)}
.mr-card:hover::before{width:100%}
.mr-card .cn{font-family:var(--mono);font-size:11px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--accent-deep)}
.mr-card h4{font-family:var(--display);text-transform:uppercase;font-size:23px;
  line-height:1.02;margin:16px 0 12px}
.mr-card p{font-size:15px;line-height:1.62;color:#4A4E57}

@media(max-width:900px){
  .mr-feature{grid-template-columns:1fr;gap:22px}
  .mr-grid{grid-template-columns:1fr}
}

/* ===== ATHLETIC COMPOSITE SCORE ===========================================
   Josh, Sept 1: "that should be a big selling point to we can quantify your
   athleticism. We can put a number on how athletic you are."

   So it gets its own band rather than a line in a stat rail. It is struck as a
   LIGHT panel inside the dark #proof section on purpose — the inversion is what
   makes it the loudest thing in that section without needing more type size.
   ========================================================================== */
.acs{position:relative;overflow:hidden;display:grid;grid-template-columns:.92fr 1.08fr;
  gap:clamp(24px,4vw,56px);align-items:center;background:var(--paper);color:var(--ink);
  border-radius:var(--r-lg);padding:clamp(30px,4.4vw,54px);margin-top:var(--s-5);
  box-shadow:0 30px 70px -40px rgba(0,0,0,.9)}
.acs::before{content:"";position:absolute;z-index:0;width:44%;aspect-ratio:1;
  right:-12%;bottom:-58%;border-radius:50%;pointer-events:none;
  background:radial-gradient(circle,rgba(42,157,214,.20),transparent 68%)}
.acs > *{position:relative;z-index:1}
.acs-lab{font-family:var(--mono);font-size:10.5px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--accent-deep);margin-bottom:14px}
.acs h3{font-family:var(--display);text-transform:uppercase;line-height:.9;
  font-size:clamp(32px,5vw,62px);letter-spacing:.005em}
.acs h3 em{font-style:normal;color:var(--accent-deep);display:block}
.acs p{font-size:16.5px;line-height:1.65;color:#3A3E47}
.acs p + p{margin-top:13px}
@media(max-width:900px){.acs{grid-template-columns:1fr;gap:20px}}

/* Footer hours. Josh, Sept 1: "2pm to 7:30 Pm M-F and Saturday 8:30am to 10am".
   Shown on every page AND declared in the LocalBusiness schema on index.html — Google
   weighs opening hours for local ranking, and the two must agree. Change both together. */
.foot-hours{font-size:13.5px;line-height:1.6;color:var(--muted-d);margin:2px 0 4px}
.foot-hours b{display:block;font-family:var(--mono);font-size:10.5px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--sky);font-weight:700;margin-bottom:4px}

/* Service area note. Sits in the contact card but must NOT inherit .contact-note's
   uppercase + wide letter-spacing — that treatment is for one short line, and turns a
   full paragraph of town names into an unreadable block. */
.svc-note{
  margin-top:18px;padding-top:16px;border-top:1px solid var(--line-d);
  font-size:14px;line-height:1.62;color:var(--muted-d);text-transform:none;letter-spacing:normal
}
.svc-note b{
  display:block;font-family:var(--display);text-transform:uppercase;font-size:15px;
  letter-spacing:.01em;color:#fff;margin-bottom:7px
}
.svc-note a{color:var(--sky);text-decoration:underline;text-underline-offset:2px}
.svc-note a:hover{color:#fff}

/* ===== ENQUIRY FORM ========================================================
   Josh, Sept 1: "Yes we should do a lead form lets figure it out." Submissions
   go to Josh@klemicperformancemethod.com.

   This is the site's ONLY form, so everything here is written from scratch
   rather than inheriting. It sits inside .contact-grid on the dark #contact
   section, so every colour is a dark-surface value.

   Netlify picks the form up from the markup at deploy time — the hidden
   form-name input and data-netlify="true" are both required, and the honeypot
   field must stay visually hidden but NOT display:none for bots to take it.
   ========================================================================== */
.lead-form{display:grid;gap:14px;margin-top:var(--s-4)}
.lf-row{display:grid;grid-template-columns:1fr 1fr;gap:14px}
.lf-field{display:flex;flex-direction:column;gap:6px}
.lf-field label{
  font-family:var(--mono);font-size:10.5px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--sky)
}
.lead-form input,.lead-form select,.lead-form textarea{
  font-family:var(--body);font-size:15px;color:#fff;
  background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.18);
  border-radius:8px;padding:11px 13px;width:100%;
  transition:border-color .2s,background .2s
}
.lead-form textarea{resize:vertical;min-height:82px;line-height:1.55}
.lead-form input::placeholder,.lead-form textarea::placeholder{color:rgba(255,255,255,.38)}
.lead-form input:hover,.lead-form select:hover,.lead-form textarea:hover{
  border-color:rgba(255,255,255,.32)
}
.lead-form input:focus,.lead-form select:focus,.lead-form textarea:focus{
  outline:2px solid var(--sky);outline-offset:2px;
  border-color:var(--sky);background:rgba(255,255,255,.09)
}
/* the native dropdown paints its list in the OS theme, so the options need an
   explicit dark background or they render white-on-white on some platforms */
.lead-form select option{background:var(--ink);color:#fff}
.lead-form button{
  font-family:var(--body);font-weight:700;font-size:14.5px;letter-spacing:.01em;
  cursor:pointer;border:0;border-radius:var(--r-pill,999px);padding:14px 26px;
  background:var(--accent-deep);color:#fff;justify-self:start;margin-top:2px;
  transition:background .25s,transform .25s
}
.lead-form button:hover{background:#14607F;transform:translateY(-1px)}
.lead-form button:focus-visible{outline:3px solid #fff;outline-offset:3px}
.lf-note{font-size:13px;color:var(--muted-d);line-height:1.55}
/* honeypot: off-screen, not display:none — a bot must still be able to fill it */
.lf-bot{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
@media(max-width:620px){ .lf-row{grid-template-columns:1fr} }

/* Test-In detail: the seven tests, and the score they roll into.
   Added Sept 1 — Josh: "I would rather have them be hit with a more detailed report."
   The Test In section is the stop between "Book a Gait Analysis" and the checkout, so it has to
   answer "what am I actually buying" before it asks for money. Every test named here came from
   Josh directly; the composite score is the deliverable they walk away with. */
.ti-tests{margin-top:var(--s-3);padding-top:var(--s-3);border-top:1px solid var(--line-l)}
.ti-tests .lab{
  font-family:var(--mono);font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--accent-deep);display:block;margin-bottom:10px
}
.ti-chips{display:flex;flex-wrap:wrap;gap:6px}
.ti-chips span{
  font-family:var(--mono);font-size:11px;letter-spacing:.04em;
  background:var(--paper-2);border:1px solid var(--line-l);border-radius:5px;
  padding:5px 9px;color:#3A3E47;white-space:nowrap
}
.ti-score{
  margin-top:12px;font-size:14px;line-height:1.55;color:#3A3E47
}
.ti-score b{color:var(--ink)}


/* Ghost button ON the green CTA band. The stock .btn-ghost-l border is --line-l, which is a
   13%-opacity ink line: 1.57:1 against --green and effectively an invisible button. Inside
   .cta it takes a solid --ink border instead (8.76:1). Audit fix, Sept 1. */
.cta .btn-ghost-l{border-color:var(--ink);border-width:1.5px}
.cta .btn-ghost-l:hover{background:var(--ink);color:var(--green)}
/* ===== SPORT JUMP NAV =======================================================
   Audit item 1 — the most-flagged finding, raised independently by five reviewers.
   programs.html carries twelve sport sections with real copy, and a search of every
   link on all eight pages for any of their names returned ZERO results: no menu item,
   no footer link, no jump list. The section's own heading said "Find your athlete's
   sport" with nothing to click.

   This is a <nav> of real anchors, so it is navigation for a reader AND a crawl path
   for Google — the two problems the audit raised were the same problem.
   ========================================================================== */
.sport-nav{margin:var(--s-4) 0 var(--s-5);padding-top:var(--s-3);border-top:1px solid var(--line-l)}
.sport-nav .lab{
  font-family:var(--mono);font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--accent-deep);display:block;margin-bottom:12px
}
.sport-nav ul{list-style:none;padding:0;margin:0;display:flex;flex-wrap:wrap;gap:8px}
.sport-nav a{
  display:inline-block;font-family:var(--body);font-size:13.5px;font-weight:600;
  text-decoration:none;color:var(--ink);background:var(--paper-2);
  border:1px solid var(--line-l);border-radius:var(--r-pill,999px);padding:8px 15px;
  transition:background .22s,border-color .22s,transform .22s
}
.sport-nav a:hover{background:var(--ink);color:#fff;border-color:var(--ink);transform:translateY(-2px)}
@media(max-width:520px){ .sport-nav a{font-size:13px;padding:7px 13px} }

/* Breadcrumb home link. The crumb read as navigation but nothing in it was clickable.
   Inherits the crumb's mono/uppercase treatment; only the interaction is added. */
.crumb a{color:inherit;text-decoration:none;border-bottom:1px solid transparent;transition:color .2s,border-color .2s}
.crumb a:hover{color:var(--accent);border-bottom-color:currentColor}

/* Back-to-top: it fades to opacity:0 but stayed in the tab order, so after using it focus was
   stranded on an invisible control and the next Tab jumped to the footer, yanking the page back
   down. visibility:hidden removes it from the tab order; the transition keeps the fade. */
.totop{visibility:hidden;transition:opacity .3s,transform .3s,visibility .3s}
.totop.show,.totop.on,.totop:focus-visible{visibility:visible}

/* ===== ALUMNI SPORT FILTER ==================================================
   Audit item 10 — 103 cards and no way for a wrestling parent to find the one
   wrestler. Every card carries data-sport (derived from its own roster URL, not
   guessed); these buttons just hide the rest.

   Real <button>s with aria-pressed, not links: this filters in place, it does not
   navigate. The live count is announced so a screen-reader user hears the result.
   ========================================================================== */
.aw-filter{margin:0 0 var(--s-5)}
.aw-filter .lab{
  font-family:var(--mono);font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--accent-deep);display:block;margin-bottom:12px
}
.aw-filter .chips{display:flex;flex-wrap:wrap;gap:8px;align-items:center}
.aw-filter button{
  font-family:var(--body);font-size:13.5px;font-weight:600;cursor:pointer;
  color:var(--ink);background:var(--paper-2);border:1px solid var(--line-l);
  border-radius:var(--r-pill,999px);padding:8px 15px;
  transition:background .2s,border-color .2s,color .2s,transform .2s
}
.aw-filter button:hover{border-color:var(--ink);transform:translateY(-1px)}
.aw-filter button[aria-pressed="true"]{background:var(--ink);color:#fff;border-color:var(--ink)}
.aw-filter button .n{opacity:.55;font-weight:500;margin-left:5px;font-variant-numeric:tabular-nums}
.aw-filter .count{
  font-size:13px;color:var(--muted);margin-top:12px;font-variant-numeric:tabular-nums
}
.aw.is-hidden{display:none}
@media(max-width:520px){ .aw-filter button{font-size:13px;padding:7px 12px} }

/* ===== PROGRAMS PAGE — layout and the entry rule ===========================
   Josh, Sept 1: the programs page "is the weakest page by far aestically" and
   "make sure it is obvious to get into the program you must buy a gait for a new
   athlete and effective range for an existing athlete".

   THE AESTHETIC PROBLEM, measured: a .pblock row runs ~1613px tall because the
   copy is long, while .media is a 1:1 square ~502px. With align-items:center the
   photo floated with ~550px of dead paper above AND below it — six times down the
   page. Making the media sticky fills that void with the photograph and keeps it
   beside the paragraph the reader is actually on.
   ========================================================================== */
.pblock{align-items:start}
/* 4/5, not the original 1/1. These photos are natively 4:5 portraits, so a 4:5 frame crops
   NOTHING (the square was discarding 20% of the height) and stands 630px instead of 504px,
   which closes most of the gap beside the long copy.
   position:sticky was tried here first and reverted: #programs sets overflow:hidden to clip its
   oversized animated ::after layer, and overflow:hidden on an ancestor disables sticky. Swapping
   it for clip-path DID restore sticky, but the unclipped layer then widened the page to 1405px
   in a 1280px window. Do not retry that without dealing with the ::after first. */
.pblock .media{aspect-ratio:4/5}

/* The entry rule, stated once and loudly at the top of the programs list. */
.entry-rule{
  display:grid;grid-template-columns:1fr 1fr;gap:0;
  border:1.5px solid var(--ink);border-radius:var(--r-lg);overflow:hidden;
  margin:var(--s-4) 0 var(--s-6);background:var(--paper-2)
}
.entry-rule > div{padding:26px 28px}
.entry-rule > div + div{border-left:1.5px solid var(--ink)}
.entry-rule .who{
  font-family:var(--mono);font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--accent-deep);display:block;margin-bottom:9px
}
.entry-rule h4{
  font-family:var(--display);text-transform:uppercase;font-size:clamp(20px,2.4vw,27px);
  line-height:1.02;margin-bottom:9px
}
.entry-rule p{font-size:14.5px;line-height:1.6;color:#4A4E57;margin-bottom:16px}
.entry-rule .btn{font-size:13.5px;padding:11px 20px}
.entry-rule-note{
  font-size:15px;line-height:1.6;color:var(--ink);margin:0 0 var(--s-3);
  padding-left:15px;border-left:3px solid var(--accent)
}
@media(max-width:760px){
  .entry-rule{grid-template-columns:1fr}
  .entry-rule > div + div{border-left:0;border-top:1.5px solid var(--ink)}
}

/* THE PER-PROGRAM TEST BLOCK. Josh, Sept 1: whatever program they pick, the first thing they
   do is a test — a gait analysis if they are new, effective range measurements if they have been
   through a block. Every one of the six programs now states both, right above its own button.
   .ew-test used to be a plain <span>; it is now the link that takes them to #start, so it needs
   to look and behave like one. */
.ew-head{margin-top:var(--s-3)}
.ew{background:var(--paper-2);border:1px solid var(--line-l);border-radius:10px;padding:18px 18px 20px;
  transition:border-color .25s,box-shadow .25s}
.ew:hover{border-color:var(--ink);box-shadow:var(--sh-1)}
a.ew-test{color:var(--accent-deep);text-decoration:underline;text-underline-offset:3px;
  font-weight:700;transition:color .2s}
a.ew-test:hover{color:var(--ink)}
@media(max-width:620px){ .ew-grid{grid-template-columns:1fr} }

/* ===== PROGRAMS: BREAKING THE SLAB =========================================
   Measured at 1280px: #programs runs 7,913px — 45% of the whole page — and flows
   straight into #by-sport on the SAME background, giving 10,200px of unbroken
   identical paper. Over half the page in one flat tone with nothing for the eye
   to catch. Six near-identical rows separated only by a 1px hairline read as one
   endless scroll rather than six choices.

   Fix: each program becomes a discrete white card on the paper ground, with real
   gaps between them. Nothing is hidden and no copy changes — the same content now
   has edges, so the section reads as six objects instead of one slab.

   The numeral is a CSS counter, so it needs no markup and can never fall out of
   step with the blocks. It also makes the heading literal: "Six ways in", and the
   reader can see which one they are on. Same big-numeral motif already used by the
   method pillars (01-04) and the cycle steps.
   ========================================================================== */
#programs{counter-reset:pgm}
#programs .pblock{
  counter-increment:pgm;
  border-top:0;
  border:1px solid var(--line-l);
  border-radius:var(--r-lg);
  background:var(--paper-2);
  padding:40px 44px 44px;
  margin-bottom:24px;
  box-shadow:0 1px 2px rgba(22,23,26,.03);
  transition:box-shadow .3s ease, border-color .3s ease;
}
#programs .pblock:hover{box-shadow:var(--sh-2);border-color:var(--rule-2,rgba(22,23,26,.22))}
#programs .pblock:first-of-type{padding-top:40px}
#programs .pblock:last-of-type{margin-bottom:0}

/* the numeral sits above the age label, in the text column (always the 2nd child,
   even in .rev blocks — those flip visually via direction, not DOM order) */
#programs .pblock > div:nth-child(2)::before{
  content:counter(pgm,decimal-leading-zero);
  display:block;
  font-family:var(--display);
  font-size:clamp(34px,4.2vw,54px);
  line-height:.8;
  letter-spacing:.01em;
  color:rgba(22,23,26,.14);
  margin-bottom:14px;
}
@media(max-width:900px){
  #programs .pblock{padding:28px 24px 32px;margin-bottom:18px}
}

/* Light-surface variant of the coaches-page expander, for the program cards.
   The .cx-* pattern is reused deliberately — app.js already drives it with proper
   aria-expanded/aria-controls and a measured height animation, and the first audit
   confirmed that implementation is correct. Only the colours change here; the
   originals are written for the dark coaches section. */
#programs .pgm-more{max-width:none}
#programs .pgm-more p{color:var(--muted);font-size:16px;line-height:1.65;margin-top:var(--s-2);max-width:62ch}
#programs .pgm-toggle{
  margin:18px 0 24px;border:1px solid var(--line-l);color:var(--ink);
  background:var(--paper);
}
#programs .pgm-toggle:hover{border-color:var(--accent-deep);background:rgba(58,166,214,.07)}
#programs .pgm-toggle .ico::before,
#programs .pgm-toggle .ico::after{background:var(--accent-deep)}
#programs .pgm-more.anim{overflow:hidden;transition:height .42s cubic-bezier(.16,1,.3,1)}
#programs .pgm-more[hidden]{display:none}

/* Privacy line under the lead form. Audit round 2: the form collects a minor's age and a
   parent's phone number and said nothing about what happens to either. */
.lf-privacy{margin-top:16px;font-size:13px;line-height:1.6;color:var(--muted-d);max-width:52ch}
.lf-privacy a{color:var(--sky);text-decoration:underline;text-underline-offset:2px}
.lf-privacy a:hover{color:#fff}

/* ===== MOBILE TAP TARGETS AND THE iOS ZOOM TRAP ============================
   Found by driving the real site at 375x812, not by reading CSS.

   1. iOS Safari ZOOMS THE WHOLE PAGE when a form field smaller than 16px is
      focused. Every field on the enquiry form measured 15px, so a parent tapping
      "Name" got a lurch and a zoom, then had to pinch back out — on every field,
      on the site's only lead form. 16px is the documented threshold.
   2. The menu button measured 18x24. It is the most-tapped control on the site
      and it was less than a fifth of the 44x44 both Apple and Google specify.
   3. Filter chips (32px), the two test links inside each program card (22px) and
      the footer/crumb links (14-20px) were all under 44 tall.
   Nothing here changes how anything looks on desktop.
   ========================================================================== */

/* 1. never let a form field trigger the iOS zoom */
input, select, textarea, .lf-field input, .lf-field select, .lf-field textarea{
  font-size:16px
}

/* 2. the menu button — 44x44 without moving anything around it */
.menu-toggle{
  min-width:44px;min-height:44px;display:none;align-items:center;justify-content:center;
  margin-right:-10px
}
/* 860, NOT 900. The nav links and .sign-in are hidden at max-width:860px (styles.css:784).
   Showing the hamburger at 900 meant that from 861-900px BOTH menus rendered and the
   "Book a Gait Analysis" pill wrapped onto three lines and spilled out of the header —
   iPhone landscape, Android tablets, split screen and any half-width desktop window.
   My own regression, introduced with the tap-target fix. The two numbers must match. */
@media(max-width:860px){ .menu-toggle{display:inline-flex} }

@media(max-width:900px){
  /* 3. give the small controls a real touch area. padding, not height, so the
        visual size is unchanged — only the tappable box grows. */
  .aw-filter button{min-height:44px}
  .ew a.ew-test{display:inline-block;padding:11px 0;min-height:22px}
  .foot-col a, .foot-contact{padding:7px 0;display:inline-block}
  .crumb a{padding:10px 2px;display:inline-block}
  .sec-link{padding:12px 0;display:inline-block}
}

/* ===== PROGRAMS PAGE — DESIGN PASS ==========================================
   Josh: "there isnt really a flow to it all it is bland and doesnt have much
   detail, the important fonts are a bit hard to read... the sports all look bland."

   Three diagnoses, measured rather than guessed:

   1. COLOUR HAD NO RHYTHM. The run was white -> dark -> white -> paper -> white,
      and the paper band (#programs) is 7,416px — over half the page. Paper and
      white differ by ~2%, so the reader scrolled ~11,000px of one off-white.
      #by-sport is now the page's second dark band and the short facility band
      went light, so no two darks touch and the page breathes in thirds.

   2. THE HARD-TO-READ TYPE IS BEBAS AT SMALL SIZES. Bebas Neue is a CONDENSED
      display face — it is built for headlines, and it fails below ~24px. The
      worst case was .ew b at 19px: the "New to Young Guns / Already a Young Gun"
      labels, i.e. the single most important choice on the page. Those move to
      Inter. Bebas is kept only where it is big enough to earn its place.

   3. THE SPORT CARDS WERE TWELVE IDENTICAL WHITE BOXES. They now carry a colour
      keyed to the pillar that sport attacks first, so the colour CARRIES MEANING
      — a parent scanning sees at a glance that wrestling and volleyball are the
      same kind of problem. Tagged via data-pillar in the markup.
   ========================================================================== */

/* ---- the pillar colour system ---- */
.sp[data-pillar="accel"]    { --pil:#3AA6D6; --pil-ink:#19729B; --pil-name:"Acceleration" }
.sp[data-pillar="velocity"] { --pil:#63B7DE; --pil-ink:#17719C; }
.sp[data-pillar="force"]    { --pil:#8CC63F; --pil-ink:#4B781A; }   /* 4.47 -> 4.73 on its own tint */
.sp[data-pillar="com"]      { --pil:#F2A03D; --pil-ink:#9A5C10; }

/* ---- the by-sport band is now dark: restyle its furniture ---- */
#by-sport .sport-nav{border-top-color:rgba(255,255,255,.16)}
#by-sport .sport-nav .lab{color:var(--sky)}
#by-sport .sport-nav a{
  background:rgba(255,255,255,.06);border-color:rgba(255,255,255,.18);color:#fff
}
#by-sport .sport-nav a:hover{background:#fff;color:var(--ink);border-color:#fff}

/* ---- the sport cards ---- */
#by-sport .sp{
  position:relative;background:var(--paper-2);border:0;border-radius:14px;
  padding:30px 26px 26px;overflow:hidden;
  box-shadow:0 18px 40px -28px rgba(0,0,0,.85)
}
#by-sport .sp::before{                    /* the pillar bar */
  content:"";position:absolute;top:0;left:0;right:0;height:5px;background:var(--pil)
}
#by-sport .sp:hover{transform:translateY(-4px);box-shadow:0 26px 54px -26px rgba(0,0,0,.9)}
#by-sport .sp h3{
  font-size:clamp(24px,2.1vw,31px);line-height:.98;letter-spacing:.012em;color:var(--ink)
}
#by-sport .sp-space{font-size:15.5px;line-height:1.62;color:#3A3E47;margin-top:12px}

/* the pillar row becomes a coloured chip instead of two lines of grey label */
#by-sport .sp-pillar{margin-top:auto;padding-top:20px}
#by-sport .sp-pillar span{
  font-size:10px;letter-spacing:.15em;color:var(--muted);margin-bottom:7px
}
#by-sport .sp-pillar b{
  display:inline-block;font-family:var(--body);font-size:12.5px;font-weight:800;
  letter-spacing:.02em;color:var(--pil-ink);
  /* plain fallback first for anything without color-mix (pre-2023), then the tint */
  background:var(--paper);border:1px solid var(--line-l);
  background:color-mix(in srgb,var(--pil) 15%,#fff);
  border:1px solid color-mix(in srgb,var(--pil) 40%,#fff);
  border-radius:999px;padding:6px 13px;margin-top:0
}
#by-sport .sp-proof{
  font-size:14px;line-height:1.6;color:#4A4E57;
  margin-top:16px;padding-top:16px;border-top:1px solid var(--line-l)
}
#by-sport .sp-proof b{color:var(--ink);font-weight:700}

/* ---- TYPOGRAPHY: the labels that were hard to read ---- */
/* Bebas at 19px was the worst offender on the page. Inter at 15.5px/700 is the
   same physical size and dramatically more legible for a short mixed-case label. */
.ew b{
  font-family:var(--body);font-size:15.5px;font-weight:800;line-height:1.3;
  letter-spacing:.005em;text-transform:none;color:var(--ink)
}
.ew-note{font-size:14px;line-height:1.6;color:#4A4E57}
a.ew-test{font-size:15px}

/* the result numbers are the most persuasive thing on the page — let them be big */
.fc-v{font-size:clamp(28px,2.6vw,34px)}
.fc-k{font-size:13.5px;color:#4A4E57}

.plist li{font-size:15.5px}

/* ===== PROGRAM DETAIL PAGES ================================================
   Six pages split out of programs.html on Sept 1. Josh: the programs page was
   "way too wordy", so the long copy lives here and programs.html keeps a card.

   The hero is a SPLIT, not another centred text block: type on the left, the
   programme's own 4:5 photograph filling the right half edge-to-edge. That gives
   each page an immediate identity — six pages that look like six programmes
   rather than six copies of the same template.
   ========================================================================== */
.pd-hero{
  position:relative;background:var(--ink);color:#fff;overflow:hidden;
  display:grid;grid-template-columns:1.05fr .95fr;align-items:center;min-height:clamp(420px,52vw,620px)
}
.pd-hero > .wrap{position:relative;z-index:3}
.pd-hero-in{padding:clamp(48px,5vw,84px) 0}
.pd-hero .crumb{margin-bottom:22px}
.pd-hero .crumb a{color:var(--muted-d);text-decoration:none;border-bottom:1px solid transparent}
.pd-hero .crumb a:hover{color:#fff;border-bottom-color:var(--accent)}
.pd-kick{
  display:inline-block;font-family:var(--mono);font-size:11px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--ink);background:var(--green);
  padding:7px 13px;border-radius:var(--r-pill,999px);margin-bottom:20px;font-weight:700
}
.pd-h1{
  font-family:var(--display);text-transform:uppercase;line-height:.9;
  font-size:clamp(44px,7vw,92px);letter-spacing:.005em;margin:0 0 18px
}
.pd-sub{font-size:clamp(17px,1.9vw,20px);line-height:1.5;color:rgba(255,255,255,.78);max-width:30ch;margin-bottom:30px}
.pd-shot{position:relative;margin:0;height:100%;min-height:inherit;overflow:hidden}
.pd-shot::after{
  content:"";position:absolute;inset:0;z-index:2;pointer-events:none;
  background:linear-gradient(90deg,var(--ink) 0%,rgba(22,23,26,.55) 22%,transparent 60%)
}
.pd-shot img{width:100%;height:100%;object-fit:cover;display:block}

/* Body copy on a detail page is the whole point of the page — set it larger and
   on a proper measure rather than at card size. */
.pd-block{max-width:none}
.pd-prose{max-width:64ch}
.pd-prose p{font-size:18px;line-height:1.72;color:#3A3E47;margin-bottom:var(--s-3)}
.pd-prose .rt-lead{font-size:clamp(20px,2.2vw,24px);line-height:1.5;color:var(--ink);font-weight:500}
.pd-prose .pnot{
  font-size:16.5px;line-height:1.65;color:#4A4E57;
  border-left:3px solid var(--green);padding:4px 0 4px 18px;margin-top:var(--s-4)
}
.pd-h2{
  font-family:var(--display);text-transform:uppercase;font-size:clamp(24px,3vw,34px);
  line-height:1;margin:0 0 var(--s-3)
}
.pd-block + .pd-block{margin-top:var(--s-5)}

@media(max-width:900px){
  .pd-hero{grid-template-columns:1fr;min-height:0}
  .pd-hero-in{padding:44px 0 34px}
  .pd-shot{height:auto;min-height:0;aspect-ratio:4/3}
  .pd-shot::after{background:linear-gradient(180deg,rgba(22,23,26,.75) 0%,transparent 42%)}
  .pd-prose p{font-size:16.5px}
}

/* ===== PROGRAMME CARDS (programs.html) =====================================
   Replaces six ~280-word in-page blocks with six links. The whole card is the
   <a>, so the tap target is the card — not a small "see the program" line at the
   bottom of it, which is what a parent on a phone would otherwise have to hit.
   ========================================================================== */
.pgc-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s-3);margin-top:var(--s-5)}
.pgc{
  display:flex;flex-direction:column;text-decoration:none;color:inherit;
  background:var(--paper-2);border:1px solid var(--line-l);border-radius:var(--r-lg);
  overflow:hidden;transition:transform .25s cubic-bezier(.16,1,.3,1),box-shadow .25s,border-color .25s
}
.pgc:hover{transform:translateY(-4px);box-shadow:var(--sh-2);border-color:var(--ink)}
.pgc-shot{display:block;aspect-ratio:4/3;overflow:hidden;background:var(--ink);position:relative}
.pgc-shot img{width:100%;height:100%;object-fit:cover;display:block;transition:transform .5s cubic-bezier(.16,1,.3,1)}
.pgc:hover .pgc-shot img{transform:scale(1.05)}
.pgc-body{display:flex;flex-direction:column;flex:1;padding:20px 20px 22px}
.pgc-age{
  font-family:var(--mono);font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--accent-deep);font-weight:700
}
.pgc-title{
  font-family:var(--display);text-transform:uppercase;font-size:clamp(24px,2.4vw,30px);
  line-height:1;letter-spacing:.01em;margin:9px 0 10px;color:var(--ink)
}
.pgc-line{font-size:15px;line-height:1.6;color:#4A4E57;margin-bottom:18px}
.pgc-go{
  margin-top:auto;font-family:var(--body);font-size:13.5px;font-weight:700;
  color:var(--accent-deep);display:inline-flex;align-items:center;gap:7px
}
.pgc:hover .pgc-go{color:var(--ink)}
.pgc:hover .pgc-go .arw{transform:translateX(4px)}
.pgc-go .arw{transition:transform .25s}
@media(max-width:1000px){ .pgc-grid{grid-template-columns:repeat(2,1fr)} }
@media(max-width:620px){ .pgc-grid{grid-template-columns:1fr} }

/* ===== THE RANGE VISUAL ====================================================
   Josh, Sept 1: the numbers block "looks so bland... maybe could we create a
   space animation change for 25-30% increase in range".

   The section's own headline is "the currency of an athlete is SPACE", and it
   was illustrating that with a number in a box. This draws the claim instead:
   two athletes leave the same line, one covers the ground he covered before,
   the other keeps going 30% further, and the gap between them is shaded and
   labelled. The argument, made visible.

   Everything is driven by one class (.rng.in) added by the existing
   IntersectionObserver in app.js, so it plays once on scroll like the rest of
   the site. Under prefers-reduced-motion every duration collapses to 0 and the
   end state simply renders — no motion, same information.
   ========================================================================== */
/* Full width of .cur-grid — the visual is the argument, not a sidebar to the text. */
.rng{position:relative;margin-top:var(--s-5);grid-column:1 / -1}
.rng-lab{
  display:flex;justify-content:space-between;align-items:baseline;gap:16px;
  font-family:var(--mono);font-size:10.5px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--muted-d);margin-bottom:14px
}
.rng-field{
  position:relative;height:132px;border-radius:var(--r-lg);overflow:hidden;
  background:linear-gradient(180deg,rgba(255,255,255,.05),rgba(255,255,255,.02));
  border:1px solid var(--line-d)
}
/* yard lines */
.rng-field::before{
  content:"";position:absolute;inset:0;
  background-image:repeating-linear-gradient(90deg,rgba(255,255,255,.14) 0 1px,transparent 1px 10%);
  opacity:.85
}
/* the start line */
.rng-field::after{content:"";position:absolute;left:0;top:0;bottom:0;width:2px;background:var(--muted-d)}

.rng-track{position:absolute;left:0;right:0;height:34px}
.rng-track.a{top:24px}
.rng-track.b{bottom:24px}

/* the bar each athlete covers */
.rng-bar{
  position:absolute;left:0;top:50%;transform:translateY(-50%);height:6px;border-radius:3px;
  width:0;transition:width 1.5s cubic-bezier(.16,1,.3,1)
}
.rng-track.a .rng-bar{background:linear-gradient(90deg,rgba(255,255,255,.35),rgba(255,255,255,.55))}
.rng-track.b .rng-bar{background:linear-gradient(90deg,var(--accent),var(--green));transition-delay:.35s}
.rng.in .rng-track.a .rng-bar{width:55%}
.rng.in .rng-track.b .rng-bar{width:71.5%}   /* 64% x 1.30 — the 30% top of his range */

/* the marker that rides the end of each bar */
.rng-dot{
  position:absolute;top:50%;left:0;width:15px;height:15px;border-radius:50%;
  transform:translate(-50%,-50%);transition:left 1.5s cubic-bezier(.16,1,.3,1);
  border:2px solid var(--ink)
}
.rng-track.a .rng-dot{background:rgba(255,255,255,.7)}
.rng-track.b .rng-dot{background:var(--green);box-shadow:0 0 0 6px rgba(140,198,63,.18);transition-delay:.35s}
.rng.in .rng-track.a .rng-dot{left:55%}
.rng.in .rng-track.b .rng-dot{left:71.5%}

.rng-tag{
  position:absolute;top:50%;transform:translateY(-50%);left:0;white-space:nowrap;
  font-family:var(--mono);font-size:10px;letter-spacing:.12em;text-transform:uppercase;
  padding-left:26px;opacity:0;transition:left 1.5s cubic-bezier(.16,1,.3,1),opacity .5s ease .9s
}
.rng-track.a .rng-tag{color:var(--muted-d)}
.rng-track.b .rng-tag{color:var(--green);transition-delay:.35s,1.25s}
.rng.in .rng-track.a .rng-tag{left:55%;opacity:1}
.rng.in .rng-track.b .rng-tag{left:71.5%;opacity:1}

/* the shaded gap — the whole point */
.rng-gap{
  position:absolute;top:14px;bottom:14px;left:55%;width:0;
  background:repeating-linear-gradient(45deg,rgba(140,198,63,.20) 0 6px,transparent 6px 12px);
  border-left:1px dashed rgba(140,198,63,.55);border-right:1px dashed rgba(140,198,63,.55);
  transition:width 1.5s cubic-bezier(.16,1,.3,1) .35s
}
.rng.in .rng-gap{width:16.5%}
.rng-gap-lab{
  position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);white-space:nowrap;
  font-family:var(--body);font-size:12px;font-weight:800;letter-spacing:.02em;color:var(--ink);
  background:var(--green);padding:5px 10px;border-radius:var(--r-pill,999px);
  opacity:0;transition:opacity .5s ease 1.5s
}
.rng.in .rng-gap-lab{opacity:1}

.rng-foot{
  margin-top:14px;font-size:13.5px;line-height:1.6;color:var(--muted-d)
}
/* Phones: the trailing "After one block" label ran off the right edge (measured clipped at
   390px). Below 700px the labels stop chasing the dot and sit pinned at the left of their own
   lane instead, which reads better anyway — the bar length is the message, not the label. */
@media(max-width:700px){
  .rng-field{height:168px}
  .rng-gap-lab{font-size:10.5px;padding:4px 8px}
  .rng-tag,
  .rng.in .rng-track.a .rng-tag,
  .rng.in .rng-track.b .rng-tag{
    left:12px !important;top:auto;bottom:-2px;transform:none;padding-left:0;
    font-size:9.5px;opacity:1
  }
  .rng-track{height:44px}
  .rng-track.a{top:16px}
  .rng-track.b{bottom:16px}
}
@media(prefers-reduced-motion:reduce){
  .rng-bar,.rng-dot,.rng-tag,.rng-gap,.rng-gap-lab{transition-duration:0s !important;transition-delay:0s !important}
}

/* ===== "PHOTO NEEDED" PLACEHOLDER =========================================
   Josh, Sept 1: "please just put place holders labels with training floor or
   cords or testing etc" — he is shooting them tomorrow.

   Deliberately looks like an EMPTY FRAME WAITING, not a broken image: dashed
   rule, a camera glyph, the shot name, and the shape required. That way a
   missing photo is obviously a to-do rather than a bug, and it is impossible to
   ship one by accident without noticing.

   TO REPLACE: swap the whole .ph-need block for a normal <img>. Every one is
   also findable with  grep -rn 'ph-need' *.html
   ========================================================================== */
.ph-need{
  position:relative;display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:9px;text-align:center;padding:26px 22px;border-radius:var(--r-lg);
  background:
    repeating-linear-gradient(45deg,rgba(58,166,214,.05) 0 10px,transparent 10px 20px),
    var(--paper-2);
  border:2px dashed rgba(58,166,214,.45);color:var(--accent-deep);min-height:180px
}
.section-d .ph-need,.data-bg .ph-need,.pd-hero .ph-need{
  background:
    repeating-linear-gradient(45deg,rgba(99,183,222,.07) 0 10px,transparent 10px 20px),
    rgba(255,255,255,.03);
  border-color:rgba(99,183,222,.4);color:var(--sky)
}
.ph-need::before{
  content:"";width:30px;height:24px;border:2px solid currentColor;border-radius:5px;
  box-shadow:inset 0 0 0 2px transparent;position:relative;opacity:.75
}
.ph-need .n{
  font-family:var(--display);text-transform:uppercase;font-size:clamp(16px,2vw,21px);
  line-height:1.05;letter-spacing:.01em
}
.ph-need .s{
  font-family:var(--mono);font-size:10px;letter-spacing:.14em;text-transform:uppercase;opacity:.8
}
.ph-need.wide{aspect-ratio:16/7;min-height:0}
.ph-need.tall{aspect-ratio:4/5;min-height:0}
.ph-need.box{aspect-ratio:4/3;min-height:0}

/* Grid for a row of "photo needed" frames. */
.ph-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s-3);margin-bottom:var(--s-4)}
@media(max-width:800px){ .ph-grid{grid-template-columns:1fr} }

/* The line under the form's submit button. This is where a parent is actually handing over
   their child's age, so the reassurance belongs here rather than only in the footer. */
.lf-privacy{
  margin-top:14px;font-size:12.5px;line-height:1.55;color:var(--muted-d);max-width:52ch
}
.lf-privacy a{color:var(--sky);text-decoration:underline;text-underline-offset:2px}
.lf-privacy a:hover{color:#fff}

/* The physical-therapy note under the Return-to-Play button. Josh, Sept 1: Dan refers athletes
   to KPM once therapy is finished, and KPM athletes/parents/former athletes can book with him
   through KPM. Both directions are real; the site previously implied KPM books therapy for
   anyone, which it does not — the practice is a separate licensed business. */
.rx-note{
  /* #4A4E57, NOT --muted-d. .rx-panel is --paper-2 (#FFF) and --muted-d is
     rgba(255,255,255,.56) — white on white, contrast 1.00, the paragraph was
     invisible on the home page. --muted-d is the token for DARK sections only.
     This is 8.34:1, and matches .sec-head p / .cyc p on the same light ground. */
  margin-top:14px;font-size:13.5px;line-height:1.6;color:#4A4E57;max-width:56ch
}
/* These three were the SAME BUG as the parent above, missed when it was fixed: the comment
   in .rx-note says --muted-d is dark-only, then the very next line put #fff on the white
   panel anyway. The bold run — "KPM athletes, their parents and former athletes" — measured
   1.00:1 and was literally invisible, which deleted the clause naming WHO may book therapy
   through KPM. That clause is the whole reason the paragraph exists. The links failed too:
   --green is 2.05:1 on white, and the hover took them to #fff, so both vanished under the
   cursor. Light ground => --ink for the bold, --green-ink (5.14:1) for the links. */
.rx-note b{color:var(--ink);font-weight:700}
.rx-note a{color:var(--green-ink);text-decoration:underline;text-underline-offset:2px}
.rx-note a:hover{color:var(--ink)}

/* ===== AFTER SCHOOL PROGRAMS ===============================================
   Built Sept 1 from Josh's SJRS flyer. The page is a HUB: one shared "how it
   works" section, then one .school block per partner school. More schools are
   coming, so adding one means copying a .school block and nothing else.

   NO PRICING ANYWHERE. Josh, explicitly: the school rate is an exclusive offer,
   the training differs from the facility programme, and publishing the two side
   by side "will make most parents think we are just ripping them off". Families
   get the figure from the school. Do not add a price here.
   ========================================================================== */
.school{
  border:1px solid var(--line-d);border-radius:var(--r-lg);overflow:hidden;
  background:rgba(255,255,255,.03);margin-bottom:var(--s-5)
}
.school-head{
  display:flex;flex-wrap:wrap;align-items:flex-end;justify-content:space-between;gap:var(--s-3);
  padding:clamp(22px,3vw,34px);border-bottom:1px solid var(--line-d)
}
.school-head .lab{
  font-family:var(--mono);font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--green);display:block;margin-bottom:10px
}
.school-head h3{
  font-family:var(--display);text-transform:uppercase;font-size:clamp(26px,3.6vw,40px);
  line-height:.96;letter-spacing:.005em
}
.school-when{display:flex;flex-wrap:wrap;gap:8px}
.school-when span{
  font-family:var(--mono);font-size:11px;letter-spacing:.08em;text-transform:uppercase;
  border:1px solid var(--line-d);border-radius:var(--r-pill,999px);padding:7px 13px;color:#fff
}
.school-when span.hi{background:var(--green);color:var(--ink);border-color:var(--green);font-weight:700}
.school-body{padding:clamp(22px,3vw,34px)}

.sgain{display:grid;grid-template-columns:1fr 1fr;gap:var(--s-3);margin-bottom:var(--s-4)}
.sgain > div{border:1px solid var(--line-d);border-radius:10px;padding:18px 20px;background:rgba(0,0,0,.25)}
.sgain b{
  display:block;font-family:var(--display);font-size:clamp(30px,4.4vw,46px);line-height:1;
  color:var(--green);letter-spacing:.01em
}
.sgain .m{font-size:15px;font-weight:700;color:#fff;margin-top:8px}
.sgain .s{font-family:var(--mono);font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:var(--muted-d);margin-top:4px}

.sweek{display:grid;grid-template-columns:repeat(2,1fr);gap:var(--s-3)}
.sweek > div{border:1px solid var(--line-d);border-left:3px solid var(--accent);border-radius:8px;padding:16px 18px}
.sweek > div.sat{border-left-color:var(--green)}
.sweek h4{font-family:var(--display);text-transform:uppercase;font-size:19px;line-height:1;margin-bottom:8px}
.sweek p{font-size:14.5px;line-height:1.55;color:rgba(255,255,255,.8)}
.sweek p b{color:#fff}
.sweek .where{
  display:block;font-family:var(--mono);font-size:10px;letter-spacing:.13em;text-transform:uppercase;
  color:var(--muted-d);margin-top:8px
}
.school-foot{
  display:flex;flex-wrap:wrap;gap:12px;align-items:center;
  padding:clamp(18px,2.4vw,26px) clamp(22px,3vw,34px);border-top:1px solid var(--line-d);
  background:rgba(0,0,0,.22)
}
.flyer-link{
  display:inline-flex;align-items:center;gap:9px;font-size:13.5px;font-weight:700;
  color:var(--sky);text-decoration:underline;text-underline-offset:3px;
  /* padding not height, so the underline still hugs the words while the tap box
     clears 44px — on a phone this was a 22px target next to a 48px button. */
  min-height:44px;padding:0 4px
}
.flyer-link:hover{color:#fff}
@media(max-width:720px){
  .sgain,.sweek{grid-template-columns:1fr}
  .school-head{flex-direction:column;align-items:flex-start}
}

/* ===== PROGRAMS NAV DROPDOWN ================================================
   Josh: "in the menu i need the programs to have a drop down ... and Afterschool
   Programs at the top."

   Three ways it opens, because three kinds of visitor exist:
     hover        — desktop mouse
     :focus-within— keyboard tabbing
     .open        — a real <button> click, which is the ONLY thing that works on a
                    touch tablet wider than 860px (iPad landscape has no hover)
   "Programs" itself stays a real link to the overview page. The chevron is a
   separate button, so tapping the word still navigates and tapping the arrow
   opens the list — a link that only opens a menu strands anyone who wanted the
   overview page.
   ========================================================================== */
.nd{position:relative;display:flex;align-items:center}
.nd-top{display:flex;align-items:center}
.nd-btn{
  display:inline-flex;align-items:center;justify-content:center;
  width:26px;height:26px;margin-left:-9px;padding:0;
  background:none;border:none;cursor:pointer;color:rgba(255,255,255,.7);
  border-radius:var(--r-sm);transition:color .2s,background .2s
}
.nd-btn:hover{color:#fff;background:rgba(255,255,255,.06)}
.nd-btn svg{width:11px;height:11px;transition:transform .24s cubic-bezier(.16,1,.3,1)}
.nd:hover .nd-btn svg,.nd.open .nd-btn svg{transform:rotate(180deg)}

.nd-menu{
  position:absolute;top:100%;left:0;z-index:5;min-width:284px;
  background:linear-gradient(180deg,#1B1D21,#131417);
  border:1px solid var(--line-d);border-radius:var(--r-lg);
  box-shadow:0 26px 60px -24px rgba(0,0,0,.95);
  padding:10px;margin-top:10px;
  opacity:0;visibility:hidden;transform:translateY(-6px);
  transition:opacity .2s,transform .24s cubic-bezier(.16,1,.3,1),visibility .2s
}
/* invisible bridge across the 10px gap — without it the menu closes the instant
   the pointer leaves the link on its way down to the first item */
.nd-menu::before{content:"";position:absolute;left:0;right:0;top:-14px;height:14px}
.nd:hover .nd-menu,.nd:focus-within .nd-menu,.nd.open .nd-menu{
  opacity:1;visibility:visible;transform:translateY(0)
}
.nav-links .nd-menu a{
  display:block;padding:10px 12px;font-size:12px;letter-spacing:.06em;
  color:rgba(255,255,255,.82);border-radius:var(--r-md);text-transform:uppercase
}
.nav-links .nd-menu a::after{display:none}
.nav-links .nd-menu a:hover{background:rgba(255,255,255,.07);color:#fff}
.nd-menu a .sub{
  display:block;margin-top:3px;font-size:11px;font-weight:500;letter-spacing:.01em;
  text-transform:none;color:var(--muted-d)
}
.nd-lab{
  display:block;padding:9px 12px 5px;font-family:var(--mono,inherit);
  font-size:10px;font-weight:700;letter-spacing:.16em;text-transform:uppercase;
  color:var(--sky)
}
.nd-lab.g{color:var(--green)}
.nd-sep{height:1px;background:var(--line-d);margin:8px 6px}
.nav-links .nd-menu a.nd-all{color:var(--sky);font-weight:800}

@media(max-width:860px){
  /* In the stacked mobile menu the panel expands in place instead of floating —
     a floating card inside an already-absolute nav column would hang off-screen. */
  .nd{display:block;width:100%}
  .nd-top{justify-content:space-between;border-bottom:1px solid var(--line-d)}
  .nav-links.open .nd-top a{border-bottom:none;flex:1}
  .nd-btn{width:44px;height:44px;margin-left:0;color:#fff}
  .nd-menu{
    position:static;min-width:0;background:none;border:none;box-shadow:none;
    padding:0 0 6px 14px;margin:0;
    opacity:1;visibility:visible;transform:none;transition:none;
    display:none
  }
  .nd-menu::before{display:none}
  .nd:hover .nd-menu,.nd:focus-within .nd-menu{display:none}
  .nd.open .nd-menu{display:block}
  .nav-links.open .nd-menu a{
    padding:12px 0;min-height:44px;border-bottom:1px solid rgba(255,255,255,.07)
  }
  .nd-menu a .sub{display:none}
  .nd-lab{padding:12px 0 4px}
  .nd-sep{display:none}
}

/* The panel is 583px tall. On a 1280x720 laptop the browser viewport is roughly
   600px, so without this the last items ("Online Programs", "All Programs") sit
   below the fold with no way to reach them. */
.nd-menu{max-height:calc(100vh - 104px);overflow-y:auto}
/* Tell a visitor which of these pages they are already on. */
.nav-links .nd-menu a[aria-current="page"]{
  background:rgba(140,198,63,.11);color:#fff;box-shadow:inset 2px 0 0 var(--green)
}
@media(max-width:860px){
  .nd-menu{max-height:none;overflow:visible}
  .nav-links .nd-menu a[aria-current="page"]{
    background:none;box-shadow:none;color:var(--green)
  }
}

/* The stacked mobile menu inherited align-items:center from the desktop flex row,
   so the top-level links sat centred with short centred underlines. Next to the
   full-width, left-aligned Programs dropdown that read as a broken menu rather
   than a style. Stretch + left is the standard pattern and makes every divider
   run the full column. */
@media(max-width:860px){
  .nav-links.open{align-items:stretch}
  .nav-links.open > a{text-align:left}
}

/* ===== AFTER SCHOOL HERO — photo / copy / photo =============================
   Josh asked for one of his own session photos on either side of the title.
   The copy centres between them, which is why .pd-sub's 30ch left-aligned
   measure is widened and centred here rather than inherited.

   Below 1080px the two flankers would squeeze the headline into a column, so
   they drop underneath as a 2-up row instead of stacking full-width — two
   portrait shots side by side stay legible all the way down to 375px, and
   keeping them visible matters because most of this page's traffic is parents
   on a phone. Placement is explicit (grid-row/grid-column) because DOM order is
   photo-copy-photo, and auto-placement would strand the copy between them.
   ========================================================================== */
.ash-hero{
  display:grid;
  grid-template-columns:minmax(0,.84fr) minmax(0,1.62fr) minmax(0,.84fr);
  gap:clamp(20px,3.2vw,48px);
  align-items:center;
  /* padding-block, NOT the `padding: X 0` shorthand — this element is also a
     .wrap, and the shorthand zeroed .wrap's side gutters, running the hero
     photos and buttons flush to both screen edges on a phone. */
  padding-block:clamp(44px,4.6vw,76px)
}
.ash-copy{text-align:center}
.ash-copy .pd-sub{max-width:44ch;margin-left:auto;margin-right:auto}
/* Faded into the hero rather than framed, matching .pd-shot on the New Athletes
   and Veteran Athletes pages. Those bleed off the side of the viewport so one
   horizontal gradient is enough; these float inside the hero and have four real
   edges, so the mask fades all of them — weighted toward the copy, which is the
   edge the eye reads across.

   A mask, not .pd-shot's ink overlay: this hero carries the .rig glow behind it,
   so painting flat --ink over the photo edge would leave a visible dark patch
   where the glow shows through beside it. A mask makes the pixels genuinely
   transparent, so whatever is behind shows through correctly.

   If a browser lacks mask-composite the photo simply renders unfaded — there is
   no border or shadow left to look broken. */
.ash-shot{
  margin:0;position:relative;aspect-ratio:4/5;overflow:hidden;
  -webkit-mask-composite:source-in;
          mask-composite:intersect
}
.ash-shot img{width:100%;height:100%;object-fit:cover;display:block}

.ash-shot-l{
  -webkit-mask-image:linear-gradient(90deg,transparent 0,#000 15%,#000 56%,transparent 100%),
                     linear-gradient(180deg,transparent 0,#000 15%,#000 84%,transparent 100%);
          mask-image:linear-gradient(90deg,transparent 0,#000 15%,#000 56%,transparent 100%),
                     linear-gradient(180deg,transparent 0,#000 15%,#000 84%,transparent 100%)
}
.ash-shot-r{
  -webkit-mask-image:linear-gradient(90deg,transparent 0,#000 44%,#000 85%,transparent 100%),
                     linear-gradient(180deg,transparent 0,#000 15%,#000 84%,transparent 100%);
          mask-image:linear-gradient(90deg,transparent 0,#000 44%,#000 85%,transparent 100%),
                     linear-gradient(180deg,transparent 0,#000 15%,#000 84%,transparent 100%)
}

@media(max-width:1080px){
  .ash-hero{grid-template-columns:1fr 1fr;gap:clamp(14px,2.6vw,22px)}
  .ash-copy{grid-column:1/-1;grid-row:1;margin-bottom:6px}
  .ash-shot-l{grid-column:1;grid-row:2;justify-self:end}
  .ash-shot-r{grid-column:2;grid-row:2;justify-self:start}
  /* Cap them, or a half-column on a tablet makes each photo 463px wide and 579
     tall — the hero then runs past the bottom of the screen and buries the rest
     of the page. Capped, they read as a centred pair. A phone is narrower than
     the cap, so this changes nothing there. */
  .ash-shot{width:100%;max-width:300px}
  /* Side by side under the copy, neither photo has an edge facing the text, so
     the horizontal weighting is dropped for an even fade. */
  .ash-shot-l,.ash-shot-r{
    -webkit-mask-image:linear-gradient(90deg,transparent 0,#000 16%,#000 84%,transparent 100%),
                       linear-gradient(180deg,transparent 0,#000 13%,#000 87%,transparent 100%);
            mask-image:linear-gradient(90deg,transparent 0,#000 16%,#000 84%,transparent 100%),
                       linear-gradient(180deg,transparent 0,#000 13%,#000 87%,transparent 100%)
  }
}

/* ===== NAV: the 861-1100px squeeze =========================================
   Pre-existing, verified against commit 43325be (before the Programs dropdown
   existed) — identical wrapping there, so this is not dropdown fallout.

   Between 861px (where the nav-links first appear) and 1180px there is
   not enough room for five links plus Athlete Login plus the CTA pill at full
   size, so "The Method" broke onto two lines and the pill grew to 67px tall.
   iPad landscape is 1024px, so this was the common case, not an edge one.

   1180, not 1100: measured at full size the bar needs 1031px of content and the
   wrap contributes 64px of padding, so the untightened layout only clears at
   about 1095px — at 1101px it had 6px of slack and rounding still broke the
   line. 1180 leaves real headroom.

   Tightening type and padding across that band only. Nothing outside it moves,
   and the 860px hamburger breakpoint is untouched — the last time those two
   numbers disagreed, both menus rendered at once.
   ========================================================================== */
@media(min-width:861px) and (max-width:1180px){
  .nav-links a{padding:10px 9px;font-size:11.5px;letter-spacing:.07em}
  .nav-links a::after{left:9px;right:9px}
  .nav-cta{gap:9px}
  .nav-cta .btn-accent{padding:11px 14px;font-size:11.5px;letter-spacing:.04em}
  .sign-in{padding:8px 9px;font-size:10px;letter-spacing:.1em}
  .nd-btn{width:22px;height:22px;margin-left:-6px}
}
/* The narrow end of the band still could not fit everything, so Athlete Login
   steps aside there. It is already hidden below 860px, this just extends that a
   little further up, and the link stays in the footer of every page. Preferred
   over moving the 860px collapse point: those two numbers (links hidden /
   hamburger shown) must stay identical, and the last time they drifted apart
   both menus rendered at once. */
@media(min-width:861px) and (max-width:975px){
  .sign-in{display:none}
  .nav-links a{padding:9px 7px;font-size:11px;letter-spacing:.05em}
  .nav-links a::after{left:7px;right:7px}
}

/* ===== PROGRAMS PAGE — PHOTOGRAPHY & LIVE CRESTS ===========================
   Josh, Sept 2: the hero needed pictures, the crest circles looked "plain", and
   the page as a whole was "too many words". Three parts below: hero flankers,
   crest motion, and reusable photo blocks for the wordy sections.
   ========================================================================== */

/* --- 1. Hero flankers ------------------------------------------------------
   Full-bleed to the hero's own edges and dissolving toward the middle, so the
   emblem and headline keep a clean centre. Running on the left, jumping on the
   right — the slogan is "Jump Higher. Run Faster.", so the two sides say it in photos.
   Costs the hero no extra height, which a photo band underneath would have.
   Hidden below 900px: at phone width a 240px flanker either swamps the type or
   shrinks to a smear, and the in-page photos carry the mobile view instead. */
.ch-flank{
  position:absolute;top:0;bottom:0;z-index:0;overflow:hidden;pointer-events:none;
  width:clamp(230px,27vw,430px)
}
.ch-flank-l{left:0}
.ch-flank-r{right:0}
.ch-flank img{width:100%;height:100%;object-fit:cover;display:block;opacity:.52}
.ch-flank-l{
  -webkit-mask-image:linear-gradient(90deg,#000 0,#000 26%,transparent 100%),
                     linear-gradient(180deg,transparent 0,#000 14%,#000 82%,transparent 100%);
          mask-image:linear-gradient(90deg,#000 0,#000 26%,transparent 100%),
                     linear-gradient(180deg,transparent 0,#000 14%,#000 82%,transparent 100%);
  -webkit-mask-composite:source-in; mask-composite:intersect
}
.ch-flank-r{
  -webkit-mask-image:linear-gradient(270deg,#000 0,#000 26%,transparent 100%),
                     linear-gradient(180deg,transparent 0,#000 14%,#000 82%,transparent 100%);
          mask-image:linear-gradient(270deg,#000 0,#000 26%,transparent 100%),
                     linear-gradient(180deg,transparent 0,#000 14%,#000 82%,transparent 100%);
  -webkit-mask-composite:source-in; mask-composite:intersect
}
/* the hero's own content must sit above the flankers */
.coach-hero > .wrap{position:relative;z-index:2}
@media(max-width:900px){ .ch-flank{display:none} }

/* --- 2. Live crests --------------------------------------------------------
   The rings already drew themselves in on scroll, but they drew a COMPLETE
   circle, so once the animation finished each one was an outline identical to
   its own track — which is exactly why they read as plain. The draw-in stays;
   what is added is motion that never finishes: a slow conic sheen around the
   rim and a lit dot orbiting it, staggered so the four are never in phase.
   Both are pseudo-elements, so no markup changed. */
.crest-ring::before,
.crest-ring::after{content:"";position:absolute;inset:0;border-radius:50%;pointer-events:none}
.crest-ring::before{
  inset:-2px;
  background:conic-gradient(from 0turn,transparent 0 60%,rgba(99,183,222,.40) 79%,
                            rgba(140,198,63,.28) 90%,transparent 100%);
  -webkit-mask:radial-gradient(closest-side,transparent 77%,#000 80%);
          mask:radial-gradient(closest-side,transparent 77%,#000 80%);
  animation:crestSheen 11s linear infinite
}
.crest-ring::after{
  background:radial-gradient(circle 3.5px at 50% 0%,#EAF6FF 0 38%,rgba(99,183,222,.7) 56%,transparent 72%);
  animation:crestOrbit 11s linear infinite
}
.crest:nth-child(2) .crest-ring::before,.crest:nth-child(2) .crest-ring::after{animation-delay:-2.75s}
.crest:nth-child(3) .crest-ring::before,.crest:nth-child(3) .crest-ring::after{animation-delay:-5.5s}
.crest:nth-child(4) .crest-ring::before,.crest:nth-child(4) .crest-ring::after{animation-delay:-8.25s}
.crest.is-big .crest-ring::before{
  background:conic-gradient(from 0turn,transparent 0 58%,rgba(140,198,63,.5) 80%,
                            rgba(99,183,222,.3) 91%,transparent 100%)
}
.crest.is-big .crest-ring::after{
  background:radial-gradient(circle 4px at 50% 0%,#F2FFE2 0 38%,rgba(140,198,63,.75) 56%,transparent 72%)
}
@keyframes crestSheen{to{transform:rotate(1turn)}}
@keyframes crestOrbit{to{transform:rotate(1turn)}}
/* pointer feedback — the rail is the first thing under the headline */
.crest-ring{transition:transform .34s cubic-bezier(.16,1,.3,1),box-shadow .34s}
.crest:hover .crest-ring{
  transform:translateY(-4px);
  box-shadow:0 0 0 1px rgba(255,255,255,.16),
             inset 0 0 0 1px rgba(255,255,255,.06),
             0 24px 40px -22px rgba(0,0,0,.95),
             0 0 54px -18px rgba(58,166,214,.8)
}

/* --- 3. Photo blocks for the wordy sections -------------------------------- */
/* A section head with one portrait photo beside it. Portrait sources cannot go
   full-bleed without losing the athlete's head or feet, so they run as a narrow
   column against the text instead. */
.hs-row{
  display:grid;grid-template-columns:minmax(0,1fr) minmax(0,clamp(240px,26vw,330px));
  gap:clamp(26px,4.5vw,60px);align-items:center;margin-bottom:clamp(30px,4vw,48px)
}
.hs-row .sec-head{margin-bottom:0}
.hs-fig{
  margin:0;position:relative;aspect-ratio:3/4;overflow:hidden;
  border-radius:var(--r-lg);border:1px solid var(--line-d);
  box-shadow:0 30px 62px -30px rgba(0,0,0,.9)
}
.hs-fig img{width:100%;height:100%;object-fit:cover;display:block}
.section-l .hs-fig,.grid-bg .hs-fig{border-color:var(--line-l)}
@media(max-width:860px){
  .hs-row{grid-template-columns:1fr;gap:24px}
  .hs-fig{aspect-ratio:4/3}
}

/* Full-bleed cinematic band. Only for genuinely landscape source files — a 16:7
   crop of a portrait frame drops 46% of its height. */
.wideband{
  position:relative;margin:0;overflow:hidden;border-radius:var(--r-lg);
  aspect-ratio:16/7;border:1px solid var(--line-d)
}
.wideband img{width:100%;height:100%;object-fit:cover;display:block}
.wideband figcaption{
  position:absolute;left:0;right:0;bottom:0;padding:clamp(18px,2.6vw,30px);
  font-family:var(--mono);font-size:11px;letter-spacing:.16em;text-transform:uppercase;
  color:rgba(255,255,255,.9);
  background:linear-gradient(180deg,transparent,rgba(11,13,16,.82))
}
@media(max-width:640px){ .wideband{aspect-ratio:4/3} }

/* Two portrait photos side by side, for closing out a text-only section. */
.duo{display:grid;grid-template-columns:1fr 1fr;gap:clamp(14px,2vw,22px);margin-top:clamp(30px,4vw,46px)}
.duo figure{
  margin:0;position:relative;aspect-ratio:4/5;overflow:hidden;border-radius:var(--r-lg);
  border:1px solid var(--line-d);box-shadow:0 30px 62px -30px rgba(0,0,0,.9)
}
.duo img{width:100%;height:100%;object-fit:cover;display:block}

@media(prefers-reduced-motion:reduce){
  .crest-ring::before,.crest-ring::after{animation:none}
  .crest-ring::after{opacity:0}
  .crest:hover .crest-ring{transform:none}
}

/* ===== .quote ON A WHITE SECTION — invisible body copy ======================
   PRE-EXISTING, verified against commit 8179b2c: the section class was already
   "section section-p2 grid-bg" before any of today's edits.

   .quote is used on exactly ONE section in the whole site, and that section is
   --paper-2, i.e. #FFFFFF. The component, though, was written for a dark ground:
     .quote p        rgba(255,255,255,.82)   <- white on white
     .quote .who span var(--muted-d) = rgba(255,255,255,.56)
     .quote border   var(--line-d)  = rgba(255,255,255,.14)
     .quote:hover    white border, white tint
   Only .mark (accent blue) and .who b (inherits ink) were ever visible, which is
   exactly what the page showed: "01 02 03" and a label, floating over nothing.
   Three paragraphs of body copy have been unreadable on the Programs page.

   Scoped to .section-p2 rather than editing .quote itself, so the component
   still works if it is ever reused on a dark section. */
.section-p2 .quote{border-color:var(--line-l)}
.section-p2 .quote p{color:#3B4048}
.section-p2 .quote .who span{color:var(--muted)}
.section-p2 .quote:hover{border-color:rgba(22,23,26,.30);background:rgba(22,23,26,.025)}
.section-p2 .quote:hover .mark{color:var(--accent-deep)}

/* ===== FIRST CYCLE — BOYS BLUE, GIRLS GREEN ================================
   Josh, Sept 2: "make the boys blue and the girls green so they look
   different... it looks too similar in that section". Both cards were the same
   paper, same border, same black display type and the same green callout, so
   the only thing telling them apart was the word in the heading.

   One token set per card drives everything downstream — tag, rule, values,
   callout, standout accents — so the two read as different objects at a glance
   without either one being restyled by hand.
   ========================================================================== */
.fc{
  --fc-hue:var(--accent-deep);
  --fc-soft:rgba(58,166,214,.13);
  --fc-tint:rgba(58,166,214,.085);
  position:relative;overflow:hidden
}
.fc-boys{
  --fc-hue:var(--accent-deep); --fc-soft:rgba(58,166,214,.13); --fc-tint:rgba(58,166,214,.085)
}
/* --green-ink, not --green: the bright green is a 2.3:1 text colour on paper.
   --green-ink is the weight-carrying green the rest of the site already uses
   for type — see the .rx notes. */
.fc-girls{
  --fc-hue:var(--green-ink); --fc-soft:rgba(140,198,63,.17); --fc-tint:rgba(140,198,63,.10)
}
.fc{background:linear-gradient(180deg,var(--fc-tint),transparent 240px),var(--paper)}
.fc::before{
  content:"";position:absolute;left:0;right:0;top:0;height:4px;
  background:linear-gradient(90deg,var(--fc-hue),transparent 88%)
}
.fc-tag{color:var(--fc-hue)}
.fc-head{border-bottom-color:var(--fc-hue);border-bottom-width:2px;opacity:1}
.fc-v{color:var(--fc-hue)}
.fc-space{background:var(--fc-soft);border-left-color:var(--fc-hue)}
.fc-src-lab{color:var(--fc-hue)}

/* --- standouts: two per card, same shape ---------------------------------- */
.so{
  background:#fff;border:1px solid var(--line-l);border-left:3px solid var(--fc-hue);
  border-radius:var(--r-md);padding:15px 17px;margin-bottom:12px;
  transition:transform .28s cubic-bezier(.16,1,.3,1),box-shadow .28s
}
.so:hover{transform:translateY(-3px);box-shadow:0 18px 34px -22px rgba(0,0,0,.5)}
.so:last-child{margin-bottom:0}
.so-name{
  display:block;font-family:var(--display);font-weight:400;text-transform:uppercase;
  font-size:20px;line-height:1;letter-spacing:.02em;color:var(--ink)
}
.so-where{
  display:block;margin-top:5px;font-family:var(--mono);font-size:11px;font-weight:600;
  letter-spacing:.1em;text-transform:uppercase;color:var(--muted)
}
.so-stats{list-style:none;display:grid;grid-template-columns:1fr 1fr;gap:0 18px;margin:13px 0 0;padding:0}
.so-stats li{
  display:flex;align-items:baseline;justify-content:space-between;gap:10px;
  padding:7px 0;border-top:1px dashed var(--line-l)
}
.so-stats .k{
  font-family:var(--body);font-size:10.5px;font-weight:700;letter-spacing:.09em;
  text-transform:uppercase;color:var(--muted);white-space:nowrap
}
.so-stats .v{
  font-family:var(--display);font-weight:400;font-size:15px;letter-spacing:.02em;
  color:var(--ink);font-variant-numeric:tabular-nums;white-space:nowrap
}
.so-stats .v i{font-style:normal;color:var(--fc-hue);padding:0 4px;font-size:13px}
.so-note{margin-top:11px;font-size:13px;line-height:1.5;color:var(--muted)}
.so-per{
  display:inline-block;margin-top:13px;font-family:var(--mono);font-size:10px;font-weight:700;
  letter-spacing:.13em;text-transform:uppercase;color:var(--fc-hue);
  background:var(--fc-soft);padding:6px 11px;border-radius:var(--r-pill)
}
/* Damari is four YEARS at KPM, not a cycle. His badge is deliberately a
   different object from the 12-week ones — solid ink rather than a tinted
   pill — so the two can never be skim-read as the same claim. */
.so-per.long{color:#fff;background:var(--ink);letter-spacing:.11em}

@media(max-width:1080px){ .so-stats{grid-template-columns:1fr} }
@media(max-width:860px){ .so-stats{grid-template-columns:1fr 1fr} }
@media(max-width:520px){ .so-stats{grid-template-columns:1fr} }

/* ===== PROGRAMS PAGE, SECOND PASS =========================================
   Josh, Sept 2: move the coaching photo up behind the test-in boxes; fill the
   dead space under the 25-30% with an expanding bubble; and "i do not like the
   six ways in background or design of the section".
   ========================================================================== */

/* --- 1. Test-in, on the training floor ------------------------------------
   The photo is the section's ground rather than a band of its own, so the two
   white cards read as objects standing ON the floor. The scrim is a hard
   requirement, not decoration: the raw frame is mid-grey where the headline
   sits and white type on it measured about 2:1. */
.entry-shot{
  position:relative;overflow:hidden;
  background:var(--ink);color:#fff;padding:var(--sec) 0
}
.entry-bg{position:absolute;inset:0;z-index:0;pointer-events:none}
.entry-bg img{width:100%;height:100%;object-fit:cover;display:block;opacity:.42}
/* darkest at the left, where the heading sits; lightest at the right, where the
   photo's own subject is */
.entry-bg::after{
  content:"";position:absolute;inset:0;
  background:linear-gradient(96deg,rgba(16,17,20,.93) 0%,rgba(16,17,20,.84) 38%,
             rgba(16,17,20,.62) 70%,rgba(16,17,20,.55) 100%)
}
.entry-shot > .wrap{position:relative;z-index:1}
.entry-shot .sec-head h2{color:#fff}
.entry-shot .sec-head p{color:rgba(255,255,255,.82)}
.entry-shot .eyebrow{color:var(--sky)}
.entry-shot .man-eyebrow::before{background:rgba(255,255,255,.3)}
/* The cards stay white on the dark ground, so anything inside them that INHERITS
   colour has to be pushed back to ink. .ti h3 sets no colour of its own, so the
   section's color:#fff reached straight through and the two headings — "Gait
   Analysis" and "Effective Range Test-In" — rendered white on white. Same trap
   as .quote on the white section: a component built for one ground, reused on
   the other. Everything else inside .ti sets its own colour explicitly. */
.entry-shot .ti{box-shadow:0 34px 70px -30px rgba(0,0,0,.95);color:var(--ink)}
.entry-shot .ti h3{color:var(--ink)}
.entry-shot .ti-note{color:rgba(255,255,255,.78)}
.entry-shot .ti-note a{color:var(--sky)}

/* --- 2. The expanding bubble ----------------------------------------------
   Sits in the .cur-fig aside, which was a third the height of the column beside
   it. Radius grows 30%; see the note in the markup for why radius and not area.
   .in arrives from the same reveal observer everything else on the page uses. */
.bub{
  position:relative;display:block;width:100%;max-width:250px;aspect-ratio:1;
  margin:var(--s-4) 0 var(--s-2)
}
.bub > span{position:absolute;left:50%;top:50%;translate:-50% -50%;border-radius:50%}
/* the grown circle — the full 1.3r, entering at .769 so it starts on the ring */
.bub-grow{
  width:100%;height:100%;
  background:radial-gradient(circle,rgba(140,198,63,.26) 0%,rgba(140,198,63,.10) 62%,rgba(140,198,63,.03) 100%);
  border:1.5px solid rgba(140,198,63,.85);
  box-shadow:0 0 44px -6px rgba(140,198,63,.35);
  transform:scale(.769);
  transition:transform 1.5s cubic-bezier(.22,1,.36,1)
}
.bub.in .bub-grow{transform:scale(1)}
/* the starting radius, held as a dashed reference so the growth is legible */
.bub-ring{
  width:76.9%;height:76.9%;
  border:1.5px dashed rgba(255,255,255,.34)
}
.bub-core{
  width:12px;height:12px;background:var(--green);
  box-shadow:0 0 18px 2px rgba(140,198,63,.6)
}
.bub-lab{
  position:absolute;left:50%;top:50%;translate:-50% -50%;
  border-radius:0;text-align:center;width:100%;
  font-family:var(--display);font-weight:400;font-size:clamp(26px,3vw,34px);
  line-height:.95;letter-spacing:.01em;color:#fff;
  opacity:0;transition:opacity .6s ease .55s
}
.bub.in .bub-lab{opacity:1}
.bub-lab em{
  display:block;margin-top:7px;font-family:var(--mono);font-style:normal;
  font-size:10px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;
  color:rgba(255,255,255,.62)
}
@media(prefers-reduced-motion:reduce){
  .bub-grow{transform:scale(1);transition:none}
  .bub-lab{opacity:1;transition:none}
}
@media(max-width:900px){ .bub{margin-inline:auto} }

/* --- 3. Six ways in, rebuilt ----------------------------------------------
   Was --paper under the pale blue .grid-bg, which read washed out and left the
   six photo cards sitting on nothing. It is the page's shop window, so it now
   gets the darkest ground on the page and the photographs carry it.
   Distinct from the .data-bg section that follows: a centred glow and a lane
   motif rather than the data grid, so the two darks do not merge into one slab. */
.pgm-dark{
  position:relative;overflow:hidden;
  background:radial-gradient(120% 90% at 50% -10%,#1D232C 0%,#141920 46%,#0E1217 100%);
  color:#fff;
  /* the section that follows is also dark; without this the two run together as
     one long slab and the page loses a beat */
  border-bottom:1px solid rgba(255,255,255,.09)
}
.pgm-dark::before{
  content:"";position:absolute;inset:0;z-index:0;pointer-events:none;
  background:repeating-linear-gradient(90deg,transparent 0 calc(100%/7 - 1px),
             rgba(255,255,255,.032) calc(100%/7 - 1px) calc(100%/7));
  mask-image:linear-gradient(180deg,transparent,#000 22%,#000 72%,transparent);
  -webkit-mask-image:linear-gradient(180deg,transparent,#000 22%,#000 72%,transparent)
}
.pgm-dark::after{
  content:"";position:absolute;left:0;right:0;top:0;height:2px;z-index:0;
  background:linear-gradient(90deg,var(--sky),var(--green) 46%,transparent 88%)
}
.pgm-dark > .wrap{position:relative;z-index:1}
.pgm-dark .sec-head h2{color:#fff}
.pgm-dark .sec-head p{color:rgba(255,255,255,.8)}
.pgm-dark .eyebrow{color:var(--sky)}
.pgm-dark .man-eyebrow::before{background:rgba(255,255,255,.3)}

/* the entry gate — was a plain white slab; now two panels that carry the same
   blue/green identity the First Cycle cards use, so "new" and "returning" mean
   the same colour everywhere on the site */
.pgm-dark .entry-rule-note{color:rgba(255,255,255,.82);border-left-color:var(--green)}
.pgm-dark .entry-rule-note b{color:#fff}
.pgm-dark .entry-rule{
  background:rgba(255,255,255,.045);border:1px solid rgba(255,255,255,.14);
  border-radius:var(--r-lg);overflow:hidden;backdrop-filter:blur(6px)
}
.pgm-dark .entry-rule > div{position:relative}
.pgm-dark .entry-rule > div::before{
  content:"";position:absolute;left:0;right:0;top:0;height:3px;background:var(--er-hue,var(--sky))
}
.pgm-dark .entry-rule > div:first-child{--er-hue:var(--sky)}
.pgm-dark .entry-rule > div:last-child{--er-hue:var(--green)}
.pgm-dark .entry-rule > div + div{border-left:1px solid rgba(255,255,255,.14)}
.pgm-dark .entry-rule .who{color:var(--er-hue)}
.pgm-dark .entry-rule h4{color:#fff}
.pgm-dark .entry-rule p{color:rgba(255,255,255,.76)}

/* the six cards */
.pgm-dark .pgc{
  background:rgba(255,255,255,.05);border-color:rgba(255,255,255,.13);color:#fff
}
.pgm-dark .pgc:hover{
  border-color:rgba(255,255,255,.4);background:rgba(255,255,255,.08);
  box-shadow:0 30px 60px -28px rgba(0,0,0,.95)
}
.pgm-dark .pgc-line{color:rgba(255,255,255,.74)}
.pgm-dark .pgc-title{color:#fff}
.pgm-dark .pgc-age{color:var(--sky)}
.pgm-dark .pgc-go{color:var(--sky)}
.pgm-dark .pgc:hover .pgc-go{color:#fff}

/* Narrow Android phones (360px and below is the most common Android width).
   The 860px step already shrinks this pill, and that was tuned on a 390px
   screen. At 360 it is not enough: measured logo 114px + pill 164px leaves a
   0px gap and forces "Book a Gait Analysis" onto two lines, so the logo and
   the button touch. One more step down for the logo and the label fixes both.
   The 48px tap target is untouched — it comes from .btn min-height. */
@media(max-width:400px){
  .brand-logo{height:36px}
  .nav-cta{gap:6px}
  .nav-cta .btn-accent{font-size:10px;letter-spacing:.02em;padding:10px 12px}
}

/* ===== RETURN-TO-PLAY CLEARANCE GATE + FOOTER MEDICAL DISCLAIMER ===== */
/* Both exist because the audit found the site made return-to-sport-shaped claims about
   injured minors with no clearance requirement and no disclaimer on any of the 18 pages.
   The gate is styled to be READ, not skimmed past — it is the first thing on the page after
   the hero. Do not shrink it into fine print. */
.rtp-gate-band{background:var(--paper-2);padding:var(--s-5) 0 0}
.rtp-gate{margin:0;padding:18px 22px;border-radius:var(--r-md);
  border:1px solid rgba(110,168,46,.34);border-left:4px solid var(--green-ink);
  background:rgba(140,198,63,.07);
  font-size:15px;line-height:1.6;color:#4A4E57;max-width:74ch}
.rtp-gate b{color:var(--ink);font-weight:800}

/* Grey and small, but 5.52:1 on the --ink footer — a disclaimer nobody can read is not a
   disclaimer, and this one exists for a legal reason. #6B7079 was the first choice and
   measured 3.60:1, under the 4.5 AA floor. Never darken it past #8A8F98 or go below 12px. */
.foot-med{display:block;margin-top:10px;max-width:78ch;font-size:12px;line-height:1.55;
  color:#8A8F98}
@media(max-width:700px){ .rtp-gate{padding:16px 18px;font-size:14.5px} }

/* ===== COACHES WHO CAN DO IT (.cdo) — index.html + coaches.html ===== */
/* Josh asked for "unique and extremely eye catching and professional". The hook is the
   NUMBERS, not the photography — so the photo is a tall crop that stops at the name, and the
   PRs sit under it at a size nothing else on either page uses.
   Inter throughout, tabular. These are the exact figures a parent will read twice; Bebas
   would condense "44.8" into something you have to squint at, which is the same mistake the
   results cards made. */
.cdo{background:var(--ink);color:#fff;padding:var(--sec) 0;position:relative;overflow:hidden}
.cdo .sec-head h2{color:#fff}
.cdo .sec-note{color:rgba(255,255,255,.72);font-size:16px;max-width:52ch}
.cdo-head{margin-bottom:var(--s-6)}

.cdo-grid{list-style:none;margin:0;padding:0;display:grid;
  grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s-4);align-items:start}
.cdo-card{background:var(--ink-2);border:1px solid var(--line-d);border-radius:var(--r-lg);
  overflow:hidden;display:flex;flex-direction:column;
  transition:transform .25s cubic-bezier(.16,1,.3,1),border-color .25s,box-shadow .25s}
.cdo-card:hover{transform:translateY(-5px);border-color:rgba(99,183,222,.4);
  box-shadow:0 30px 60px -30px rgba(0,0,0,.9)}

.cdo-shot{margin:0;position:relative;aspect-ratio:4/5;overflow:hidden}
.cdo-shot img{width:100%;height:100%;object-fit:cover;object-position:50% 22%;display:block;
  transition:transform .5s cubic-bezier(.16,1,.3,1)}
.cdo-card:hover .cdo-shot img{transform:scale(1.04)}
/* The name sits ON the photo, so it needs its own ground — a scrim, not a guess about how
   dark the picture happens to be behind it. All three frames are bright outdoor shots. */
.cdo-shot figcaption{position:absolute;left:0;right:0;bottom:0;padding:60px 20px 18px;
  background:linear-gradient(180deg,transparent,rgba(15,16,19,.72) 42%,rgba(15,16,19,.94))}
.cdo-tag{display:inline-block;margin-bottom:8px;padding:4px 9px;border-radius:var(--r-sm);
  background:var(--sky);color:var(--ink);
  font-family:var(--body);font-size:9.5px;font-weight:800;letter-spacing:.12em;
  text-transform:uppercase}
.cdo-role{display:block;font-family:var(--body);font-size:10px;font-weight:700;
  letter-spacing:.14em;text-transform:uppercase;color:rgba(255,255,255,.72)}
.cdo-name{display:block;margin-top:5px;font-family:var(--display);font-weight:400;
  font-size:clamp(24px,2.5vw,31px);line-height:.96;letter-spacing:.015em;color:#fff}

.cdo-prs{list-style:none;margin:0;padding:var(--s-2) var(--s-3) var(--s-3);flex:1}
.cdo-prs li{display:flex;align-items:baseline;justify-content:space-between;gap:var(--s-2);
  padding:13px 0;border-bottom:1px solid rgba(255,255,255,.09)}
.cdo-prs li:last-child{border-bottom:0;padding-bottom:4px}
.cdo-prs b{font-family:var(--body);font-weight:800;font-size:30px;line-height:1;
  letter-spacing:-.025em;color:var(--sky);
  font-variant-numeric:tabular-nums;font-feature-settings:"tnum"}
/* Only WORD units shrink (mph). The double-prime is part of the figure's notation, not a
   unit label — shrunk to .46em it read as a stray mark rather than inches, and 10'10" beside
   it was already full size, so the two disagreed. */
.cdo-prs b i{font-style:normal;font-size:.5em;font-weight:700;margin-left:3px;
  letter-spacing:0;color:rgba(99,183,222,.85)}
.cdo-prs span{font-family:var(--body);font-size:10.5px;font-weight:700;letter-spacing:.11em;
  text-transform:uppercase;color:rgba(255,255,255,.62);text-align:right}

.cdo-note{margin:var(--s-4) 0 0;font-size:13px;line-height:1.6;color:rgba(255,255,255,.55);
  max-width:76ch}

@media(max-width:900px){
  .cdo-grid{grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s-3)}
  /* Three cards do not halve. The founder leads, so he takes the full row rather than being
     the one left stranded on his own underneath. */
  .cdo-card:first-child{grid-column:1 / -1}
  .cdo-card:first-child .cdo-shot{aspect-ratio:16/9}
  .cdo-card:first-child .cdo-shot img{object-position:50% 18%}
}
@media(max-width:620px){
  .cdo{padding:var(--sec-sm) 0}
  .cdo-grid{grid-template-columns:1fr}
  .cdo-card:first-child{grid-column:auto}
  .cdo-card:first-child .cdo-shot{aspect-ratio:4/5}
  .cdo-prs b{font-size:27px}
}

/* ================= PEAK PERFORMANCE — BOOKING ==========================
   Josh, Sept 8: "Make sure Peak Performance website link has a button for booking."
   Spectrum Fitness Rehab & Peak Performance is a SEPARATE practice in the same
   building — Josh's standing rule is "PT does not get any of that they are their
   own private entity". So this button goes to THEIR booking form
   (spectrumrehabnj.com/contact/, the destination behind their own "Schedule An
   Appointment" link) and never to a KPM booking flow. It is deliberately a
   secondary control everywhere it appears, so it never outweighs a KPM CTA sharing
   the same screen. Appears on index (#therapy), return-to-play (#in-house) and
   method (#who) — all three on LIGHT grounds, which is what --ink text needs. */
.rx-cta-pt{margin-top:10px}
.pt-book{display:inline-flex;align-items:center;gap:8px;margin-top:var(--s-2);
  font-family:var(--mono);font-size:11.5px;font-weight:800;letter-spacing:.12em;
  text-transform:uppercase;padding:11px 16px;border-radius:var(--r-pill);
  border:1px solid var(--line-l);color:var(--ink);
  transition:border-color .2s,background .2s}
.pt-book:hover{border-color:var(--ink);background:rgba(22,23,26,.04)}
.pt-book .arw{display:inline-block;transition:transform .2s}
.pt-book:hover .arw{transform:translateX(3px)}

/* ================= THE WEEK — CALENDAR BAND (.wk) ======================
   Josh, Sept 8: "make sure on the veteran athletes, new athletes and young guns
   there is a calender like theme highlighting the schedule."
   Six day columns, Monday to Saturday. Sunday is deliberately absent: the facility
   is closed and a seventh empty column only steals width from the six that matter.

   THE TIMES ARE JOSH'S, GIVEN 1 SEPTEMBER. Do not derive them from anything else:
     Ages 11+    3x/week, ONE track for the whole cycle.
                 Track 1 = Mon/Wed/Fri.  Track 2 = Tue/Thu/Sat.
                 Weekday slots 3:30 PM / 4:45 PM / 6:00 PM — pick one, keep it.
                 Track 2's Saturday IS the max-velocity session.
     Young Guns  2x/week, Tue & Thu 3:30 PM at KPM. Saturday 8:30 AM at Atlantic
                 Christian is OPTIONAL for them — required only for Track 2.
   The same figures live in programs.html#hours, faq.html#schedule and the FAQPage
   JSON-LD in faq.html. Change one and you must change all four. */
.wk-band{background:var(--paper-2);padding:var(--sec-sm) 0;
  border-top:1px solid var(--line-l);border-bottom:1px solid var(--line-l)}
.wk-band .sec-head{margin-bottom:var(--s-3)}
.wk-lede{margin:12px 0 0;max-width:64ch;font-size:16px;color:var(--muted)}

.wk-key{list-style:none;display:flex;flex-wrap:wrap;gap:10px var(--s-4);
  margin:0 0 var(--s-3);padding:0}
.wk-key li{display:flex;align-items:center;gap:9px;font-family:var(--mono);
  font-size:12px;font-weight:500;letter-spacing:.05em;color:var(--muted)}
.wk-key b{font-weight:800;letter-spacing:.1em;text-transform:uppercase;color:var(--ink)}
.wk-dot{width:10px;height:10px;border-radius:var(--r-pill);flex:none;
  background:var(--accent-deep)}
.wk-key-2 .wk-dot{background:var(--green-ink)}
.wk-key-opt .wk-dot{background:transparent;border:1px dashed var(--muted)}

.wk{list-style:none;display:grid;grid-template-columns:repeat(6,minmax(0,1fr));
  gap:10px;margin:0;padding:0}
.wk-day{display:flex;flex-direction:column;min-width:0}
.wk-dow{font-family:var(--mono);font-size:11px;font-weight:800;letter-spacing:.16em;
  text-transform:uppercase;color:var(--muted);padding:0 0 9px 2px}
.wk-ev{flex:1;display:flex;flex-direction:column;gap:4px;padding:16px 14px 18px;
  background:var(--paper);border:1px solid var(--line-l);
  border-top:3px solid var(--line-l);border-radius:var(--r-lg)}
.wk-ev-t{font-family:var(--display);font-size:clamp(17px,1.6vw,20px);line-height:1.04;
  text-transform:uppercase;color:var(--ink)}
.wk-ev-w{font-family:var(--mono);font-size:12.5px;font-weight:700;color:var(--ink)}
.wk-ev-l{font-family:var(--mono);font-size:10.5px;font-weight:500;letter-spacing:.09em;
  text-transform:uppercase;color:var(--muted)}

/* .wk-on is the track-less version of .wk-t1, for young-guns.html — that page has no
   Track 1 or Track 2 and must not carry their class names. */
.wk-t1 .wk-ev,.wk-on .wk-ev{border-top-color:var(--accent-deep);background:rgba(58,166,214,.08)}
.wk-t2 .wk-ev{border-top-color:var(--green-ink);background:rgba(140,198,63,.13)}

/* The Saturday max-velocity card is the only one that is somewhere else, so it is the
   only one drawn on ink — it has to be impossible to mistake for a session at 514 New
   Road. --muted-d is white-on-dark and is legal ONLY inside this block. */
/* .wk .wk-ev-mv, not .wk-ev-mv — the Saturday card is inside a .wk-t2 day, and
   `.wk-t2 .wk-ev` is two classes deep. A bare .wk-ev-mv loses to it on specificity and
   the card came out pale green with 56%-white text on it, which is unreadable. */
.wk .wk-ev-mv{background:var(--ink);border-color:var(--ink);border-top-color:var(--green)}
.wk .wk-ev-mv .wk-ev-t,.wk .wk-ev-mv .wk-ev-w{color:#fff}
.wk .wk-ev-mv .wk-ev-l{color:var(--muted-d)}

.wk-tag{align-self:flex-start;margin-top:6px;padding:3px 9px;border-radius:var(--r-pill);
  font-family:var(--mono);font-size:9.5px;font-weight:800;letter-spacing:.16em;
  text-transform:uppercase;background:rgba(22,23,26,.07);color:var(--muted)}
.wk .wk-ev-mv .wk-tag{background:rgba(255,255,255,.16);color:#fff}

/* border, not border-top, so all four sides reset to the dashed 1px rest state */
.wk-ev-off{background:transparent;border:1px dashed var(--line-l);justify-content:center}
.wk-ev-off .wk-ev-t{font-family:var(--mono);font-size:11px;font-weight:700;
  letter-spacing:.12em;color:var(--muted)}

.wk-note{margin:var(--s-3) 0 0;max-width:78ch;font-size:14.5px;line-height:1.62;
  color:var(--muted)}
.wk-note b{color:var(--ink);font-weight:700}
.wk-actions{display:flex;align-items:center;gap:var(--s-3) var(--s-4);flex-wrap:wrap;
  margin-top:var(--s-4)}

@media(max-width:900px){
  .wk{grid-template-columns:repeat(3,minmax(0,1fr))}
}
@media(max-width:560px){
  .wk{grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}
  .wk-ev{padding:13px 11px 15px}
  .wk-actions .btn{width:100%;justify-content:center}
}

/* ================= ANTEPES PAGE (antepes.html) =========================
   Josh, Sept 8: "add a Antepes on the top menu with its own actual page. Pull any
   ad copy available from antepes website."

   OWNERSHIP OF CLAIMS. index.html#gear is the home-page showcase and antepes.html is
   the deep page. Everything a claim can be checked against — the four trademarks, the
   spec table, the usage protocol — now lives on the PAGE. The home page keeps the
   short version and links here. The .antx compact blocks on method.html and
   programs.html link here too, so there is exactly one place that owns the detail.
   Every product figure on that page is Antepes's own, from antepes.com, and the page
   says so twice. Two things stay off it on purpose: the plantar-fasciitis claim
   (clinical, and a gym with a PT partner in the building does not repeat one) and the
   price (their checkout owns that, same rule as ours). */

/* The hero shot is the shoe itself, so it has to CONTAIN, not cover, and it needs its
   own ground — the product photo is a cut-out on alpha. .pd-shot's ink wipe is
   replaced by a gradient stack in the background so the shoe never sits under it. */
.pd-shot-gear{display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:var(--s-2);padding:clamp(26px,4vw,58px);
  background:
    radial-gradient(112% 86% at 60% 46%,transparent 0%,rgba(22,23,26,.55) 54%,var(--ink) 88%),
    linear-gradient(90deg,var(--ink) 0%,rgba(22,23,26,.72) 26%,rgba(22,23,26,.42) 100%),
    url(photos/antepes-track.jpg) center/cover no-repeat}
.pd-shot-gear::after{display:none}
.pd-shot-gear img{width:100%;height:auto;object-fit:contain}
.pd-shot-gear .gear-shoe{max-width:520px;filter:drop-shadow(0 24px 30px rgba(0,0,0,.6))}
.pd-shot-gear .gear-mark{max-width:148px;opacity:.85}
@media(max-width:900px){
  .pd-shot-gear{aspect-ratio:auto;padding:clamp(22px,6vw,40px)}
  .pd-shot-gear .gear-shoe{max-width:360px}
  .pd-shot-gear .gear-mark{max-width:120px}
}

/* Spec table. These are measurements, not marketing lines, and they are the reason
   the page is worth having — the home page cannot carry eight of them. */
.spec{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 var(--s-5);
  margin:var(--s-4) 0 0;padding:0}
.spec div{display:flex;justify-content:space-between;align-items:baseline;gap:var(--s-2);
  padding:13px 0;border-bottom:1px solid var(--line-d)}
.spec dt{font-family:var(--mono);font-size:11.5px;font-weight:500;letter-spacing:.08em;
  text-transform:uppercase;color:var(--muted-d)}
.spec dd{margin:0;font-family:var(--mono);font-size:13.5px;font-weight:700;color:#fff;
  text-align:right;white-space:nowrap}
.spec-src{margin:var(--s-3) 0 0;font-size:12.5px;color:rgba(255,255,255,.6)}
@media(max-width:760px){ .spec{grid-template-columns:1fr} }

/* .quote has existed since the first build and nothing ever used it. It is the right
   card for these two, so it finally gets a grid to sit in. */
.q2{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:22px;margin-top:var(--s-3)}
@media(max-width:760px){ .q2{grid-template-columns:1fr} }
.q-src{margin:var(--s-3) 0 0;font-size:13.5px;line-height:1.6;color:var(--muted-d);max-width:76ch}

/* .cta-inner is text-align:center, which is enough for one button and not for two. */
.cta-actions{display:flex;justify-content:center;align-items:center;gap:var(--s-2) var(--s-3);
  flex-wrap:wrap}
.cta .btn-ghost-l{border-color:rgba(22,23,26,.34);padding:18px 34px;font-size:16px}
.cta .btn-ghost-l:hover{border-color:var(--ink);background:rgba(22,23,26,.06)}
@media(max-width:560px){ .cta-actions .btn{width:100%;justify-content:center} }
