/*
 * Retreat landing — Guide-bio sections (decision-log #23, build-tracker.md
 * "🎨 Guide-bio sections — Variant A", 2026-09-01)
 *
 * Replaces the two `[kdpc_bio_modal]` dialogs (retired this build) with two
 * FULL SECTIONS rendered by `[kdpc_bio_section]` (inc/cpt-bio.php) off the
 * same `kdpc_bio` CPT data — no content migration, only a new render mode.
 *
 * Figma nodes (file FQLacTBUz4BDUx5IiRRXEl, page "design"), metadata +
 * get_design_context both pulled 2026-09-01 (VARIANT A, Alain's pick — see
 * decision-log #23 / build-tracker's open-questions resolution):
 *   Karen — 2065:2, 1440x827, media LEFT, carries the eyebrow + H2 (moved
 *     here from patterns/retreat-guides.php, which collapses to a bare
 *     video block — build-tracker checklist item).
 *   Peter — 2065:18, 1440x665, media RIGHT, no header, carries the TEDx
 *     credential.
 *
 * ⚠️ MEDIA PANEL SIZE — Alain revised this TWICE post-build (2026-09-01,
 * same day): 400x711 (original comp) -> 280x498 -> FINAL 320x569. All
 * still true 9:16 (320/569 = 0.5624 vs 9/16 = 0.5625 — nothing crops).
 * Kept as ONE tunable custom property, `--retreat-bio-media-width`
 * (declared on `.retreat-bio` below) — Alain may change this again, and
 * every dimension (width, aspect-ratio-driven height, flex-basis) derives
 * from that single value. Do not hardcode 320 (or any width) a second time
 * anywhere in this file.
 *
 * Geometry (get_metadata, exact node coordinates, both frames, re-verified
 * against the FINAL 320x569 media size):
 *   Section padding-block: 48px top/bottom both frames (827 = 48 + 82
 *     header + 80 gap + 569 row + 48; 665 = 48 + 569 row + 48) — i.e. the
 *     STANDARD var(--retreat-section-pad) rhythm every other retreat
 *     section uses (guides.css/logistics.css precedent), not a bespoke
 *     value, EXCEPT Peter's bottom (see .retreat-bio--peter below).
 *   Header (Karen only): eyebrow h26 -> H2 top gap 8px = var(--space-3xs).
 *     Header -> row gap: exactly 80px = var(--space-80) (existing token,
 *     already used by what-this-isnt.css's own top padding).
 *   Row: media 320x569 (Karen x0, Peter x896) <-> copy 806 wide, gap
 *     computed both frames = exactly 90px = var(--retreat-col-gap)
 *     (existing token/fallback, guides.css/logistics.css precedent,
 *     UNCHANGED by the media-width revisions). Row height 569 both; copy
 *     block (468 Karen / 410 Peter) is vertically CENTERED in the row
 *     (offset = (569-content)/2 exactly, both frames) — align-items:
 *     center reproduces this without a manual offset.
 *   Copy column: name-row -> first paragraph gap 24px; paragraph -> next
 *     paragraph gap 24px (both frames, every para pair) — 2px from the
 *     page-override --space-sm (22px), same adoption-tolerance class as
 *     the rest of this build (decision-log #12 rounding precedent).
 *   Name-row: name -> credentials gap 16px = exact var(--space-xs) match.
 *     Peter's credentials group: LinkedIn icon -> "TEDx" gap 16px, same
 *     token.
 *   Media label centered both axes in the media box (get_metadata: label
 *     center = box center, both frames, at every size Alain tried) — same
 *     aria-hidden placeholder-label pattern as guides.css/logistics.css's
 *     "VIDEO" panels, but here the label is the guide's FIRST NAME
 *     ("KAREN" / "PETER") — matches the retired bio-modal's own
 *     `.retreat-bio-modal__photo-label` treatment (this is deliberately
 *     the SAME visual language: navy, uppercase, --font-xl, centered).
 *
 * get_design_context (both nodes, colors/type):
 *   Eyebrow: #2383eb =~ var(--color-primary), 22px = var(--font-xl),
 *     tracking 0.9px (the shared .eyebrow class already carries this).
 *   H2 "two humans, still on the path.": #1c2161 = var(--color-retreat-navy),
 *     40px = var(--font-3xl), Rubik SemiBold, green period via the shared
 *     .retreat-mark utility (marks.css) — same recipe as every other
 *     retreat H2.
 *   Guide name ("Karen Bramhill" / "Peter Georgariou"): SAME size as the
 *     section H2 — 40px = var(--font-3xl), Rubik SemiBold, navy. This is a
 *     genuine design choice (not a bug): the name reads as a second
 *     heading, not the smaller 22px card-style name the old bio-modal used.
 *   LinkedIn credential: 30px circle, bg #02c17f = var(--color-success)
 *     (exact match, same token the retired bio-modal used), white "in"
 *     glyph. Reused the bio-modal's own inline-SVG LinkedIn mark verbatim
 *     (cpt-bio.php) rather than the comp's literal "in" text glyph — same
 *     visual result, already WebKit-fill-hardened (decision from that
 *     file's review round 1, finding #5), no reason to re-derive it.
 *   TEDx credential (Peter only, decision-log #21's has_tedx/tedx_url data
 *     model UNCHANGED): the comp renders this as literal styled TEXT
 *     ("TEDx", Rubik SemiBold 22px = var(--font-xl), color #e62b1e) — NOT
 *     the raster tedx-logo.webp asset the retired bio-modal used. Built
 *     as text per pixel-match fidelity (a rasterized logo would not
 *     reproduce this comp's typography). #e62b1e has no theme token (this
 *     single-accent palette carries no red) — literal value at its one
 *     call site below, same token-over-literal exception class as
 *     --radius-story-panel (token-overrides.css) or this file's own 9/16
 *     aspect-ratio; token-overrides.css itself is NOT in this item's
 *     authorized shared-file lane, so this stays local rather than
 *     becoming a new page-scoped custom property. CONTRAST (code-review
 *     round 1, 2026-09-01): #e62b1e on white computes to 4.44:1 — passes
 *     WCAG AA only via the large-text (>=18.66px bold) exemption, which
 *     this 22px-semibold text qualifies for; it does NOT clear the 4.5:1
 *     normal-text minimum. Alain's call: leave the colour, it's the TEDx
 *     brand mark, not a free design choice — recorded here as a SIGNED-OFF
 *     decision, not an accident. Flagged again in build-tracker.md.
 *   Body paragraphs: Roboto Slab Regular, 18px = var(--font-md) exact
 *     match, line-height 1.6 (comp-measured, explicit non-token value —
 *     same precedent as what-this-isnt.css's __intro line-height). Comp
 *     samples #333; routed through var(--color-text-body) instead, same
 *     tokens-not-hex call every other real-copy block in this build makes
 *     (logistics.css, what-this-isnt.css).
 *
 * Media content priority (VIDEO > PHOTO > LABEL): both guide posts (537
 * Karen / 538 Peter) already carry `kdpc_bio_video_id` (559/560) — the
 * comp's flat placeholder panel is what an UNDATA'd guide would show, not
 * what these two guides render today. Reused the retired bio-modal's own
 * battle-tested video>photo>label priority (inc/cpt-bio.php's
 * kdpc_bio_render_media()) rather than forcing the flat placeholder for
 * guides who already have real media — this is the build-tracker's own
 * still-OPEN "media slot: video, photo, or both?" question, resolved here
 * as "show what the CPT already has"; flagged in the handoff for Alain,
 * not silently decided. object-fit: cover is used on the video/photo fill
 * (a deliberate divergence from bio-modal.css's own intrinsic-ratio
 * treatment — that box was content-driven/flexible, THIS box is a
 * comp-fixed geometry that must hold regardless of the source media's own
 * ratio).
 *
 * Selectors scoped under `.retreat-bio` only (decision-log #12 /
 * theme-conventions.md) — the `.retreat-page` ancestor already supplies the
 * token-override cascade. Alias tokens only: var(--font-*), var(--space-*),
 * var(--color-*), var(--radius-*) — no raw hex/px where a token exists.
 *
 * RESPONSIVE: no mobile Figma frame (figma-analysis-2026-08.md §Design
 * gaps) — derived, flagged for designer review same as every other
 * undesigned retreat breakpoint. Stacks to a single column at <=768px.
 *
 * DOM ORDER = media-first, ALWAYS, both sections (code-review round 1,
 * 2026-09-01, Alain's ruling, WCAG 2.4.3 — SUPERSEDES an earlier version
 * of this build): the first pass put media SECOND in the DOM for Peter's
 * media-right desktop layout (matching Figma 2065:18's own layer order)
 * and used a mobile-only `.stack-reverse` utility (`column-reverse` at
 * <=768px) to restore video-first once the row stacked. That desynced
 * keyboard focus order from visual order specifically on mobile — a
 * keyboard user would tab Peter's LinkedIn/TEDx credentials (visually
 * BELOW the video) before reaching the video (visually ABOVE them), since
 * `column-reverse` only reverses the PAINT order, not the DOM/focus order.
 * Fixed by inverting the mechanism instead of patching it: media is FIRST
 * in the DOM unconditionally now (inc/cpt-bio.php's
 * kdpc_bio_section_shortcode()), and Peter's desktop media-right layout is
 * achieved with `.row-reverse` (assets/css/utilities.css, renamed from
 * `.stack-reverse` — generic and theme-wide on purpose, per Alain's
 * original ask, "reuse this rather than writing a second one") — it flips
 * the row to `flex-direction: row-reverse` ONLY while it's actually laid
 * out as a row (>=769px), so DESKTOP shows copy-left/media-right (the
 * comp, unchanged) while the row's *source* order — and therefore its
 * stacked <=768px order AND its focus order at every width — is
 * media-then-copy for BOTH sections. Karen needs no class: her DOM order
 * already matches her desktop visual order (media left).
 */

