/* ═══════════════════════════════════════════════════════════════
   KOVΔ · Кузня справжності
   Brand stylesheet — ink + gold + cream on black.
   ═══════════════════════════════════════════════════════════════ */

/* ═══ DESIGN TOKENS ═══
   Everything the site renders sits on one warm axis: cream → gold →
   bronze → ember. The hero (KOVΔ + prompt) sets the key — every other
   surface picks a stop on the same axis, never leaves the family.

   Site is dark-first. Light mode not implemented.

   Breakpoint reference (kept hardcoded — CSS @media does not read vars):
     --bp-sm:  560px   (phones)
     --bp-md:  820px   (small tablets)
     --bp-lg: 1100px   (large tablets / small laptops)                */
:root {
  --ink:       #0A0907;
  --ink-bg:    #050508;
  --gold:      #D4B896;        /* 212, 184, 150 */
  --gold-hi:   #EFD9B1;        /* 239, 217, 177 */
  --cream:     #f5f5f5;
  --cream-hi:  rgba(255, 255, 245, 0.95);

  /* RGB triplets — used inside rgba(var(--x), a) glows so any surface
     can pull the same warmth the hero uses. */
  --cream-rgb:      255, 250, 240;   /* canonical cream triplet for rgba() */
  --rgb-cream:      255, 250, 240;   /* legacy alias — kept for back-compat */
  --rgb-gold:       212, 184, 150;
  --rgb-gold-hi:    239, 217, 177;
  --rgb-amber:      255, 220, 170;
  --rgb-ember:      246, 170,  76;
  --rgb-ember-hi:   255, 210, 145;   /* bright ember — neon tube core */
  --rgb-ember-deep: 188, 110,  30;

  /* Cream opacity buckets — for surfaces that pick standard stops on
     the cream axis. Most legacy values use bespoke alpha (0.55 / 0.65 /
     0.75…) and stay verbatim via rgba(var(--cream-rgb), X). */
  --cream-3:  rgba(var(--cream-rgb), 0.03);
  --cream-10: rgba(var(--cream-rgb), 0.10);
  --cream-20: rgba(var(--cream-rgb), 0.20);
  --cream-50: rgba(var(--cream-rgb), 0.50);
  --cream-90: rgba(var(--cream-rgb), 0.90);

  /* Canonical 6-layer warm-neon halo — same anatomy as the brightest
     verbs/tags. Inherits the surrounding --accent / --accent-hi pair so
     every card picks its own colour. Used for the loudest accent text. */
  --text-neon-stack:
    0 0 1px  rgba(var(--accent-hi), 1),
    0 0 4px  rgba(var(--accent-hi), 0.95),
    0 0 12px rgba(var(--accent),    0.7),
    0 0 28px rgba(var(--accent),    0.42),
    0 0 56px rgba(var(--accent),    0.2),
    0 0 96px rgba(var(--accent),    0.08);

  /* Z-index ladder — only the seven canonical bands. Exotic numbers
     (5, 6, 7, 11, 12, 50, 110, 9600+ …) keep their literal values
     because they encode finer ordering inside one band. */
  --z-base:      0;
  --z-content:   1;
  --z-fixed:     10;
  --z-overlay:   100;
  --z-modal:     9000;
  --z-toast:     9500;
  --z-skip-link: 9999;

  /* Animation timing tokens — reserved for future consolidation of
     keyframe/transition magic numbers. Existing animations keep their
     verbatim durations so visuals are identical; new code should reach
     for these tokens first. */
  --dur-breath: 3.2s;       /* slow neon-tube pulse */
  --dur-drift:  18s;        /* ambient long drift */
  --dur-fade:   350ms;      /* default cross-fade */
  --ease-out:   cubic-bezier(0.2, 0.7, 0.3, 1);

  /* Path accents — three stops on the same warm axis so the forge
     cards read as one family. Each has a -hi twin that's lighter and
     more luminous: it fills the hot neon-tube core, while the base
     accent drives the outer halo. Without -hi, moonstone/gold neon
     would read flat; ember already has enough intrinsic brightness. */
  --path-observer:      198, 192, 178;  /* moonstone — quiet warm cream */
  --path-observer-hi:   236, 232, 218;  /* pearl */
  --path-apprentice:    212, 184, 150;  /* gold */
  --path-apprentice-hi: 246, 226, 188;  /* gold-light */
  --path-smith:         216, 140,  78;  /* bronze / forge ember */
  --path-smith-hi:      252, 200, 140;  /* warm amber-bronze */

  --ease-silk: cubic-bezier(0.25, 0.0, 0.15, 1);
  --dur-collapse: 0.8s;

  --font-display: 'Unbounded', sans-serif;
  --font-mono:    'Unbounded', sans-serif;
  --font-serif:   'Cormorant Garamond', Georgia, serif;

  /* ═══ TYPOGRAPHY SCALE — single source of truth ═══
     Every text on the site picks ONE of these tokens. Mobile (375px)
     baseline → desktop (1280px+) ceiling. Each step ≈1.2× larger,
     so the scale reads as a natural rhythm. clamp() handles fluid
     scaling — no per-breakpoint font-size overrides downstream. */
  --fs-3xs:  clamp(10px, 0.4vw + 8.5px,  12px);  /* status, refs */
  --fs-2xs:  clamp(11px, 0.4vw + 9.5px,  13px);  /* small tags, footer-year, legal */
  --fs-xs:   clamp(12px, 0.4vw + 10.5px, 14px);  /* doc-link, mono caps, button labels */
  --fs-sm:   clamp(13px, 0.5vw + 11.2px, 16px);  /* hints, footer, cta-verb, body-small */
  --fs-base: clamp(16px, 0.6vw + 13.6px, 18px);  /* body, prompt-input, form labels (≥16 = no iOS zoom on focus) */
  --fs-md:   clamp(17px, 0.8vw + 14px,   22px);  /* subtitle, paragraph lead, sub */
  --fs-lg:   clamp(20px, 1.2vw + 15.5px, 28px);  /* book paragraphs, lesson-verb */
  --fs-xl:   clamp(24px, 1.8vw + 17px,   36px);  /* support-verb, bento-verb */
  --fs-2xl:  clamp(28px, 2.4vw + 19px,   44px);  /* doc-title, book-title, lesson-preview */
  --fs-3xl:  clamp(32px, 3.4vw + 20px,   52px);  /* choice-verb, hero verbs */
  --fs-hero: clamp(64px, 8vw   + 36px,   104px); /* KOVΔ logo */

  /* ═══ CARD TOKENS — wider mobile↔desktop amplitude ═══
     Choice-cards + support-card collapse to 4 horizontal pills filling
     100svh on phones, so their verbs need a tighter floor than the
     desktop scale. These tokens grow more aggressively with viewport so
     desktop still gets a hero-sized verb without crushing mobile layout. */
  --fs-card-verb: clamp(20px, 3vw   + 8px,    38px);  /* mobile 20-23 → desktop 32-38 */
  --fs-card-name: clamp(15px, 1vw   + 12px,   22px);  /* mobile 15-16 → desktop 20-22 */

  /* ═══ SUBTITLE — single token for EVERY italic-serif body line ═══
     One size for every poetic subtitle on the site, so .choice-sub,
     .choice-class-act, .support-sub, .bento-sub, .bento-body,
     .lesson-preview__summary, .lesson-book__yako-summary, donate-form
     .sub / .desc / .custom-label / .cta-sub, and donate.html .thanks-body
     all share identical scale. No surface speaks louder than another. */
  --fs-subtitle: clamp(13px, 0.8vw + 10.5px, 20px);  /* mobile 13 → desktop 20 */

  /* ═══ VERB — single token for every BENTO heading ═══
     Bento verbs across all 4 views (follow / learn / learn-mechanics /
     forge) + back tile + blurred placeholders share ONE size. Long
     mechanics words like "Призначення" / "Гартування" must fit a 5-col
     grid tile (~220 px wide on 1280), so the desktop ceiling stays at 24 px. */
  --fs-verb: clamp(18px, 0.8vw + 15px, 24px);  /* mobile 18 → desktop 24 */

  /* Line heights */
  --lh-tight:   1.15;
  --lh-snug:    1.25;
  --lh-normal:  1.4;
  --lh-relaxed: 1.6;
  --lh-loose:   1.75;

  /* Letter spacing */
  --ls-snug:          0.01em;
  --ls-base:          0.02em;
  --ls-wide:          0.08em;
  --ls-wider:         0.12em;
  --ls-widest:        0.22em;
  --ls-tracked:       0.32em;
  --ls-extra-tracked: 0.42em;

  /* Spacing scale */
  --sp-1:  4px;
  --sp-2:  8px;
  --sp-3:  12px;
  --sp-4:  16px;
  --sp-5:  20px;
  --sp-6:  24px;
  --sp-7:  28px;
  --sp-8:  32px;
  --sp-9:  36px;
  --sp-10: 40px;
  --sp-12: 48px;
  --sp-14: 56px;
  --sp-16: 64px;
}

/* ═══ BASE ═══ */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html, body { overflow-x: hidden; }
html {
  /* Smooth animation for any programmatic scrollTo (nav-back, scroll-hint,
     anchor links). Native touch momentum is unaffected. */
  scroll-behavior: smooth;
  /* Stop scroll chains from leaking into parent contexts and prevent
     iOS "rubber band" overscroll past the page edges — gives the
     hero ↔ cards transition a clean stop at both boundaries. */
  overscroll-behavior-y: contain;
}
body {
  background: var(--ink-bg);
  color: var(--cream);
  min-height: 100svh;
  cursor: default;
  -webkit-user-select: none;
  user-select: none;
  font-family: var(--font-mono);
  -webkit-font-smoothing: antialiased;
}

/* Allow text selection inside inputs. */
input, textarea { user-select: text; -webkit-user-select: text; }

/* Visible focus ring for keyboard navigation only.
   Mouse clicks and programmatic focus (e.g. after reload restoring
   focus on an anchor) should not show any ring — only real Tab-based
   a11y navigation earns the gold outline. */
:focus { outline: none; }
:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 3px;
  border-radius: 6px;
}
/* Choice cards are large interactive surfaces with rounded radii — give
   them a slightly warmer ember outline + extra offset so the focus ring
   reads as part of the card, not a generic browser frame. */
.choice-card:focus-visible {
  outline: 2px solid rgba(var(--rgb-ember-hi), 0.9);
  outline-offset: 4px;
}
/* Kill the browser's default tap-highlight on touch devices. */
a, button { -webkit-tap-highlight-color: transparent; }

/* Skip link for screen readers / keyboard users. */
.skip-link {
  position: absolute;
  left: -10000px;
  top: 12px;
  padding: 10px 16px;
  background: var(--ink);
  color: var(--cream);
  border: 1px solid var(--gold);
  border-radius: 8px;
  z-index: var(--z-skip-link);
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  text-decoration: none;
}
.skip-link:focus { left: 12px; }

/* Screen-reader-only helper. */
.sr-only {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0);
  white-space: nowrap; border: 0;
}

/* ═══ BACKGROUND CANVAS LAYERS ═══ */
canvas#flames,
canvas#embers,
canvas#bubbles { pointer-events: none; }
canvas#flames  { position: fixed; left: 0; right: 0; bottom: 0; width: 100%; height: 32vh; z-index: var(--z-base); }
canvas#bubbles { position: fixed; inset: 0; z-index: var(--z-base); }
canvas#embers  { position: fixed; inset: 0; z-index: var(--z-content); }
.vignette {
  position: fixed; inset: 0; z-index: var(--z-content); pointer-events: none;
  background:
    linear-gradient(to top, rgba(0,0,0,.55) 0%, rgba(0,0,0,.15) 30%, transparent 55%),
    radial-gradient(ellipse at center, transparent 50%, rgba(0,0,0,.55) 100%);
}

/* ═══ THOUGHTS FIELD ═══ */
#field {
  position: fixed;
  left: 0; right: 0; top: 0;
  height: 100svh;
  z-index: 2;
  pointer-events: none;
  mask-image: linear-gradient(to bottom, transparent 0%, black 11%, black calc(100% - 220px), transparent calc(100% - 144px));
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, black 11%, black calc(100% - 220px), transparent calc(100% - 144px));
  opacity: 1;
  transition: opacity 1.6s ease;
}
#field.fade-out { opacity: 0; }

/* ═══ LOGO SAFE ZONE (frosted bar for collapsed logo) ═══ */
#logo-safe-zone {
  position: fixed; top: 0; left: 0; right: 0;
  height: 73px; z-index: 6;
  background: rgba(5,5,8,0.88);
  backdrop-filter: blur(28px);
  -webkit-backdrop-filter: blur(28px);
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.6s ease;
}
#logo-safe-zone.visible { opacity: 1; }
#logo-safe-zone::after {
  content: ''; position: absolute; bottom: -24px; left: 0; right: 0; height: 24px;
  background: linear-gradient(to bottom, rgba(5,5,8,0.6), transparent);
  pointer-events: none;
}

/* ═══ SECTION DIVIDER ═══ */
#section-divider {
  position: fixed; top: 72px; left: 0; right: 0;
  z-index: 7; height: 1px; width: 0%; margin: 0 auto;
  background: linear-gradient(90deg,
    transparent 0%,
    rgba(255,240,200,0.06) 15%,
    rgba(255,240,200,0.15) 35%,
    rgba(var(--cream-rgb), 0.22) 50%,
    rgba(255,240,200,0.15) 65%,
    rgba(255,240,200,0.06) 85%,
    transparent 100%);
  box-shadow: 0 0 12px rgba(255,240,200,0.08), 0 0 30px rgba(255,230,170,0.04);
  opacity: 0;
  transition: width 0.3s ease, opacity 0.3s ease;
  pointer-events: none;
}
#section-divider.visible {
  width: 100%; opacity: 1;
  transition: width 0.7s var(--ease-silk), opacity 0.5s ease;
}


/* ═══ LOGO — pure GPU transform ═══ */
#logo {
  position: fixed;
  top: 14px; left: 50%;
  transform: translate(-50%, calc(50vh - 50% - 14px)) scale(1);
  transform-origin: center top;
  z-index: 5;
  display: flex; flex-direction: column; align-items: center;
  pointer-events: none;
  will-change: transform, opacity;
  backface-visibility: hidden;
  transition:
    transform var(--dur-collapse) var(--ease-silk),
    opacity   var(--dur-collapse) var(--ease-silk);
}
/* Initial mount: hide logo until scroll.js has detected the restored
   scroll position and snapped to the correct state (hero or collapsed).
   Without this, reloading while scrolled past the hero shows a 0.8s
   hero→collapsed animation — scroll restoration fires AFTER first
   paint, so the logo paints at hero scale before .collapsed gets
   toggled. opacity:0 + transition:none = no visible state at all
   until scroll.js drops the gate via removing `no-transition`. */
#logo.no-transition {
  transition: none !important;
  opacity: 0;
}

/* Master FOUC gate (set on <html> by index.html, removed by scroll.js
   once scroll is settled AND fonts are loaded). Hides every element
   that would otherwise flash through an intermediate state on reload:
     - #scroll-hint  : "Увійти в кузню" pops in before scroll.js can
                       toggle .hidden on it for collapsed reloads.
     - #site-footer  : footer text paints in the fallback family then
                       snaps to Unbounded once fonts arrive.
     - .char-rest    : "ожен бирає ласну втентичність" raw text shows
                       before logo-reveal.js's splitTails() wraps each
                       glyph in an opacity-0 .c span.
   transition:none keeps the un-hide instantaneous — once the gate is
   dropped, everything appears in its final form at the same moment. */
html.booting #logo,
html.booting #scroll-hint,
html.booting #site-footer,
html.booting #logo-kova .char-rest {
  opacity: 0 !important;
  transition: none !important;
}

body.logo-transitioning #scroll-hint-next,
body.logo-transitioning #scroll-hint svg,
body.logo-transitioning .scroll-hint-btn,
body.logo-transitioning .footer-tag {
  animation-play-state: paused;
}

#logo-glow {
  position: absolute;
  top: 42%; left: 50%;
  transform: translate(-50%, -50%);
  /* Halo scales with viewport: caps at 520px on desktop, shrinks on
     phones and short landscapes so it never overshoots the hero. */
  width:  clamp(220px, min(52vw, 52vh), 520px);
  height: clamp(220px, min(52vw, 52vh), 520px);
  border-radius: 50%;
  background: radial-gradient(circle,
    rgba(255,255,250,0.045) 0%,
    rgba(255,240,180,0.025) 20%,
    rgba(255,200,80,0.01) 40%,
    transparent 65%);
  pointer-events: none;
  will-change: opacity, transform;
}

#logo-kova {
  font-family: 'Geologica', sans-serif;
  font-weight: 100;
  font-size: var(--fs-hero);
  line-height: 1;
  color: var(--cream-hi);
  display: inline-flex;
  gap: 0.32em;
  will-change: opacity, text-shadow;
  /* Baseline neon so the glow is visible from the first paint —
     logo-neon.js overrides per-char text-shadow on its first tick. */
  text-shadow:
    0 0 6px rgba(255,255,245,0.7),
    0 0 18px rgba(255,240,210,0.35),
    0 0 40px rgba(255,220,160,0.15);
  margin: 0;
  /* Hide until the brand font (Geologica 100) has loaded — otherwise
     the first paint flashes letters in a fallback family with the
     same halo, which reads as "glow appears after". */
  opacity: 0;
  transition: opacity 0.45s ease;
}
#logo-kova.loaded { opacity: 1; }
#logo-kova [data-char] {
  display: inline-block;
  will-change: opacity, text-shadow, color;
}

/* ═══ EASTER EGG — CHARACTER CASCADE (v4 picked from the variations)
   The wordmark layout NEVER changes — tails live out of flow
   (`position: absolute`), so the hero's bounding box is the classic
   KOVΔ width and `logo.js`'s subtitle-sync is untouched.

   On `.revealing` (set by logo-reveal.js when the user enters the
   Пізнавай view) two tempos run together:

     1. KOVΔ's capitals glide apart on a long 2 s expo-out curve —
        no teleport, no snap. The whole h1 re-centres at the same
        time so the expanded phrase stays viewport-centered.
     2. Each glyph of every tail ("ожен", "бирає", …) is split into
        its own <span class="c"> by logo-reveal.js and rises from
        translateY(0.25 em) + opacity 0 with a 60 ms stagger and a
        450 ms lead-in, so the cascade reads as a response to the
        capitals parting, not a competition.

   Retract drops the cascade delays so tails collapse in one quick
   breath while the capitals slide back on the same long curve.

     K → Кожен   O → Обирає   V → Власну   Δ → Автентичність
   ──────────────────────────────────────────────────────────────── */

#logo-kova {
  transform: translate3d(0, 0, 0);
  transition: transform 2s cubic-bezier(0.22, 1, 0.3, 1);
  will-change: transform;
}
#logo-kova.revealing {
  transform: translate3d(calc(-1 * var(--total-shift, 0px) / 2), 0, 0);
}

#logo-kova .word {
  display: inline-block;
  position: relative;            /* anchor for the absolutely-positioned tail */
  white-space: nowrap;
  vertical-align: baseline;
  transition: transform 2s cubic-bezier(0.22, 1, 0.3, 1);
  will-change: transform;
}
#logo-kova.revealing .word {
  transform: translate3d(var(--shift, 0px), 0, 0);
}

/* .char-rest-slot is an inline-block with width: 0 — it takes NO
   horizontal space in the word's layout (so the h1's bounding box
   stays classic-KOVΔ compact), but it still sits on the word's
   inline baseline. Its child .char-rest is a plain inline-block
   whose baseline is inherited naturally by the browser — no
   `position: absolute` gymnastics, no font-metric guesswork. Every
   tail glyph sits on exactly the same baseline as K / O / V / Δ. */
#logo-kova .char-rest-slot {
  display: inline-block;
  width: 0;
  vertical-align: baseline;
  overflow: visible;              /* let the tail spill to the right */
  pointer-events: none;
}
#logo-kova .char-rest {
  display: inline-block;
  white-space: nowrap;
  vertical-align: baseline;
  font-family: 'Unbounded', sans-serif;   /* reveal tail words */
  font-weight: 200;
  font-size: 0.4em;              /* ~42 px at 104 px K, ~18 px at 46 px K */
  line-height: 1;
  letter-spacing: 0.02em;
  /* Full 6-layer cream neon — same anatomy as the KOVΔ glyphs. */
  color: rgba(255, 250, 235, 0.95);
  text-shadow:
    0 0 1px  rgba(255, 255, 250, 1),
    0 0 4px  rgba(255, 255, 250, 0.9),
    0 0 12px rgba(255, 240, 200, 0.55),
    0 0 28px rgba(255, 225, 165, 0.3),
    0 0 56px rgba(255, 210, 130, 0.13),
    0 0 96px rgba(255, 180,  80, 0.05);
}
/* Per-word margin compensation — ONE canonical visual gap (~7 px at
   104 px K) at baseline level, where the eye actually reads spacing.
   Values derived empirically: rendered each capital + each tail's
   first letter to canvas, scanned only the bottom band (last ~13 %
   of the glyph) for rightmost / leftmost ink, then computed
     marginLeft = TARGET_GAP − (advance − baselineRight) − tailBaselineLeft
   for each pair. K/O/Δ all settle in the 0–0.05 em range; V needs a
   bigger negative pull because its diagonals meet at advance-box
   centre on baseline, leaving ~half the box as visual whitespace.
   Values in `em` on `.char-rest` (its own font-size = 0.4× the
   capital's) so spacing scales with the viewport font-size clamp. */
#logo-kova .word:nth-child(1) .char-rest { margin-left: 0.017em; }   /* K→о */
#logo-kova .word:nth-child(2) .char-rest { margin-left: -0.053em; }  /* O→б */
#logo-kova .word:nth-child(3) .char-rest { margin-left: -0.32em; }   /* V→л */
#logo-kova .word:nth-child(4) .char-rest,
#logo-kova .delta-rest                   { margin-left: 0.029em; }   /* Δ→в */

