/*
 * Retreat landing — Section 11 "Join / Founding Cohort" (item S11, build-tracker.md)
 * THE FINAL SECTION. Full-bleed blue grain band (F1 `.retreat-band--blue` +
 * `.retreat-band--rounded`), id="join" anchor — 4 CTAs across the page point here
 * (build-tracker.md hygiene note).
 *
 * Nodes: eyebrow 90:229 "JOIN" (white 22px uppercase, NOT the hero's white/16px
 * exception — get_design_context confirmed `text-[22px] text-white uppercase`, the
 * same size as every other section's standard eyebrow, only recolored white for
 * the band). H2 90:228 "the founding cohort." (white + green period via
 * .retreat-mark, marks.css). Body copy 90:226 + 90:227 (2 text nodes, each
 * containing 2 <p>s internally at a comp-measured 16px/--space-xs gap — same
 * "mb-[16px]" pattern as retreat-leave-with.php; VERBATIM copy including the
 * comp's own "$2,495" next-cohort mention, which is intentionally a DIFFERENT
 * number from the founding price $1,950 below — read the copy: the founding
 * cohort gets the current $1,950 rate, the NEXT cohort (after this one sells
 * out) goes to $2,495. Not a typo, not a conflict — do not "fix" it). Price
 * lockup: $1,950 90:232 (Rubik SemiBold 600, --color-accent #ffdb38 exact,
 * var(--font-price) — the 80/56/44 page token already defined in
 * token-overrides.css, consumed here unmodified) + subtitle 90:233 "our all-in
 * founding rate" (white, comp 23px ≈ var(--font-xl) 22px, negligible drift, token
 * over literal per convention). Stat 90:256 "Everything included" (white, 20px =
 * var(--font-lg) exact) + desc 90:257 "All sessions, materials, your room, and
 * every meal." (white, 16px = var(--font-sm) exact) — SAME copy as S8/logistics'
 * "Everything included" stat, reused intentionally. CTA 90:234-236 "Reserve your
 * spot" — navy pill, full width of its own column (measured node w=520.8, comp
 * right edge lands short of the section's outer right edge — the price column is
 * narrower than the copy column, not a layout bug).
 *
 * ── VERIFIED DEVIATIONS FROM BUILD BRIEF (Figma ground truth overrides the brief's
 *    assumptions — both confirmed via cropped pixel inspection of refs/v1-full.png,
 *    not guessed) ──
 *
 * 1. TOP/BOTTOM corner treatment is the OPPOSITE of what the brief specified. The
 *    brief said "square the TOP corners exactly like the hero's fix... bottom
 *    corners keep r20" (pattern-matched from hero.css, where the hero sits FLUSH
 *    under the sticky header with zero gap — rounded top corners there read as an
 *    accidental notch). Pixel-sampled all 4 corners of the join band in the comp:
 *    TOP-LEFT and TOP-RIGHT are clearly ROUNDED (curve visible against the white
 *    section above — there IS a normal white gap above this band, unlike the
 *    hero), while BOTTOM-LEFT and BOTTOM-RIGHT are perfectly SQUARE (hard
 *    right-angle edge, band flows directly into the dark-navy footer with zero
 *    gap and zero curve). This is a mid-page-to-footer band, not a
 *    header-to-first-band case — the hero's specific notch problem doesn't apply
 *    here at all, and the comp's own corners confirm the opposite treatment.
 *    Implemented below: default `.retreat-band--rounded` 100px (all corners,
 *    R1-2 fix — see token-overrides.css's --radius-band) is kept for the
 *    top, and the bottom two corners are squared with the same
 *    scoped-selector/specificity technique hero.css uses (class + class beats the
 *    utility's own class+class at equal specificity via source order — this file
 *    globs after bands.css).
 *
 * 2. The "yellow bar, hero stat treatment" the brief described for the
 *    "Everything included" stat does not exist in the comp. get_metadata on the
 *    only geometry node in the 90:256-259 range that could be a bar (90:259,
 *    90:258 doesn't resolve/was likely deleted) returned a plain WHITE
 *    (`bg-white`) 4×114px rounded rectangle positioned BETWEEN the price lockup
 *    and the stat block (x1016, between price's right edge ~1002 and the stat
 *    title's left edge 1043) — a vertical DIVIDER separating the two, not a
 *    yellow accent bar belonging to the stat text the way hero.css's
 *    `.retreat-hero__stat::before` works. Implemented as a white `::before` on
 *    `.retreat-join__stat` (same flex-bar mechanism as hero/who-for, just white
 *    instead of yellow, and positioned as a divider rather than a per-stat
 *    accent) — no yellow anywhere in this section, which is comp-correct.
 *
 * Layout: two-column row (copy ~54% / price-col ~46%, --retreat-col-gap 90px,
 * align-items: center — verified via geometry: left column's vertical midpoint
 * (eyebrow-top to body2-bottom) ≈ 7585, right column's midpoint (price-top to
 * CTA-bottom) ≈ 7597, an 12px match that confirms center-alignment, same
 * mechanism as .retreat-hero__row). Price-col: lockup row (price-group + white
 * divider + stat, gap var(--space-xs) each side of the divider) above the
 * full-width CTA.
 *
 * Band vertical padding is DERIVED (thumbnail-resolution measurement only — no
 * Figma node bounds the whole band as a single parent, per figma-analysis's
 * "file is FLAT" warning) — flag for live visual re-check at self-verify.
 *
 * Selectors scoped under `.retreat-join` only (decision-log #12 /
 * theme-conventions.md) — `.retreat-page` ancestor already supplies the
 * token-override cascade; this file only consumes var(--font-*)/var(--space-*),
 * never redeclares them.
 *
 * CTA href: pending decision-log #4b (direct-buy vs application-first, OPEN
 * as of this fix) — markup uses href="#" plus a
 * `.retreat-join__cta--href-pending` marker class (unstyled, stub only) so C1
 * can grep-and-swap in the real URL in one pass once #4b resolves: (a) if
 * direct-buy wins, swap in the Stripe Payment Link URL; (b) if
 * application-first wins, swap in the application-form URL instead. The
 * marker name deliberately doesn't commit to either branch.
 */

