/* how-it-works — section 6 of 11 · Figma heading `Как проходит`
   desktop 3001:388 (1440 x 752 @ 40,4523) · mobile 3001:3459 (335 x 2015.36)

   Written by SECTION_BUILD. Scoped rules ONLY: .how-it-works__* / .hiw-card*. No global
   selector, no :root, no .container override, no template stylesheet link — this section uses
   no template (slider / accordion / carousel / marquee / comparison-table all fail
   recognition on measured grounds, slice §5.0) and needs no JS: its interactive surface is
   provably EMPTY on both layers (no CTA, no link, no Vector, no icon, no state pair, no
   hidden node, no cornerRadius). A later stage that finds an interactive element here is
   inventing one.

   Layer shapes (they differ strongly — the desktop 4-up is MANDATORY, never the mobile stack):
     mobile  335 x 2015.36 — column: head(102) + 30 + grid(1883.36); grid = 4 cards stacked, gap 20
     desktop 1440 x 752   — column: head row(192) + 40 + grid(520); grid = 4 x 345, gap 20

   Container pattern A (slice §1b): the section carries no fill, no child bleeds, and
   padding is [0,0,0,0] on BOTH layers — the 20/40px gutter comes from `.container`
   (base.css), never from here, and never as a `padding` shorthand.

   Bands: mobile 0-767 (base) · pseudo-tablet 768-1023 · desktop 1024+.
   The head row goes side-by-side at 768 (slice §11 D-12: text-beside-text, so §7.4's 767
   drop point applies, not the 768 image-split guard). The card row stays 1-up until 1024
   exactly — no 2-up intermediate stage is invented anywhere.
*/

/* ============================================================================
   SECTION-SCOPED TOKENS — declared in ALL THREE BANDS.

   Declared on `.how-it-works` rather than `:root` on purpose: the GLOBAL-SCOPE LOCK bars a
   section stylesheet from writing `:root`, and every consumer of these values is a descendant
   of the section, so inheritance delivers them identically. Names are --hiw-* so they cannot
   collide with a page token or another slice's.

   All three bands are mandatory, not thorough: ragazzi-pdp2 shipped a badge 2x too large
   across 768-1023 because 2 of 51 scoped tokens were missing from exactly the middle block.

   Two tokens are deliberately FLAT, not clamped:
     --hiw-card-gap: 10  and  --hiw-pill-pad: 8  are drawn identical on both layers (all 8
     cards), which puts them in the same class as the page's --grid-gap ("20 on BOTH layers —
     fixed, do not clamp"). Turning them into three-band ramps adds motion the design has not
     got. The card->card gap is the PAGE token --grid-gap (20 both layers) and is referenced,
     never duplicated here — a private ramp shadowing a page token with an identical
     fingerprint was a real defect on ragazzi-mission.
============================================================================ */
.how-it-works {
  /* mobile band: clamp(M-min, calc(M-base + (max-vw - 375px) * 0.015), M-max) */
  --hiw-stack-gap:   clamp(26px, calc(30px + (var(--max-vw) - 375px) * 0.015), 61px);  /* head -> cards, D 40 */
  --hiw-head-gap:    clamp(17px, calc(20px + (var(--max-vw) - 375px) * 0.015), 41px);  /* heading <-> lead, D 40 */
  --hiw-pill-gap:    clamp(9px,  calc(10px + (var(--max-vw) - 375px) * 0.015), 20px);  /* pill -> body, D 15 */
  --hiw-pill-gap-03: clamp(13px, calc(15px + (var(--max-vw) - 375px) * 0.015), 31px);  /* card 03 only, see below */
  --hiw-pill-minh:   clamp(27px, calc(32px + (var(--max-vw) - 375px) * 0.015), 65px);  /* dark pill, D 56 */
  --hiw-ordinal:     clamp(31px, calc(36px + (var(--max-vw) - 375px) * 0.015), 74px);  /* the 01-04 numerals, D 64 */
  --hiw-body:        clamp(14px, calc(16px + (var(--max-vw) - 375px) * 0.015), 33px);  /* card body copy, D 16 */

  --hiw-card-gap: 10px;   /* NOT fluid — drawn 10 on both layers, all 8 cards */
  --hiw-pill-pad: 8px;    /* NOT fluid — drawn 8 on both layers, all 8 pills */
}