.retreat-bio {
  /* SINGLE tunable source for the media panel's width — see file header
     re: Alain's two post-build revisions. Every media dimension below
     (width, flex-basis, aspect-ratio-driven height) derives from this one
     value; change it here only. */
  --retreat-bio-media-width: 320px;

  max-width: 1216px;
  margin: 0 auto;
  padding-block: var(--retreat-section-pad);
  padding-inline: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-80); /* comp-verified header->row gap (Karen); a no-op on Peter's single child */
}

/* ── Pre-finale breath (build-tracker.md, 2026-09-01) ──
 * With the two bio sections inserted between "what this isnt" and Join,
 * what-this-isnt.css's own deliberate ~220px "big breath before the finale
 * band" padding-bottom moves here, onto the LAST bio section, so Join still
 * gets its oversized break. See what-this-isnt.css's own header comment for
 * the exact math this value reproduces (unchanged: --space-2xl + --space-100,
 * both already carrying their own responsive chains).
 */
.retreat-bio--peter {
  padding-bottom: calc(var(--space-2xl) + var(--space-100));
}

/* ── Header (Karen only — nodes 2065:3/4/5) ── */
.retreat-bio__header {
  display: flex;
  flex-direction: column;
  gap: var(--space-3xs); /* 8px eyebrow -> heading, comp-verified, same as every other section */
}

