/*
 * onlyoss landing page
 * ---------------------------------------------------------------------------
 * LOCAL FILE, loaded only by resources/views/pages/home.blade.php via a
 * <link> in its own @section('styles'). Not part of the JustFans vendor
 * package, so vendor updates never overwrite it.
 *
 * SELF-CONTAINED BY DESIGN. Every colour, font and spacing value this page
 * needs is declared below under .oss-landing. It deliberately does NOT read
 * --oss-* tokens from onlyoss-brand.css, because that file loads through the
 * `site.custom_code_css` database setting - and when that setting is empty
 * (settings restore, fresh DB import) every var() silently resolves to
 * nothing and the page renders unstyled. That happened once. Not again.
 *
 * Palette sampled from the client's own logo artwork
 * ("New folder/onlyoss logo plane.jpg"): navy #011F5D, gold #FFD800.
 * Regression-tested in tests/brand/contrast_test.php.
 * Gold NEVER carries text on a light surface (1.39:1).
 *
 * SHAPE RULE (locked, applied everywhere): interactive controls are full
 * pill (999px); surfaces and panels are 16px; nothing else has a radius.
 *
 * DIALS: variance 8 (asymmetric, left-weighted, no centred hero) /
 * motion 5 (entry cascade + scroll-driven reveal, no JS) / density 3 (airy).
 */

/* CASCADE FIX: onlyoss-brand.css also declares background/color/font-family on
   .oss-landing (it predates this page and stays as a fallback for the case
   where THIS file fails to load). Both files load at the SAME selector
   specificity, and brand.css is injected later via site.custom_code_css, so
   without help it always wins - the page was silently rendering on brand.css's
   flat #011F5D instead of this file's 4-depth ink scale. The three rules below
   use a doubled class (.oss-landing.oss-landing, specificity 0-2-0) to beat
   brand.css's single-class rules (0-1-0) regardless of load order, without
   touching brand.css or depending on source order. */
.oss-landing.oss-landing {
  background: var(--oz-ink);
  color: var(--oz-text);
}

.oss-landing.oss-landing h1,
.oss-landing.oss-landing h2,
.oss-landing.oss-landing h3 {
  font-family: var(--oz-display);
}

/* LOCAL (patch 284, option B): the real athlete card sits inside this page and
   colours its own paragraphs (the name white, the nickname gold), and so do the
   drawn phone, the drawn story card and the gold eyebrows. Leave those be: this
   rule's doubled class would otherwise outrank every one of them. */
.oss-landing.oss-landing p:not(.oz-ap p, .oz-phone-b p, .oz-story p, .oz-pane-k, .oz-eyebrow, .oz-editor-h) { color: var(--oz-text); }

.oss-landing {
  /* Ink scale - one hue, four depths, so the page layers instead of
     sitting on one flat navy. */
  --oz-ink:      #01102F;   /* page base, deepest */
  --oz-navy:     #011F5D;   /* brand navy, elevated surfaces */
  --oz-navy-up:  #052A78;   /* raised surface / hairline emphasis */
  --oz-gold:     #FFD800;
  --oz-gold-dim: #E6C200;

  --oz-line:      rgba(255, 255, 255, 0.14);
  --oz-line-soft: rgba(255, 255, 255, 0.13);
  --oz-text:      rgba(255, 255, 255, 0.76);
  --oz-text-dim:  rgba(255, 255, 255, 0.62);

  --oz-display: 'Archivo', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --oz-body:    'Manrope', system-ui, -apple-system, 'Segoe UI', sans-serif;

  --oz-ease: cubic-bezier(0.16, 1, 0.3, 1);
  /* Max end brought down from 9rem: at wide viewports two adjacent sections'
     padding was stacking into 280px+ of undifferentiated navy - it read as a
     loading gap, not rhythm. */
  --oz-section: clamp(5rem, 8vw, 7rem);
  --oz-radius: 16px;

  /* LOCAL (see PATCHES.md patch 324): this page is navy, so the colour a link takes
     when hovered, focused or pressed is gold (app.css and the brand sheet apply it;
     their default is the navy meant for light pages, which is this page's background). */
  --oss-link-hover: #FFD800;

  background: var(--oz-ink);
  color: var(--oz-text);
  font-family: var(--oz-body);
  font-size: 1.0625rem;
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
}

/* ---------------------------------------------------------------------------
 * Type. Archivo shouts, Manrope talks.
 * ------------------------------------------------------------------------- */

.oss-landing h1,
.oss-landing h2,
.oss-landing h3 {
  font-family: var(--oz-display);
  color: #fff;
  text-wrap: balance;
  margin: 0;
}

.oss-landing h1 {
  font-size: clamp(2.75rem, 7.2vw, 6.25rem);
  font-weight: 900;
  line-height: 0.96;
  letter-spacing: -0.035em;
}

.oss-landing h2 {
  font-size: clamp(2rem, 4.2vw, 3.15rem);
  font-weight: 800;
  line-height: 1.05;
  letter-spacing: -0.03em;
}

.oss-landing h3 {
  font-size: 1.15rem;
  font-weight: 700;
  letter-spacing: -0.012em;
}

.oss-landing p { margin: 0; color: var(--oz-text); }

.oz-lead {
  font-size: clamp(1.0625rem, 1.5vw, 1.1875rem);
  line-height: 1.62;
  color: rgba(255, 255, 255, 0.8);
  max-width: 42ch;
}

/* Browser surfaces are part of the design. */
.oss-landing ::selection { background: var(--oz-gold); color: var(--oz-navy); }

/* No border-radius override here: modern browsers already shape the outline
   to match the element's own border-radius. Setting one explicitly squared
   off every pill button (.oz-btn/.oz-btn-ghost) on focus, violating the
   locked SHAPE RULE above the moment a keyboard user tabbed to a CTA. */
.oss-landing a:focus-visible,
.oss-landing button:focus-visible {
  outline: 3px solid var(--oz-gold);
  outline-offset: 3px;
}

.oz-section { padding: var(--oz-section) 0; }
.oz-rule { border-top: 1px solid var(--oz-line-soft); }

/* ---------------------------------------------------------------------------
 * Hero - asymmetric, left-weighted. Variance 8 forbids a centred hero, and
 * with no photography the composition itself has to carry the asymmetry:
 * the headline holds the left seven columns, the right stays deliberately
 * empty so the type has somewhere to breathe.
 * ------------------------------------------------------------------------- */

/* The vendor navbar is `sticky-nav`, so it sits over the top of this section
   rather than pushing it down. Top padding therefore has to clear the navbar
   (~90px) BEFORE it buys any breathing room, or the headline renders jammed
   against it on first paint. */
.oz-hero {
  position: relative;
  overflow: hidden;
  padding: clamp(8rem, 13vw, 11rem) 0 clamp(4rem, 8vw, 6.5rem);
}

/* One wide, low-opacity wash anchored to the left, where the type sits.
   Not a centred "gradient blob". */
.oz-hero::before {
  content: '';
  position: absolute;
  top: -30%;
  left: -10%;
  width: min(52rem, 90%);
  aspect-ratio: 1;
  background: radial-gradient(circle, rgba(255, 216, 0, 0.09) 0%, rgba(255, 216, 0, 0.025) 40%, transparent 70%);
  pointer-events: none;
}

.oz-hero > .container { position: relative; z-index: 1; }

.oz-hero-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(2.5rem, 5vw, 4rem);
  align-items: center;
}

@media (min-width: 992px) {
  .oz-hero-grid { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); }
}

.oz-hero h1 { max-width: 13ch; }
.oz-hero .oz-lead { margin-top: clamp(1.5rem, 2.5vw, 2rem); }

/* The photograph. A single elevation cue (radius, no border and no shadow),
   and a navy wash over the top so the image sits inside the palette instead
   of fighting it - the original has teal-green in the shadows. */
.oz-hero-figure {
  position: relative;
  margin: 0;
  border-radius: var(--oz-radius);
  overflow: hidden;
  isolation: isolate;
}

.oz-hero-figure img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1100 / 1648;
  object-fit: cover;
}

.oz-hero-figure::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(1, 31, 93, 0.30) 0%, rgba(1, 16, 47, 0.62) 100%);
  mix-blend-mode: multiply;
  pointer-events: none;
}

@media (max-width: 991.98px) {
  /* Below the split, the portrait becomes a band rather than a tall column,
     so it never pushes the CTAs off the first screen on a phone. At 4:3 the
     visible height is only ~50% of the 1100x1648 source - centered cover
     kept the torso and cut the fighter's head off entirely. The subject's
     head sits in roughly the top third of the frame, so bias the crop up. */
  .oz-hero-figure img { aspect-ratio: 4 / 3; object-position: 50% 18%; }
}

.oz-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.875rem;
  margin-top: clamp(2rem, 3.5vw, 2.75rem);
}

/* ---------------------------------------------------------------------------
 * Controls. Gold fill carries navy text (11.12:1). Press is a real scale.
 * ------------------------------------------------------------------------- */

.oz-btn,
.oz-btn-ghost {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 3rem;
  padding: 0.875rem 1.75rem;
  border-radius: 999px;
  font-family: var(--oz-body);
  font-size: 1rem;
  font-weight: 700;
  white-space: nowrap;
  text-decoration: none;
  transition: background-color 0.18s var(--oz-ease), color 0.18s var(--oz-ease),
              border-color 0.18s var(--oz-ease), transform 0.14s var(--oz-ease);
}

.oz-btn {
  background: var(--oz-gold);
  color: var(--oz-navy);
  border: 1px solid var(--oz-gold);
}