/* PSEUDO-TABLET 768-1023 — interpolated, nothing is drawn here. MANDATORY. */
@media (min-width: 768px) {
  .how-it-works {
    /* clamp(M-base, calc(M-base + (max-vw - 768px) * 0.025), D-base) */
    --hiw-stack-gap:   clamp(30px, calc(30px + (var(--max-vw) - 768px) * 0.025), 40px);
    --hiw-head-gap:    clamp(20px, calc(20px + (var(--max-vw) - 768px) * 0.025), 40px);
    --hiw-pill-gap:    clamp(10px, calc(10px + (var(--max-vw) - 768px) * 0.025), 15px);
    --hiw-pill-minh:   clamp(32px, calc(32px + (var(--max-vw) - 768px) * 0.025), 56px);
    --hiw-ordinal:     clamp(36px, calc(36px + (var(--max-vw) - 768px) * 0.025), 64px);
    /* --hiw-body and --hiw-pill-gap-03 COLLAPSE to a flat value here, and that is CORRECT,
       not the "min === base === max" mistake fluid-formulas.md warns about: both are drawn
       at the SAME number on both layers (body 16/16, card-03 pill gap 15/15), so the value
       genuinely does not change between the bands. Do not "fix" either into a ramp. */
    --hiw-body:        clamp(16px, calc(16px + (var(--max-vw) - 768px) * 0.025), 16px);
    --hiw-pill-gap-03: clamp(15px, calc(15px + (var(--max-vw) - 768px) * 0.025), 15px);
  }
}

/* DESKTOP 1024+ — proportional to --vw-base 1520, capped by --max-vw.
   clamp(D-min, calc(D-base * (max-vw / vw-base)), D-max) */
@media (min-width: 1024px) {
  .how-it-works {
    --hiw-stack-gap:   clamp(27px, calc(40px * (var(--max-vw) / var(--vw-base))), 51px);
    --hiw-head-gap:    clamp(27px, calc(40px * (var(--max-vw) / var(--vw-base))), 51px);
    --hiw-pill-gap:    clamp(10px, calc(15px * (var(--max-vw) / var(--vw-base))), 19px);
    --hiw-pill-gap-03: clamp(10px, calc(15px * (var(--max-vw) / var(--vw-base))), 19px);
    --hiw-pill-minh:   clamp(38px, calc(56px * (var(--max-vw) / var(--vw-base))), 71px);
    --hiw-ordinal:     clamp(43px, calc(64px * (var(--max-vw) / var(--vw-base))), 81px);
    --hiw-body:        clamp(11px, calc(16px * (var(--max-vw) / var(--vw-base))), 20px);
  }
}

/* ============================================================================
   SECTION FRAME
============================================================================ */

/* Section rhythm: the leading gap on BOTH layers is the page default (desktop 120.00 = the
   drawn `program -> how-it-works` boundary, mobile 50 = the parent column's own gap), so this
   is the page token verbatim, NOT a section-scoped override. The trailing non-default
   (101.00 -> pricing) belongs to `pricing` as the following section: applying it here as well
   would silently double that boundary to about 221px. */
.how-it-works {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--hiw-stack-gap);
  margin-block-start: var(--section-gap);
}

/* ============================================================================
   HEAD — heading + lead. Mobile: stacked column, gap 20. 768+: side by side, the lead
   BOTTOM-aligned to the heading block (3001:389 alignItems: MAX — the lead sits at y=144
   with height 48, so its bottom edge lands on the row's own 192).
============================================================================ */
.how-it-works__head {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--hiw-head-gap);
  width: 100%;
}

/* .t-h2 supplies family/size/case and the per-band weight + colour flip, which are drawn:
   Oswald 600 #232323 on mobile, Oswald 700 #252627 on desktop (brief §4.3b-1/-2, 10/10
   consistent per layer). Nothing here unifies them.
   nowrap is Figma's own `whitespace-nowrap` on both heading nodes; the desktop 2-line shape
   comes from the explicit <br>, never from wrapping. */