/* Character cascade + neon bloom (v6 from the variations page).
   Each glyph does THREE things simultaneously on its turn:
     · rise from translateY(0.22 em) to 0        (cascade)
     · scale from 0.92 to 1                      (bloom)
     · blur from 3 px to 0                       (bloom)
   With opacity 0 → 1 on top. `--gi` drives the reveal order
   (left → right); `--gr` drives the retract order (right → left)
   so the phrase unclicks glyph by glyph from the tail. */
#logo-kova .char-rest .c {
  display: inline-block;
  opacity: 0;
  transform: translate3d(0, 0.22em, 0) scale(0.92);
  transform-origin: left center;
  filter: blur(3px);
  /* Retract pose (applies while `.revealing` is absent) — ALL tails
     fade as one. Per-glyph stagger only exists on reveal; staggered
     retract was tried and ditched because mid-reveal cancellation
     left glyphs stuck for the duration of their delay before they
     started retracting.
     Durations and easing match the reveal arc (was 0.22s/0.28s
     ease-in — a snap, 8× faster than the 2.2s reveal cascade) so the
     phrase doesn't pop out: it drifts back into the wordmark with
     the same silk ease as everything else on the page. */
  transition:
    opacity   0.42s var(--ease-silk),
    transform 0.50s var(--ease-silk),
    filter    0.42s var(--ease-silk);
  will-change: opacity, transform, filter;
}
#logo-kova.revealing .char-rest .c {
  opacity: 1;
  transform: translate3d(0, 0, 0) scale(1);
  filter: blur(0);
  /* Reveal — 350 ms lead-in lets the capitals begin their glide
     first, then every glyph takes its 55 ms turn with a silky
     cubic-bezier. The blur fades on a short tail so the bloom
     "lands" crisp on each letter. */
  transition:
    opacity   0.45s ease-out                     calc(var(--gi, 0) * 55ms + 350ms),
    transform 0.55s cubic-bezier(0.2, 1, 0.3, 1) calc(var(--gi, 0) * 55ms + 350ms),
    filter    0.45s ease-out                     calc(var(--gi, 0) * 55ms + 400ms);
}

@media (prefers-reduced-motion: reduce) {
  #logo-kova,
  #logo-kova .word,
  #logo-kova .char-rest .c { transition: none !important; }
}

#logo-sub {
  margin-top: 20px;
  font-family: var(--font-mono);
  font-weight: 300;
  font-size: var(--fs-sm);
  letter-spacing: 0;
  text-transform: uppercase;
  white-space: nowrap;
  display: flex;
  justify-content: space-between;
  align-items: center;
  color: rgba(255,255,250,1);
  /* 6-layer neon halo — same anatomy as .choice-verb so the subtitle
     reads as a lit tube. Tight bright core + warm outer bloom carries
     the same heat as the KOVΔ mark above. */
  text-shadow:
    0 0 1px  rgba(255,255,250,1),
    0 0 4px  rgba(var(--cream-rgb), 0.95),
    0 0 12px rgba(255,240,210,0.7),
    0 0 28px rgba(255,225,170,0.42),
    0 0 56px rgba(255,210,140,0.22),
    0 0 96px rgba(255,200,120,0.10);
  will-change: opacity;
}
#logo-sub > span { display: inline-block; }
#logo-sub > span.sp { flex: 0 0 1.2em; }

/* ═══ PROMPT ═══ */
#prompt {
  margin-top: 44px;
  display: flex; flex-direction: column; align-items: center;
  pointer-events: none;
}
#prompt-row {
  position: relative;
  display: flex; align-items: center;
  pointer-events: auto;
  /* Button sits absolutely past the field's right edge so the field's
     width alone equals the KOVA width. */
}
#prompt-field {
  position: relative;
  /* JS syncs this to KOVA width; fallback for early paint. */
  width: min(360px, 72vw);
}
#prompt-send {
  position: absolute;
  left: calc(100% + 14px);
  top: 50%;
  transform: translateY(-50%);
}
#prompt-float {
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%) scale(1);
  transform-origin: center center;
  font-family: var(--font-mono);
  font-size: var(--fs-md);
  font-weight: 300;
  font-style: italic;
  color: rgba(255,235,210,0.92);
  text-shadow:
    0 0 4px rgba(255,225,180,0.55),
    0 0 12px rgba(255,200,130,0.25),
    0 0 26px rgba(255,180,100,0.1);
  pointer-events: none;
  white-space: nowrap;
  transition: transform 0.4s cubic-bezier(0.25, 0.1, 0.25, 1), color 0.4s ease;
}
#prompt-float::after {
  content: ''; display: inline-block;
  width: 1px; height: 1em;
  margin-left: 2px; vertical-align: text-bottom;
  background: rgba(255,220,160,0.7);
  animation: cursorBlink 1s step-end infinite;
}
#prompt-float.up::after { display: none; }
@keyframes cursorBlink { 0%,100%{opacity:1} 50%{opacity:0} }

@keyframes promptNudge {
  0%,100%{transform:translate(-50%,-50%) scale(1)}
  15%{transform:translate(calc(-50% + 4px),-50%) scale(1)}
  30%{transform:translate(calc(-50% - 3px),-50%) scale(1)}
  45%{transform:translate(calc(-50% + 2px),-50%) scale(1)}
  60%{transform:translate(calc(-50% - 1px),-50%) scale(1)}
}
#prompt-float.nudge {
  animation: promptNudge 0.5s ease;
  color: rgba(255,200,140,0.9);
  text-shadow: 0 0 6px rgba(255,200,120,0.6), 0 0 16px rgba(255,180,100,0.25);
}
@keyframes borderFlash {
  0%{border-bottom-color:rgba(255,220,170,0.3)}
  30%{border-bottom-color:rgba(255,200,120,0.7)}
  100%{border-bottom-color:rgba(255,220,170,0.3)}
}
#prompt-input.nudge { animation: borderFlash 0.6s ease; }
#prompt-float.up {
  transform: translate(-50%, -280%) scale(0.72);
  color: rgba(255,220,180,0.5);
  text-shadow: 0 0 3px rgba(255,200,140,0.2);
}
#prompt-hint {
  margin-top: 14px;
  text-align: center;
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  font-weight: 300;
  letter-spacing: 0.04em;
  color: rgba(255,240,220,0.55);
  pointer-events: none;
  user-select: none;
  transition: opacity 0.6s ease;
}
#prompt-input {
  font-family: var(--font-mono);
  /* User's typed answer sits at the body scale — quieter than the
     float label's hero-question class (--fs-md). ≥16px on mobile
     prevents iOS auto-zoom on focus. Note: --fs-base goes 15→18;
     on iOS Safari with viewport 375px it resolves to 15.25px which
     is below the 16px zoom threshold. We accept this — the field is
     centered on the hero, zoom-on-focus is mild and standard iOS
     behaviour for the very smallest phones. */
  font-size: var(--fs-base);
  font-weight: 300;
  font-style: italic;
  color: rgba(255,240,220,1);
  background: none; border: none;
  border-bottom: 1px solid rgba(255,220,170,0.42);
  outline: none; text-align: center; width: 100%;
  padding: 12px 4px;
  -webkit-user-select: text; user-select: text;
  caret-color: rgba(255,220,160,0.95);
  text-shadow: 0 0 5px rgba(255,200,130,0.28);
  transition: border-color 0.4s ease, color 0.4s ease;
}
#prompt-input:focus {
  color: rgba(255,248,235,1);
  border-bottom-color: rgba(255,220,160,0.7);
  text-shadow: 0 0 6px rgba(255,210,140,0.4), 0 0 14px rgba(255,180,80,0.15);
}

/* ═══ NEON BUTTON ═══ */
.neon-btn {
  width: 40px; height: 40px;
  border: 1.5px solid rgba(var(--cream-rgb), 0.6);
  border-radius: 50%;
  background: none;
  cursor: pointer; padding: 0;
  display: flex; align-items: center; justify-content: center;
  color: rgba(var(--cream-rgb), 0.75);
  font-family: var(--font-mono);
  font-size: var(--fs-2xs); font-weight: 500;
  letter-spacing: var(--ls-wide);
  box-shadow:
    0 0 4px rgba(var(--cream-rgb), 0.5),
    0 0 12px rgba(255,240,200,0.15),
    0 0 28px rgba(255,220,150,0.05);
  transition: border-color 0.3s ease, box-shadow 0.3s ease, transform 0.3s ease, color 0.3s ease;
  pointer-events: auto;
  flex-shrink: 0;
  -webkit-tap-highlight-color: transparent;
}
.neon-btn:hover {
  border-color: rgba(var(--cream-rgb), 0.9);
  color: rgba(255,255,240,0.95);
  box-shadow:
    0 0 6px rgba(var(--cream-rgb), 0.75),
    0 0 18px rgba(255,240,200,0.28),
    0 0 36px rgba(255,220,150,0.1);
}
.neon-btn:active { transform: scale(0.9); }
.neon-btn svg {
  width: 14px; height: 14px;
  filter: drop-shadow(0 0 4px rgba(var(--cream-rgb), 0.6)) drop-shadow(0 0 10px rgba(255,230,170,0.2));
}

/* ═══ COLLAPSED LOGO ═══ */
#logo.collapsed {
  transform: translate(-50%, 0) scale(0.42);
  opacity: 0.95;
  z-index: var(--z-fixed);
}
#logo-glow, #logo-sub, #prompt {
  transition: opacity var(--dur-collapse) var(--ease-silk);
}
/* Hide subtitle + prompt until logo.js has synced their widths to KOVA.
   Without this, first paint shows them at the CSS fallback width
   (min(360px, 72vw)) and they snap to the synced width on the next
   frame — a visible flash on every reload. */
#logo:not(.synced) #logo-sub,
#logo:not(.synced) #prompt {
  opacity: 0;
  pointer-events: none;
}
#logo.collapsed #logo-glow    { opacity: 0; }
#logo.collapsed #logo-sub     { opacity: 0; }
#logo.collapsed #prompt       { opacity: 0; pointer-events: none; }
#logo.collapsed #prompt-row   { pointer-events: none; }
#logo.hidden-deep { display: none !important; }
#logo.in-section { opacity: 0 !important; pointer-events: none; }

/* ═══ NAV CONTROLS ═══ */
#nav-back, #nav-lang {
  position: fixed; top: 20px;
  z-index: 11;
  background: rgba(15,15,18,0.55);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}
#nav-back {
  left: 20px;
  opacity: 0; pointer-events: none;
  transition: opacity 0.5s ease;
}
#nav-back.visible { opacity: 1; pointer-events: auto; }
#nav-lang { right: 20px; opacity: 1; }
@media (max-width: 560px) {
  #nav-back, #nav-lang { top: 14px; }
  #nav-back { left: 14px; }
  #nav-lang { right: 14px; }
}

/* ═══ FOOTER — fixed glowing note + signature ═══ */

/* ═══ SCROLL HINT ═══ */
#scroll-hint {
  position: fixed; bottom: clamp(48px, 12vh, 100px); left: 50%;
  transform: translateX(-50%);
  z-index: 6;
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  pointer-events: auto;
  cursor: pointer;
  opacity: 1;
  transition: opacity 1s ease;
  animation: scrollBounce 2s ease-in-out infinite;
  background: none;
  border: 0;
  color: inherit;
  font: inherit;
  padding: 0;
}
/* pointer-events:none is critical — otherwise the invisible hint keeps
   catching clicks after scroll and blocks whatever sits underneath
   (e.g. the middle of the .support-card in the forge section). */
#scroll-hint.hidden { opacity: 0; pointer-events: none; transition: opacity 0.3s ease; }
#scroll-hint-next {
  font-family: var(--font-mono);
  font-size: var(--fs-sm); font-weight: 300;
  letter-spacing: var(--ls-wider);
  color: rgba(var(--cream-rgb), 0.95);
  margin-bottom: 6px;
  animation: scrollTextGlow 3.2s ease-in-out infinite;
}
.scroll-hint-btn {
  width: 40px; height: 40px;
  border-radius: 50%;
  border: 1.5px solid rgba(var(--cream-rgb), 0.6);
  display: flex; align-items: center; justify-content: center;
  box-shadow:
    0 0 4px rgba(var(--cream-rgb), 0.5),
    0 0 12px rgba(255,240,200,0.15),
    0 0 28px rgba(255,220,150,0.05);
  animation: scrollArrowGlow 3.2s ease-in-out infinite;
}
#scroll-hint svg {
  width: 14px; height: 14px;
  stroke: rgba(var(--cream-rgb), 0.95);
  stroke-width: 1.6;
  filter:
    drop-shadow(0 0 3px rgba(var(--cream-rgb), 0.7))
    drop-shadow(0 0 8px rgba(255,230,170,0.3));
}
@keyframes scrollTextGlow {
  0%, 100% {
    text-shadow:
      0 0 2px #fff,
      0 0 6px rgba(var(--cream-rgb), 0.65),
      0 0 14px rgba(255,240,200,0.4),
      0 0 30px rgba(255,220,150,0.18),
      0 0 55px rgba(255,200,120,0.08);
  }
  50% {
    text-shadow:
      0 0 3px #fff,
      0 0 10px rgba(var(--cream-rgb), 0.9),
      0 0 22px rgba(255,240,200,0.6),
      0 0 46px rgba(255,220,150,0.32),
      0 0 80px rgba(255,200,120,0.18);
  }
}
@keyframes scrollArrowGlow {
  0%, 100% {
    border-color: rgba(var(--cream-rgb), 0.55);
    box-shadow:
      0 0 4px rgba(var(--cream-rgb), 0.45),
      0 0 12px rgba(255,240,200,0.15),
      0 0 28px rgba(255,220,150,0.05);
  }
  50% {
    border-color: rgba(var(--cream-rgb), 0.85);
    box-shadow:
      0 0 6px rgba(var(--cream-rgb), 0.75),
      0 0 18px rgba(255,240,200,0.35),
      0 0 42px rgba(255,220,150,0.15);
  }
}
@keyframes scrollBounce {
  0%,100% { transform: translateX(-50%) translateY(0); }
  50%     { transform: translateX(-50%) translateY(6px); }
}

/* ═══ FORGE · CHOICE SECTION ═══
   Game-style vertical choice panels. Locked to exactly one viewport,
   with padding that reserves room for the collapsed top bar (73px)
   and the fixed footer bar (~88px incl. safe-area). Frosted glass,
   Apple-rounded. Hover dims the siblings so the chosen path glows.
   --forge-top / --forge-bot keep scroll-target math honest: clicking
   scroll-hint lands with cards sitting exactly between the two bars. */
section.forge {
  --forge-top: calc(73px + 2.2svh);
  /* Bottom padding only as a small buffer — the footer sits directly
     below the section now, so the support row is anchored to the
     bottom (space-between) and the empty band the centered layout
     used to leave between the row and the footer is gone. */
  --forge-bot: calc(20px + env(safe-area-inset-bottom, 0px));
  position: relative;
  z-index: 5;
  margin-top: 100svh;
  min-height: 100svh;
  padding: var(--forge-top) 3vw var(--forge-bot);
  display: flex; flex-direction: column; align-items: center; justify-content: space-between;
  gap: 16px;
}

.choices {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 18px;
  width: 100%;
  max-width: 1400px;
  flex: 1;
  min-height: 0;
}

.choice-card {
  --card-op: 1;
  --accent: 212, 184, 150;          /* gold, per-card overridable */
  position: relative;
  display: block;
  text-decoration: none;
  border-radius: 28px;
  overflow: hidden;
  isolation: isolate;
  background:
    linear-gradient(180deg,
      rgba(255,255,255,0.020) 0%,
      rgba(255,255,255,0.008) 55%,
      rgba(255,255,255,0.003) 100%);
  backdrop-filter: blur(6px) saturate(115%);
  -webkit-backdrop-filter: blur(6px) saturate(115%);
  border: 1px solid rgba(255, 235, 210, 0.07);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.04),
    0 20px 60px rgba(0,0,0,0.30);
  opacity: var(--card-op);
  transition:
    opacity 0.55s var(--ease-silk),
    border-color 0.55s var(--ease-silk),
    transform 0.55s var(--ease-silk),
    box-shadow 0.55s var(--ease-silk);
  cursor: pointer;
}

.choice-card[data-choice="follow"] {
  --accent:    var(--path-observer);
  --accent-hi: var(--path-observer-hi);
}
.choice-card[data-choice="learn"]  {
  --accent:    var(--path-apprentice);
  --accent-hi: var(--path-apprentice-hi);
}
.choice-card[data-choice="forge"]  {
  --accent:    var(--path-smith);
  --accent-hi: var(--path-smith-hi);
}

/* Thematic texture — per-card soft radial + fine noise grid.
   Lives below .choice-inner, above the frosted pane. */
.choice-tex {
  position: absolute; inset: 0;
  z-index: var(--z-base);
  pointer-events: none;
  opacity: 0.55;
  background:
    radial-gradient(ellipse at 50% 110%,
      rgba(var(--accent), 0.22) 0%,
      rgba(var(--accent), 0.08) 35%,
      transparent 65%),
    radial-gradient(circle at 50% 20%,
      rgba(255,255,255,0.04) 0%,
      transparent 45%);
  transition: opacity 0.55s var(--ease-silk);
}
.choice-tex::after {
  content: '';
  position: absolute; inset: 0;
  background-image:
    linear-gradient(rgba(255,255,255,0.025) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255,255,255,0.025) 1px, transparent 1px);
  background-size: 48px 48px;
  mask-image: radial-gradient(ellipse at 50% 60%, black 0%, transparent 75%);
  -webkit-mask-image: radial-gradient(ellipse at 50% 60%, black 0%, transparent 75%);
  opacity: 0.35;
}

.choice-inner {
  position: relative;
  z-index: var(--z-content);
  height: 100%;
  display: flex; flex-direction: column; align-items: center; justify-content: space-between;
  padding: 34px 24px 22px;
  gap: 14px;
}

.choice-top {
  display: flex; flex-direction: column; align-items: center;
  gap: 8px;
  text-align: center;
}

.choice-verb {
  font-family: var(--font-display);
  font-weight: 200;
  font-size: var(--fs-card-verb);
  letter-spacing: var(--ls-base);
  /* Neon in each card's own colour — moonstone / gold / bronze. The
     two tight inner layers use the lighter --accent-hi to simulate
     the hot tube core (otherwise desaturated accents read flat); the
     outer stops diffuse in --accent for the coloured halo. */
  color: rgba(var(--accent-hi), 1);
  text-shadow:
    0 0 2px  rgba(var(--accent-hi), 1),
    0 0 10px rgba(var(--accent),    0.7),
    0 0 26px rgba(var(--accent),    0.36),
    0 0 60px rgba(var(--accent),    0.14);
  transition: color 0.55s var(--ease-silk), text-shadow 0.55s var(--ease-silk);
}

@keyframes verbNeon {
  0%, 100%   { opacity: 0.92; filter: brightness(1); }
  16%, 17.5% { opacity: 0.32; filter: brightness(0.65); }
  19%        { opacity: 1;    filter: brightness(1.12); }
  46%, 48%   { opacity: 0.38; filter: brightness(0.7); }
  50%        { opacity: 1;    filter: brightness(1.14); }
  72%, 73.5% { opacity: 0.6;  filter: brightness(0.85); }
  78%        { opacity: 1;    filter: brightness(1); }
}

.choice-sub {
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 300;
  font-size: var(--fs-subtitle);
  line-height: var(--lh-normal);
  /* Tinted in the card's own -hi accent so the subtitle carries the
     same colour progression as the verb above and the action below. */
  color: rgba(var(--accent-hi), 0.68);
  letter-spacing: var(--ls-snug);
  max-width: 22ch;
  transition: color 0.55s var(--ease-silk);
}

.choice-icon {
  width: clamp(60px, 6.2vw, 92px);
  height: clamp(60px, 6.2vw, 92px);
  /* Icon stroke = card accent (hi core). Stacked drop-shadows mirror
     the verb neon: tight bright halo + wider coloured aura. */
  color: rgba(var(--accent-hi), 0.92);
  filter:
    drop-shadow(0 0 3px rgba(var(--accent-hi), 0.75))
    drop-shadow(0 0 12px rgba(var(--accent),    0.38));
  transition: color 0.55s var(--ease-silk), filter 0.55s var(--ease-silk), transform 0.55s var(--ease-silk);
}

/* ═══ CLASS BADGE — visually separated bottom block ═══ */
.choice-class {
  position: relative;
  width: 86%;
  padding: 20px 8px 6px;
  display: flex; flex-direction: column; align-items: center;
  gap: 10px;
}
.choice-class::before {
  content: '';
  position: absolute;
  top: 0; left: 10%; right: 10%;
  height: 1px;
  background: linear-gradient(90deg,
    transparent 0%,
    rgba(var(--accent), 0.45) 50%,
    transparent 100%);
  opacity: 0.65;
  transition: opacity 0.55s var(--ease-silk);
}

.choice-class-name {
  font-family: var(--font-display);
  font-weight: 200;
  font-size: var(--fs-card-name);
  letter-spacing: var(--ls-wider);
  text-transform: uppercase;
  color: rgba(var(--accent), 1);
  text-shadow: 0 0 12px rgba(var(--accent), 0.28);
  padding-left: 0.14em;
  transition: text-shadow 0.55s var(--ease-silk), color 0.55s var(--ease-silk);
}

/* Action line — what the role DOES with the form.
   Italic serif, tinted in the card's base accent (one stop quieter
   than the subtitle's -hi tint so the block has a top→bottom fade
   within the same hue). */
.choice-class-act {
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 300;
  font-size: var(--fs-subtitle);
  letter-spacing: var(--ls-snug);
  color: rgba(var(--accent), 0.70);
  margin-top: 4px;
  transition: color 0.55s var(--ease-silk);
}

