/* ============================================================
   Tracey Potter Coaching — site stylesheet
   Design system: Visual Pass 01 "Performance Editorial",
   built on homepage Direction B (Periodization).
   Source of truth for the look: ../../../wireframes/visual-pass.html

   Deliberately one plain stylesheet, no build step and no
   framework. The whole point of leaving Squarespace is weight:
   the current site ships 188 KB of HTML and 503 KB of unused JS.
   Keep this file boring.

   NOTE ON TYPE: the comp specifies Neue Haas Grotesk Display Pro,
   which is a licensed face we do not own. Nothing here loads a
   webfont — we ride the system grotesk stack instead. That is a
   real performance win (zero font bytes, no FOIT) and it is also
   an open decision: see site/README.md.
   ============================================================ */

:root {
  --ice:        #EFF3F1;
  --paper:      #F8FAF9;
  --graphite:   #171D1A;
  --steel:      #5D6E68;
  --hairline:   #D6DEDA;
  --forest:     #1D3D2E;
  --forest-deep:#0F2419;
  --clay:       #B5502E;

  /* Muted ink, one token per ground. These were a single #8A9A93
     doing both jobs, which met neither: 2.6:1 on the pale grounds
     (unreadable, and most of the site's mono micro-labels use it)
     and unnecessarily bright on the dark ones. Split, and each half
     measured against the ground it actually sits on.
       --steel-2  4.5:1 on --ice, the harder of the two pale grounds
       --on-dark  6.5:1 on --forest-deep
       --on-dark-2 5.4:1 — the dimmer label tint, still passing */
  --steel-2:    #63726C;
  --steel-3:    #4E5E58;   /* hero caption — darkest steel, 5.9:1 on ice */
  --on-dark:    #93A89E;
  --on-dark-2:  #829A8E;

  /* The four seasons. These are GRAPHIC colours — fills, rules,
     nodes, spines — and they are the identity, so they do not move.
     Two of them fail as small text on a pale ground, so the -ink
     variants below exist for that job and nothing else. */
  --st1: #4E7E8C;   /* Heal      — steel blue */
  --st2: #5B7F63;   /* Rebuild   — moss       */
  --st3: #2E5240;   /* Discipline— forest     */
  --st4: #B5502E;   /* Reinvent  — clay       */

  --st1-ink: #3E6675;   /* the same blue, legible at label size */
  --st2-ink: #4A6851;   /* the same moss, ditto                 */

  --grot: "Helvetica Neue", Helvetica, Arial, "Segoe UI", Roboto, system-ui, sans-serif;
  /* Labels and fine print were a monospace until 2026-09-21. Jack found
     it hard to read at label size ("A few questions…", the creds
     strip), so they now set in the same face as everything else. The
     token stays so the label rules remain findable as a group. */
  --label: var(--grot);

  --gut: 48px;   /* horizontal gutter, desktop */

  /* ---------- vertical rhythm ----------
     Section padding was set by hand per page and had drifted to
     thirteen different values between 60 and 92px, which is why the
     page-to-page rhythm read as approximate. Three tokens now, and
     they are fluid, so the mobile step-down happens once here
     instead of in five separate media queries.

       --sec     the default section
       --sec-lg  the signature sections (Method, the closes)
       --sec-sm  strips, ribbons, anything that is a beat not a stop */
  --sec:    clamp(52px, 6.4vw, 76px);
  --sec-lg: clamp(66px, 8.4vw, 96px);
  --sec-sm: clamp(36px, 4.4vw, 54px);

  /* ---------- type ----------
     Same reason: 13.5 / 14 / 14.5 / 15 / 15.5 / 16 / 16.5 / 17 / 17.5
     were all in use for body-sized text. Four sizes now. The small
     end came up — 13.5px was under the floor for a site read by
     people who are having a hard week. */
  --t-lead:  17px;    /* standfirsts, section leads */
  --t-body:  15.5px;  /* body paragraphs            */
  --t-cap:   14.5px;    /* captions, card body, lists */
  --t-fine:  13px;    /* sentence-case fine print   */
  --t-micro: 11.5px;  /* uppercase labels           */
}

* { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }

/* Nothing on this site is allowed to scroll the page sideways.
   `clip` rather than `hidden` so it never creates a scroll
   container that breaks position: sticky later. This is a
   backstop — the real fixes live in the responsive block. */
html, body { max-width: 100%; overflow-x: clip; }

body {
  margin: 0;
  background: var(--ice);
  color: var(--graphite);
  font-family: var(--grot);
  font-size: var(--t-body);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4, p, ul, blockquote, figure { margin: 0; padding: 0; }

/* Display type has to declare its own leading. Without this the
   headings inherit body's 1.6, which at 36-50px opens gaps you can
   park a car in — it was the single loosest thing about the page
   and it affected every unset heading on the site. Anything that
   genuinely wants looser leading sets it on its own class. */
h1, h2, h3, h4 { line-height: 1.1; }
ul { list-style: none; }
img { max-width: 100%; height: auto; display: block; }

a { color: inherit; text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 3px; }

:focus-visible { outline: 2px solid var(--clay); outline-offset: 2px; }

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--forest); color: var(--ice); padding: 12px 18px;
  font-size: 13px;
}
.skip:focus { left: 8px; top: 8px; }

.lbl {
  font-family: var(--label); font-size: var(--t-micro); letter-spacing: 0.1em;
  text-transform: uppercase;
}

/* ---------- buttons ---------- */

/* Upscaled 2026-09-21 at Jack's ask: was 14/26 padding at 12.5px, and
   the one action on the page read as a label rather than a button. */