.how-it-works__title {
  white-space: nowrap;
}

/* The hard break exists only on the drawn desktop layer (3001:390 = "Как \nпроходит" in a
   690 x 192 box = 2 x 96). Mobile/pseudo-tablet render the single line `Как проходит`. */
.how-it-works__br {
  display: none;
}

/* .t-lead supplies --text-body-lg (M 16 / D 20 — the drawn sizes exactly). Two metrics
   differ from the page token and are overridden here, per slice §11 D-3: the drawn
   line-height is 120% and letter-spacing -3%, where §4.3 records 115% / -5% for that token.
   The page token itself is NOT edited — that is page-level territory. */
.how-it-works__lead {
  line-height: 1.2;
  letter-spacing: -0.03em;
}

@media (min-width: 768px) {
  .how-it-works__head {
    flex-direction: row;
    align-items: flex-end;      /* alignItems: MAX — bottom-aligned, not top */
    column-gap: var(--hiw-head-gap);
  }
  /* 690 + 40 + 710 = 1440. Measured on the node — NOT the 710 + 20 + 710 that brief-page
     §1.1's cross-check table lists (both close on 1440, so only the decomposition differs;
     building 710/20/710 makes the heading 20px too wide and the gap 20px short).
     The lead is the fixed side: 710 / 1440 = 49.3056% of the content box, a percentage so it
     survives the 1024 seam and the --max-vw cap without a second set of numbers. The heading
     takes the remainder. */
  .how-it-works__title {
    flex: 1 1 auto;
    min-width: 0;
  }
  .how-it-works__lead {
    flex: 0 0 49.3056%;
  }
}

@media (min-width: 1024px) {
  .how-it-works__br {
    display: inline;
  }
}

/* ============================================================================
   CARD GRID — mobile: 4 stacked, gap 20. Desktop: 4 x 345 in one row, gap 20.
============================================================================ */
.how-it-works__grid {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--grid-gap);          /* PAGE token: 20 on both layers, deliberately unclamped */
  width: 100%;
}

@media (min-width: 1024px) {
  .how-it-works__grid {
    flex-direction: row;
    /* alignItems: MIN on 3001:392 — the cards genuinely differ in height (501/501/520/501
       drawn) and must NOT be stretched to a common one. This is the one place the
       equal-height card default is opted out of. */
    align-items: flex-start;
    column-gap: var(--grid-gap);
  }
}

/* ============================================================================
   STEP CARD — five children in one order on both layers:
   ordinal · rule · media · pill(label) · body. No radius, no border, no shadow, no padding.

   Each card frame also carries justifyContent: CENTER in Figma. It is INERT once the height
   is natural, and translating it into `justify-content: center` would centre a stack that is
   top-aligned. Not translated.
============================================================================ */
.hiw-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--hiw-card-gap);
  width: 100%;
  border-radius: var(--r-flat);
}

@media (min-width: 1024px) {
  /* 4 equal columns: (1440 - 3 x 20) / 4 = 345 at a 1440 content box, and proportional above
     and below it. flex-basis 0 (not width) so the gap is subtracted before the split. */
  .hiw-card {
    flex: 1 1 0;
    width: auto;
    min-width: 0;
  }
}

/* ---- ordinal ---------------------------------------------------------------
   Mobile: the box HUGS the digits (31 for `01`, 35 for `02`-`04`) -> width auto.
   Desktop: all four are a fixed 104 x 77 with centred text (so `01` sits about 26px in from
   the card's left edge, not flush). 4 of 4 makes it deliberate, not drift — expressed as
   104/345 = 30.1449% so it tracks the card at any width. Desktop band ONLY: 768-1023 is the
   stacked 1-up layout, where 30% of a ~728px card would be a 219px box holding a 29px
   numeral.
   letter-spacing looks like cross-layer drift and is not: 36 x 0.0867 = 3.121 and
   64 x 0.0488 = 3.121 — the designer set the same absolute -3.1208px on both layers, and the
   em form reproduces it exactly at each band's base size. Per the page convention the mobile
   metric carries through the pseudo-tablet band; the desktop metric starts at 1024. */