.choice-card:hover .choice-sub       { color: rgba(var(--accent-hi), 0.95); }
.choice-card:hover .choice-class-act { color: rgba(var(--accent-hi), 0.92); }

/* Game-choice dimming — desktop only. On touch devices :hover fires on
   tap and the dim/highlight reads as a permanent "selection" state which
   the user didn't ask for. Pointer media query keeps it mouse-only. */
@media (hover: hover) and (pointer: fine) {
  /* `.forge-transitioning` gate: during the bento → choice back
     animation the cursor is often already inside the .choices area
     (because the user just clicked the bento back-tile, which is
     near the centre). The dim-siblings rule would then kick in MID-
     emerge — half the cards appear pre-dimmed while one comes in at
     full opacity, reading as random "some cards never finished
     animating in". Suppress the hover-dim until the transition
     window closes; bento-view.js removes the class at ~1100 ms. */
  body:not(.forge-transitioning) .choices:hover .choice-card { --card-op: 0.30; }
  body:not(.forge-transitioning) .choices:hover .choice-card:hover { --card-op: 1; }
}

/* Click feedback — brief press + brighter accent ring. Proves the
   whole card (not just the inner pill) registers the click. */
.choice-card.is-pressed,
.support-card.is-pressed {
  transform: translateY(0) scale(0.985);
  transition:
    transform 0.12s var(--ease-silk),
    box-shadow 0.12s var(--ease-silk),
    border-color 0.12s var(--ease-silk);
}
.choice-card.is-pressed {
  border-color: rgba(var(--accent), 0.8);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.10),
    0 14px 36px rgba(0,0,0,0.45),
    0 0 0 1px rgba(var(--accent), 0.45),
    0 0 70px -6px rgba(var(--accent), 0.5);
}
.support-card.is-pressed {
  border-color: rgba(var(--accent-hot), 0.8);
  box-shadow:
    inset 0 1px 0 rgba(255, 200, 160, 0.10),
    0 14px 36px rgba(var(--accent-dim), 0.35),
    0 0 0 1px rgba(var(--accent-hot), 0.5),
    0 0 70px -6px rgba(var(--accent-hot), 0.55);
}

.choice-card:hover {
  border-color: rgba(var(--accent), 0.55);
  transform: translateY(-4px);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.10),
    0 28px 70px rgba(0,0,0,0.55),
    0 0 0 1px rgba(var(--accent), 0.25),
    0 0 60px -10px rgba(var(--accent), 0.35);
}
.choice-card:hover .choice-tex { opacity: 1; }
.choice-card:hover .choice-icon {
  color: rgba(var(--accent-hi), 1);
  filter:
    drop-shadow(0 0 5px rgba(var(--accent-hi), 1))
    drop-shadow(0 0 16px rgba(var(--accent),   0.7))
    drop-shadow(0 0 36px rgba(var(--accent),   0.32));
  transform: translateY(-2px) scale(1.04);
}
.choice-card:hover .choice-verb {
  animation: verbNeon 4.2s ease-in-out infinite;
  color: rgba(var(--accent), 1);
  text-shadow:
    0 0 1px rgba(var(--accent), 0.9),
    0 0 10px rgba(var(--accent), 0.7),
    0 0 24px rgba(var(--accent), 0.45),
    0 0 52px rgba(var(--accent), 0.22);
}
.choice-card:hover .choice-class::before { opacity: 1; }
.choice-card:hover .choice-class-name {
  text-shadow:
    0 0 16px rgba(var(--accent), 0.55),
    0 0 34px rgba(var(--accent), 0.25);
}

/* ═══ SUPPORT CARD — horizontal ember bar, not a "class" ═══
   Deliberately HOT: warm oranges, pulsing ember halo, strong glow
   on hover. It reads as a different kind of action from the three
   path cards above — something the visitor does FOR the forge. */
/* Support row: manifesto brackets the donation card —
     [Себе не знаходять.]  [ДОДАЙ ЖАРУ · CTA]  [Себе — кують.]
   The halves of the quote open and close the action. The middle
   column needs room for icon + verb + CTA pill on ONE line (~540px
   minimum). Below the side-by-side breakpoint the row collapses to
   a stack (see the media block farther down). */
.support-row {
  --accent-hot: var(--rgb-ember);
  display: grid;
  /* Card still owns the middle and keeps its 540px minimum, but the
     outer frame (max-width + wider gap) mirrors the `.choices` grid
     above so the row reads as the same full-width rhythm. The bigger
     gap pulls the credos away from the card so they stand as their
     own lines, not captions pinned to the pill. */
  grid-template-columns: minmax(0, 1fr) minmax(540px, 1.5fr) minmax(0, 1fr);
  align-items: center;
  gap: clamp(32px, 4.2vw, 72px);
  width: 100%;
  max-width: clamp(320px, 96vw, 1400px);
  margin: 0 auto;
}

/* Caption above the donation pill — reads as a quote inside a book,
   not as a stamped sign. Same serif italic used on the card subtitles
   but ~1.65× larger, soft cream ink, no tracking, no pulse. Scale
   chosen so the manifesto reads as the heart of the page rather than
   a companion to the donate CTA. */
.support-credo {
  margin: 0;
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 300;
  font-size: var(--fs-lg);
  line-height: var(--lh-snug);
  letter-spacing: 0;
  text-transform: none;
  color: rgba(250, 246, 236, 0.95);
  /* Warm-cream neon halo — blurs re-scaled back down to match the
     smaller letterforms. Bigger blurs on small type wash out. */
  text-shadow:
    0 0 2px  rgba(var(--cream-rgb), 1),
    0 0 7px  rgba(255, 245, 220, 0.8),
    0 0 17px rgba(255, 230, 180, 0.5),
    0 0 36px rgba(255, 210, 140, 0.22),
    0 0 66px rgba(255, 195, 110, 0.1);
  /* Two animations: scrollTextGlow pulses the halo size,
     credoFlicker drops brightness at irregular beats (neon tube). */
  animation:
    scrollTextGlow 3.2s ease-in-out infinite,
    credoFlicker   7.4s steps(1, end) infinite;
  will-change: opacity, filter, text-shadow;
}

/* Halves lean INTO the card so the credo brackets the pill as one
   continuous thought: left half ends at the pill, right half starts
   from the pill. Reads as a single flowing quote wrapping the action. */
.support-credo--left  { text-align: right; }
.support-credo--right { text-align: left; }

/* Per-view credo swap — the default couplet reads as the universal
   frame around the support pill. On the Apprentice screen the quote
   leans into the practice itself:
     default   "Себе не знаходять." / "Себе кують."
     learn     "Куй себе."         / "Поки горить."
   Both copies live in the DOM so i18n.js can translate each; CSS
   flips which one is visible based on the forge's current view.
   `.support-row` is a descendant of `#forge-section`, so the simple
   descendant selector matches. */
.credo-text--learn  { display: none; }
.credo-text--forge  { display: none; }
.credo-text--follow { display: none; }
.forge[data-view="learn"]  .credo-text--default { display: none; }
.forge[data-view="learn"]  .credo-text--learn   { display: inline; }
.forge[data-view="forge"]  .credo-text--default { display: none; }
.forge[data-view="forge"]  .credo-text--forge   { display: inline; }
.forge[data-view="follow"] .credo-text--default { display: none; }
.forge[data-view="follow"] .credo-text--follow  { display: inline; }

/* Irregular neon-tube flicker — same rhythm family as the logo:
   fully lit most of the cycle, with sudden quick dropouts. */
@keyframes credoFlicker {
  0%,   16%  { opacity: 1;    filter: brightness(1); }
  16.4%      { opacity: 0.32; filter: brightness(0.6); }
  16.9%      { opacity: 1;    filter: brightness(1.08); }
  17%,  43%  { opacity: 1;    filter: brightness(1); }
  43.3%      { opacity: 0.28; filter: brightness(0.55); }
  43.7%      { opacity: 0.85; filter: brightness(0.9); }
  44.1%      { opacity: 0.4;  filter: brightness(0.7); }
  44.5%      { opacity: 1;    filter: brightness(1.1); }
  45%,  72%  { opacity: 1;    filter: brightness(1); }
  72.2%      { opacity: 0.55; filter: brightness(0.8); }
  72.6%      { opacity: 1;    filter: brightness(1.05); }
  72.9%      { opacity: 0.4;  filter: brightness(0.7); }
  73.3%      { opacity: 1;    filter: brightness(1); }
  73.5%, 100% { opacity: 1;   filter: brightness(1); }
}


.support-card {
  --accent-hot:    var(--rgb-ember);      /* 246, 170,  76 — amber heat */
  --accent-hot-hi: var(--rgb-ember-hi);   /* 255, 210, 145 — bright core */
  --accent-dim:    var(--rgb-ember-deep); /* 188, 110,  30 — deep base */
  position: relative;
  display: block;
  width: 100%;
  text-decoration: none;
  border-radius: 22px;
  overflow: hidden;
  isolation: isolate;
  flex-shrink: 0;
  background:
    linear-gradient(180deg,
      rgba(var(--rgb-amber),      0.020) 0%,
      rgba(var(--rgb-ember),      0.012) 55%,
      rgba(var(--rgb-ember-deep), 0.008) 100%);
  backdrop-filter: blur(6px) saturate(115%);
  -webkit-backdrop-filter: blur(6px) saturate(115%);
  border: 1px solid rgba(var(--accent-hot), 0.09);
  /* Ember in the dark — not a spotlight. Everything ≈ 50% of prior. */
  box-shadow:
    inset 0 1px 0 rgba(var(--rgb-amber), 0.03),
    0 8px  22px rgba(var(--accent-dim), 0.05),
    0 0 32px -14px rgba(var(--accent-hot), 0.09);
  /* Split: border/shadow respond instantly to the cursor (~180ms),
     transform keeps the slower physical lift. */
  transition:
    border-color 0.18s var(--ease-silk),
    transform    0.5s  var(--ease-silk),
    box-shadow   0.18s var(--ease-silk);
  cursor: pointer;
}

/* Ember wash: twin glows at the bottom corners + faint grid.
   Dimmed ~50% — the card should carry warmth, not broadcast it. */
.support-tex {
  position: absolute; inset: 0;
  z-index: var(--z-base);
  pointer-events: none;
  background:
    radial-gradient(ellipse at 15% 130%,
      rgba(var(--rgb-ember),      0.11) 0%,
      rgba(var(--rgb-ember),      0.05) 32%,
      transparent 68%),
    radial-gradient(ellipse at 85% 130%,
      rgba(var(--rgb-ember-deep), 0.09) 0%,
      rgba(var(--rgb-ember),      0.04) 32%,
      transparent 62%),
    radial-gradient(ellipse at 50% 10%,
      rgba(var(--rgb-amber),      0.02) 0%,
      transparent 55%);
  opacity: 0.55;
}

/* Slow heat-pulse behind the icon — kept alive but quieter, so the
   card reads like a sleeping coal rather than an open flame. */
.support-ember {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 70%;
  z-index: var(--z-base);
  pointer-events: none;
  background:
    radial-gradient(ellipse at 50% 120%,
      rgba(var(--rgb-ember),      0.07) 0%,
      rgba(var(--rgb-ember-deep), 0.025) 35%,
      transparent 70%);
  animation: emberPulse 5.2s ease-in-out infinite alternate;
  filter: blur(10px);
}
@keyframes emberPulse {
  0%   { opacity: 0.20; transform: translateY(4px) scale(0.99); }
  100% { opacity: 0.40; transform: translateY(0)   scale(1.02); }
}

.support-inner {
  position: relative;
  z-index: var(--z-content);
  display: flex; align-items: center;
  gap: 22px;
  padding: 16px 26px;
  min-height: 92px;
}

.support-icon {
  width: clamp(40px, 4.2vw, 56px);
  height: clamp(40px, 4.2vw, 56px);
  /* Quiet ember — readable without demanding attention. */
  color: rgba(var(--accent-hot), 0.70);
  filter:
    drop-shadow(0 0 2px rgba(var(--accent-hot-hi), 0.38))
    drop-shadow(0 0 8px rgba(var(--accent-hot),    0.20));
  flex-shrink: 0;
  transition: color 0.5s var(--ease-silk), filter 0.5s var(--ease-silk), transform 0.5s var(--ease-silk);
}

.support-text {
  display: flex; flex-direction: column;
  gap: 2px;
  flex: 1;
  min-width: 0;
}

.support-verb {
  font-family: var(--font-display);
  font-weight: 200;
  /* Smaller cap than .choice-verb — "Додай жару" is the support CTA,
     not a path label, and shouldn't outweigh «Відчувай / Пізнавай /
     Кувай» on desktop. Mobile shares the lower bound. */
  font-size: clamp(16px, 1vw + 8px, 24px);
  letter-spacing: var(--ls-base);
  /* Never break the verb — it's the card's anchor. If the column
     can't hold it on one line, the whole row already collapsed to
     stacked above, so there's always room. */
  white-space: nowrap;
  /* Tighter neon than .choice-verb — the verb sits inches from the
     CTA pill, so the outer halo is trimmed to keep the bloom from
     bleeding through the pill border. */
  color: rgba(var(--accent-hot-hi), 1);
  text-shadow:
    0 0 1px  rgba(var(--accent-hot-hi), 1),
    0 0 4px  rgba(var(--accent-hot-hi), 0.95),
    0 0 10px rgba(var(--accent-hot),    0.65),
    0 0 22px rgba(var(--accent-hot),    0.32);
}

.support-sub {
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 300;
  font-size: var(--fs-subtitle);
  /* Closing stop of the subtitle gradient — warm ember core. */
  color: rgba(var(--accent-hot-hi), 0.78);
  letter-spacing: var(--ls-snug);
}

.support-cta {
  display: inline-flex;
  /* Center vertically — icon has a fixed 56×56 so it sits flush at
     the same height as the pill (which also has min-height: 56),
     and the label lands exactly on the pill's vertical midline. */
  align-items: center;
  /* The pill sits inside the <a> — keep pointer-events: auto so clicks
     on the pill itself register. Previously this was `none` to let
     clicks "pass through" to the wrapping <a>, but empty spots inside
     the pill (gap between icon and label, padding) created dead zones
     where clicks hit no descendant and never reached the anchor. */
  pointer-events: auto;
  min-height: 56px;
  gap: 14px;
  font-family: var(--font-mono);
  font-weight: 300;
  font-size: var(--fs-xs);
  letter-spacing: var(--ls-wider);
  text-transform: uppercase;
  color: rgba(var(--rgb-amber), 0.96);
  /* No left padding — the icon sits flush against the left edge
     so its left arc overlaps the pill's own left arc exactly. */
  padding: 0 22px 0 0;
  line-height: 1.18;
  /* Live ember neon tube — pill reads as part of the card's glow. */
  border: 1.2px solid rgba(var(--accent-hot), 0.55);
  border-radius: 999px;
  flex-shrink: 0;
  text-shadow:
    0 0 4px  rgba(var(--rgb-amber),  0.55),
    0 0 12px rgba(var(--accent-hot), 0.32),
    0 0 28px rgba(var(--accent-hot), 0.14);
  box-shadow:
    0 0 4px  rgba(var(--accent-hot), 0.40),
    0 0 14px rgba(var(--accent-hot), 0.22),
    0 0 34px rgba(var(--accent-hot), 0.10);
  transition:
    background 0.35s var(--ease-silk),
    color 0.35s var(--ease-silk),
    border-color 0.35s var(--ease-silk),
    box-shadow 0.35s var(--ease-silk),
    text-shadow 0.35s var(--ease-silk),
    transform 0.2s var(--ease-silk);
  background: linear-gradient(180deg,
    rgba(var(--rgb-ember),      0.08),
    rgba(var(--rgb-ember-deep), 0.03));
}
/* Inner circle — same size as the pill's min-height so width = height
   and the left arcs fuse into a single line. Negative margins pull
   the icon's border onto the pill's border so they overlap exactly
   (no double line, no gap). */
.support-cta-icon {
  width: 56px;
  height: 56px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1.2px solid rgba(var(--accent-hot), 0.55);
  border-radius: 50%;
  margin: -1.2px 0 -1.2px -1.2px;
  flex-shrink: 0;
  background: radial-gradient(circle at 50% 55%,
    rgba(var(--accent-hot), 0.10) 0%,
    rgba(var(--accent-hot), 0.03) 60%,
    transparent 100%);
  box-shadow:
    inset 0 0 5px rgba(var(--accent-hot), 0.10),
    0 0 2px rgba(var(--accent-hot), 0.3);
  transition:
    border-color 0.35s var(--ease-silk),
    background 0.35s var(--ease-silk),
    box-shadow 0.35s var(--ease-silk);
}
.support-cta-icon svg {
  opacity: 0.95;
  filter:
    drop-shadow(0 0 3px rgba(var(--accent-hot-hi), 0.7))
    drop-shadow(0 0 10px rgba(var(--accent-hot),    0.35));
  transition: transform 0.35s var(--ease-silk), filter 0.35s var(--ease-silk);
}
/* Press feedback lives on the whole card (.support-card.is-pressed) —
   the pill echoes the card's state so it still feels responsive. */
.support-card:active .support-cta,
.support-card.is-pressed .support-cta { transform: scale(0.97); }

/* CTA label: honours the `&#10;` in data-uk/data-en, so the label
   always breaks in the designed place: "Підкинути / дров" and
   "Feed the / fire". `pre-line` keeps the newline, collapses
   regular whitespace. The stacked breakpoint collapses it back to
   one line so the pill stays compact on narrow screens. */
.support-cta-text {
  /* Take all the room between the icon and the pill's right edge,
     then center the 2-line label inside it. Otherwise the label
     hugs whatever intrinsic width the text produces and drifts off
     the pill's visual midline. */
  flex: 1;
  text-align: center;
  white-space: pre-line;
  line-height: 1.18;
}
@media (max-width: 1100px) {
  .support-cta-text { white-space: normal; }
}

.support-card:hover {
  border-color: rgba(var(--accent-hot), 0.28);
  transform: translateY(-2px);
  /* Breathed-on coal — halo warms by ~40% on hover, not blinds. */
  box-shadow:
    inset 0 1px 0 rgba(var(--rgb-amber), 0.08),
    0 12px 30px rgba(var(--accent-dim), 0.13),
    0 0 52px -10px rgba(var(--accent-hot), 0.20);
}
.support-card:hover .support-icon {
  color: rgba(var(--accent-hot-hi), 0.92);
  filter:
    drop-shadow(0 0 3px rgba(var(--accent-hot-hi), 0.55))
    drop-shadow(0 0 12px rgba(var(--accent-hot),    0.35))
    drop-shadow(0 0 26px rgba(var(--accent-hot),    0.14));
  transform: scale(1.04);
}
.support-card:hover .support-cta {
  background: linear-gradient(180deg, rgba(var(--accent-hot), 0.18), rgba(var(--accent-hot), 0.05));
  color: rgba(var(--rgb-amber), 1);
  border-color: rgba(var(--accent-hot), 0.85);
  text-shadow:
    0 0 6px  rgba(var(--rgb-amber),  0.78),
    0 0 14px rgba(var(--accent-hot), 0.5),
    0 0 32px rgba(var(--accent-hot), 0.22);
  box-shadow:
    0 0 6px  rgba(var(--accent-hot), 0.5),
    0 0 22px rgba(var(--accent-hot), 0.32),
    0 0 52px rgba(var(--accent-hot), 0.15);
}
/* On hover the inner circle intensifies in the same ember family
   as the pill — border brighter, inner wash richer, arrow leans
   a touch further left. */
.support-card:hover .support-cta-icon {
  border-color: rgba(var(--accent-hot), 0.85);
  background: radial-gradient(circle at 50% 55%,
    rgba(var(--accent-hot), 0.18) 0%,
    rgba(var(--accent-hot), 0.05) 60%,
    transparent 100%);
  box-shadow:
    inset 0 0 7px rgba(var(--accent-hot), 0.18),
    0 0 4px rgba(var(--accent-hot), 0.5);
}
.support-card:hover .support-cta-icon svg {
  transform: translateX(-2px);
  filter:
    drop-shadow(0 0 4px rgba(var(--accent-hot-hi), 0.95))
    drop-shadow(0 0 14px rgba(var(--accent-hot),    0.5));
}

@media (max-width: 820px) {
  /* Tablet / large-phone layout shifts only — every font-size scales
     fluidly via the design tokens above, so no size overrides here. */
  section.forge { padding: 3svh 4vw 8svh; min-height: auto; height: auto; }
  .choices {
    grid-template-columns: 1fr;
    grid-auto-rows: 1fr;
    height: auto;
    gap: 14px;
    max-width: 560px;
  }
  .choice-card { min-height: 24svh; border-radius: 20px; }
  .choice-inner { padding: 22px 20px 18px; gap: 12px; }
  .choice-icon { width: 52px; height: 52px; }
  .choice-class { width: 84%; padding: 12px 4px 0; }

  .support-card { border-radius: 18px; }
  .support-inner { padding: 14px 18px; gap: 14px; min-height: 72px; }
  .support-icon  { width: 36px; height: 36px; }
  .support-cta   { padding: 9px 14px; }
}

/* ═══ SUPPORT ROW — stack earlier than the rest of the forge ═══
   Below ~1100px there isn't enough row width to fit the ember card
   (needs ≥540px for icon + verb + CTA on one line) AND two credo
   gutters without crushing them to a sliver. Collapse the grid into
   a single centered column early; tighter sizes continue inside the
   @media (max-width: 820px) block above. */
@media (max-width: 1100px) {
  .support-row {
    grid-template-columns: 1fr;
    gap: 14px;
    max-width: 560px;
  }
  .support-credo,
  .support-credo--left,
  .support-credo--right { text-align: center; }
}

