/* ============================================================================
   layout.css — deck shell, the 4 stage modes, and reusable slide primitives
   Requires tokens.css. Vanilla CSS, no build step.
   ----------------------------------------------------------------------------
   The floating 3D canvas (#stage-canvas inside .stage) "floats" between four
   roles (hero / split / ambient / off). The deck toggles a single modifier
   class on .deck-shell (or .stage) and the canvas width + opacity tween so the
   scene never hard-cuts size — it glides between being the star, a companion,
   a corner vignette, or absent. Stage3D.setMode() re-frames the ortho camera to
   match the visible region (e.g. right ~48% in split).
   ============================================================================ */

/* ----------------------------------------------------------------------------
   DECK SHELL — fixed full-viewport stage; one slide visible at a time
   ---------------------------------------------------------------------------- */
.deck-shell {
  position: fixed;
  inset: 0;
  overflow: hidden;
  color: var(--text-secondary);
  /* REDESIGN v2: ONE flat, uniform grey plane across the whole page (jholec
     Light Gray #EBEBEB). No radial vignette — a gradient made the plane read as
     non-uniform / subtly divided; a single flat tone is what makes the whole
     scene feel unified. The transparent 3D canvas floats the model directly on
     this plane (right); the flat white content panel sits on it (left). Dark
     slides only darken the PANEL — the plane stays constant. */
  background-color: var(--surface-canvas);
}

/* ---- Reserved per-slide VISUAL SLOT (replaces the old 3D canvas host) -------
   The right half of the plane is held for a per-slide visual to be added later.
   For now it is a calm, near-empty placeholder so the split composition still
   reads as one scene (white panel left, quiet plane right). When a visual is
   added per slide, it mounts inside .stage. */
.stage {
  position: absolute;
  top: 0;
  right: 0;
  height: 100vh;
  width: 50vw;                 /* right half of the plane — the slide panel owns the left half */
  z-index: var(--z-stage);
  opacity: 1;
  pointer-events: none;        /* never steals clicks from the deck nav */
  display: grid;
  place-items: center;
}
/* The placeholder: a single, very soft coral-tinted ring — a quiet "something
   lives here" mark, not a busy graphic. Replace per slide when visuals land. */
.stage__placeholder {
  width: clamp(160px, 22vw, 300px);
  aspect-ratio: 1;
  border-radius: var(--radius-pill);
  border: 1px solid var(--mood-terracotta-12);
  background:
    radial-gradient(60% 60% at 50% 42%, var(--mood-terracotta-12), transparent 70%);
  opacity: 0.7;
}
.section--dark .stage__placeholder { border-color: var(--mood-cream-12); background: radial-gradient(60% 60% at 50% 42%, var(--mood-cream-06), transparent 70%); }

/* ---- Slide content layer -------------------------------------------------- */
/* REDESIGN: .slide is now just a positioning wrapper over the shared grey plane;
   the slide content lives inside a floating WHITE card (.slide__content styled
   as the card below). No grid columns anymore. */
.slide {
  position: absolute;
  inset: 0;
  z-index: var(--z-content);
  display: block;
  opacity: 1;                  /* REDESIGN v5: the container NEVER fades — it's a constant frame. Only the inner .rise elements animate (below). */
  pointer-events: none;
}
.slide.is-active { pointer-events: auto; }   /* .is-active also triggers the inner .rise stagger */

/* ============================================================================
   LAYOUT MODEL — REDESIGN v3: card-on-grey, ONE geometry for every slide.
   · Every slide is a jholec slide: a FLAT white panel filling the LEFT HALF of
     the shared grey plane; the 3D model floats on the transparent canvas to its
     right on EVERY slide. There is no more "cover" mode — dense 2D artefacts are
     reflowed into the left panel as jholec cards / stacks (see slides/*.js).
   The card IS .slide__content (no DOM change in slides).
   ============================================================================ */

/* Map slide content → FLAT white panel filling the LEFT HALF of the plane.
   REDESIGN v2 (user direction): the panel is a FIXED-SIZE flat rectangle — its
   geometry is identical on every slide regardless of content (only the content
   inside changes). No float shadow → it reads as part of the one grey scene, not
   a separate floating half. Pinned top+bottom+left with a small uniform gutter;
   width spans the full left half. _fit() zoom scales the inner content to fit
   this constant box. */
.slide .slide__content {
  position: absolute;
  top: var(--card-gutter);
  bottom: var(--card-gutter);
  left: var(--card-gutter);
  width: calc(50vw - var(--card-gutter) * 1.5);   /* full left half, minus the small gutters */
  max-width: none;
  height: auto;                                    /* fixed: top+bottom pin → constant height every slide */
  margin: 0;
  /* REDESIGN v6: one even edge inset (W & top, vw-only so it doesn't diverge on a
     wide-short screen) + an explicit larger BOTTOM that absorbs the reserved
     footer band so content never reaches the fixed chrome line. _fit() measures
     clientHeight − padding, so dense slides auto-shrink to clear the footer. */
  --panel-pad: clamp(2.25rem, 1.6rem + 2.2vw, 3.5rem);
  /* TOP padding navíc (user 17.6.): nadpis níž, pod horní progress bar, s víc dechem.
     Bar je fixní (top: card-gutter+panel-pad−1.6rem), takže extra top padding jen posune
     obsah dolů → větší mezera bar→nadpis. */
  padding: calc(var(--panel-pad) + var(--space-md)) var(--panel-pad)
           calc(var(--footer-band) + var(--space-xs)) var(--panel-pad);
  background: var(--surface-card);
  border: 1px solid var(--surface-card-edge);
  border-radius: var(--radius-card);
  box-shadow: none;            /* flat panel — no float shadow (user direction) */
  overflow: hidden;            /* content must not spill past the radius */
  display: flex;
  flex-direction: column;
  justify-content: flex-start; /* the single .slide__fit child anchors to the top; _fit() guarantees fit */
}