/* ── Outer band ── */
.retreat-join {
  margin: 0;
}

/* Bottom corners squared (verified deviation #1 above) — default
   .retreat-band--rounded gives 100px on all four corners (R1-2 fix,
   2026-08-15: node-verified via 90:29's exact `rounded-bl-[100px]/
   rounded-br-[100px]` for this band's top-adjacent slice, plus a pixel-fit
   of the rendered corner curve — was wrongly r20 pre-R1-2); this section
   keeps the TOP 100px (comp-correct, unlike the hero) and only zeroes the
   bottom pair. Equal-specificity + later source order (join.css globs after
   bands.css) wins the cascade, same technique as hero.css's top-corner
   override. */
.retreat-join.retreat-band--rounded {
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
}

.retreat-join__inner {
  /* Matches every other section's .retreat-*__inner: max-width + margin:auto
     only, whitespace from centering (global.css .container convention). */
  max-width: 1216px;
  margin: 0 auto;
  padding-top: var(--space-80); /* measured ~85px, thumbnail-derived, see docblock */
  padding-bottom: var(--space-2xl); /* measured ~148px against the taller left
    column — closest token, thumbnail-derived, flag for live re-check */
}

@media (max-width: 1240px) {
  .retreat-join__inner {
    padding-inline: 24px;
  }
}

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