/* Sub-cap the credo size once the row is already stacked & narrow. */
/* support-credo size scales fluidly via --fs-lg — no per-bp override. */

/* ═══ SHORT / LANDSCAPE VIEWPORT GUARDS ═══
   On short screens (landscape phones, ~500px tall) the logo halo, nav
   buttons and scroll-hint all compete for vertical space. Shrink them. */
@media (max-height: 560px) {
  #logo-glow { width: 42vh; height: 42vh; }
  #scroll-hint { bottom: 24px; }
  #nav-back, #nav-lang { top: 12px; }
  section.forge { padding: 6svh 4vw 8svh; }
}

/* ═══ DOCS — merchant-required (WayForPay) legal links.
   Live inside the footer between "Кузня справжності" and "Україна · MMXXVI". */
.docs-nav {
  display: flex;
  flex-wrap: nowrap;
  justify-content: center;
  align-items: center;
  gap: clamp(18px, 2.4vw, 36px);
  max-width: 1200px;
  width: 100%;
}
.doc-link {
  font-family: var(--font-mono);
  font-size: var(--fs-3xs);
  font-weight: 300;
  letter-spacing: var(--ls-widest);
  text-transform: uppercase;
  color: rgba(255, 245, 225, 0.65);
  text-decoration: none;
  text-shadow: none;
  padding: 6px 2px;
  border-bottom: 1px solid rgba(255, 220, 180, 0.12);
  transition: color 0.3s ease, border-color 0.3s ease, text-shadow 0.3s ease;
}
.doc-link:hover, .doc-link:focus-visible {
  color: rgba(255, 252, 240, 1);
  border-color: rgba(255, 220, 180, 0.55);
  text-shadow:
    0 0 6px rgba(var(--cream-rgb), 0.65),
    0 0 18px rgba(255, 230, 180, 0.28),
    0 0 38px rgba(255, 210, 140, 0.14);
}
@media (max-width: 560px) {
  /* Layout-only mobile rules — sizes inherit from --fs-xs token above. */
  .docs-nav {
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    justify-content: space-between;
    gap: 8px;
  }
  .doc-link {
    /* Narrow tracking so all three legal links fit one row at 360–390px. */
    letter-spacing: var(--ls-wide);
    text-align: center;
    white-space: nowrap;
    padding: 8px 0;
  }
}

/* ═══ DONATE MODAL — holds <kova-donate-form> directly.
   No iframe: the component is instantiated once in the modal panel
   and carries its own shadow-DOM styles. The panel is a simple
   scrollable shell with a close button + backdrop. */
.donate-modal {
  position: fixed; inset: 0;
  z-index: 110;
  display: flex; align-items: center; justify-content: center;
  padding: 24px;
  opacity: 0; pointer-events: none;
  transition: opacity 0.4s ease;
}
.donate-modal.visible { opacity: 1; pointer-events: auto; }
.donate-modal-backdrop {
  position: absolute; inset: 0;
  background: rgba(5, 5, 8, 0.78);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
}
.donate-modal-panel {
  position: relative;
  width: min(980px, 100%);
  max-height: 94vh;
  overflow-y: auto;
  overflow-x: hidden;
  border-radius: 22px;
  padding: 24px;
  background: rgba(10, 9, 7, 0.92);
  border: 1px solid rgba(var(--rgb-ember), 0.18);
  box-shadow:
    0 30px 80px rgba(0, 0, 0, 0.65),
    0 0 80px -20px rgba(var(--rgb-ember), 0.25);
  transform: translateY(16px) scale(0.985);
  transition: transform 0.4s var(--ease-silk);
}
.donate-modal.visible .donate-modal-panel { transform: translateY(0) scale(1); }
.donate-modal-content { display: block; width: 100%; }
.donate-modal-close {
  position: absolute;
  top: 14px; right: 14px;
  width: 36px; height: 36px;
  border: 1px solid rgba(var(--rgb-ember), 0.35);
  border-radius: 50%;
  background: rgba(10, 9, 7, 0.75);
  backdrop-filter: blur(8px);
  color: rgba(var(--rgb-amber), 0.9);
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  z-index: 2;
  transition: color 0.25s ease, border-color 0.25s ease, background 0.25s ease;
}
.donate-modal-close svg { width: 16px; height: 16px; }
.donate-modal-close:hover,
.donate-modal-close:focus-visible {
  color: var(--cream-hi);
  border-color: rgba(var(--rgb-ember-hi), 0.7);
  background: rgba(20, 16, 12, 0.88);
}
body.donate-modal-open { overflow: hidden; }
@media (max-width: 560px) {
  .donate-modal { padding: 0; }
  .donate-modal-panel { max-height: 100%; height: 100%; width: 100%; border-radius: 0; border: none; padding: 56px 12px 20px; }
  .donate-modal-close { top: 10px; right: 10px; width: 32px; height: 32px; }
}

/* ═══ DOC MODAL — popup for legal docs ═══ */
.doc-modal {
  position: fixed; inset: 0;
  z-index: var(--z-overlay);
  display: flex; align-items: center; justify-content: center;
  padding: 32px 20px;
  opacity: 0; pointer-events: none;
  transition: opacity 0.35s ease;
}
.doc-modal.visible { opacity: 1; pointer-events: auto; }
.doc-modal-backdrop {
  position: absolute; inset: 0;
  background: rgba(5, 5, 8, 0.72);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}
.doc-modal-panel {
  position: relative;
  max-width: 760px;
  width: 100%;
  max-height: 88vh;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 56px 48px 48px;
  border-radius: 22px;
  background:
    linear-gradient(180deg,
      rgba(18, 14, 10, 0.92) 0%,
      rgba(10, 9, 7, 0.94) 100%);
  border: 1px solid rgba(212, 184, 150, 0.18);
  box-shadow:
    inset 0 1px 0 rgba(255, 220, 180, 0.05),
    0 30px 80px rgba(0, 0, 0, 0.65),
    0 0 80px -20px rgba(255, 200, 120, 0.15);
  transform: translateY(14px) scale(0.985);
  transition: transform 0.35s var(--ease-silk);
  /* Re-enable text selection inside the doc. */
  user-select: text; -webkit-user-select: text;
}
.doc-modal.visible .doc-modal-panel { transform: translateY(0) scale(1); }
.doc-modal-close {
  position: absolute;
  top: 14px; right: 14px;
  width: 36px; height: 36px;
  border: 1px solid rgba(212, 184, 150, 0.28);
  border-radius: 50%;
  background: rgba(10, 9, 7, 0.6);
  color: rgba(255, 240, 215, 0.8);
  cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  transition: color 0.25s ease, border-color 0.25s ease, background 0.25s ease;
}
.doc-modal-close svg { width: 16px; height: 16px; }
.doc-modal-close:hover,
.doc-modal-close:focus-visible {
  color: rgba(255, 252, 240, 1);
  border-color: rgba(239, 217, 177, 0.7);
  background: rgba(20, 16, 12, 0.85);
}
.doc-modal-loading {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  letter-spacing: var(--ls-tracked);
  text-transform: uppercase;
  color: rgba(255, 240, 215, 0.55);
  text-align: center;
  padding: 40px 0;
}
/* Inline the docs.css typography so fetched article content looks right. */
.doc-modal-body .doc-title {
  font-family: var(--font-serif);
  font-weight: 300;
  font-size: var(--fs-2xl);
  line-height: var(--lh-tight);
  color: var(--cream-hi);
  margin-bottom: 10px;
  text-shadow: 0 0 6px rgba(255,255,245,0.35), 0 0 22px rgba(255,230,180,0.12);
}
.doc-modal-body .doc-sub {
  font-family: var(--font-mono);
  font-size: var(--fs-2xs); font-weight: 300;
  letter-spacing: var(--ls-tracked);
  text-transform: uppercase;
  color: rgba(255, 240, 215, 0.55);
  margin-bottom: 36px;
}
.doc-modal-body .doc-article h2 {
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: var(--fs-lg);
  color: var(--gold-hi);
  margin: 32px 0 12px;
}
.doc-modal-body .doc-article h3 {
  font-family: var(--font-mono);
  font-weight: 400;
  font-size: var(--fs-xs);
  letter-spacing: var(--ls-widest);
  text-transform: uppercase;
  color: rgba(255, 240, 215, 0.78);
  margin: 24px 0 8px;
}
.doc-modal-body .doc-article p,
.doc-modal-body .doc-article li {
  font-family: var(--font-mono);
  font-size: var(--fs-sm); font-weight: 300;
  line-height: var(--lh-loose);
  color: rgba(245, 245, 245, 0.82);
  margin-bottom: 10px;
}
.doc-modal-body .doc-article ul,
.doc-modal-body .doc-article ol { padding-left: 22px; margin-bottom: 14px; }
.doc-modal-body .doc-article a {
  color: var(--gold-hi);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: rgba(212, 184, 150, 0.35);
  transition: text-decoration-color 0.3s ease;
}
.doc-modal-body .doc-article a:hover { text-decoration-color: var(--gold-hi); }
.doc-modal-body .doc-article strong { color: var(--cream-hi); font-weight: 400; }
.doc-modal-body .doc-placeholder {
  margin-top: 32px;
  padding: 16px 20px;
  border: 1px dashed rgba(212, 184, 150, 0.25);
  border-radius: 10px;
  background: rgba(212, 184, 150, 0.03);
  font-size: var(--fs-xs);
  color: rgba(255, 230, 190, 0.7);
  letter-spacing: 0.06em;
}
.doc-modal-body .doc-meta {
  margin-top: 48px;
  padding-top: 20px;
  border-top: 1px solid rgba(212, 184, 150, 0.12);
  font-size: var(--fs-2xs);
  letter-spacing: var(--ls-widest);
  text-transform: uppercase;
  color: rgba(255, 240, 215, 0.5);
}

/* Lock the body scroll while the modal is open. */
body.doc-modal-open { overflow: hidden; }

@media (max-width: 560px) {
  .doc-modal { padding: 12px; }
  .doc-modal-panel { padding: 44px 22px 28px; border-radius: 16px; max-height: 94vh; }
  .doc-modal-close { top: 10px; right: 10px; width: 32px; height: 32px; }
  /* h2 size adapts via clamp on var(--fs-lg); only the spacing tightens. */
  .doc-modal-body .doc-article h2 { margin-top: 26px; }
}

/* ═══ FOOTER — static at end of document; signature stack ═══
   Lives in normal flow after the docs section. A thin gold rule
   separates it from the docs above; "Кузня справжності" sits on
   its own line, with "Україна · MMXXVI" beneath it. */
#site-footer {
  position: relative;
  z-index: 5;
  display: flex; flex-direction: column; align-items: center; justify-content: flex-start;
  gap: 18px;
  padding: 28px 28px calc(32px + env(safe-area-inset-bottom, 0px));
  color: rgba(var(--cream-rgb), 0.95);
}
/* Thin gold rule above the signature — fades at both ends, in the
   same warm-amber family as #section-divider but a touch brighter so
   it reads as the site-end punctuation. */
#site-footer::before {
  content: '';
  display: block;
  height: 1px;
  width: min(720px, 86%);
  background: linear-gradient(90deg,
    transparent 0%,
    rgba(255, 200, 140, 0.18) 18%,
    rgba(var(--rgb-ember), 0.55) 50%,
    rgba(255, 200, 140, 0.18) 82%,
    transparent 100%);
  box-shadow:
    0 0 8px rgba(var(--rgb-ember), 0.18),
    0 0 22px rgba(var(--rgb-amber), 0.06);
}
.footer-tag {
  margin: 0;
  cursor: default;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 14px;
  text-align: center;
}
/* Mirror of #site-footer::before — closes the signature/contact block
   before the docs-nav opens. Same warm-amber gradient + glow as the
   top rule, so the footer reads as a triplet: line · text · line · docs. */
.footer-tag .docs-nav {
  position: relative;
  margin-top: 6px;
  padding-top: 22px;
}
.footer-tag .docs-nav::before {
  content: '';
  position: absolute;
  top: 0; left: 50%;
  transform: translateX(-50%);
  height: 1px;
  width: min(720px, 86%);
  background: linear-gradient(90deg,
    transparent 0%,
    rgba(255, 200, 140, 0.18) 18%,
    rgba(var(--rgb-ember), 0.55) 50%,
    rgba(255, 200, 140, 0.18) 82%,
    transparent 100%);
  box-shadow:
    0 0 8px rgba(var(--rgb-ember), 0.18),
    0 0 22px rgba(var(--rgb-amber), 0.06);
}
/* Glow only on the signature lines — docs nav between them stays calm
   (CSS text-shadow inherits, so the animation must live on these spans
   directly, not on the .footer-tag wrapper). */
.footer-tag-name,
.footer-tag-meta {
  animation: scrollTextGlow 3.2s ease-in-out infinite;
  animation-delay: 0.6s;
}
/* All four footer-tag spans share one style — identical font, size,
   weight, letter-spacing, casing. The footer reads as a single voice
   regardless of which span carries which token (name / place / year
   / handle). Only the meta-row layout is set on .footer-tag-meta. */
.footer-tag-name,
.footer-tag-place,
.footer-tag-year,
.footer-tag-handle {
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  font-weight: 300;
  letter-spacing: var(--ls-tracked);
  text-transform: uppercase;
}
.footer-tag-meta {
  display: inline-flex;
  align-items: baseline;
}
.footer-tag-handle::before,
.footer-tag-year::before {
  content: '·';
  margin: 0 10px;
  opacity: 0.55;
}
@media (max-width: 560px) {
  #site-footer {
    gap: 14px;
    padding: 22px 16px calc(22px + env(safe-area-inset-bottom, 0px));
  }
  .footer-tag { gap: 6px; }
}

/* ═══ ICON NEON ANIMATIONS ═══
   Live icon animations live in the "RAIL CHOICE-ICON ANIMATIONS"
   section below (railFlipBack/railMarch/railForgeSync). The forge
   inferno (.support-icon) has its own keyframes farther down. */

/* ─── SUPPORT · CTA — button static; text a whisper of warm copper ─── */
.support-cta {
  text-shadow:
    0 0 3px rgba(var(--accent-hot), 0.20),
    0 0 8px rgba(var(--accent-dim), 0.10);
}

/* Quiet coal-breath on the same 6-layer ember neon — swings the halo
   intensities while keeping the core bright, so the verb glows in its
   own colour just like the other card verbs. */
.support-verb { animation: supportVerbGlow 4.2s ease-in-out infinite; }
@keyframes supportVerbGlow {
  0%, 100% {
    text-shadow:
      0 0 1px  rgba(var(--accent-hot-hi), 1),
      0 0 4px  rgba(var(--accent-hot-hi), 0.95),
      0 0 12px rgba(var(--accent-hot),    0.78),
      0 0 26px rgba(var(--accent-hot),    0.48),
      0 0 52px rgba(var(--accent-hot),    0.22),
      0 0 88px rgba(var(--accent-hot),    0.08);
  }
  50% {
    text-shadow:
      0 0 2px  rgba(var(--accent-hot-hi), 1),
      0 0 7px  rgba(var(--accent-hot-hi), 1),
      0 0 18px rgba(var(--accent-hot),    0.95),
      0 0 38px rgba(var(--accent-hot),    0.60),
      0 0 72px rgba(var(--accent-hot),    0.32),
      0 0 120px rgba(var(--accent-hot),   0.14);
  }
}

/* ═══ ACCESSIBILITY — reduced motion ═══
   Respect users who prefer reduced motion. Canvas layers are stopped
   from JS; here we kill every CSS animation + transition so nothing
   pulses, bounces, or flickers. The site remains fully readable. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.001s !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001s !important;
    scroll-behavior: auto !important;
  }
  #logo-kova {
    text-shadow: 0 0 2px rgba(255,255,245,0.35);
  }
  #scroll-hint, .scroll-hint-btn,
  #scroll-hint-next, .footer-tag {
    animation: none !important;
  }
}

/* ═══════════════════════════════════════════════════════════════
   SUPPORT CARD · FORGE INFERNO
   Replaces the simple flame SVG with a full blacksmith forge:
   arch structure, coal bed, 3 chaotic flames (coprime timings so
   they never sync), sparks rising, smoke drifting out the mouth.
   ═══════════════════════════════════════════════════════════════ */

