/* ============================================================================
   AJAY CHEEMA — Home page styles
   Ported from: Ajay Cheema/Ajay Cheema Website.html \3c style> block.
   Only rules used by the FINAL home markup are ported (hero, coach/creds,
   experience index, booking shell, video system). The unused concepts in the
   design file (hero-cine, bookgrid/bookcard, rails, pcard, lightbox,
   filterbar) are intentionally NOT ported.
   Bundled by PostCSS → assets/css/page-home.css
   ============================================================================ */

/* ============================================================================
   SHARED EDITORIAL INDEX GRAMMAR
   Used by the home Experience section and the Method page (steps / receive).
   Source: Ajay Cheema Website.html page styles (exp / idx / metaline).
   ============================================================================ */

.exp { display: grid; grid-template-columns: minmax(240px, 1fr) 2fr; gap: clamp(32px, 6vw, 96px); align-items: start; }

@media (max-width: 860px){ .exp { grid-template-columns: 1fr; gap: 28px; } }

.exp__intro { position: sticky; top: 96px; }

@media (max-width: 860px){ .exp__intro { position: static; } }

.exp__intro p { color: var(--ash-400); font-size: 15.5px; line-height: 1.6; margin: 18px 0 0; max-width: 34ch; }

/* shared editorial index language */

.idx { font-family: var(--font-text); font-size: 13px; letter-spacing: .12em;
  color: var(--ignite); font-weight: 600; }

.on-dark .idx { color: var(--ignite-300); }

.metaline { font-family: var(--font-text); font-size: 12px; font-weight: 600;
  letter-spacing: .16em; text-transform: uppercase; color: var(--text-muted); }

/* ---- EDITORIAL HERO (text-forward) ---- */

.hero { position: relative; display: grid; grid-template-columns: 1.05fr 1fr; align-items: stretch;
  min-height: clamp(560px, 90vh, 940px); background: var(--carbon); }

/* GRAIN — the reason this hero can carry a 464×832 source at all.
   The film is upscaled ~2x on a DPR-3 phone, and an upscale reads as soft and
   plasticky. Fine grain is the colourist's fix: high-frequency noise reads as
   detail, so the softness reads as film stock rather than low resolution. It
   also masks the VP9 banding that shows in this footage's dark gym walls.
   On .hero::after because .hero__media's ::before (seam) and ::after (blurred
   surround) are both taken — and crucially this adds NO element, so the video
   and poster stay direct children of .hero__media and `.v-live > .poster-img`
   keeps matching (video.js sets .v-live on the video's parentElement).
   z-index 5 clears the caption (4); pointer-events:none keeps the CTAs live.
   Inline SVG data URI — no request, no dependency. */

.hero::after {
  content: ""; position: absolute; inset: 0; z-index: 5; pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)' opacity='.5'/%3E%3C/svg%3E");
  opacity: .15; mix-blend-mode: overlay; }

/* The tile is in CSS px, so on HiDPI it renders at a third the physical size
   and stacks into mush — back it off there. */

@media (min-resolution: 2dppx){ .hero::after { opacity: .10; } }

.hero .eyebrow { color: var(--ignite-300); }

/* Scoped to 620px, NOT 920px: tablet keeps the desktop two-column grid. Under
   the old 920px scope a 768px tablet stacked a contained portrait film in a
   full-width block, which left ~51% of it as empty carbon — the film rendered
   375px wide inside 768px. Two columns put the copy beside the film instead. */

@media (max-width: 620px){ .hero { grid-template-columns: 1fr; min-height: 0; }
  .hero__media { order: -1; } }

.hero__text { align-self: center; padding: clamp(48px,6vw,104px) clamp(24px,5vw,84px); max-width: 760px; }

.hero__head { font-family: var(--font-head) !important; color: var(--bone); font-weight: 700; font-style: normal; text-transform: none;
  font-size: clamp(48px, 6.2vw, 96px); line-height: 1.02; letter-spacing: -.025em; margin: 16px 0 0; text-wrap: balance; }

.hero__em { font-style: normal; color: var(--ignite-300); margin-left: 0.147em; }

.hero__sub { font-size: clamp(17px,1.5vw,21px); color: var(--ash-400); line-height: 1.5; margin: 26px 0 0; max-width: 46ch; }

.hero__cta { display: flex; gap: 14px; flex-wrap: wrap; margin-top: 38px; }

/* hero service cards (repurposed stats repeater: value = title, label = blurb) */

.hero__stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 14px; margin-top: 46px;
  padding-top: 30px; border-top: 1px solid rgba(255,255,255,.14); }

