/* =============================================================================
   Built by Faith Love Fitness - concept preview
   Blueprint recreation: templates/blueprints/fitness/gym-solace

   TYPE PAIRING AND WHY
   --------------------
   Display / headlines / pull-quotes : LITERATA (600, upright)
     The blueprint's tonal trick is an editorial serif carrying every headline,
     which is what stops a gym page reading as an "aggro fitness" flyer and lets
     it sell belonging instead. Literata was chosen over the obvious literary
     serifs for three reasons that matter on THIS page. (a) LOW STROKE CONTRAST:
     four of this page's headings are reversed white over photography, and a
     transitional face with hairline joins (Playfair, Prata) shatters there.
     Literata's stems and hairlines stay close in weight, so a 56px white
     headline survives a scrim. (b) It carries REAL 600 and 700 cuts on its
     upright axis, which the font link requests - a display heading asked for a
     weight the link never loaded gets a synthesised faux-bold, which is exactly
     the smeared look this build is trying to avoid (TASTE_LEDGER #53).
     (c) Its slightly narrow, sturdy lowercase gives "Strengthen what God made."
     a two-line set on a 390px phone without hyphenation, and its warmth suits a
     studio that describes itself as a ministry rather than a facility.
     Deliberately NOT Fraunces (operator taste rule) and deliberately not the
     clinical build's Newsreader - a lighter, more bookish face whose italic is
     its whole point, where this page never uses italic at all.
   Body / UI / labels : ARCHIVO (400/500/600/700)
     A grotesque with slightly condensed, athletic proportions. This page is
     dense with things a reader has to actually parse - five programs, six
     certifications, seven rows of opening hours, a two-step booking wizard -
     and Archivo sets small text tightly without going brittle. Its caps are
     narrow enough that the tracked-caps eyebrow register reads as a label
     rather than a banner, and its figures are even enough for a phone number
     and an hours column.

   PALETTE - the prospect's own scheme, nothing imported
   -------
     #18C8E8  brand cyan     : their logo (barbell + heart + cross) and the only
                               saturated colour anywhere on their real site.
                               Used as an ACCENT: icons on dark, rules, hovers.
                               Never a page canvas - a cyan page is not their
                               site, their site is white.
     #0C7B92  brand deep     : the AA-safe darkening of that cyan recorded in
                               theme.json as brandStrong. Primary CTA fill and
                               every link on a light ground.
     #06576A  brand darker   : the footer ground. Their real footer is #000000;
                               this is that darkness pulled onto their own hue so
                               the page closes in the brand rather than in black.
     #A8761A  gold           : theme.json's --color-accent (#B8862E) taken to a
                               contrast-safe depth. The blueprint spends a gold
                               on its display accents; this is that gold, and it
                               is the ONE warm note against the cyan.
     #E8B65A  gold light     : the same accent reversed onto dark bands - the h1
                               accent word, the 01/02/03 numerals, dark eyebrows.
     #12181B  ink            : the near-black their own footer already uses.
   ============================================================================= */

:root {
  --brand: #18C8E8;
  --brand-deep: #0C7B92;
  --brand-darker: #06576A;
  --brand-pale: #8FE3F4;

  --gold: #A8761A;
  --gold-ink: #8A6420;
  --gold-light: #E8B65A;

  --ink: #12181B;
  --ink-soft: #35414A;
  --grey: #566169;
  --grey-line: #DBE5E9;
  --paper: #ffffff;
  --paper-warm: #F9FCFD;
  --tint: #E2F0F5;
  --tint-soft: #F1F8FB;

  --serif: "Literata", Georgia, "Times New Roman", serif;
  --sans: "Archivo", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

  --wrap: 1240px;
  --gutter: clamp(1.25rem, 4vw, 3.5rem);
  --radius: 14px;
}

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

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

/* Anchor jumps must not park a heading under the sticky nav. Every element that
   can be an anchor target reserves the nav's height plus air above itself.
   --nav-h is MEASURED at runtime by main.js, because the real height is driven
   by the brand logo's aspect ratio and so differs per viewport; the values here
   are the measured fallback for a no-JS render (TASTE_LEDGER #62). */
:root { --nav-h: 96px; }
@media (max-width: 960px) { :root { --nav-h: 66px; } }
[id] { scroll-margin-top: calc(var(--nav-h) + 1.25rem); }

body {
  margin: 0;
  font-family: var(--sans);
  font-size: clamp(1rem, 0.97rem + 0.16vw, 1.0625rem);
  line-height: 1.65;
  color: var(--ink-soft);
  background: var(--paper);
  /* NO overflow-x on the body, deliberately. Both values are traps here:
     `hidden` turns the body into a scroll container and silently kills every
     position:sticky inside it (the nav), and `clip` on one axis forces the
     other axis to compute to `auto`, which does the same thing by a different
     route - and, measured on this page, left the reviews photograph unpainted.
     Nothing on the page bleeds past the viewport any more (the one 100vw
     element, an earlier masked band photo, is gone), and .reviews keeps its own
     `overflow: hidden` so a future bleed is contained by its own band rather
     than by a page-wide rule with side effects. The gate's `overflow` check
     measures this at both widths. */
}

img { max-width: 100%; display: block; }

/* [hidden] must beat any component's own display rule, or a flex form stays on
   screen underneath its own confirmation panel. */
[hidden] { display: none !important; }

h1, h2, h3, h4 {
  font-family: var(--serif);
  color: var(--ink);
  font-weight: 600;
  line-height: 1.12;
  margin: 0;
  letter-spacing: -0.02em;
}

p { margin: 0 0 1.05em; }
p:last-child { margin-bottom: 0; }

a { color: inherit; }

.wrap { max-width: var(--wrap); margin-inline: auto; padding-inline: var(--gutter); }

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

.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--ink); color: #fff; padding: 0.7rem 1.1rem; border-radius: 0 0 8px 0;
  font-size: 0.9rem;
}
.skip-link:focus { left: 0; }

:where(a, button, input, select, textarea):focus-visible {
  outline: 3px solid var(--gold);
  outline-offset: 2px;
}

/* ---------- shared bits -------------------------------------------------- */

.eyebrow {
  font-family: var(--sans);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  margin: 0 0 1.1rem;
  color: var(--gold-ink);
}

.pill {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem;
  font-family: var(--sans);
  font-size: 0.9375rem;
  font-weight: 600;
  line-height: 1;
  padding: 0.95rem 1.6rem;
  border-radius: 999px;
  border: 1.5px solid transparent;
  text-decoration: none;
  cursor: pointer;
  transition: background-color .18s ease, color .18s ease, border-color .18s ease, transform .18s ease;
  white-space: nowrap;
}
.pill:hover { transform: translateY(-1px); }

