/* audience — css/sections/audience.css · Figma D 3001:364 / M 3001:3202
   SECTION_BUILD owns this file. Scoped rules ONLY (.audience__*). No global selector, no
   :root, no .container, no template stylesheet — those are PAGE-SCAFFOLD's (base.css,
   tokens.css, components.css) and this section links none of them.

   Every number below is a node value from cache/audience.{desktop,mobile}.json, not the brief
   alone. Three section-scoped ramps live here because brief-page.md 4 carries no page token
   for them; each is declared in ALL THREE bands (mobile base / 768-1023 pseudo-tablet /
   1024+), because a scoped token missing from the pseudo-tablet block is the ragazzi-pdp2
   defect that shipped a badge 2x too large across 768-1023.

   The section is entirely static: no JS, no listener, no ARIA state, no template, no asset
   (slice 5.0 / D9 / D10). If a later stage finds itself adding an <img>, an <svg> or a click
   handler here, it has invented it. */

/* ============================================================================
   MOBILE base — 0-767, anchor 375. Section frame 3001:3202: vertical, gap 30, MIN/MIN,
   padding [0,0,0,0]. The 20px gutter is .container's, not this section's.
   NO mobile margin-top: on mobile all 10 body sections are children of one auto-layout
   column with gap 50 (brief 4.5) — the page owns that rhythm, not this section.
============================================================================ */
.audience {
  /* h2 -> cards            M 30 / D 40 (gap on 3001:3202 / 3001:364) */
  --aud-head-gap: clamp(26px, calc(30px + (var(--max-vw) - 375px) * 0.015), 61px);
  /* ordinal -> text block  M 15 / D 20 (gap on the card frames) */
  --aud-card-gap: clamp(13px, calc(15px + (var(--max-vw) - 375px) * 0.015), 31px);
  /* label -> body          M 10 / D 15 (gap on the text-block frames) */
  --aud-text-gap: clamp(9px, calc(10px + (var(--max-vw) - 375px) * 0.015), 20px);

  display: flex;
  flex-direction: column;
  gap: var(--aud-head-gap);
}

/* Heading 3001:3203 — 188 x 25 on mobile. It MUST HUG: a plain block <h2> measures 335
   against Figma's 188 (+147px on a mapped node). Per-node, NOT a page rule — about-course's
   mobile heading 3001:3172 really is a 335 fill, so nothing here generalises.
   Size/weight/leading/tracking/case/ink all come from .t-h2 (components.css), which is bound
   to the band: Oswald 600 #232323 lh 0.88 on mobile, Oswald 700 #252627 lh 1 at 1024+. */
.audience__title {
  width: fit-content;
  max-width: 100%;
  white-space: nowrap;   /* safe at 320px too: 27.2px type -> ~183px in a 280px content box */
}

/* Cards wrapper 3001:3204 (M) / 3001:366 (D) and the grid 3001:367 (D).
   Both are emitted on both layers so every Figma frame keeps a DOM counterpart (D8);
   neither has a fill or a stroke. On mobile the stack is a single column. */
.audience__cards {
  display: flex;
  flex-direction: column;
}

.audience__grid {
  display: flex;
  flex-direction: column;
  width: 100%;
  /* NO align-items here — the flex default is what makes the desktop row equal-height (D3).
     align-items: flex-start would give four ragged cards (248/286/305/267) and break the
     shared vertical rules into stubs. */
}

/* Card 3001:3205/3210/3215/3220 (M) · 3001:368/373/378/383 (D).
   PADDING IS 19px, NOT 20 (D2). Figma's stroke is CENTER-aligned, so half of it sits inside
   the padding box, while a CSS border ADDS to it. 19 + 1 lands six mapped boxes per card
   exactly (mobile card 1 = 19+43+15+111+19+2 = 209; desktop card 3 = 19+58+20+187+19+2 = 305;
   content width = 335-2-38 = 295 / 360-2-38 = 320). 20 + 1 misses every one of them by 2px
   and compounds to +5px over the mobile stack. Not clamped: 20 is identical on the 375 and
   the 1520 frame, i.e. a drawn constant (same class as --grid-gap).
   Radius 0 and no shadow — nothing on this page has either. */