.support-icon.forge-inferno .forge-struct {
  fill: none;
  stroke: rgba(235, 225, 210, 0.75);
  stroke-width: 1.3;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.support-icon.forge-inferno .forge-bed {
  fill: rgba(var(--rgb-ember-hi), 0.85);
  filter: drop-shadow(0 0 4px rgba(var(--rgb-ember-hi), 0.7));
  animation: forgeBedGlow 1.8s ease-in-out infinite;
}

.support-icon.forge-inferno .forge-fire {
  fill: rgba(var(--rgb-ember), 0.72);
  transform-origin: center bottom;
  transform-box: fill-box;
}
.support-icon.forge-inferno .forge-fire.f1 { animation: forgeWild1 1.3s cubic-bezier(.4,.1,.6,.9)   infinite;       }
.support-icon.forge-inferno .forge-fire.f2 { animation: forgeWild2 1.7s cubic-bezier(.5,.05,.4,.95) -0.3s infinite; }
.support-icon.forge-inferno .forge-fire.f3 { animation: forgeWild3 1.1s cubic-bezier(.3,.2,.7,.85)  -0.7s infinite; }

.support-icon.forge-inferno .forge-spark {
  fill: rgba(var(--rgb-ember-hi), 0.95);
  opacity: 0;
  transform-origin: center;
  transform-box: fill-box;
  animation: forgeSpark 1.4s ease-out infinite;
}
.support-icon.forge-inferno .forge-spark.p1 { animation-delay: 0s;    }
.support-icon.forge-inferno .forge-spark.p2 { animation-delay: 0.28s; }
.support-icon.forge-inferno .forge-spark.p3 { animation-delay: 0.56s; }
.support-icon.forge-inferno .forge-spark.p4 { animation-delay: 0.84s; }

.support-icon.forge-inferno .forge-smoke {
  fill: none;
  stroke: rgba(200, 200, 205, 0.5);
  stroke-width: 1.3;
  stroke-linecap: round;
  opacity: 0;
  animation: forgeSmoke 3.2s ease-out infinite;
}
.support-icon.forge-inferno .forge-smoke.s1 { animation-delay: 0s;    }
.support-icon.forge-inferno .forge-smoke.s2 { animation-delay: 1.1s;  }
.support-icon.forge-inferno .forge-smoke.s3 { animation-delay: 2.2s;  }

/* Hover: intensify chaos slightly (card already scales the whole icon) */
.support-card:hover .support-icon.forge-inferno .forge-bed   { filter: drop-shadow(0 0 8px rgba(var(--rgb-ember-hi), 1)); }

@keyframes forgeBedGlow {
  0%, 100% { opacity: 0.7; }
  50%      { opacity: 1;   }
}

@keyframes forgeWild1 {
  0%   { transform: scaleY(1)    rotate(-3deg) skewX(-2deg); filter: brightness(1)    drop-shadow(0 0 5px  rgba(var(--rgb-ember-hi), 0.6));  opacity: 0.85; }
  18%  { transform: scaleY(1.3)  rotate(5deg)  skewX(3deg);  filter: brightness(1.5)  drop-shadow(0 0 14px rgba(var(--rgb-ember-hi), 0.95)); opacity: 1;    }
  35%  { transform: scaleY(1.08) rotate(-4deg) skewX(-1deg); filter: brightness(1.1);                                                          opacity: 0.9;  }
  55%  { transform: scaleY(1.4)  rotate(6deg)  skewX(2deg);  filter: brightness(1.45) drop-shadow(0 0 12px rgba(var(--rgb-ember-hi), 0.9));  opacity: 1;    }
  78%  { transform: scaleY(0.9)  rotate(-2deg) skewX(-3deg); filter: brightness(0.85);                                                         opacity: 0.8;  }
  100% { transform: scaleY(1)    rotate(-3deg) skewX(-2deg); filter: brightness(1);                                                             opacity: 0.85; }
}
@keyframes forgeWild2 {
  0%   { transform: scaleY(1.1)  rotate(4deg)  skewX(2deg);  filter: brightness(1.1);                                                           opacity: 0.9;  }
  22%  { transform: scaleY(0.95) rotate(-5deg) skewX(-3deg); filter: brightness(0.85);                                                          opacity: 0.8;  }
  45%  { transform: scaleY(1.4)  rotate(3deg)  skewX(4deg);  filter: brightness(1.5)  drop-shadow(0 0 16px rgba(var(--rgb-ember-hi), 0.95));  opacity: 1;    }
  66%  { transform: scaleY(1.12) rotate(-6deg) skewX(-2deg); filter: brightness(1.2);                                                           opacity: 0.95; }
  85%  { transform: scaleY(1.28) rotate(2deg)  skewX(3deg);  filter: brightness(1.4);                                                           opacity: 1;    }
  100% { transform: scaleY(1.1)  rotate(4deg)  skewX(2deg);  filter: brightness(1.1);                                                           opacity: 0.9;  }
}
@keyframes forgeWild3 {
  0%   { transform: scaleY(0.95) rotate(-4deg) skewX(-3deg); filter: brightness(0.9);                                                          opacity: 0.8;  }
  24%  { transform: scaleY(1.25) rotate(4deg)  skewX(2deg);  filter: brightness(1.3);                                                           opacity: 0.95; }
  42%  { transform: scaleY(1.05) rotate(-5deg) skewX(-4deg); filter: brightness(0.95);                                                          opacity: 0.85; }
  62%  { transform: scaleY(1.45) rotate(3deg)  skewX(3deg);  filter: brightness(1.5)  drop-shadow(0 0 12px rgba(var(--rgb-ember-hi), 0.9));   opacity: 1;    }
  84%  { transform: scaleY(1)    rotate(-2deg) skewX(-1deg); filter: brightness(1);                                                              opacity: 0.9;  }
  100% { transform: scaleY(0.95) rotate(-4deg) skewX(-3deg); filter: brightness(0.9);                                                          opacity: 0.8;  }
}

@keyframes forgeSpark {
  0%   { transform: translate(0, 0)     scale(1);    opacity: 1; }
  100% { transform: translate(0, -22px) scale(0.15); opacity: 0; }
}

@keyframes forgeSmoke {
  0%   { opacity: 0;    transform: translateY(0)     scale(0.8);  }
  12%  { opacity: 0.55;                                            }
  55%  { opacity: 0.45;                                            }
  100% { opacity: 0;    transform: translateY(-34px) scale(0.35); }
}

/* ═══════════════════════════════════════════════════════════════
   RAIL ICON ANIMATIONS — triggered on card hover ("обирають блок")
   Each role gets a signature motion that reflects its meaning:
     Свідок  · flip       → two options alternate (back grows as front fades)
     Учень   · slow march → dashes march around the outer triangle
     Коваль  · sync       → stroke-weight + drop-shadow breathe together
   ═══════════════════════════════════════════════════════════════ */

/* ── FOLLOW · FLIP ─────────────────────────────────────────── */
.choice-card[data-choice="follow"]:hover .choice-icon path.back {
  transform-origin: center;
  transform-box: fill-box;
  animation: railFlipBack 2.4s ease-in-out infinite;
}
.choice-card[data-choice="follow"]:hover .choice-icon path.front {
  transform-origin: center;
  transform-box: fill-box;
  animation: railFlipFront 2.4s ease-in-out infinite;
}
@keyframes railFlipBack {
  0%, 100% { transform: scale(1);    opacity: 0.35; }
  50%      { transform: scale(1.08); opacity: 1;    }
}
@keyframes railFlipFront {
  0%, 100% { transform: scale(1);    opacity: 1;   }
  50%      { transform: scale(0.88); opacity: 0.2; }
}

/* ── LEARN · SLOW MARCH ────────────────────────────────────── */
.choice-card[data-choice="learn"]:hover .choice-icon path.outer {
  stroke-dasharray: 4 3;
  animation: railMarch 3s linear infinite;
}
@keyframes railMarch { to { stroke-dashoffset: -14; } }

/* ── FORGE · SYNC (weight + glow) ──────────────────────────── */
.choice-card[data-choice="forge"]:hover .choice-icon path {
  animation: railForgeSync 2.4s ease-in-out infinite;
}
@keyframes railForgeSync {
  0%, 100% {
    stroke-width: 1.5;
    filter: drop-shadow(0 0 2px rgba(var(--accent-hi), 0.55));
  }
  50% {
    stroke-width: 2.8;
    filter: drop-shadow(0 0 10px rgba(var(--accent-hi), 1))
            drop-shadow(0 0 22px rgba(var(--accent),    0.6));
  }
}

/* ═══════════════════════════════════════════════════════════════
   BENTO STAGE — nested views that replace the 3 choice cards.
   .forge[data-view="root"]  → the 3 choice cards are visible
   .forge[data-view="follow" | "learn" | "forge" | ...] → choices
     shatter outward and the matching .bento grid emerges in place.
   ═══════════════════════════════════════════════════════════════ */

.forge-main {
  position: relative;
  width: 100%;
  max-width: 1400px;
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: 1fr;
  grid-template-rows: 1fr;
}
.forge-main > .choices    { grid-area: 1 / 1; width: 100%; min-height: 0; z-index: var(--z-content); }
.forge-main > .bento-stage { grid-area: 1 / 1; width: 100%; min-height: 0; z-index: 2; }

/* ── Choices shatter/return — scale + blur + fade, symmetric. Base
   transition doubles as hover + return-to-root. */
.choice-card {
  /* Split hover feedback from motion: border/shadow light up instantly
     (~180ms) so the ring responds to the cursor without lag; transform
     (lift) keeps its longer curve for the smooth physical feel. */
  transition:
    opacity      0.45s var(--ease-silk),
    border-color 0.18s var(--ease-silk),
    transform    0.45s var(--ease-silk),
    box-shadow   0.18s var(--ease-silk),
    filter       0.45s var(--ease-silk);
}
.forge:not([data-view="root"]) .choices { pointer-events: none; }

/* Return-to-root — choice cards re-emerge AFTER the bento cascade
   clears, then cascade in themselves on per-card stagger (--i set
   on each .choice-card in markup: follow=0, learn=1, forge=2). 0.5 s
   base delay gives the first bento card time to dissolve; from there
   each choice card takes its 90 ms turn so they appear "Відчувай →
   Пізнавай → Куй" rather than all at once. */
.forge[data-returning="1"] .choice-card {
  transition:
    opacity      0.40s var(--ease-silk) calc(0.50s + var(--i, 0) * 90ms),
    transform    0.50s var(--ease-silk) calc(0.50s + var(--i, 0) * 90ms),
    filter       0.40s var(--ease-silk) calc(0.50s + var(--i, 0) * 90ms),
    border-color 0.55s var(--ease-silk),
    box-shadow   0.55s var(--ease-silk);
}

.forge:not([data-view="root"]) .choice-card {
  opacity: 0;
  transform: scale(0.38);
  filter: blur(10px);
  transition:
    opacity   0.32s var(--ease-silk),
    transform 0.38s var(--ease-silk),
    filter    0.32s var(--ease-silk);
}

/* Performance: while a forge view is changing, drop the heaviest GPU
   work so the staggered card animations have full bandwidth.
   Empirically (audited via two perf agents) the dominant costs were:
     1. backdrop-filter on 12 bento + 3 choice cards re-sampling the
        underlying paint every frame
     2. filter:blur(10px) animating on all 15 cards simultaneously
     3. decorative keyframe animations (forge-fire flicker, credo
        glow, verb neon) compounding paint thrash on elements
        positioned behind/around the cards
   The user's eyes are on the cards during the 1.1s window; pausing
   the ambient effects is invisible but reclaims ~30-40% GPU per
   frame. background.js + logo.js also short-circuit their RAF work
   when this class is present. */
body.forge-transitioning .bento-card,
body.forge-transitioning .choice-card {
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}
body.forge-transitioning .support-icon.forge-inferno .forge-fire,
body.forge-transitioning .credo-text,
body.forge-transitioning .bento-verb,
body.forge-transitioning .choice-verb {
  animation-play-state: paused !important;
}

/* ── Bento stage: flat 3×2 grid, every tile the same size ── */
.bento-stage {
  position: relative;
  pointer-events: none;
}
.bento {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(2, 1fr);
  gap: 16px;
  pointer-events: none;
  /* Inactive bento is fully hidden from paint — even at opacity:0 the
     card's backdrop-filter + scaled box-shadow bleed through behind
     the choice cards. The visibility flip has to wait for the LAST
     staggered card to finish exiting: card with max --i (=7 on an
     8-tile grid) starts at 385 ms and ends transform at 1035 ms.
     1100 ms covers that with a small margin so no card is suddenly
     hidden mid-flight. */
  visibility: hidden;
  transition: visibility 0s linear 1.10s;
}
.forge[data-view="follow"]          .bento[data-bento-view="follow"],
.forge[data-view="learn"]           .bento[data-bento-view="learn"],
.forge[data-view="learn-mechanics"] .bento[data-bento-view="learn-mechanics"],
.forge[data-view="forge"]           .bento[data-bento-view="forge"] {
  visibility: visible;
  transition-delay: 0s;
}
/* Forge view ships 12 tiles (Назад + 11 продуктів) → 4×3 grid.
   Learn view ships 8 tiles (Назад + 7 уроків) → 4×2 grid.
   Learn·Mechanics drill-down ships 10 tiles (Назад + 9 складників) → 5×2.
   Other views keep the default 3×2. */
.bento[data-bento-view="forge"] {
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: repeat(3, 1fr);
  gap: 12px;
}
.bento[data-bento-view="learn"] {
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: repeat(2, 1fr);
  gap: 12px;
}
.bento[data-bento-view="learn-mechanics"] {
  grid-template-columns: repeat(5, 1fr);
  grid-template-rows: repeat(2, 1fr);
  gap: 12px;
}

/* ── Forge card v2 layout: tag (top-left), status (top-right),
   verb (center), body/embodiment (bottom). ── */
.bento[data-bento-view="forge"] .bento-status {
  position: absolute;
  top: 14px;
  right: 18px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-mono);
  font-weight: 300;
  font-size: var(--fs-3xs);
  letter-spacing: var(--ls-tracked);
  text-transform: uppercase;
  color: rgba(var(--accent), 0.78);
  z-index: 2;
}
.bento[data-bento-view="forge"] .bento-status::before {
  content: '';
  width: 5px; height: 5px;
  border-radius: 50%;
  background: rgba(var(--accent-hi), 0.9);
  box-shadow: 0 0 6px rgba(var(--accent-hi), 0.7), 0 0 12px rgba(var(--accent), 0.5);
}
.bento[data-bento-view="forge"] .bento-card.bento-forging .bento-status::before {
  animation: forgingPulse 1.8s ease-in-out infinite;
}
.bento[data-bento-view="forge"] .bento-card.bento-queued .bento-status::before {
  background: rgba(var(--accent), 0.45);
  box-shadow: none;
  animation: none;
}
.bento[data-bento-view="forge"] .bento-body {
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 300;
  font-size: var(--fs-subtitle);
  line-height: var(--lh-normal);
  letter-spacing: var(--ls-snug);
  text-transform: lowercase;
  color: rgba(var(--accent-hi), 0.95);
}

/* Forge-view tag: steady neon. No flicker, no pulse — просто світиться.
   Strongest text accent in the view: full-saturation core + deep 6-layer
   ember halo so it outglows the verb, sub, body, and status around it. */
.bento[data-bento-view="forge"] .bento-tag {
  color: rgba(var(--accent-hi), 1);
  text-shadow:
    0 0 1px  rgba(var(--accent-hi), 1),
    0 0 4px  rgba(var(--accent-hi), 0.95),
    0 0 12px rgba(var(--accent),    0.8),
    0 0 26px rgba(var(--accent),    0.55),
    0 0 52px rgba(var(--accent),    0.28),
    0 0 90px rgba(var(--accent),    0.12);
}
.bento[data-bento-view="forge"] .bento-card.bento-queued .bento-tag {
  /* Same glow — just a touch less saturated core so forging cards still
     read as primary. The halo stays full; the letters remain lit. */
  color: rgba(var(--accent-hi), 0.9);
}
.bento[data-bento-view="forge"] .bento-card.bento-queued:hover .bento-tag {
  color: rgba(var(--accent-hi), 1);
}
.bento[data-bento-view="forge"] .bento-card.bento-queued .bento-body {
  color: rgba(var(--accent-hi), 0.7);
}

/* Blurred verb — placeholder text under a Gaussian smudge so it reads
   as "a word was here" rather than a solid rectangle. Drops the glow
   because it would haloo through the blur. */
.bento-verb--blurred {
  filter: blur(6px);
  user-select: none;
  pointer-events: none;
  opacity: 0.82;
  text-shadow: none;
  color: rgba(var(--accent-hi), 0.78);
}
/* In forge view the blurred text carries longer questions; a smaller
   fluid size keeps them on one or two lines without clipping. */
.bento[data-bento-view="forge"] .bento-verb--blurred {
  font-size: var(--fs-verb);
  line-height: var(--lh-snug);
}
@media (prefers-reduced-motion: reduce) {
  .bento-verb--blurred { filter: blur(4px); }
}
.bento[data-bento-view="forge"] .bento-card { padding: 18px 20px; border-radius: 18px; }
.bento[data-bento-view="forge"] .bento-verb {
  font-size: var(--fs-verb);
  line-height: var(--lh-tight);
}
/* .bento-sub is a constant 20px across all views — no per-view size
   override. Colour differs per platform, nothing else. */

/* ── Learn card (bento-lesson): tag at top, title centered, question at
   bottom. Each tile is a chapter of the path and expands into its own
   section on click. Same frosted frame as other bentos, just resized
   for phrase-length titles in a 4×2 grid. ── */
.bento[data-bento-view="learn"] .bento-card { padding: 18px 20px; border-radius: 18px; }
.bento[data-bento-view="learn"] .bento-card.bento-lesson {
  /* Layout handled by the universal `.bento-card:has(.bento-tag)`
     grid rule; here we only add pointer + text-align context. */
  text-align: left;
  cursor: pointer;
}
.bento[data-bento-view="learn"] .bento-lesson .bento-verb {
  font-family: var(--font-display);
  font-weight: 200;
  font-size: var(--fs-verb);
  line-height: var(--lh-snug);
  letter-spacing: var(--ls-snug);
  /* `\n` in the JSON string is kept as a real line break so long
     phrases can break in the designed place (e.g. "Середовище /
     формує тебе"). Short titles have no `\n` and stay on one line. */
  white-space: pre-line;
  color: rgba(var(--accent-hi), 1);
  /* 6-layer neon tube — brighter than the generic .bento-verb so the
     learn titles carry real accent. Bright ember-hi core, ember halo
     fading outward: same anatomy as .choice-verb on hover, just
     steady (no flicker). */
  text-shadow: var(--text-neon-stack);
}
.bento[data-bento-view="learn"] .bento-lesson .bento-sub {
  /* Inherit the constant 20px / italic serif rhythm from .bento-sub.
     Learn only dims the colour to 0.72 — questions read as secondary. */
  color: rgba(var(--accent-hi), 0.72);
}

/* Learn-view tag: same steady neon tube as the forge tags. Strongest
   accent in the tile — the chapter label owns the identity. */
.bento[data-bento-view="learn"] .bento-tag {
  color: rgba(var(--accent-hi), 1);
  text-shadow:
    0 0 1px  rgba(var(--accent-hi), 1),
    0 0 4px  rgba(var(--accent-hi), 0.95),
    0 0 12px rgba(var(--accent),    0.8),
    0 0 26px rgba(var(--accent),    0.55),
    0 0 52px rgba(var(--accent),    0.28),
    0 0 90px rgba(var(--accent),    0.12);
}

/* Transition tile (last card, "Вдар один раз сьогодні") — hot accent
   borrowed from the support card. It's the CTA of this view: the step
   out of thinking and into action. */
.bento-card.bento-lesson--transition {
  --accent:    var(--rgb-ember);
  --accent-hi: var(--rgb-ember-hi);
}

/* Mechanics tile (6th card, "Як з металу постає форма") — drills into
   the 9-part mechanics view; visually highlighted as the core chapter
   of the Learn track. Warm ember accent + subtle persistent glow so it
   catches peripheral vision without competing with the transition CTA. */
.bento-card.bento-lesson--mechanics {
  --accent:    var(--rgb-ember);
  --accent-hi: var(--rgb-ember-hi);
  border-color: rgba(var(--rgb-ember), 0.28);
  background: linear-gradient(180deg,
    rgba(var(--rgb-ember), 0.07) 0%,
    rgba(var(--rgb-ember-deep), 0.02) 100%);
  box-shadow:
    inset 0 1px 0 rgba(255, 240, 220, 0.08),
    0 14px 40px rgba(0,0,0,0.30),
    0 0 28px -8px rgba(var(--rgb-ember), 0.32);
}

/* ── Sequence number — quiet neon digit in the bottom-right corner of
   every chapter-style card (Learn lessons + Forge products). Pulled
   from the `data-num` attribute via CSS `attr()` so HTML stays clean.
   Small display-serif glyph with a 6-layer ember halo, dimmer in the
   core so it reads as a chapter marker rather than competing with the
   title. Brightens on hover along with the card border. ── */
.bento-card.bento-lesson::after,
.bento-card.bento-forging::after,
.bento-card.bento-queued::after,
.bento-card.bento-mech::after {
  content: attr(data-num);
  position: absolute;
  bottom: 12px;
  right: 16px;
  font-family: var(--font-display);
  font-weight: 200;
  font-size: var(--fs-lg);
  line-height: 1;
  letter-spacing: 0;
  color: rgba(var(--accent-hi), 0.5);
  text-shadow:
    0 0 1px  rgba(var(--accent-hi), 0.8),
    0 0 4px  rgba(var(--accent-hi), 0.65),
    0 0 10px rgba(var(--accent),    0.5),
    0 0 22px rgba(var(--accent),    0.28),
    0 0 44px rgba(var(--accent),    0.12),
    0 0 76px rgba(var(--accent),    0.05);
  pointer-events: none;
  transition: color 0.25s var(--ease-silk), text-shadow 0.25s var(--ease-silk);
}
.bento-card.bento-lesson:hover::after,
.bento-card.bento-forging:hover::after,
.bento-card.bento-queued:hover::after,
.bento-card.bento-mech:hover::after {
  color: rgba(var(--accent-hi), 0.9);
  text-shadow:
    0 0 1px  rgba(var(--accent-hi), 1),
    0 0 4px  rgba(var(--accent-hi), 0.95),
    0 0 12px rgba(var(--accent),    0.7),
    0 0 26px rgba(var(--accent),    0.42),
    0 0 52px rgba(var(--accent),    0.2);
}

/* Mechanics-only override: number sits at the TOP of the card (right
   corner, mirroring the bento-tag at the top-left) so the 9 parts of
   "Як працює кузня" read as a numbered chapter index from the top. */
.bento-card.bento-mech::after {
  top: 14px;
  right: 16px;
  bottom: auto;
}

/* ── Learn · Mechanics sub-view: 10 tiles (Назад + 9 складників) in a
   5×2 grid. Each card carries a tag (МАТЕРІАЛ / НАПРУГА …), a single
   concept word (Метал, Вогонь…), and a question. Same vertical rhythm
   as the main learn lessons: tag top, verb middle, sub at the bottom.
   These will drill down further into their own explanations. ── */
.bento[data-bento-view="learn-mechanics"] .bento-card { padding: 18px 20px; border-radius: 18px; }
.bento[data-bento-view="learn-mechanics"] .bento-card.bento-mech {
  /* Layout handled by the universal `.bento-card:has(.bento-tag)`
     grid rule; here we only add pointer + text-align context. */
  text-align: left;
  cursor: pointer;
}
.bento[data-bento-view="learn-mechanics"] .bento-mech .bento-verb {
  font-family: var(--font-display);
  font-weight: 200;
  font-size: var(--fs-verb);
  letter-spacing: var(--ls-base);
  line-height: var(--lh-tight);
  color: rgba(var(--accent-hi), 1);
  text-shadow:
    0 0 1px  rgba(var(--accent-hi), 1),
    0 0 4px  rgba(var(--accent-hi), 0.9),
    0 0 14px rgba(var(--accent),    0.55),
    0 0 34px rgba(var(--accent),    0.22);
}
.bento[data-bento-view="learn-mechanics"] .bento-mech .bento-sub {
  /* Questions read as secondary — same 20px constant, colour dimmed to
     match the learn-lesson subtitle treatment. */
  color: rgba(var(--accent-hi), 0.72);
}

/* Mechanics tag: same steady-neon tube as the main learn and forge
   tags, so the whole system speaks one language. */
.bento[data-bento-view="learn-mechanics"] .bento-tag {
  color: rgba(var(--accent-hi), 1);
  text-shadow:
    0 0 1px  rgba(var(--accent-hi), 1),
    0 0 4px  rgba(var(--accent-hi), 0.95),
    0 0 12px rgba(var(--accent),    0.8),
    0 0 26px rgba(var(--accent),    0.55),
    0 0 52px rgba(var(--accent),    0.28),
    0 0 90px rgba(var(--accent),    0.12);
}

.forge[data-view="follow"]          .bento[data-bento-view="follow"],
.forge[data-view="learn"]           .bento[data-bento-view="learn"],
.forge[data-view="learn-mechanics"] .bento[data-bento-view="learn-mechanics"],
.forge[data-view="forge"]           .bento[data-bento-view="forge"] {
  pointer-events: auto;
}

/* ── Bento card — shares frosted aesthetic with .choice-card.
   EXIT (base, no selector): fast uniform collapse (scale+blur+fade).
   ENTER (active selector): slower, staggered, delayed so choice cards
   get out of the way first. This asymmetry is what kills the "коряве"
   return feel — exiting bentos don't linger. */
.bento-card {
  --accent:    212, 184, 150;
  --accent-hi: 246, 226, 188;
  position: relative;
  /* Flex is the fallback layout (used by Follow cards which have
     only verb + sub). Cards that carry a tag switch to a 3-row grid
     below (.bento-card:has(.bento-tag)) so tag / verb / sub anchor
     at identical Y positions across every tile — short content no
     longer makes cards feel uneven. */
  display: flex; flex-direction: column; justify-content: space-between;
  align-items: flex-start;
  gap: 6px;
  padding: 22px 24px;
  text-align: left;
  text-decoration: none;
  border-radius: 20px;
  overflow: hidden;
  isolation: isolate;
  background: linear-gradient(180deg,
    rgba(255,255,255,0.020) 0%,
    rgba(255,255,255,0.008) 55%,
    rgba(255,255,255,0.003) 100%);
  backdrop-filter: blur(6px) saturate(115%);
  -webkit-backdrop-filter: blur(6px) saturate(115%);
  border: 1px solid rgba(255, 235, 210, 0.07);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.04),
    0 14px 40px rgba(0,0,0,0.30);
  color: rgba(var(--accent-hi), 0.95);
  cursor: pointer;
  font: inherit;
  will-change: transform, opacity, filter;

  /* Default state = exit pose. The transition stagger is the REVERSE
     of the enter cascade so back reads as "last in, first out" —
     the bottom-right card that emerged last dissolves first; the
     back-tile (card 0, top-left) stays until the very end. Without
     this reversal, back used the same 0→N order as forward, which
     felt like a continuation of the wave rather than its undoing.
     The constant 7 is the max --i across all bento grids (8-card
     follow + learn lessons); shorter grids end up with a slightly
     compressed but still right-to-left cascade. backdrop-filter is
     killed via body.forge-transitioning to keep this affordable. */
  opacity: 0;
  transform: scale(0.30);
  filter: blur(10px);
  transition:
    opacity      0.55s var(--ease-silk) calc((7 - var(--i, 0)) * 55ms),
    transform    0.65s var(--ease-silk) calc((7 - var(--i, 0)) * 55ms),
    filter       0.55s var(--ease-silk) calc((7 - var(--i, 0)) * 55ms),
    border-color 0.18s var(--ease-silk),
    box-shadow   0.18s var(--ease-silk);
}

