/* Magic City Indoor Golf — one stylesheet, no framework, no build step.
   Page files should need almost no CSS of their own. If you find yourself
   writing a <style> block in a page, add the pattern here instead.

   Palette (issue #41): the logo is monochrome line art, so the base is
   black/white/grey straight from it, with Manchester United red as the single
   action colour and United yellow as a rare accent on dark grounds only.

   The contrast rules are not stylistic — they are measured:
     white on red      4.87  AA        -> red buttons take white text
     #B4130A on paper  6.74  AA        -> link text on light grounds
     red on ink        3.65  fails AA  -> on dark, red is for filled shapes only
     yellow on ink    13.44  AAA       -> accent text on dark
     yellow on paper   1.29  unusable  -> never yellow on light
*/

/* ---------------------------------------------------------------- tokens */

:root {
  --ink:        #181818;   /* from the logo */
  --ink-soft:   #2e2e2e;
  --paper:      #fcfcfc;   /* from the logo */

  --grey-100:   #f2f2f0;
  --grey-200:   #e4e4e1;
  --grey-300:   #d2d2ce;
  --grey-500:   #8a8a86;
  --grey-600:   #6b6b67;
  --grey-700:   #4a4a47;

  --red:        #da291c;   /* Manchester United red */
  --red-deep:   #b4130a;
  --red-dim:    rgba(218,41,28,.1);
  --yellow:     #fbe122;   /* United yellow — dark grounds only */

  --bg:          var(--paper);
  --surface:     #ffffff;
  --surface-2:   var(--grey-100);
  --line:        var(--grey-200);
  --line-strong: var(--grey-300);
  --text:        var(--ink);
  --text-muted:  var(--grey-600);
  /* Was --grey-500, which measured 3.09 on --surface-2 and failed AA. No
     lighter grey clears 4.5:1 while staying distinguishable from muted, so
     on light grounds these two tiers are the same colour and the hierarchy
     is carried by size and position instead. --grey-500 is still used for
     non-text marks, where the text rule does not apply. */
  --text-faint:  var(--grey-600);   /* 4.77 on --surface-2 */
  /* Muted text on a --red-dim highlight row: the tint darkens the ground
     enough to put --text-muted at 4.12, under AA. One shade darker clears it
     on both grounds these rows appear on (5.34 and 5.81). */
  --text-muted-strong: #5a5a56;
  --link:        var(--red-deep);

  --on-dark:       #f4f4f2;
  --on-dark-muted: #a9a9a4;

  --radius:      6px;
  --radius-lg:   10px;
  --radius-pill: 999px;

  --shadow-sm: 0 1px 2px rgba(24,24,24,.07);
  --shadow:    0 1px 3px rgba(24,24,24,.08), 0 8px 20px rgba(24,24,24,.07);
  --shadow-lg: 0 2px 6px rgba(24,24,24,.08), 0 18px 40px rgba(24,24,24,.12);

  --measure: 68ch;
  --page:    1120px;
  --gutter:  clamp(1.15rem, 4vw, 2.5rem);

  --font: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto,
          "Helvetica Neue", Arial, sans-serif;

  /* The logo is a condensed, heavy badge face. Without shipping a webfont we
     get close with weight, tight tracking and uppercase — see #41. */
  --font-display: var(--font);

  --step--1: clamp(.83rem, .8rem + .12vw, .89rem);
  --step-0:  clamp(1rem, .97rem + .18vw, 1.08rem);
  --step-1:  clamp(1.19rem, 1.12rem + .34vw, 1.4rem);
  --step-2:  clamp(1.42rem, 1.3rem + .62vw, 1.8rem);
  --step-3:  clamp(1.69rem, 1.48rem + 1.02vw, 2.32rem);
  --step-4:  clamp(2.01rem, 1.68rem + 1.65vw, 3rem);
  --step-5:  clamp(2.4rem, 1.88rem + 2.6vw, 3.9rem);
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg:          #111110;
    --surface:     #1a1a19;
    --surface-2:   #212120;
    --line:        #2e2e2c;
    --line-strong: #3d3d3a;
    --text:        #f0f0ee;
    --text-muted:  #a3a39e;
    --text-faint:  #8f8f89;   /* 4.96 on --surface-2; #82827d was 4.17 */
    /* On a dark ground the highlight tint lightens rather than darkens, so
       muted text is already clear and needs no separate value. */
    --text-muted-strong: var(--text-muted);
    --link:        var(--yellow);
    --shadow-sm: 0 1px 2px rgba(0,0,0,.5);
    --shadow:    0 1px 3px rgba(0,0,0,.4), 0 8px 20px rgba(0,0,0,.4);
    --shadow-lg: 0 2px 6px rgba(0,0,0,.45), 0 18px 40px rgba(0,0,0,.5);
  }
}

/* ---------------------------------------------------------------- reset */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 5.5rem;
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    transition-duration: .01ms !important;
  }
}

body {
  font-family: var(--font);
  font-size: var(--step-0);
  line-height: 1.6;
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
}

img, svg, video { display: block; max-width: 100%; height: auto; }
input, button, textarea, select { font: inherit; color: inherit; }
p, li { text-wrap: pretty; }

h1, h2, h3, h4 {
  font-family: var(--font-display);
  line-height: 1.08;
  font-weight: 800;
  letter-spacing: -.022em;
  text-wrap: balance;
}