/* REDESIGN v6: inner content column. The PANEL above is the constant frame; THIS
   wrapper is what _fit() scales (zoom) so dense slides shrink WITHOUT resizing the
   panel. It carries the column flow + vertical rhythm (the gap moved off the
   panel onto here). transform-origin top-left so zoom anchors to the panel's
   top-left, matching justify-content:flex-start. */
.slide .slide__fit {
  display: flex;
  flex-direction: column;
  gap: 0;                       /* CONTENT-SPACING (16.6.): rytmus přes head/body, ne uniform gap */
  width: 100%;
  flex: 1 1 auto;              /* vyplň panel → .slide__body flex:1 může centrovat obsah */
  min-height: 0;
  transform-origin: top left;
}

/* CONTENT-SPACING systém (16.6.): head = nadpisová sekce MIMO _fit zoom → konzistentní
   velikost a pozice nadpisu na KAŽDÉM slidu. body = jediný target _fit() zoom + dýchá. */
.slide__head {
  flex: 0 0 auto;
  margin-bottom: var(--head-body-gap, 2rem);
}
.slide__head .eyebrow { margin-bottom: var(--space-xs); }   /* eyebrow hugs heading */
.slide__body {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  gap: var(--body-item-gap, 1.5rem);
  min-height: 0;
  transform-origin: top left;
}
/* desktop: první body prvek dostane auto-top → obsah „plave" / vertikálně centrovaný
   ve zbylém prostoru pod fixním headingem (margin-top:auto se NEpočítá do scrollHeight
   → žádná zoom penalta). Na mobilu vypnuto (níže v @media). */
.slide__body > *:first-child { margin-top: auto; }
.slide__body > *:last-child  { margin-bottom: auto; }
.slide__fit > .quote { margin-top: var(--space-2xs); }

/* CONTENT-SPACING: optické zalomení — balance vyrovná řádky nadpisů (bez orphanů),
   pretty zlepší wrapping delších odstavců. Fallback = běžné wrapping (žádný bug). */
.heading, .heading--sub, .heading--small, .display,
.bento__title, .card__title { text-wrap: balance; }
.lead, .body, .quote, .slide__sub,
.bento__body, .card__sub, .bento__kicker { text-wrap: pretty; }

/* Dark brand moments (title / finale / pains) → the CARD is charcoal; the shared
   grey plane and logo stay constant. (.section--dark is toggled on the slide
   node by deck.js, re-binding the semantic tokens so the card paints dark.)
   The .section--dark base rule paints background-color: var(--bg) — but the
   .slide node is full-viewport, so that would flood the whole plane dark.
   Keep the slide node itself transparent; only the CARD goes charcoal. */
.slide.section--dark { background-color: transparent; }
.slide.section--dark .slide__content {
  background: var(--bg);       /* Finshape navy (--navy via .section--dark) */
  border-color: var(--mood-cream-12);
  box-shadow: none;            /* flat panel on the grey plane (user direction) */
}
.section--dark .display,
.section--dark .slide__sub,
.section--dark .slide__meta { color: var(--mood-cream); }

/* COLORED PANEL — coral. Same pattern as dark: the slide node stays transparent
   (grey plane constant), only the PANEL paints in the Finshape accent; nested
   cards/bento cells use the re-bound --bg-raised. */