.pill-brand { background: var(--brand-deep); color: #fff; }
.pill-brand:hover { background: var(--brand-darker); }

.pill-brand-light { background: var(--brand-pale); color: var(--ink); }
.pill-brand-light:hover { background: #fff; }

.pill-white { background: #fff; color: var(--ink); }
.pill-white:hover { background: var(--tint); }

.pill-ghost-dark { background: transparent; color: var(--ink); border-color: rgba(18,24,27,.28); }
.pill-ghost-dark:hover { background: var(--ink); color: #fff; border-color: var(--ink); }

/* One icon register for the whole build: line icons, currentColor by default,
   overridden to the brand cyan wherever the control is a secondary option. */
.ico {
  flex: 0 0 auto;
  fill: none; stroke: currentColor; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
}
/* The sprite every .ico references. Out of flow and out of the a11y tree; it
   must not be display:none, which in some engines stops <use> resolving. */
.icon-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

/* Section rhythm at the x0.6 standard (TASTE_LEDGER #52): a section pair reads
   121px at 1440 and 67px at 390. */
.section { padding-block: clamp(2.1rem, 4.2vw, 3.9rem); }

/* Shared band grain. Every painted band carries a fine SVG noise tile over its
   photo + scrim stack so the surface reads as a printed tone rather than a flat
   CSS gradient, and so a wide ramp does not band on 8-bit displays. */
.beliefs::before, .reviews::before, .book::before {
  content: ""; position: absolute; inset: 0;
  pointer-events: none; z-index: 0;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23g)'/%3E%3C/svg%3E");
  background-size: 120px 120px;
  opacity: .10;
}
.beliefs, .reviews, .book { position: relative; isolation: isolate; }
.beliefs > .wrap, .book > .wrap { position: relative; z-index: 1; }

/* ---------- 1. utility bar ----------------------------------------------- */

.utility {
  background: var(--ink);
  color: rgba(255,255,255,.82);
  font-size: 0.8125rem;
  letter-spacing: 0.01em;
}
.utility .wrap {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 1.6rem;
  min-height: 42px; padding-block: 0.5rem;
}
.utility a { text-decoration: none; }
.utility a:hover { color: #fff; text-decoration: underline; }
.utility-sep { margin-left: auto; }
.utility-strong { color: #fff; font-weight: 600; }

@media (max-width: 860px) {
  .utility { font-size: 0.75rem; }
  .utility .wrap { justify-content: center; gap: 0.35rem 1rem; }
  .utility-sep { margin-left: 0; }
  .utility-hide-sm { display: none; }
}

/* ---------- 2. nav -------------------------------------------------------
   The blueprint's nav is white with a serif wordmark and a gold pill top right.
   This studio's real logotype is a cyan mark plus a cyan wordmark on white, and
   their live site runs a white header, so the nav stays white and carries the
   true mark. The gold is spent on display accents instead, and the nav's pill
   takes the brand's own deep cyan so the primary action is unmistakably theirs.
   ------------------------------------------------------------------------- */

.nav {
  position: sticky; top: 0; z-index: 60;
  background: rgba(255,255,255,.96);
  backdrop-filter: saturate(140%) blur(8px);
  border-bottom: 1px solid var(--grey-line);
}
.nav .wrap {
  display: flex; align-items: center; gap: 1.1rem;
  min-height: 76px; padding-block: 0.7rem;
}
.nav-logo { display: block; flex: 0 0 auto; min-width: 0; }
/* Never pin a logo's HEIGHT inside a flex row: flex-shrink squeezes the width
   while the height holds and the lockup distorts. Cap, never fix. */
.nav-logo img {
  width: clamp(150px, 16vw, 196px);
  max-width: 100%; height: auto;
  min-width: 0; object-fit: contain;
}

.nav-links {
  display: flex; align-items: center; gap: clamp(0.85rem, 1.7vw, 1.6rem);
  margin-left: auto;
  list-style: none; padding: 0; margin-block: 0;
}
.nav-links a {
  text-decoration: none;
  white-space: nowrap;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--ink-soft);
  padding-block: 0.4rem;
  border-bottom: 2px solid transparent;
}
.nav-links a:hover { color: var(--brand-deep); border-bottom-color: var(--brand); }

.nav-actions { display: flex; align-items: center; gap: 0.55rem; flex: 0 0 auto; }
.nav-actions .pill { padding: 0.8rem 1.15rem; font-size: 0.875rem; }
.nav-call .ico { stroke: var(--brand-deep); transition: stroke .18s ease; }
.nav-call:hover .ico { stroke: #fff; }
.nav-call { font-variant-numeric: tabular-nums; }

.nav-toggle {
  display: none;
  background: none; border: 1px solid var(--grey-line); border-radius: 10px;
  width: 44px; height: 44px; cursor: pointer;
  align-items: center; justify-content: center;
  color: var(--ink);
}
.nav-toggle span, .nav-toggle span::before, .nav-toggle span::after {
  content: ""; display: block; width: 20px; height: 2px; background: currentColor; border-radius: 2px;
}
.nav-toggle span { position: relative; }
.nav-toggle span::before { position: absolute; top: -6px; }
.nav-toggle span::after { position: absolute; top: 6px; }

@media (max-width: 1080px) {
  .nav .wrap { min-height: 66px; }
  .nav-toggle { display: inline-flex; order: 9; }
  .nav-links {
    position: absolute; inset: 100% 0 auto 0;
    flex-direction: column; align-items: stretch; gap: 0;
    background: #fff; border-bottom: 1px solid var(--grey-line);
    padding: 0.5rem var(--gutter) 1.1rem;
    margin-left: 0;
    display: none;
  }
  .nav[data-open="true"] .nav-links { display: flex; }
  .nav-links a { padding-block: 0.85rem; border-bottom: 1px solid var(--grey-line); }
  .nav-links li:last-child a { border-bottom: 0; }
  /* Both conversion controls survive on a phone, collapsed to icon-only round
     buttons; the labels stay in the accessibility tree. */
  .nav-actions { margin-left: auto; order: 8; gap: 0.4rem; }
  .nav-actions .pill { padding: 0; width: 44px; height: 44px; }
  .nav-label {
    position: absolute; width: 1px; height: 1px;
    margin: -1px; padding: 0; overflow: hidden;
    clip-path: inset(50%); white-space: nowrap; border: 0;
  }
}
@media (max-width: 600px) {
  .nav .wrap { gap: 0.6rem; }
  .nav-logo img { width: clamp(128px, 38vw, 160px); }
}

/* ---------- 3. hero -------------------------------------------------------
   Blueprint: a full-bleed real photograph of the gym under a warm overlay, a
   left-aligned stacked headline of very few words, one location-anchored
   paragraph and the conversion pair. The photograph is this studio's own floor,
   from their Google Business profile; the CTA pair collapses to one two-step
   booking wizard, because a single-coach studio has one conversion, not two.
   ------------------------------------------------------------------------- */

.hero { position: relative; isolation: isolate; background: var(--ink); }

/* A real <img>, not a CSS background: the gate's hero-photo, images-load and
   overlay-legibility checks all need an element they can measure, and a lazily
   loaded band image stays undecoded while images-load still reports fine. */
.hero-photo {
  position: absolute; inset: 0; z-index: -2;
  width: 100%; height: 100%;
  object-fit: cover;
  /* 38% lands the crop on the rack wall, the ball rack and the member training
     under it rather than on the empty floor; at 390 the band's aspect is close
     to the source's own, so almost the whole frame is in view and the position
     barely moves anything. */
  object-position: 50% 38%;
}

.hero::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(180deg, rgba(10,16,18,.58) 0%, rgba(10,16,18,.62) 38%, rgba(10,16,18,.86) 100%),
    linear-gradient(96deg, rgba(6,20,26,.62) 0%, rgba(6,20,26,.34) 46%, rgba(6,20,26,.12) 78%, rgba(6,20,26,.30) 100%);
}

.hero-inner {
  padding-block: clamp(3.25rem, 7vw, 5.75rem);
  min-height: clamp(540px, 76vh, 740px);
  display: flex; flex-direction: column; justify-content: center; align-items: flex-start;
  text-align: left;
}

.hero h1 {
  color: #fff;
  font-size: clamp(2.05rem, 1.05rem + 3.9vw, 4.25rem);
  max-width: 15ch;
  line-height: 1.04;
  text-wrap: balance;
  text-shadow: 0 2px 26px rgba(0,0,0,.5);
  margin-bottom: clamp(1rem, 2.2vw, 1.5rem);
}
/* Exactly one accent word in the whole headline (TASTE_LEDGER #41), upright and
   700 so it is the heaviest thing on the line as well as the only coloured one.
   #E8B65A over this scrim measures far past the 4.5 floor; a mid gold would not
   have. */
.hero h1 em { font-style: normal; font-weight: 700; color: var(--gold-light); }

.hero-sub {
  color: rgba(255,255,255,.92);
  font-size: clamp(1rem, 0.95rem + 0.35vw, 1.1875rem);
  max-width: 54ch;
  margin: 0 0 clamp(1.5rem, 3vw, 2.1rem);
  text-shadow: 0 1px 14px rgba(0,0,0,.55);
}

/* The wizard plate. Step 1 is name/phone/advance and fits 620px; step 2 carries
   four controls, so the plate opens to 900px and transitions rather than jumps. */
.hero-form {
  background: rgba(255,255,255,.96);
  padding: 0.5rem;
  border-radius: 999px;
  width: min(620px, 100%);
  box-shadow: 0 18px 44px rgba(0,0,0,.30);
  transition: width .22s ease;
}
.hero-form[data-step="2"] { width: min(900px, 100%); }
/* The panels, not the form, are the flex rows: the form holds exactly one
   visible panel at a time and [hidden] takes the other out of the layout. */
.hero-step {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem;
  width: 100%;
}
.hero-form input,
.hero-form select {
  flex: 1 1 140px; min-width: 0;
  border: 0; background: transparent;
  font: inherit; font-size: 0.9375rem;
  color: var(--ink);
  padding: 0.75rem 1.1rem;
  border-radius: 999px;
}
/* The selects share the white plate with the inputs, so they lose the platform
   chrome to match; the caret is drawn back as a background mark with room
   reserved in the right padding. */
.hero-form select {
  appearance: none; -webkit-appearance: none;
  padding-right: 2.1rem;
  text-overflow: ellipsis;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' fill='none' stroke='%230C7B92' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1 1.5 6 6.5l5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 1rem center;
  cursor: pointer;
}
.hero-form input::placeholder { color: #78838a; }
/* The selects' "placeholder" is a real empty-valued first option, so it is
   styled to match rather than inheriting the chosen-value ink. */
.hero-form select:has(option[value=""]:checked) { color: #78838a; }
/* Options are painted by the platform, which does NOT inherit the control's
   colours - state them, or a dark system theme drops white text on white
   (TASTE_LEDGER #55). Stated on every select on the page, not just this one. */
select option { background-color: #ffffff; color: var(--ink); }
.hero-form input:focus, .hero-form select:focus { outline: 2px solid var(--brand-deep); outline-offset: -1px; }
.hero-form .pill { flex: 0 0 auto; }
.hero-next { text-decoration: none; }

/* Wizard chrome under the bar: where you are, and the way back. */
.hero-stepper {
  display: flex; align-items: center; gap: 0.85rem; flex-wrap: wrap;
  width: min(900px, 100%);
  margin: 0.85rem 0 0;
  font-family: var(--sans); font-size: 0.8125rem;
  color: rgba(255,255,255,.92);
  text-shadow: 0 1px 10px rgba(0,0,0,.6);
}
.hero-back {
  display: inline-flex; align-items: center; gap: 0.35rem;
  font: inherit; font-weight: 600; color: #fff;
  background: rgba(255,255,255,.14);
  border: 1px solid rgba(255,255,255,.42);
  border-radius: 999px;
  padding: 0.3rem 0.8rem 0.3rem 0.6rem;
  cursor: pointer;
}
.hero-back .ico { stroke-width: 2.2; }
.hero-back:hover { background: rgba(255,255,255,.26); }

/* The hero's preview-honest confirmation takes the form's place in the layout,
   on the same white plate so it stays fully legible over the photograph. */
.hero-done {
  width: min(680px, 100%); margin: 0;
  background: rgba(255,255,255,.96);
  border-radius: 20px;
  padding: 1.05rem 1.35rem;
  color: var(--ink);
  font-size: 0.9375rem; line-height: 1.6; text-align: left;
  box-shadow: 0 18px 44px rgba(0,0,0,.28);
}
.hero-done a { color: var(--brand-deep); font-weight: 600; white-space: nowrap; }

.hero-objection {
  margin: clamp(1.1rem, 2.4vw, 1.6rem) 0 0;
  color: #fff;
  font-family: var(--serif);
  font-size: clamp(1.0625rem, 0.98rem + 0.42vw, 1.35rem);
  font-weight: 500;
  text-shadow: 0 1px 14px rgba(0,0,0,.6);
}

@media (max-width: 900px) {
  /* The wizard stacks: the plate becomes a rounded card and both steps become a
     column of full-width controls, so the step-2 width bump is pointless here
     and both steps share one width.
     The generous bottom padding is not decoration - it is what keeps the hero's
     primary control clear of OUR fixed preview badge at scroll 0, which the
     gate's preview-chrome-clear check measures at 390. */
  .hero-inner {
    min-height: 84vh;
    justify-content: flex-end;
    padding-bottom: clamp(5rem, 15vw, 6.5rem);
  }
  .hero h1 {
    max-width: 100%;
    text-wrap: normal;
    font-size: clamp(1.85rem, 8vw, 2.7rem);
  }
  .hero-sub { font-size: 1rem; }
  .hero-form { border-radius: 18px; padding: 0.75rem; }
  .hero-form[data-step="2"] { width: min(620px, 100%); }
  .hero-step { flex-direction: column; align-items: stretch; gap: 0.6rem; }
  .hero-form input,
  .hero-form select {
    flex: 0 0 auto; width: 100%;
    border-radius: 11px;
    /* background-COLOR, not the shorthand: the shorthand would reset
       background-image and silently delete the select's drawn caret. */
    background-color: #fff;
    box-shadow: inset 0 0 0 1px var(--grey-line);
    padding: 0.85rem 1rem;
  }
  .hero-form select { padding-right: 2.1rem; }
  .hero-form .pill { width: 100%; }
  .hero-stepper { width: min(620px, 100%); }
}

/* ---------- 4. the method (paper) -----------------------------------------
   Blueprint's signature-class band: copy column left with a short list and one
   CTA, an offset photo mosaic of real training shots right. Their signature is
   a METHOD rather than a class, so the list is the method's four letters,
   exactly as their one-on-one page publishes them and no further - "Energy" is
   the only one they gloss, so it is the only one glossed here (rule 79).
   ------------------------------------------------------------------------- */

.method { background: var(--paper); }
/* align-items: stretch is what squares the two columns off at the bottom
   (TASTE_LEDGER #62); both columns also START at the band's top padding, so no
   text start drifts with copy length (#61). */
.method .wrap {
  display: grid; gap: clamp(1.75rem, 4vw, 3.25rem);
  grid-template-columns: minmax(0, 1.02fr) minmax(0, 0.98fr);
  align-items: stretch;
}
.method-copy { display: flex; flex-direction: column; }
.method h2 {
  font-size: clamp(1.9rem, 1.15rem + 2.6vw, 3.1rem);
  margin-bottom: 1rem;
}
.method-copy p { color: var(--grey); max-width: 54ch; }

.method-label {
  font-family: var(--sans);
  font-size: 0.6875rem; font-weight: 700;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--brand-deep);
  margin: clamp(1.3rem, 2.6vw, 1.9rem) 0 0.9rem;
}
/* The method as four lettered items, not an icon grid. The letter is the
   graphic; there is not a single SVG in this band. */
.fuel {
  list-style: none; padding: 0; margin: 0;
  display: grid; gap: 0.7rem clamp(0.9rem, 2vw, 1.6rem);
  grid-template-columns: repeat(2, minmax(0, 1fr));
}
.fuel li {
  display: flex; align-items: baseline; gap: 0.7rem;
  border-top: 1px solid var(--grey-line);
  padding-top: 0.6rem;
}
.fuel-letter {
  font-family: var(--serif); font-weight: 700;
  font-size: 1.5rem; line-height: 1;
  color: var(--gold-ink);
  flex: 0 0 auto;
}
.fuel-word {
  font-family: var(--sans); font-weight: 600; font-size: 1rem;
  color: var(--ink); line-height: 1.3;
}
.fuel-gloss {
  display: block;
  font-weight: 400; font-size: 0.8125rem; color: var(--grey);
  letter-spacing: 0.01em;
}
/* margin-top:auto drops the actions to the bottom of the stretched column so
   they land level with the bottom edge of the mosaic. */
.method-actions {
  display: flex; flex-wrap: wrap; gap: 0.7rem;
  margin-top: auto; padding-top: clamp(1.5rem, 3vw, 2.1rem);
}

.mosaic {
  display: grid;
  grid-template-columns: 1.16fr 0.84fr;
  grid-template-rows: 0.96fr 1.04fr;
  gap: clamp(0.55rem, 1.2vw, 0.9rem);
  min-height: clamp(340px, 34vw, 520px);
}
.mosaic figure {
  margin: 0; border-radius: 10px; overflow: hidden;
  background: var(--tint);
  box-shadow: 0 14px 34px rgba(6,87,106,.13);
}
.mosaic img { width: 100%; height: 100%; object-fit: cover; }
.mosaic-a { grid-column: 1 / -1; grid-row: 1; }
.mosaic-b { grid-column: 1; grid-row: 2; }
.mosaic-c { grid-column: 2; grid-row: 2; }
/* The mobility shot is a wide frame in a tall box; centre-left lands on the two
   people rather than on the empty half of the room. */
.mosaic-c img { object-position: 46% 50%; }

/* ---- media columns must not DRIVE the row height -------------------------
   Shared by all three two-column bands. An in-flow <img> inside a grid figure
   contributes its own intrinsic height to the column, so the photo column, not
   the copy, set the row height - and the copy column's `margin-top: auto`
   actions then dropped to the bottom of a column hundreds of pixels taller than
   their own text. MEASURED before this rule: 560px of dead white inside .coach
   and ~250px inside .programs at 1440, with the columns technically
   bottom-aligned and the band visibly broken.
   Taking the images out of flow makes each media column's intrinsic height
   ZERO, so the row is sized by the copy, the grid stretches the media column to
   exactly that height, and the fr rows divide it. The columns end on the same
   line because the photos fill the space the copy defines, which is the right
   way round (TASTE_LEDGER #62). Wide layouts only: below 901px both columns
   stack and the images are back in flow, where they belong. */
@media (min-width: 901px) {
  .mosaic figure, .programs-media figure, .coach-media figure { position: relative; min-height: 0; }
  .mosaic figure img, .programs-media figure img, .coach-media figure img {
    position: absolute; inset: 0; width: 100%; height: 100%;
  }
}

@media (max-width: 900px) {
  .method .wrap { grid-template-columns: 1fr; }
  .mosaic { min-height: 300px; }
}
@media (max-width: 520px) {
  .fuel { grid-template-columns: 1fr; }
}

/* ---------- 5. what we believe (dark photo band) --------------------------
   The blueprint's numbered 01/02/03 band - the page's one typographic breather,
   zero icons. A real photograph of one of their own classes breathes under an
   ink scrim, so the band is a place rather than a slab of paint
   (TASTE_LEDGER #48 / #60). background-color repeats the ink so a failed image
   still paints a band.
   ------------------------------------------------------------------------- */

.beliefs {
  background-color: var(--ink);
  background-image:
    repeating-linear-gradient(135deg, rgba(255,255,255,.026) 0 1px, rgba(255,255,255,0) 1px 7px),
    linear-gradient(112deg, rgba(9,32,40,.93) 0%, rgba(12,24,28,.90) 52%, rgba(6,49,60,.91) 100%),
    linear-gradient(rgba(8,14,16,.42), rgba(8,14,16,.42)),
    url("../img/band-community.jpg");
  background-size: auto, auto, auto, cover;
  background-position: center, center, center, 50% 44%;
  background-repeat: repeat, no-repeat, no-repeat, no-repeat;
  color: rgba(255,255,255,.88);
}
.beliefs .eyebrow { color: var(--gold-light); }
.beliefs h2 {
  color: #fff;
  font-size: clamp(1.9rem, 1.15rem + 2.6vw, 3.1rem);
  margin-bottom: 0.9rem;
}
.beliefs-lede {
  max-width: 58ch;
  color: rgba(255,255,255,.92);
  margin-bottom: clamp(1.7rem, 3.6vw, 2.5rem);
}
.beliefs-grid {
  display: grid; gap: clamp(1rem, 2.2vw, 1.6rem);
  grid-template-columns: repeat(3, minmax(0, 1fr));
  list-style: none; padding: 0; margin: 0 0 clamp(1.6rem, 3vw, 2.3rem);
}
.beliefs-grid li {
  background: rgba(255,255,255,.06);
  border: 1px solid rgba(255,255,255,.10);
  border-top: 3px solid var(--gold-light);
  border-radius: 12px;
  padding: clamp(1.15rem, 2.2vw, 1.6rem) clamp(1.15rem, 2.2vw, 1.5rem) clamp(1.3rem, 2.4vw, 1.7rem);
  box-shadow: 0 14px 30px rgba(4,10,12,.30);
}
/* The numeral is a span INSIDE the h3, so numeral and title are one heading
   line at one size; `font: inherit` takes the h3's family, size, weight and
   line-height by definition so the two can never drift, and only the colour
   differs. aria-hidden because the <ol> already carries the ordering. */
.belief-num {
  font: inherit; letter-spacing: inherit;
  color: var(--gold-light);
  margin-right: 0.34em;
}
.beliefs-grid h3 {
  color: #fff; font-weight: 600;
  font-size: clamp(1.1rem, 0.98rem + 0.42vw, 1.3rem);
  line-height: 1.18;
  padding-bottom: 0.75rem; margin-bottom: 0.9rem;
  border-bottom: 1px solid rgba(232,182,90,.34);
}
.beliefs-grid p { font-size: 0.9375rem; color: rgba(255,255,255,.86); margin-bottom: 0; }

.beliefs-cta {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 0.9rem 1.5rem;
}
.beliefs-cta-copy {
  margin: 0; max-width: 44ch;
  font-size: 0.9375rem; line-height: 1.5;
  color: rgba(255,255,255,.92);
}

@media (max-width: 860px) { .beliefs-grid { grid-template-columns: 1fr; } }
@media (max-width: 560px) {
  .beliefs-cta { flex-direction: column; align-items: stretch; gap: 1rem; }
  .beliefs-cta .pill { justify-content: center; }
}

/* ---------- 6. programs (paper) -------------------------------------------
   The blueprint's membership band, scaled honestly: this studio publishes no
   prices anywhere, so the band cannot be a price table. It is the five programs
   their services pages list, in their own descriptions, beside two real
   photographs of the two that are easiest to picture wrongly.
   ------------------------------------------------------------------------- */

.programs { background: var(--paper-warm); }
.programs .wrap {
  display: grid; gap: clamp(1.75rem, 4vw, 3.25rem);
  grid-template-columns: minmax(0, 1.25fr) minmax(0, 0.75fr);
  align-items: stretch;
}
.programs-copy { display: flex; flex-direction: column; }
.programs h2 {
  font-size: clamp(1.9rem, 1.15rem + 2.6vw, 3.1rem);
  margin-bottom: 0.9rem;
}
.programs-lede { color: var(--grey); max-width: 56ch; margin-bottom: clamp(1.4rem, 2.8vw, 2rem); }

.program-list { list-style: none; padding: 0; margin: 0; }
.program-list li {
  display: grid;
  grid-template-columns: minmax(0, 0.62fr) minmax(0, 1fr);
  gap: 0.35rem clamp(1rem, 2.4vw, 2rem);
  border-top: 1px solid var(--grey-line);
  padding: clamp(0.9rem, 1.8vw, 1.2rem) 0;
}
.program-list li:last-child { border-bottom: 1px solid var(--grey-line); }
.program-list h3 {
  font-size: clamp(1.0625rem, 1rem + 0.35vw, 1.25rem);
  font-weight: 600;
  grid-column: 1; grid-row: 1;
}
.program-meta {
  grid-column: 1; grid-row: 2;
  margin: 0;
  font-size: 0.6875rem; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--gold-ink);
}
.program-list li > p:last-child {
  grid-column: 2; grid-row: 1 / span 2;
  margin: 0;
  font-size: 0.9375rem; color: var(--grey);
}

.programs-cta {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 0.9rem 1.5rem;
  margin-top: auto; padding-top: clamp(1.4rem, 2.8vw, 2rem);
}
.programs-cta-copy { margin: 0; max-width: 40ch; color: var(--grey); font-size: 0.9375rem; }

.programs-media {
  display: grid; grid-template-rows: 1fr 1fr;
  gap: clamp(0.55rem, 1.2vw, 0.9rem);
  min-height: 380px;
}
.programs-media figure {
  margin: 0; border-radius: 10px; overflow: hidden;
  background: var(--tint);
  box-shadow: 0 14px 34px rgba(6,87,106,.13);
}
.programs-media img { width: 100%; height: 100%; object-fit: cover; }

@media (max-width: 900px) {
  .programs .wrap { grid-template-columns: 1fr; }
  .programs-media { grid-template-rows: none; grid-template-columns: 1fr 1fr; min-height: 260px; }
}
@media (max-width: 620px) {
  .program-list li { grid-template-columns: 1fr; }
  .program-list h3, .program-meta, .program-list li > p:last-child { grid-column: 1; grid-row: auto; }
  .program-list li > p:last-child { margin-top: 0.45rem; }
}
@media (max-width: 560px) {
  .programs-cta { flex-direction: column; align-items: stretch; gap: 1rem; }
  .programs-cta .pill { justify-content: center; }
}

/* ---------- 7. your coach (tint) ------------------------------------------
   Blueprint's "personal training that is actually personal" band, at the scale
   this business really is: one coach, so one card, and every fact on it is
   published on their own about page.
   ------------------------------------------------------------------------- */

/* --tint, not --tint-soft. The band above is --paper-warm (#F9FCFD) and the
   soft tint (#F1F8FB) is only four points off it, so at full page scale the two
   read as ONE continuous pale run - technically two grounds, visually a single
   band, which is not what "no two adjacent sections share a background" is
   asking for. The full tint separates them and still clears AA for the muted
   body colour (measured 5.0:1). */
.coach { background: var(--tint); }
.coach .wrap {
  display: grid; gap: clamp(1.75rem, 4vw, 3.25rem);
  grid-template-columns: minmax(0, 1.06fr) minmax(0, 0.94fr);
  align-items: stretch;
}
.coach-copy { display: flex; flex-direction: column; }
.coach h2 {
  font-size: clamp(1.9rem, 1.15rem + 2.6vw, 3.1rem);
  margin-bottom: 1.1rem;
}
/* A TOP rule, not a left one. An accent-coloured left border on a block is the
   pattern TASTE_LEDGER #21 banned permanently; this is a pull-quote rather than
   a card, but a master candidate is the wrong place to argue a technicality, and
   the 3px top rule is the register the belief cards already use, so the two read
   as one system. */
.coach-quote {
  margin: 0 0 0.6rem;
  font-family: var(--serif);
  font-size: clamp(1.15rem, 1rem + 0.75vw, 1.5rem);
  font-weight: 500; line-height: 1.42;
  color: var(--ink);
  border-top: 3px solid var(--gold);
  padding-top: clamp(0.85rem, 1.8vw, 1.2rem);
  max-width: 40ch;
}
.coach-attrib {
  font-family: var(--sans); font-size: 0.75rem; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--brand-deep);
  margin: 0 0 1.15rem;
}
.coach-copy > p { color: var(--grey); max-width: 52ch; }

.coach-label {
  font-family: var(--sans);
  font-size: 0.6875rem; font-weight: 700;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--gold-ink);
  margin: clamp(1.2rem, 2.4vw, 1.7rem) 0 0.85rem;
}
.creds {
  list-style: none; padding: 0; margin: 0 0 1.35rem;
  display: flex; flex-direction: column; gap: 0.55rem;
}
/* A small rotated square in the accent, never a default disc and never an icon
   - this band has no SVG in it either. */
.creds li {
  position: relative; padding-left: 1.1rem;
  font-size: 0.9375rem; font-weight: 500; line-height: 1.45;
  color: var(--ink);
}
.creds li::before {
  content: ""; position: absolute; left: 0; top: 0.52em;
  width: 6px; height: 6px; border-radius: 1px;
  background: var(--gold);
  transform: rotate(45deg);
}
.coach-record {
  font-size: 0.875rem; line-height: 1.55; color: var(--grey);
  border-top: 1px solid var(--grey-line);
  padding-top: 0.9rem; margin: 0;
  max-width: 52ch;
}
.coach-actions {
  display: flex; flex-wrap: wrap; gap: 0.7rem;
  margin-top: auto; padding-top: clamp(1.4rem, 2.8vw, 2rem);
}

.coach-media {
  display: grid;
  grid-template-rows: 1.3fr 0.9fr;
  gap: clamp(0.55rem, 1.2vw, 0.9rem);
  min-height: 420px;
}
.coach-media figure {
  margin: 0; border-radius: 10px; overflow: hidden;
  background: var(--tint);
  box-shadow: 0 16px 38px rgba(6,87,106,.15);
}
.coach-media img { width: 100%; height: 100%; object-fit: cover; }
.coach-portrait img { object-position: 50% 30%; }
/* The lower tile is a wide strip cut from a portrait frame, so the crop has to
   be pulled UP: at centre it took the two people off at the shoulders. */
.coach-action img { object-position: 50% 32%; }

@media (max-width: 900px) {
  .coach .wrap { grid-template-columns: 1fr; }
  .coach-media { grid-template-rows: none; grid-template-columns: 1.3fr 0.7fr; min-height: 280px; }
}

/* ---------- 8. reviews (dark band) ----------------------------------------
   The blueprint's dark reviews band, with its one recorded defect fixed: the
   inspiration paints this slot through a JS carousel that photographs BLANK
   whenever the script does not run, so these three quotes are static markup.
   The band opens on a real photograph of the coach these reviews are about,
   which dissolves into the ink just below the rating pill, so the heading and
   stars sit ON imagery and every quote card below sits on clean ground.
   ------------------------------------------------------------------------- */

/* Never a bare slab: the ink carries a wide off-axis ramp toward the brand's
   own deep cyan plus the shared grain, so the darkest band on the page still
   has a surface (TASTE_LEDGER #48). */
.reviews {
  background-color: var(--ink);
  background-image:
    repeating-linear-gradient(135deg, rgba(255,255,255,.022) 0 1px, rgba(255,255,255,0) 1px 7px),
    linear-gradient(146deg, #11181c 0%, #0d2129 46%, #10171b 100%);
  overflow: hidden;
  color: rgba(255,255,255,.88);
}
.reviews > .wrap { position: relative; z-index: 1; }

/* Heading and photograph share a row. The photo column is deliberately the
   narrower one: the tile is SQUARE, so its height is set by its width, and at
   0.78fr it stood ~220px taller than the heading stack it sits beside. Centred
   rather than top-aligned because the two are a caption and a portrait, not two
   columns of reading - and the tile's height is a fixed function of the column,
   never of copy length, so nothing here drifts as the lede rewraps
   (TASTE_LEDGER #61). */
.reviews-head {
  display: grid; gap: clamp(1.5rem, 3.4vw, 2.75rem);
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.66fr);
  align-items: center;
  margin-bottom: clamp(1.6rem, 3.2vw, 2.4rem);
}
.reviews-intro .eyebrow { color: var(--gold-light); }
.reviews-head h2 {
  color: #fff;
  font-size: clamp(1.7rem, 1.1rem + 2.2vw, 2.85rem);
  max-width: 18ch;
  text-wrap: balance;
}
.reviews-lede {
  color: rgba(255,255,255,.86);
  margin: 1.15rem 0 0;
  max-width: 46ch;
}
.reviews-figure {
  margin: 0; border-radius: 12px; overflow: hidden;
  /* SQUARE on purpose. The source is 4:3, so a 4:3 tile crops nothing and the
     frame read as a man standing in a lot of empty wall; the square takes a
     quarter off the width and lands on him and the sign he is standing under.
     Done with the tile's aspect and object-position rather than a transform on
     the image: a scaled <img> here stopped painting altogether in Chromium,
     measured, and a photograph that vanishes is a worse crop than a loose one. */
  aspect-ratio: 1 / 1;
  background: rgba(255,255,255,.06);
  box-shadow: 0 18px 44px rgba(0,0,0,.42);
}
.reviews-figure img { width: 100%; height: 100%; object-fit: cover; object-position: 58% 44%; }

@media (max-width: 860px) {
  .reviews-head { grid-template-columns: 1fr; }
  .reviews-figure { aspect-ratio: 16 / 10; }
}

.review-stack {
  position: relative; z-index: 2;
  max-width: 780px; margin-inline: auto;
  display: flex; flex-direction: column; align-items: stretch;
  gap: clamp(1.1rem, 2.4vw, 1.8rem);
}
.quote-card {
  position: relative; z-index: 2;
  background: #fff;
  border-radius: 12px;
  padding: clamp(1.5rem, 3.2vw, 2.4rem);
  box-shadow: 0 16px 40px rgba(0,0,0,.34);
  text-align: center;
  margin: 0;
}
/* The body sans, not the display serif: members actually READ these, and a
   60-word story is long-form reading rather than a headline. */
.quote-card blockquote {
  margin: 0;
  font-family: var(--sans);
  font-size: clamp(1rem, 0.95rem + 0.4vw, 1.1563rem);
  line-height: 1.62;
  color: var(--ink);
  max-width: 58ch; margin-inline: auto;
}
.quote-card cite {
  display: block; margin-top: 0;
  font-family: var(--sans); font-style: normal;
  font-size: 0.8125rem; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--grey);
}
/* When the review was written, under the name: the real `publishedAt` out of
   place.json at full day precision, numeric dd/mm/yyyy, the order this studio's
   Canadian readers use. Deliberately the smallest defensible step and dropped
   out of the name's caps register so the name still leads the attribution;
   tabular figures so three dates line up on their slashes. */
.quote-date {
  display: block; margin-top: 0.35rem;
  text-transform: none; letter-spacing: 0.02em; font-weight: 500;
  font-variant-numeric: tabular-nums;
  font-size: 0.625rem; color: var(--ink-soft);
}
.star-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }
/* --gold measures 3.98:1 on the white card and on the white rating chip, past
   the 3:1 WCAG bar for a meaningful graphic; the brighter --gold-light would
   not have held on white. */
.stars { display: block; height: 22px; width: auto; fill: var(--gold); }
.stars-lg { height: 27px; }
.card-stars {
  display: flex; justify-content: center;
  margin-top: clamp(1.1rem, 2.2vw, 1.5rem);
  margin-bottom: clamp(0.7rem, 1.3vw, 0.95rem);
}
.card-stars .stars { height: 17px; }

/* Source attribution: stars plus the Google mark on a white chip, the standard
   review-widget register. No count, no badge, no claim beyond the source. */
.rating-strip {
  display: inline-flex; align-items: center; gap: 0.85rem;
  margin-top: 1.15rem;
  padding: 0.6rem 1.15rem;
  background: #fff;
  border-radius: 999px;
  box-shadow: 0 8px 24px rgba(0,0,0,.34);
}
.rating-sep { width: 1px; height: 20px; background: var(--grey-line); }
.g-mark { display: block; width: 20px; height: 20px; }

.reviews-foot { text-align: center; margin-top: clamp(1.7rem, 3.4vw, 2.6rem); position: relative; z-index: 2; }

/* ---------- 9. booking (paper) --------------------------------------------
   The blueprint's closing push, carrying the studio's own contact-page copy.
   ------------------------------------------------------------------------- */

.book {
  background-color: var(--paper);
  background-image:
    repeating-linear-gradient(135deg, rgba(6,87,106,.02) 0 1px, rgba(6,87,106,0) 1px 7px),
    linear-gradient(118deg, rgba(255,255,255,.96) 0%, rgba(241,248,251,.92) 100%);
}
.book .wrap {
  display: grid; gap: clamp(1.75rem, 4vw, 3.5rem);
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
  align-items: start;
}
/* The real outside of the studio, squared off on purpose - the one deliberately
   hard-edged image on a page of soft cards, so it reads as a document of the
   place rather than another decorative tile. The source is a 640px square
   Street View still, so 640 is the crispness ceiling on the long edge; past it
   `cover` starts enlarging. */
.book-photo {
  position: relative;
  margin: 0 0 clamp(1.3rem, 2.6vw, 1.9rem);
  max-width: 640px;
}
.book-photo img {
  display: block; width: 100%;
  height: clamp(150px, 12vw, 195px);
  /* Right of centre and low: the studio's own grey unit and its door, with the
     road foreground and the neighbouring frontage cropped back. */
  object-fit: cover; object-position: 70% 52%;
  border-radius: 0;
  box-shadow: 0 12px 28px rgba(6,87,106,.20);
}
/* Placed after the base rule on purpose - same specificity, so source order
   decides. In the two-column layout the aside becomes a flex column and the
   figure is the one growing item, so the two columns bottom-align at every
   width instead of at the one width a fixed height was tuned for
   (TASTE_LEDGER #62). */
@media (min-width: 901px) {
  .book .wrap { align-items: stretch; }
  .book-aside { display: flex; flex-direction: column; }
  .book-photo { flex: 1 1 0; min-height: clamp(150px, 12vw, 195px); max-height: 640px; }
  .book-photo img { position: absolute; inset: 0; height: 100%; }
}
/* THE CHIP IS LOAD-BEARING. Street View imagery must carry its © Google notice
   wherever it is displayed; removing this chip without restoring the notice
   somewhere else breaks the licence terms. */
.photo-credit {
  position: absolute; right: 0; bottom: 0;
  font-family: var(--sans); font-size: 0.625rem; letter-spacing: 0.02em;
  line-height: 1;
  color: #fff;
  background: rgba(8,14,16,.62);
  padding: 0.3rem 0.45rem;
}
.book h2 { margin-bottom: 1rem; }
.book h2.book-h2 {
  font-weight: 600;
  font-size: clamp(1.7rem, 0.2rem + 2.9vw, 2.4rem);
  letter-spacing: -0.03em;
}
/* The one accent word in this band, and the only 700 on the page's serif here.
   Gold rather than the band's cyan: the phone and email below are already deep
   cyan, so a third cyan element would not read as an accent at all. */
.book-h2 em { font-style: normal; font-weight: 700; color: var(--gold-ink); }
@media (max-width: 900px) {
  .book h2.book-h2 { font-size: clamp(1.6rem, 0.15rem + 6.6vw, 2.4rem); }
}
.book-aside p { color: var(--grey); }
.book-contacts {
  display: flex; flex-direction: column; align-items: flex-start;
  gap: 0.6rem; margin-top: 1.35rem;
}
/* The phone and the email are ONE designed unit: same face, size, weight and
   colour for both values, the same small label register on both, one shared gap.
   Body sans rather than the display serif - a phone number set in the headline
   voice reads as a pull quote, not as something to act on. */
.book-call {
  display: inline-flex; align-items: baseline; gap: 0.6rem; flex-wrap: wrap;
  font-family: var(--sans); font-size: 1.0625rem; font-weight: 600;
  letter-spacing: -0.005em;
  font-variant-numeric: tabular-nums;
  line-height: 1.35;
  color: var(--brand-deep); text-decoration: none;
}
.book-call .ico { align-self: center; }
.book-email { overflow-wrap: anywhere; max-width: 100%; }
.book-call:hover { text-decoration: underline; }
.book-call .small {
  font-family: var(--sans); font-size: 0.75rem; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--brand-deep);
}