a { color: var(--link); text-underline-offset: .18em; text-decoration-thickness: .07em; }
a:hover { color: var(--red); }
@media (prefers-color-scheme: dark) { a:hover { color: #fff; } }

:focus-visible { outline: 3px solid var(--red); outline-offset: 3px; border-radius: 3px; }
@media (prefers-color-scheme: dark) { :focus-visible { outline-color: var(--yellow); } }

.skip-link {
  position: absolute; left: .5rem; top: -100vh; z-index: 200;
  padding: .7rem 1.1rem; background: var(--ink); color: #fff;
  border-radius: var(--radius); text-decoration: none; font-weight: 700;
}
.skip-link:focus { top: .5rem; color: #fff; }

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

/* ---------------------------------------------------------------- layout */

.wrap { width: min(100% - var(--gutter) * 2, var(--page)); margin-inline: auto; }
.wrap--narrow { --page: 760px; }

.section { padding-block: clamp(2.75rem, 6.5vw, 5rem); }
.section--tight { padding-block: clamp(1.75rem, 4vw, 2.75rem); }
.section--tint { background: var(--surface-2); }
/* Dark grounds. `.hero` shares every one of these rules — it is a dark ground
   too, and when it did not inherit them the hero rendered red-on-black accent
   text at 3.65, below AA. Keep .hero in each selector list below. */
.section--dark { background: var(--ink); color: var(--on-dark); }
.section--dark h1, .section--dark h2, .section--dark h3,
.hero h1, .hero h2, .hero h3 { color: #fff; }
.section--dark p, .section--dark .lede { color: var(--on-dark-muted); }

/* :not(.btn) matters — without it this rule (0,1,1) outranks .btn-primary
   (0,1,0) and repaints button labels yellow. */
.section--dark a:not(.btn), .hero a:not(.btn) { color: var(--yellow); }
.section--dark a:not(.btn):hover, .hero a:not(.btn):hover { color: #fff; }

.grid { display: grid; gap: clamp(1rem, 2.2vw, 1.6rem); }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 21rem), 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr)); }
/* Hold two columns, not auto-fit's three. .grid-2's 21rem track means four cards
   land 3 + 1 with a hole where the fourth should be, which the /technology
   photos made obvious. Opt in per section: .grid-2 is used on eleven pages and
   most of them want the auto behaviour. */
.grid-2up { grid-template-columns: repeat(auto-fit, minmax(min(100%, 28rem), 1fr)); }

.prose { max-width: var(--measure); }
.prose > * + * { margin-top: 1.1em; }
.prose h2 { font-size: var(--step-2); margin-top: 2em; }
.prose h3 { font-size: var(--step-1); margin-top: 1.6em; }
.prose ul, .prose ol { padding-left: 1.25em; }
.prose li + li { margin-top: .35em; }

.divider { border: 0; border-top: 1px solid var(--line); margin-block: 2.25rem; }

/* ------------------------------------------------------- credentials */
/* The affiliations under an instructor's name: PGA of America, the Quarter
   Century Club, the British PGA. Text, not images, because a trademark logo
   has to come from the member's own PGA asset pack rather than be scraped,
   and because these read fine without one. `.cred-logo` is the slot to drop
   an official mark into when there is one; it is absent until then. */
.creds { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: 1.1rem; padding: 0; list-style: none; }
.cred {
  display: inline-flex; align-items: center; gap: .45rem;
  border: 1px solid var(--line-strong); border-radius: 999px;
  padding: .32rem .7rem;
  font-size: var(--step--1); font-weight: 650; color: var(--text);
  background: var(--surface-2);
}
/* The PGA of America mark. It is a detailed badge, not a wordmark, so it needs
   real size: inside a chip at text height it is an illegible smudge. It sits
   beside the chips instead.

   Navy on a dark ground fails contrast, and recoloring somebody's trademark is
   not ours to do, so in dark mode it gets a white plaque. That is the standard
   treatment for a one-color logo on dark, and it keeps the mark itself
   untouched. */
.cred-mark { display: flex; align-items: center; gap: .9rem; margin-top: 1.1rem; flex-wrap: wrap; }
.cred-mark img { height: 3.25rem; width: auto; display: block; }
@media (prefers-color-scheme: dark) {
  .cred-mark img {
    background: #fff;
    border-radius: .4rem;
    padding: .3rem .45rem;
    box-sizing: content-box;
  }
}

/* ----------------------------------------------- junior levels ladder */
/* One level per row. Name and description on the left, what moves them up on
   the right, so the ladder reads top to bottom and the "moves up by" lines
   stack into a column you can scan on their own. Below 40rem it is one column:
   two narrow columns is what the 2x2 grid was already doing wrong. */
.levels { display: flex; flex-direction: column; gap: 1rem; margin-top: 1.5rem; }
.level { display: grid; gap: .6rem 2rem; grid-template-columns: 1fr; align-items: start; }
/* The level name needs air under it. Headings here run at line-height 1.08 with
   no bottom margin of their own, so the description sat on top of it. */
.level-main h3 { margin-bottom: .55rem; }
.level-main > :last-child, .level-next > :last-child { margin-bottom: 0; }
.level-next .eyebrow { margin-bottom: .2rem; }
@media (min-width: 40rem) {
  .level { grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr); }
  .level-next { border-left: 1px solid var(--line); padding-left: 2rem; }
}

/* ------------------------------------------------------ contact form */
.contact-form { margin-top: 1.6rem; max-width: 36rem; }
.contact-form .field { margin-bottom: 1.1rem; }
.contact-form label {
  display: block; font-weight: 700; font-size: var(--step--1);
  margin-bottom: .35rem; color: var(--text);
}
.contact-form label span { color: var(--red); }
.contact-form input,
.contact-form select,
.contact-form textarea {
  width: 100%; box-sizing: border-box;
  /* 16px minimum: anything smaller and iOS zooms the page on focus. */
  font: inherit; font-size: 1rem;
  padding: .7rem .8rem;
  color: var(--text); background: var(--surface);
  border: 1px solid var(--line-strong); border-radius: .4rem;
}
.contact-form textarea { resize: vertical; min-height: 7rem; }
.contact-form input:focus-visible,
.contact-form select:focus-visible,
.contact-form textarea:focus-visible {
  outline: 3px solid var(--red); outline-offset: 1px; border-color: var(--red);
}
.contact-form [aria-invalid="true"] { border-color: var(--red); }
.contact-form .field-error { display: block; margin-top: .3rem; font-size: var(--step--1); color: var(--red); font-weight: 650; }
/* Off-screen rather than display:none, so a bot filling everything still
   trips it while a screen reader skips it (aria-hidden on the wrapper). */
.contact-form .hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.contact-form .form-status { margin: .25rem 0 1rem; font-weight: 650; }
.contact-form .form-status[data-state="error"] { color: var(--red); }
.contact-form .form-status[data-state="ok"] { color: var(--text); }
@media (prefers-color-scheme: dark) {
  .contact-form .form-status[data-state="error"] { color: var(--yellow); }
  .contact-form label span { color: var(--yellow); }
}

/* ---------------------------------------------------------------- type */

.eyebrow {
  font-size: var(--step--1); font-weight: 800;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--red-deep);
}
.section--dark .eyebrow, .hero .eyebrow { color: var(--yellow); }
/* In dark mode every section is a dark ground, not just .section--dark, so the
   deep red drops to 2.3–2.7:1. Same treatment the other red-on-dark text
   already gets: red becomes a filled shape, yellow carries the accent. */