.audience__card {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;   /* content is TOP-packed; slack sits at the bottom (D3).
                                    space-between would push the text to the card's bottom. */
  gap: var(--aud-card-gap);
  padding: 19px;
  border: var(--bw-hairline) solid var(--c-hairline);   /* #000000, NOT --c-ink #232323 */
  /* NO align-items: the default stretch is what makes .audience__body fill the 295/320
     content box, exactly as Figma reports it. */
}

/* THE SHARED 1px RULE (D1). All eight card frames carry a 1px CENTER stroke and their parents
   use gap 0 with exactly adjacent children, so adjacent strokes COINCIDE. Pixel-proven on the
   Figma renders: dark bands at exactly x = 0/360/720/1080/1440 and y = 0/209/452/712/950 —
   five rules of 1px per axis, never 2px. So the borders must COLLAPSE, not stack:
   border everywhere + a -1px margin pulling each card onto its neighbour's edge.
     - border + gap 0 and NO negative margin -> every internal rule renders 2px and the
       desktop row overruns 1440 by 3px;
     - "fixing" that with gap: 1px + borders on two sides -> a 1px white sliver. Figma has
       no gap at all; the cards touch. */
.audience__card + .audience__card { margin-top: -1px; }

/* Ordinal 3001:3206/... — a FIXED 60px box on BOTH layers (D7): the export reports width 60
   at 36px type (mobile) AND at 48px (desktop), which proves a fixed box, not a hug. A hugging
   <span> measures ~40/~51 and reads as a delta on eight mapped nodes. Height comes free from
   --text-stat x 1.2 (43.2 mobile / 57.6 desktop). NO text-transform — the ordinals carry no
   textCase in Figma. */
.audience__num {
  display: block;
  flex: 0 0 auto;
  width: 60px;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--text-stat);
  line-height: var(--lh-stat);
  letter-spacing: var(--ls-stat);
  color: var(--c-ink);
}

/* Text block 3001:3207/... (M 295 wide) · 3001:370/... (D 320 wide) — fills the card's
   content box; width comes from the card's default stretch. */
.audience__body {
  display: flex;
  flex-direction: column;
  gap: var(--aud-text-gap);
}

/* Label 3001:3208/... — Onest 700, --text-label (16 M / 20 D), lh 1, ls -0.08em M /
   -0.064em D, UPPER via CSS (the DOM keeps the string as typed: the gate compares
   `characters`, and pre-uppercased source is a documented false-delta, FD-79).
   It WRAPS. `white-space: nowrap` is forbidden here: at exactly 1024 the card content box is
   only ~202px against a ~185px label (8% headroom), and a miss with nowrap overflows the
   hairline on all four cards at once, while a miss with wrap costs one line the equal-height
   row absorbs. base.css resets h1-h6 to inherit, so every metric is set explicitly. */
.audience__label {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: var(--text-label);
  line-height: var(--lh-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--c-ink);
}

/* Body 3001:3209/... — Onest 600, lh 1.2, ls -0.03em.
   `pre-line` is REQUIRED, not decoration (D5): cards 02 and 03 end their Figma `characters`
   with a newline and Figma draws the resulting empty line box, which is why those paragraphs
   need 7 and 8 line boxes for 6 and 7 lines of text. pre-line collapses spaces but honours
   the newline, so textContent stays byte-equal to Figma AND the drawn empty line appears.
   Dropping it takes the desktop row 305 -> 286 and the mobile stack 950 -> 917. */
.audience__text {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--text-body-alt);
  line-height: var(--lh-body-alt);
  letter-spacing: var(--ls-body-alt);
  color: var(--c-ink);
  white-space: pre-line;
}

/* Card 4's mobile body is drawn at 16px while cards 1-3 are 14px (3001:3224 vs
   3001:3209/3214/3219) — shipped AS DRAWN per slice BA-1/D4, in a narrowly scoped token.
   The node's own height corroborates it: 114 / (16 x 1.2) = 5.94 -> 6 whole lines, whereas
   14px would need 6.79. Desktop is a uniform 16 across all four cards, so this token exists
   ONLY to differ below 1024 — at 1024+ it returns to --text-body-alt's own desktop band,
   or card 4 would stay flat-16 forever while its three siblings scale. */