.hiw-card__ord {
  display: block;
  width: auto;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--hiw-ordinal);
  line-height: 1.2;              /* real 120%: box 43 / font 36 = 1.194 (not Figma AUTO) */
  letter-spacing: -0.0867em;
  color: var(--c-ink-alt);
  text-align: center;
}

@media (min-width: 1024px) {
  .hiw-card__ord {
    width: 30.1449%;             /* = 104 / 345 -> 104px at a 1440 content box */
    letter-spacing: -0.0488em;   /* same absolute -3.1208px, at 64px */
  }
}

/* ---- rule (Line 36 x8) -----------------------------------------------------
   type: line, width 345/335 x height 0, stroke #252627b2, strokeWidth 1, alignment CENTER.
   The export tags it `exportAs: asset` and the MCP hands back an SVG, but that SVG is one
   <line> — 8 HTTP requests for a 1px rule is waste, and #252627 at 70% is already the page
   token --c-alt-70. NOT --c-hairline: the page's #000000 1px card border is a different
   value and this rule is not it.
   A zero-height CENTER stroke occupies 0 in Figma's layout but 1px in CSS flow. That 1px is
   the whole of the mobile delta (4 cards x 1px) and is accounted for, not fought — see the
   height table in the report. */
.hiw-card__rule {
  display: block;
  width: 100%;
  height: 0;
  border-top: 1px solid var(--c-alt-70);
}

/* ---- media -----------------------------------------------------------------
   ONE aspect-ratio serves both layers: desktop 345/247 = 1.39676, mobile 335/239.84 =
   1.39684, and Figma's codegen emits aspect-[345/247] on both. So width 100% + the ratio
   reproduces the drawn 247 and 239.84 exactly — and reserves the space, which is the point:
   the page is 10011px tall and image-led in four sections, so CLS is the real risk. Never
   hard-code height: 239.84px, and never drop the ratio for intrinsic sizing. */
.hiw-card__media {
  width: 100%;
  aspect-ratio: 345 / 247;
}

/* The ratio must be on the <img> ITSELF, not only on the wrapper. A wrapper with
   `aspect-ratio` and auto height gives its child no DEFINITE height to resolve `height: 100%`
   against, so the percentage falls back to auto, the img takes its own INTRINSIC ratio, and
   the wrapper then grows to fit it. Measured before this fix: card 01 desktop rendered
   345 x 488.02 (= 345 x 778/550, the raw source's ratio) and card 02 345 x 345 — 241px and
   98px too tall, and 34px/95px too tall on mobile. Cards 03/04 hid the bug completely,
   because their composed renders happen to BE 345 x 247. On a replaced element the ratio
   makes the box definite, and `cover` then crops exactly as Figma's scaleMode FILL does. */
.hiw-card__img {
  width: 100%;
  height: auto;
  aspect-ratio: 345 / 247;
  object-fit: cover;
}

/* Cards 03 and 04 stack a solid #ffffff UNDERNEATH the image in Figma (fills:
   ["#ffffffff", {image, CROP}]), and that white layer is VISIBLE because the image does not
   fill its box: card 03 renders a 512x512 square at 272x272 with 36.5px bars L/R, card 04 a
   1080x1906 portrait at 280x494 with 9.4% bars. They ship as Figma's composed node render
   with the bars baked in, so the box aspect equals the file's aspect and `cover` performs no
   crop. The backdrop mirrors the node's lower fill so a slow/failed image cannot show grey.
   Do NOT "fix" these to cover-with-object-position (kills the bars) or contain (wrong size:
   it would fit card 03 to 247x247 with 49px bars). */
.hiw-card--03 .hiw-card__media,
.hiw-card--04 .hiw-card__media {
  background-color: #ffffff;     /* the node's own lower fill, #ffffffff */
}