.btn {
  display: inline-block; padding: 18px 34px;
  font-size: 14px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase;
  background: var(--forest); color: var(--ice); border-radius: 2px;
  border: 0; cursor: pointer; font-family: inherit; text-align: center;
  transition: background .15s ease, transform .15s ease;
}
.btn:hover { background: #17301F; text-decoration: none; transform: translateY(-1px); }
.btn.clay { background: var(--clay); color: #FBF2ED; }
.btn.clay:hover { background: #9C4426; }
.btn[disabled] { opacity: .55; cursor: not-allowed; }

/* ---------- photo placeholders ----------
   Every photograph on this site is still a commission, not an
   asset. These blocks carry the art direction brief so the shot
   list survives contact with the build. Replace with <img>. */

.ph {
  position: relative; display: flex; align-items: flex-end;
  background: linear-gradient(170deg, #C6D3CE 0%, #93A8A0 58%, #718780 100%);
  overflow: hidden;
}
/* real photography — where we actually have the frame.
   The placeholder gradient stays wherever we don't, on purpose. */
.ph.real { background: #DCE3E0; }
.ph.real img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; object-position: 50% 20%;
}

.ph .shot {
  font-family: var(--label); font-size: var(--t-micro); letter-spacing: 0.1em;
  text-transform: uppercase; color: #35443E;
  background: rgba(239, 243, 241, 0.85); padding: 8px 12px; margin: 14px;
  line-height: 1.5; max-width: 34ch;
}

/* ============================================================
   PREVIEW BANNER
   Shown on every page of the preview deploy. It is one element
   and one rule — delete the markup, or set --preview-banner:none,
   to ship. See site/README.md "Going live".
   ============================================================ */

.preview {
  background: var(--clay); color: #FBF2ED;
  padding: 9px var(--gut);
  font-family: var(--label); font-size: var(--t-micro); letter-spacing: 0.08em;
  text-transform: uppercase; text-align: center;
}
.preview b { color: #fff; font-weight: 700; }

/* ---------- header ---------- */

.topbar {
  display: flex; align-items: center; justify-content: space-between; gap: 24px;
  padding: 18px var(--gut); border-bottom: 1px solid var(--hairline); background: var(--ice);
}
.wordmark { display: flex; align-items: center; gap: 10px; }
.wordmark:hover { text-decoration: none; }
/* The bounce mark. Was a 9px square; it is now the same curve as the
   favicon and the season arc, so the identity repeats at three scales
   instead of appearing once. Inline SVG, ~150 bytes, no request. */
.wordmark .glyph {
  width: 21px; height: 14px; flex: none; display: block;
  fill: none; stroke: var(--forest); stroke-width: 2.6;
  stroke-linecap: round; stroke-linejoin: round;
}
.wordmark .name {
  font-weight: 800; font-size: 13.5px; letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--graphite); white-space: nowrap;
}
.topbar nav ul { display: flex; gap: 22px; font-size: 12px; letter-spacing: 0.03em; color: var(--steel); }
.topbar nav a[aria-current="page"] { color: var(--graphite); font-weight: 700; }
.topbar .side { display: flex; align-items: center; gap: 16px; }
.topbar .tel { font-family: var(--label); font-size: var(--t-fine); letter-spacing: 0.02em; color: var(--steel); }
.topbar .btn { padding: 13px 22px; font-size: 12px; }

.navtoggle {
  display: none; background: none; border: 1px solid var(--hairline);
  padding: 8px 12px; border-radius: 2px; cursor: pointer;
  font-family: var(--label); font-size: var(--t-micro); letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--steel);
}

/* ---------- hero ---------- */

.hero {
  display: grid; grid-template-columns: 1.15fr 0.85fr;
  border-bottom: 1px solid var(--hairline); background: var(--ice);
}
.hero .copy {
  padding: var(--sec) 56px var(--sec) var(--gut);
  display: flex; flex-direction: column; justify-content: center; align-items: flex-start;
}
.hero .kicker { color: var(--forest); margin-bottom: 26px; }
.hero h1 {
  font-weight: 780; font-size: clamp(33px, 5vw, 66px); line-height: 1.0;
  letter-spacing: -0.045em; max-width: 20ch; margin-bottom: 26px; text-wrap: balance;
}
/* Hero design pass (2026-09-01): the headline sets on two lines,
   "Rebuild your life / from the inside out." — the 82px three-line
   setting broke the phrase mid-thought. The <em> stays in the markup
   for meaning but no longer changes colour: forest on graphite read
   as a tint, not an accent, and the hero should not carry two
   colours in one sentence. */
.hero h1 em { font-style: normal; color: inherit; }
.hero .sub {
  font-size: var(--t-lead); color: var(--steel); max-width: 46ch; line-height: 1.6; margin-bottom: 34px;
}
.hero .under {
  font-family: var(--label); font-size: var(--t-fine); letter-spacing: 0.02em;
  color: var(--steel-3); margin-top: 16px;   /* 5.9:1 on ice; steel-2 was 4.4:1 */
}
/* 1. The portrait is 1320x2150 forced into a 560px box; at 50% 20%
   cover cropped her hairline. 6. A paper hairline under the photo
   closes the frame against the credential strip, which otherwise
   butted straight into the image. */
.hero .ph { min-height: 560px; border-bottom: 1px solid var(--paper); }
.hero .ph.real img { object-position: 50% 6%; }

/* hero entrance — motion moment 1 of 3.
   No-JS safe: without the .loaded class the rules below never
   hide anything, because the hidden state is scoped to .js. */
.js .hero .rise { opacity: 0; transform: translateY(18px); }
.js .loaded .hero .rise,
.js body.loaded .hero .rise {
  opacity: 1; transform: none;
  transition: opacity .7s ease, transform .7s cubic-bezier(.2, .6, .2, 1);
}
.js body.loaded .hero .rise:nth-child(2) { transition-delay: .08s; }
.js body.loaded .hero .rise:nth-child(3) { transition-delay: .16s; }
.js body.loaded .hero .rise:nth-child(4) { transition-delay: .24s; }
.js body.loaded .hero .rise:nth-child(5) { transition-delay: .32s; }
/* The hero photograph is deliberately NOT part of the entrance
   animation. It is the LCP element, and gating it behind the
   script would delay the largest paint on a site whose whole
   argument is that it loads fast. The comp faded it in; the comp
   was not being measured. Text still rises. */

/* ---------- credential strip ---------- */

.creds {
  display: flex; flex-wrap: wrap;
  border-bottom: 1px solid var(--hairline); background: var(--paper);
}
.creds span {
  flex: 1 1 auto; padding: 16px 24px; text-align: center;
  font-family: var(--label); font-size: var(--t-micro); letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--steel);
  border-right: 1px solid var(--hairline);
}
.creds span:last-child { border-right: 0; }

/* ---------- THE METHOD — signature section ---------- */

.method { background: var(--forest-deep); color: #DCE7E1; padding: var(--sec-lg) var(--gut); }
.method .head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 18px; flex-wrap: wrap; margin-bottom: 10px;
}
.method .head h2 {
  font-weight: 780; font-size: clamp(26px, 3.2vw, 40px); letter-spacing: -0.035em;
  line-height: 1.04; color: #F2F7F4;
}
.method .head .meta {
  font-family: var(--label); font-size: var(--t-micro); letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--on-dark);
}
.method .intro { color: var(--on-dark); max-width: 58ch; font-size: var(--t-body); margin-bottom: 36px; }

/* ---------- the season arc ----------
   Periodization drawn rather than described: arrive falling, bottom
   out in the healing season, leave higher than you came in. The four
   nodes are the four seasons and carry the same colours as the .wk
   labels below, so the graphic and the list are visibly the same
   object.

   Decorative — the stages underneath say all of this in text, so the
   SVG is aria-hidden and nothing is lost without it. Inline, ~700
   bytes, no request, scales to any width. */

.arc { margin-bottom: 30px; }
.arc svg { width: 100%; height: auto; display: block; overflow: visible; }
.arc .base { stroke: rgba(220, 231, 225, 0.16); stroke-width: 1; }
.arc .line {
  fill: none; stroke: #DCE7E1; stroke-width: 2.5;
  stroke-linecap: round; stroke-linejoin: round;
}
.arc .n1 { fill: var(--st1); }
.arc .n2 { fill: var(--st2); }
.arc .n3 { fill: #7FA98F; }
.arc .n4 { fill: #E8A183; }
.arc .halo { fill: none; stroke: #E8A183; stroke-width: 1.5; opacity: .45; }

/* The line draws itself once, in step with the stage reveals below.
   JS-gated and reduced-motion-gated like every other motion here. */
.js .arc .line { stroke-dasharray: 1400; stroke-dashoffset: 1400; }
.js .arc.in .line { transition: stroke-dashoffset 1.5s cubic-bezier(.3, .5, .2, 1); stroke-dashoffset: 0; }
.js .arc .node { opacity: 0; }
.js .arc.in .node { opacity: 1; transition: opacity .5s ease; }
.js .arc.in .n1 { transition-delay: .35s; }
.js .arc.in .n2 { transition-delay: .65s; }
.js .arc.in .n3 { transition-delay: .95s; }
.js .arc.in .n4, .js .arc.in .halo { transition-delay: 1.3s; }

/* Her sentence, verbatim, sitting on the graphic it describes. */
.arc .seasons {
  font-size: var(--t-cap); color: var(--on-dark); max-width: 60ch;
  margin-top: 20px; line-height: 1.6;
}
.arc .seasons b { color: #DCE7E1; font-weight: 600; }

.stage {
  display: grid; grid-template-columns: 130px 1fr 300px;
  gap: 12px 36px; align-items: baseline;
  padding: 30px 0; border-top: 1px solid rgba(220, 231, 225, 0.14);
}
.stage .wk {
  font-family: var(--label); font-size: var(--t-micro); letter-spacing: 0.1em;
  text-transform: uppercase; font-variant-numeric: tabular-nums;
}
.stage .word {
  font-weight: 800; letter-spacing: -0.04em; line-height: 0.95;
  text-transform: uppercase; color: #F2F7F4; text-wrap: balance;
}
/* scale progression — load builds through the block */
.stage.s1 .word { font-size: clamp(30px, 4.6vw, 54px); }
.stage.s2 .word { font-size: clamp(34px, 5.4vw, 64px); }
.stage.s3 .word { font-size: clamp(38px, 6.2vw, 76px); }
.stage.s4 .word { font-size: clamp(42px, 7.2vw, 90px); color: #E8A183; }
.stage .body p { font-size: var(--t-cap); color: var(--on-dark); line-height: 1.6; margin-bottom: 12px; }
/* The .verbs / .verb tags that used to sit under each season body
   were removed from the markup on 2026-09-01 — "its just repeating
   what you are saying for no reason" — and their rules came out with
   them rather than being left as dead CSS. */
.stage.s1 .wk { color: #7FAAB8; }
.stage.s2 .wk { color: #8FB396; }
.stage.s3 .wk { color: #7FA98F; }
.stage.s4 .wk { color: #E8A183; }

/* sequential reveal — motion moment 2 of 3. JS-gated, see above. */
.js .stage { opacity: 0; transform: translateY(22px); }
.js .stage.in {
  opacity: 1; transform: none;
  transition: opacity .65s ease, transform .65s cubic-bezier(.2, .6, .2, 1);
}

.method .after {
  display: flex; align-items: center; gap: 22px; flex-wrap: wrap;
  padding-top: 36px; border-top: 1px solid rgba(220, 231, 225, 0.14);
}
.method .after .note {
  font-family: var(--label); font-size: var(--t-fine); letter-spacing: 0.02em; color: var(--on-dark);
}

/* ---------- who — editorial list, not cards ---------- */

.who { padding: var(--sec) var(--gut); background: var(--ice); }
.seclead {
  font-weight: 780; font-size: clamp(24px, 3vw, 36px); letter-spacing: -0.032em;
  line-height: 1.06; margin-bottom: 10px; text-wrap: balance;
}
.secsub { color: var(--steel); font-size: var(--t-body); line-height: 1.7; max-width: 58ch; margin-bottom: 38px; }
.who .row {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr); gap: 10px 44px;
  align-items: baseline; padding: 30px 0; border-top: 1px solid var(--hairline);
}
.who .row:last-child { border-bottom: 1px solid var(--hairline); }
.who .row h4 {
  font-weight: 750; font-size: clamp(19px, 2.2vw, 26px);
  letter-spacing: -0.025em; line-height: 1.12; text-wrap: balance;
}
.who .row p { font-size: var(--t-body); color: var(--steel); line-height: 1.7; max-width: 46ch; }

/* ============================================================
   THE TIMELINE BAND — redesigned 2026-08-26.

   This was a 380px "Photo 02" slot: a grey-green gradient with an
   art-direction note pinned in the corner and a caption laid over
   it. With no photograph it read as a broken image, and it was the
   weakest block on the page by some distance.

   The photograph is still not commissioned and may never be, so
   this stops depending on one. Instead the band does the job a
   photograph could not: it draws the bounce mark at its largest
   scale. The curve is already the favicon, the wordmark glyph and
   the season arc — this is the same line a fourth time, running
   the full width of the page, and it is the only place on the site
   where the identity is the size of the identity.

   The line over it is hers, verbatim, and the canon nominated this
   exact slot for it (research/tracey-canon-2026-08-22.md §2,
   "Start Here / homepage season band").

   IF THE PHOTOGRAPH IS EVER SHOT, this markup takes it: drop an
   <img> in as the first child of .band and add .haspic. The brief
   is preserved in the comment above the band in index.html — do
   not lose it, it is the commission spec.
   ============================================================ */

.band {
  position: relative; overflow: hidden;
  background: var(--forest-deep); color: #DCE7E1;
  padding: var(--sec-lg) var(--gut);
}
/* the mark, drawn large. Decorative and aria-hidden — the sentence
   over it says everything, so a screen reader loses nothing. */
.band .curve {
  position: absolute; left: -4%; right: -4%; top: 50%; width: 108%;
  transform: translateY(-50%); height: auto; display: block; pointer-events: none;
}
.band .curve path {
  fill: none; stroke: rgba(220, 231, 225, 0.20); stroke-width: 2.5;
  stroke-linecap: round; stroke-linejoin: round; vector-effect: non-scaling-stroke;
}
.band .curve .dot { fill: rgba(232, 161, 131, 0.75); stroke: none; }
/* subtle drift on scroll — motion moment 3 of 3. It moves the
   graphic now rather than a gradient, which is the same gesture
   against something you can actually see. */
.band .curve { transition: transform .2s linear; will-change: transform; }

.band .inner { position: relative; max-width: 900px; }
.band .lbl { color: var(--on-dark-2); display: block; margin-bottom: 22px; }
.band .caption {
  color: #F2F7F4; max-width: 17ch;
  font-weight: 780; font-size: clamp(28px, 5vw, 60px);
  letter-spacing: -0.042em; line-height: 1.02; text-wrap: balance;
}
.band .caption em { font-style: normal; color: #E8A183; }

/* photograph slot, for the day it exists */
.band.haspic > img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; z-index: 0;
}
.band.haspic::after {
  content: ""; position: absolute; inset: 0; z-index: 0;
  background: linear-gradient(90deg, rgba(15,36,25,.86) 0%, rgba(15,36,25,.45) 70%);
}
.band.haspic .inner { z-index: 1; }

/* ---------- program + price ---------- */

.prog { padding: var(--sec) var(--gut); background: var(--paper); border-bottom: 1px solid var(--hairline); }
.prog .inner { display: grid; grid-template-columns: 1.15fr 0.85fr; gap: 56px; align-items: start; }
.prog .secsub { max-width: 52ch; margin-bottom: 26px; }
.incl { display: grid; gap: 11px; }
.incl li {
  font-size: var(--t-cap); color: var(--steel); padding-left: 22px; position: relative; line-height: 1.6;
}
.incl li::before {
  content: ""; position: absolute; left: 0; top: 9px;
  width: 10px; height: 2px; background: var(--forest);
}
.pricecard { border: 1px solid var(--hairline); background: #fff; padding: 32px 30px; }
.pricecard .t {
  font-family: var(--label); font-size: var(--t-micro); letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--steel); display: block; margin-bottom: 12px;
}
.pricecard .amt {
  font-family: var(--label); font-weight: 500; font-size: 44px; letter-spacing: -0.03em;
  line-height: 1; display: block; margin-bottom: 4px; color: var(--clay);
  font-variant-numeric: tabular-nums;
}
/* The price is the last unfilled thing on the site. Labelling the
   gap is more honest than letting a bare em dash read as an
   oversight, and it matches the treatment on /programs. */
.pricecard .todo {
  font-family: var(--label); font-size: var(--t-micro); letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--clay); display: block; margin-bottom: 16px;
}
.pricecard p { font-size: var(--t-cap); color: var(--steel); margin-bottom: 20px; line-height: 1.6; }
/* 2026-09-15: the pricecard and the closing band lost their buttons (one CTA
   per page) and gained an inline "Apply for coaching" link instead.
   2026-09-21: Jack asked for both back as buttons — the inline links read
   as footnotes. The link rule stays for any prose link in the card. */
.pricecard p a { color: var(--forest-deep); text-decoration: underline; text-underline-offset: 3px; }
.pricecard .btn { width: 100%; margin-top: 6px; }

/* An unresolved value we are NOT allowed to invent. Marked in the
   markup with data-pending so a grep finds every one of them.

   The dotted marker is a review affordance, so it is keyed to the
   preview banner: the same element the launch checklist deletes.
   Remove the banner and every marker goes with it in the same
   commit, instead of a clay dotted line surviving under whichever
   attribute was forgotten. Browsers without :has() simply never draw
   the marker, which is the launch state, not a regression. */
body:has(> .preview) [data-pending] { border-bottom: 2px dotted var(--clay); }

/* ---------- the record — editorial numerals ----------
   Twenty-nine years is the least fakeable thing she owns and it was
   previously one sentence in a credential strip. Set large, set still:
   no count-up animation, which would undercut the point. */

.record {
  padding: var(--sec) var(--gut); background: var(--ice);
  border-top: 1px solid var(--hairline); border-bottom: 1px solid var(--hairline);
}
.record .secsub { margin-bottom: 44px; }
.record .figs { display: grid; grid-template-columns: repeat(3, 1fr); gap: 0; }
.record .fig {
  padding: 0 32px; border-left: 1px solid var(--hairline);
}
.record .fig:first-child { padding-left: 0; border-left: 0; }
.record .num {
  display: block; font-weight: 800; letter-spacing: -0.055em; line-height: 0.86;
  font-size: clamp(56px, 9vw, 116px); color: var(--forest);
  font-variant-numeric: tabular-nums lining-nums; margin-bottom: 16px;
}
.record .fig:last-child .num { color: var(--clay); }
.record .cap {
  display: block; font-size: var(--t-cap); color: var(--steel);
  line-height: 1.6; max-width: 26ch;
}
.record .cap b { color: var(--graphite); font-weight: 650; }

/* ---------- proof — pull quotes, no containers ---------- */

/* Colour is set here, not inherited. /programs paints its whole
   <main> in pale-on-dark text, and when the pull quotes moved onto
   that page in v3 they inherited it: the heading and all four quotes
   rendered #DCE7E1 on paper, 1.3:1, effectively invisible. This
   block is always on paper, so it always states its own ink. */
.proof { padding: var(--sec-lg) var(--gut); background: var(--paper); color: var(--graphite); }
.proof .seclead { font-size: clamp(30px, 4.2vw, 50px); }
.proof .secsub { margin-bottom: 52px; }

/* Rebuilt 2026-09-21 at Jack's ask for the section to carry more
   weight. It was four equal quotes in one column with a pale grey
   mark, every second one stepped in 72px; nothing in it was louder
   than the body copy around it. Now the first quote is a lead at
   display size and the other three sit in a row under it, each
   under a forest rule. The mark is clay: it is the one accent on the
   page and this is where it is spent.

   Everything is scoped to .proof. /for-athletes/ reuses .pull with
   its own inline rules and only wants the two base declarations. */
.pull { max-width: 780px; position: relative; }
.pull blockquote { margin: 0 0 14px; letter-spacing: -0.022em; text-wrap: balance; }

.proof .pulls {
  display: grid; grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 0 44px; max-width: 1180px;
}
.proof .pull { max-width: none; padding: 24px 0 0; border-top: 2px solid var(--forest); }
.proof .pull .mark {
  display: block; height: 0.42em; margin-bottom: 14px;
  font-weight: 800; font-size: 54px; line-height: 1; color: var(--clay);
}
.proof .pull blockquote { font-weight: 500; font-size: 17.5px; line-height: 1.5; margin-bottom: 18px; }
.proof .pull .who2 {
  display: block; font-family: var(--label); font-size: var(--t-micro); letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--steel-3);
}
.proof .pull:first-child { grid-column: 1 / -1; border-top: 0; padding: 0 0 60px; max-width: 980px; }
.proof .pull:first-child .mark { font-size: 120px; margin-bottom: 22px; }
.proof .pull:first-child blockquote {
  font-weight: 700; font-size: clamp(27px, 3.5vw, 44px);
  letter-spacing: -0.03em; line-height: 1.16; margin-bottom: 24px;
}
.proof .pull:first-child .who2 { font-size: 12.5px; color: var(--graphite); }

/* ---------- magnet ---------- */

.magnet { padding: var(--sec) var(--gut); background: var(--ice); border-top: 1px solid var(--hairline); }
.magnet .inner {
  display: grid; grid-template-columns: 1.1fr 1fr; gap: 48px; align-items: center;
  border: 1px solid var(--hairline); background: var(--paper);
  padding: 38px 40px 40px;
}
.magnet .inner::before {
  content: ""; position: absolute; left: 40px; top: -1px; width: 46px; height: 3px;
  background: var(--clay);
}
.magnet { position: relative; }
.magnet .inner { position: relative; }
.magnet h3 {
  font-weight: 780; font-size: clamp(21px, 2.4vw, 28px); letter-spacing: -0.03em;
  line-height: 1.12; margin-bottom: 10px; max-width: 18ch; text-wrap: balance;
}
.magnet p { font-size: var(--t-body); color: var(--steel); line-height: 1.65; }

/* ---------- forms ---------- */

.fieldrow { display: flex; gap: 10px; flex-wrap: wrap; }
.fieldrow > * { flex: 1 1 180px; }

.field label,
.formgrid label {
  display: block; font-family: var(--label); font-size: var(--t-micro); letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--steel); margin-bottom: 6px;
}
input[type="text"], input[type="email"], input[type="tel"], textarea, select {
  width: 100%; border: 1px solid var(--hairline); background: #fff;
  padding: 13px 14px; font-size: 14px; color: var(--graphite);
  font-family: inherit; border-radius: 2px;
}
textarea { min-height: 140px; resize: vertical; }
input:focus, textarea:focus, select:focus { border-color: var(--forest); }

.formgrid { display: grid; gap: 18px; max-width: 560px; }
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.formnote {
  font-family: var(--label); font-size: var(--t-fine); letter-spacing: 0.02em;
  color: var(--steel-2); line-height: 1.6;
}
.formstatus { font-size: var(--t-cap); padding: 14px 16px; border-left: 3px solid var(--forest); background: var(--paper); }
.formstatus[data-state="error"] { border-left-color: var(--clay); }
.formstatus:empty { display: none; }

/* ---------- close — the peak ---------- */

.close { padding: var(--sec-lg) var(--gut); background: var(--forest-deep); color: #DCE7E1; text-align: center; }
.close h3 {
  font-weight: 780; font-size: clamp(28px, 4.2vw, 50px); letter-spacing: -0.04em;
  line-height: 1.04; color: #F2F7F4; margin: 0 auto 16px; max-width: 22ch; text-wrap: balance;
}
.close p { color: var(--on-dark); font-size: var(--t-body); max-width: 46ch; margin: 0 auto 30px; }
.close p a { color: #DCE7E1; text-decoration: underline; text-underline-offset: 3px; }
/* 2026-09-21: the close was one centred paragraph, and the sentence in it
   is a serious one — she may say no. The instruction, the two outcomes and
   the button are now separate things: each outcome gets its own cell, the
   condition dim above the promise. One column under 640. */
.close .lede { font-size: var(--t-lead); color: #DCE7E1; margin-bottom: 26px; }
.close .paths {
  display: grid; grid-template-columns: 1fr 1fr; max-width: 680px; margin: 0 auto 38px;
  border-top: 1px solid rgba(220, 231, 225, .16); border-bottom: 1px solid rgba(220, 231, 225, .16);
}
.close .paths p {
  margin: 0; max-width: none; padding: 24px 26px;
  font-size: var(--t-lead); line-height: 1.45; color: #F2F7F4; text-wrap: balance;
}
.close .paths p + p { border-left: 1px solid rgba(220, 231, 225, .16); }
.close .paths span { display: block; margin-bottom: 6px; font-size: var(--t-body); color: var(--on-dark); }
@media (max-width: 640px) {
  .close .paths { grid-template-columns: 1fr; }
  .close .paths p { padding: 20px 8px; }
  .close .paths p + p { border-left: 0; border-top: 1px solid rgba(220, 231, 225, .16); }
}
.close .fine {
  font-family: var(--label); font-size: var(--t-fine); letter-spacing: 0.02em;
  color: var(--on-dark-2); margin-top: 22px; max-width: none;
}

/* ---------- interior pages ---------- */

.page { padding: var(--sec) var(--gut); background: var(--ice); }
.page .inner { max-width: 760px; }
.page .kicker { color: var(--clay); display: block; margin-bottom: 18px; }
.page h1 {
  font-weight: 780; font-size: clamp(30px, 4.6vw, 54px); line-height: 1.02;
  letter-spacing: -0.04em; margin-bottom: 18px; max-width: 18ch; text-wrap: balance;
}
.page .standfirst { color: var(--steel); font-size: var(--t-lead); max-width: 58ch; line-height: 1.6; margin-bottom: 30px; }
.page .body p { margin-bottom: 16px; color: var(--steel); font-size: var(--t-body); line-height: 1.7; max-width: 62ch; }
.page h2 { font-weight: 780; font-size: clamp(20px, 2.4vw, 28px); letter-spacing: -0.03em; margin: 34px 0 12px; }

/* The 404's bounce mark: the curve runs, then goes dotted and
   wanders off where the page should have been. */
.lostmark { width: 240px; max-width: 60%; height: auto; display: block; margin: 4px 0 26px; }
.lostmark .line {
  fill: none; stroke: var(--forest); stroke-width: 3;
  stroke-linecap: round; stroke-linejoin: round;
}
.lostmark .ghost {
  fill: none; stroke: var(--steel-2); stroke-width: 3;
  stroke-linecap: round; stroke-dasharray: 2 9; opacity: .8;
}
.lostmark .dot { fill: var(--clay); }

/* ============================================================
   THE EDITORIAL SPLIT
   Heading column, then content column. Four pages had each invented
   their own name for this grid before it was written down once; it
   lives here so the fifth does not invent a fifth.
   ============================================================ */

.split { display: grid; grid-template-columns: 0.82fr 1.18fr; gap: 24px 56px; align-items: start; }
.split.wide  { grid-template-columns: 1.1fr 0.9fr; }
.split.even  { grid-template-columns: 1fr 1fr; }
.split > .col { min-width: 0; }
.split .measure { max-width: 60ch; }

/* ============================================================
   HUB PAGES
   /results, /journal and the three keyword hubs. Their body copy is
   gated on Tracey, but their structure is not, so they are built as
   real pages with a designed gate rather than held as placeholders.
   ============================================================ */

.hubhead { padding: var(--sec-lg) var(--gut) var(--sec); border-bottom: 1px solid var(--hairline); }
.hubhead .kicker { display: block; margin-bottom: 20px; color: var(--clay); }
.hubhead h1 {
  font-weight: 780; font-size: clamp(31px, 5vw, 54px); line-height: 1.02;
  letter-spacing: -0.042em; max-width: 15ch; margin: 0; text-wrap: balance;
}
.hubhead h1 em { font-style: normal; color: var(--forest); }
.hubhead .standfirst {
  font-size: var(--t-lead); color: var(--steel); max-width: 50ch; line-height: 1.6; margin: 0;
}
.hubhead .split { align-items: end; }

.hubsec { padding: var(--sec) var(--gut); border-bottom: 1px solid var(--hairline); }
.hubsec.paper { background: var(--paper); }
.hubsec h2 {
  font-weight: 780; font-size: clamp(23px, 2.9vw, 34px); letter-spacing: -0.032em;
  line-height: 1.08; margin: 0; max-width: 16ch; text-wrap: balance;
}
.hubsec .k {
  font-family: var(--label); font-size: var(--t-micro); letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--forest); display: block; margin-bottom: 14px;
}
.hubsec p { color: var(--steel); line-height: 1.7; margin: 0 0 16px; }
.hubsec p:last-child { margin-bottom: 0; }

/* ---------- the gate ----------
   Replaces the red warning box on the five unwritten pages. Same job
   — it must be impossible to mistake for finished work — but it is
   the last thing you read rather than the first thing you see, and it
   is designed rather than alarming. Everything in it still carries
   data-pending, so `grep -rn data-pending site/` still finds it. */

/* Graphite, not forest-deep: on four of the five pages the gate sits
   directly above the close, and two identical dark grounds separated
   by a hairline read as one very long dark block. Graphite is also
   the footer's ground, which is the right register for a note about
   the page rather than a part of it. */
.gate { background: var(--graphite); color: #DCE7E1; padding: var(--sec) var(--gut); }
.gate .inner {
  display: grid; grid-template-columns: 0.92fr 1.08fr;
  /* the fourth row is empty and exists to absorb the height the list
     adds, so the left column stays pinned to the top instead of
     spreading itself down the block */
  grid-template-rows: auto auto auto 1fr;
  gap: 10px 56px; align-items: start;
}
.gate .tag { grid-column: 1; grid-row: 1; }
.gate h3   { grid-column: 1; grid-row: 2; }
.gate > .inner > p { grid-column: 1; grid-row: 3; }
.gate ul { grid-column: 2; grid-row: 1 / -1; }
@media (max-width: 860px) {
  .gate .inner { grid-template-columns: 1fr; grid-template-rows: none; gap: 10px; }
  .gate .tag, .gate h3, .gate > .inner > p, .gate ul { grid-column: 1; grid-row: auto; }
  .gate ul { margin-top: 10px; }
}
.gate .tag {
  font-family: var(--label); font-size: var(--t-micro); letter-spacing: 0.1em;
  text-transform: uppercase; color: #E8A183; display: block; margin-bottom: 16px;
}
.gate h3 {
  font-weight: 750; font-size: clamp(20px, 2.4vw, 27px); letter-spacing: -0.03em;
  line-height: 1.1; color: #F2F7F4; margin: 0 0 14px; max-width: 26ch; text-wrap: balance;
}
.gate > .inner > p { color: var(--on-dark); line-height: 1.7; max-width: 46ch; margin: 0; }
.gate ul { display: grid; gap: 14px; margin: 0; padding: 0; max-width: 56ch; align-content: start; }
/* padding + an absolute rule, not a grid: the <b> and the text after
   it are two separate children, so a grid put every trailing word in
   its own 16px row. */
.gate li {
  position: relative; padding-left: 24px;
  font-size: var(--t-cap); color: var(--on-dark); line-height: 1.65;
}
.gate li::before {
  content: ""; position: absolute; left: 0; top: 10px;
  width: 12px; height: 2px; background: #E8A183;
}
.gate li b { color: #F2F7F4; font-weight: 600; }

/* ============================================================
   /RESULTS — the clients wall.
   Warmer than the homepage's editorial pull-quotes on purpose: this
   is the page where the people are the content, so they get cards
   with a face-shaped amount of space rather than a column of rules.
   ============================================================ */

.wall { padding: var(--sec) var(--gut); background: var(--paper); border-bottom: 1px solid var(--hairline); }
.wall .grid {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1px; background: var(--hairline); border: 1px solid var(--hairline); margin-top: 40px;
}
.client { background: var(--ice); padding: 34px 34px 30px; display: flex; flex-direction: column; }
.client .dur {
  font-family: var(--label); font-size: var(--t-micro); letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--clay); display: block; margin-bottom: 18px;
}
.client blockquote {
  margin: 0 0 22px; font-size: clamp(16px, 1.7vw, 19px); font-weight: 500;
  letter-spacing: -0.016em; line-height: 1.5; color: var(--graphite); flex: 1;
}
.client .att { display: grid; gap: 3px; padding-top: 16px; border-top: 1px solid var(--hairline); }
.client .att .nm { font-weight: 700; font-size: 15px; letter-spacing: -0.018em; }
.client .att .role {
  font-family: var(--label); font-size: var(--t-micro); letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--steel);
}

/* the three whose words we do not have. Named rather than invented —
   they are on her current About page, and the gap is the permission,
   not the person. */
.client.awaited { background: var(--paper); }
.client.awaited .said {
  font-size: var(--t-body); color: var(--steel); line-height: 1.65; margin: 0 0 22px; flex: 1;
}
.client.awaited .said b { color: var(--graphite); font-weight: 600; }

@media (max-width: 860px) {
  .wall .grid { grid-template-columns: 1fr; }
  .client { padding: 28px 24px 26px; }
}

/* ============================================================
   /JOURNAL — the index, empty.
   Built as the index it will be rather than held as a placeholder:
   the four lanes are the four keyword clusters that survived recon,
   and each one says what it is for and what would go in it. No post
   titles are printed, because no posts exist.
   ============================================================ */

.lanes { padding: var(--sec) var(--gut); border-bottom: 1px solid var(--hairline); }
.lanes.paper { background: var(--paper); }
.lane {
  display: grid; grid-template-columns: 52px minmax(0, 1fr) minmax(0, 1.25fr);
  gap: 10px 44px; align-items: baseline;
  padding: 30px 0; border-top: 1px solid var(--hairline);
}
.lane:last-of-type { border-bottom: 1px solid var(--hairline); }
.lane .n {
  font-family: var(--label); font-size: var(--t-fine); letter-spacing: 0.02em; color: var(--clay);
  font-variant-numeric: tabular-nums;
}
.lane h3 {
  font-weight: 750; font-size: clamp(18px, 2.1vw, 24px); letter-spacing: -0.026em;
  line-height: 1.14; margin: 0; max-width: 20ch; text-wrap: balance;
}
.lane p { font-size: var(--t-body); color: var(--steel); line-height: 1.7; max-width: 46ch; margin: 0; }
.lane .count {
  display: block; margin-top: 12px; font-family: var(--label); font-size: var(--t-micro);
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--steel-2);
}
/* "The hub is here" was the link text on all four lanes — useless to a
   screen reader pulling a link list, and useless to a crawler. The
   destination names itself now. */
.lane .count a { color: var(--forest); text-decoration: underline; text-underline-offset: 3px; }
.lane .count a:hover { color: var(--clay); }
@media (max-width: 860px) {
  .lane { grid-template-columns: 1fr; gap: 6px; }
}

/* ============================================================
   THE COACHING/THERAPY LINE
   The device on /trauma-informed-coaching, and the reason anyone
   searching that phrase is searching it. Two columns, stated plainly,
   with the referral posture underneath rather than in a footnote.

   Called .vs rather than the obvious .line: /start-here already has
   .jewel .line spans, and a global .line rule painted that page's one
   dark pull-quote pale-on-pale. Caught by the contrast sweep.
   ============================================================ */

.vs { padding: var(--sec) var(--gut); background: var(--paper); border-bottom: 1px solid var(--hairline); }
.vs .cols { display: grid; grid-template-columns: 1fr 1fr; gap: 1px; background: var(--hairline);
  border: 1px solid var(--hairline); margin-top: 36px; }
.vs .side { background: var(--ice); padding: 30px 32px 34px; }
.vs .side.other { background: var(--paper); }
.vs .side .h {
  font-family: var(--label); font-size: var(--t-micro); letter-spacing: 0.1em;
  text-transform: uppercase; display: block; margin-bottom: 20px; padding-bottom: 14px;
  border-bottom: 2px solid var(--forest); color: var(--forest);
}
.vs .side.other .h { border-bottom-color: var(--steel-2); color: var(--steel); }
.vs .side ul { display: grid; gap: 14px; }
.vs .side li {
  font-size: var(--t-cap); color: var(--steel); line-height: 1.6;
  padding-left: 20px; position: relative;
}
.vs .side li::before {
  content: ""; position: absolute; left: 0; top: 9px; width: 10px; height: 2px; background: var(--forest);
}
.vs .side.other li::before { background: var(--steel-2); }
@media (max-width: 860px) { .vs .cols { grid-template-columns: 1fr; } }

/* ---------- footer ---------- */

.sitefoot {
  background: var(--graphite); color: #A9B8B1;
  padding: var(--sec-sm) var(--gut) 40px;
}
.sitefoot .cols {
  display: grid; grid-template-columns: 1.4fr 1fr 1fr; gap: 40px;
  padding-bottom: 34px; border-bottom: 1px solid rgba(169, 184, 177, .18);
}
.sitefoot h4 {
  font-family: var(--label); font-size: var(--t-micro); letter-spacing: 0.1em;
  text-transform: uppercase; color: #E4EDE8; margin-bottom: 14px; font-weight: 600;
}
.sitefoot ul { display: grid; gap: 10px; font-size: var(--t-cap); }
.sitefoot .blurb { font-size: var(--t-cap); max-width: 34ch; line-height: 1.65; }
.sitefoot .wordmark .name { color: #F2F7F4; }
.sitefoot .wordmark { margin-bottom: 14px; }
.sitefoot .wordmark .glyph { stroke: var(--clay); }
.sitefoot .base {
  padding-top: 20px; display: flex; flex-wrap: wrap; gap: 6px 24px;
  font-family: var(--label); font-size: var(--t-fine); letter-spacing: 0.02em; color: #7C8C85;
}
.sitefoot .base b { color: #C9D6D0; font-weight: 600; }

/* The 988 crisis line is the only link in this strip, and until now it was
   the one nobody could find: it inherited the body colour (#7C8C85) at the
   same weight with no underline, so "988" read as plain text in a sentence.
   Three things are wrong with that and all three are the same question —
   can a person in crisis, on a phone, actually use this link.

   1.4.1  It is now underlined, so it is identifiable without relying on
          colour at all.
   1.4.3  #C9D6D0 on the #171D1A footer measures 11.4:1, up from 4.85:1.
          Both pass AA; the point is that it now reads as interactive
          rather than merely legible. Measured, per the note above.
   2.5.8  The tap target was 20x11 at 10px. The padding below takes it past
          24x24. It is deliberately on an inline element: inline padding
          grows the hit area and is painted, but does not touch the line
          box, so the sentence does not reflow and the footer rhythm is
          unchanged. The negative inline margin keeps the surrounding words
          from being pushed apart.

   Deliberately NOT enlarged visually. The restraint of this line is the
   point — it should not shout at someone who is not in crisis. Nothing
   here changes its size or weight. */
.sitefoot .base a {
  color: #C9D6D0;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
  padding: 7px 4px;
  margin: 0 -4px;
}
.sitefoot .base a:hover,
.sitefoot .base a:focus-visible { color: #FFFFFF; }

/* ---------- responsive ---------- */

@media (max-width: 860px) {
  :root { --gut: 22px; }

  /* Narrow-screen overflow guards. Every one of these fixes a real
     clipped element found at 390px, not a hypothetical: a flex
     container with align-items:flex-start sizes children to
     max-content, which lets long uppercase button labels and the
     letterspaced kicker push past the viewport. */
  .hero .copy > * { max-width: 100%; }
  .btn { max-width: 100%; white-space: normal; }
  .hero .kicker { letter-spacing: 0.1em; font-size: 9.5px; }
  .topbar .btn { padding: 11px 16px; font-size: 11px; letter-spacing: 0.02em; }
  .creds span { flex-basis: 50%; }

  /* At 375 the wordmark, Menu and the header button came to a few
     pixels more than the row, so the button dropped to a line of its
     own and made the header two rows tall before any content
     appeared. (The button was labelled "Book a Call" when this was
     measured; it became "Apply for coaching" on 2026-09-15 and is
     wider. Re-measure in a real viewport.) */
  .topbar { flex-wrap: wrap; gap: 10px 12px; }
  .topbar .side { gap: 10px; }
  .topbar nav { order: 3; flex-basis: 100%; }
  .topbar nav ul { flex-wrap: wrap; gap: 14px 18px; }
  .topbar .tel { display: none; }
  .js .topbar nav[data-collapsible] { display: none; }
  .js .topbar nav[data-collapsible].open { display: block; }
  .js .navtoggle { display: inline-block; }

  .hero { grid-template-columns: minmax(0, 1fr); }
  .hero .copy { padding: 36px var(--gut) 40px; }
  /* Phone: she comes first. A 300px band of face under a wall of text
     put her below the fold on the page whose whole argument is the
     person. 4:5 crop, headline directly beneath. */
  .hero .ph { order: -1; min-height: 0; aspect-ratio: 4 / 5; border-bottom: 0; }
  .hero .ph.real img { object-position: 50% 18%; }
  .stage { grid-template-columns: 1fr; gap: 8px; padding: 24px 0; }
  .who .row { grid-template-columns: 1fr; gap: 6px; }
  .band .caption { bottom: 24px; }
  .prog .inner, .magnet .inner, .sitefoot .cols { grid-template-columns: 1fr; gap: 26px; }
  .proof .pulls { grid-template-columns: 1fr; gap: 34px 0; }
  .proof .pull:first-child { padding-bottom: 10px; }
  .proof .pull:first-child .mark { font-size: 84px; }

  /* The editorial split never collapsed. Every other two-column grid
     on the site goes single-column here, but .split was written after
     this block and never got a rule, so on a phone the six pages built
     on it (/resources and the five hubs) kept two columns at 390px:
     a 150px heading column pinned to the bottom of the row beside a
     body column wrapping every four words. Found 2026-09-07 in a real
     390px viewport. Heading, then body, same as every other section. */
  .split, .split.wide, .split.even { grid-template-columns: 1fr; gap: 14px; }
  .hubhead .split { align-items: start; }

  /* Three 116px numerals will not sit side by side on a phone. Stack
     them and move the hairline from left edge to top edge. */
  .record .figs { grid-template-columns: 1fr; }
  .record .fig {
    padding: 22px 0 0; border-left: 0; border-top: 1px solid var(--hairline);
  }
  .record .fig:first-child { padding-top: 0; border-top: 0; }
  .record .cap { max-width: 40ch; }
}

@media (max-width: 420px) {
  /* The wordmark gained a word on 2026-09-01 ("Tracey Potter Coaching"),
     and it is set uppercase, tracked and nowrap, so it is the widest
     thing in the header row. Measured at a real 390px viewport: the
     row has 346px of usable width, and wordmark + Menu + "Book a
     Call" came to 359 before this rule and 331 after it. The button
     was relabelled "Apply for coaching" on 2026-09-15, which is wider
     than anything measured here — these numbers need re-taking in a
     real viewport before launch. Keep them on one
     line — the button dropping to a second row makes the header two
     rows tall before any content appears, which is exactly what the
     860px block above was written to prevent. */
  .wordmark .name { font-size: 9.5px; letter-spacing: 0.05em; }
  .topbar { gap: 8px 10px; }
  .wordmark .glyph { width: 18px; height: 12px; }
  .navtoggle { padding: 8px 10px; }

  /* 390 was the only width measured. At 375 — iPhone SE, 12/13 mini —
     the row has 331px and the three pieces came to 335 (wordmark 173,
     Menu 51, button 91, two 10px gaps), so the button dropped to its
     own row again. Measured 2026-09-07. Four pixels back from the
     button's padding, four from the two gaps: 327, one row. At 360
     (small Android) the row has 316 and it still wraps; that is a
     taller header, not a broken one, and it is left alone.
     (2026-09-21: the 9px 10px squeeze on the button is gone. The header
     button is hidden at 520 and below, so this block only ever styles it
     from 521 up, where the row has room for the upscaled size.) */
  .topbar .side { gap: 8px; }
  .topbar { column-gap: 8px; }

}

/* Measured 2026-09-16 in a real viewport: "Apply for coaching" is 131px
   wide at 375 and 135px at 422, 40 more than "Book a Call" was, so the
   header row cannot be made to fit by trimming padding below ~520px.
   Rather than a two-row header on every phone, the header button goes
   at those widths: the same link is the last item in the Menu, and every
   page's one in-page CTA carries the same label. */
@media (max-width: 520px) {
  .topbar .side { display: none; }
}
/* The nav's "Apply for coaching" item exists for the phone Menu, where
   the header button is hidden. Above that width the button is showing,
   so the item would be the same link twice in one bar (Jack, 2026-09-16). */
@media (min-width: 521px) {
  .topbar nav li.apply { display: none; }
}

/* ============================================================
   CROSS-DOCUMENT VIEW TRANSITIONS
   Page-to-page navigation cross-fades instead of flashing white.
   Three declarations, no JavaScript, no library, zero bytes on the
   wire beyond this rule — and in a browser without support it is
   simply ignored and navigation behaves exactly as it does today.

   The header and footer are named, so they hold still while only the
   content between them changes. That is what makes a multi-page
   static site feel like an application instead of a stack of
   documents, which is most of the "expensive" feeling.
   ============================================================ */

@view-transition { navigation: auto; }

.topbar   { view-transition-name: topbar; }
.sitefoot { view-transition-name: sitefoot; }

::view-transition-old(root),
::view-transition-new(root) { animation-duration: .22s; }

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
  .hero .rise, .hero .ph, .stage { opacity: 1 !important; transform: none !important; }
  .band .curve { transform: translateY(-50%) !important; }
  .arc .line { stroke-dashoffset: 0 !important; }
  .arc .node, .arc .halo { opacity: 1 !important; }

  /* View-transition pseudo-elements live outside the document tree,
     so the blanket `* { animation: none }` above does not reach them.
     1ms rather than none: cancelling outright can leave the outgoing
     snapshot painted. */
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) { animation-duration: 1ms !important; }
}

@media print {
  .preview, .topbar, .sitefoot, .btn { display: none; }
  body { background: #fff; }
}

/* ---- homepage clip (2026-09-22) ------------------------------
   One short video, click-to-play. The frame is 9:16 and capped so
   it never dominates the page: it reads as an inlay beside the
   copy, not a feature. Nothing from TikTok loads until the tap. */
.clip { padding: var(--sec) var(--gut); background: var(--ice); border-bottom: 1px solid var(--hairline); }
.clip .split { grid-template-columns: 1.18fr 0.82fr; align-items: center; max-width: 1180px; }
.clip .clipbox {
  padding: 36px 40px; background: var(--paper);
  border: 1px solid var(--hairline); border-top: 2px solid var(--forest); border-radius: 6px;
}
.clip h2 { margin: 0 0 18px; }
.clip .clipnote { font-size: var(--t-cap); color: var(--steel-3); margin-top: 18px; }
.clip .clipnote a { color: var(--graphite); font-weight: 700; text-decoration: underline; text-underline-offset: 3px; }
.clipframe {
  display: block; position: relative; width: min(100%, 300px); aspect-ratio: 9 / 16;
  margin: 0 0 0 auto; overflow: hidden; border-radius: 6px;
  background: var(--forest-deep); border: 1px solid var(--hairline);
}
.clipframe img { display: block; width: 100%; height: 100%; object-fit: cover; }
.clipframe .play {
  position: absolute; left: 50%; top: 50%; width: 64px; height: 64px;
  transform: translate(-50%, -50%); border-radius: 50%;
  background: rgba(248, 250, 249, 0.92); transition: transform .15s ease;
}
.clipframe .play::after {
  content: ""; position: absolute; left: 25px; top: 20px;
  border-left: 20px solid var(--forest-deep);
  border-top: 12px solid transparent; border-bottom: 12px solid transparent;
}
.clipframe:hover .play, .clipframe:focus-visible .play { transform: translate(-50%, -50%) scale(1.06); }
.clipframe iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
@media (max-width: 860px) {
  .clip .split { grid-template-columns: 1fr; }
  .clip .clipbox { padding: 26px 22px; }
  .clipframe { margin: 8px 0 0; width: min(100%, 260px); }
}