.audience__card:nth-child(4) .audience__text {
  --aud-body-4: clamp(14px, calc(16px + (var(--max-vw) - 375px) * 0.015), 33px);
  font-size: var(--aud-body-4);
}

/* ============================================================================
   PSEUDO-TABLET 768-1023 — INTERPOLATED, nothing is drawn here. MANDATORY: a scoped token
   declared in only two bands silently inherits the wrong one across the third.
   Layout stays the mobile single-column stack — the 4-across row starts at 1024, not 768
   (D6): nothing is drawn in this band, and four cards across a ~728px content box would
   need ~142px cells that no layer draws.
============================================================================ */
@media (min-width: 768px) {
  .audience {
    --aud-head-gap: clamp(30px, calc(30px + (var(--max-vw) - 768px) * 0.025), 40px);
    --aud-card-gap: clamp(15px, calc(15px + (var(--max-vw) - 768px) * 0.025), 20px);
    --aud-text-gap: clamp(10px, calc(10px + (var(--max-vw) - 768px) * 0.025), 15px);
  }

  /* Flat 16 ON PURPOSE: M-base == D-base == 16, so there is genuinely nothing to interpolate
     across this band. This is NOT fluid-formulas "common mistake #2" (a collapsed ramp that
     should ramp) — but it MUST still be declared, or the mobile clamp leaks into the band. */
  .audience__card:nth-child(4) .audience__text {
    --aud-body-4: 16px;
  }
}

/* ============================================================================
   DESKTOP 1024+ — the drawn layer. 4 x 360 in ONE row inside the 1440 content box, gap 0,
   shared 1px borders, cards equal-height 305 by stretch. This row is MANDATORY and is never
   approximated with the mobile stack.
============================================================================ */
@media (min-width: 1024px) {
  .audience {
    --aud-head-gap: clamp(27px, calc(40px * (var(--max-vw) / var(--vw-base))), 51px);
    --aud-card-gap: clamp(13px, calc(20px * (var(--max-vw) / var(--vw-base))), 25px);
    --aud-text-gap: clamp(10px, calc(15px * (var(--max-vw) / var(--vw-base))), 19px);

    /* about-course -> audience is 84px on desktop, a REAL drawn value (brief 4.5 lists it as
       one of five genuine exceptions to the 120 default; the page total is 10011 and closes
       exactly, so normalising it to 120 shows up as cumulative drift). Desktop band only —
       below 1024 the page's own 50px stack rhythm applies untouched.
       D-min = round(84 x 1024/1520) = 57 · D-max = round(84 x 1920/1520) = 106.
       This REPLACES any page-level section rhythm rule (.audience beats a type selector);
       it must never be ADDED on top of a wrapper gap. */
    margin-top: clamp(57px, calc(84px * (var(--max-vw) / var(--vw-base))), 106px);
  }

  /* The mobile hug is released: 3001:365 legitimately fills the 1440 content box (1440 x 96,
     textAlignVertical CENTER — with lh 1 the box IS the line box). */
  .audience__title {
    width: auto;
    white-space: normal;
  }

  /* 3001:366 is horizontal with alignItems CENTER. That is INERT — it has a single child whose
     height defines the row. Keeping it here is faithful and harmless; carrying it down onto
     .audience__grid would size each card to its natural height and centre it, destroying the
     equal-height row and leaving visible gaps in the shared borders (D8 trap). */
  .audience__cards {
    flex-direction: row;
    align-items: center;
  }

  .audience__grid { flex-direction: row; }

  /* Figma reports flex-[1_0_0] on all four cards: four equal cells of the content box, not a
     hardcoded 360 (brief 1.1 — express desktop columns as a share of the content box, never
     as clamped px, so the 1024 seam and the --max-vw cap need no second set of numbers).
     4 x 360 = 1440 exactly at --vw-base. */
  .audience__card {
    flex: 1 1 0;
    min-width: 0;
  }

  /* The shared rule turns horizontal: collapse leftwards, not upwards. */
  .audience__card + .audience__card {
    margin-top: 0;
    margin-left: -1px;
  }

  /* Card 4 rejoins its siblings: byte-identical to --text-body-alt's desktop band. */
  .audience__card:nth-child(4) .audience__text {
    --aud-body-4: clamp(11px, calc(16px * (var(--max-vw) / var(--vw-base))), 20px);
  }
}