/* Enter state — slower, staggered, delayed so the exiting layer clears
   first. Asymmetry is what gives the "shatter → emerge" feel.
   Per-property delays: enter fx (opacity/transform/filter) wait for
   the stagger, but border-color/box-shadow have ZERO delay so hover
   rings light up instantly, not after 200–500 ms. */
.forge[data-view="follow"]          .bento[data-bento-view="follow"]          .bento-card,
.forge[data-view="learn"]           .bento[data-bento-view="learn"]           .bento-card,
.forge[data-view="learn-mechanics"] .bento[data-bento-view="learn-mechanics"] .bento-card,
.forge[data-view="forge"]           .bento[data-bento-view="forge"]           .bento-card {
  opacity: 1;
  transform: scale(1);
  filter: blur(0);
  transition:
    opacity      0.55s var(--ease-silk) calc(0.22s + var(--i, 0) * 55ms),
    transform    0.65s var(--ease-silk) calc(0.22s + var(--i, 0) * 55ms),
    filter       0.55s var(--ease-silk) calc(0.22s + var(--i, 0) * 55ms),
    border-color 0.18s var(--ease-silk) 0s,
    box-shadow   0.18s var(--ease-silk) 0s;
}

/* ═══ CARD ALIGNMENT GRID ═══════════════════════════════════════
   Cards that carry a tag (Learn lessons, Mechanics, Forge) switch
   from flex to a fixed 3-row grid so every element anchors at the
   same Y position across the view — tag top, verb middle (with a
   min-height that reserves two lines so single-line and two-line
   titles share the same vertical slot), sub/body bottom.

   The middle 1fr row absorbs leftover space; tag + sub remain
   pinned regardless of content length. `:has()` keeps the rule
   scoped to tagged cards only, so Follow cards (no tag) keep
   their flex layout. ──────────────────────────────────────────── */
.bento-card:has(.bento-tag) {
  display: grid;
  grid-template-rows: auto 1fr auto;
  row-gap: 14px;
  /* Reset the flex gap from the base rule so grid row-gap is the
     single source of vertical spacing between sections. */
  gap: 14px;
}
.bento-card:has(.bento-tag) > .bento-tag    { grid-row: 1; }
.bento-card:has(.bento-tag) > .bento-verb   { grid-row: 2; align-self: start; }
.bento-card:has(.bento-tag) > .bento-sub,
.bento-card:has(.bento-tag) > .bento-body   {
  grid-row: 3;
  /* Bottom-anchor the content inside the reserved 2.8em slot below —
     single-line subtitles sit on the same baseline as two-line ones. */
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
}

/* Reserve two title-lines of vertical space so a 1-line verb still
   occupies the same area as "Як з металу / постає форма". Values
   are per-view because each layout uses a different verb line-height.
   Kept in `em` so the reservation scales with the clamp()-sized font. */
.bento[data-bento-view="learn"]           .bento-lesson  .bento-verb { min-height: 2.4em; } /* LH 1.2 × 2 */
.bento[data-bento-view="learn-mechanics"] .bento-mech    .bento-verb { min-height: 2.2em; } /* LH 1.1 × 2 */
.bento[data-bento-view="forge"]           .bento-forging .bento-verb,
.bento[data-bento-view="forge"]           .bento-queued  .bento-verb { min-height: 2.3em; } /* LH 1.15 × 2 */

/* Same idea for subs/bodies: two-line reservation, bottom-anchored
   (via align-self: end above) so the last line of every subtitle
   lands on the same baseline across cards. Relative to the 19px
   sub font-size, 2×1.4 line-height ≈ 2.8em. */
.bento-card:has(.bento-tag) > .bento-sub,
.bento-card:has(.bento-tag) > .bento-body {
  min-height: 2.8em;
}

.bento-card::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    radial-gradient(ellipse at 50% 120%,
      rgba(var(--accent), 0.22) 0%,
      rgba(var(--accent), 0.06) 45%,
      transparent 72%);
  opacity: 0.7;
  transition: opacity 0.30s var(--ease-silk);
  pointer-events: none;
}

.bento-card:hover {
  border-color: rgba(var(--accent), 0.5);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.08),
    0 18px 44px rgba(0,0,0,0.40),
    0 0 0 1px rgba(var(--accent), 0.30),
    0 0 60px -10px rgba(var(--accent), 0.35);
}
.bento-card:hover::before { opacity: 1; }

.bento-card:focus-visible {
  outline: none;
  border-color: rgba(var(--accent), 0.7);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.08),
    0 0 0 2px rgba(var(--accent), 0.55);
}

.bento-verb {
  font-family: var(--font-display);
  font-weight: 200;
  font-size: var(--fs-verb);
  letter-spacing: var(--ls-base);
  line-height: var(--lh-tight);
  color: rgba(var(--accent-hi), 1);
  text-shadow:
    0 0 2px  rgba(var(--accent-hi), 0.9),
    0 0 14px rgba(var(--accent),    0.45),
    0 0 34px rgba(var(--accent),    0.18);
}
.bento-sub {
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 300;
  /* CONSTANT across all three bento views — Follow, Learn, Forge.
     Only the colour changes per platform/state; the size, weight,
     family, and rhythm stay the same for equal readability.
     `white-space: pre-line` so `\n` in translated strings renders
     as a real line break (used in mechanics subs). */
  font-size: var(--fs-subtitle);
  line-height: var(--lh-normal);
  letter-spacing: var(--ls-snug);
  white-space: pre-line;
  color: rgba(var(--accent-hi), 0.92);
}

/* ── Platform icon: official brand mark with the same 2-layer neon
   glow as .choice-icon — tight bright core + softer coloured halo,
   in the card's own accent. Matches the site's existing "lit glass"
   feel without over-saturating. ── */
.bento-icon {
  position: absolute;
  top: 20px;
  right: 22px;
  width: clamp(30px, 2.6vw, 42px);
  height: clamp(30px, 2.6vw, 42px);
  color: rgba(var(--accent-hi), 0.92);
  filter:
    drop-shadow(0 0 3px  rgba(var(--accent-hi), 0.75))
    drop-shadow(0 0 12px rgba(var(--accent),    0.38));
  pointer-events: none;
  transition: color 0.30s var(--ease-silk), filter 0.30s var(--ease-silk);
}
.bento-card:hover .bento-icon {
  color: rgba(var(--accent-hi), 1);
  filter:
    drop-shadow(0 0 3px  rgba(var(--accent-hi), 0.9))
    drop-shadow(0 0 16px rgba(var(--accent),    0.55));
}

/* ── Per-platform accents — each icon glows in its own brand colour ── */
.bento-card[data-platform="instagram"] { --accent: 230, 135, 180; --accent-hi: 255, 200, 225; }
.bento-card[data-platform="youtube"]   { --accent: 230,  80,  80; --accent-hi: 255, 160, 160; }
.bento-card[data-platform="threads"]   { --accent: 215, 215, 225; --accent-hi: 245, 245, 255; }
.bento-card[data-platform="tiktok"]    { --accent:  90, 220, 215; --accent-hi: 160, 245, 240; }
.bento-card[data-platform="telegram"]  { --accent: 100, 170, 230; --accent-hi: 170, 210, 250; }
.bento-card[data-platform="learn"]     { --accent: var(--path-apprentice); --accent-hi: var(--path-apprentice-hi); }
.bento-card[data-platform="forge"]     { --accent: var(--path-smith);      --accent-hi: var(--path-smith-hi); }
.bento-card[data-platform="back"]      { --accent: 170, 162, 148; --accent-hi: 218, 210, 198; }

/* ── Back tile: arrow + "Назад" on one line. Returns the user to the
   root forge view; styled like a card so it sits cleanly as tile #1
   in the bento grid. ── */
.bento-card.bento-backtile {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: center;
  gap: 14px;
  text-align: left;
}
.bento-card.bento-backtile .bento-icon {
  position: static;
  width: clamp(38px, 3.4vw, 52px);
  height: clamp(38px, 3.4vw, 52px);
  margin-bottom: 0;
}
.bento-card.bento-backtile .bento-verb {
  font-size: var(--fs-verb);
}

/* ── Small uppercase tag above the verb: "книга" / "застосунок".
   Tinted in accent-hi with a subtle neon halo so it reads as lit
   metal rather than plain label text. ── */
.bento-tag {
  font-family: var(--font-mono);
  font-weight: 300;
  font-size: var(--fs-2xs);
  letter-spacing: var(--ls-extra-tracked);
  text-transform: uppercase;
  color: rgba(var(--accent-hi), 0.92);
  text-shadow:
    0 0 2px  rgba(var(--accent-hi), 0.7),
    0 0 8px  rgba(var(--accent),    0.35),
    0 0 18px rgba(var(--accent),    0.15);
}
/* ── Forging state: slow pulsing dot next to the subtitle so the
   viewer feels "work in progress" without any visual noise. ── */
.bento-card.bento-forging .bento-sub {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.bento-card.bento-forging .bento-sub::before {
  content: '';
  width: 6px; height: 6px;
  border-radius: 50%;
  background: rgba(var(--accent-hi), 0.9);
  box-shadow: 0 0 6px rgba(var(--accent-hi), 0.9), 0 0 14px rgba(var(--accent), 0.6);
  animation: forgingPulse 1.8s ease-in-out infinite;
}
@keyframes forgingPulse {
  0%, 100% { opacity: 0.4; transform: scale(0.85); }
  50%      { opacity: 1;   transform: scale(1.15); }
}

/* ── Queued state: name is public and the card IS clickable (each
   product has its own landing), but dimmed so the active ones read
   as the primary CTA. Hover restores full brightness.
   NOTE: opacity is NOT set here — it's applied only in the active-view
   selector below. Otherwise the 0.72 would override the exit opacity:0
   in the base .bento-card rule, causing 9 of 12 tiles to linger at 72 %
   during back-navigation (read: "double load" feel). ── */
.forge[data-view="follow"] .bento[data-bento-view="follow"] .bento-card.bento-queued,
.forge[data-view="learn"]  .bento[data-bento-view="learn"]  .bento-card.bento-queued,
.forge[data-view="forge"]  .bento[data-bento-view="forge"]  .bento-card.bento-queued {
  opacity: 0.72;
}
.bento-card.bento-queued .bento-verb {
  color: rgba(var(--accent), 0.75);
  text-shadow:
    0 0 1px rgba(var(--accent), 0.5),
    0 0 6px rgba(var(--accent), 0.15);
  transition: color 0.35s var(--ease-silk), text-shadow 0.35s var(--ease-silk);
}
.bento-card.bento-queued .bento-sub {
  font-family: var(--font-mono);
  font-style: normal;
  font-size: var(--fs-2xs);
  letter-spacing: var(--ls-extra-tracked);
  text-transform: uppercase;
  color: rgba(var(--rgb-amber), 0.45);
}
.forge[data-view="follow"] .bento[data-bento-view="follow"] .bento-card.bento-queued:hover,
.forge[data-view="learn"]  .bento[data-bento-view="learn"]  .bento-card.bento-queued:hover,
.forge[data-view="forge"]  .bento[data-bento-view="forge"]  .bento-card.bento-queued:hover {
  opacity: 1;
}
.bento-card.bento-queued:hover .bento-verb {
  color: rgba(var(--accent-hi), 1);
  text-shadow:
    0 0 2px rgba(var(--accent-hi), 0.9),
    0 0 14px rgba(var(--accent), 0.5);
}
/* Queued cards without a landing (PERO) render as div — keep non-interactive.
   Forging cards with external links render as <a> and stay clickable. */
div.bento-card.bento-queued { cursor: default; pointer-events: none; }
@media (prefers-reduced-motion: reduce) {
  .bento-card.bento-forging .bento-sub::before { animation: none; opacity: 0.8; }
}

/* ── Mobile: 2 columns × 3 visible rows = 6 cards on screen.
   Views with more cards (8/10/12) keep the SAME card size; the extras
   fall below and scroll into view. ── */
@media (max-width: 820px) {
  .bento-card { padding: 12px 14px; border-radius: 14px; }

  /* Card text — verbs and subs scale through --fs-verb / --fs-subtitle
     tokens, so all bento views read at one consistent rhythm. The only
     per-view tweak here is reserving room for the bento-icon so the
     verb never collides with the social brand mark in the corner. */
  .bento-verb,
  .bento[data-bento-view="forge"] .bento-verb,
  .bento[data-bento-view="learn"] .bento-lesson .bento-verb,
  .bento[data-bento-view="learn-mechanics"] .bento-mech .bento-verb {
    line-height: var(--lh-tight);
    padding-right: 32px;
  }
  .bento-card.bento-backtile .bento-verb {
    padding-right: 0;
  }
  .bento-sub,
  .bento[data-bento-view="forge"] .bento-body {
    line-height: var(--lh-snug);
  }
  .bento-card.bento-queued .bento-sub {
    font-size: var(--fs-3xs);
  }
  .bento-tag {
    font-size: var(--fs-3xs);
    letter-spacing: var(--ls-tracked);
  }
  .bento[data-bento-view="forge"] .bento-status {
    font-size: var(--fs-3xs);
  }

  /* Smaller social/platform icon so 24px Telegram mark doesn't overlap
     a 16px verb in a tight 150px tile. Tucked further into the corner. */
  .bento-icon {
    top: 10px; right: 10px;
    width: 22px;
    height: 22px;
  }
  .bento-card.bento-backtile .bento-icon {
    width: 20px; height: 20px;
    position: static;
  }

  /* Number badge: smaller + dimmer so it reads as an index, not the
     focal point. Sits at the bottom-right of lesson/forge cards;
     mechanics keeps its top-right anchor. */
  .bento-card.bento-lesson::after,
  .bento-card.bento-forging::after,
  .bento-card.bento-queued::after,
  .bento-card.bento-mech::after {
    font-size: var(--fs-md);
    bottom: 8px;
    right: 10px;
    opacity: 0.5;
  }
  .bento-card.bento-mech::after {
    top: 10px;
    right: 10px;
    bottom: auto;
  }

  /* Tighter row-gap inside grid-anchored cards on mobile — 14px was
     desktop generosity, 8px reads cleanly at this scale. */
  .bento-card:has(.bento-tag) { row-gap: 8px; gap: 8px; }
  .bento-card:has(.bento-tag) > .bento-sub,
  .bento-card:has(.bento-tag) > .bento-body { min-height: auto; }
  .bento[data-bento-view="learn"]           .bento-lesson  .bento-verb,
  .bento[data-bento-view="learn-mechanics"] .bento-mech    .bento-verb,
  .bento[data-bento-view="forge"]           .bento-forging .bento-verb,
  .bento[data-bento-view="forge"]           .bento-queued  .bento-verb { min-height: auto; }

  /* Mobile shatter: symmetric scale — no translate drama */
  .forge:not([data-view="root"]) .choice-card {
    transform: scale(0.4);
  }
}

/* ── Accessibility: respect reduced motion ── */
@media (prefers-reduced-motion: reduce) {
  .choice-card,
  .bento-card,
  .bento,
  .support-row {
    transition-duration: 0.15s !important;
    transition-delay: 0s !important;
  }
  .forge:not([data-view="root"]) .choice-card {
    transform: none;
    filter: none;
  }
}

/* ═══════════════════════════════════════════════════════════════
   LESSON PREVIEW — epigraph overlay for Учень lesson cards.

   Click a .bento-lesson card → the slate fades in over the bento,
   drifting warm glows move behind it, two gold rules bracket the
   text. "Читати в режимі книжки" opens a scroll-reader where
   lines vivify/fade based on viewport centre (backtome-style).

   Uses the SAME tokens as the rest of the site: apprentice gold
   (--path-apprentice), Geologica title (matches .bento-lesson
   .bento-verb neon), Cormorant serif for the body. Back control
   reuses .bento-card.bento-backtile directly — no new button
   grammar introduced.
   ═══════════════════════════════════════════════════════════════ */

/* Scroll lock — overflow:hidden only, NOT position:fixed. We keep
   the real scrollY intact so scroll.js still reads "we're past the
   hero threshold" and the collapsed-logo bar stays collapsed. A
   position:fixed body would reset scrollY to 0 and snap the hero
   logo back open — exactly what we don't want. */
body.lesson-preview-open {
  overflow: hidden;
}
html:has(body.lesson-preview-open) { overflow: hidden; }

.lesson-preview {
  position: fixed; inset: 0;
  z-index: var(--z-modal);
  pointer-events: none;
  opacity: 0;
  transition: opacity 520ms var(--ease-silk);
  /* Lock to apprentice palette — this is an Учень view, gold not ember. */
  --accent:    var(--path-apprentice);
  --accent-hi: var(--path-apprentice-hi);
}
.lesson-preview.active { pointer-events: auto; opacity: 1; }

.lesson-preview__backdrop {
  position: absolute; inset: 0;
  background: radial-gradient(ellipse at 50% 45%,
    rgba(10, 9, 7, 0.55) 0%,
    rgba(5, 5, 8, 0.92) 70%,
    rgba(5, 5, 8, 0.97) 100%);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  opacity: 0;
  transition: opacity 520ms var(--ease-silk);
}
.lesson-preview.active .lesson-preview__backdrop { opacity: 1; }

/* Dynamic field — three drifting orbs + slow-rising embers. The
   orbs are deliberately oversized and blurred so they read as
   warm ambient light, never as "objects" on screen. */
.lesson-preview__field {
  position: absolute; inset: 0;
  pointer-events: none;
  overflow: hidden;
  opacity: 0;
  transition: opacity 1000ms var(--ease-silk) 200ms;
}
.lesson-preview.active .lesson-preview__field { opacity: 1; }

.lesson-preview__glow {
  position: absolute;
  border-radius: 50%;
  filter: blur(90px);
  mix-blend-mode: screen;
  will-change: transform;
}
.lesson-preview__glow--a {
  width: 640px; height: 640px; left: -18%; top: -12%;
  background: radial-gradient(circle,
    rgba(var(--path-apprentice), 0.4), transparent 65%);
  animation: lesson-glow-a 18s ease-in-out infinite;
}
.lesson-preview__glow--b {
  width: 640px; height: 640px; right: -16%; bottom: -18%;
  background: radial-gradient(circle,
    rgba(var(--path-apprentice-hi), 0.3), transparent 65%);
  animation: lesson-glow-b 22s ease-in-out infinite;
}
.lesson-preview__glow--c {
  width: 480px; height: 480px; left: 35%; top: 55%;
  background: radial-gradient(circle,
    rgba(var(--rgb-ember), 0.18), transparent 70%);
  animation: lesson-glow-c 26s ease-in-out infinite;
}
@keyframes lesson-glow-a {
  0%,100% { transform: translate(0, 0)        scale(1);    }
  50%     { transform: translate(140px, 80px) scale(1.12); }
}
@keyframes lesson-glow-b {
  0%,100% { transform: translate(0, 0)          scale(1);    }
  50%     { transform: translate(-120px, -70px) scale(1.08); }
}
@keyframes lesson-glow-c {
  0%,100% { transform: translate(-50%, -50%) scale(0.95); }
  50%     { transform: translate(-40%, -60%) scale(1.1);  }
}

.lesson-preview__ember {
  position: absolute;
  bottom: -8px;
  width: 3px; height: 3px;
  border-radius: 50%;
  background: rgba(var(--path-apprentice-hi), 0.85);
  box-shadow: 0 0 8px rgba(var(--path-apprentice), 0.7);
  opacity: 0;
  animation: lesson-ember 14s linear infinite;
}
@keyframes lesson-ember {
  0%   { opacity: 0; transform: translateY(0) translateX(0); }
  15%  { opacity: 0.85; }
  85%  { opacity: 0.6; }
  100% { opacity: 0; transform: translateY(-110vh) translateX(var(--ex, 40px)); }
}

/* ─── Slate — echoes the .bento-card frame, centred & enlarged ─── */
.lesson-preview__slate {
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, -48%);
  width: min(720px, 90vw);
  padding: 56px clamp(28px, 5vw, 64px) 48px;
  /* Faint dark glass, just enough to read as "the artifact itself" —
     distinct from the viewport-wide backdrop behind it. Kept subtle so
     it still feels like content floating, not a boxed card. */
  background: linear-gradient(180deg,
    rgba(10, 8, 6, 0.42) 0%,
    rgba(6, 5, 5, 0.58) 100%);
  backdrop-filter: blur(8px) saturate(105%);
  -webkit-backdrop-filter: blur(8px) saturate(105%);
  border: 1px solid rgba(var(--path-apprentice), 0.08);
  border-radius: 22px;
  box-shadow:
    inset 0 1px 0 rgba(255, 240, 220, 0.03),
    0 24px 60px -20px rgba(0, 0, 0, 0.55);
  text-align: center;
  opacity: 0;
  transition: opacity 680ms var(--ease-silk) 150ms,
              transform 680ms var(--ease-silk) 150ms;
}
.lesson-preview.active .lesson-preview__slate {
  opacity: 1;
  transform: translate(-50%, -50%);
}

/* Breathing inner light — extremely subtle, 6s cycle. */
.lesson-preview__slate::before {
  content: '';
  position: absolute; inset: 0;
  border-radius: 20px;
  pointer-events: none;
  background: radial-gradient(ellipse at 50% 0%,
    rgba(var(--path-apprentice), 0.08), transparent 70%);
  animation: lesson-slate-breathe 6s ease-in-out infinite;
}
@keyframes lesson-slate-breathe {
  0%,100% { opacity: 0.8; }
  50%     { opacity: 1;   }
}