@media (prefers-color-scheme: dark) { .eyebrow { color: var(--yellow); } }

.h-hero { font-size: var(--step-5); text-transform: uppercase; letter-spacing: -.028em; }
.h-1    { font-size: var(--step-4); }
/* The lesson headline is an equation, so it stacks one term per line. At the
   narrowest widths the terms are wider than the column, so it steps down a
   size rather than pushing the page sideways. */
.h-equation { text-wrap: balance; }
@media (max-width: 26rem) { .h-equation { font-size: var(--step-3); } }
.h-2    { font-size: var(--step-3); }
.h-3    { font-size: var(--step-2); }
.h-4    { font-size: var(--step-1); }

.lede { font-size: var(--step-1); color: var(--text-muted); max-width: 54ch; line-height: 1.45; }
.muted { color: var(--text-muted); }
.small { font-size: var(--step--1); }
.center { text-align: center; }
.center .lede, .center .prose { margin-inline: auto; }

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

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5em;
  padding: .75em 1.4em;
  border: 2px solid transparent;
  border-radius: var(--radius);
  font-weight: 700; font-size: var(--step-0); line-height: 1.2;
  text-decoration: none; cursor: pointer;
  /* Labels wrap only when they genuinely do not fit. `nowrap` here used to push
     the whole page sideways at 320px on any button with a long label — two
     pages did it. Wrapping is confined to the header, where the space is
     controlled and a two-line button would break the bar. */
  white-space: normal; max-width: 100%;
  transition: background-color .15s ease, border-color .15s ease,
              color .15s ease, transform .12s ease;
}
.btn:active { transform: translateY(1px); }
.header-actions .btn {
  white-space: nowrap;
  /* The header bar runs on smaller type than the page body: nav links are
     var(--step--1) and 40px tall. A body-sized button dropped in here stood
     51px tall with 17px text and dwarfed everything beside it. */
  font-size: var(--step--1);
  padding: .65em 1.2em;
}