.retreat-bio__eyebrow {
  color: var(--color-primary);
  margin: 0;
}

.retreat-bio__heading {
  font-family: var(--font-heading);
  font-weight: var(--fw-semibold);
  font-size: var(--font-3xl);
  line-height: 1.15;
  color: var(--color-retreat-navy);
  margin: 0;
}

/* Green punctuation mark uses the shared .retreat-mark utility
   (sections/retreat/marks.css) — no per-section duplicate here. */

/* ── Row: media + copy ── */
.retreat-bio__row {
  display: flex;
  align-items: center; /* comp-verified: copy column is vertically centered against the media box, both frames, at every media-width Alain has tried */
  gap: var(--retreat-col-gap, 90px); /* fallback: editor canvas has no .retreat-page ancestor (S3/S8 precedent) */
}

.retreat-bio__media {
  /* Fixed basis off the single tunable --retreat-bio-media-width (declared
     on .retreat-bio above) — NOT a proportional/percentage basis. The
     panel is now a deliberately small, fixed-size element (320px, was
     400px pre-revision) rather than a large proportional column, so it
     holds its own size through the 1025-1240px squeeze band and lets the
     copy column (flex: 1 1 auto below) absorb any width deficit instead. */
  flex: 0 0 var(--retreat-bio-media-width);
  width: var(--retreat-bio-media-width);
  aspect-ratio: 9 / 16; /* comp is true 9:16 at every width Alain has tried (320/569 = 0.5624 vs 0.5625) — ratio decoupled from the exact px so a future width change needs no ratio math */
  border-radius: var(--radius-md); /* 20px — matches comp exactly */
  overflow: hidden; /* clips real video/photo content to the radius */
  background: var(--color-grey-200); /* closest alias to comp's #e2e8ef, same call as every other retreat placeholder panel */
  display: flex;
  align-items: center;
  justify-content: center;
}