/* Horizontal gold rules — draw in, then shimmer a highlight pass. */
.lesson-preview__rule {
  height: 1px;
  background: linear-gradient(90deg,
    transparent 0%,
    rgba(var(--path-apprentice), 0.55) 20%,
    rgba(var(--path-apprentice-hi), 1)  50%,
    rgba(var(--path-apprentice), 0.55) 80%,
    transparent 100%);
  background-size: 200% 100%;
  transform: scaleX(0);
  transform-origin: center;
  transition: transform 900ms var(--ease-silk);
}
.lesson-preview.active .lesson-preview__rule {
  transform: scaleX(1);
  animation: lesson-rule-shimmer 6s linear infinite 1.2s;
}
@keyframes lesson-rule-shimmer {
  0%   { background-position: -100% 0%; }
  100% { background-position:  100% 0%; }
}
.lesson-preview__rule--top    { margin-bottom: 32px; }
.lesson-preview__rule--bottom { margin-top: 32px; }

/* Tag — same anatomy as .bento-tag (mono uppercase + neon halo). */
.lesson-preview__tag {
  font-family: var(--font-mono);
  font-weight: 300;
  font-size: var(--fs-2xs);
  letter-spacing: var(--ls-extra-tracked);
  text-transform: uppercase;
  color: rgba(var(--accent-hi), 0.92);
  text-shadow:
    0 0 2px  rgba(var(--accent-hi), 0.7),
    0 0 8px  rgba(var(--accent),    0.35),
    0 0 18px rgba(var(--accent),    0.15);
  opacity: 0;
  transition: opacity 600ms ease 300ms;
}
.lesson-preview.active .lesson-preview__tag { opacity: 1; }

/* Title — mirrors .bento-lesson .bento-verb exactly (6-layer neon). */
.lesson-preview__title {
  font-family: var(--font-display);
  font-weight: 200;
  font-size: var(--fs-2xl);
  line-height: var(--lh-tight);
  letter-spacing: var(--ls-snug);
  white-space: pre-line;
  margin: 18px 0 20px;
  color: rgba(var(--accent-hi), 1);
  text-shadow:
    0 0 1px  rgba(var(--accent-hi), 1),
    0 0 4px  rgba(var(--accent-hi), 0.95),
    0 0 14px rgba(var(--accent),    0.7),
    0 0 32px rgba(var(--accent),    0.42),
    0 0 64px rgba(var(--accent),    0.2);
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 800ms ease 500ms, transform 800ms ease 500ms;
}
.lesson-preview.active .lesson-preview__title {
  opacity: 1; transform: translateY(0);
}

/* Summary — Cormorant italic, same rhythm as ambient thoughts. */
.lesson-preview__summary {
  font-family: var(--font-serif);
  font-style: italic;
  font-weight: 300;
  font-size: var(--fs-subtitle);
  line-height: var(--lh-loose);
  letter-spacing: var(--ls-snug);
  color: var(--cream-hi);
  max-width: 560px;
  margin: 0 auto;
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 800ms ease 700ms, transform 800ms ease 700ms;
}
.lesson-preview__summary em {
  color: rgba(var(--accent-hi), 0.95);
  font-style: italic;
}
.lesson-preview.active .lesson-preview__summary {
  opacity: 1; transform: translateY(0);
}

/* CTA — adopts the hero's scroll-hint glow grammar: cream-warm
   halo pulse on border + text, no gold fill. Reads as the same
   "increase the intensity and go deeper" cue the hero provides. */
.lesson-preview__cta {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  margin-top: 30px;
  padding: 12px 26px;
  background: transparent;
  border: 1.5px solid rgba(var(--cream-rgb), 0.6);
  border-radius: 999px;
  color: rgba(var(--cream-rgb), 0.95);
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  font-weight: 300;
  letter-spacing: var(--ls-wider);
  cursor: pointer;
  opacity: 0;
  /* Two intros: opacity fade in on active, then loop the pulse. */
  transition:
    transform 220ms ease,
    background-color 220ms ease,
    opacity 600ms ease 1100ms;
  box-shadow:
    0 0 4px rgba(var(--cream-rgb), 0.5),
    0 0 12px rgba(255, 240, 200, 0.15),
    0 0 28px rgba(255, 220, 150, 0.05);
}
.lesson-preview.active .lesson-preview__cta {
  opacity: 1;
  /* Same 3.2s heartbeat cadence as the hero's scroll-hint glow. */
  animation:
    lesson-cta-border-glow 3.2s ease-in-out infinite,
    lesson-cta-text-glow   3.2s ease-in-out infinite;
}
.lesson-preview__cta:hover {
  background: rgba(var(--cream-rgb), 0.06);
  transform: translateY(-1px);
}
.lesson-preview__cta:active {
  transform: translateY(0) scale(0.98);
}
.lesson-preview__cta svg {
  width: 14px; height: 14px;
  stroke: rgba(var(--cream-rgb), 0.95);
  stroke-width: 1.6;
  filter:
    drop-shadow(0 0 3px rgba(var(--cream-rgb), 0.7))
    drop-shadow(0 0 8px rgba(255, 230, 170, 0.3));
  transition: transform 220ms ease;
}
.lesson-preview__cta:hover svg { transform: translateX(3px); }

/* Hero-matched glow animations — border ring + text bloom pulse. */
@keyframes lesson-cta-border-glow {
  0%, 100% {
    border-color: rgba(var(--cream-rgb), 0.55);
    box-shadow:
      0 0 4px  rgba(var(--cream-rgb), 0.45),
      0 0 12px rgba(255, 240, 200, 0.15),
      0 0 28px rgba(255, 220, 150, 0.05);
  }
  50% {
    border-color: rgba(var(--cream-rgb), 0.9);
    box-shadow:
      0 0 6px  rgba(var(--cream-rgb), 0.75),
      0 0 18px rgba(255, 240, 200, 0.4),
      0 0 46px rgba(255, 220, 150, 0.2);
  }
}
@keyframes lesson-cta-text-glow {
  0%, 100% {
    text-shadow:
      0 0 2px  #fff,
      0 0 6px  rgba(var(--cream-rgb), 0.6),
      0 0 14px rgba(255, 240, 200, 0.35),
      0 0 30px rgba(255, 220, 150, 0.15);
  }
  50% {
    text-shadow:
      0 0 3px  #fff,
      0 0 10px rgba(var(--cream-rgb), 0.9),
      0 0 22px rgba(255, 240, 200, 0.55),
      0 0 46px rgba(255, 220, 150, 0.28);
  }
}

/* Back wrapper — reuses the EXISTING .bento-card.bento-backtile
   markup unchanged. We only pin it and compensate for the grid-entry
   animation (which is mid-transition without its grid context). The
   book's back control is a .neon-btn inside .lesson-book__header
   instead — different grammar for a different context. */
.lesson-preview__back {
  position: fixed;
  top: clamp(18px, 2.4vw, 32px);
  left: clamp(18px, 2.4vw, 32px);
  z-index: 12;
  pointer-events: auto;
  min-width: 148px;
  opacity: 0;
  transform: translateX(-8px);
  transition: opacity 520ms var(--ease-silk) 250ms,
              transform 520ms var(--ease-silk) 250ms;
}
.lesson-preview.active .lesson-preview__back {
  opacity: 1;
  transform: translateX(0);
}
.lesson-preview__back > .bento-card.bento-backtile {
  /* Neutralise the grid's entrance (scale/filter/opacity) since we're
     outside the .bento grid. Keep the frosted frame + hover behaviour. */
  opacity: 1 !important;
  transform: none !important;
  filter: none !important;
  transition: border-color 0.22s var(--ease-silk),
              box-shadow   0.22s var(--ease-silk),
              background   0.22s var(--ease-silk);
  padding: 14px 20px;
}

/* ═══════════════════════════════════════════════════════════════
   BOOK MODE — reuses the site's EXISTING header (logo-safe-zone +
   collapsed KOVΔ + section-divider + nav-back) and ports the
   backtome "yako-header" (subsection name + typewriter summary)
   plus top/bottom fades verbatim from site/css/yako-{header,slides}.
   Book bg is transparent so the fire + bubbles + embers canvases
   stay visible underneath.
   ═══════════════════════════════════════════════════════════════ */
body.lesson-book-open { overflow: hidden; }

/* Hide every main-page surface that would otherwise show through
   the book overlay — forge bento + support, docs links, preview,
   thoughts field, scroll hint, footer, bubbles + embers canvases.
   Only the flames canvas (bottom 32vh) stays — fire glow at the
   reader's feet as they read, but no drifting bubbles/embers
   muddying the reading area. */
body.lesson-book-open #forge-section,
body.lesson-book-open .lesson-preview,
body.lesson-book-open #field,
body.lesson-book-open #scroll-hint,
body.lesson-book-open #site-footer,
body.lesson-book-open #bubbles,
body.lesson-book-open #embers {
  display: none !important;
}

/* Lift the real header above the book overlay and FORCE the
   collapsed-logo pose — so opening a book from any scroll position
   snaps the header into its top-bar shape, not the big hero lockup. */
body.lesson-book-open #logo-safe-zone  { z-index: 9600; opacity: 1; }
body.lesson-book-open #section-divider { z-index: 9601; opacity: 1; width: 100%; }
body.lesson-book-open #logo            {
  z-index: 9602;
  transform: translate(-50%, 0) scale(0.42);
  opacity: 0.95;
}
body.lesson-book-open #logo #logo-glow,
body.lesson-book-open #logo #logo-sub,
body.lesson-book-open #logo #prompt { opacity: 0; }
body.lesson-book-open #nav-back { z-index: 9603; opacity: 1; pointer-events: auto; }
body.lesson-book-open #nav-lang { z-index: 9603; }

/* ─── #nav-back becomes a pill with "Назад" label + left arrow
   while a book is open. Toggled via JS by swapping the icon and
   adding .lesson-book-back-mode to the existing #nav-back button. */
#nav-back.lesson-book-back-mode {
  width: auto;
  min-width: 34px;
  height: 34px;
  padding: 0 14px 0 10px;
  border-radius: 20px;
  gap: 8px;
  border: 1.5px solid rgba(var(--cream-rgb), 0.6);
  background: rgba(15, 15, 18, 0.55);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  box-shadow:
    0 0 4px rgba(var(--cream-rgb), 0.5),
    0 0 12px rgba(255, 240, 200, 0.15),
    0 0 28px rgba(255, 220, 150, 0.05);
  color: rgba(255, 240, 200, 0.8);
}
#nav-back.lesson-book-back-mode:hover,
#nav-back.lesson-book-back-mode:active {
  color: rgba(var(--cream-rgb), 0.98);
  border-color: rgba(var(--cream-rgb), 0.9);
  box-shadow:
    0 0 6px rgba(var(--cream-rgb), 0.75),
    0 0 18px rgba(255, 240, 200, 0.28),
    0 0 36px rgba(255, 220, 150, 0.1);
}
#nav-back.lesson-book-back-mode svg {
  width: 14px; height: 14px;
  stroke: currentColor; stroke-width: 1.5;
  filter: drop-shadow(0 0 3px rgba(var(--cream-rgb), 0.6));
}
#nav-back.lesson-book-back-mode .nav-back-label {
  font-family: var(--font-mono);
  font-size: var(--fs-2xs);
  font-weight: 300;
  letter-spacing: var(--ls-widest);
  text-transform: uppercase;
  line-height: 1;
}

.lesson-book {
  position: fixed; inset: 0;
  z-index: var(--z-toast);
  /* Transparent — flames, bubbles, embers remain visible underneath. */
  background: transparent;
  overflow-y: auto;
  overflow-x: hidden;  /* clip any slide that scales past viewport width */
  overscroll-behavior: contain;
  opacity: 0;
  transition: opacity 520ms var(--ease-silk);
  --accent:    var(--path-apprentice);
  --accent-hi: var(--path-apprentice-hi);
}
.lesson-book.active { opacity: 1; }

/* ─── Yako sub-header (ported from #yako-header on backto.me) ───
   Sits BELOW the KOVA safe-zone at top: 73 px. Subsection name on
   top, Cormorant italic summary beneath — typewrites as the
   reader scrolls through the slides. */
.lesson-book__yako-header {
  position: fixed;
  top: 73px;
  left: 0; right: 0;
  z-index: 9604;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  /* Roomier vertical padding so the soft mask fades don't eat the text. */
  padding: 22px 60px 26px;
  /* Pure black, no frosted blur — reads as solid darkness, not a
     second translucent bar stacked over the safe-zone. */
  background: #000;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
  opacity: 0;
  /* No CSS transition — the scroll tick() writes opacity every frame as
     headerOp = 1 - titleOp. A CSS transition lags each JS write by
     500ms, which is exactly the "disappear then appear" gap the user
     sees. Instant opacity writes = seamless cross-fade. */
  transition: none;
  pointer-events: none;
  /* Soft vertical edges — no hard line at top or bottom. The mask
     feathers the bar's top/bottom so it bleeds into the surrounding
     darkness instead of cutting a visible seam. */
  -webkit-mask-image: linear-gradient(to bottom,
    transparent 0%, #000 28%, #000 72%, transparent 100%);
  mask-image: linear-gradient(to bottom,
    transparent 0%, #000 28%, #000 72%, transparent 100%);
}
.lesson-book.active .lesson-book__yako-header {
  opacity: 1;
  transform: translateY(0);
}
/* Header opacity is JS-driven while reading (cross-fades with title
   slide); this base rule applies only during the open transition. */
.lesson-book.active .lesson-book__yako-header {
  transition: transform 0.5s ease;
}

.lesson-book__yako-name {
  font-family: var(--font-display);
  font-weight: 300;
  font-size: var(--fs-xs);
  letter-spacing: var(--ls-widest);
  text-transform: uppercase;
  color: rgba(255, 255, 245, 0.85);
  white-space: nowrap;
  text-shadow:
    0 0 2px  rgba(255, 255, 255, 0.6),
    0 0 8px  rgba(var(--cream-rgb), 0.3),
    0 0 20px rgba(255, 240, 200, 0.12);
}

.lesson-book__yako-summary {
  display: block;
  width: 100%;
  font-family: var(--font-serif);
  font-size: var(--fs-subtitle);
  font-weight: 300;
  font-style: italic;
  letter-spacing: var(--ls-base);
  color: rgba(var(--cream-rgb), 0.65);
  white-space: nowrap;
  min-height: 1.3em;
  text-align: center;
}

/* Reading progress — sits BELOW the yako sub-header. Header = 73
   (safe-zone) + ~95 box at desktop max (22 pad-top + ~17 name + 4 gap
   + 26 summary 1.3em@20px + 26 pad-bot). Earlier 133 was sized for a
   smaller box and pushed the bar up into the resume line. */
.lesson-book__progress {
  position: fixed;
  top: 168px; left: 0;
  height: 2px; width: 0%;
  background: linear-gradient(90deg,
    transparent,
    rgba(var(--accent-hi), 1));
  box-shadow: 0 0 14px rgba(var(--accent), 0.5);
  z-index: 9605;
  transition: width 120ms linear;
}

/* Edge fades — ported verbatim from #yako-fade-top / -bottom. */
.lesson-book__fade-top {
  position: fixed;
  top: 170px; left: 0; right: 0;
  height: 120px;
  z-index: 9502;
  background: linear-gradient(to bottom,
    rgba(5, 5, 8, 0.95) 0%,
    rgba(5, 5, 8, 0.5)  40%,
    rgba(5, 5, 8, 0.15) 70%,
    transparent         100%);
  pointer-events: none;
}
/* No bottom fade — the flames canvas at bottom should burn through
   just like on the main page. Slide fade-out is handled by the
   scroll engine's exit zone, not a static gradient. */
.lesson-book__fade-bottom { display: none; }

/* Slides wrapper — no top padding; the first slide is the title
   slide which handles its own vertical centering. Bottom padding
   keeps the last content slide reachable by the crawl. */
.lesson-book__slides {
  padding-top: 0;
  padding-bottom: 25svh;
}

/* Content slide — ported verbatim from .yako-slide. JS drives
   opacity + transform via the zone classifier. */
.lesson-book__slide {
  min-height: 80svh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 60px 32px 80px;
  text-align: center;
  will-change: opacity, transform;
  transform-origin: center 40%;
}
.lesson-book__slide p {
  font-family: var(--font-serif);
  font-size: var(--fs-lg);
  font-weight: 300;
  font-style: italic;
  line-height: var(--lh-loose);
  color: rgba(255, 252, 245, 0.95);
  max-width: 480px;
  white-space: pre-line;
  margin: 0;
  /* Warm-cream neon bloom — same palette as the KOVΔ hero lockup.
     Three soft layers give glyphs a self-lit feel that reads better
     over the dark background than pure flat white. */
  text-shadow:
    0 0 2px  rgba(var(--cream-rgb), 0.55),
    0 0 10px rgba(255, 240, 200, 0.25),
    0 0 28px rgba(255, 220, 150, 0.12),
    0 0 60px rgba(255, 200, 120, 0.06);
}
.lesson-book__slide p em,
.lesson-book__slide p strong {
  font-weight: 400;
  font-style: normal;
  color: #ffffff;
  /* Accent words burn a notch brighter — adds a fifth core layer
     so the em/strong phrase pops out of the paragraph glow. */
  text-shadow:
    0 0 1px  rgba(255, 255, 255, 1),
    0 0 4px  rgba(255, 255, 250, 0.85),
    0 0 14px rgba(255, 240, 200, 0.5),
    0 0 32px rgba(255, 220, 150, 0.22),
    0 0 72px rgba(255, 200, 120, 0.1);
}

/* Title slide — first slide, shows section title big. JS drives
   scale/opacity on .lesson-book__title-inner and cross-fades with
   the yako-header. Ported from .yako-slide--title. Height tuned
   to 80svh so the title lands at textY = morphBot (full scale,
   full opacity) when the book opens at scrollTop = 0. */
.lesson-book__slide--title {
  min-height: 80svh;
  padding: 0;
  /* Wrapper itself stays at identity — JS drives the inner only. */
  opacity: 1 !important;
  transform: none !important;
}
.lesson-book__title-inner {
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-weight: 300;
  font-size: var(--fs-2xl);
  letter-spacing: var(--ls-wider);
  color: rgba(255, 255, 245, 0.92);
  text-align: center;
  text-transform: uppercase;
  text-shadow:
    0 0 2px  rgba(255, 255, 255, 0.75),
    0 0 8px  rgba(var(--cream-rgb), 0.4),
    0 0 24px rgba(255, 240, 200, 0.18),
    0 0 60px rgba(255, 220, 150, 0.07);
  will-change: transform, opacity;
  transform-origin: center center;
}
/* Title size scales fluidly via --fs-2xl; only the tracking eases on
   small phones so KOVA-width caps don't crowd the safe-zone bar. */
@media (max-width: 500px) {
  .lesson-book__title-inner { letter-spacing: var(--ls-wide); }
}

/* Subsection-title slide — same morph mechanics as the hero title
   but rendered in a smaller Cormorant serif so it reads as a
   chapter's inner heading ("Ти вже тут", "Це кузня", ...). */
.lesson-book__slide--subtitle {
  min-height: 80svh;
  padding: 0;
  opacity: 1 !important;
  transform: none !important;
}
.lesson-book__subtitle-inner {
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-weight: 200;
  font-size: var(--fs-2xl);
  letter-spacing: var(--ls-base);
  line-height: var(--lh-tight);
  color: rgba(255, 255, 245, 0.95);
  text-align: center;
  max-width: 720px;
  padding: 0 24px;
  text-shadow:
    0 0 2px  rgba(255, 255, 255, 0.75),
    0 0 10px rgba(var(--cream-rgb), 0.35),
    0 0 28px rgba(255, 240, 200, 0.15),
    0 0 64px rgba(255, 220, 150, 0.06);
  will-change: transform, opacity;
  transform-origin: center center;
}
/* Subtitle scales fluidly via --fs-2xl — no per-breakpoint override. */

/* ─── End-of-chapter slide — next lesson preview + Далі CTA ─── */
.lesson-book__slide--end {
  gap: 28px;
}
.lesson-book__end-intro {
  font-family: var(--font-mono);
  font-size: var(--fs-2xs);
  letter-spacing: var(--ls-extra-tracked);
  text-transform: uppercase;
  color: rgba(var(--accent), 0.55);
  text-shadow:
    0 0 8px  rgba(var(--accent), 0.25),
    0 0 20px rgba(var(--accent), 0.12);
}

/* Next-lesson card — echoes the .bento-card frame (same gradient,
   frosted glass, neon halo on hover) so it reads as a continuation
   of the bento grid the user came from. */
.lesson-book__next {
  display: flex;
  flex-direction: column;
  gap: 14px;
  width: min(520px, 90vw);
  padding: 26px 30px 22px;
  text-align: left;
  border-radius: 20px;
  background: linear-gradient(180deg,
    rgba(255, 255, 255, 0.020) 0%,
    rgba(255, 255, 255, 0.008) 55%,
    rgba(255, 255, 255, 0.003) 100%);
  backdrop-filter: blur(6px) saturate(115%);
  -webkit-backdrop-filter: blur(6px) saturate(115%);
  border: 1px solid rgba(255, 235, 210, 0.07);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.04),
    0 14px 40px rgba(0, 0, 0, 0.30);
  color: rgba(var(--accent-hi), 0.95);
  cursor: pointer;
  font: inherit;
  transition: all 0.24s var(--ease-silk);
}
.lesson-book__next:hover,
.lesson-book__next:focus-visible {
  border-color: rgba(var(--accent), 0.55);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.06),
    0 20px 50px rgba(0, 0, 0, 0.4),
    0 0 0 1px rgba(var(--accent), 0.25),
    0 0 60px -10px rgba(var(--accent), 0.35);
  outline: none;
}