.oz-btn-ghost {
  background: transparent;
  color: #fff;
  /* 0.3 alpha measured 2.55:1 against the page ink - below the 3:1 WCAG
     1.4.11 non-text-contrast minimum, and this border is the only thing
     marking the element as a control. 0.4 clears it with margin. */
  border: 1px solid rgba(255, 255, 255, 0.4);
}

@media (hover: hover) and (pointer: fine) {
  .oz-btn:hover { background: var(--oz-gold-dim); border-color: var(--oz-gold-dim); color: var(--oz-navy); }
  .oz-btn-ghost:hover { border-color: #fff; }
}

/* LOCAL (see PATCHES.md patch 324): a pill states its own colour in every state. Each
   had ONE class of colour (0-1-0) and the site-wide `a:hover, a:focus` (0-1-1) outranked
   it: the ghost pill went navy on navy under the pointer and on a tap ("Create your
   profile" on the home page emptied), and would go gold on gold on the gold pill now
   that the page's link colour is gold. No underline: the border and the fill say
   "button". */
.oz-btn:hover, .oz-btn:focus, .oz-btn:active { color: var(--oz-navy); text-decoration: none; }
.oz-btn-ghost:hover, .oz-btn-ghost:focus, .oz-btn-ghost:active { color: #fff; text-decoration: none; }

.oz-btn:active,
.oz-btn-ghost:active { transform: scale(0.97); }

/* ---------------------------------------------------------------------------
 * Facts - a hairline rule strip. Layout family: inline rule row.
 * ------------------------------------------------------------------------- */

.oz-facts {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  border-top: 1px solid var(--oz-line);
  border-bottom: 1px solid var(--oz-line);
}

.oz-fact {
  padding: clamp(1.5rem, 3vw, 2.25rem) clamp(1rem, 2.2vw, 2rem);
  border-left: 1px solid var(--oz-line-soft);
}

.oz-fact:first-child { border-left: 0; padding-left: 0; }

.oz-fact dt {
  margin: 0 0 0.3rem;
  font-family: var(--oz-display);
  font-size: 1.05rem;
  font-weight: 800;
  letter-spacing: -0.015em;
  color: #fff;
}

.oz-fact dd { margin: 0; font-size: 0.9375rem; line-height: 1.55; color: var(--oz-text-dim); }

/* Matches .oz-grid's breakpoint rather than its own 700px: between 701-991px
   three Archivo-800 dt's ("Your audience is yours") had ~160px each inside a
   Bootstrap container and wrapped 2-3 lines. Going straight to 1-column at
   the same point .oz-grid does skips that too-narrow 3-column zone. */
@media (max-width: 991.98px) {
  .oz-facts { grid-template-columns: minmax(0, 1fr); }
  .oz-fact { border-left: 0; border-top: 1px solid var(--oz-line-soft); padding-left: 0; }
  .oz-fact:first-child { border-top: 0; }
}

/* ---------------------------------------------------------------------------
 * Section headings. Left-weighted to match the hero.
 * ------------------------------------------------------------------------- */

/* max-width in rem, NOT ch: `ch` resolves against this wrapper's own font
   (the 17px body face), not the heading inside it, which silently squeezed
   section headings into a ~320px column beside a half-empty canvas. */
.oz-head { max-width: 36rem; margin-bottom: clamp(2.5rem, 5vw, 3.5rem); }
.oz-head p { margin-top: 1rem; max-width: 52ch; color: var(--oz-text-dim); }

/* ---------------------------------------------------------------------------
 * Catalogue - hairline-topped columns. Layout family: column grid.
 * ------------------------------------------------------------------------- */

.oz-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(1.75rem, 3vw, 2.5rem);
}

@media (max-width: 991.98px) { .oz-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 575.98px) { .oz-grid { grid-template-columns: minmax(0, 1fr); } }

.oz-item { padding-top: 1.25rem; border-top: 2px solid var(--oz-gold); }
.oz-item h3 { margin-bottom: 0.5rem; }
/* text-wrap: pretty avoids the last-line orphan ("…your students return
   to." dropping "to." alone) that balance doesn't protect against in body
   copy. Unsupported browsers just keep normal wrapping - no fallback needed. */
.oz-item p { font-size: 0.9688rem; line-height: 1.62; color: var(--oz-text-dim); text-wrap: pretty; }

/* ---------------------------------------------------------------------------
 * Steps - a numbered gutter list, deliberately NOT another equal-column grid.
 * Layout family: gutter list. The numerals are the sequence, so they earn
 * their place; the rule between rows carries the eye down.
 * ------------------------------------------------------------------------- */

/* No max-width: the 56rem cap left the hairlines stopping mid-container at
   wide viewports (896px inside a 1280px container), reading as an unfinished
   rule rather than a deliberate edge. Full container width instead.
   list-style/margin/padding reset: this is a real <ol> now (screen readers
   get native "1. Set up your page" numbering), so strip the browser's own
   marker/indent - the visual numeral is drawn by .oz-step-n instead. */
.oz-steps { display: grid; gap: 0; list-style: none; margin: 0; padding: 0; }

.oz-step {
  display: grid;
  grid-template-columns: 4.5rem minmax(0, 1fr);
  gap: clamp(1rem, 2.5vw, 2rem);
  align-items: baseline;
  padding: clamp(1.5rem, 3vw, 2.25rem) 0;
  border-top: 1px solid var(--oz-line);
}

.oz-step:last-child { border-bottom: 1px solid var(--oz-line); }

.oz-step-n {
  font-family: var(--oz-display);
  font-size: clamp(2rem, 4vw, 2.75rem);
  font-weight: 900;
  line-height: 1;
  letter-spacing: -0.04em;
  font-variant-numeric: tabular-nums;
  color: var(--oz-gold);
}

.oz-step h3 { margin-bottom: 0.35rem; }
.oz-step p { font-size: 0.9688rem; color: var(--oz-text-dim); max-width: 54ch; }

@media (max-width: 575.98px) {
  .oz-step { grid-template-columns: 3rem minmax(0, 1fr); gap: 1rem; }
}

/* ---------------------------------------------------------------------------
 * Economics - split. Layout family: two-column split.
 * "80%" is emphasis inside the sentence, never a detached metric widget.
 * ------------------------------------------------------------------------- */

.oz-split {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(2.5rem, 5vw, 4rem);
  align-items: start;
}

@media (min-width: 992px) { .oz-split { grid-template-columns: minmax(0, 6fr) minmax(0, 5fr); } }

.oz-figure { font-variant-numeric: tabular-nums; color: var(--oz-gold); }

.oz-notes { margin-top: 1.5rem; display: grid; gap: 0.875rem; max-width: 52ch; }

/* p.oz-fine (element+class): `.oss-landing p { margin: 0 }` above is the same
   0-1-1 specificity as a bare `.oz-fine` would be, and it comes first in the
   file, so a same-specificity `.oz-fine` alone loses on the tie and margin-top
   was silently zeroed - "…never come out of your share." ran straight into
   "Invite coaches…" with no separation. The element qualifier breaks the tie. */
p.oz-fine { margin-top: 1.75rem; font-size: 0.9063rem; line-height: 1.6; color: var(--oz-text-dim); max-width: 52ch; }
.oz-fine a {
  color: var(--oz-gold);
  text-decoration: underline;
  text-underline-offset: 3px;
  /* Standalone link (no surrounding sentence) needs a real touch target;
     also stops "Referral terms" from breaking mid-link. */
  white-space: nowrap;
}
.oz-fine a:hover { color: var(--oz-gold-dim); }

/* The content-guidelines link in the Standards section has no sentence
   around it - it's the whole paragraph. Pad it to the WCAG 2.5.8 24px
   minimum target size instead of sitting at raw line-height (~20px). */
.oz-statement .oz-fine a { display: inline-block; padding: 0.25rem 0; }
/* .oz-actions is a flex row and left-aligns by default, which reads as a
   mistake inside a centred statement. Centring it here rather than in
   .oz-actions itself keeps the hero's left-aligned buttons untouched. */
.oz-statement .oz-actions { justify-content: center; }

/* The page's one panel. Elevation declared once: border, no shadow.
   Border uses --oz-line (white-based), not --oz-navy-up: navy-on-navy here
   measured 1.19:1 - effectively invisible. --oz-line reads as a real edge
   regardless of which navy depth sits behind the panel. */
.oz-panel {
  padding: clamp(1.75rem, 3.5vw, 2.5rem);
  background: var(--oz-navy);
  border: 1px solid var(--oz-line);
  border-radius: var(--oz-radius);
}

.oz-panel h3 { margin-bottom: 0.75rem; }
.oz-panel p { font-size: 0.9688rem; }
.oz-panel p + p { margin-top: 0.875rem; }

/* ---------------------------------------------------------------------------
 * Standards - a single narrow statement. Layout family: centred statement.
 * ------------------------------------------------------------------------- */

.oz-statement { max-width: 44rem; margin: 0 auto; text-align: center; }
.oz-statement p { margin-top: 1.25rem; color: var(--oz-text-dim); }
/* Every capped paragraph needs auto side margins here, not just .oz-fine (see
   PATCHES.md patch 155). .oz-lead carries max-width: 42ch, so inside the 44rem
   statement it is a narrower box pinned to the LEFT edge: its lines centre
   within that box, 109px left of the heading at 1280px. Invisible on a phone,
   where the column is narrower than the cap. */
.oz-statement .oz-lead,
.oz-statement .oz-fine { margin-left: auto; margin-right: auto; }

/* ---------------------------------------------------------------------------
 * Closing - elevated full-bleed band. Layout family: elevated band.
 * ------------------------------------------------------------------------- */

/* Full-bleed photograph behind the closing band. The navy scrim is heavy on
   purpose: white body text over the lit part of the image would otherwise
   drop under 4.5:1. Measured at the image's brightest region the text still
   clears AA - see tests/brand/contrast_test.php. `image-set` is not used
   because the scrim, not the source, does the heavy lifting here. */
.oz-close {
  position: relative;
  isolation: isolate;
  padding: clamp(5.5rem, 11vw, 9rem) 0;
  border-top: 1px solid var(--oz-navy-up);
  background-color: var(--oz-navy);
  background-image:
    linear-gradient(90deg, rgba(1, 16, 47, 0.94) 0%, rgba(1, 16, 47, 0.86) 45%, rgba(1, 31, 93, 0.72) 100%),
    image-set(url('/img/landing/close-kick.webp') type('image/webp'),
              url('/img/landing/close-kick.jpg') type('image/jpeg'));
  background-size: cover;
  background-position: center right;
  background-repeat: no-repeat;
}

@media (max-width: 767.98px) {
  /* At desktop the band is wider than the 1800x1200 source, so cover fills
     width and the right-pin is inert. Once the band goes portrait-ish on a
     phone, cover fills HEIGHT instead and right-pin shows only the empty
     wall at frame-right - the centre-left subject disappears entirely. */
  .oz-close { background-position: 20% center; }
}

.oz-close-inner { position: relative; z-index: 1; max-width: 42rem; }
.oz-close .oz-lead { margin-top: 1.25rem; }

/* ---------------------------------------------------------------------------
 * Controls on a phone.
 *
 * The pill buttons had no small-screen rule at all, so they carried desktop
 * padding (1.75rem each side) and a 3rem min-height onto a 360px viewport. A
 * hero pair measured roughly 157px + 136px + a 14px gap against ~330px of
 * usable width inside .container — just over, so the two buttons wrapped onto
 * separate lines and, being content-width and left-aligned, read as ragged
 * rather than as a deliberate stack.
 *
 * Tightening padding and type below 576px brings a pair back onto one row on
 * an ordinary phone. flex-wrap stays `wrap` on .oz-actions deliberately: it is
 * the safety valve for a 320px screen or a long translated label, where a
 * clean stack beats a squeezed row or a horizontal scrollbar.
 * ------------------------------------------------------------------------- */

@media (max-width: 575.98px) {
  /* Share the row instead of trying to fit two content-width pills into it.
     `flex: 1 1 0` gives both buttons an equal share whatever their labels say,
     so the pair stays side by side and, being equal, actually looks aligned —
     rather than depending on an estimate of how wide "Create your profile"
     renders in 700-weight Manrope, which is the sort of guess that produced
     the ragged wrap in the first place.

     `white-space: normal` overrides the desktop nowrap: once a pill is only
     half the row, a long or translated label must be allowed to run to a
     second line inside it rather than overflow. min-width: 0 is what actually
     lets a flex item shrink below its content width. */
  .oz-actions { gap: 0.625rem; flex-wrap: nowrap; }

  .oz-btn,
  .oz-btn-ghost {
    flex: 1 1 0;
    min-width: 0;
    white-space: normal;
    text-align: center;
    padding: 0.75rem 0.9rem;
    font-size: 0.9375rem;
    min-height: 2.75rem;
  }

  /* A lone button — the instructor section's "Apply for a founding place" —
     must not stretch edge to edge just because it is the only flex item.
     Content width, centred. */
  .oz-statement .oz-actions { justify-content: center; }
  .oz-statement .oz-btn,
  .oz-statement .oz-btn-ghost { flex: 0 1 auto; }
}

/* ---------------------------------------------------------------------------
 * Motion (intensity 5). Two devices, both CSS-only, no scroll listeners:
 *   1. a one-time entry cascade on the hero
 *   2. scroll-driven reveals via animation-timeline: view()
 * Content is visible by default; motion is layered on top, so a browser
 * without support or a reduced-motion preference loses nothing.
 * ------------------------------------------------------------------------- */

@media (prefers-reduced-motion: no-preference) {
  /* Waterfall entry. Three rules drive the numbers below:
     1. Opacity is BINARY, never a fade - an arrival is movement, not a
        dissolve. The keyframe jumps 0 to 1 in the first 1% (~2ms), which
        reads as instant while still allowing fill-mode: both to hold the
        pre-start state.
     2. Velocity varies by weight - the headline is the anchor and travels
        furthest/longest; the buttons are light and snap in tight.
     3. Gaps SHRINK across the cascade, so the wave accelerates and the last
        element snaps rather than trailing off. Each element starts before
        the previous has settled. One direction throughout (from below). */
  .oz-rise {
    opacity: 0;
    animation: oz-whip var(--oz-dur, 0.22s) var(--oz-ease) var(--oz-at, 0s) both;
  }

  .oz-rise-1 { --oz-travel: 64px; --oz-dur: 0.28s; --oz-at: 0.06s; }  /* headline, anchor */
  .oz-rise-2 { --oz-travel: 40px; --oz-dur: 0.22s; --oz-at: 0.26s; }  /* lead, normal */
  .oz-rise-3 { --oz-travel: 32px; --oz-dur: 0.20s; --oz-at: 0.40s; }  /* actions, light */

  @supports (animation-timeline: view()) {
    .oz-reveal {
      opacity: 0;
      animation: oz-reveal-in linear both;
      animation-timeline: view();
      animation-range: entry 5% cover 26%;
    }
  }
}

@keyframes oz-whip {
  from { opacity: 0; transform: translateY(var(--oz-travel, 40px)); }
  1%   { opacity: 1; }
  to   { opacity: 1; transform: translateY(0); }
}

/* Scroll-driven reveals keep a soft fade on purpose: they are not arrivals,
   they are content coming into view, and a hard cut mid-scroll reads as a
   glitch rather than a beat. */
@keyframes oz-reveal-in { from { opacity: 0; transform: translateY(18px); } to { opacity: 1; transform: translateY(0); } }

/* ---------------------------------------------------------------------------
   Q&A — layout family: stacked definition list.

   Deliberately not an accordion. Every answer here handles an objection, and an
   objection the reader has to click to see is an objection that goes unanswered;
   the whole point is that a sceptical coach can scan all six without deciding
   which doubt to admit to. Hairline rules, no cards, so it reads as continuous
   prose rather than another grid of boxes.
   ------------------------------------------------------------------------- */

.oz-qa { margin: 0; padding: 0; }

.oz-qa-item {
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
  gap: clamp(1rem, 3vw, 3rem);
  padding: clamp(1.5rem, 3vw, 2.25rem) 0;
  border-top: 1px solid var(--oz-line);
}

.oz-qa-item:last-child { border-bottom: 1px solid var(--oz-line); }

.oz-qa dt {
  font-family: var(--oz-display);
  font-weight: 700;
  font-size: clamp(1.05rem, 1.7vw, 1.3rem);
  line-height: 1.25;
  letter-spacing: -0.015em;
  color: #fff;
  text-wrap: balance;
}

.oz-qa dd {
  margin: 0;
  color: var(--oz-text);
  font-size: clamp(0.98rem, 1.2vw, 1.05rem);
  line-height: 1.65;
  max-width: 58ch;
}

/* Single column below the split: two columns at phone width would leave the
   question orphaned on its own line above a very narrow answer.
   767.98 rather than 767 to match every other breakpoint in this file — at a
   fractional viewport width of, say, 767.5px a plain `767` rule would not
   apply while the rest of the page had already collapsed, leaving this one
   section stubbornly two-column. */
@media (max-width: 767.98px) {
  .oz-qa-item {
    grid-template-columns: minmax(0, 1fr);
    gap: 0.6rem;
  }
}

/* ---------------------------------------------------------------------------
   Worked example inside the economics split — the 80% figure made concrete.
   ------------------------------------------------------------------------- */

.oz-maths {
  margin-top: clamp(1.25rem, 2.5vw, 1.75rem);
  padding: clamp(1rem, 2vw, 1.35rem) clamp(1.1rem, 2.2vw, 1.5rem);
  border: 1px solid var(--oz-line);
  border-left: 1px solid var(--oz-gold);
  border-radius: var(--oz-radius);
  background: rgba(255, 255, 255, 0.03);
}

.oz-maths-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  padding: 0.32rem 0;
  font-size: 0.97rem;
  color: var(--oz-text);
  /* The figure is nowrap, so on a 320px screen the label must be free to give
     way rather than push the row wider than the viewport. */
  flex-wrap: wrap;
}