.hstat { display: flex; flex-direction: column; gap: 8px; padding: 18px 18px 20px;
  background: rgba(255,255,255,.04); border: 1px solid rgba(255,255,255,.12);
  border-radius: 10px; transition: border-color .25s var(--ease); }

.hstat:hover { border-color: rgba(212,168,124,.55); }

.hstat b { font-family: var(--font-head); font-weight: 700; font-style: normal;
  font-size: clamp(18px, 1.6vw, 21px); color: var(--bone); line-height: 1.15; letter-spacing: -.01em; }

.hstat span { font-size: 13.5px; line-height: 1.55; color: var(--ash-400); }

/* --- media column ---
   Desktop keeps the inset plate below. Phone/tablet are sized by aspect-ratio
   instead of a vh guess, so the block is exactly as tall as the film inside
   it — which is what removes the leftover black. */

.hero__media { position: relative; background: var(--carbon); overflow: hidden;
  min-height: clamp(520px, 86vh, 1020px); }

/* The film is inset rather than full-bleed: it sits centred in the media
   column with carbon around it, so it reads as a framed portrait plate rather
   than filling the whole hero height. The source is 464×832, so a portrait
   aspect keeps it sharp instead of upscaling to fill.
   Plate raised 82%→88% / 84%→86%: once phone and tablet go full-bleed, this is
   the only place black appears, and it was reading as dead margin rather than
   matting. At 88% the film still renders under ~560px wide on a 1440px screen,
   so the 464px source is barely upscaled. */

.hero__media .bgvid,
.hero__media .poster-img,
.hero__media .fallback-img {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: auto; height: 88%; max-width: 86%; aspect-ratio: 464 / 832;
  -o-object-fit: cover;
     object-fit: cover; -o-object-position: 50% 38%; object-position: 50% 38%; }

/* The fallback photo is cropped to the film's own 464×832, so every sizing
   rule that targets .bgvid/.poster-img must target it too — that is what makes
   it land in exactly the same box at every breakpoint. It sits UNDER the
   poster, so on the normal path it is covered and never seen. */

.hero__media .fallback-img { z-index: 0; }

.hero__media .poster-img { z-index: 1; }

.hero__media .bgvid { z-index: 2; }

/* The plate settles in rather than popping — a 1.03→1 scale so the film seats
   itself into the carbon as the text staggers in beside it.
   Applied to BOTH layers so they scale together, and it animates TRANSFORM
   ONLY. Touching opacity here would be a silent killer: the animation's `both`
   fill outlasts the crossfade, so an opacity keyframe pins .poster-img at 1
   and `.v-live > .poster-img { opacity: 0 }` can never take effect — the sharp
   poster sits on top of the playing film forever and the video looks broken.
   The keyframes MUST repeat translate(-50%,-50%): the plate is centred with a
   transform, so a bare scale() would drop the centring and throw it to the
   corner. */

@media (prefers-reduced-motion: no-preference) {
  .hero__media .poster-img,
  .hero__media .fallback-img,
  .hero__media .bgvid { animation: plate-settle 1.1s var(--ease) both; }
}

@keyframes plate-settle {
  from { transform: translate(-50%, -50%) scale(1.03); }
  to   { transform: translate(-50%, -50%) scale(1); }
}

/* STACKED (≤920px) — the blurred surround.
   The film is CONTAINED below 921px (see the sizing blocks under this), which
   necessarily leaves space around it. That space is filled by a heavily
   blurred copy of the poster rather than flat black.
   This is NOT the backdrop dropped in 1c6a507: that was a different sharp
   photograph competing with the film for attention. This is the film's own
   first frame, blurred past legibility into a colour field — one subject, and
   no extra request since the poster <img> is already fetched at high priority.
   It lives on ::after, not on .hero__media, because `filter: blur()` applies
   to an element's children — putting it on the block would blur the sharp film
   too. ::before is already the seam. No wrapper element is introduced, so the
   video and poster stay DIRECT children and `.v-live > .poster-img` keeps
   matching (video.js adds .v-live to the video's parentElement).
   z-index 0 sits below the poster (1) and film (2); scale hides the
   transparent fringe blur pulls in at the edges.
   Scoped to 620px: only the stacked phone/landscape layouts leave space around
   a contained film. Tablet now uses the desktop inset plate, whose surround is
   the seam vignette, not a blur. */

@media (max-width: 620px){
  .hero__media::after {
    content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
    background-image: var(--hero-poster, none);
    background-size: cover; background-position: 50% 35%;
    background-repeat: no-repeat;
    filter: blur(40px) brightness(.68) saturate(.95);
    transform: scale(1.12); }
}