.slide.theme-coral { background-color: transparent; }
.slide.theme-coral .slide__content {
  background: var(--bg);   /* --bg = deep Finshape orange #C2410C (white text ≈ 5:1) */
  border-color: rgba(255, 255, 255, 0.20);
  box-shadow: none;
}
.theme-coral .display,
.theme-coral .slide__sub,
.theme-coral .slide__meta { color: #FFFFFF; }
/* nested .card / .bento__cell on the coral panel → re-bound bg-raised + frame */
.theme-coral .slide__content .card,
.theme-coral .bento__cell {
  background: var(--bg-raised);
  border-color: var(--frame);
  color: #FFFFFF;
}
.theme-coral .bento__cell--accent {
  background: var(--accent-fill);   /* white tile, deep-orange text */
  border-color: rgba(255, 255, 255, 0.35);
}

/* ============================================================================
   #13 — FULL-PAGE HERO (slide 01 only). The panel spans the WHOLE page (equal
   L/R gutter), covering the 3D scene. The title content stays in the SAME left
   column as every other slide (so nothing moves when the panel later springs
   back to the left half — deck.js animates the panel's `right` edge). While the
   hero is full-page, the footer chrome is hidden and the logo flips to white
   (it now sits on the charcoal panel, not the grey plane).
   ============================================================================ */
.slide--hero .slide__content {
  right: var(--card-gutter);     /* left:gutter + right:gutter ⇒ full-page width */
  width: auto;
  justify-content: center;       /* #15: use the full page HEIGHT — centre the block */
}
.slide--hero .slide__fit {
  /* #15: the hero uses more of the page (wider column + bigger title). The morph
     fades this content out BEFORE the panel clips, so a wide title is safe — the
     clip never cuts visible text. */
  max-width: min(62vw, 900px);
  gap: var(--space-lg);
}
/* font-size per title-line is now owned by the scoped styles in 01-title.js
   (.slide--hero .hero-title-line1 / .hero-title-line2) — do not set here. */
.slide--hero .display { /* font-size intentionally unset — see 01-title.js hero styles */ }

/* ============================================================================
   HYBRID A+C (16.6.) — HERO-ONLY: warm scrim + mix-weight titul + hairline.
   Vše scopováno na .slide--hero / třídy použité jen v 01-title.js → žádný jiný
   slide se nemění. Snadno revertovatelné (jeden blok + 01-title.js).
   ============================================================================ */
/* warm terracotta radial scrim z dolního-levého rohu (background-color charcoal
   zůstává z .section--dark .slide__content; přidáváme jen background-image) */
.slide--hero .slide__content {
  background-image: radial-gradient(
    ellipse 140% 90% at 25% 115%,
    rgba(188, 110, 87, 0.20) 0%,
    rgba(154, 111, 46, 0.06) 40%,
    transparent 65%
  );
}
/* Hero title / rule / sub-label styles are injected by 01-cover.js (scoped to that
   slide). The hero base layout (centering, full-page panel, chrome) stays below. */
/* #15: the hero shows the SAME chrome as every slide. The hero panel is full-page,
   so the nav cluster sits at the FULL-PAGE right edge (not the 50vw half edge);
   the progress ticks stay bottom-left. Ticks/arrows already get the dark-panel
   treatment via .deck-shell.is-dark (slide 01 is dark). */
.deck-shell.is-hero .slide-nav { right: calc(var(--card-gutter) + var(--footer-inset)); }
/* #10 (16.6.): on the full-page hero the TOP progress bar spans the WHOLE page width
   (same --panel-pad inset both sides), matching the full-page hero panel. On the
   1→2 morph the bar retracts to the left-half in sync with the panel clip (driven by
   _heroMorph in deck.js), so this static override only sets the hero's resting width. */
.deck-shell.is-hero .progress-dial { right: calc(var(--card-gutter) + var(--panel-pad)); }
/* the corner logo would collide with the nav cluster on the full-page hero (panel
   right edge == page right edge), so hide it on the hero — the title slide carries
   the MOOD ✕ MUNI identity in its own content. */
.deck-shell.is-hero .deck-logo { opacity: 0; pointer-events: none; }
/* fade the chrome opacity changes smoothly */
.progress-dial,
.slide-nav,
.deck-logo { transition: opacity 300ms var(--ease-out); }   /* Emil: chrome show/hide ≤300ms (bylo 560ms) */

/* REDESIGN v3: "cover" mode is gone — every slide is the left-panel split, the
   3D floats right on every slide. The full-width cover card + .has-cover stage
   masking have been removed; the .stage stays visible at all times. */
.stage[aria-hidden='true'] { pointer-events: none; }

/* ============================================================================
   SLIDE PRIMITIVES — reusable building blocks for all slides
   ============================================================================ */

/* ---- section number + eyebrow (jholec numbered-section signature) --------- */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  font-size: var(--fs-micro);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--text-muted);
}
.eyebrow__num {
  font-variant-numeric: tabular-nums;
  color: var(--accent-text);   /* WCAG: small label → deeper terracotta / peach on dark */
}
.eyebrow__slash { color: var(--rule); }   /* the jholec " / " separator */
/* §A.2 — when a slide spends its single terracotta accent ELSEWHERE (a key word,
   a .tag--accent, an accent chip), quiet the eyebrow number to muted so only ONE
   terracotta hit survives on the slide. */
.eyebrow--quiet .eyebrow__num { color: var(--text-muted); }

/* ---- IDENTITY BADGE — top-left of the panel, built from slide metadata ------
   STEP-2 (§C). Replaces the bottom-right counter: a soft fill-shape pill with a
   thin Lucide topic icon + slide number + label, pinned absolute to the panel's
   top-left. Built in deck.js _enter() from slide.label / slide.icon / index, and
   inserted OUTSIDE .slide__fit so _fit()'s zoom never moves it. Works on white,
   charcoal, terracotta and sage panels (variants below). */
.slide-badge {
  /* REDESIGN 16.6.: persistent fixed chrome in the panel's BOTTOM-LEFT corner,
     inline with the nav arrows (both share --footer-baseline; 38px height matches
     the 38px nav button row so their centres align). Progress ticks moved to TOP. */
  position: fixed;
  bottom: var(--footer-baseline);
  left: calc(var(--card-gutter) + var(--footer-inset));
  top: auto;
  z-index: var(--z-chrome);
  height: 38px;
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  padding: 0;                        /* REDESIGN 16.6.: čistý text+ikony, žádný pill */
  font-size: var(--fs-micro);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-label);
  /* no background / border / radius — clean identity text on the panel (user 16.6.).
     default WHITE panel: terracotta icon/number, muted label (kontrast ≥ AA na cream). */
  color: var(--text-muted);
  pointer-events: none;   /* identity only — not interactive */
}
.slide-badge[hidden] { display: none; }   /* override inline-flex on hero */
.slide-badge__icon  { color: var(--accent-text); flex: 0 0 auto; display: block; }
.slide-badge__num   { color: var(--accent-text); font-variant-numeric: tabular-nums; }
.slide-badge__label { text-transform: uppercase; color: var(--text-secondary); }