/* ── Two-column row ── */
.retreat-join__row.wp-block-columns {
  gap: var(--retreat-col-gap, 90px); /* fallback: editor canvas has no
    .retreat-page ancestor (S3 precedent) */
  /* R2 gate finding (2026-08-16): this align-items: center was never
     actually winning — WP core prints an inline `.wp-block-columns {
     align-items: initial !important; }` block-supports reset (confirmed
     live via CSSOM: cssRules[].style.getPropertyPriority('align-items')
     === 'important'), which beats this non-!important rule regardless of
     selector specificity. Kept here as the documented intent (and it's
     harmless — every column that doesn't opt out still stretches, matching
     the comp for a single-item row), but the actual fix lives on
     .retreat-join__price-col below via align-self, which core's reset does
     NOT touch (core only resets align-items on the row, never align-self
     on the children — confirmed no competing !important rule on
     .wp-block-column's align-self in the same CSSOM sweep). Same
     mechanism Gutenberg's own per-column "vertical alignment" toolbar
     control uses (.wp-block-column.is-vertically-aligned-center {
     align-self: center; }, also not !important) — this is that pattern,
     just applied via our own class instead of the editor UI toggle. */
  align-items: center;
}

/* ── Left column: eyebrow + H2 + body ── */
.retreat-join__eyebrow {
  /* Band exception (verified via get_design_context — 90:229 renders
     text-white, not the standard .retreat-*__eyebrow blue #2380E5 treatment
     every other section uses). Size stays the standard --font-xl (22px) from
     token-overrides.css's `.retreat-page .eyebrow` rule — only color changes. */
  color: var(--color-white);
  margin: 0;
}

.retreat-join__heading {
  font-family: var(--font-heading);
  font-weight: var(--fw-semibold);
  font-size: var(--font-3xl); /* 40 / 34@1024 / 28@768 via token-overrides.css */
  line-height: 1.15;
  color: var(--color-white);
  margin: var(--space-3xs) 0 0; /* eyebrow -> H2, 8px measured exact */
}
/* Green period uses the shared .retreat-mark utility (marks.css) — no
   per-section duplicate. */

.retreat-join__body {
  margin-top: var(--space-sm); /* H2 -> body, 19px measured, nearest token */
}

.retreat-join__body-block {
  font-family: var(--font-body);
  font-weight: var(--fw-regular);
  font-size: var(--font-md);
  line-height: 1.55; /* theme.json global body default, matches comp's 28/18 ratio */
  color: var(--color-white);
}

.retreat-join__body-block + .retreat-join__body-block {
  margin-top: var(--space-lg); /* between the two paragraph blocks, 46px measured */
}

.retreat-join__body-block p {
  margin: 0;
}

.retreat-join__body-block p + p {
  margin-top: var(--space-xs); /* comp's own "mb-[16px]" between paragraphs
    within one text node, matches retreat-leave-with__body-group exactly */
}

/* ── Right column: price lockup + stat + CTA ── */
/* R2-3 fix (2026-08-16): the real vertical-centering mechanism — see the
   .retreat-join__row header comment above for why align-items: center on
   the row doesn't win. Left column (.retreat-join__copy) is untouched —
   it's the taller of the two (eyebrow through body content sets the row's
   own cross-size), so it needs no align-self; this column alone opts out
   of the row's stretch default and centers within that height instead.
   Verified live: left content midpoint (eyebrow-top to body-bottom) and
   right content midpoint (price-top to CTA-bottom) match within <1px at
   1440 (comp evidence: 90:229-236 left / 90:256-259 right measure ~12px
   apart, well inside float-rounding of a true center-match). */
.retreat-join__price-col {
  align-self: center;
}

.retreat-join__lockup {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  /* nowrap, not wrap (finding #4, live-measured): with flex-wrap: wrap, the
     two-item hypothetical-width line-break test (price-group + stat) blows
     the budget well before 1024 — even at 1440 desktop the stat gets pushed
     onto its own row below the price the moment its unconstrained content
     width doesn't fit, re-reading the divider as a left accent bar instead
     of the comp's single-row lockup. nowrap + .retreat-join__price-group's
     flex-shrink: 0 (never shrink the price numeral) + .retreat-join__stat's
     min-width: 0 (let it shrink below its own content's intrinsic width,
     the flex default min-width: auto otherwise blocks that) keeps this one
     row at every width down to the 1024 stacking breakpoint; the stat-copy
     max-width below does the rest of the work by giving the desc paragraph
     somewhere to wrap into instead. Verified no wrap live at
     1440/1100/1024. */
  flex-wrap: nowrap;
}