/* STACKED SIZING — now phone-only (was ≤920px).
   Kept for the landscape-phone case further down, which still stacks a
   contained film. The portrait phone layout overrides all of this immediately
   below with the full-bleed band.
   `contain`, not `cover`: the film is a multi-scene montage, so no single
   object-position frames every cut — cropping is wrong in principle here, not
   merely badly tuned. */

@media (max-width: 620px){
  .hero__media { min-height: 0; aspect-ratio: auto;
    height: min(112vw, calc(78svh - var(--header-h))); }
  .hero__media .bgvid,
  .hero__media .poster-img,
  .hero__media .fallback-img {
    position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
    width: auto; height: 93%; max-width: 94%; aspect-ratio: 464 / 832;
    -o-object-fit: contain;
       object-fit: contain; -o-object-position: 50% 50%; object-position: 50% 50%; }
}

/* TABLET (621–920px) — inherits the DESKTOP two-column grid and inset plate.
   Under the old ≤920px scope this range stacked a contained portrait film in a
   full-width block: at 768×1024 the film rendered ~375px wide inside 768px,
   leaving ~51% of the block as blurred fill. The :has(.hero__caption) rule
   below was meant to offset the film left and balance it against a caption
   rail, but neither caption field is set on this site so it never applies and
   the film just sat dead-centre in empty space.

   Extending the phone's full-bleed `cover` band up here was measured and
   rejected: at 768–912px it is a 3.3–3.9× effective upscale at DPR2 with ~66%
   of the frame cropped — worse than the full-bleed treatment already dropped in
   round 2 (3.31× / 52%). Two columns keep the film contained at 1.1–1.6×, so it
   stays sharp, and put the CTAs beside it rather than a screen below.

   Only the values the desktop rules do not cover are set here. */

@media (min-width: 621px) and (max-width: 920px){
  /* The desktop floors are sized for a full-height column and would blow the
     block out at this width — .hero is clamp(560px,90vh,940px) and .hero__media
     is clamp(520px,86vh,1020px). Let both size to their content instead. */
  .hero { min-height: 0; }
  .hero__media { min-height: 0; height: auto; }

  /* The text column is W×1.05/2.05 — only 318px at 621px wide. The desktop
     side padding (up to 84px) would eat 62px of that, leaving 256px for a 48px
     headline. This leaves 275px at 621px and 340px at 768px. */
  .hero__text { padding: clamp(28px,4vw,56px) clamp(20px,3.5vw,40px); }

  /* Every hero clamp() bottoms out at its floor across this whole range —
     6.2vw of 768px is 47.6px, so it pins to 48px and a 621px tablet renders the
     headline identically to a 920px one while the layout width changes by 50%.
     This ramp actually varies across the range. */
  .hero__head { font-size: clamp(40px, 5.6vw, 62px); }

  /* One across: the cards are in the narrow text column now, not the full page
     width. Three across at 621px would be ~75px each. */
  .hero__stats { grid-template-columns: 1fr; }
}

/* The caption overlay is optional content (both its fields are empty on this
   site, so .hero__caption isn't rendered at all). When it IS set, give it a
   rail down the right on tablets and let the film shift left to make room —
   the offset only earns its keep when there's something opposite to balance
   it, so it's scoped to :has() rather than applied unconditionally. */

@media (min-width: 621px) and (max-width: 920px){
  .hero__media:has(.hero__caption) .bgvid,
  .hero__media:has(.hero__caption) .poster-img,
  .hero__media:has(.hero__caption) .fallback-img { left: 38%; }
  .hero__caption { left: auto; right: clamp(20px,3vw,40px);
    width: min(30%, 190px); bottom: clamp(20px,3vh,34px);
    flex-direction: column; align-items: flex-start; gap: 6px; }
}

/* PHONE (≤620px) — "framed & fused" (design doc 2b).
   The previous treatment stacked a contained film above a separate text block,
   which pushed the headline and both CTAs below the fold and made the two
   halves read as unrelated sections. Here the film is a full-bleed band across
   the top of the hero and the copy runs directly beneath it, tied together by
   a gradient that resolves the film into the carbon rather than ending it on a
   hard line.

   The copy does NOT overlap the film. An earlier revision pulled it up over the
   band with a negative margin (the "fused" treatment in the design doc); the
   client preferred the film uninterrupted. The cost of that choice is real and
   deliberate: at 390×844 the copy starts at 520px, so the CTAs sit below the
   fold and booking takes a scroll. Do not "fix" that by shrinking the band
   without asking — the full-height film is the point.

   The film goes to `cover` here — the ONLY place it is cropped. At 390px a
   contained 464×832 plate could not fill the width. `object-position` keeps the
   subject high in frame so the crop comes off the bottom.

   Desktop and tablet are untouched — the client signed off on those. */