/* DARK panel (charcoal): clean text, no fill → icon/num/label must all be a LIGHT
   colour (terracotta #9A4F37 fails on charcoal without a pill behind it). Cream
   reads ≥ AA on charcoal; the terracotta number would drop below 4.5:1. */
.deck-shell.is-dark .slide-badge__icon,
.deck-shell.is-dark .slide-badge__num   { color: var(--mood-cream); }
.deck-shell.is-dark .slide-badge__label { color: var(--mood-cream); }

/* COLOURED panel (terracotta / sage): clean white text on the deep colour (≥ AA). */
.deck-shell.is-colored .slide-badge__icon,
.deck-shell.is-colored .slide-badge__num,
.deck-shell.is-colored .slide-badge__label { color: #FFFFFF; }

/* Badge no longer sits at the panel TOP → no top reserve needed. The TOP progress
   bar lives inside the existing --panel-pad top zone (above the content). */

/* ---- headings ------------------------------------------------------------- */
.heading {
  font-family: var(--font-sans);
  font-size: var(--fs-h1);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-tight);
  letter-spacing: var(--ls-heading);
  color: var(--text);
  max-width: 22ch;
}
.heading--sub {
  font-size: var(--fs-h2);
  line-height: var(--lh-snug);
}
.heading--small {
  font-size: var(--fs-h3);
  line-height: var(--lh-snug);
}
/* hero display — template default: tight-tracked Inter, žádná kurzíva (jholec).
   Brand se serif display fontem (Playfair apod.) přemapuje --font-serif
   v tokens.css a přepne font-style na italic — v mood yoga to Jakub explicitně
   chtěl (revert 16.6.), s Interem kurzíva default není. */
.display {
  font-family: var(--font-serif);
  font-style: normal;
  font-weight: var(--fw-medium);
  font-size: var(--fs-display);
  line-height: var(--lh-tight);
  letter-spacing: var(--ls-display);
  color: var(--text);
}

/* ---- slide-level sub-title + meta (used in slide 01 title hero) ---------- */
/* jholec §3: distinct Body-L for sub-text, Meta (muted, uppercase) for author
   line. Both classes live here so the dark-section overrides above can reach
   them via the .section--dark cascade. */
.slide__sub {
  font-size: var(--fs-lead);
  font-weight: var(--fw-medium);
  color: var(--text-secondary);
  line-height: var(--lh-snug);
}
.slide__meta {
  font-size: var(--fs-small);
  font-weight: var(--fw-medium);
  color: var(--text-muted);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  margin-top: var(--space-lg);
}

/* ---- body column ---------------------------------------------------------- */
.body {
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--text-secondary);
  max-width: var(--measure);
}
.body--narrow { max-width: var(--measure-narrow); }
.lead {
  font-size: var(--fs-lead);
  line-height: 1.5;
  color: var(--text-secondary);
  max-width: var(--measure);
}
.body p + p { margin-top: var(--space-sm); }

/* ---- quote callout (Playfair brand voice) --------------------------------- */
.quote {
  position: relative;
  /* simple handwriting (Caveat) for quotes — supports Czech diacritics. Caveat
     reads large, so keep it only modestly above body size. User 18.6.: vrátit
     postranní vertikální linku vlevo (accent) u VŠECH citací. */
  font-family: var(--font-hand);
  font-style: normal;
  font-weight: var(--fw-medium);
  font-size: calc(var(--fs-lead) * 1.2);
  line-height: 1.25;
  color: var(--text);
  max-width: var(--measure);
  padding-left: 0.95rem;
  border-left: 2px solid var(--accent);
}
.quote__cite {
  display: block;
  margin-top: var(--space-sm);
  font-family: var(--font-sans);
  font-style: normal;
  font-size: var(--fs-small);
  font-weight: var(--fw-medium);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--text-muted);
}

/* ---- 2D artefact frame (off-mode: CJM, blueprint, matice, maps) ----------- */
.artefact {
  position: relative;
  z-index: var(--z-artefact);
  background: var(--bg-raised);
  border: var(--border-hair) solid var(--frame);
  border-radius: var(--radius);
  box-shadow: var(--shadow-art);
  overflow: hidden;
}
.artefact > img,
.artefact > svg,
.artefact > canvas {
  display: block;
  width: 100%;
  height: auto;
}
.artefact__caption {
  padding: var(--space-sm) var(--space-md);
  font-size: var(--fs-small);
  color: var(--text-muted);
  border-top: var(--border-hair) solid var(--rule);
}

/* ---- generic card (icon + title + subtitle, jholec card pattern) ----------
   jholec card: light-gray fill, rounded 16px, NO border, NO shadow. */