.form-card {
  background: var(--tint-soft);
  border: 1px solid var(--grey-line);
  border-radius: var(--radius);
  padding: clamp(1.35rem, 3vw, 2.25rem);
}
/* The card is labelled in the eyebrow register the rest of the page uses to
   name a band, at a real title size, and then goes straight into the fields.
   The tracking comes DOWN as the size goes up: 0.18em is tuned for 12px type,
   and carried to 19px it would read s p a c e d  o u t. */
.form-eyebrow {
  color: var(--brand-deep);
  font-size: 1.1875rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  margin-bottom: 1.35rem;
}
.field-grid { display: grid; gap: 1rem; grid-template-columns: repeat(2, minmax(0, 1fr)); }
.field { display: flex; flex-direction: column; gap: 0.4rem; }
.field.full { grid-column: 1 / -1; }
.field label { font-size: 0.8125rem; font-weight: 600; letter-spacing: 0.04em; color: var(--ink); }
.field input, .field select, .field textarea {
  font: inherit; font-size: 0.9375rem;
  color: var(--ink);
  background: #fff;
  border: 1px solid var(--grey-line);
  border-radius: 9px;
  padding: 0.75rem 0.9rem;
  width: 100%;
}
.field textarea { min-height: 118px; resize: vertical; }
.field input:focus, .field select:focus, .field textarea:focus {
  outline: 2px solid var(--brand-deep); outline-offset: -1px; border-color: var(--brand-deep);
}
/* Primary alone on the left, the two secondary options grouped hard right with
   the classic divider between them, so the booking action is the one the eye
   lands on. All three pills share one line-box height because all three carry
   the same 17px icon. */