@media (max-width: 620px){
  /* One block: a single column, film first. This MUST stay a flex (or grid)
     container — .hero__media comes SECOND in the DOM and is lifted above the
     copy by `order: -1`. `display: block` would drop `order` entirely and the
     film would fall back to its source position, rendering underneath the text
     and the service cards. */
  .hero { display: flex; flex-direction: column; position: relative;
    min-height: 0;

    /* How tall the film band is. 62svh with a 520px ceiling: the percentage
       keeps it proportional on small screens, the ceiling stops it running away
       on a tall phone where more height buys nothing.
       The copy sits BELOW this, not over it — see .hero__text. */
    --hero-band: min(62svh, 520px); }

  /* The band is a fraction of the viewport rather than of the film's own
     aspect: 2b puts the film at 56% of a 390×844 screen, with the copy taking
     the rest. svh (not vh) so mobile browser chrome does not push the CTAs off
     — the whole point of this layout is that they stay visible.
     The 470px ceiling stops the band running away on tall phones, where a bare
     56svh would push the CTAs down without showing meaningfully more film. */
  .hero__media { aspect-ratio: auto; height: var(--hero-band); min-height: 260px;
    /* flex-shrink:0 — without it the film is squeezed by the text below it
       (which is taller than the leftover space once the CTAs and cards are in)
       and the band collapses well under its set height. */
    flex: 0 0 auto; order: -1; }

  .hero__media .bgvid,
  .hero__media .poster-img,
  .hero__media .fallback-img {
    /* Full-bleed: inset:0 rather than the centred plate. `cover` crops rather
       than letterboxes, and 50% 32% holds Ajay in the upper-middle so the
       gradient and copy below take the crop instead of his head. */
    position: absolute; inset: 0; top: 0; left: 0;
    transform: none; width: 100%; height: 100%; max-width: none;
    aspect-ratio: auto;
    -o-object-fit: cover;
       object-fit: cover; -o-object-position: 50% 32%; object-position: 50% 32%; }

  /* The blurred poster surround has no job now the film is full-bleed — there
     is no space around it left to fill. */
  .hero__media::after { display: none; }

  /* plate-settle MUST be cancelled here, not merely overridden. Its keyframes
     carry translate(-50%,-50%) and it runs with `both`, so the fill outlasts
     the animation and keeps applying that transform — which would drag the
     now-full-bleed film half off the screen, exactly the failure the base
     rule's comment warns about. `transform: none` above cannot win against an
     animation fill, so the animation itself is removed. */
  .hero__media .poster-img,
  .hero__media .fallback-img,
  .hero__media .bgvid { animation: none; }

  /* (The seam gradient for this layout is overridden after the base
     .hero__media::before rule further down — it has equal specificity, so it
     has to come later in source order to win.) */

  /* Sits directly under the band, no overlap. Overriding the base padding
     entirely: that is a clamp() up to 104px vertically, which would open a
     visible gap between the film and the headline and break the run-on. */
  .hero__text { position: relative; z-index: 4;
    padding: 14px 24px 40px;
    max-width: none; }

  /* The headline is still the anchor of the screen, but the whole copy block
     (this + the subhead) has a hard budget: 100svh − nav − the 62svh film
     band ≈ 176px on a chrome-visible phone, and the film band is untouchable.
     The previous 13.5vw/58px scale needed ~217px and clipped the subhead at
     the fold; this scale + the tightened gaps above/below land the full
     headline and subhead inside the first frame. Capped in px so it cannot
     run away on a large phone. */
  .hero__head { font-size: clamp(38px, 11.5vw, 50px); line-height: .94;
    letter-spacing: -.035em; margin: 0; }

  /* Subhead gets 2b's accent rule down its left edge, which ties it to the
     headline instead of floating as loose body copy.
     14px is deliberate, not just "smaller": at 390px wide it lets the sentence
     break as two lines instead of three ("…build strength," / "improve
     fitness…"), which is what buys the first frame its last ~26px. If the
     copy ever gets longer, this wraps to three lines and the fold is at risk
     again — trim the sentence rather than shrinking the type below this. */
  .hero__sub { position: relative; margin: 10px 0 0; padding-left: 14px;
    font-size: 14px; line-height: 1.4; max-width: none; }
  .hero__sub::before { content: ""; position: absolute; left: 0; top: 2px;
    bottom: 2px; width: 2px; border-radius: 2px;
    background: linear-gradient(180deg, var(--ignite-300), rgba(212,168,124,0)); }

  /* Full-width stacked CTAs — thumb targets. */
  .hero__cta { display: flex; flex-direction: column; gap: 11px; margin-top: 22px; }
  .hero__cta .btn { width: 100%; }

  /* Service cards stay on mobile, below the CTAs, reached by scrolling. Kept
     deliberately: they are real content, not decoration. They live INSIDE
     .hero__text (hero.php), so they inherit its box — the margin here is just
     separation from the buttons above. */
  .hero__stats { grid-template-columns: 1fr;
    margin-top: 30px; padding-top: 26px; }
}