/* Card 02's image is DESATURATED in Figma and no stage could see it from the cache.
   `figma_export.py` drops image-fill `filters` entirely (FD-177, logged this run), so the
   downloaded original is the colour master while Figma draws it black-and-white. Scanned through
   the Figma Plugin API over both layer frames: 12 of the page's 40 image fills carry
   `filters.saturation = -1` — the 10 mentor photos, and exactly these two nodes:
     3001:405  card 02 desktop   hash 6852ff1e
     3001:3477 card 02 mobile    hash 6852ff1e
   Every other fill on the page, including this section's cards 01/03/04 (884b98d2, cd20812d,
   c4d79a65), is saturation 0 and correct in colour. Applied by the driver at integration,
   2026-08-12, after the builder's session had ended. */
.hiw-card--02 .hiw-card__img {
  filter: grayscale(1);
}

/* ---- text block: dark pill + body copy ------------------------------------- */
.hiw-card__text-block {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--hiw-pill-gap);
  width: 100%;
}

/* Mobile card 03 really is drawn at 15 while the other three are 10 — verified on the export
   and on live Figma (3001:3485.gap = 15). It is drawn, so it ships as drawn. Do not average
   the four to 11.25 and do not "correct" card 03 down to 10. On desktop all four are 15, so
   this override is a no-op there by construction. */
.hiw-card--03 .hiw-card__text-block {
  gap: var(--hiw-pill-gap-03);
}

/* The pill is a normal in-flow child, not an overlay: a full-width #232323 bar butted
   against the body copy, radius 0, no border, no shadow.
   min-height, never height: mobile cards 03/04 draw their label at 319 = 335 - 8 - 8, i.e.
   the content box with ZERO slack, so `wrap` is the designed fallback and a fixed height
   would clip a 2-line label instead of growing the pill.
   One rule reproduces all four desktop pills: cards 01/02 carry a hard h-[56px] with a
   20px single-line label centred at y=18 = (56-20)/2, i.e. 20px of deliberate slack; cards
   03/04 reach 56 naturally because their labels wrap to 2 lines (8 + 40 + 8). */
.hiw-card__pill {
  display: flex;
  align-items: center;
  width: 100%;
  padding: var(--hiw-pill-pad);
  min-height: var(--hiw-pill-minh);
  background-color: var(--c-ink);
  border-radius: var(--r-flat);
}

/* Size/weight/case come from --text-label (M 16 / D 20, Onest 700, UPPER) — the drawn
   values. letter-spacing does NOT: brief-page §4.3 assigns --text-label's tracking (M -8% /
   D -6.4%) and even names `Делаешь на своём бренде`, but every one of the 8 label nodes is
   drawn at 0% on BOTH layers. The gate compares width and -6.4% on 20px Onest 700 is about
   1.28px per character, so the drawn value wins over the inferred page mapping (§11 D-4). */
.hiw-card__pill-label {
  font-family: var(--font-body);
  font-weight: 700;
  font-size: var(--text-label);
  line-height: 1;                /* real 100%: box 20 / font 20 = 1.0, not Figma AUTO */
  letter-spacing: 0;
  text-transform: uppercase;
  color: #ffffff;                /* the node fill, #ffffffff */
  white-space: normal;           /* serves all four: 01/02 have ~50px slack, 03/04 wrap to 2 lines by design */
}

/* Labels 03 and 04 are FILL-width text nodes on BOTH layers, not hugging ones: 319 = 335-8-8
   on mobile and 329 = 345-8-8 on desktop, i.e. the pill's content box with ZERO slack —
   which is what lets the desktop pair wrap to the drawn 2 lines (label height 40 = 2 x 20).
   Labels 01 and 02 hug their text (Figma 221/242 mobile, 276/302 desktop) and are left alone. */
.hiw-card--03 .hiw-card__pill-label,
.hiw-card--04 .hiw-card__pill-label {
  flex: 1 0 0;
}

/* --hiw-body, not a page token: the card body is 16px on BOTH layers, and no page token
   matches both bands at once (--text-body-alt is M 14 / D 16, --text-body-lg is M 16 / D 20).
   Binding one element to two different page tokens per band is how a token silently inherits
   the wrong band across the third. */
.hiw-card__text {
  width: 100%;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--hiw-body);
  line-height: 1.2;
  letter-spacing: -0.03em;
  color: var(--c-ink);
}