.oz-maths-row span:first-child { min-width: 0; }

.oz-maths-row span:last-child { font-variant-numeric: tabular-nums; white-space: nowrap; }

.oz-maths-row.is-total {
  margin-top: 0.35rem;
  padding-top: 0.7rem;
  border-top: 1px solid var(--oz-line);
  color: #fff;
  font-weight: 700;
}

.oz-maths-row.is-total span:last-child {
  font-family: var(--oz-display);
  font-size: 1.25rem;
  color: var(--oz-gold);
}

.oz-maths-note {
  margin: 0.75rem 0 0;
  font-size: 0.82rem;
  line-height: 1.5;
  color: var(--oz-text-dim);
}

/* ---------------------------------------------------------------------------
   The two doors (see PATCHES.md patch 118)

   One page, two readers: the athlete who wants a profile and the instructor who
   confirms ranks and hires the services. The switch sits directly under the
   hero, so the choice is made before the first section is read.

   Both panels stay in the HTML and only their visibility changes - nothing here
   is hidden from a crawler, from a payment review, or from a visitor whose
   JavaScript never ran. Focus rings and reduced motion are already handled
   globally further up this file.
   --------------------------------------------------------------------------- */

.oz-switch { margin-top: clamp(2rem, 4vw, 3rem); }

.oz-switch-inner {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.75rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--oz-line);
}