/* LANDSCAPE PHONE — a portrait film in a ~390px-tall viewport. Sizing by svh
   alone would leave it a sliver, so the block takes the full short viewport,
   the film is sized by height to stay portrait, and the text sits beside it
   rather than below. The caption has no vertical room here. */

@media (max-width: 920px) and (max-height: 520px) and (orientation: landscape){
  /* Two things match this rule, and it has to serve both:
     - a phone in landscape, UNDER 620px wide, where the fused portrait layout
       above also applies and must be undone (the overlap would drag the copy
       over a film that is no longer above it);
     - a short viewport BETWEEN 621 and 920px — a resized desktop window, a
       foldable, an iPad split-screen pane — where the tablet two-column rules
       apply but a full-height plate will not fit.
     Real tablets in landscape never match: an iPad mini landscape is 1024px
     wide. Side-by-side with a contained plate is right for both cases. */
  .hero { display: grid; grid-template-columns: 1fr 1fr; }
  .hero__media { order: 0; height: calc(100svh - var(--header-h));
    min-height: 0; max-height: none; }
  /* The blurred surround is defined at ≤620px only, so above that there is no
     ::after to reveal — restate it rather than just flipping display, or a
     621–920px landscape pane gets bare carbon around the plate. */
  .hero__media::after {
    content: ""; display: block; position: absolute; inset: 0; z-index: 0;
    pointer-events: none;
    background-image: var(--hero-poster, none);
    background-size: cover; background-position: 50% 35%;
    background-repeat: no-repeat;
    filter: blur(40px) brightness(.68) saturate(.95);
    transform: scale(1.12); }
  .hero__media .bgvid,
  .hero__media .poster-img,
  .hero__media .fallback-img {
    position: absolute; inset: auto; top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    width: auto; height: 92%; max-width: 96%; aspect-ratio: 464 / 832;
    -o-object-fit: contain;
       object-fit: contain; -o-object-position: 50% 50%; object-position: 50% 50%; }
  .hero__text { margin-top: 0; padding: clamp(24px,4vw,48px);
    align-self: center; }
  .hero__head { font-size: clamp(32px, 5.4vw, 44px); }
  .hero__caption { display: none; }
}

/* Seam — a bottom scrim for the caption's legibility, confined to the bottom
   strip. This is the DESKTOP AND TABLET seam (the phone overrides it below).
   Where the film is contained and a blurred surround sits behind it, that
   surround is already dimmed by the ::after brightness and a full-height scrim
   on top went muddy.
   Was rgba(14,15,18,…), a legacy near-black LIGHTER than --carbon (#000),
   which left a faint grey lip against the true-black page. */

.hero__media::before { content: ""; position: absolute; inset: 0;
  z-index: 3; pointer-events: none;
  background:
    /* Vignette: sinks the plate's corners into the carbon so the film sits IN
       the page rather than floating on it — and the corners are exactly where
       an upscale goes softest, so the darkening does double duty. */
    radial-gradient(120% 85% at 50% 45%, rgba(0,0,0,0) 44%, rgba(0,0,0,.42) 100%),
    /* Bottom seam, unchanged in effect: the old rule was a 42%-tall box with a
       0→100% ramp; measured against full height that is a 0→42% ramp. */
    linear-gradient(0deg, rgba(0,0,0,.62) 0%, rgba(0,0,0,0) 42%); }

/* PHONE seam (2b) — the fuse between film and copy. Must come AFTER the base
   rule above: same specificity, so source order decides. The vignette is
   dropped because the film is full-bleed here — there are no plate corners to
   sink — and replaced by a ramp that lands on solid carbon at the band's foot,
   which is what the overlapping headline sits on. */