.form-actions {
  margin-top: 1.35rem;
  display: flex; flex-wrap: wrap; align-items: center;
  justify-content: space-between;
  gap: 0.75rem 0.5rem;
}
.form-or {
  font-family: var(--sans); font-size: 0.8125rem; font-weight: 500;
  color: var(--grey); line-height: 1;
  flex: 0 0 auto;
}
.form-opts { display: flex; flex-wrap: wrap; align-items: stretch; gap: 0.6rem; }
.form-alt { padding-inline: 0.9rem; }
.form-actions .pill { min-height: 49px; }
.form-alt .ico { stroke: var(--brand-deep); transition: stroke .18s ease; }
.form-alt:hover .ico { stroke: #fff; }

@media (max-width: 620px) {
  .form-actions { flex-direction: column; align-items: stretch; gap: 0.7rem; }
  .form-actions > .pill { width: 100%; }
  .form-or { text-align: center; }
  .form-opts { justify-content: center; gap: 0.6rem; }
  .form-opts .pill { flex: 1 1 auto; padding-inline: 0.9rem; }
  .book-call { flex-direction: column; align-items: flex-start; gap: 0.15rem; }
}

/* Success state, sized and padded like the form it replaces so the column does
   not jump when they swap. */
.form-done { text-align: center; }
.form-done-mark {
  display: inline-flex; align-items: center; justify-content: center;
  width: 52px; height: 52px; border-radius: 50%;
  background: var(--brand-deep); margin-bottom: 1.1rem;
}
.form-done-mark svg { fill: none; stroke: #fff; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
.form-done h3 {
  font-family: var(--serif); font-weight: 600;
  font-size: clamp(1.35rem, 1.1rem + 1vw, 1.75rem);
  color: var(--ink); margin: 0 0 0.7rem;
}
.form-done p { color: var(--ink-soft); font-size: 0.9375rem; line-height: 1.6; margin: 0 auto; max-width: 46ch; }
.form-done-alt {
  margin-top: 1.1rem !important; padding-top: 1.1rem;
  border-top: 1px solid var(--grey-line);
  font-weight: 600;
}
.form-done-alt a { color: var(--brand-deep); overflow-wrap: anywhere; }

@media (max-width: 900px) { .book .wrap { grid-template-columns: 1fr; } }
@media (max-width: 560px) { .field-grid { grid-template-columns: 1fr; } }

/* ---------- 10. footer ----------------------------------------------------- */

.footer { background: var(--brand-darker); color: rgba(255,255,255,.88); padding-block: clamp(2.6rem, 5vw, 4rem) 0; }
.footer-grid {
  display: grid; gap: clamp(1.75rem, 4vw, 3rem);
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.95fr) minmax(0, 0.8fr) minmax(0, 1.1fr);
  align-items: start;
}
.footer h3 {
  color: #fff; font-family: var(--sans);
  font-size: 0.75rem; font-weight: 700; letter-spacing: 0.18em; text-transform: uppercase;
  margin-bottom: 1rem;
}
.footer a { color: #fff; text-decoration: none; }
.footer a:hover { text-decoration: underline; }
.footer ul { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 0.55rem; font-size: 0.9375rem; }
/* Their mark is cyan line art with a cyan wordmark, drawn for white. On the
   footer's deep cyan it would half-disappear, so it sits on its own white
   plate rather than being recoloured - the real logo, never a reconstruction. */
.footer-logo-plate {
  display: inline-block; background: #fff; border-radius: 10px;
  padding: 0.8rem 1rem; margin-bottom: 1.25rem;
}
.footer-logo-plate img { width: 178px; max-width: 100%; height: auto; object-fit: contain; }
.footer address { font-style: normal; font-size: 0.9375rem; line-height: 1.7; }
/* The two accounts their contact page actually links to. Circles in the same
   pill geometry as everything else, brand glyphs filled rather than stroked. */
/* `.footer .social-row`, not `.social-row`: `.footer ul` is (0,2,0) and sets
   `flex-direction: column`, so a bare single-class rule loses to it and the two
   marks stacked vertically. Measured, not assumed. */
.footer .social-row {
  display: flex; flex-direction: row; gap: 0.55rem;
  list-style: none; padding: 0;
  margin: 1.15rem 0 0;
}
.social-row a {
  display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; border-radius: 50%;
  border: 1px solid rgba(255,255,255,.38);
  color: #fff;
  transition: background-color .18s ease, color .18s ease, border-color .18s ease;
}
.social-row a:hover { background: #fff; color: var(--brand-darker); border-color: #fff; }
.footer-addr { margin: 0 0 0.75rem; }
.contact-line {
  display: flex; align-items: center; gap: 0.6rem;
  margin: 0 0 0.45rem;
  color: #fff; text-decoration: none;
}
.contact-line:last-child { margin-bottom: 0; }
.contact-line .ico { stroke: var(--brand-pale); }
.footer a.contact-line:hover span { text-decoration: underline; text-underline-offset: 3px; }
/* One grid for the whole week with the rows as display:contents, so day and
   time are two REAL columns and every time starts at the same x. */
.hours-grid {
  display: grid;
  grid-template-columns: max-content max-content;
  column-gap: 1rem; row-gap: 0.5rem;
  font-size: 0.9375rem;
}
.hours-row { display: contents; }
.hours-day { position: relative; padding-left: 0.95rem; }
.hours-time { text-align: left; white-space: nowrap; color: rgba(255,255,255,.78); }
/* Today's marker: a triangle pointing right at the day name. Its colour is set
   by main.js from the visitor's real local time against this row's own
   data-open/data-close, so it states whether the studio is open RIGHT NOW
   rather than merely which day it is. The gutter is reserved on EVERY row and
   the triangle is transparent until it is today's, so marking one costs zero
   layout shift and a no-JS render is simply uniformly indented. */
.hours-day::before {
  content: ""; position: absolute; left: 0; top: calc(0.5em + 2px);
  /* content-box explicitly: the global border-box rule makes `width: 0` resolve
     against the borders that FORM the triangle, so the shape stops collapsing. */
  box-sizing: content-box;
  width: 0; height: 0;
  border-top: 4.5px solid transparent;
  border-bottom: 4.5px solid transparent;
  border-left: 7.5px solid transparent;
}
.hours-row[data-today="true"] { font-weight: 700; color: #fff; }
.hours-row[data-today="true"] .hours-time { color: #fff; }
.hours-row[data-today="true"][data-state="open"] .hours-day::before { border-left-color: #9BF0A8; }
.hours-row[data-today="true"][data-state="closed"] .hours-day::before { border-left-color: #FFCFC0; }

.footer-map {
  width: 100%; height: 200px; border: 0; border-radius: 10px; display: block;
  background: rgba(255,255,255,.10);
}
/* Get directions is a white button in the shared pill geometry, carrying the
   Google Maps pin in Google's own red as the one spot of colour down here.
   Stated at (0,2,0) because `.footer a { color:#fff }` is (0,1,1) and outranks
   `.pill-white`'s (0,1,0), which rendered the label white on white. */
.footer .btn-directions {
  color: var(--ink);
  padding: 0.8rem 1.25rem;
  display: flex; width: max-content;
  margin: 0.9rem auto 0;
}
.footer .btn-directions:hover { color: var(--ink); background: var(--tint); }
.ico-pin { flex: 0 0 auto; stroke: none; }

.footer-bottom {
  margin-top: clamp(2rem, 4.5vw, 3rem);
  border-top: 1px solid rgba(255,255,255,.24);
  padding-block: 1.4rem;
  display: flex; flex-wrap: wrap; gap: 0.5rem 1.5rem; align-items: center;
  font-size: 0.8125rem; color: rgba(255,255,255,.80);
}
.footer-bottom .spacer { margin-left: auto; }
/* Google place-photo attribution, at the same size as the rest of the colophon
   so it is a real credit rather than fine print hidden below the legible floor. */
.footer-credit a { color: #fff; text-decoration: underline; text-underline-offset: 3px; }

@media (max-width: 980px) { .footer-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) { .footer-grid { grid-template-columns: 1fr; } }

/* ---------- preview badge -------------------------------------------------- */

.preview-badge {
  position: fixed; left: 50%; transform: translateX(-50%); bottom: 14px; z-index: 120;
  display: flex; align-items: stretch; gap: 1px;
  background: rgba(18,24,27,.94);
  border-radius: 999px; overflow: hidden;
  box-shadow: 0 10px 30px rgba(0,0,0,.28);
  font-family: var(--sans); font-size: 0.75rem;
  max-width: calc(100vw - 24px);
}
.preview-badge a { text-decoration: none; padding: 0.6rem 1rem; white-space: nowrap; }
.preview-badge-info { color: rgba(255,255,255,.85); }
.preview-badge-cta { background: var(--brand-pale); color: #0a1417; font-weight: 700; }
.preview-badge-cta:hover { background: #fff; }

@media (max-width: 540px) {
  .preview-badge { font-size: 0.6875rem; }
  .preview-badge a { padding: 0.5rem 0.7rem; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; scroll-behavior: auto !important; }
}