.oss-landing .oz-door {
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
  padding: 1.15rem 1.3rem;
  border: 1px solid var(--oz-line);
  border-radius: var(--oz-radius);
  color: var(--oz-text);
  text-decoration: none;
  transition: border-color 0.18s var(--oz-ease), background-color 0.18s var(--oz-ease);
}

.oss-landing .oz-door:hover {
  border-color: rgba(255, 216, 0, 0.42);
  color: var(--oz-text);
  text-decoration: none;
}

/* Selected is a change of surface, not of hue: gold carries the label only on
   the deep navy, never on the page base. Same rule as the plan cards. */
.oss-landing .oz-door.is-on {
  background: var(--oz-navy);
  border-color: rgba(255, 216, 0, 0.62);
}

.oz-door-k {
  font-family: var(--oz-display);
  font-size: 1.05rem;
  font-weight: 800;
  letter-spacing: -0.01em;
  color: #fff;
}

.oss-landing .oz-door.is-on .oz-door-k { color: var(--oz-gold); }

.oz-door-s { font-size: 0.82rem; line-height: 1.45; color: var(--oz-text-dim); }

/* The panel's own heading: it names the stack for anybody reading the page with
   the switch inert, and reads as a section eyebrow when it is working. */
/* Specificity note: the landing sheet styles `.oss-landing h2` (0,1,1), so a
   lone class here loses and this renders as a full section heading. */
.oss-landing .oz-door-h {
  margin: clamp(2rem, 4vw, 3rem) 0 0;
  padding: 0 1rem;
  font-family: var(--oz-display);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--oz-text-dim);
  text-align: center;
}

.oz-door-panel.is-off { display: none; }

/* LOCAL (see PATCHES.md patch 382): the third door ("I coach on my own"). Three
   across from a tablet up; stacked on a phone like the two were. */
.oz-switch-inner.oz-switch-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }

@media (max-width: 767.98px) {
  .oz-switch-inner.oz-switch-3 { grid-template-columns: 1fr; }
}

@media (max-width: 575.98px) {
  .oz-switch-inner { grid-template-columns: 1fr; }
  .oss-landing .oz-door { padding: 1rem 1.1rem; }
}

/* ---------------------------------------------------------------------------
   The assistant demo (see PATCHES.md patch 145)

   A phone frame holding a direct-message thread, beside the five fields that
   drive it. The frame is deliberately plain: this is not a picture of
   Instagram, it is a shape people recognise as a phone so the conversation
   reads as a conversation. Anything more faithful would be imitating somebody
   else's interface, which is not ours to do.

   The screen is a light surface inside a dark page, because that is what a
   messaging app looks like and because the point of the panel is that your eye
   goes to it.
--------------------------------------------------------------------------- */
.oss-landing .oz-demo {
  display: grid;
  grid-template-columns: minmax(0, 360px) minmax(0, 1fr);
  gap: clamp(1.5rem, 4vw, 3rem);
  align-items: start;
}

.oss-landing .oz-phone {
  background: var(--oz-navy);
  border: 1px solid var(--oz-line);
  border-radius: 26px;
  padding: 10px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.35);
  max-width: 100%;
}

.oss-landing .oz-phone-screen {
  background: #FFFFFF;
  border-radius: 18px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  /* Tall enough to hold a real exchange without the thread scrolling on the
     first reply, short enough to sit above the fold on a laptop. */
  height: 460px;
}

.oss-landing .oz-dm-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 12px 14px;
  border-bottom: 1px solid #E6E8EC;
  background: #FFFFFF;
}

.oss-landing .oz-dm-back { color: #8A8F98; font-size: 1.4rem; line-height: 1; }

.oss-landing .oz-dm-avatar {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--oz-navy);
  color: #FFFFFF;
  display: grid;
  place-items: center;
  font-family: var(--oz-display);
  font-weight: 700;
  font-size: 0.95rem;
  flex: 0 0 auto;
}