/* White on red measures 4.87 — the one component that works on any ground. */
.btn-primary { background: var(--red); border-color: var(--red); color: #fff; }
.btn-primary:hover { background: var(--red-deep); border-color: var(--red-deep); color: #fff; }

.btn-solid { background: var(--ink); border-color: var(--ink); color: #fff; }
.btn-solid:hover { background: var(--ink-soft); border-color: var(--ink-soft); color: #fff; }
@media (prefers-color-scheme: dark) {
  .btn-solid { background: var(--paper); border-color: var(--paper); color: var(--ink); }
  .btn-solid:hover { background: #fff; border-color: #fff; color: var(--ink); }
}

.btn-ghost { background: transparent; border-color: var(--line-strong); color: var(--text); }
.btn-ghost:hover { border-color: var(--red); color: var(--red-deep); background: var(--red-dim); }
.section--dark .btn-ghost, .hero .btn-ghost { border-color: rgba(255,255,255,.3); color: #fff; }
.section--dark .btn-ghost:hover, .hero .btn-ghost:hover { border-color: #fff; background: rgba(255,255,255,.1); color: #fff; }

/* Slightly roomier than a normal button, not a different species. This used
   to raise the font a whole step as well, and because the padding is em
   based the two compounded: 71px tall against 51px for a normal button. */
.btn-lg { padding: .8em 1.55em; font-size: var(--step-0); }
.btn-sm { padding: .5em 1em; font-size: var(--step--1); }

.btn-row { display: flex; flex-wrap: wrap; gap: .7rem; align-items: center; }
.center .btn-row { justify-content: center; }

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

.site-header {
  position: sticky; top: 0; z-index: 100;
  background: var(--ink); color: var(--on-dark);
  border-bottom: 3px solid var(--red);
}
.header-inner {
  width: min(100% - var(--gutter) * 2, var(--page));
  margin-inline: auto;
  display: flex; align-items: center; gap: 1rem;
  min-height: 4.2rem;
  position: relative;
}

.brand {
  display: flex; align-items: center; gap: .5rem;
  color: #fff; text-decoration: none;
  line-height: 1.02; margin-right: auto; flex-shrink: 0;
}
.brand-text { display: flex; flex-direction: column; }
/* The badge logo itself, straight from magiccityindoorgolf.com. Height-led so
   it sits on the header baseline; width follows its 700x554 ratio. */
/* A small mark beside the wordmark, matched to the height of the two text
   lines (27.7px measured). Shipped at 2x so the browser is not squashing
   the 700px original. Its lettering is not meant to be read at this size —
   the wordmark next to it does that. */
.brand .mark { height: 1.73rem; width: auto; flex-shrink: 0; }
.brand-text b {
  font-family: var(--font-display);
  font-size: 1.12rem; font-weight: 800;
  letter-spacing: -.01em; text-transform: uppercase;
}
.brand-text > span {
  font-size: .58rem; font-weight: 700;
  letter-spacing: .22em; text-transform: uppercase;
  color: var(--yellow);
}
.brand:hover { color: #fff; }

.nav { display: flex; gap: .1rem; }
.nav a {
  color: var(--on-dark-muted); text-decoration: none;
  font-weight: 600; font-size: .92rem;
  padding: .5rem .7rem; border-radius: var(--radius); white-space: nowrap;
}
.nav a:hover { color: #fff; background: rgba(255,255,255,.09); }
.nav a[aria-current="page"] { color: #fff; box-shadow: inset 0 -3px 0 var(--red); }

/* ---- All Services dropdown ----
   Built on <details> so it opens with the keyboard and works with JavaScript
   off; app.js only adds close-on-Escape and close-on-outside-click. */
/* Static at both sizes: the panel anchors itself to .header-inner, not to the
   summary. At three columns it is wider than the gap to the right of "All
   Services", so anything hung off the summary ran past the viewport edge just
   above the drawer breakpoint. app.js probes the PANEL's position to tell
   desktop from drawer, precisely because this is no longer a reliable signal. */
.nav-drop { position: static; }
.nav-drop > summary {
  display: inline-flex; align-items: center; gap: .3rem;
  color: var(--on-dark-muted); font-weight: 600; font-size: .92rem;
  padding: .5rem .7rem; border-radius: var(--radius);
  cursor: pointer; white-space: nowrap; list-style: none;
}
.nav-drop > summary::-webkit-details-marker { display: none; }
.nav-drop > summary:hover { color: #fff; background: rgba(255,255,255,.09); }
.nav-drop > summary svg { width: .85em; height: .85em; transition: transform .15s ease; }
.nav-drop[open] > summary { color: #fff; background: rgba(255,255,255,.09); }
.nav-drop[open] > summary svg { transform: rotate(180deg); }
.nav-drop[data-current="true"] > summary { color: #fff; box-shadow: inset 0 -3px 0 var(--red); }
.nav-drop > summary:focus-visible { outline: 3px solid var(--red); outline-offset: 2px; }

/* Ten destinations is too many for one column of bare links, so they are
   grouped by what someone is trying to do and each carries a line saying what
   it is (#74). Centred on the header container, and capped so it can never be
   wider than the viewport it has to fit inside. */
.nav-drop-panel {
  position: absolute; top: calc(100% + .45rem); left: 50%; z-index: 120;
  transform: translateX(-50%);
  /* The full header column, edge-aligned with the brand and Get Started. It is
     a percentage of .header-inner rather than a fixed width, so it tracks the
     page container and cannot overhang the viewport at any size. */
  width: 100%;
  /* Stretch, not start: the columns hold different numbers of items, and the
     dividers between them have to run the full height or they end raggedly
     partway down. */
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  align-items: stretch; gap: .3rem 1.5rem;
  padding: 1.5rem 1.5rem 1.65rem;
  background: var(--ink);
  border: 1px solid rgba(255,255,255,.14);
  border-top: 3px solid var(--red);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
}
/* At this width three groups need a visible edge between them, or the columns
   read as one loose grid of ten. */
.nav-col + .nav-col { padding-left: 1.5rem; border-left: 1px solid rgba(255,255,255,.12); }
.nav-col-h {
  margin: 0 0 .45rem; padding: 0 .6rem;
  font-size: .7rem; font-weight: 800; letter-spacing: .11em; text-transform: uppercase;
  color: var(--yellow);
}
.nav-drop-panel a {
  display: grid; grid-template-columns: 1.55rem 1fr; column-gap: .6rem; row-gap: .15rem;
  align-items: start;
  color: var(--on-dark-muted); text-decoration: none;
  padding: .6rem .6rem; border-radius: var(--radius); white-space: normal;
}
/* Red fails AA on this ground, and these are strokes rather than filled
   shapes, so the icons are muted white and only warm up on hover. */
.nav-drop-panel a svg {
  grid-row: span 2; width: 1.25rem; height: 1.25rem; margin-top: .1rem;
  color: rgba(255,255,255,.5);
}
.nav-drop-panel a b { color: #fff; font-weight: 700; font-size: .93rem; line-height: 1.3; }
.nav-drop-panel a span { font-size: .79rem; line-height: 1.38; }
.nav-drop-panel a:hover { background: rgba(255,255,255,.09); }
.nav-drop-panel a:hover svg { color: var(--yellow); }
.nav-drop-panel a[aria-current="page"] {
  background: rgba(255,255,255,.06); box-shadow: inset 2px 0 0 var(--red);
}
.nav-drop-panel a[aria-current="page"] svg { color: var(--yellow); }

.header-actions { display: flex; align-items: center; gap: .5rem; flex-shrink: 0; }

.phone-link {
  display: inline-flex; align-items: center; gap: .45rem;
  color: #fff; text-decoration: none;
  font-weight: 700; font-size: .95rem;
  padding: .5rem .65rem; border-radius: var(--radius); white-space: nowrap;
}
.phone-link:hover { color: var(--yellow); background: rgba(255,255,255,.09); }
.phone-link svg { width: 1.05em; height: 1.05em; flex-shrink: 0; }

.nav-toggle {
  display: none; order: 3;
  background: transparent; border: 2px solid rgba(255,255,255,.28);
  color: #fff; border-radius: var(--radius);
  padding: .4rem .55rem; cursor: pointer;
}
.nav-toggle svg { width: 1.3rem; height: 1.3rem; }
.nav-toggle[aria-expanded="true"] .icon-menu,
.nav-toggle[aria-expanded="false"] .icon-close { display: none; }

/* Breakpoint set to where the horizontal nav actually fits alongside the
   brand, phone and Get Started — verified by sweep, not guessed. */
/* Raised from 60rem when "Junior Classes" became a fifth top-bar item (issue
   #120). At 1024px the five links plus the phone number and the Get Started
   button ran 21px past the viewport and pushed the page sideways. The menu
   now takes over before that happens. */
@media (max-width: 66rem) {
  .nav {
    display: none;
    position: absolute; left: 0; right: 0; top: 100%;
    flex-direction: column; gap: 0;
    background: var(--ink);
    border-bottom: 3px solid var(--red);
    padding: .25rem var(--gutter) 1rem;
    box-shadow: var(--shadow-lg);
    margin-inline: calc(var(--gutter) * -1);
  }
  .nav.is-open { display: flex; }
  .nav a { padding: .85rem .25rem; font-size: 1.02rem; border-radius: 0; }
  .nav a + a,
  .nav a + .nav-drop,
  .nav .nav-drop + a { border-top: 1px solid rgba(255,255,255,.09); }

  .nav-drop { position: static; }
  .nav-drop > summary {
    padding: .85rem .25rem; font-size: 1.02rem; border-radius: 0;
    justify-content: space-between; width: 100%;
  }
  .nav-drop[open] > summary { background: transparent; }
  .nav-drop[data-current="true"] > summary { box-shadow: none; }
  .nav-drop-panel {
    position: static; transform: none; width: auto; min-width: 0;
    display: block; padding: 0 0 .5rem .9rem;
    background: transparent; border: 0; box-shadow: none;
    border-left: 2px solid rgba(255,255,255,.14); margin-left: .25rem;
  }
  .nav-col + .nav-col { padding-left: 0; border-left: 0; }
  .nav-drop-panel a { padding: .55rem .25rem; grid-template-columns: 1.5rem 1fr; column-gap: .55rem; }
  .nav-drop-panel a b { font-size: .98rem; }
  /* Ten items with a line of prose each makes the drawer longer than the
     screen. The icon and the grouping carry it here; the summaries do not. */
  .nav-drop-panel a span { display: none; }
  .nav-col-h { padding-left: .25rem; margin: .75rem 0 .1rem; }
  .nav-col:first-child .nav-col-h { margin-top: .35rem; }
  .nav-toggle { display: inline-flex; }
}

/* The number never hides in the menu — it only shrinks to its icon. */
@media (max-width: 34rem) {
  .header-inner { gap: .5rem; }
  .brand { gap: .4rem; }
  .phone-link span { display: none; }
  .phone-link { padding: .5rem; }
  .header-actions .btn { padding: .58em .95rem; font-size: .88rem; }
  .brand-text b { font-size: .98rem; }
  .brand-text > span { font-size: .52rem; letter-spacing: .18em; }
}

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

.hero {
  background: var(--ink); color: var(--on-dark);
  padding-block: clamp(2.75rem, 7vw, 5.5rem);
  position: relative; overflow: hidden;
}
.hero::before {
  content: ""; position: absolute; inset: 0;
  background: repeating-linear-gradient(
    115deg, transparent 0 42px, rgba(255,255,255,.018) 42px 84px);
  pointer-events: none;
}
.hero > * { position: relative; }
.hero h1 { color: #fff; max-width: 16ch; }
/* The centred hero sits above the tour video and needs the full width —
   the 16ch cap above is for the side-by-side hero on /contact. */
.hero .center h1 { max-width: none; margin-inline: auto; }
.hero .lede { color: var(--on-dark-muted); margin-top: 1.15rem; }

.hero-layout { display: grid; gap: clamp(2rem, 5vw, 3.25rem); grid-template-columns: 1fr; align-items: center; }
@media (min-width: 60rem) {
  .hero-layout { grid-template-columns: 1.05fr .95fr; }
  /* Side by side, the video is a grid item — its own top margin would push it
     out of alignment with the text beside it. The "watch the full tour" link
     has to travel with it, or the grid treats it as a third item and drops it
     into the next row under the copy instead of under the video. */
  .hero-layout .hero-media .tour { margin-top: 0; }
}

/* ---------------------------------------------------- hero tour video */
/* Click-to-play facade. On load the page fetches only the 39 KB poster; the
   31 MB video is not requested at all — no preload, no metadata — until
   someone presses play. app.js swaps the real <video> in on click, and the
   <noscript> link still reaches the file with JavaScript off.
   (The source WordPress file was 268 MB at 9.8 Mbps for 720p. Re-encoded at
   1.16 Mbps, which is visually indistinguishable and 89% smaller.) */

.tour {
  margin-top: clamp(1.75rem, 4vw, 2.5rem);
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid rgba(255,255,255,.14);
  background: #0d0d0c;
  position: relative;
  aspect-ratio: 16 / 9;
}
.tour video { width: 100%; height: 100%; display: block; object-fit: cover; background: #000; }

/* The ambient loop sits behind the facade. It is decorative — silent, muted,
   aria-hidden — and the narrated tour is what the button plays. */
.tour-loop { position: absolute; inset: 0; }

/* The narrated tour is a link beneath the video now, not an overlay on it, so
   the loop plays unobstructed (#51). Nothing covers the picture, which means
   there is no scrim to measure and no text sitting over moving footage. */
.tour-more { margin-top: .85rem; font-size: var(--step--1); }
.tour-link {
  display: inline-flex; align-items: center; gap: .55rem;
  color: var(--yellow); font-weight: 700; text-decoration: none;
}
.tour-link:hover { color: #fff; text-decoration: underline; }
.tour-link .tour-runtime { font-weight: 500; color: var(--on-dark-muted); }
.tour-play {
  display: grid; place-items: center; flex-shrink: 0;
  width: 1.9rem; height: 1.9rem; border-radius: 50%;
  background: var(--red); color: #fff;
  transition: transform .12s ease, background-color .15s ease;
}
.tour-link:hover .tour-play { transform: scale(1.08); }
.tour-play svg { width: .85rem; height: .85rem; margin-left: 1px; }

/* ---------------------------------------------------------- region map */

.region-map { margin: 0; }
.region-map svg { width: 100%; height: auto; max-height: 29rem; border-radius: var(--radius-lg); }
.region-map figcaption {
  margin-top: .8rem; font-size: var(--step--1);
  color: var(--on-dark-muted); text-align: center;
}

/* The map is drawn from tokens rather than fixed colours, so the same SVG
   reads correctly on a light section or inside the dark hero. Yellow is
   unusable on light (1.29), so the exit callout uses red there and yellow
   only on dark — the same rule as everywhere else. */
.region-map {
  --map-bg:        var(--surface-2);
  --map-bg-line:   var(--line);
  --map-road:      var(--grey-300);
  --map-road-2:    var(--grey-200);
  --map-dot:       var(--grey-500);
  --map-dot-city:  var(--grey-700);
  --map-ink:       var(--text-muted);
  --map-ink-strong:var(--text);
  --map-accent:    var(--red-deep);
  --map-shield-bg: var(--surface);
  --map-pin-core:  #fff;
}
.section--dark .region-map, .hero .region-map {
  --map-bg:        rgba(255,255,255,.04);
  --map-bg-line:   rgba(255,255,255,.11);
  --map-road:      rgba(255,255,255,.2);
  --map-road-2:    rgba(255,255,255,.12);
  --map-dot:       rgba(255,255,255,.4);
  --map-dot-city:  rgba(255,255,255,.78);
  --map-ink:       var(--on-dark-muted);
  --map-ink-strong:#fff;
  --map-accent:    var(--yellow);
  --map-shield-bg: rgba(255,255,255,.1);
  --map-pin-core:  #fff;
}
@media (prefers-color-scheme: dark) {
  .region-map {
    --map-bg:        rgba(255,255,255,.035);
    --map-bg-line:   var(--line);
    --map-road:      #3f3f3c;
    --map-road-2:    #2f2f2d;
    --map-dot:       #6b6b66;
    --map-dot-city:  #b9b9b3;
    --map-accent:    var(--yellow);
    --map-shield-bg: var(--surface-2);
  }
}

.map-bg { fill: var(--map-bg); stroke: var(--map-bg-line); stroke-width: 1; }
.map-road .road-interstate { stroke: var(--map-road); stroke-width: 5; }
.map-road .road-us { stroke: var(--map-road-2); stroke-width: 2.5; stroke-dasharray: 7 6; }
.map-road .road-primary { stroke: var(--red); stroke-width: 6; }

.map-shield rect { fill: var(--map-shield-bg); stroke: var(--map-road); }
.map-shield text { fill: var(--map-ink); font-size: 15px; font-weight: 800; text-anchor: middle; font-family: var(--font); }

.map-place circle { fill: var(--map-dot); }
.map-place .dot-city { fill: var(--map-dot-city); }
.map-place text { fill: var(--map-ink); font-size: 16px; font-weight: 500; font-family: var(--font); dominant-baseline: middle; }
.map-place .label-city { fill: var(--map-ink-strong); font-weight: 700; }

.map-exit line { stroke: var(--map-accent); stroke-width: 1.5; stroke-dasharray: 4 4; }
.map-exit text { fill: var(--map-accent); font-size: 14px; font-weight: 700; font-family: var(--font); dominant-baseline: middle; }

.pin-halo { fill: var(--red); opacity: .28; }
.pin { fill: var(--red); }
.pin-core { fill: var(--map-pin-core); }
.label-us { fill: var(--map-ink-strong); font-size: 17px; font-weight: 800; letter-spacing: .08em; font-family: var(--font); }

.map-meta text { fill: var(--text-faint); font-size: 13px; font-weight: 600; font-family: var(--font); }
.map-meta .compass { fill: var(--map-ink); }
.map-meta .scale-bar { stroke: var(--text-faint); stroke-width: 1.5; }

/* The map caption inherits dark-ground colour only inside a dark ground. */
.map-course { color: var(--map-accent, var(--red)); }
.map-course text {
  fill: var(--map-ink); font-size: 11px; font-weight: 600;
  font-family: var(--font); dominant-baseline: middle;
}
.pin-halo-2 { fill: var(--red); opacity: .13; }
.map-leader { stroke: var(--map-dot); stroke-width: 1; opacity: .55; }

.region-map figcaption { color: var(--text-muted); }
.section--dark .region-map figcaption, .hero .region-map figcaption { color: var(--on-dark-muted); }

/* Location block: map beside the practical details. */
.locate { display: grid; gap: clamp(1.5rem, 4vw, 2.75rem); grid-template-columns: 1fr; align-items: center; }
@media (min-width: 58rem) { .locate { grid-template-columns: 1.1fr .9fr; } }

@media (prefers-reduced-motion: no-preference) {
  /* The origin used to be hard-coded at 358px 346px — the beacon's position on
     the *old* map. When the map was rebuilt the pin moved and the pulse kept
     scaling around the old point, so the rings visibly drifted off the marker
     (#64). transform-box: fill-box makes the origin the element's own centre,
     so it cannot go stale again. */
  .pin-halo {
    animation: pin-pulse 2.8s ease-in-out infinite;
    transform-box: fill-box; transform-origin: center;
  }
}
@keyframes pin-pulse {
  0%, 100% { opacity: .28; transform: scale(1); }
  50%      { opacity: .1;  transform: scale(1.35); }
}

/* -------------------------------------------------- local quick-contact */

.local-bar { background: var(--surface); border-bottom: 1px solid var(--line); }
.local-bar-inner { display: grid; gap: .75rem; grid-template-columns: 1fr; padding-block: 1.1rem; }
@media (min-width: 48rem) { .local-bar-inner { grid-template-columns: repeat(3, 1fr); } }

.local-item {
  display: flex; align-items: center; gap: .75rem;
  text-decoration: none; color: var(--text);
  padding: .7rem .85rem;
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--surface-2);
}
.local-item:hover { border-color: var(--red); color: var(--text); }
.local-item svg { width: 1.3rem; height: 1.3rem; flex-shrink: 0; color: var(--red); }
.local-item b { display: block; font-size: var(--step-0); line-height: 1.25; }
.local-item span span { display: block; font-size: var(--step--1); color: var(--text-muted); }

.hours-list { margin-top: 1.35rem; }
.hours-list div {
  display: flex; justify-content: space-between; gap: 1rem;
  padding: .55rem 0; border-bottom: 1px solid var(--line); max-width: 26rem;
}
.hours-list dt { color: var(--text-muted); }
.hours-list dd { font-weight: 700; font-variant-numeric: tabular-nums; }

/* ------------------------------------------------ sticky mobile actions */

.mobile-actions {
  position: fixed; inset: auto 0 0 0; z-index: 90; display: none;
  background: var(--surface); border-top: 1px solid var(--line);
  box-shadow: 0 -4px 18px rgba(24,24,24,.15);
  padding: .45rem .45rem calc(.45rem + env(safe-area-inset-bottom));
}
.mobile-actions a {
  flex: 1; display: flex; flex-direction: column; align-items: center; gap: .18rem;
  padding: .5rem .25rem; text-decoration: none; color: var(--text);
  font-size: .72rem; font-weight: 700; border-radius: var(--radius);
  min-height: 44px; justify-content: center;
}
.mobile-actions a svg { width: 1.25rem; height: 1.25rem; color: var(--red); }
.mobile-actions a.is-primary { background: var(--red); color: #fff; }
.mobile-actions a.is-primary svg { color: #fff; }
.mobile-actions a:active { background: var(--surface-2); }
.mobile-actions a.is-primary:active { background: var(--red-deep); }

@media (max-width: 47.99rem) {
  .mobile-actions { display: flex; gap: .3rem; }
  body { padding-bottom: 4.6rem; }
}

/* ---------------------------------------------------------------- cards */

.card {
  background: var(--surface); border: 1px solid var(--line);
  border-radius: var(--radius-lg); padding: clamp(1.15rem, 2.4vw, 1.75rem);
}
.card h3 { font-size: var(--step-1); }
.card > * + * { margin-top: .8rem; }

/* A photograph inside a card (/technology, /instruction#fitting). 3:2 because
   that is what the phone shot: forcing 16:9 cropped the ceiling unit out of the
   Falcon frame. Full bleed is deliberately NOT used; the card has generous
   padding and a photo running to the edge fought the border. */
.shot {
  display: block; width: 100%; aspect-ratio: 3 / 2; object-fit: cover;
  border-radius: var(--radius); border: 1px solid var(--line);
  background: var(--surface-2);
}

/* ------------------------------------------------------- club fitting rows */

/* One row per thing you get to hit: photograph left, copy right. Full width
   rather than a three-up, because the photographs carry the argument here and
   at a third of the page the shaft labels and the loose heads are unreadable. */
.fit-rows { display: flex; flex-direction: column; gap: 1rem; margin-top: 1.1rem; }
.fit-row { display: grid; gap: .9rem; grid-template-columns: 1fr; align-items: center; }
.fit-row > :last-child > :last-child { margin-bottom: 0; }
.fit-row h4 { margin-bottom: .5rem; }

/* The Optimizer screenshots are phone captures, so they keep their portrait
   shape instead of being cropped into the 3:2 .shot frame. */
.fit-app { display: grid; gap: 1.2rem; grid-template-columns: 1fr; margin-top: 1.1rem; }
.fit-app > div > * + * { margin-top: .8rem; }
.app-shot { margin: 0; }
.app-shot img {
  display: block; width: 100%; max-width: 15rem; height: auto;
  border-radius: var(--radius); border: 1px solid var(--line);
}
.app-shot figcaption { margin-top: .45rem; }

@media (min-width: 46rem) {
  .fit-row { grid-template-columns: minmax(0, 22rem) minmax(0, 1fr); gap: 1.8rem; }
  .fit-app { grid-template-columns: minmax(0, 1fr) auto auto; align-items: start; gap: 1.6rem; }
}

.path-card {
  display: flex; flex-direction: column;
  background: var(--surface); border: 1px solid var(--line-strong);
  border-radius: var(--radius-lg); padding: clamp(1.3rem, 2.8vw, 2rem);
  text-decoration: none; color: var(--text);
  transition: border-color .15s ease, transform .15s ease, box-shadow .15s ease;
  position: relative; overflow: hidden;
}
.path-card::before {
  content: ""; position: absolute; inset: 0 auto 0 0; width: 4px;
  background: var(--red); transform: scaleY(0); transform-origin: top;
  transition: transform .18s ease;
}
.path-card:hover { border-color: var(--red); transform: translateY(-2px); box-shadow: var(--shadow); color: var(--text); }
.path-card:hover::before { transform: scaleY(1); }

.path-card .path-icon {
  width: 2.75rem; height: 2.75rem; display: grid; place-items: center;
  border-radius: var(--radius); background: var(--red-dim); color: var(--red);
  margin-bottom: 1rem;
}
.path-card .path-icon svg { width: 1.5rem; height: 1.5rem; }
.path-card h2, .path-card h3 { font-size: var(--step-2); }
.path-card p { color: var(--text-muted); margin-top: .55rem; }
.path-card ul { list-style: none; padding: 0; margin-top: .9rem; font-size: var(--step--1); color: var(--text-muted); }
.path-card li { padding-left: 1.3em; position: relative; }
.path-card li + li { margin-top: .32em; }
.path-card li::before {
  content: ""; position: absolute; left: .25em; top: .6em;
  width: .38em; height: .38em; background: var(--red);
}
.path-card .path-go {
  margin-top: auto; padding-top: 1.3rem;
  font-weight: 700; color: var(--red-deep);
  display: inline-flex; align-items: center; gap: .35em;
  transition: gap .15s ease;
}
@media (prefers-color-scheme: dark) { .path-card .path-go { color: var(--yellow); } }
.path-card:hover .path-go { gap: .65em; }

.path-card--quiet { background: transparent; border-style: dashed; }
.path-card--quiet::before { display: none; }

/* ---------------------------------------------------------------- stats */

.stat-row { display: grid; gap: 1.25rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 8.5rem), 1fr)); }
.stat { text-align: center; }
.stat b {
  display: block; font-family: var(--font-display);
  font-size: var(--step-3); font-weight: 800; letter-spacing: -.03em; color: #fff;
}
.stat span { font-size: var(--step--1); color: var(--on-dark-muted); }

/* ---------------------------------------------------------------- tables */

.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }

table.rates { width: 100%; min-width: 33rem; border-collapse: collapse; font-variant-numeric: tabular-nums; }
table.rates caption { text-align: left; font-weight: 800; font-size: var(--step-1); padding-bottom: .65rem; }
table.rates th, table.rates td { padding: .75rem .85rem; text-align: left; border-bottom: 1px solid var(--line); }
table.rates thead th {
  font-size: var(--step--1); text-transform: uppercase; letter-spacing: .07em;
  color: var(--text-muted); border-bottom: 2px solid var(--ink); font-weight: 800;
}
@media (prefers-color-scheme: dark) { table.rates thead th { border-bottom-color: var(--line-strong); } }
table.rates td.num, table.rates th.num { text-align: right; }
table.rates tbody tr:hover { background: var(--surface-2); }
table.rates .tier-name { font-weight: 700; }
table.rates .price { font-weight: 800; font-size: 1.05em; }
table.rates .effective { color: var(--red-deep); font-weight: 700; }
@media (prefers-color-scheme: dark) { table.rates .effective { color: var(--yellow); } }
table.rates .save { color: var(--text-muted); font-size: var(--step--1); }
/* Prices in the membership tables link straight to that tier's signup page on
   uSchedule (#49 — someone ready to join could previously only phone). The
   price stays the visible thing; the link is what it always was. */
/* The price IS the join link, and as an underlined number it did not read as
   one: nothing on the page said "this is how you sign up" (issue #123). It is a
   button now. The 12-month column, the term we want, is solid red; the 3-month
   column is outlined, so the table still has a visual recommendation rather
   than eight identical buttons shouting equally. */
table.rates .price a {
  display: inline-block;
  padding: .34em .85em;
  border: 1px solid var(--red);
  border-radius: 999px;
  background: var(--red);
  color: #fff;
  font-weight: 800;
  text-decoration: none;
  white-space: nowrap;
  transition: background-color .15s ease, border-color .15s ease, transform .12s ease;
}
table.rates .price a:hover { background: var(--red-deep); border-color: var(--red-deep); color: #fff; }
table.rates .price a:active { transform: translateY(1px); }
/* The second price column on each row is the shorter term. */
table.rates .price--alt a { background: transparent; color: var(--text); border-color: var(--line-strong); }
table.rates .price--alt a:hover { background: var(--surface-2); color: var(--text); border-color: var(--red); }
/* The badge is a filled red shape, so its link keeps the badge's own colour. */
.price-badge a { color: inherit; text-decoration: underline; text-underline-offset: .18em; }

table.rates tr.is-highlight { background: var(--red-dim); }
table.rates tr.is-highlight .muted,
table.rates tr.is-highlight .save { color: var(--text-muted-strong); }

/* ---------------------------------------------------------------- callouts */

.callout {
  border: 1px solid var(--line); border-left: 4px solid var(--red);
  background: var(--surface-2); border-radius: var(--radius);
  padding: 1.05rem 1.3rem;
}
.callout h3 {
  font-size: var(--step-0); text-transform: uppercase;
  letter-spacing: .09em; color: var(--red-deep);
}
@media (prefers-color-scheme: dark) { .callout h3 { color: var(--yellow); } }
.callout > * + * { margin-top: .55rem; }

.fineprint-grid {
  display: grid; gap: 1rem 1.6rem;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 12rem), 1fr));
  list-style: none; padding: 0;
}
.fineprint-grid li { font-size: var(--step--1); color: var(--text-muted); }
.fineprint-grid b { display: block; font-size: var(--step-0); color: var(--text); }

.price-badge {
  display: inline-flex; align-items: baseline; gap: .3em;
  background: var(--ink); color: #fff;
  border-radius: var(--radius); padding: .28em .8em;
  font-weight: 800; font-size: var(--step--1);
  letter-spacing: .02em;
}
@media (prefers-color-scheme: dark) { .price-badge { background: var(--red); } }

/* ---------------------------------------------------------------- faq */

.faq details { border-bottom: 1px solid var(--line); }
.faq summary {
  cursor: pointer; font-weight: 700; padding: .9rem 0; list-style: none;
  display: flex; justify-content: space-between; align-items: center; gap: 1rem;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: "+"; font-size: 1.35em; font-weight: 400; color: var(--red);
  transition: transform .15s ease; line-height: 1;
}
.faq details[open] summary::after { transform: rotate(45deg); }
.faq details > *:not(summary) { padding-bottom: 1rem; color: var(--text-muted); max-width: var(--measure); }

/* A page hero with copy on one side and a picture on the other. Single column
   on a phone, and the picture goes second so it never pushes the heading below
   the fold. */
.split { display: grid; gap: clamp(1.5rem, 4vw, 2.75rem); grid-template-columns: 1fr; align-items: center; }
@media (min-width: 54rem) { .split { grid-template-columns: 1.1fr .9fr; } }
.split .photo img { aspect-ratio: 4 / 5; object-fit: cover; object-position: 50% 35%; max-height: 26rem; margin-inline: auto; }

/* Instructor cards carry two actions, so the card is no longer a link itself. */
.person-card { display: flex; flex-direction: column; }
.person-card ul { padding-left: 1.1em; margin-top: .55rem; }
.person-card .btn-row { margin-top: auto; padding-top: 1.1rem; }

/* ---------------------------------------------------------------- photos */

/* Real photographs of the building and the people in it (#47). Sources came
   off the old WordPress media library and are modest — 700-1290px — so these
   are sized to what they can actually fill rather than stretched to the page. */
.photo { margin: 0; }
.photo img {
  display: block; width: 100%; height: auto;
  border-radius: var(--radius-lg); background: var(--surface-2);
}
.photo figcaption {
  margin-top: .6rem; font-size: var(--step--1); color: var(--text-muted);
}
/* A wide shot that runs the width of the column it sits in. */
.photo--band img { aspect-ratio: 16 / 9; object-fit: cover; }
/* Two of the three usable sources are portrait (700x989). Cropping those to a
   16/9 band throws most of the picture away, so they get a narrower column and
   keep their own shape. */
.photo--portrait { max-width: 30rem; margin-inline: auto; }
.photo--portrait img { aspect-ratio: 3 / 4; object-fit: cover; object-position: 50% 35%; }
.photo--portrait figcaption { text-align: center; }

/* ---------------------------------------------------------------- people */

.person-head {
  /* Now a real photograph (#47). The sources are modest and vary in framing
     (a suit-and-award shot next to two taken outdoors), so a square crop is
     what makes the three sit together on the index.

     The square is shown whole. A max-height of 22rem used to clamp the profile
     hero, where the column is wider than 352px: that turned the square into a
     1.55:1 letterbox and threw away 250 of the 700 source pixels, cutting the
     top of Neil's head and everything below Jeff's chin. It was never doing
     the job its comment claimed, because the index cards are 249px to 317px
     wide at every breakpoint and the clamp never reached them. Capping the
     WIDTH instead keeps the hero a sensible size and crops nothing. */
  aspect-ratio: 1 / 1; width: 100%; max-width: 24rem; margin-inline: auto;
  object-fit: cover; object-position: 50% 30%;
  display: block; border-radius: var(--radius-lg);
  background: var(--surface-2); border: 1px solid var(--line);
}

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

.site-footer {
  background: var(--ink); color: var(--on-dark-muted);
  padding-block: clamp(2.25rem, 5vw, 3.5rem) 1.75rem;
  font-size: var(--step--1);
  border-top: 3px solid var(--red);
}
.site-footer a { color: var(--on-dark-muted); text-decoration: none; }
.site-footer a:hover { color: #fff; text-decoration: underline; }
.site-footer h2 {
  font-size: var(--step--1); text-transform: uppercase; letter-spacing: .12em;
  color: var(--yellow); margin-bottom: .75rem; font-weight: 800;
}
.footer-mark { display: block; margin-bottom: 1.1rem; }
.footer-mark .mark { height: 5.5rem; width: auto; }

.footer-grid { display: grid; gap: 1.75rem; grid-template-columns: repeat(auto-fit, minmax(min(100%, 13rem), 1fr)); }
.footer-grid ul { list-style: none; padding: 0; }
.footer-grid li + li { margin-top: .4rem; }
.footer-social {
  display: flex; flex-wrap: wrap; gap: .4rem 1.4rem;
  margin-top: 2rem;
}
.footer-social a {
  display: inline-flex; align-items: center; gap: .5rem;
  color: var(--on-dark-muted); text-decoration: none; font-weight: 600;
}
.footer-social a:hover { color: var(--yellow); }
.footer-social svg { width: 1.15rem; height: 1.15rem; flex-shrink: 0; }

.footer-bottom {
  margin-top: 2.25rem; padding-top: 1.35rem;
  border-top: 1px solid rgba(255,255,255,.1);
  display: flex; flex-wrap: wrap; gap: .5rem 1.5rem; justify-content: space-between;
  /* The footer sits on --ink, so it takes the on-dark token. It used to take
     --text-faint, which is scaled for light grounds and only cleared AA here by
     accident — the moment --text-faint was darkened for its actual job, this
     dropped to 3.32. */
  color: var(--on-dark-muted);
}

/* ---------------------------------------------------------------- misc */

.placeholder {
  display: grid; place-items: center; min-height: 13rem;
  border: 2px dashed var(--line-strong); border-radius: var(--radius-lg);
  background: var(--surface-2); color: var(--text-faint);
  font-size: var(--step--1); text-align: center; padding: 1.4rem;
}

/* Below ~340px there is not room for the wordmark alongside the phone, the
   Get Started button and the menu toggle. The mark stays; the words go. */
@media (max-width: 21.5rem) {
  .brand-text { display: none; }
}