@media (max-width: 620px){
  .hero__media::before {
    background: linear-gradient(180deg,
      rgba(0,0,0,.25) 0%,
      rgba(0,0,0,0) 50%,
      /* Ramp reduced again (round-5 feedback asked for less blending between
         the film and the headline): it now holds clear until 85% and peaks at
         .55 instead of .88, so the film ends near-crisply — only the last few
         percent resolve into the carbon the copy sits on, which is all that is
         needed to avoid a hard cut line. */
      rgba(0,0,0,0) 85%,
      rgba(0,0,0,.55) 97%,
      var(--carbon) 100%); }
}

/* Landscape phone keeps the contained plate, so it keeps the original seam. */

@media (max-width: 920px) and (max-height: 520px) and (orientation: landscape){
  .hero__media::before {
    background:
      radial-gradient(120% 85% at 50% 45%, rgba(0,0,0,0) 44%, rgba(0,0,0,.42) 100%),
      linear-gradient(0deg, rgba(0,0,0,.62) 0%, rgba(0,0,0,0) 42%); }
}

/* caption — overlaid in the Experience-index grammar */

.hero__caption { position: absolute; z-index: 4; left: clamp(20px,3vw,40px); right: clamp(20px,3vw,40px);
  bottom: clamp(16px,2.6vh,28px); display: flex; justify-content: space-between; align-items: baseline;
  gap: 18px; padding-top: 14px; border-top: 1px solid rgba(255,255,255,.22); }

.hero__caption .idx { color: var(--ignite-300); }

.hero__caption .metaline { color: rgba(245,242,236,.72); }

/* On phones the caption (when set) sits in the margin below the contained
   plate rather than crossing the subject, so it stays visible — it just needs
   pulling closer to the edge than the desktop offset. */

@media (max-width: 620px){
  .hero__caption { bottom: clamp(12px,2vh,20px); }
}

/* ---- COACH / ABOUT ---- */

.coach { display: grid; grid-template-columns: .9fr 1.1fr; gap: clamp(32px,5vw,72px); align-items: stretch; }

@media (max-width: 920px) { .coach { grid-template-columns: 1fr; } }

/* Photo height follows the text column on desktop; capped landscape-ish box when stacked. */

.coach__media { position: relative; }

.coach__img { width: 100%; aspect-ratio: 4/3; max-height: 440px; -o-object-fit: cover; object-fit: cover;
  -o-object-position: var(--focus, center 30%);
     object-position: var(--focus, center 30%); border-radius: 14px; display: block; }

@media (min-width: 921px) {
  .coach__media { min-height: 360px; }
  .coach__img { position: absolute; inset: 0; height: 100%; max-height: none; aspect-ratio: auto; }
}

/* about testimonial — ENB School quote under the bio */

.coach__quote { margin: 28px 0 0; padding: 4px 0 4px 22px;
  border-left: 3px solid var(--ignite); max-width: 58ch; }

.coach__quote p { margin: 0; font-size: 15.5px; line-height: 1.7;
  font-style: italic; color: var(--text-muted); }

.coach__quote cite { display: block; margin-top: 14px; font-style: normal;
  font-family: var(--font-display); font-size: 11.5px; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--ignite); }

/* ---- NOTABLE EXPERIENCE — editorial index ---- */

.explist { list-style: none; margin: 0; padding: 0; counter-reset: exp; }

.explist li { counter-increment: exp; position: relative;
  border-bottom: 1px solid rgba(255,255,255,.14);
  transition: background .25s var(--ease); }

.explist li > a { display: grid; grid-template-columns: 52px 1fr auto; align-items: baseline; gap: 18px;
  padding: 26px 4px; text-decoration: none;
  transition: padding-left .3s var(--ease); }

.explist li:first-child { border-top: 1px solid rgba(255,255,255,.14); }

.explist li > a::before { content: "0" counter(exp); font-family: var(--font-text);
  font-size: 13px; letter-spacing: .12em; color: var(--ignite-300); font-weight: 600; }

.explist .name { font-family: var(--font-head); font-weight: 700; letter-spacing: -.015em;
  font-size: clamp(24px, 3.2vw, 40px); line-height: 1.05; color: var(--bone);
  transition: color .25s var(--ease); }

.explist .meta { font-family: var(--font-text); font-size: 12px; font-weight: 600;
  letter-spacing: .16em; text-transform: uppercase; color: var(--ash-400); white-space: nowrap; }

@media (max-width: 620px){
  .explist li > a { grid-template-columns: 40px 1fr; }
  .explist .meta { grid-column: 2; margin-top: 6px; white-space: normal; }
}

.explist li:hover > a { padding-left: 14px; }

.explist li:hover .name { color: var(--ignite-300); }