.oss-landing .oz-dm-who { display: flex; flex-direction: column; min-width: 0; }
.oss-landing .oz-dm-who b {
  font-family: var(--oz-display);
  font-size: 0.92rem;
  color: #11131A;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.oss-landing .oz-dm-who small { font-size: 0.72rem; color: #8A8F98; }

.oss-landing .oz-dm-thread {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 8px;
  background: #FFFFFF;
}

.oss-landing .oz-dm-day {
  text-align: center;
  font-size: 0.7rem;
  color: #9AA0A8;
  margin: 0 0 4px;
}

.oss-landing .oz-dm-msg {
  max-width: 78%;
  padding: 9px 13px;
  border-radius: 18px;
  font-size: 0.88rem;
  line-height: 1.45;
  color: #11131A;
  /* A long unbroken string typed into the box must not widen the phone. */
  overflow-wrap: anywhere;
  /* Patch 163: a reply's line breaks are kept, as Instagram keeps them — the
     address and its map link are two lines there, and ran together here. */
  white-space: pre-line;
  /* Patch 171: with dir="auto" on each bubble, every line takes its own
     direction, so an Arabic sentence naming "BJJ" reads right to left and the
     map URL under it still reads left to right. text-align: start so each line
     also sits against its own starting edge — the page's left alignment had an
     Arabic reply's short last line hugging the wrong side. */
  unicode-bidi: plaintext;
  text-align: start;
}

/* Them: the visitor, on the right, the way your own messages sit. */
.oss-landing .oz-dm-them {
  align-self: flex-end;
  background: var(--oz-navy);
  color: #FFFFFF;
  border-bottom-right-radius: 5px;
}

/* The gym: the assistant, on the left. */
.oss-landing .oz-dm-gym {
  align-self: flex-start;
  background: #F0F1F4;
  border-bottom-left-radius: 5px;
}

.oss-landing .oz-dm-typing { color: #8A8F98; letter-spacing: 2px; }

.oss-landing .oz-dm-note {
  background: #FFF6D6;
  color: #4A3B00;
  font-size: 0.82rem;
  max-width: 100%;
}

.oss-landing .oz-dm-note a {
  color: inherit;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* Patch 164: the human check, once per conversation, inside the phone. The
   standard widget is 304px wide; the phone's screen is wider than that from
   phone width up, and overflow is hidden rather than allowed to widen it. */
.oss-landing .oz-dm-captcha {
  margin: 0 10px 8px;
  padding: 8px 0 0;
  border-top: 1px solid #E6E8EC;
  overflow: hidden;
}

.oss-landing .oz-dm-captcha[hidden] { display: none; }

.oss-landing .oz-dm-captcha p {
  margin: 0 0 6px;
  font-size: 0.78rem;
  line-height: 1.35;
  color: #50565F;
}

/* Sent before ticking: the line turns into the instruction it is. */
.oss-landing .oz-dm-captcha-ask p { color: #4A3B00; font-weight: 600; }

/* Patch 163: the faded suggestion above the compose bar. Faded so it reads as a
   hint rather than a message; full opacity on hover and focus so it is plainly
   a thing you can press. Colours stay AA on white at rest. */
.oss-landing .oz-dm-suggest {
  display: flex;
  align-items: baseline;
  gap: 6px;
  margin: 0 10px 8px;
  padding: 7px 12px;
  border: 1px dashed #B9BEC7;
  border-radius: 999px; /* SHAPE RULE: a control is a pill */
  background: #FFFFFF;
  color: #50565F;
  font-family: var(--oz-body);
  font-size: 0.82rem;
  line-height: 1.35;
  text-align: left;
  cursor: pointer;
  opacity: 0.9;
  transition: opacity 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}

.oss-landing .oz-dm-suggest[hidden] { display: none; }

.oss-landing .oz-dm-suggest:hover,
.oss-landing .oz-dm-suggest:focus-visible {
  opacity: 1;
  border-color: var(--oz-navy);
  color: #11131A;
}

.oss-landing .oz-dm-suggest:focus-visible {
  outline: 2px solid var(--oz-navy);
  outline-offset: 1px;
}

.oss-landing .oz-dm-suggest-try {
  flex: 0 0 auto;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #5B616B;
}

@media (prefers-reduced-motion: reduce) {
  .oss-landing .oz-dm-suggest { transition: none; }
}

.oss-landing .oz-dm-compose {
  display: flex;
  gap: 8px;
  padding: 10px;
  border-top: 1px solid #E6E8EC;
  background: #FFFFFF;
}

.oss-landing .oz-dm-compose input {
  flex: 1 1 auto;
  min-width: 0;
  border: 1px solid #D9DCE2;
  border-radius: 999px;
  padding: 9px 14px;
  font-family: var(--oz-body);
  font-size: 0.88rem;
  color: #11131A;
  background: #FFFFFF;
}

.oss-landing .oz-dm-compose input:focus-visible {
  outline: 2px solid var(--oz-navy);
  outline-offset: 1px;
}

.oss-landing .oz-dm-compose button {
  border: 0;
  border-radius: 999px;
  padding: 9px 18px;
  background: var(--oz-navy);
  color: #FFFFFF;
  font-family: var(--oz-display);
  font-weight: 600;
  font-size: 0.85rem;
  cursor: pointer;
}

.oss-landing .oz-dm-compose button:disabled,
.oss-landing .oz-dm-compose input:disabled { opacity: 0.45; cursor: not-allowed; }

.oss-landing .oz-demo-side h2 { margin-top: 0; }

.oss-landing .oz-demo-fields {
  display: grid;
  gap: 4px 12px;
  margin: 1.2rem 0 1.4rem;
}

.oss-landing .oz-demo-fields label {
  font-family: var(--oz-display);
  font-size: 0.72rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--oz-text-dim);
  margin: 0.5rem 0 0;
}

.oss-landing .oz-demo-fields input {
  width: 100%;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid var(--oz-line);
  border-radius: 8px;
  padding: 9px 12px;
  color: #FFFFFF;
  font-family: var(--oz-body);
  font-size: 0.9rem;
}

.oss-landing .oz-demo-fields input:focus-visible {
  outline: 2px solid var(--oz-gold);
  outline-offset: 1px;
}

@media (max-width: 991.98px) {
  .oss-landing .oz-demo { grid-template-columns: minmax(0, 1fr); }
  .oss-landing .oz-phone { justify-self: center; width: 100%; max-width: 380px; }
}

@media (max-width: 575.98px) {
  .oss-landing .oz-phone-screen { height: 420px; }
  .oss-landing .oz-dm-msg { max-width: 86%; }
}

/* The demo's heading is a section head, not a hero (see PATCHES.md patch 147).
   It was inheriting the hero h1 scale and filling the first screen on its own,
   which put the phone — the entire reason for the page — below the fold. On a
   page whose pitch is "watch it answer", the thing answering has to be on
   screen when you arrive. */
.oss-landing .oz-demo-head h1 {
  font-size: clamp(1.9rem, 4.2vw, 2.9rem);
  line-height: 1.08;
  margin-bottom: 0.6rem;
}

.oss-landing .oz-demo-head p { max-width: 58ch; }

/* The section carries the page, so it does not need the full stack of padding
   above it as well. */
.oss-landing .oz-demo-head { margin-bottom: clamp(1.4rem, 3vw, 2.2rem); }

/* The demo's remaining-turns meter (see PATCHES.md patch 148). Under the phone,
   not inside it: the thread has to keep looking like a thread. */
.oss-landing .oz-demo-meter {
  margin: 0.7rem 0 0;
  font-family: var(--oz-display);
  font-size: 0.76rem;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--oz-text-dim);
  text-align: center;
}

/* The demo's address form (see PATCHES.md patch 149). Set apart from the gym
   fields above it with a rule rather than a card: it is a different question,
   asked once, and a second panel would make the column look like a form stack
   rather than a demo with an ask at the end. */
.oss-landing .oz-demo-email {
  margin: 1.6rem 0 1.4rem;
  padding-top: 1.4rem;
  border-top: 1px solid var(--oz-line);
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  align-items: flex-start;
}

.oss-landing .oz-demo-email h3 {
  font-family: var(--oz-display);
  font-size: 1.05rem;
  margin: 0;
  color: #FFFFFF;
}

.oss-landing .oz-demo-email p { margin: 0; }

.oss-landing .oz-demo-email input[type="email"] {
  width: 100%;
  max-width: 380px;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid var(--oz-line);
  border-radius: 8px;
  padding: 10px 12px;
  color: #FFFFFF;
  font-family: var(--oz-body);
  font-size: 0.95rem;
}

.oss-landing .oz-demo-email input[type="email"]:focus-visible {
  outline: 2px solid var(--oz-gold);
  outline-offset: 1px;
}

.oss-landing .oz-demo-email input[type="email"]:disabled { opacity: 0.5; }

.oss-landing .oz-demo-email button {
  background: var(--oz-gold);
  color: var(--oz-navy);
  border: 1px solid var(--oz-gold);
  border-radius: 999px;
  padding: 10px 22px;
  font-family: var(--oz-display);
  font-weight: 700;
  font-size: 0.88rem;
  cursor: pointer;
}

.oss-landing .oz-demo-email button:disabled { opacity: 0.55; cursor: not-allowed; }

/* Patch 171: "Show me the hand-off" and "What it costs" side by side; on a
   narrow phone the second wraps under the first instead of squeezing. */
.oss-landing .oz-demo-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.6rem;
}

/* Side by side they must be the same size: the pricing link carried the page's
   larger .oz-btn and stood taller than the form's button. Same padding, type
   and height; the link is the ghost variant, so the hand-off stays the step. */
.oss-landing .oz-demo-actions .oz-btn-ghost {
  margin: 0;
  padding: 10px 22px;
  font-family: var(--oz-display);
  font-size: 0.88rem;
  flex: 0 0 auto;
}

/* One height for both, whatever line-height each would inherit. */
.oss-landing .oz-demo-actions > button,
.oss-landing .oz-demo-actions > a {
  box-sizing: border-box;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1.2;
}

.oss-landing .oz-demo-email-said { color: var(--oz-gold); }

/* The captcha widget ships with bootstrap row classes from the shared partial;
   inside this column they would centre it against nothing. */
.oss-landing .oz-demo-email .captcha-field {
  margin: 0;
  justify-content: flex-start !important;
}

/* ===========================================================================
   Patch 284 (option B): the split stage.

   The hero is the brand line, one sentence and the two doors; under it a
   stage split in two, each half a live preview (the real athlete card, the
   recorded school tour) with its claim and its buttons. Choosing a door sets
   data-side on the stage: that half grows to 1.3fr and the other dims to 62%
   but stays in view, so the fork is never lost. Equal and fully lit until
   somebody chooses. On a phone the halves stack and the chosen one comes
   first (a visual order only; the source order never changes).

   The chosen state is a change of width and border, never of hue: gold on
   the deep navy only, as everywhere else on this page.
   ------------------------------------------------------------------------- */

.oz-hero-b { padding-bottom: clamp(1.5rem, 3vw, 2.5rem); }
.oz-hero-b h1 { max-width: 14ch; }
.oz-hero-b .oz-lead { max-width: 54ch; }
.oz-hero-b .oz-switch { margin-top: clamp(2rem, 4vw, 3rem); }
.oz-hero-b .oz-switch-inner { border-top: 0; padding-top: 0; max-width: none; } /* LOCAL (see PATCHES.md patch 440): the three doors span the stage, in line with the halves below */
.oss-landing .oz-hero-b .oz-door-k { text-transform: uppercase; letter-spacing: 0.08em; font-size: 0.9rem; }
.oss-landing .oz-hero-b .oz-door { gap: 0.4rem; padding: 1.2rem 1.4rem; }
.oss-landing .oz-hero-b .oz-door-s { font-size: 0.9rem; }

.oz-stage { padding: clamp(1rem, 2vw, 2rem) 0 clamp(3rem, 6vw, 5rem); }

.oz-stage-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 1.25rem;
  align-items: start;
}

@media (min-width: 992px) {
  .oz-stage-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 1.5rem; }
  .oz-stage[data-side="athlete"] .oz-stage-grid { grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr); }
  .oz-stage[data-side="gym"] .oz-stage-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1.3fr); }
  .oz-stage[data-side] .oz-pane:not(.is-on) { opacity: 0.62; }
  .oz-stage[data-side] .oz-pane:not(.is-on):hover,
  .oz-stage[data-side] .oz-pane:not(.is-on):focus-within { opacity: 1; }
}

@media (max-width: 991.98px) {
  .oz-stage[data-side="gym"] .oz-pane-gym { order: -1; }
}

@media (prefers-reduced-motion: no-preference) {
  .oz-stage-grid { transition: grid-template-columns 0.55s var(--oz-ease); }
  .oz-pane { transition: opacity 0.3s var(--oz-ease), border-color 0.3s var(--oz-ease); }
}

.oz-pane {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
  min-width: 0;
  padding: clamp(1.25rem, 2.5vw, 2rem);
  background: var(--oz-navy);
  border: 1px solid var(--oz-line);
  border-radius: var(--oz-radius);
}

.oz-pane.is-on { border-color: rgba(255, 216, 0, 0.62); }

.oss-landing .oz-pane-k,
.oss-landing .oz-eyebrow,
.oss-landing .oz-editor-h {
  display: block;
  margin: 0 0 0.75rem;
  font-family: var(--oz-display);
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--oz-gold);
}

.oss-landing .oz-eyebrow { color: var(--oz-text-dim); }

.oss-landing .oz-pane h2 {
  font-size: clamp(1.5rem, 2.2vw, 1.95rem);
  line-height: 1.1;
  letter-spacing: -0.02em;
}

.oz-pane-copy p:not(.oz-pane-k) { margin-top: 0.85rem; font-size: 1rem; line-height: 1.6; max-width: 50ch; }
.oz-pane .oz-actions { margin-top: 1.4rem; }

.oz-pane-figure {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.75rem;
  min-width: 0;
  margin: 0;
}

.oz-showcase { width: 100%; max-width: 460px; min-width: 0; }
.oz-showcase .oz-ap {
  border-radius: var(--oz-radius);
  border: 1px solid var(--oz-line);
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.35);
}

.oz-pane-cap {
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--oz-text-dim);
}

/* The school half: a browser frame around the recorded tour. */
.oz-frame {
  width: 100%;
  overflow: hidden;
  border-radius: 14px;
  border: 1px solid var(--oz-line);
  background: #0B1A3A;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.35);
}