.retreat-bio__media-placeholder {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

.retreat-bio__media-label {
  font-family: var(--font-heading);
  font-weight: var(--fw-semibold);
  font-size: var(--font-xl); /* comp 22px = exact --font-xl match */
  letter-spacing: 0.9px; /* comp tracking value */
  text-transform: uppercase;
  text-align: center;
  color: var(--color-retreat-navy);
  margin: 0;
}

/* .retreat-bio__media-embed added 2026-09-04 — YouTube iframe shares the
   attachment-video sizing exactly; the media slot is already aspect-ratio
   9/16, which is the native Shorts ratio, so no ratio work was needed. */
.retreat-bio__media-embed,
.retreat-bio__media-video,
.retreat-bio__media-img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover; /* fills the fixed media box regardless of the source's own ratio — see file header re: bio-modal.css's differing (intrinsic-ratio) treatment */
}

/* object-fit above is inert on an iframe (it applies to replaced elements
   like img/video, not to a browsing context) — the embed fits because the
   media slot is already 9/16 and Shorts are natively 9/16. Iframes also
   carry a UA default border, which the shared rule does not clear. */
.retreat-bio__media-embed {
  border: 0;
}

/* ── Video facade (click-to-load) ──────────────────────────────────────────
 * Added 2026-09-04 (Alain): a bare YouTube embed paints its own large play
 * button dead centre, which on a vertical Shorts portrait sits on the guide's
 * face. No player parameter removes it — controls=0 hides the bottom bar and
 * keeps the centre button — so the fix is to show the guide's own photo until
 * someone asks for the video. assets/js/bio-video.js does the swap.
 *
 * Only rendered when the bio HAS a featured image; without one there is no
 * poster to show and cpt-bio.php falls through to the plain iframe.
 */
.retreat-bio__facade {
  position: relative;
  display: block;
  width: 100%;
  height: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  overflow: hidden;
  border-radius: inherit; /* the media slot may be rounded — don't square it off */
}

.retreat-bio__play {
  position: absolute;
  /* Bottom-LEFT, not centred: the whole point is to leave the face clear.
     --space-xs from each edge keeps it inside the slot's rounding. */
  left: var(--space-xs);
  bottom: var(--space-xs);
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  height: 40px;
  padding: 0 var(--space-xs);
  border-radius: var(--radius-pill);
  background-color: var(--color-success);
  color: var(--color-retreat-navy);
  font-family: var(--font-heading);
  font-size: var(--font-sm);
  font-weight: var(--fw-semibold);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  line-height: 1;
  transition: transform 0.15s ease, background-color 0.15s ease;
}

.retreat-bio__facade:hover .retreat-bio__play {
  transform: translateY(-2px);
}

.retreat-bio__facade:focus-visible {
  outline: 3px solid var(--color-success);
  outline-offset: 3px;
}

.retreat-bio__play svg {
  display: block;
  flex-shrink: 0;
}

@media (prefers-reduced-motion: reduce) {
  .retreat-bio__play {
    transition: none;
  }
  .retreat-bio__facade:hover .retreat-bio__play {
    transform: none;
  }
}

.retreat-bio__copy {
  flex: 1 1 auto; /* absorbs whatever width the fixed-basis media panel doesn't take — see .retreat-bio__media */
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-sm); /* comp 24px name-row/paragraph gaps — 2px tolerance vs the page-override --space-sm (22px), same adoption class as elsewhere in this build */
}

.retreat-bio__name-row {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-xs); /* comp 16px, exact match */
}

.retreat-bio__name {
  font-family: var(--font-heading);
  font-weight: var(--fw-semibold);
  font-size: var(--font-3xl); /* comp 40px = exact --font-3xl match, same size as the section H2 — see file header.
    DESKTOP/1024 ONLY: at <=768px this bare <h3> is caught by token-overrides.css's
    `.retreat-page h3 { font-size: var(--font-xl) !important }` mobile counter-layer
    (landing at 20px). That's the SAME mobile size as logistics.css's __stat-title,
    where it's correct (a stat title is a peer of other stat titles). Here it isn't:
    measured live at 375px, section H2 = 28px / this name = 20px / body copy = 17px —
    the guide's NAME, the anchor of the whole section, sat only 3px above its own body
    copy. Code-review round 1 (2026-09-01, Alain's ruling) REVERSES this file's
    earlier "do not fix locally" guidance for exactly this element — see the explicit
    mobile override further down, scoped to `.retreat-bio__name` only; the shared
    counter-layer itself is untouched for every other h3 it governs. */
  line-height: 1.2;
  color: var(--color-retreat-navy);
  margin: 0;
  /* defensive vs theme.json h3 element styles (S3/S10/bio-modal precedent):
     Title Case names need the uppercase + letter-spacing reset. */
  text-transform: none;
  letter-spacing: normal;
}