.explist li::after { content: ""; position: absolute; left: 0; bottom: -1px; height: 1px;
  width: 0; background: var(--ignite); transition: width .45s var(--ease); }

.explist li:hover::after { width: 100%; }

/* ---- BOOKING CTA (light) ---- */

.booking { background: var(--bone); border-top: 1px solid var(--border); }

.booking__deposit { display: inline-flex; align-items: baseline; gap: 10px; flex-wrap: wrap;
  margin-top: 26px; padding: 14px 20px; border: 1px solid var(--border);
  border-left: 3px solid var(--ignite); background: var(--bone-100); }

.booking__deposit strong { font-family: var(--font-display); font-weight: 800;
  letter-spacing: .04em; text-transform: uppercase; font-size: 14px; color: var(--ignite); }

.booking__deposit span { font-size: 14px; color: var(--text-muted); }

.bookrows__note { font-size: 13.5px; color: var(--text-muted); max-width: 52ch; }

/* inline booking layout (from brand.css — the .bkm widget itself is Phase 3) */

.bookwrap { display: grid; grid-template-columns: minmax(280px, 1fr) minmax(0, 520px);
  gap: clamp(36px, 6vw, 96px); align-items: start; }

@media (max-width: 980px){ .bookwrap { grid-template-columns: 1fr; } }

.bookalts { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px 22px; margin-top: 30px;
  padding-top: 22px; border-top: 1px solid var(--border); }

.bookalts__label { flex-basis: 100%; font-family: var(--font-display); font-size: 11.5px;
  font-weight: 700; letter-spacing: .16em; text-transform: uppercase; color: var(--text-muted); }

.bookalts a { display: inline-flex; align-items: center; gap: 6px; font-family: var(--font-head);
  font-weight: 700; font-size: 17px; letter-spacing: -.01em; color: var(--carbon);
  text-decoration: none; transition: color .2s var(--ease); }

.bookalts a .arrow { color: var(--ignite); font-family: var(--font-text); font-size: 15px;
  opacity: 0; transform: translateX(-5px); transition: opacity .2s var(--ease), transform .25s var(--ease); }

.bookalts a:hover { color: var(--ignite); }

.bookalts a:hover .arrow { opacity: 1; transform: translateX(0); }

/* ===== REAL VIDEO / MEDIA ===== */

.bgvid { position: absolute; inset: 0; width: 100%; height: 100%; -o-object-fit: cover; object-fit: cover; -o-object-position: var(--focus, center); object-position: var(--focus, center); }

.media-img { width: 100%; height: 100%; -o-object-fit: cover; object-fit: cover; -o-object-position: var(--focus, center 30%); object-position: var(--focus, center 30%); display: block; }

/* poster-behind-video: video fades in only once it actually plays;
   in environments that can't play video, the poster shows instead. */

.has-poster { background-size: cover; background-position: var(--focus, center); background-repeat: no-repeat; }

.bgvid { opacity: 0; transition: opacity .7s var(--ease); }

.bgvid.v-on { opacity: 1; }

@media (prefers-reduced-motion: reduce){ .bgvid { transition: none; } }

/* real <img> poster layer — sharp, cacheable, LCP-friendly. Sits behind the
   video; where the video is suppressed the photo carries the section. */

.poster-img { position: absolute; inset: 0; width: 100%; height: 100%;
  -o-object-fit: cover;
     object-fit: cover; -o-object-position: var(--focus, center); object-position: var(--focus, center); z-index: -3; }

/* Inside the hero the poster is positioned by the inset-plate rule above
   (z-index 1, sitting under the film at 2, the seam at 3 and caption at 4). */

/* crossfade the poster out once the video is genuinely playing (video.js adds
   .v-live to the media column); it fades back if playback stops/pauses. */

.poster-img { transition: opacity .7s var(--ease); }

.v-live > .poster-img { opacity: 0; }

@media (prefers-reduced-motion: reduce){ .poster-img { transition: none; } }

/* ===== HERO FALLBACK PHOTOGRAPH =====
   Shown ONLY when the film cannot play. Outside the hero it needs the same
   base geometry as .poster-img; inside the hero the inset-plate rules above
   position it (z-index 0, under the poster at 1).
   The reveal works by hiding the POSTER, uncovering the photo already beneath
   it — the photo itself is never toggled, so there is no flash of it on the
   normal path. video.js sets .v-failed on .hero__media for a genuine error or
   a stall that never recovers; an autoplay REFUSAL is not a failure (the film
   is fine, it just needs a gesture), so that case keeps the poster. */