.oz-frame-bar {
  display: flex;
  align-items: center;
  gap: 6px;
  height: 32px;
  padding: 0 12px;
  background: #152447;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

.oz-frame-bar span { width: 9px; height: 9px; border-radius: 50%; background: rgba(255, 255, 255, 0.22); }

.oz-frame-bar em {
  flex: 1;
  margin-left: 10px;
  height: 18px;
  padding-left: 8px;
  border-radius: 6px;
  background: rgba(255, 255, 255, 0.08);
  font-family: var(--oz-body);
  font-style: normal;
  font-size: 11px;
  line-height: 18px;
  color: rgba(255, 255, 255, 0.6);
}

.oz-frame img { display: block; width: 100%; height: auto; aspect-ratio: 960 / 795; }

/* Ticks and a stacked pair of buttons. */
.oz-ticks { list-style: none; margin: 1.4rem 0 0; padding: 0; display: grid; gap: 0.7rem; }

.oz-ticks li { position: relative; padding-left: 1.9rem; font-size: 0.97rem; line-height: 1.5; color: var(--oz-text); }

.oz-ticks li::before {
  content: '';
  position: absolute;
  left: 0.1rem;
  top: 0.32em;
  width: 1rem;
  height: 0.55rem;
  border-left: 2.5px solid var(--oz-gold);
  border-bottom: 2.5px solid var(--oz-gold);
  transform: rotate(-45deg);
}

.oz-ticks strong { color: #fff; }
.oz-actions-stack { margin-top: 0; }

/* The school showcase: the claim beside the three pillars. */
.oz-pillars { display: grid; gap: clamp(2rem, 4vw, 3.5rem); align-items: start; }

@media (min-width: 992px) {
  .oz-pillars { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); }
}

.oz-pillars-copy h2 { max-width: 16ch; }
.oz-pillars-copy p:not(.oz-eyebrow) { margin-top: 1.1rem; max-width: 52ch; }

.oz-pillar-list {
  margin: 0;
  padding: 0.25rem 1.5rem;
  background: var(--oz-navy);
  border: 1px solid var(--oz-line);
  border-radius: var(--oz-radius);
}

.oz-pillar { padding: 1.1rem 0; border-bottom: 1px solid var(--oz-line); }
.oz-pillar:last-child { border-bottom: 0; }

.oz-pillar dt {
  margin-bottom: 0.3rem;
  font-family: var(--oz-display);
  font-size: 0.75rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--oz-gold);
}

.oz-pillar dd { margin: 0; font-size: 0.97rem; line-height: 1.55; color: var(--oz-text); }

/* The ad page builder and the share story: copy beside a picture. */
.oz-builder,
.oz-share { display: grid; gap: clamp(2rem, 4vw, 3.5rem); align-items: center; }

@media (min-width: 992px) {
  .oz-builder { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); }
  .oz-share { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); }
}

.oz-builder-copy p:not(.oz-eyebrow),
.oz-share-copy p:not(.oz-eyebrow) { margin-top: 1.1rem; max-width: 52ch; }

.oz-builder-copy .oz-actions,
.oz-share-copy .oz-actions,
.oz-pillars-copy .oz-actions { margin-top: 1.75rem; }

.oz-demo-b {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 200px;
  gap: 1.25rem;
  align-items: center;
  padding: clamp(1rem, 2vw, 1.5rem);
  background: var(--oz-navy);
  border: 1px solid var(--oz-line);
  border-radius: var(--oz-radius);
}

@media (max-width: 575.98px) {
  .oz-demo-b { grid-template-columns: minmax(0, 1fr); justify-items: center; }
  .oz-editor { width: 100%; }
}

.oz-editor { min-width: 0; display: grid; gap: 0.8rem; }
.oz-editor-field { display: grid; gap: 0.35rem; margin: 0; }
.oz-editor-field span,
.oz-editor-row span { font-size: 0.78rem; font-weight: 700; color: var(--oz-text-dim); }

.oz-editor-field input {
  width: 100%;
  min-height: 44px;
  padding: 0.5rem 0.8rem;
  border-radius: 10px;
  border: 1px solid rgba(255, 255, 255, 0.35);
  background: #fff;
  color: var(--oz-navy);
  font: 600 0.95rem/1.3 var(--oz-body);
}

.oz-editor-field input:focus-visible { outline: 3px solid var(--oz-gold); outline-offset: 2px; }
.oz-editor-row { display: grid; gap: 0.3rem; }

.oz-editor-row em {
  display: block;
  min-height: 40px;
  padding: 0.5rem 0.8rem;
  border-radius: 10px;
  border: 1px dashed rgba(255, 255, 255, 0.3);
  font-style: normal;
  font-size: 0.85rem;
  color: var(--oz-text-dim);
}

.oz-phone-b {
  width: 200px;
  padding: 8px;
  border-radius: 30px;
  background: #1C1C1E;
  box-shadow: inset 0 0 0 2px #3A3B3F, 0 24px 50px rgba(0, 0, 0, 0.45);
}

.oz-phone-b-screen {
  display: grid;
  gap: 6px;
  overflow: hidden;
  padding: 0 0 14px;
  border-radius: 23px;
  background: #fff;
  color: var(--oz-navy);
}