.card {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  padding: var(--space-md);
  background: var(--surface-canvas-deep);
  border: 0;
  border-radius: 16px;
  box-shadow: none;
}
/* REDESIGN fix (finding #7): nested .card inside the white floating card would
   be white-on-white (bg-raised = #FFF, same as the outer card). Override to the
   warm canvas grey so hierarchy is: grey plane → white card → grey nested cards.
   This matches jholec card-on-canvas §2 (gray-light as card bg on white).
   WCAG fix: scope this to the DEFAULT (white) panel only. On dark / coloured
   panels the nested card text is cream/white; a grey #EBEBEB fill made it 1.12:1
   (invisible). There the card uses the re-bound --bg-raised (a light alpha tint of
   the dark/coloured panel) so cream text keeps its contrast. */
.slide:not(.section--dark):not(.theme-coral)
  .slide__content .card {
  background: var(--surface-canvas-deep);
}
/* On dark / coloured panels the flat card uses a light alpha tint so its text
   keeps contrast (a flat grey would vanish). Still no border / radius / shadow. */
.slide.section--dark .slide__content .card,
.slide.theme-coral .slide__content .card {
  background: var(--bg-raised);
}
.card__title { font-size: var(--fs-h3); font-weight: var(--fw-semibold); color: var(--text); }
.card__sub   { font-size: var(--fs-small); color: var(--text-muted); }

/* ---- pill / tag / Light·Deep duality marker ------------------------------- */
.tag {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  padding: 0.25em 0.75em;
  font-size: var(--fs-micro);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--text-muted);
  background: var(--scrim);
  border: var(--border-hair) solid var(--rule);
  border-radius: var(--radius-pill);
}
.tag--accent { color: var(--accent-fill-on); background: var(--accent-fill); border-color: transparent; }
.tag--support{ color: var(--accent-on); background: var(--support); border-color: transparent; }

/* ---- hairline divider ----------------------------------------------------- */
.rule { height: var(--border-hair); border: 0; background: var(--rule); width: 100%; }

/* ============================================================================
   CHROME — logo + progress dial + nav affordance (persistent, fixed)
   ============================================================================ */

/* ---- brand logo (swaps dark/white per section via two <img>) -------------- */
.deck-logo {
  /* REDESIGN v4 (user direction): the MOOD ✕ MUNI lockup lives in the bottom-RIGHT
     corner of the PAGE (over the grey / 3D right area), where the counter used to
     be. It sits on the light grey plane — never on a panel — so it always uses the
     DARK variant. */
  position: fixed;
  bottom: clamp(1.25rem, 3vh, 2.25rem);
  right: clamp(1.25rem, 2.5vw, 2.5rem);
  left: auto;
  top: auto;
  height: clamp(16px, 2vh, 22px);   /* shrunk overall (user: "obě zmenši") */
  display: flex;
  align-items: center;
  gap: clamp(0.45rem, 0.8vw, 0.75rem);
  z-index: var(--z-chrome);
  pointer-events: none;
}
/* Finshape wordmark in the bottom-right corner — fills the .deck-logo height. */
.deck-logo__finshape { height: 100%; width: auto; display: block; }
/* Text wordmark used in the loader lockup ("AI Marketplace"). */
.brand-wm {
  font-family: var(--font-sans);
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1;
  white-space: nowrap;
  color: var(--mood-ink);
}

/* ---- progress bar — horizontal step-ticks, bottom-LEFT of the SLIDE PANEL ---- */
/* REDESIGN v4 (user direction): the progress bar moves INTO the slide panel, in
   its bottom-LEFT corner (where the logo briefly was). It sits directly on the
   panel now, so no pill background/blur is needed — clean ticks. One tick per
   slide; the active tick widens + colours terracotta. */
.progress-dial {
  /* REDESIGN 16.6.: moved from bottom-left to the TOP of the slide panel, spanning
     the content inner width (aligned with --panel-pad on both sides). Ticks are now
     a SEGMENTED proportional bar (each tick flex:1) — active segment colours in. */
  position: fixed;
  top: calc(var(--card-gutter) + var(--panel-pad) - 1.6rem);
  left: calc(var(--card-gutter) + var(--panel-pad));
  right: calc(50vw + var(--card-gutter) * 0.5 + var(--panel-pad));
  bottom: auto;
  transform: none;
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 6px;
  z-index: var(--z-chrome);
  pointer-events: auto;
}
.progress-dial__tick {
  position: relative;
  flex: 1 1 0;            /* segmented bar — each tick stretches equally across the width */
  height: 3px;
  border-radius: var(--radius-pill);
  background: var(--rule);
  border: 0;
  padding: 0;
  cursor: pointer;
  opacity: 0.7;
  /* no more width animation (segments are fixed-flex); only colour/height/opacity */
  transition:
    background var(--dur-base) var(--ease-out),
    height     var(--dur-fast) var(--ease-out),
    opacity    var(--dur-base) var(--ease-out);
}
/* extend the clickable/touch box vertically (segment is already wide) so the thin
   bar stays comfortably hittable */