.lesson-book__next-tag {
  font-family: var(--font-mono);
  font-weight: 300;
  font-size: var(--fs-2xs);
  letter-spacing: var(--ls-extra-tracked);
  text-transform: uppercase;
  color: rgba(var(--accent-hi), 0.92);
  text-shadow:
    0 0 2px  rgba(var(--accent-hi), 0.7),
    0 0 8px  rgba(var(--accent),    0.35),
    0 0 18px rgba(var(--accent),    0.15);
}

.lesson-book__next-title {
  font-family: var(--font-display);
  font-weight: 200;
  font-size: var(--fs-xl);
  line-height: var(--lh-snug);
  letter-spacing: var(--ls-snug);
  color: rgba(var(--accent-hi), 1);
  text-shadow:
    0 0 1px  rgba(var(--accent-hi), 1),
    0 0 4px  rgba(var(--accent-hi), 0.95),
    0 0 14px rgba(var(--accent),    0.7),
    0 0 32px rgba(var(--accent),    0.42),
    0 0 64px rgba(var(--accent),    0.2);
}

.lesson-book__next-cta {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-top: 4px;
  font-family: var(--font-mono);
  font-weight: 300;
  font-size: var(--fs-2xs);
  letter-spacing: var(--ls-widest);
  text-transform: uppercase;
  color: rgba(var(--accent-hi), 0.9);
}
.lesson-book__next-cta svg {
  width: 14px; height: 14px;
  stroke: currentColor;
  transition: transform 0.22s ease;
}
.lesson-book__next:hover .lesson-book__next-cta svg,
.lesson-book__next:focus-visible .lesson-book__next-cta svg {
  transform: translateX(4px);
}

/* Final end-slide (last lesson) — closes with Δ + "кінець шляху". */
.lesson-book__slide--end-final { gap: 20px; }
.lesson-book__end-delta {
  font-family: var(--font-serif);
  font-style: italic;
  font-size: var(--fs-3xl);
  color: rgba(var(--accent-hi), 0.7);
  text-shadow:
    0 0 12px rgba(var(--accent), 0.35),
    0 0 40px rgba(var(--accent), 0.15);
}

/* ─── Floating "Далі · Розділ 7" pill — appears in the mechanics
   drill-down after the reader arrives there from Chapter 5's book.
   Matches the site's neon-btn family. ─── */
.lesson-mechanics-cta {
  position: fixed;
  bottom: clamp(28px, 6vh, 56px);
  left: 50%;
  transform: translate(-50%, 10px);
  z-index: 50;
  display: inline-flex;
  align-items: center;
  gap: 14px;
  padding: 14px 26px 14px 22px;
  background: rgba(15, 15, 18, 0.7);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1.5px solid rgba(var(--path-apprentice), 0.55);
  border-radius: 999px;
  color: rgba(var(--path-apprentice-hi), 0.95);
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  font-weight: 300;
  letter-spacing: var(--ls-widest);
  text-transform: uppercase;
  cursor: pointer;
  opacity: 0;
  box-shadow:
    0 10px 30px rgba(0, 0, 0, 0.4),
    0 0 18px rgba(var(--path-apprentice), 0.2);
  transition:
    opacity 360ms var(--ease-silk),
    transform 360ms var(--ease-silk),
    border-color 220ms ease,
    box-shadow 220ms ease;
}
.lesson-mechanics-cta.visible {
  opacity: 1;
  transform: translate(-50%, 0);
}
.lesson-mechanics-cta.leaving {
  opacity: 0;
  transform: translate(-50%, -8px);
}
.lesson-mechanics-cta:hover,
.lesson-mechanics-cta:focus-visible {
  border-color: rgba(var(--path-apprentice-hi), 1);
  box-shadow:
    0 14px 34px rgba(0, 0, 0, 0.5),
    0 0 28px rgba(var(--path-apprentice), 0.4);
  outline: none;
}
.lesson-mechanics-cta__label {
  color: rgba(var(--path-apprentice), 0.75);
  letter-spacing: 0.22em;
}
.lesson-mechanics-cta__title {
  font-family: var(--font-display);
  font-weight: 200;
  font-size: var(--fs-sm);
  letter-spacing: var(--ls-wider);
  color: rgba(var(--path-apprentice-hi), 1);
  text-shadow:
    0 0 1px  rgba(var(--path-apprentice-hi), 1),
    0 0 8px  rgba(var(--path-apprentice),    0.6),
    0 0 20px rgba(var(--path-apprentice),    0.3);
}
.lesson-mechanics-cta svg {
  width: 14px; height: 14px;
  stroke: currentColor;
  transition: transform 0.22s ease;
}
.lesson-mechanics-cta:hover svg,
.lesson-mechanics-cta:focus-visible svg {
  transform: translateX(4px);
}
/* All lesson-book/mechanics sizes scale fluidly via the typography
   tokens above (--fs-lg for paragraphs, --fs-xs for the mechanics CTA,
   --fs-2xs for the yako name). The only mobile-specific changes are
   structural — padding for the yako header bar and the matching offset
   of the fade/progress sliding into the new bar height. */
@media (max-width: 500px) {
  .lesson-mechanics-cta {
    padding: 12px 22px 12px 18px;
    gap: 10px;
  }
  .lesson-book__yako-header { padding: 14px 48px 12px; }
  /* Mobile box ≈ 73 + (14 + ~15 + 4 + ~17 + 12) ≈ 135 px. */
  .lesson-book__fade-top    { top: 137px; }
  .lesson-book__progress    { top: 135px; }
}

/* ═══════════════════════════════════════════════════════════════
   MOBILE PHONE OVERRIDES — < 560px
   Desktop (≥ 561px) untouched. Only fixes for true phone widths.
   ═══════════════════════════════════════════════════════════════ */
@media (max-width: 560px) {
  /* Pull the centered hero logo up so it doesn't sit dead-center on
     a tall phone screen. Center at ~36vh leaves room below for prompt
     + hint + scroll-hint without crowding. */
  #logo {
    transform: translate(-50%, calc(36vh - 50% - 14px));
  }
  /* Bigger padding for tap-target on the prompt input. Font-size
     scales fluidly via --fs-base (≥16px → no iOS zoom). */
  #prompt-input { padding: 14px 8px; }

  /* SUPPORT CARD — break the horizontal pill layout on phones.
     Icon + text + CTA stacked vertically gives every element room
     instead of crushing the text column. Sizes inherit from the
     --fs-card-* tokens above. */
  .support-inner {
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 22px 18px;
    gap: 16px;
    min-height: auto;
  }
  .support-text {
    align-items: center;
    text-align: center;
    width: 100%;
  }
  .support-cta { margin-top: 4px; }
  .support-cta-text {
    text-align: center;
    white-space: normal;
  }
}

/* ═══════════════════════════════════════════════════════════════
   MOBILE PHONE — STRUCTURE & POLISH (placed last so it overrides
   any earlier base rules that share the same ID-only specificity).
   ═══════════════════════════════════════════════════════════════ */
@media (max-width: 560px) {
  /* Pre-size the prompt field close to the synced KOVA-width so the
     initial paint doesn't visibly shift when logo.js measures and
     sets the real width. KOVA at 70px font ≈ 263px wordmark. */
  #prompt-field { width: clamp(220px, 68vw, 300px); }

  /* ═══ 4 RECTANGULAR PILLS, FULL WIDTH, ICON CENTERED ═══
     Choice cards collapse to 4 horizontal pills (3 paths + 1 support)
     filling 100svh. Sizes flow from --fs-card-* tokens — no per-element
     overrides here. Layout-only properties: stack direction, gaps,
     border-radius, icon dimensions. */
  .choices {
    grid-template-columns: 1fr;
    gap: clamp(6px, 1.2svh, 10px);
    max-width: 100%;
  }
  .choice-card {
    min-height: clamp(96px, 14svh, 140px);
    border-radius: 16px;
  }
  .choice-inner {
    flex-direction: column;
    align-items: center;
    justify-content: space-between;
    text-align: center;
    padding: clamp(8px, 1.3svh, 14px) 14px;
    gap: clamp(2px, 0.8svh, 8px);
  }
  .choice-icon {
    width: clamp(80px, 13svh, 116px);
    height: clamp(80px, 13svh, 116px);
    flex-shrink: 0;
  }
  .choice-top {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1px;
    min-width: 0;
  }
  .choice-verb { line-height: var(--lh-tight); }
  body .choice-sub { font-size: clamp(14px, 1.9svh, 17px); line-height: var(--lh-snug); }
  .choice-class {
    width: auto;
    padding: 0;
    border: none;
    text-align: center;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1px;
  }
  .choice-class-name  { letter-spacing: var(--ls-wide); }
  body .choice-class-act { font-size: clamp(12px, 1.6svh, 14px); line-height: var(--lh-snug); }

  /* ═══ FORGE SECTION = exactly 1 viewport on mobile, 2×2 grid ═══
     Hero (overlaid via fixed positioning) takes the 1st viewport.
     Forge starts at 100svh and IS 100svh tall — 4 pills laid out
     as a 2×2 block fills the menu screen. Docs + footer follow in
     normal flow and stay off-screen until the user scrolls past.
     svh keeps the layout stable when iOS toolbar shows/hides. */
  section.forge {
    margin-top: 100svh !important;
    height: 100svh !important;
    min-height: 100svh !important;
    padding: clamp(40px, 8svh, 80px) 4vw clamp(20px, 4svh, 40px) !important;
  }
  /* Only flatten the layout while we're at the root menu — bento
     sub-views need their own .forge-main grid overlay to render. */
  .forge[data-view="root"] {
    display: grid !important;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: 1fr 1fr;
    gap: clamp(6px, 1.2svh, 10px);
    align-items: stretch;
    justify-items: stretch;
  }
  .forge[data-view="root"] .forge-main,
  .forge[data-view="root"] .choices,
  .forge[data-view="root"] .support-row {
    display: contents;
  }
  /* Bento stage is empty at root view — hide it so it doesn't claim
     a grid cell. (Overridden when forge enters a sub-view.) */
  .forge[data-view="root"] .bento-stage {
    display: none;
  }

  /* ═══ BENTO SUB-VIEWS — fill the forge viewport, 6 cards visible ═══
     When the user enters Відчувай / Пізнавай / Куй, the choice cards
     scale-out and the bento takes their place. Mobile layout:
       · forge-main fills the section (flex: 1, no grid stacking)
       · choices keep their grid-collapsed state but become absolute so
         they don't push the bento down
       · bento-stage owns the full height and acts as the scroll container
       · bento itself renders cards at a fixed row size, so views with
         8/10/12 tiles keep card legibility — the extras simply scroll. */
  .forge:not([data-view="root"]) {
    display: flex !important;
    flex-direction: column;
  }
  .forge:not([data-view="root"]) .forge-main {
    position: relative;
    flex: 1 1 0;
    min-height: 0;
    width: 100%;
    display: block;
  }
  .forge:not([data-view="root"]) .choices {
    position: absolute;
    inset: 0;
    pointer-events: none;
  }
  .forge:not([data-view="root"]) .support-row {
    display: none;
  }
  .forge:not([data-view="root"]) .bento-stage {
    position: relative;
    height: 100%;
    width: 100%;
  }
  /* Each bento STAYS absolute (layered overlay) so visibility:hidden
     siblings don't claim normal-flow space and stack 4 view heights.
     The active bento itself becomes the scroll container — extra rows
     scroll inside the grid, the section height never changes. */
  .forge:not([data-view="root"]) .bento {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    /* 2 cols × fixed-height rows scaled to viewport. 3 rows fit at
       100% of the bento height; views with 8/10/12 cards form extra
       rows below at the same row height — scrollable inside this bento. */
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    grid-auto-rows: clamp(116px, 18svh, 170px);
    gap: 10px;
    padding-bottom: 12px;
    align-content: start;
    overflow-y: auto;
    overflow-x: hidden;
    overscroll-behavior: contain;
    /* Hide scrollbar visuals — the card rhythm is its own cue. */
    scrollbar-width: none;
  }
  .forge:not([data-view="root"]) .bento::-webkit-scrollbar {
    display: none;
  }
  /* Drop the root view's vertical centering on the section — bento
     should pin to the top so the very first row is immediately read. */
  .forge:not([data-view="root"]) {
    justify-content: flex-start !important;
  }

  /* ═══ ICON ANIMATIONS — always on, on mobile ═══
     Mirrors the per-icon hover animations from desktop, but fires them
     continuously since there is no hover on touch. Same keyframes
     (railFlip / railMarch / railForgeSync) — only the trigger differs.
     Each card keeps its own visual signature instead of a generic
     breath, so mobile feels like the desktop reveal. */
  .choice-card[data-choice="follow"] .choice-icon path.back {
    transform-origin: center;
    transform-box: fill-box;
    animation: railFlipBack 2.4s ease-in-out infinite;
  }
  .choice-card[data-choice="follow"] .choice-icon path.front {
    transform-origin: center;
    transform-box: fill-box;
    animation: railFlipFront 2.4s ease-in-out infinite;
  }
  .choice-card[data-choice="learn"] .choice-icon path.outer {
    stroke-dasharray: 4 3;
    animation: railMarch 3s linear infinite;
  }
  .choice-card[data-choice="forge"] .choice-icon path {
    animation: railForgeSync 2.4s ease-in-out infinite;
  }
}

@keyframes choiceIconBreath {
  0%, 100% {
    opacity: 0.78;
    filter:
      drop-shadow(0 0 3px rgba(var(--accent), 0.4))
      drop-shadow(0 0 8px rgba(var(--accent), 0.2));
    transform: scale(0.94);
  }
  50% {
    opacity: 1;
    filter:
      drop-shadow(0 0 8px  rgba(var(--accent), 0.95))
      drop-shadow(0 0 22px rgba(var(--accent), 0.55))
      drop-shadow(0 0 44px rgba(var(--accent), 0.22));
    transform: scale(1.10);
  }
}

@media (max-width: 560px) {
  /* ═══ ACTIVE-STATE-ALWAYS on mobile ═══
     Touch devices have no hover, so the desktop "highlight on hover,
     dim others" pattern leaves every card looking inactive. Apply the
     hover treatment to every card permanently — minus the lift/scale
     transforms that would push neighbours out of place in a 3-col grid. */
  .choice-card {
    border-color: rgba(var(--accent), 0.50);
    box-shadow:
      inset 0 1px 0 rgba(255,255,255,0.10),
      0 14px 40px rgba(0,0,0,0.45),
      0 0 0 1px rgba(var(--accent), 0.20),
      0 0 38px -10px rgba(var(--accent), 0.30);
  }
  .choice-card .choice-tex { opacity: 1; }
  .choice-card .choice-icon {
    color: rgba(var(--accent-hi), 1);
    filter:
      drop-shadow(0 0 4px rgba(var(--accent-hi), 1))
      drop-shadow(0 0 12px rgba(var(--accent), 0.65))
      drop-shadow(0 0 26px rgba(var(--accent), 0.28));
  }
  .choice-card .choice-verb {
    /* Static glow — no neon flicker animation on phones (the
       desktop verbNeon dropouts read as a glitch on mobile). */
    color: rgba(var(--accent), 1);
    text-shadow:
      0 0 1px rgba(var(--accent), 0.9),
      0 0 8px  rgba(var(--accent), 0.6),
      0 0 18px rgba(var(--accent), 0.35);
  }
  .choice-card .choice-class::before { opacity: 1; }
  .choice-card .choice-class-name {
    text-shadow:
      0 0 12px rgba(var(--accent), 0.5),
      0 0 26px rgba(var(--accent), 0.22);
  }
  .choice-card .choice-sub { color: rgba(var(--accent-hi), 0.92); }
  .choice-card .choice-class-act { color: rgba(var(--accent-hi), 0.88); }

  /* Same for support — always in the warm "lit ember" state. */
  .support-card {
    border-color: rgba(var(--accent-hot), 0.30);
    box-shadow:
      inset 0 1px 0 rgba(var(--rgb-amber), 0.08),
      0 12px 30px rgba(var(--accent-dim), 0.13),
      0 0 52px -10px rgba(var(--accent-hot), 0.20);
  }
  .support-card .support-icon {
    color: rgba(var(--accent-hot-hi), 0.92);
    filter:
      drop-shadow(0 0 3px rgba(var(--accent-hot-hi), 0.55))
      drop-shadow(0 0 12px rgba(var(--accent-hot),    0.35))
      drop-shadow(0 0 26px rgba(var(--accent-hot),    0.14));
  }

  /* Docs nav: tighten tracking so all three legal links fit one row at 390px.
     Font-size still flows from --fs-xs token. */
  .doc-link {
    letter-spacing: 0.06em;
    padding: 6px 0;
  }
  .docs-nav { gap: 4px; }

  /* ═══ SUPPORT ROW ═══
     The card sits inline as the 4th pill in the stack. The two credos
     escape into position:fixed at the bottom of the viewport — see
     ".support-credo" rules farther down. */
  .support-row {
    display: block;
    max-width: 100%;
  }

  /* ═══ FIXED CREDO at bottom of viewport ═══
     The two halves of the manifesto sit side-by-side as one inline
     line at the very bottom, fading in once the user has scrolled
     past the hero (matches the same threshold the site-footer uses
     on desktop). Pointer-events:none so they don't block taps on
     the docs links underneath. */
  .support-credo {
    position: fixed;
    top: calc(56px + env(safe-area-inset-top, 0px));
    z-index: 50;
    pointer-events: none;
    opacity: 0;
    /* The base rule sets credoFlicker animation which forces opacity:1
       at 0% — disable it in dormant state so the credo stays hidden
       until the user has scrolled past the hero. */
    animation: none !important;
    transition: opacity 0.6s ease;
    /* Smaller font on the bottom-fixed credo so the two halves meet
       at center without overflowing. Uses --fs-sm so it stays in step
       with the rest of the small UI text. */
    font-size: clamp(15px, 2svh, 18px);
    /* Brighter color + stronger glow so the line is actually
       legible on a phone — was rgba(250,246,236,0.95) which read
       as "barely there" against the dark cards. */
    color: rgba(255, 255, 255, 1);
    text-shadow:
      0 0 2px  rgba(255, 255, 250, 1),
      0 0 8px  rgba(255, 245, 220, 0.85),
      0 0 20px rgba(255, 230, 180, 0.55),
      0 0 40px rgba(255, 210, 140, 0.25);
    max-width: 50vw;
  }
  .support-credo--left  { right: 50%; padding-right: 6px; text-align: right; }
  .support-credo--right { left:  50%; padding-left:  6px; text-align: left; }
  body.scrolled-past-hero .support-credo {
    opacity: 1;
    animation: scrollTextGlow 3.2s ease-in-out infinite !important;
  }

  /* ═══ SUPPORT CARD — 4th pill, vertical layout matching choices ═══
     Verb top · icon center · CTA pill bottom. Same rectangle height
     and shape as the 3 choice pills above so the stack reads as one
     uniform menu. */
  .support-card {
    min-height: clamp(96px, 14svh, 140px);
    border-radius: 16px;
  }
  .support-inner {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: space-between;
    text-align: center;
    padding: clamp(12px, 2svh, 20px) 12px;
    gap: clamp(4px, 1svh, 10px);
    min-height: auto;
    /* Fill the card so verb/icon/CTA distribute top/middle/bottom
       — same as .choice-inner does for choice cards. */
    height: 100%;
    width: 100%;
  }
  .support-text {
    order: 1;
    flex: 0 0 auto;
    min-width: 0;
    align-items: center;
    text-align: center;
    width: auto;
  }
  .support-icon {
    order: 2;
    width: clamp(80px, 13svh, 116px);
    height: clamp(80px, 13svh, 116px);
    flex-shrink: 0;
  }
  /* Rotate the CTA arrow 90° counter-clockwise so it points UP on
     the vertical card layout — visually matches "throw fuel onto
     the fire" instead of "go back". */
  .support-cta-icon svg {
    transform: rotate(-90deg);
  }
  .support-cta {
    order: 3;
    flex-shrink: 0;
    align-self: auto;
    margin-top: 0;
    padding: 0 10px 0 0;
    min-height: clamp(26px, 3.8svh, 34px);
    gap: 6px;
  }
  .support-cta-icon {
    width: clamp(26px, 3.8svh, 34px);
    height: clamp(26px, 3.8svh, 34px);
  }
  .support-cta-icon svg { width: 11px; height: 11px; }
  /* Sizes inherit from --fs-card-* tokens (verb/sub) and --fs-2xs (CTA text).
     Only line-height is tightened so the 4-pill stack reads compactly. */
  .support-verb {
    /* On mobile match choice-verb scale so the 4-pill stack reads as one
       uniform tier — desktop's smaller cap (32 px) doesn't apply here. */
    font-size: var(--fs-card-verb);
    line-height: var(--lh-tight);
    /* Allow wrap on the narrow 2×2 cell — base sets nowrap. */
    white-space: normal;
  }
  body .support-sub { font-size: clamp(13px, 1.7svh, 15px); line-height: var(--lh-snug); }
  .support-cta-text {
    font-size: var(--fs-2xs);
    letter-spacing: 0.14em;
    text-align: center;
    /* Override "Підкинути\nдров" newline so the CTA label sits
       on one line inside the narrow grid cell. */
    white-space: normal;
  }

  /* ═══ LOGO ACRONYM REVEAL ═══
     "Кожен Обирає Власну Автентичність" cannot fit in a phone-width
     row at the brand font-size. Stack each word on its own line on
     mobile so the acronym reads top-down without horizontal overflow. */
  #logo-kova.revealing {
    flex-direction: column;
    align-items: center;
    gap: 2px;
    transform: translate3d(0, 0, 0) !important;
  }
  #logo-kova.revealing .word {
    display: block;
    transform: translate3d(0, 0, 0) !important;
    text-align: center;
  }
  #logo-kova.revealing .char-rest {
    font-size: 0.45em;
  }
}