.fallback-img { position: absolute; inset: 0; width: 100%; height: 100%;
  -o-object-fit: cover;
     object-fit: cover; -o-object-position: var(--focus, center); object-position: var(--focus, center); z-index: -4; }

.hero__media.v-failed .poster-img { opacity: 0; transition: opacity .4s var(--ease); }

/* Belt and braces: a failed film must never sit visible over the photo,
   whatever .v-on was doing at the moment it broke. */

.hero__media.v-failed .bgvid { opacity: 0; }

/* ===== MEDIA REEL (template-parts/home/instagram.php) =====
   Was a 4-across grid under a heading, intro and follow card. Round-3 feedback
   asked for "a scroll through reel of media" with no Instagram references, so
   the header block is gone entirely and the tiles are a single scrolling row.
   Carbon band: still a deliberate dark break after the white booking section,
   and the treatment where the photography carries on its own. */

/* The rail bleeds full-width, but its first tile must still line up with the
   text margin every other section uses. .container is centred at max 1240px
   with --s-6 padding, so past 1240px the inset is the leftover gutter plus that
   padding; below it, just the padding. max() picks whichever applies. */

.reel { background: var(--carbon);
  --reel-inset: max(var(--s-6), (100vw - var(--container)) / 2 + var(--s-6)); }

/* The rail bleeds past .container to both viewport edges — a strip that stops
   inside a gutter reads as a finished grid, not as something that continues.
   scroll-padding lines the first and last tiles up with the page's text margin
   so the row still starts where every other section does.
   Momentum scrolling on iOS needs -webkit-overflow-scrolling; scroll-snap makes
   the drag settle on a tile rather than anywhere. */

.reel__rail { list-style: none; margin: 0; padding: 0 var(--reel-inset);
  display: flex; gap: 12px;
  overflow-x: auto; overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: var(--reel-inset);
  -webkit-overflow-scrolling: touch;
  /* Firefox + WebKit thin scrollbar, tinted to the section rather than the OS
     default light bar, which flashes bright against the carbon. */
  scrollbar-width: thin;
  scrollbar-color: var(--ink-700) transparent; }

.reel__rail::-webkit-scrollbar { height: 6px; }

.reel__rail::-webkit-scrollbar-track { background: transparent; }

.reel__rail::-webkit-scrollbar-thumb { background: var(--ink-700); border-radius: 3px; }

.reel__rail:hover::-webkit-scrollbar-thumb { background: var(--steel-500); }

/* The rail is focusable (tabindex=0) so it can be scrolled by keyboard — that
   focus has to be visible, or keyboard users land on it with no indication. */

.reel__rail:focus-visible { outline: 2px solid var(--ignite-300); outline-offset: 4px; }

/* Tiles are sized in vw with a px ceiling so several are always partly visible
   — a row where one tile fills the screen reads as a carousel, not a reel, and
   loses the "there is more, keep going" cue that makes people scroll. */

.reel__item { flex: 0 0 auto; scroll-snap-align: start;
  width: clamp(200px, 30vw, 320px); }

.reel__media { position: relative; display: block; aspect-ratio: 4 / 5;
  overflow: hidden; background: var(--ink-800); }

.reel__img { width: 100%; height: 100%; -o-object-fit: cover; object-fit: cover; display: block;
  transition: transform .6s var(--ease); }

/* Per-tile opt-out of cropping: a tall portrait loses height to the 4:5 frame,
   so "Fit whole image" letterboxes it instead. Zooming a letterboxed photo
   would push it past its own edges, so the hover scale is dropped there. */

.reel__media.is-contain .reel__img { -o-object-fit: contain; object-fit: contain; }

.reel__media.is-contain:hover .reel__img,
.reel__media.is-contain:focus-visible .reel__img { transform: none; }

.reel__media:hover .reel__img,
.reel__media:focus-visible .reel__img { transform: scale(1.04); }

a.reel__media:focus-visible { outline: 2px solid var(--ignite-300); outline-offset: 3px; }

/* 4:5 is a lot of height on a phone; squarer keeps more of the next tile in
   view, which is the whole point of the reel. */

@media (max-width: 620px){
  .reel__item { width: clamp(180px, 62vw, 260px); }
  .reel__media { aspect-ratio: 1; }
  .reel__rail { gap: 8px; }
}

@media (prefers-reduced-motion: reduce){
  .reel__img { transition: none; }
  .reel__media:hover .reel__img { transform: none; }
  /* Snapping yanks the viewport during a drag — proximity still settles tiles
     tidily without the abrupt correction. */
  .reel__rail { scroll-snap-type: x proximity; }
}