.progress-dial__tick::before {
  content: '';
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  transform: translateY(-50%);
  height: 40px;            /* ≥40px comfortable touch/click hit area for the thin bar */
}
@media (hover: hover) and (pointer: fine) {
  .progress-dial__tick:hover { opacity: 1; background: var(--text-muted); }
}
.progress-dial__tick.is-active {
  background: var(--accent);
  opacity: 1;
  height: 4px;
}
.progress-dial__tick:active { transform: scaleY(0.7); }   /* tactile press feedback */
/* dark slide panels (01 / 10 / 15): lift the inactive ticks so they read on the
   charcoal panel; the active tick stays terracotta (legible on charcoal). */
.deck-shell.is-dark .progress-dial__tick { background: rgba(250, 248, 243, 0.22); }
.deck-shell.is-dark .progress-dial__tick.is-active { background: var(--accent); }
/* STEP-2 (§D): coloured panels — active tick is normally terracotta (--accent),
   which would vanish on a terracotta panel → force white ticks on is-colored. */
.deck-shell.is-colored .progress-dial__tick { background: rgba(255, 255, 255, 0.30); }
.deck-shell.is-colored .progress-dial__tick.is-active { background: #FFFFFF; }

/* STEP-2 (§C): the numeric counter (.progress-dial__count) was REMOVED — the
   identity badge now carries the slide number + topic. Rule intentionally gone. */

/* ---- slide-nav arrows — bottom-RIGHT corner INSIDE the left slide panel ----- */
/* Decent jholec hairline pill buttons; click → deck.prev()/next(). Keyboard nav
   stays unchanged. The panel's right edge = left gutter + width = 50vw - 0.5*gutter.
   We position with `right` measured from the panel's right edge inward so the
   inset is explicit and can never push the buttons back onto the grey gap.
   Panel right edge from viewport-right = 50vw + 0.5*card-gutter; we subtract a
   small inset so the buttons sit inside the panel corner. */
.slide-nav {
  position: fixed;
  /* REDESIGN v6: shares --footer-baseline with the ticks. Mirror the left inset:
     the panel's right edge is (50vw + 0.5*card-gutter) from the viewport right;
     step the SAME --footer-inset inward so left/right insets match exactly. */
  bottom: var(--footer-baseline);
  right: calc(50vw + var(--card-gutter) * 0.5 + var(--footer-inset));
  transform: none;
  margin: 0;
  display: inline-flex;
  align-items: center;          /* counter + arrows share one baseline */
  gap: var(--space-xs);
  z-index: var(--z-chrome);
}
.slide-nav__btn {
  width: 40px;            /* ≥40px hit area */
  height: 40px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: var(--border-hair) solid var(--rule);
  border-radius: var(--radius-pill);
  background: var(--surface-card);   /* blends with the white panel */
  color: var(--text-muted);
  cursor: pointer;
  padding: 0;
  transition:
    color        var(--dur-fast) var(--ease-out),
    border-color var(--dur-fast) var(--ease-out),
    background    var(--dur-fast) var(--ease-out),
    transform     100ms var(--ease-out),
    opacity      var(--dur-fast) var(--ease-out);
}
.slide-nav__btn svg { width: 18px; height: 18px; display: block; }
/* Emil: scale-on-press tactile feedback (0.96 — nikdy pod 0.95) */
.slide-nav__btn:active { transform: scale(0.96); }
/* hover jen na zařízeních s myší (touch by sticky-hover držel zvýraznění po tapu) */
@media (hover: hover) and (pointer: fine) {
  .slide-nav__btn:hover { color: var(--accent); border-color: var(--accent); }
}
.slide-nav__btn[disabled] { opacity: 0.32; pointer-events: none; }

/* dark panel (01 title / 10 pains / 15 close): the arrows sit ON the charcoal
   panel, so flip them to a charcoal-tinted button (deck.js toggles .is-dark on
   the shell when slide.dark). Progress bar + counter live over the grey/3D right
   half, NOT over the panel, so they are NOT flipped. */
.deck-shell.is-dark .slide-nav__btn {
  background: var(--mood-ink-soft);
  border-color: var(--mood-cream-12);
  color: var(--mood-cream-60);
}
@media (hover: hover) and (pointer: fine) {
  .deck-shell.is-dark .slide-nav__btn:hover { color: var(--accent); border-color: var(--accent); }
}

/* STEP-2 (§D): coloured panel (terracotta / sage) — arrows sit ON the colour, so
   flip them to a translucent-white pill (white-on-colour). */
.deck-shell.is-colored .slide-nav__btn {
  background: rgba(255, 255, 255, 0.16);
  border-color: rgba(255, 255, 255, 0.32);
  color: #FFFFFF;
}
@media (hover: hover) and (pointer: fine) {
  .deck-shell.is-colored .slide-nav__btn:hover { color: #FFFFFF; border-color: #FFFFFF; }
}

/* ============================================================================
   MULTI-STEP SLIDE support (slide 08 current-journey walkthrough)
   sub-steps fade between synced text blocks while the stage walks W2→W6
   ============================================================================ */
/* The synced left-hand text for each 3D step slides in from its own (left) side
   as the stage walks to the matching waypoint on the right. */
.step {
  opacity: 0;
  pointer-events: none;
  transform: translateX(-26px);
  transition:
    opacity   var(--dur-base) var(--ease-out),
    transform var(--dur-slow) var(--ease-out);
}
.step.is-active {
  opacity: 1;
  pointer-events: auto;
  transform: none;
}
@media (prefers-reduced-motion: reduce) {
  .step { transform: none; }
  /* honour the OS setting: no travel, no blur — a plain instant opacity swap */
  .rise { transform: none; filter: none; }
  .is-active .rise { transition: opacity var(--dur-fast) var(--ease-out); }
}

/* entrance helper — split & staggered rise: each block fades up from --rise-y
   (the deck flips its sign per nav direction) with a soft blur-in. Calm, never
   bouncy. Combining opacity + translateY + blur reads far smoother than a flat
   container crossfade, and the stagger gives the eye a path to follow. */
.rise {
  opacity: 0;
  transform: translateY(var(--rise-y, 18px));
  filter: blur(4px);            /* soft defocus; 4px reads as well as 6px, cheaper */
}
.is-active .rise {
  opacity: 1;
  transform: none;
  filter: blur(0);
  transition:
    opacity   var(--dur-base) var(--ease-out),
    transform var(--dur-base) var(--ease-out),
    filter    var(--dur-base) var(--ease-out);
  /* CONTENT-SPACING (16.6.): po head/body splitu nejsou .rise přímí potomci .slide__fit,
     takže nth-child cascade přestala fungovat. Stagger teď řídí inline --delay nastavený
     v deck.js v DOM pořadí (head .rise → body .rise). ~50ms krok (Emil: 30–80ms). */
  transition-delay: var(--delay, 0ms);
}

/* ============================================================================
   RESPONSIVE — mobile / portrait: stack the 3D scene as a TOP strip (~40% of the
   viewport) and the slide content BELOW it (~60%). The deck's left/right split
   doesn't work on a narrow screen, so we go full-width top-and-bottom. Stage3D's
   ResizeObserver re-frames the ortho camera to the new wide-short canvas, so the
   scene just adapts — no JS change needed there.
   ============================================================================ */
@media (max-width: 900px), (orientation: portrait) {
  /* The right-half visual slot is empty for now, so on mobile we collapse it and
     let the slide card own the whole screen (no reserved top strip). When per-slide
     visuals land, give them a mobile strip and restore --stage-h. */
  :root { --stage-h: 0.75rem; }
  .stage { display: none; }

  /* #15: on mobile the hero is NOT full-page (no horizontal retract) — it uses the
     normal bottom band like every slide. Reset the desktop hero overrides so the
     title column fills the band, the nav sits in the band's corner, and the logo
     stays on the scene strip. */
  .slide--hero .slide__fit { max-width: none; }
  .deck-shell.is-hero .slide-nav { right: 0.9rem; }
  .deck-shell.is-hero .deck-logo { opacity: 1; }

  /* 3D scene → full-width strip pinned to the TOP. Transparent canvas → the grey
     plane (deep tone via shell vignette) shows behind the strip.
     NOTE (16.6.): user wants the scene FULL-height on mobile (island visible at top
     above the card). Naive full-height broke per-waypoint island framing (tall-narrow
     aspect ≠ wide-short strip) → reverted to the working strip; full-height + proper
     per-waypoint mobile camera re-tune is a dedicated task. */
  /* USER 17.6.: scéna PŘES CELOU VÝŠKU obrazovky (full-height), karta na ní PLAVE.
     Karta = BÍLÝ panel + ŠEDÉ buňky (jako desktop) — ALE kolem/za zaoblenou kartou
     ŽÁDNÝ šedý box: scéna prosvítá v okrajích (deck-shell grey plane je celý překrytý
     full-height canvasem). --stage-h zůstává jen jako TOP offset karty (horních ~40vh
     ukazuje ostrov/panáčka, karta začíná pod ním a scéna jede full-height ZA ní). */
  .stage {
    inset: 0;
    width: 100vw;
    height: 100dvh;
    opacity: 1;
    pointer-events: none;
  }

  /* The slide stays a plain wrapper; the CARD (=.slide__content) becomes a
     full-width-ish card pinned under the strip — still a card (margin + radius +
     shadow), not edge-to-edge, keeping the jholec card-on-grey feel on mobile. */
  .slide .slide__content {
    position: absolute;
    inset: calc(var(--stage-h) + 0.75rem) 0.9rem 0.9rem 0.9rem;
    top: calc(var(--stage-h) + 0.75rem);
    left: 0.9rem;
    right: 0.9rem;
    transform: none;
    width: auto;
    height: auto;
    max-width: 640px;
    margin-inline: auto;
    border-radius: var(--radius-card);
    box-shadow: none;            /* flat panel on the grey plane (user direction) */
    overflow-y: auto;
    /* REDESIGN fix (finding #12): dense cover artefacts (blueprint 5-col grid,
       impact matrix) can be wider than any mobile viewport. Clip the card so
       no horizontal bleed escapes the card container. The .artefact inside gets
       overflow-x:auto so users can scroll the diagram within its own frame. */
    overflow-x: hidden;
    -webkit-overflow-scrolling: touch;
    /* Fix [finding #3]: reserve the nav pill's full footprint. Pill height = 38px
       (button) + 0.45rem*2 (padding) = 38px + 0.9rem. Pill bottom = 0.9rem + safe-area.
       Add 0.75rem breathing above the pill. Total: 38px + 0.9rem + 0.9rem + safe-area + 0.75rem. */
    padding: 1.5rem 1.4rem calc(38px + 1.65rem + env(safe-area-inset-bottom, 0px) + 0.75rem);
    justify-content: flex-start;
  }

  /* (Panel + buňky: mobil dědí desktop originál — BÍLÁ karta + ŠEDÉ prvky.
     Žádný mobilní inverzní override. Desktop = mobil.) */

  /* Dense artefact diagrams (blueprint, impact, ecosystem) scroll horizontally
     within their own frame on mobile rather than forcing layout bleed. */
  .artefact {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }

  /* Chrome on mobile: hide the horizontal progress bar (no room), keep the
     counter bottom-LEFT and the slide-nav arrows bottom-RIGHT inside the panel
     band so they never collide. */
  .progress-dial { display: none; }   /* 16 horizontal ticks would collide with the nav cluster on a phone */
  /* Badge is now clean text (no pill) fixed over the card — on mobile the card content
     scrolls UNDER it → unreadable collision (no opaque fill to hide content). Hide it
     on mobile; the heading carries the slide's topic. (Desktop keeps it bottom-left.) */
  .slide-badge { display: none; }

  /* CONTENT-SPACING mobil: žádné vertikální centrování (přirozený scroll), menší
     head→body mezera, vypnout desktop margin-top/bottom:auto. */
  .slide__head { margin-bottom: var(--space-md); }
  .slide__body { justify-content: flex-start; }
  .slide__body > *:first-child { margin-top: 0; }
  .slide__body > *:last-child  { margin-bottom: 0; }
  /* the counter now rides INSIDE .slide-nav (bottom-right) — no separate rule */
  .slide-nav {
    left: auto;
    right: 0.9rem;
    /* Fix [finding #3]: incorporate iOS safe-area-inset-bottom so the pill clears
       the home-bar on notched devices. Increase base bottom from 1rem to 0.9rem
       (matches card inset) plus the safe area offset. */
    bottom: calc(0.9rem + env(safe-area-inset-bottom, 0px));
    transform: none;
    margin: 0;
    /* Fix [finding #3]: increase pill padding for less cramped counter + arrows.
       0.45rem vertical × 0.75rem horizontal. */
    background: var(--surface-card);
    border-radius: var(--radius-pill);
    padding: 0.45rem 0.75rem;
    box-shadow: 0 1px 2px rgba(43,43,43,0.05), 0 6px 18px rgba(43,43,43,0.08);
  }
  /* Fix [finding #3 + #6]: dark-panel mobile pill goes dark-on-dark (--mood-ink-soft
     on --mood-ink background, no border). Add a hairline cream border so the pill
     shape reads against the charcoal card. */
  .deck-shell.is-dark .slide-nav {
    background: var(--mood-ink-soft);
    border: 1px solid var(--mood-cream-12);
    box-shadow: none;
  }
  /* Mobile: the lockup sits TOP-left on the 3D scene strip (its mobile home),
     not in the page bottom-right where the nav cluster lives. Always dark on grey. */
  .deck-logo {
    top: 0.9rem;
    left: 0.9rem;
    right: auto;
    bottom: auto;
    height: 18px;
  }
}

@media (max-width: 560px) {
  /* phones: keep the 40/60 split; just trim the logo so it sits neatly on the
     3D strip. Dense cover artefacts (CJM / blueprint / matrix) scroll within the
     content band — unavoidable for a wide diagram on a phone. */
  .deck-logo { height: 20px; }
}

/* ── Mobile-only hint (deck tuned for desktop; mobile WIP) ────────────────────
   Default skrytý (desktop). Zobrazí se jen na úzkých/portrait obrazovkách jako
   horní toast. .is-gone = fade-out. User 17.6. */
.mobile-hint { display: none; }

@media (max-width: 900px), (orientation: portrait) {
  .mobile-hint {
    display: flex;
    align-items: center;
    gap: var(--space-xs);
    position: fixed;
    top: calc(0.6rem + env(safe-area-inset-top, 0px));
    left: 0.6rem;
    right: 0.6rem;
    z-index: 9000;
    padding: 0.7rem 0.85rem;
    border-radius: var(--radius-md, 16px);
    background: var(--surface-card, #fff);
    color: var(--text, #2b2b2b);
    box-shadow: 0 6px 24px rgba(43, 43, 43, 0.22), 0 1px 3px rgba(43, 43, 43, 0.12);
    border: 1px solid var(--mood-ink-08, rgba(43,43,43,0.08));
    font-size: var(--fs-small, 0.82rem);
    line-height: 1.35;
    -webkit-font-smoothing: antialiased;
    transition: opacity 0.4s ease, transform 0.4s ease;
  }
  .mobile-hint__icon { flex: 0 0 auto; font-size: 1.2rem; }
  .mobile-hint__text { flex: 1 1 auto; }
  .mobile-hint__text strong { color: var(--accent-text, var(--accent)); }
  .mobile-hint__close {
    flex: 0 0 auto; opacity: 0.5; font-size: 0.95rem; line-height: 1;
    padding: 0.25rem 0.4rem; margin: -0.25rem -0.2rem -0.25rem 0;
    background: none; border: 0; color: inherit; cursor: pointer;
    -webkit-appearance: none; appearance: none;
  }
  .mobile-hint.is-gone { opacity: 0; transform: translateY(-8px); pointer-events: none; }
}