.oz-phone-b-photo { height: 96px; background: url('/images/for-students/sample-cover.jpg') center / cover, #052A78; }

.oss-landing .oz-phone-b-name {
  padding: 8px 12px 0;
  font-size: 0.62rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #5A6478;
}

.oss-landing .oz-phone-b-h {
  padding: 0 12px;
  font-family: var(--oz-display);
  font-weight: 900;
  font-size: 0.95rem;
  line-height: 1.05;
  letter-spacing: -0.02em;
  text-transform: uppercase;
  color: var(--oz-navy);
  overflow-wrap: anywhere;
}

.oss-landing .oz-phone-b-sub { padding: 0 12px; font-size: 0.62rem; line-height: 1.4; color: #3F4A5E; }

.oz-phone-b-btn {
  display: block;
  margin: 4px 12px 0;
  padding: 8px;
  border-radius: 999px;
  background: var(--oz-gold);
  color: var(--oz-navy);
  text-align: center;
  font-size: 0.7rem;
  font-weight: 800;
}

.oz-story-wrap { display: flex; flex-direction: column; align-items: center; gap: 0.75rem; margin: 0; }

.oz-story {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 8px;
  width: min(100%, 270px);
  aspect-ratio: 9 / 16;
  padding: 18px;
  overflow: hidden;
  border-radius: 22px;
  border: 1px solid var(--oz-line);
  background: linear-gradient(180deg, #052A78 0%, #011F5D 55%, #01102F 100%);
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.45);
  color: #fff;
}

.oz-story-brand { font-family: var(--oz-display); font-weight: 900; font-size: 0.9rem; color: var(--oz-gold); }
.oz-story-photo { flex: 0 0 auto; height: 34%; margin-top: 6px; border-radius: 12px; background: url('/images/for-students/sample-cover.jpg') center / cover, #011F5D; }
.oss-landing .oz-story-name { margin-top: 10px; font-family: var(--oz-display); font-weight: 900; font-size: 1.35rem; line-height: 1; color: #fff; }
.oss-landing .oz-story-rank { font-size: 0.9rem; font-weight: 700; color: rgba(255, 255, 255, 0.85); }

.oss-landing .oz-story-pill {
  align-self: flex-start;
  margin-top: 4px;
  padding: 4px 10px;
  border-radius: 999px;
  background: var(--oz-gold);
  color: var(--oz-navy);
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

.oz-story-rec { display: flex; gap: 14px; margin-top: auto; }
.oz-story-rec span { display: flex; flex-direction: column; font-size: 0.62rem; letter-spacing: 0.06em; text-transform: uppercase; color: rgba(255, 255, 255, 0.7); }
.oz-story-rec b { font-family: var(--oz-display); font-size: 1.3rem; line-height: 1; color: #fff; }
.oz-story-url { font-size: 0.65rem; color: rgba(255, 255, 255, 0.6); }

/* The three plans, briefly. */
.oz-plans { list-style: none; margin: 0 0 2rem; padding: 0; display: grid; gap: 1rem; grid-template-columns: repeat(3, minmax(0, 1fr)); }

@media (max-width: 767.98px) {
  .oz-plans { grid-template-columns: minmax(0, 1fr); }
}

.oz-plan-b {
  display: grid;
  gap: 0.35rem;
  padding: 1.4rem 1.5rem;
  background: var(--oz-navy);
  border: 1px solid var(--oz-line);
  border-radius: var(--oz-radius);
}

.oz-plan-b-name { font-family: var(--oz-display); font-weight: 800; font-size: 1.05rem; color: #fff; }
.oz-plan-b-price { font-family: var(--oz-display); font-weight: 900; font-size: 2rem; line-height: 1; letter-spacing: -0.02em; color: var(--oz-gold); }
.oz-plan-b-price small { font-family: var(--oz-body); font-weight: 600; font-size: 0.9rem; letter-spacing: 0; color: var(--oz-text-dim); }
.oz-plan-b-line { font-size: 0.9rem; line-height: 1.5; color: var(--oz-text-dim); }
#plans .oz-actions { margin-top: 0; }
/* LOCAL (see PATCHES.md patch 454): each plan's own "Start ... — 14 days free" button, at the
   bottom of its card (the cards keep one height in a row), the full width, at least 44px tall
   (.oz-btn is 3rem), and the words may wrap on a 360px phone. */
.oz-plan-b { grid-template-rows: auto auto 1fr auto; }
.oz-plan-b .oz-plan-b-buy { margin-top: 0.75rem; width: 100%; min-height: 2.75rem; justify-content: center; text-align: center; white-space: normal; }
/* LOCAL (see PATCHES.md patch 459): "Run several branches? See Enterprise", a small gold link under the
   three plans, a 44px tap. */
.oz-plan-enterprise { margin: 1rem 0 0; text-align: center; font-size: 0.9375rem; }
.oss-landing .oz-plan-enterprise a { display: inline-flex; align-items: center; min-height: 2.75rem; padding: 0 0.5rem; color: var(--oz-gold); font-weight: 700; text-decoration: underline; text-underline-offset: 3px; }

/* The home showcase shows the card down to its confirmed main rank: the cover,
   the name, the chips, the buttons, the rank the school confirmed and the one
   line that explains the gold. The other arts and the record are on
   /for-students, where the whole card is the point; here they made the athlete
   half twice the height of the school half. Nickname: the landing p rule
   (0,1,1) outranked the card's own gold (0,1,0). */
.oz-showcase .oz-ap-rot,
.oz-showcase .oz-ap-others,
.oz-showcase .oz-ap-record { display: none; }
.oss-landing .oz-ap .oz-ap-nick { color: var(--ap-gold); }

/* LOCAL (see PATCHES.md patch 422): the tour's stops under the school half, a card of
   six numbered rows (the owner's list, 2026-10-05), each a link to that stop of
   /try-it with one plain line under its name. The card has the athlete card's edge,
   corners and shadow, so the two halves read as a pair; on a desktop both halves are
   stretched to the taller one and the card takes up the rest of the school half. */
.oz-tour {
  list-style: none;
  counter-reset: oz-tour;
  width: 100%;
  margin: 0;
  padding: 0.1rem 0;
  border: 1px solid var(--oz-line);
  border-radius: var(--oz-radius);
  background: var(--oz-ink);
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.35);
}
.oz-tour li { counter-increment: oz-tour; }
.oz-tour li + li { border-top: 1px solid var(--oz-line-soft); }
.oss-landing .oz-tour a {
  position: relative;
  display: grid;
  grid-template-columns: 1.75rem minmax(0, 1fr);
  column-gap: 0.85rem;
  align-items: center;
  min-height: 44px;
  padding: 0.4rem 2.4rem 0.4rem 1rem;
  color: #fff;
  text-decoration: none;
}
.oz-tour a::before {
  content: counter(oz-tour);
  content: counter(oz-tour) / "";
  grid-row: 1 / span 2;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 50%;
  background: var(--oz-gold);
  color: var(--oz-navy);
  font-family: var(--oz-display);
  font-size: 0.8rem;
  font-weight: 800;
}
.oz-tour a::after {
  content: "";
  position: absolute;
  right: 1.1rem;
  top: 50%;
  width: 0.5rem;
  height: 0.5rem;
  border-top: 2px solid var(--oz-text-dim);
  border-right: 2px solid var(--oz-text-dim);
  transform: translateY(-50%) rotate(45deg);
}
.oz-tour-t { font-family: var(--oz-display); font-size: 0.95rem; font-weight: 800; line-height: 1.3; color: #fff; }
.oz-tour-s { margin-top: 0.15rem; font-size: 0.85rem; line-height: 1.45; color: var(--oz-text-dim); }
.oss-landing .oz-tour a:hover .oz-tour-t { color: var(--oz-gold); }
.oss-landing .oz-tour a:hover::after { border-color: var(--oz-gold); }
.oss-landing .oz-tour a:focus-visible { outline: 2px solid var(--oz-gold); outline-offset: -2px; border-radius: var(--oz-radius); }

@media (min-width: 992px) {
  .oz-stage-grid { align-items: stretch; }
  .oz-pane-gym .oz-pane-figure { flex: 1 1 auto; }
  .oz-pane-gym .oz-tour { flex: 1 1 auto; display: flex; flex-direction: column; justify-content: space-around; }
}

/* LOCAL (see PATCHES.md patch 416): "Trusted by" + one word that rolls to the next
   (owner, 2026-10-02 / 2026-10-04), the home page's first line, ported from patch 323.
   Without motion (the default here, and under prefers-reduced-motion) the whole
   sentence shows. With motion the sentence is kept for screen readers only and the
   rolling copy takes its place: five words and the first again, each still for half a
   second, a quarter of a second rolling, 3.75s a turn. The colours are on the spans,
   not the paragraph: the landing sheet colours every p. The gold word may drop to its
   own line on a narrow phone (flex-wrap), so nothing scrolls sideways at 390px. */
.oss-landing .oz-trusted {
  margin: 0 0 clamp(0.875rem, 2vw, 1.25rem);
  font-family: var(--oz-display);
  font-size: clamp(1rem, 0.9rem + 0.6vw, 1.3rem);
  font-weight: 800;
  line-height: 1.4;
  letter-spacing: 0.01em;
}
.oss-landing .oz-trusted-all { color: #fff; }
.oss-landing .oz-trusted-live { display: none; }
.oss-landing .oz-trusted-k { color: #fff; }
.oss-landing .oz-trusted-w { color: var(--oz-gold); }
@media (prefers-reduced-motion: no-preference) {
  .oss-landing .oz-trusted-all {
    position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0;
    overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
  }
  .oss-landing .oz-trusted-live { display: inline-flex; flex-wrap: wrap; align-items: flex-start; gap: 0 0.4em; max-width: 100%; }
  .oss-landing .oz-trusted-roll { display: inline-block; height: 1.4em; overflow: hidden; }
  .oss-landing .oz-trusted-col { display: flex; flex-direction: column; animation: ozTrustedRoll 3.75s cubic-bezier(0.3, 0.7, 0.2, 1) infinite; }
  .oss-landing .oz-trusted-w { display: block; height: 1.4em; white-space: nowrap; text-align: start; }
  .oss-landing .oz-trusted:hover .oz-trusted-col { animation-play-state: paused; }
}
@keyframes ozTrustedRoll {
  0%, 13.33% { transform: translateY(0); }
  20%, 33.33% { transform: translateY(-1.4em); }
  40%, 53.33% { transform: translateY(-2.8em); }
  60%, 73.33% { transform: translateY(-4.2em); }
  80%, 93.33% { transform: translateY(-5.6em); }
  100% { transform: translateY(-7em); }
}

/* LOCAL (see PATCHES.md patch 440, owner 2026-10-05): THREE lit halves, patch 154's design extended.
   Left to right: "I train", "I coach on my own", "I run a school or gym". From 992px the chosen half is
   wide (~62%) and fully clear; the other two are narrow (~19% each), dimmed and blurred so they read as
   "behind", their title still sharp: a button over each brings it forward (44px+). The widths change over
   ~350 ms (not at all for reduced motion). The stage always has a chosen half (data-side; the athlete
   by default, or the door in the link). On a phone the halves stack, the chosen one first, all clear. */
.oz-peek { display: none; }
@media (min-width: 992px) {
  .oz-stage-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 1fr); gap: 1rem; align-items: stretch; }
  .oz-stage[data-side="athlete"] .oz-stage-grid { grid-template-columns: minmax(0, 3.3fr) minmax(0, 1fr) minmax(0, 1fr); }
  .oz-stage[data-side="coach"] .oz-stage-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 3.3fr) minmax(0, 1fr); }
  .oz-stage[data-side="gym"] .oz-stage-grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) minmax(0, 3.3fr); }
  .oz-stage-grid { container-type: inline-size; }
  .oz-pane { position: relative; padding: 1.5rem; overflow: hidden; }
  /* Every half lays its content out at the width it has when it is the chosen one (3.3 of 5.3 of the row,
     less the gaps, the padding and the border), whether it is wide or narrow: a half behind is a clipped, blurred
     look at the real page from its left edge, and nothing reflows while it widens. The title stays at the half's
     own width, so it stays readable. */
  .oz-stage-grid { --oz-wide: calc((100cqw - 2rem) * 0.6226 - 3rem - 2px); }
  .oz-pane-copy > :not(.oz-pane-k), .oz-pane-figure { width: var(--oz-wide); max-width: none; flex: none; }
  .oz-pane-copy > p:not(.oz-pane-k) { max-width: 50ch; }
  /* The school's and the coach's pictures stop at 640px, so no half is much taller than the others and the row (the tallest, whichever half is chosen) stays put. */
  .oz-pane-gym .oz-pane-figure, .oz-pane-coach .oz-pane-figure { width: min(var(--oz-wide), 640px); }
  .oz-pane-k { min-height: 2.8em; }
  .oz-stage[data-side] .oz-pane:not(.is-on) { opacity: 1; border-color: var(--oz-line); }
  /* The coaching peek shows the sample photo: the picture is centred in its frame, so a coach half behind slides the
     frame left until the photo's centre is the middle of the strip (the frame's left edge is clipped, which is fine in a peek). */
  .oz-stage[data-side] .oz-pane-coach:not(.is-on) .oz-pane-figure { margin-left: calc(((100cqw - 2rem) * 0.1887 - 3rem - 2px) / 2 - min(var(--oz-wide), 640px) / 2); }
  .oz-stage[data-side] .oz-pane:not(.is-on) .oz-pane-figure,
  .oz-stage[data-side] .oz-pane:not(.is-on) .oz-pane-copy > :not(.oz-pane-k) { opacity: 0.5; filter: blur(3px); pointer-events: none; user-select: none; }
  .oz-stage[data-side] .oz-pane:not(.is-on) .oz-pane-k { opacity: 1; line-height: 1.4; }
  .oz-stage[data-side] .oz-pane:not(.is-on) .oz-pane-k::after { content: ""; display: block; width: 28px; height: 2px; margin-top: 0.6rem; background: var(--oz-gold); opacity: 0.7; }
  .oz-stage[data-side] .oz-pane:not(.is-on):hover { border-color: rgba(255, 216, 0, 0.45); }
  .oz-stage[data-side] .oz-pane:not(.is-on) .oz-peek {
    display: block;
    position: absolute;
    inset: 0;
    z-index: 4;
    min-height: 44px;
    margin: 0;
    padding: 0;
    border: 0;
    border-radius: var(--oz-radius);
    background: transparent;
    cursor: pointer;
  }
  .oz-stage[data-side] .oz-pane:not(.is-on) .oz-peek:focus-visible { outline: 2px solid var(--oz-gold); outline-offset: -2px; }
}
@media (max-width: 991.98px) {
  .oz-stage[data-side="coach"] .oz-pane-coach { order: -1; }
}
@media (min-width: 992px) and (prefers-reduced-motion: no-preference) {
  .oz-stage-grid { transition: grid-template-columns 0.35s var(--oz-ease); }
  .oz-pane { transition: border-color 0.35s var(--oz-ease); }
  .oz-pane .oz-pane-figure, .oz-pane .oz-pane-copy > * { transition: opacity 0.35s var(--oz-ease), filter 0.35s var(--oz-ease); }
  .oz-pane-coach .oz-pane-figure { transition: margin-left 0.35s var(--oz-ease), opacity 0.35s var(--oz-ease), filter 0.35s var(--oz-ease); }
}

/* The sample coaching page: a browser frame like the school half's, the cover, the sample coach's cut-out (patch 444: a licensed stock photo, not a real member)
   in the gold ring with the head over the cover (patch 427's styles, the ring's light from
   hero-id-styles), a generic name and a "Book a session" look. The cover is tall enough for the
   head (it rises about one ring above the cover's bottom edge; patch 448). */
.oss-landing .oz-cs .oz-popout-frame { --oz-pop-d: 112px; }
/* LOCAL (see PATCHES.md patch 448): the sample sits in an .oz-frame, whose `.oz-frame img` rule (the school tour's 960:795
   picture) also caught the cut-out: full width and that aspect ratio stretched the person sideways to 1.5 times their width,
   so the shoulders spilled out of the ring. The cut-out keeps its own shape, as on a real coach's page. */
.oss-landing .oz-frame .oz-popout-person img { width: auto; aspect-ratio: auto; }
/* LOCAL (see PATCHES.md patch 448, owner 2026-10-05): the sample's person box is the SAME as a real coach's pop-out (patch 427: 1.16 rings wide, mask = above the ring's centre line + the circle inside the ring). Patch 440 had widened it to 1.6 rings, so the shoulders and sleeves spilled out of the ring over the cover; the cut-out is now centred on the head and shoulders (scripts/brand/render-coach-sample.py) and shown at --oz-pop-scale 1.45, so the body stays inside the ring and only the head breaks out of the top. */
.oz-cs-page { position: relative; background: radial-gradient(120% 90% at 100% 0%, rgba(5, 42, 120, 0.55) 0%, rgba(1, 16, 47, 0) 70%), var(--oz-ink); }
/* LOCAL (see PATCHES.md patch 444): a picture behind the sample coach: a row of heavy bags (Unsplash, muay-thai.jpg's top strip,
   public/img/samples/coach-sample-cover.webp) under a navy veil, so the gold "Sample" chip and the coach stay clear. */
.oz-cs-cover, .oz-phone-coach-cover { background: linear-gradient(135deg, rgba(22, 53, 127, 0.80) 0%, rgba(11, 29, 79, 0.86) 60%, rgba(58, 47, 11, 0.80) 100%), url("../img/samples/coach-sample-cover.webp") center 40% / cover no-repeat, #0b1d4f; }
.oz-cs-cover { position: relative; height: 132px; }
.oz-cs-tag {
  position: absolute;
  top: 10px;
  left: 10px;
  z-index: 4;
  display: inline-flex;
  align-items: center;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--oz-gold);
  color: var(--oz-navy);
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
[dir="rtl"] .oz-cs-tag { left: auto; right: 10px; }
.oz-cs-body { display: flex; flex-direction: column; align-items: center; padding: 0 1rem 1.25rem; text-align: center; }
/* LOCAL (see PATCHES.md patch 457): the sample coach's rating row, a labelled placeholder (outlined stars, no number). */
.oz-cs-rating { margin-top: 0.45rem; display: flex; justify-content: center; max-width: 100%; }
.oz-cs-rating .oss-crate { justify-content: center; }
.oz-phone-b-rating { margin-top: 0; }
.oz-phone-b-rating .oss-crate-star { width: 12px; height: 12px; }
.oz-phone-b-rating .oss-crate-ph { font-size: 0.7rem; }
.oz-cs-label { margin-top: 0.75rem; font-size: 0.72rem; font-weight: 800; letter-spacing: 0.1em; text-transform: uppercase; color: var(--oz-text-dim); }
.oz-cs-name { margin-top: 0.3rem; font-family: var(--oz-display); font-weight: 900; font-size: 1.3rem; line-height: 1.15; letter-spacing: -0.01em; color: #fff; overflow-wrap: anywhere; }
.oz-cs-book {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;
  margin-top: 0.9rem;
  padding: 0.5rem 1.5rem;
  border-radius: 999px;
  background: var(--oz-gold);
  color: var(--oz-navy);
  font-weight: 800;
}
/* LOCAL (see PATCHES.md patch 462): "Book a session" and the "Open to hire" chip side by side on the sample (a status, not a rating). */
.oz-cs-actions { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 0.5rem 0.625rem; margin-top: 0.9rem; }
.oz-cs-actions .oz-cs-book { margin-top: 0; }
/* The phone is narrow: the button keeps its full width and the chip sits centred right under it. */
.oz-phone-coach-act { justify-self: stretch; display: flex; flex-direction: column; align-items: center; gap: 6px; }
.oz-phone-coach-act .oz-phone-b-btn { align-self: stretch; white-space: nowrap; }

/* The gold "Beta" tag on the moving portrait's row. */
.oz-beta-tag {
  display: inline-flex;
  align-items: center;
  margin-left: 0.35rem;
  padding: 0 0.45rem;
  border-radius: 999px;
  border: 1px solid var(--oz-gold);
  color: var(--oz-gold);
  font-family: var(--oz-body);
  font-size: 0.65rem;
  font-weight: 800;
  letter-spacing: 0.06em;
  line-height: 1.5;
  text-transform: uppercase;
  vertical-align: 0.1em;
}
[dir="rtl"] .oz-beta-tag { margin-left: 0; margin-right: 0.35rem; }

/* The coach's live phone: the coaching page is navy, so its phone screen is too. */
.oz-phone-coach .oz-phone-b-screen { background: var(--oz-ink); justify-items: center; text-align: center; }
.oz-phone-coach-cover { position: relative; justify-self: stretch; height: 84px; }
.oz-phone-coach .oz-cs-tag { top: 8px; left: 8px; padding: 1px 7px; font-size: 0.55rem; }
.oss-landing .oz-phone-coach .oz-popout-frame { --oz-pop-d: 72px; margin-top: -42px; }
.oss-landing .oz-phone-coach .oz-phone-b-name { padding-top: 2px; color: var(--oz-text-dim); }
.oss-landing .oz-phone-coach .oz-phone-b-h { color: #fff; }
.oss-landing .oz-phone-coach .oz-phone-b-sub { color: var(--oz-text-dim); }
.oz-phone-coach .oz-phone-b-btn { justify-self: stretch; }

/* LOCAL (see PATCHES.md patch 440): the recorded school tour (the poster and the GIF, patch 273) was filmed with the real
   site's round "Tell us" bubble in its bottom-right corner. The real bubble is on the page; the one in the picture is a
   second, dead one. The corner of the recording is plain page background in every frame, so a patch of that colour (in
   percentages, so it scales with the picture) covers it. */
.oz-pane-gym .oz-frame { position: relative; }
.oz-pane-gym .oz-frame::after { content: ""; position: absolute; right: 0; bottom: 0; width: 9%; height: 10%; background: #000f2c; pointer-events: none; }

/* LOCAL (see PATCHES.md patch 448, owner 2026-10-05): the three halves' words on a phone. At 390px the headlines ran to four
   lines and the paragraphs to tall narrow stacks. Below 576px: a little less side padding in each half, a smaller and tighter
   headline (balanced, so two or three even lines), the paragraphs a touch smaller with a shorter line height and no 50ch cap,
   the two buttons one above the other at full width (side by side, "Start my coaching page" broke inside its pill), and the
   sample's "Coach Sam · Personal coaching" sized to the screen so it stays on one line. Wider screens are unchanged. */
@media (max-width: 575.98px) {
  .oz-pane { padding: 1.25rem 1rem; gap: 1.25rem; }
  .oss-landing .oz-pane h2 { font-size: 1.375rem; line-height: 1.15; letter-spacing: -0.025em; text-wrap: balance; }
  .oz-pane-copy p:not(.oz-pane-k) { margin-top: 0.7rem; font-size: 0.9375rem; line-height: 1.5; max-width: none; text-wrap: pretty; }
  .oz-pane .oz-actions { margin-top: 1.15rem; flex-direction: column; gap: 0.5rem; }
  .oz-pane .oz-actions .oz-btn, .oz-pane .oz-actions .oz-btn-ghost { flex: none; width: 100%; white-space: normal; min-height: 48px; }
  .oz-cs-name { font-size: clamp(1rem, 4.6vw, 1.3rem); letter-spacing: -0.015em; }
}

/* LOCAL (see PATCHES.md patch 492): the trial and refund promise next to a school-plan buy button
   (elements/pricing/trial-promise). Gold shield, white words, the refund rules link underlined. */
.oz-promise { display: flex; gap: 10px; align-items: flex-start; margin-top: 14px; padding: 12px 14px; max-width: 44rem; border: 1px solid rgba(255, 216, 0, 0.45); border-radius: 12px; background: rgba(255, 216, 0, 0.07); color: rgba(255, 255, 255, 0.86); font-size: 0.9375rem; line-height: 1.5; text-align: left; }
.oz-promise strong { color: #fff; font-weight: 700; }
.oz-promise .oz-promise-icon { flex: none; margin-top: 1px; color: #FFD800; }
.oz-promise a { color: #FFD800; text-decoration: underline; text-underline-offset: 2px; white-space: nowrap; }
.oz-promise a:hover { color: #E6C200; }
.oz-promise-center { margin-left: auto; margin-right: auto; }
@media (max-width: 575.98px) { .oz-promise { font-size: 0.875rem; padding: 10px 12px; } }