.retreat-join__price-group {
  flex-shrink: 0; /* see .retreat-join__lockup nowrap comment above */
}

.retreat-join__price {
  font-family: var(--font-heading);
  font-weight: var(--fw-semibold);
  font-size: var(--font-price, 80px); /* 80 / 56@768 / 44@480 — page token,
    token-overrides.css. fallback: editor canvas has no .retreat-page
    ancestor (S3 precedent) */
  line-height: 1;
  color: var(--color-accent); /* #FFDB38 exact match */
  margin: 0;
}

/* ── Tax note (Alain, 2026-08-24) ──
 * Sits between the price numeral and its subtitle. Stripe's product is
 * configured tax-behaviour EXCLUSIVE (stripe-payment-link.md), so tax is
 * added on top of $1,950 at checkout — this line is what makes that true
 * on the page. Body font, not the heading face the price/subtitle use:
 * it's a qualifier, not part of the lockup. */
.retreat-join__price-tax {
  font-family: var(--font-body);
  font-weight: var(--fw-regular);
  font-size: var(--font-md);
  line-height: 1.2;
  color: var(--color-white);
  margin: var(--space-3xs) 0 0; /* price -> tax note */
}

.retreat-join__price-sub {
  font-family: var(--font-heading);
  font-weight: var(--fw-semibold);
  font-size: var(--font-xl); /* comp 23px, negligible drift from 22px token */
  color: var(--color-white);
  margin: var(--space-2xs) 0 0; /* price -> sub, 13px measured, near-exact */
}

.retreat-join__stat {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  min-width: 0; /* see .retreat-join__lockup nowrap comment above — flex's
    default min-width: auto would otherwise floor this at its unconstrained
    content width and defeat the nowrap fix */
}

/* White divider bar between the price lockup and the stat (verified deviation
   #2 above — comp-confirmed white, not the hero's yellow per-stat accent).
   Explicit height, not align-self: stretch: the divider is a CHILD of
   .retreat-join__stat (the stat ROW, not the .retreat-join__lockup row that
   also contains the price-group), so stretch only ever matches the stat's
   own cross-size (~80-90px, title+desc text height) — visibly short of the
   comp. Own cropped-pixel measurement of refs/v1-full.png (join region,
   price-digit top y1831 to divider bottom y1857 in the 352px-wide reference,
   scaled to real px) puts the divider at ~114px tall, matching the
   price-lockup's own height (price digits + subtitle stacked), not the
   stat's — comp-confirmed distinct from stretch behavior, so height must be
   set explicitly. No token lands on 114px; nearest is --space-2xl (120px,
   ~5% drift, token-over-literal per convention, theme-conventions.md).
   --space-2xl is itself one of tokens.css's fluid-spacing vars (120 / 80@1024
   / 60@768, tokens.css:96-122) — live-verified this DOES step down with it
   (120px desktop, 80px @1024, presumably 60px @768/375, not separately
   re-checked in this file since it's inherited, not redeclared here), which
   reads as correct: no mobile Figma frame exists to measure an independent
   mobile value against (figma-analysis-2026-08.md §Design gaps), and letting
   it ride the same fluid scale as everything else in the price-lockup
   (--font-price, etc.) keeps the divider proportionate at every breakpoint
   instead of needing its own arm. */
/* Hygiene pass: shared box geometry (content/display/width/flex-shrink)
 * moved to sections/retreat/stat-bar.css. Colour overrides the shared
 * default (yellow) via --retreat-bar-color — this is the WHITE divider
 * variant (see the block comment above). Height/radius stay local — see
 * stat-bar.css's header for why. */