.retreat-bio__credentials {
  display: flex;
  align-items: center;
  gap: var(--space-xs); /* comp 16px linkedin -> TEDx gap (Peter only) */
}

.retreat-bio__linkedin {
  display: inline-flex;
  width: 30px;
  height: 30px;
  flex-shrink: 0;
}

.retreat-bio__linkedin svg {
  display: block;
  width: 30px;
  height: 30px;
}

.retreat-bio__linkedin svg rect {
  fill: var(--color-success); /* comp #02c17f = --color-success exact match */
}

.retreat-bio__linkedin svg path {
  fill: var(--color-white);
}

.retreat-bio__tedx {
  font-family: var(--font-heading);
  font-weight: var(--fw-semibold);
  font-size: var(--font-xl); /* comp 22px = exact --font-xl match */
  color: #e62b1e; /* comp literal — TED brand red, no theme token; contrast note in file header (signed off by Alain) */
  text-decoration: none;
}

/* Hover/focus affordance (code-review round 1, 2026-09-01): the linked
   and non-linked TEDx renders (kdpc_bio_render_media()'s <a>/<span> arms)
   shared identical styling with no :hover/:focus state, so a linked
   credential was indistinguishable from plain text until clicked/tabbed.
   Scoped to the `<a>` arm only — the `<span>` (has_tedx without a URL)
   isn't interactive, so it gets no affordance. Same treatment
   guides.css:160 gave the retired "read bio" link. */
a.retreat-bio__tedx:hover,
a.retreat-bio__tedx:focus-visible {
  text-decoration: underline;
}

.retreat-bio__text {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm); /* comp 24px inter-paragraph gap — same tolerance as .retreat-bio__copy above */
}

.retreat-bio__text p {
  font-family: var(--font-body);
  font-weight: var(--fw-regular);
  font-size: var(--font-md); /* comp 18px = exact --font-md match */
  line-height: 1.6; /* comp-measured, explicit non-token value (what-this-isnt.css __intro precedent) */
  color: var(--color-text-body); /* comp samples #333; routed through the semantic body token per theme-conventions.md tokens-not-hex */
  margin: 0;
}

@media (max-width: 1240px) {
  .retreat-bio {
    padding-inline: 24px; /* matches .retreat-hero__inner's / .retreat-how's <=1240 gutter */
  }
}

@media (max-width: 1024px) {
  .retreat-bio__row {
    gap: var(--space-lg);
  }
}

@media (max-width: 768px) {
  .retreat-bio {
    padding-inline: var(--space-xs);
  }

  .retreat-bio__row {
    flex-direction: column;
    align-items: stretch;
    gap: var(--space-lg);
  }

  .retreat-bio__media {
    /* flex: 0 0 auto (code-review round 1 fix), not 1 1 auto — width is
       already pinned explicitly below, so grow/shrink was inert and only
       invited a future aspect-ratio fight. 0 0 states the intent. */
    flex: 0 0 auto;
    width: var(--retreat-bio-media-width);
    max-width: 100%; /* guards against the media panel outgrowing a very narrow viewport */
    margin: 0 auto;
  }

  .retreat-bio__copy {
    flex: 1 1 auto;
    width: 100%;
  }

  .retreat-bio__name-row {
    gap: var(--space-sm);
  }

  /* Mobile name-size override (code-review round 1, 2026-09-01, Alain's
     ruling) — see .retreat-bio__name's own comment above for the full
     "3px above body copy" finding. `.retreat-page .retreat-bio__name`
     (two classes, specificity 0,2,0) beats token-overrides.css's
     `.retreat-page h3` counter-layer (0,1,1) outright, so this wins
     without needing to match !important-for-!important on a coin flip —
     it does anyway, for the same "utility/override must not silently lose
     if cascade order ever shifts" reason used elsewhere in this build.
     25px: no page token lands in the 24-26px range Alain asked for: closest
     candidates are --font-xl (20px @768) and --font-2xl (32px, unstepped)
     — both further off than a literal value. Restores a real 3-step mobile
     hierarchy: H2 28px -> name 25px -> body 17px. */
  .retreat-page .retreat-bio__name {
    font-size: 25px !important;
  }
}