.retreat-join__stat::before {
  --retreat-bar-color: var(--color-white);
  height: var(--space-2xl); /* ~114px comp-measured, nearest token 120px */
  border-radius: var(--radius-pill);
}

.retreat-join__stat-copy {
  /* Wrap fix, part 2 (see .retreat-join__lockup's nowrap comment for part 1
     — the mechanism that keeps this row from wrapping at all). Unconstrained,
     the desc paragraph ("All sessions, materials, your room, and every
     meal.") renders as one 358px-wide unbroken line — wider than the row
     budget at any two-col width down to 1024, and wider than looks right
     against the comp either way (comp shows it 2-line-wrapped: "All
     sessions, materials," / "your room, and every meal."). max-width caps
     it so the desc wraps in place; min-width: 0 (flex's own default is
     min-width: auto, i.e. never shrink below content) is what lets this
     item actually respect that cap instead of forcing its parent row wider.
     206px is the narrowest width that still holds the title ("Everything
     included", measured natural width ~197px via canvas measureText) on one
     line while still forcing the longer desc paragraph to wrap. Verified no
     lockup wrap + this exact line split live at 1440/1100/1024. */
  max-width: 206px;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs); /* title -> desc, 12px measured exact */
}

.retreat-join__stat-title {
  font-family: var(--font-heading);
  font-weight: var(--fw-semibold);
  font-size: var(--font-lg); /* 20px exact — matches comp, no override needed */
  color: var(--color-white);
  margin: 0;
}

.retreat-join__stat-body {
  font-family: var(--font-body);
  font-weight: var(--fw-regular);
  font-size: var(--font-sm); /* 16px ≈ theme --font-sm (15px), negligible drift */
  color: var(--color-white);
  margin: 0;
}

/* ── CTA — full width of its own column (comp-verified, not just a mobile
   full-width treatment like who-for/how-it-works) ── */
.retreat-join__cta {
  margin-top: var(--space-md); /* lockup -> CTA, 28px measured, nearest token */
}

.retreat-join__cta .wp-block-button,
.retreat-join__cta .wp-block-button__link {
  width: 100%;
}

.retreat-join__cta .wp-block-button:not(.is-style-outline) .wp-block-button__link {
  background: var(--color-retreat-navy);
  transition: filter 0.2s ease; /* matches hero/logistics/who-for hover treatment */
}

.retreat-join__cta .wp-block-button:not(.is-style-outline) .wp-block-button__link:hover {
  filter: brightness(0.85);
}

/* ── Focus ring on the band (hero precedent — bare :focus-visible's default
   outline-color is --color-primary blue, low-contrast against this band's
   blue gradient) ── */
.retreat-join a:focus-visible,
.retreat-join .wp-block-button__link:focus-visible {
  outline-color: var(--color-white);
}

/* ══════════════════════════════════════
   RESPONSIVE (no mobile Figma frame — derived per figma-analysis-2026-08.md
   §Design gaps, same stacking mechanism as .retreat-hero__row)
   ══════════════════════════════════════ */

@media (max-width: 1024px) {
  /* Same two-fight rationale as hero.css: core's `flex-wrap: nowrap
     !important` on .wp-block-columns (782px+ query) and its un-stacked
     `flex: 1 1 0 !important` both need matching !important + the inline
     flex-basis from the width attrs also needs overriding when stacking. */
  .retreat-join__row.wp-block-columns {
    flex-wrap: wrap !important;
    row-gap: var(--space-lg);
  }
  .retreat-join__row .retreat-join__copy,
  .retreat-join__row .retreat-join__price-col {
    flex: 1 1 100% !important;
  }
}

@media (max-width: 480px) {
  /* Price lockup stacks (price+sub above, divider+stat below) — narrow
     enough at this width that the 80px→44px price numeral plus the stat
     text side-by-side would crowd the 375px viewport. Derived, not measured
     (no mobile frame). */
  .retreat-join__lockup {
    flex-direction: column;
    align-items: flex-start;
  }
}
