/* ==========================================================================
   Fonts — Manrope (SIL OFL 1.1), self-hosted, latin + latin-ext subsets.
   Both subsets point at the same variable font file per weight, mirroring
   how Google Fonts itself serves it — the browser instances the requested
   weight out of the single variable file.
   ========================================================================== */
@font-face {
  font-family: "Manrope";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../assets/fonts/manrope-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Manrope";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../assets/fonts/manrope-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Manrope";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../assets/fonts/manrope-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Manrope";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../assets/fonts/manrope-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Manrope";
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url("../assets/fonts/manrope-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
    U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
    U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Manrope";
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url("../assets/fonts/manrope-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
    U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
    U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ==========================================================================
   Tokens — palette per PROJECT-BRIEF.md. One accent hue, two tints:
   --color-accent for icons/borders/focus (3:1 graphical-object contrast),
   --color-accent-strong for filled buttons with white text (4.5:1 text contrast).
   ========================================================================== */
:root {
  --color-bg: #f5f5f3;
  --color-surface: #ffffff;
  --color-ink: #30302f;
  --color-ink-soft: #777777;
  --color-ink-dark: #777777;
  --color-accent: #249b55;
  --color-accent-strong: #1d7c44;
  --color-border: #e3e3df;

  --font-display: "Manrope", -apple-system, "Segoe UI", Roboto, system-ui, sans-serif;
  --font-body: "Manrope", -apple-system, "Segoe UI", Roboto, system-ui, sans-serif;

  --radius: 14px;
  --scrim-width: min(44vw, 540px);
  --env-transition: 900ms;

  /* Hero glass (S0) — antracite frosted-glass panel tokens. Kept separate
     from the light --color-* tokens above: this is the one deliberately
     dark surface in the S0/S1 journey, scoped entirely to .hero-glass. */
  /*--hero-glass-bg-opaque: rgba(38, 38, 38, 0.95);*/
  /*--hero-glass-bg-mid: rgba(38, 38, 38, 0.80);*/
  /*--hero-glass-bg-edge: rgba(38, 38, 38, 0.30);*/

  --hero-glass-bg-opaque: rgba(38, 38, 38, 0.90);
  /* -mid/-edge no longer read anywhere — the edge used to be a 3-stop
     background gradient (opaque -> mid -> edge) cut by a clip-path wave.
     Replaced by a flat --hero-glass-bg-opaque background + mask-image
     fade on .hero-glass__surface (see that rule for why). Kept here,
     commented, in case the multi-stop falloff is wanted back. */
  /*--hero-glass-bg-mid: rgba(38, 38, 38, 0.0);*/
  /*--hero-glass-bg-edge: rgba(38, 38, 38, 0.0);*/


  --hero-glass-text: #f5f5f3;
  --hero-glass-text-soft: rgba(245, 245, 243, 0.72);

  /* Curved-edge glow (.hero-glass__edge-glow-path) — a crisp line traced
     along the wavy inner edge, then blurred into a soft band. White reads
     as light catching the edge on the dark glass; the light theme inverts
     this to a dark line so the same edge treatment reads as a shadow/crease
     instead of a stray bright glow on a light panel. */
  --hero-glass-edge-glow: #ffffff;

  /* Vertical divider between .hero-glass__benefit items. */
  --hero-glass-benefit-divider: rgba(245, 245, 243, 0.18);

  /*--hero-glass-bg-opaque: rgba(23, 24, 22, 0.88);*/
  /*--hero-glass-bg-fade: rgba(23, 24, 22, 0.3);*/
  /*--hero-glass-text: var(--color-bg);*/
  /*--hero-glass-text-soft: rgba(245, 245, 243, 0.7);*/

  /* Shared glass-selection design system — S1 season picker. Built for
     Variant A (list rows) but deliberately kept generic/reusable (not
     scoped to .s1-list) so Variant B (tiles, next step) can reuse the same
     glass + thematic-selection language without duplicating values. */
  --selection-glass-bg: rgba(255, 255, 255, 0.08);
  --selection-glass-bg-hover: rgba(255, 255, 255, 0.16);
  --selection-glass-bg-selected: rgba(255, 255, 255, 0.14);
  --selection-glass-border: rgba(245, 245, 243, 0.18);
  --selection-glass-border-hover: rgba(245, 245, 243, 0.28);
  --selection-glass-border-selected: var(--color-accent);
  --selection-glass-blur: 18px;

  /* Tile overlay background — same family as the tokens above, but its own
     variable because .s1-tile__overlay sits on top of .s1-tile__scrim (a
     dark photo-legibility gradient the list rows never have to fight). By
     default it just mirrors --selection-glass-bg* (identical to today), so
     only the light theme below needs to actually diverge. */
  --tile-overlay-bg: var(--selection-glass-bg);
  --tile-overlay-bg-hover: var(--selection-glass-bg-hover);
  --tile-overlay-bg-selected: var(--selection-glass-bg-selected);

  /* Tile outer border — unlike the list rows' border (always over the
     glass panel), this sits directly on the photo, whose brightness varies
     wildly by season (dark summer road vs. bright winter snow). Own
     variable so the light theme can pick a color that survives either. */
  --tile-border: var(--selection-glass-border);
  --tile-border-hover: var(--selection-glass-border-hover);
  /* Neutral depth shared by every row regardless of selection: a soft top
     highlight (glass catching light) plus a soft inward darkening (glass
     has thickness). Thematic per-season insets below are layered on top of
     this, never replace it. */
  --selection-glass-inner-depth: inset 0 1px 0 rgba(255, 255, 255, 0.08),
    inset 0 -14px 22px -12px rgba(0, 0, 0, 0.35);

  /* Season accent colors — one hue per season, used for the solid icon
     color AND, since the request to move away from a universal green
     selected/hover state, also the selected border, the ~3px inner shadow
     and the hover glow — everything about a row's "this is the
     summer/winter/... one" identity ties back to this single token.
     Unsure deliberately uses white, not brand green: it has no natural
     "season" hue of its own, and white reads clearly against the
     antracite glass without being confused for a real selection color. */
  --season-summer-accent: #ffb946;
  --season-winter-accent: #78c2ff;
  --season-allseason-accent: var(--color-accent);
  --season-unsure-accent: #ffffff;

  /* All-season's own accent colors — spring green + autumn ochre added
     alongside the existing summer-yellow/winter-blue, so its glow/inset
     reads as "all four seasons blended", not just a warm/cold 2-tone. */
  --season-allseason-spring: #8bc98a;
  --season-allseason-autumn: #c98a4b;

  /* Selected-state inset "colored light reflecting inside the glass" —
     strongest at the edges, fading toward the center (0-offset inset
     shadows do this naturally). All-season blends all four season hues:
     cool corner (winter blue + spring green) on the left, warm corner
     (summer yellow + autumn ochre) on the right. */
  --season-summer-inset: inset 0 0 20px rgba(255, 190, 70, 0.16),
    inset 0 0 3px rgba(255, 190, 70, 0.28);
  --season-winter-inset: inset 0 0 20px rgba(120, 190, 255, 0.16),
    inset 0 0 3px rgba(120, 190, 255, 0.28);
  --season-allseason-inset: inset 20px 0 22px -10px rgba(120, 190, 255, 0.13),
    inset 20px 0 22px -10px rgba(139, 201, 138, 0.1),
    inset -20px 0 22px -10px rgba(255, 190, 70, 0.13),
    inset -20px 0 22px -10px rgba(201, 138, 75, 0.1),
    inset 0 0 3px rgba(245, 245, 243, 0.22);
  --season-unsure-inset: inset 0 0 20px rgba(255, 255, 255, 0.14),
    inset 0 0 3px rgba(255, 255, 255, 0.3);

  /* Hover-only: a soft OUTER glow (not inset), same hue as the row's
     icon/selected color, so hovering previews "this is the summer one"
     before committing to a click. Widened blur + upped opacity from the
     first pass, which read as too faint against the glass. */
  --season-summer-hover-glow: 0 0 12px 1px rgba(255, 190, 70, 0.6);
  --season-winter-hover-glow: 0 0 12px 1px rgba(120, 190, 255, 0.6);
  --season-allseason-hover-glow: 0 0 12px 1px rgba(120, 190, 255, 0.4),
    0 0 12px 1px rgba(255, 190, 70, 0.4);
  --season-unsure-hover-glow: 0 0 12px 1px rgba(255, 255, 255, 0.55);

  /* ==========================================================================
     Wizard shell (S2+) design tokens. Light-mode only for now — the S2 spec
     explicitly scopes this palette to light mode and says not to redesign
     dark mode for it (see docs/99-decisions.md). Reuses --color-surface/
     --color-border/--radius/--font-* directly below where the spec's own
     values are the same or close enough not to justify a duplicate token;
     new tokens exist only where the spec's palette is meaningfully
     different from the S0/S1 glass tokens (e.g. a deeper forest green than
     --color-accent, a near-black-green text color instead of --color-ink).
     Borders/shadows throughout the S2 spec are all --wizard-text at varying
     alpha (rgba(20,30,25,.05/.07/.08) ≈ #111714 tinted) — used here via
     color-mix() at the call site instead of one flat token per alpha step. */
  --wizard-bg: #fafaf8;
  /* Sidebar/content/visual backgrounds (2026-08-11) — each panel is its own
     subtle 3-stop gradient, deliberately angled so the three connect into
     one continuous surface instead of reading as three flat-colored
     boxes: sidebar darkens toward its bottom-left, content darkens toward
     its top-left, visual darkens toward its bottom-right — the darker
     corners of adjacent panels never touch, so the page reads as one
     gently-lit surface, not a striped layout. */
  --wizard-sidebar-bg: linear-gradient(
          to top right,
          #d5dad6 0%,
          #e5e9e5 45%,
          #fafaf8 100%
  );
  /* Inner step-nav panel (2026-08-11) — deliberately just a flat starting
     value (not a gradient like the outer sidebar), meant to be tuned. */
  --wizard-step-nav-bg: var(--wizard-surface);
  --wizard-content-bg: linear-gradient(
          to bottom right,
          #d9dedb 0%,
          #e7ebe8 30%,
          #f5f6f4 65%,
          #ffffff 100%
  );
  --wizard-visual-bg: linear-gradient(
          to top left,
          #cbd5d7 0%,
          #dce4e4 32%,
          #edf1ef 65%,
          #fafaf8 100%
  );
  --wizard-surface: var(--color-surface);
  /* Spec's card border (#E4E7E5) and divider (#E5E8E6) are both within a
     couple of units of the existing --color-border (#E3E3DF) — same
     token, not three near-identical greys. */
  --wizard-border: var(--color-border);

  --wizard-text: #111714;
  --wizard-text-secondary: #626a66;
  --wizard-text-muted: #929995;

  --wizard-primary: #07883f;
  --wizard-primary-hover: #067a38;
  --wizard-primary-active: #056d32;
  --wizard-primary-surface: #edf7f1;
  /* Selected-card tint is a hair lighter than --wizard-primary-surface —
     the spec gives it its own value, not a reuse of the sidebar one. */
  --wizard-card-selected-bg: #f5fbf7;
  /* "Neviete si rady?" helper box — flat, standalone value on purpose, not
     color-mix()'d from --wizard-sidebar-bg/--wizard-step-nav-bg like it
     used to be: those are gradients now, and color-mix() with a gradient
     argument is invalid CSS that silently drops the whole declaration —
     which is exactly why this box lost its background (2026-08-11). */
  --wizard-helper-bg: #f3f4f2;
  /* S3 "Zvolený rozmer" summary panel (2026-08-12) — a plain summary area,
     not a success/confirmation state, so it shouldn't read as green.
     Reuses two of --wizard-content-bg's own stops (#ffffff/#f5f6f4/#e7ebe8
     above) instead of inventing a new color, just re-angled left-to-right
     and lightest-first so the panel reads as "cut from the same material"
     as the content area behind it. */
  --wizard-summary-bg: linear-gradient(
          to right,
          #ffffff 0%,
          #f5f6f4 55%,
          #e7ebe8 100%
  );
}

/* Light theme override — dev-only Light/Dark switch (js/theme.js flips
   [data-theme] on <body>). Same token names as above, just re-pointed at a
   muted soft-gray glass instead of antracite, so every scene reading from
   the --hero-glass-... / --selection-glass-... tokens picks it up
   automatically. Deliberately not white/ivory — kept low-luminance and
   neutral so the glass doesn't read as a glowing wall against the photo.
   Opaque/mid/edge keep the same three-stop falloff as the dark theme (mid
   ~85%, edge ~30% of the opaque alpha) so the glass keeps gradually losing
   opacity toward the curved right edge, blending into the photo instead of
   cutting off hard. Deliberately narrow scope: only the glass panel and
   what's inside it (buttons, boxes, text) changes — no photo/background
   swap. Season accent colors and --selection-glass-inner-depth are shared,
   not overridden. */
[data-theme="light"] {
  /*--hero-glass-bg-opaque: rgba(224, 226, 222, 0.2);*/
  --hero-glass-bg-opaque: rgba(224, 226, 222, 0.7);
  /* -mid/-edge no longer read anywhere — see the dark-theme block above. */
  /*--hero-glass-bg-mid: rgba(224, 226, 222, 0.28);*/
  /*--hero-glass-bg-edge: rgba(224, 226, 222, 0);*/

  --hero-glass-text: #252826;
  /*--hero-glass-text-soft: rgba(37, 40, 38, 0.66);*/
  --hero-glass-text-soft: rgba(37, 40, 38, 0.90);

  /* Inverted from the dark theme's white edge-glow: a dark line on the
     light glass reads as a crease/shadow instead of a stray bright glow. */
  --hero-glass-edge-glow: #252826;

  --hero-glass-benefit-divider: rgba(37, 40, 38, 0.18);

  --selection-glass-bg: rgba(224, 226, 222, 0.35);
  --selection-glass-bg-hover: rgba(224, 226, 222, 0.45);
  --selection-glass-bg-selected: rgba(224, 226, 222, 0.48);
  --selection-glass-border: rgba(224, 226, 222, 0.49);
  --selection-glass-border-hover: rgba(224, 226, 222, 0.54);

  /* Tiles only: .s1-tile__scrim underneath is a fixed dark gradient (photo
     legibility), so the same low --selection-glass-bg* opacity used for
     list rows reads as a near-black overlay here and swallows the (now
     dark-ink) text. Raised well past the list-row values so the light
     glass actually wins over the dark scrim — same opacity at rest/hover/
     selected so the text stays equally legible in every state. */
  --tile-overlay-bg: rgba(224, 226, 222, 0.78);
  --tile-overlay-bg-hover: rgba(224, 226, 222, 0.78);
  --tile-overlay-bg-selected: rgba(224, 226, 222, 0.78);

  /* Dark ink border instead of light gray — reads against both bright
     (winter/snow) and dark (summer/road) tile photos alike, where a light
     border would wash out on the bright ones. */
  --tile-border: rgba(37, 40, 38, 0.35);
  --tile-border-hover: rgba(37, 40, 38, 0.55);

  /* Season icon/border accents — dark theme's #ffb946/#78c2ff are pastel
     enough to fade into the antracite glass in a *good* way, but the same
     values wash out almost invisibly against the light glass. Deepened/
     more saturated versions of the same hues for legibility here only. */
  --season-summer-accent: #c97b00;
  --season-winter-accent: #0e7fc4;

  /* Hover glow re-based on the same deepened accents above (was the dark
     theme's pastel rgba(255,190,70,...)/rgba(120,190,255,...), same
     low-contrast problem as the icon color it was matching). */
  --season-summer-hover-glow: 0 0 12px 1px rgba(201, 123, 0, 0.6);
  --season-winter-hover-glow: 0 0 12px 1px rgba(14, 127, 196, 0.6);

  /* Selected-state inset, same deepened hues. Allseason's blend keeps its
     spring/autumn corners as-is and re-bases only the summer/winter ones,
     plus swaps its center highlight from a light-glass white fleck to a
     dark-ink one (same invert as the edge-glow above). */
  --season-summer-inset: inset 0 0 20px rgba(201, 123, 0, 0.16),
    inset 0 0 3px rgba(201, 123, 0, 0.28);
  --season-winter-inset: inset 0 0 20px rgba(14, 127, 196, 0.16),
    inset 0 0 3px rgba(14, 127, 196, 0.28);
  --season-allseason-inset: inset 20px 0 22px -10px rgba(14, 127, 196, 0.13),
    inset 20px 0 22px -10px rgba(139, 201, 138, 0.1),
    inset -20px 0 22px -10px rgba(201, 123, 0, 0.13),
    inset -20px 0 22px -10px rgba(201, 138, 75, 0.1),
    inset 0 0 3px rgba(37, 40, 38, 0.22);

  /* Allseason's hover glow blends the (now-deepened) summer/winter hues,
     same low-contrast problem as those two on their own. Unsure's plain
     white glow already reads well against the light glass, so allseason
     borrows it here instead of its own blended version. */
  --season-allseason-hover-glow: var(--season-unsure-hover-glow);
}

/* ==========================================================================
   Reset / base
   ========================================================================== */
*,
*::before,
*::after {
  box-sizing: border-box;
}

html {
  color-scheme: light;
}

body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-ink);
  font-family: var(--font-body);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

h1,
h2,
p {
  margin: 0;
}

button {
  font: inherit;
  color: inherit;
}

img {
  max-width: 100%;
  display: block;
}

/* Skip link — visible only on keyboard focus */
.skip-link {
  position: absolute;
  left: 12px;
  top: -60px;
  background: var(--color-ink);
  color: #fff;
  padding: 10px 18px;
  border-radius: var(--radius);
  z-index: 100;
  text-decoration: none;
  transition: top 0.2s ease;
}
.skip-link:focus {
  top: 12px;
}

:focus-visible {
  outline: 3px solid var(--color-accent);
  outline-offset: 3px;
}

/* ==========================================================================
   Journey — sticky scene behind, scrolling content on top.
   Both children share the same grid cell (the classic sticky-background /
   scrolling-foreground overlay technique), so .journey's total height is
   driven purely by the content panels (2 x 100vh) — no manual spacer needed.
   ========================================================================== */
.journey {
  display: grid;
}

.journey__stage,
.journey__glass,
.journey__content {
  grid-column: 1;
  grid-row: 1;
}

.journey__stage {
  position: sticky;
  top: 0;
  height: 100vh;
  /*height: 100dvh;*/
  overflow: hidden;
  z-index: 0;
  background: #1c1c1b; /* letterboxing fallback while the image decodes */
}

/* Sticky like .journey__stage (same containing block, same pin duration),
   but a separate layer: .hero-glass lives here now instead of inside
   .panel--hero, so it's the SAME element throughout the whole S0->S1
   scroll — only its content (the two .hero-glass__screen crossfade
   targets) changes. It used to scroll away with .panel--hero along with
   the rest of .journey__content, which is why the glass previously
   appeared to "vanish" and get replaced by .panel--question's old scrim. */
.journey__glass {
  position: sticky;
  top: 0;
  height: 100vh;
  /*height: 100dvh;*/
  z-index: 1;
  pointer-events: none;
}

.journey__content {
  position: relative;
  z-index: 2;
  pointer-events: none;
}

/* ==========================================================================
   Environment — the photographic layers. One scene is visible at a time
   (opacity crossfade); everything else about "which one" is decided by
   js/environment.js, which only ever toggles the .is-visible class.
   ========================================================================== */
.env-stack {
  position: absolute;
  inset: 0;
  transform-origin: center center;
}

.env-layer {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity var(--env-transition) ease;
}
.env-layer.is-visible {
  opacity: 1;
}
.env-layer picture,
.env-layer img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 42%;
}

/* Snow — decorative only, created once by js/snow.js, toggled via .is-active */
.env-snow {
  position: absolute;
  inset: 0;
  overflow: hidden;
  opacity: 0;
  transition: opacity 500ms ease;
}
.env-snow.is-active {
  opacity: 1;
}
.snow-particle {
  position: absolute;
  top: -6%;
  left: var(--left);
  width: var(--size);
  height: var(--size);
  border-radius: 50%;
  background: #ffffff;
  opacity: 0.8;
  animation: snow-fall var(--duration) linear infinite;
  animation-delay: var(--delay);
  animation-play-state: paused;
}
.env-snow.is-active .snow-particle {
  animation-play-state: running;
}

@keyframes snow-fall {
  from {
    transform: translate(0, -10%);
  }
  to {
    transform: translate(var(--drift), 112vh);
  }
}

/* ==========================================================================
   Panels — text content, scrolling in normal flow over the sticky stage.
   ========================================================================== */
.panel {
  min-height: 100vh;
  /*min-height: 100dvh;*/
  display: flex;
  pointer-events: none;
}

/* .panel--hero no longer holds visible content — .hero-glass moved to
   .journey__glass so it can stay pinned across the whole S0->S1 scroll (see
   that rule's comment). This is now purely a 100vh scroll-height spacer
   (min-height comes from the base .panel rule); removing it would collapse
   .journey__content back to 100vh and break the sticky pin math. */

.panel--question {
  position: relative;
  align-items: flex-end;
}

/* ==========================================================================
   S1 dev variant switch — presentation-only A/B toggle for comparing the
   list vs tiles layout while both are being built (KROK 2-4). Not part of
   the real wizard UI; safe to delete once one variant is chosen for good.
   ========================================================================== */
.s1-demo-switch {
  position: absolute;
  /* Stacked below .theme-demo-switch (2026-08-13) — both used the exact
     same top/right offset, so the theme switch (position: fixed, higher
     z-index, visible on every scene) sat directly on top of this one and
     hid it completely. This is only ever shown on S1 anyway (see markup —
     it lives inside .panel--question), so it only ever needs to clear the
     theme switch's own height + a gap, never anything else. */
  top: calc(clamp(16px, 3vh, 28px) + 52px);
  right: clamp(16px, 3vw, 28px);
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 9px;
  pointer-events: auto;
  padding: 8px 14px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.22);
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  /* Milky glass, sunken into the surface rather than floating on top of
     it: an inset shadow along the top/left reads as a recessed groove,
     a thin inset highlight along the bottom/right keeps it from looking
     like a flat hole punched in the glass. */
  box-shadow:
    inset 0 3px 4px rgba(0, 0, 0, 0.16),
    inset 0 -1px 1px rgba(255, 255, 255, 0.5),
    inset 0 0 0 1px rgba(255, 255, 255, 0.25);
}

.s1-demo-switch__label {
  position: relative;
  top: 1px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.65rem;
  line-height: 1;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-ink-soft);
}

.s1-demo-switch__group {
  display: flex;
  align-items: center;
  border-radius: 999px;
  overflow: hidden;
}

.s1-demo-switch__btn {
  border: none;
  background: transparent;
  padding: 6px 13px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.75rem;
  line-height: 1;
  color: var(--color-ink-soft);
  cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease;
}

.s1-demo-switch__btn[aria-pressed="true"] {
  background: var(--color-accent-strong);
  color: #ffffff;
}

/* ==========================================================================
   Dev Light/Dark theme switch — spans every scene (js/theme.js flips
   [data-theme] on <body>), so unlike .s1-demo-switch above (scoped to the
   S1 panel) this is `position: fixed` and lives outside .journey, staying
   on-screen through scroll. Same milky-glass visual language. Moved to
   top-right (2026-08-11) — top-left now covers the S2 sidebar's
   "SPRIEVODCA VÝBEROM" heading. Trade-off: during the S0->S1 scroll
   segment this now sits over the same corner as .s1-demo-switch (S1's own
   dev A/B switch, also top-right) — both are dev-only overlays, acceptable
   for now. Safe to delete once a theme is chosen for good.
   ========================================================================== */
.theme-demo-switch {
  position: fixed;
  top: clamp(16px, 3vh, 28px);
  right: clamp(16px, 3vw, 28px);
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 9px;
  pointer-events: auto;
  padding: 8px 14px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.42);
  /*background: rgba(255, 255, 255, 0.22);*/
  backdrop-filter: blur(14px) saturate(160%);
  -webkit-backdrop-filter: blur(14px) saturate(160%);
  box-shadow:
    inset 0 3px 4px rgba(0, 0, 0, 0.16),
    inset 0 -1px 1px rgba(255, 255, 255, 0.5),
    inset 0 0 0 1px rgba(255, 255, 255, 0.25);
}

.theme-demo-switch__label {
  position: relative;
  top: 1px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.65rem;
  line-height: 1;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-ink-soft);
}

.theme-demo-switch__group {
  display: flex;
  align-items: center;
  border-radius: 999px;
  overflow: hidden;
}

.theme-demo-switch__btn {
  border: none;
  background: transparent;
  padding: 6px 13px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.75rem;
  line-height: 1;
  text-transform: uppercase;
  color: var(--color-ink-soft);
  cursor: pointer;
  transition: background-color 0.15s ease, color 0.15s ease;
}

.theme-demo-switch__btn[aria-pressed="true"] {
  background: var(--color-accent-strong);
  color: #ffffff;
}

/* S1 variants — both wrappers always exist; [data-active-variant] (set by
   js/s1-variant.js) just picks which one is display:block. Never remounted,
   so selectedSeason (owned by wizard.js) survives switching. Lives inside
   .hero-glass__screen--s1 (moved there in KROK 2), so it renders directly
   on the antracite glass — no card/scrim of its own. */
.s1-variants {
  margin-top: 28px;
}

.s1-variant {
  display: none;
}

[data-active-variant="list"] .s1-variant--list,
[data-active-variant="tiles"] .s1-variant--tiles {
  display: block;
}

.s1-variant__placeholder {
  font-size: 0.9rem;
  color: var(--hero-glass-text-soft);
  font-style: italic;
}

/* ==========================================================================
   Variant A — LIST. Four large glass rows, one per season. Built on the
   shared --selection-glass---season-* tokens above (KROK 3/4) so Variant
   B (tiles, next step) can reuse the same glass + thematic-selection
   language instead of duplicating these values.
   ==========================================================================
*/
/* Element+class selector, not just `.s1-list` — the UA stylesheet's own
   `ul { padding-inline-start: 40px }` targets the element directly, and
   needed the matching specificity to actually lose every time (a plain
   class-only `.s1-list { padding: 0 }` was not enough in testing). Applies
   at every breakpoint on purpose, so rows run edge-to-edge in the glass
   panel on desktop/tablet too, not just mobile. */
ul.s1-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
}

/* Per-row entrance stagger, driven by the EXISTING --s1-reveal (from
   js/parallax.js, untouched here) with a small per-row offset — not a
   separate transition/animation, so it can't drift out of sync with the
   scroll-scrubbed reveal or need its own JS trigger. Each row's --row-offset
   shifts where in the 0..1 reveal range IT starts climbing from 0 to 1. */
.s1-list__row:nth-child(1) {
  --row-offset: 0;
}
.s1-list__row:nth-child(2) {
  --row-offset: 0.07;
}
.s1-list__row:nth-child(3) {
  --row-offset: 0.14;
}
.s1-list__row:nth-child(4) {
  --row-offset: 0.21;
}

.s1-list__row {
  list-style: none;
  margin-bottom: 12px;
  --row-reveal: clamp(
    0,
    calc((var(--s1-reveal, 0) - var(--row-offset, 0)) / (1 - var(--row-offset, 0))),
    1
  );
  opacity: var(--row-reveal);
  transform: translateX(calc((1 - var(--row-reveal)) * -10px));
}

.s1-list__row:last-child {
  margin-bottom: 0;
}

.s1-list__control {
  position: relative;
  display: flex;
  align-items: center;
  gap: 18px;
  width: 100%;
  min-height: 78px;
  padding: 16px 22px;
  border: 1px solid var(--selection-glass-border);
  border-radius: var(--radius);
  background: var(--selection-glass-bg);
  backdrop-filter: blur(var(--selection-glass-blur)) saturate(140%);
  -webkit-backdrop-filter: blur(var(--selection-glass-blur)) saturate(140%);
  box-shadow: var(--selection-glass-inner-depth);
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: transform 0.15s ease, background-color 0.15s ease,
    border-color 0.15s ease, box-shadow 0.2s ease;
}

/* Hover/focus only ever lift + highlight the row itself — never touch the
   S1 background/environment (that's CLICK-only, wired in js/s1-list.js). */
.s1-list__control:hover,
.s1-list__control:focus-visible {
  transform: translateY(-2px);
  background: var(--selection-glass-bg-hover);
  border-color: var(--selection-glass-border-hover);
}

/* Thematic hover glow — same hue each row will turn if selected, so
   hovering previews the choice. Comes before .is-selected below so a
   selected+hovered row keeps its (stronger) selected treatment. */
.s1-list__control[data-season-id="summer"]:hover,
.s1-list__control[data-season-id="summer"]:focus-visible {
  box-shadow: var(--selection-glass-inner-depth), var(--season-summer-hover-glow);
}
.s1-list__control[data-season-id="winter"]:hover,
.s1-list__control[data-season-id="winter"]:focus-visible {
  box-shadow: var(--selection-glass-inner-depth), var(--season-winter-hover-glow);
}
.s1-list__control[data-season-id="allseason"]:hover,
.s1-list__control[data-season-id="allseason"]:focus-visible {
  box-shadow: var(--selection-glass-inner-depth), var(--season-allseason-hover-glow);
}
.s1-list__control[data-season-id="unsure"]:hover,
.s1-list__control[data-season-id="unsure"]:focus-visible {
  box-shadow: var(--selection-glass-inner-depth), var(--season-unsure-hover-glow);
}

.s1-list__control.is-selected {
  background: var(--selection-glass-bg-selected);
}

/* Selected border + inner shadow are now thematic (the row's own season
   color), not a universal brand-green ring. */
.s1-list__control[data-season-id="summer"].is-selected {
  border-color: var(--season-summer-accent);
  box-shadow: var(--selection-glass-inner-depth), var(--season-summer-inset);
}
.s1-list__control[data-season-id="winter"].is-selected {
  border-color: var(--season-winter-accent);
  box-shadow: var(--selection-glass-inner-depth), var(--season-winter-inset);
}
.s1-list__control[data-season-id="allseason"].is-selected {
  border-color: var(--season-allseason-accent);
  box-shadow: var(--selection-glass-inner-depth), var(--season-allseason-inset);
}
.s1-list__control[data-season-id="unsure"].is-selected {
  border-color: var(--season-unsure-accent);
  box-shadow: var(--selection-glass-inner-depth), var(--season-unsure-inset);
}

.s1-list__icon {
  flex: none;
  width: 30px;
  height: 30px;
  color: var(--hero-glass-text-soft);
  transition: color 0.2s ease;
}
.s1-list__icon svg {
  width: 100%;
  height: 100%;
}

.s1-list__control[data-season-id="summer"].is-selected .s1-list__icon {
  color: var(--season-summer-accent);
}
.s1-list__control[data-season-id="winter"].is-selected .s1-list__icon {
  color: var(--season-winter-accent);
}
.s1-list__control[data-season-id="allseason"].is-selected .s1-list__icon {
  color: var(--season-allseason-accent);
}
.s1-list__control[data-season-id="unsure"].is-selected .s1-list__icon {
  color: var(--season-unsure-accent);
}

.s1-list__body {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.s1-list__title {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.05rem;
  color: var(--hero-glass-text);
}

.s1-list__desc {
  font-size: 0.85rem;
  line-height: 1.4;
  color: var(--hero-glass-text-soft);
}

/* Recommendation is a computed UI hint (current month), independent of
   selection — shown on whichever row it applies to regardless of what (if
   anything) the user has actually picked. */
.s1-list__chip {
  display: none;
  margin-left: auto;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.65rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-accent);
  background: color-mix(in srgb, var(--color-accent) 16%, transparent);
  border: 1px solid color-mix(in srgb, var(--color-accent) 40%, transparent);
  border-radius: 999px;
  padding: 3px 9px;
  white-space: nowrap;
}

.s1-list__row.is-recommended .s1-list__chip {
  display: inline-block;
}

.s1-list__arrow {
  flex: none;
  /* 1.8rem is the floor, not a breakpoint-tunable value — hover/selected
     only ever change color/transform below, never font-size, and the
     mobile override (further down) intentionally no longer shrinks this
     either, so it can't go back to reading as "lost" on a small screen. */
  font-size: 1.8rem;
  color: var(--hero-glass-text);
  transition: color 0.2s ease, transform 0.2s ease;
}

.s1-list__control[data-season-id="summer"].is-selected .s1-list__arrow {
  color: var(--season-summer-accent);
}
.s1-list__control[data-season-id="winter"].is-selected .s1-list__arrow {
  color: var(--season-winter-accent);
}
.s1-list__control[data-season-id="allseason"].is-selected .s1-list__arrow {
  color: var(--season-allseason-accent);
}
.s1-list__control[data-season-id="unsure"].is-selected .s1-list__arrow {
  color: var(--season-unsure-accent);
}

.s1-list__control:hover .s1-list__arrow,
.s1-list__control:focus-visible .s1-list__arrow,
.s1-list__control.is-selected .s1-list__arrow {
  transform: translateX(2px);
}

/* ==========================================================================
   Variant B — TILES. 2x2 grid of image tiles, one per season (KROK 4/4).
   Same selection-glass / season accent tokens as Variant A (defined near
   the top of :root) drive the overlay glass and the thematic selected/hover
   treatment here too — only the layout (photo tile vs. glass row) differs,
   so switching A<->B never looks like two unrelated design systems.
   ========================================================================== */
.s1-tiles {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
}

.s1-tile {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 1 / 1;
  border: 1px solid var(--tile-border);
  border-radius: var(--radius);
  overflow: hidden;
  padding: 0;
  margin: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: transform 0.15s ease, border-color 0.2s ease, border-width 0.15s ease,
    box-shadow 0.2s ease;
}

/* Hover reads as more than just the lift — a visibly thicker (2px, up from
   the resting 1px) border makes the "this tile is being considered" state
   unmistakable even before the overlay glow kicks in. box-sizing:border-box
   keeps the tile's outer footprint fixed, so the extra 1px only nudges the
   inset:0 children by a sub-pixel amount, not a visible layout shift. */
.s1-tile:hover,
.s1-tile:focus-visible {
  transform: translateY(-2px);
  border-width: 2px;
  border-color: var(--tile-border-hover);
}

/* The photo itself — object-fit: cover fills the whole tile, not a
   card-above-image composition. Desaturated/dimmed by default (the
   "inactive but still quality" look); selecting or hovering brings color
   back in, exactly like Variant A's icon/border tinting on select. */
.s1-tile__media {
  position: absolute;
  inset: 0;
  z-index: 0;
}
.s1-tile__media picture,
.s1-tile__media img {
  display: block;
  width: 100%;
  height: 100%;
}
/* All 4 season photos are 16:9 — wider than every tile aspect ratio we use
   (1:1 desktop, 3:4 tablet, 4:3 mobile), so object-fit:cover alone already
   shows the FULL photo height with zero vertical slack: object-position's
   vertical component would be a no-op here, and the source's road (bottom
   half of every photo) ends up sitting almost exactly behind the bottom
   text overlay, reading as "just sky/mountains" above it. Fixed with an
   explicit zoom + pan transform instead: scale() creates deliberate
   overflow on all sides, then translate() shifts the image up (and
   sideways per season) to pull the road out from under the overlay. Both
   values are per-season custom properties (below) so each photo's own
   road/landmark position drives its own crop, not one shared guess.
   --s1-tile-hover-zoom composes with the season zoom in one transform, so
   the existing hover "image comes alive" bump doesn't need its own
   transform declaration (which would otherwise just overwrite this one). */
.s1-tile__media img {
  object-fit: cover;
  filter: grayscale(0.85) brightness(0.72) saturate(0.6);
  --s1-tile-hover-zoom: 1;
  transform: scale(calc(var(--s1-tile-zoom, 1.2) * var(--s1-tile-hover-zoom, 1)))
    translate(var(--s1-tile-pan-x, 0%), var(--s1-tile-pan-y, -9%));
  transition: filter 0.3s ease, transform 0.3s ease;
}

/* Per-season crop. Each --s1-tile-pan-y stays comfortably inside the
   vertical overflow its own --s1-tile-zoom creates (overflow per side =
   (zoom-1)/2, e.g. zoom 1.3 -> 15% budget), so lifting the road never pulls
   the photo's bottom edge above the tile's bottom edge (which would leave
   a gap). Horizontal pans are small, deliberate nudges: summer/winter just
   recenter slightly, allseason stays dead-center to keep the summer/winter
   split seam visible, unsure shifts right to keep the question-sign post
   in frame alongside the road. */
.s1-tile[data-season-id="summer"] .s1-tile__media img {
  --s1-tile-zoom: 1.3;
  --s1-tile-pan-x: 2%;
  --s1-tile-pan-y: -12%;
}
.s1-tile[data-season-id="winter"] .s1-tile__media img {
  --s1-tile-zoom: 1.3;
  --s1-tile-pan-x: 1%;
  --s1-tile-pan-y: -12%;
}
.s1-tile[data-season-id="allseason"] .s1-tile__media img {
  --s1-tile-zoom: 1.18;
  --s1-tile-pan-x: 0%;
  --s1-tile-pan-y: -8%;
}
.s1-tile[data-season-id="unsure"] .s1-tile__media img {
  --s1-tile-zoom: 1.2;
  --s1-tile-pan-x: -9%;
  --s1-tile-pan-y: -7%;
}

.s1-tile:hover .s1-tile__media img,
.s1-tile:focus-visible .s1-tile__media img {
  --s1-tile-hover-zoom: 1.02;
  filter: grayscale(0.4) brightness(0.85) saturate(0.9);
}

.s1-tile.is-selected .s1-tile__media img {
  filter: none;
}
.s1-tile.is-selected:hover .s1-tile__media img,
.s1-tile.is-selected:focus-visible .s1-tile__media img {
  --s1-tile-hover-zoom: 1.02;
}

/* Pure photo-legibility scrim, separate from the glass overlay below it —
   not a second glass/blur system, just enough of a gradient that the glass
   panel's own translucency doesn't have to fight the photo for contrast. */
.s1-tile__scrim {
  position: absolute;
  inset: auto 0 0 0;
  z-index: 1;
  height: 55%;
  background: linear-gradient(0deg, rgba(10, 11, 9, 0.55) 0%, rgba(10, 11, 9, 0) 100%);
  pointer-events: none;
}

.s1-tile__overlay {
  position: absolute;
  inset: auto 0 0 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
  min-height: 36%;
  padding: 12px 14px;
  border-top: 1px solid var(--selection-glass-border);
  background: var(--tile-overlay-bg);
  backdrop-filter: blur(var(--selection-glass-blur)) saturate(140%);
  -webkit-backdrop-filter: blur(var(--selection-glass-blur)) saturate(140%);
  box-shadow: var(--selection-glass-inner-depth);
  transition: background-color 0.15s ease, border-color 0.2s ease, box-shadow 0.2s ease;
}

.s1-tile:hover .s1-tile__overlay,
.s1-tile:focus-visible .s1-tile__overlay {
  background: var(--tile-overlay-bg-hover);
  border-top-color: var(--selection-glass-border-hover);
}

/* Hover glow + border tint live on .s1-tile itself, not .s1-tile__overlay:
   the overlay sits flush against the tile's left/right/bottom edges, so an
   outer box-shadow placed on it gets clipped by the tile's own
   overflow:hidden (required for the photo zoom/crop). Both properties on
   the tile's own box are unaffected by the tile's own overflow:hidden —
   that property only clips descendant content, never the element's own
   border/shadow. Same thematic accent as .is-selected below, so hovering
   previews the exact color the tile will lock to. */
.s1-tile[data-season-id="summer"]:hover,
.s1-tile[data-season-id="summer"]:focus-visible {
  border-color: var(--season-summer-accent);
  box-shadow: var(--season-summer-hover-glow);
}
.s1-tile[data-season-id="winter"]:hover,
.s1-tile[data-season-id="winter"]:focus-visible {
  border-color: var(--season-winter-accent);
  box-shadow: var(--season-winter-hover-glow);
}
.s1-tile[data-season-id="allseason"]:hover,
.s1-tile[data-season-id="allseason"]:focus-visible {
  border-color: var(--season-allseason-accent);
  box-shadow: var(--season-allseason-hover-glow);
}
.s1-tile[data-season-id="unsure"]:hover,
.s1-tile[data-season-id="unsure"]:focus-visible {
  border-color: var(--season-unsure-accent);
  box-shadow: var(--season-unsure-hover-glow);
}

.s1-tile.is-selected .s1-tile__overlay {
  background: var(--tile-overlay-bg-selected);
}

/* Selected keeps the same thicker 2px border as hover (not the resting
   1px) so a picked tile still reads as picked after the pointer moves
   away — shared across themes, same as the border-width bump on hover. */
.s1-tile.is-selected {
  border-width: 2px;
}

/* Selected border + inner shadow — the exact same thematic tokens Variant A
   uses (border-color + inset "colored light inside the glass"), so a
   season reads identically whether it was picked as a list row or a tile. */
.s1-tile[data-season-id="summer"].is-selected {
  border-color: var(--season-summer-accent);
}
.s1-tile[data-season-id="summer"].is-selected .s1-tile__overlay {
  border-top-color: var(--season-summer-accent);
  box-shadow: var(--selection-glass-inner-depth), var(--season-summer-inset);
}
.s1-tile[data-season-id="winter"].is-selected {
  border-color: var(--season-winter-accent);
}
.s1-tile[data-season-id="winter"].is-selected .s1-tile__overlay {
  border-top-color: var(--season-winter-accent);
  box-shadow: var(--selection-glass-inner-depth), var(--season-winter-inset);
}
.s1-tile[data-season-id="allseason"].is-selected {
  border-color: var(--season-allseason-accent);
}
.s1-tile[data-season-id="allseason"].is-selected .s1-tile__overlay {
  border-top-color: var(--season-allseason-accent);
  box-shadow: var(--selection-glass-inner-depth), var(--season-allseason-inset);
}
.s1-tile[data-season-id="unsure"].is-selected {
  border-color: var(--season-unsure-accent);
}
.s1-tile[data-season-id="unsure"].is-selected .s1-tile__overlay {
  border-top-color: var(--season-unsure-accent);
  box-shadow: var(--selection-glass-inner-depth), var(--season-unsure-inset);
}

.s1-tile__header {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
}

.s1-tile__icon {
  flex: none;
  width: 24px;
  height: 24px;
  color: var(--hero-glass-text-soft);
  transition: color 0.2s ease;
}
.s1-tile__icon svg {
  width: 100%;
  height: 100%;
}

.s1-tile[data-season-id="summer"].is-selected .s1-tile__icon {
  color: var(--season-summer-accent);
}
.s1-tile[data-season-id="winter"].is-selected .s1-tile__icon {
  color: var(--season-winter-accent);
}
.s1-tile[data-season-id="allseason"].is-selected .s1-tile__icon {
  color: var(--season-allseason-accent);
}
.s1-tile[data-season-id="unsure"].is-selected .s1-tile__icon {
  color: var(--season-unsure-accent);
}

.s1-tile__title {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1rem;
  line-height: 1;
  color: var(--hero-glass-text);
}

.s1-tile__desc {
  font-size: 0.78rem;
  line-height: 1.35;
  color: var(--hero-glass-text-soft);
}

/* Recommendation badge — same logic/token as Variant A's chip, but a
   floating badge over the IMAGE (top-right corner), not inline with the
   title: the title/desc live in the bottom overlay band, so a badge down
   there would compete with them for the same cramped space. Sits above
   .s1-tile__media/.s1-tile__scrim (z-index) and never reaches the overlay
   band, so it can't overlap the title at any breakpoint. */
.s1-tile__badge {
  display: none;
  position: absolute;
  top: 9px;
  right: 9px;
  z-index: 3;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.62rem;
  line-height: 1;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-accent);
  background: color-mix(in srgb, #0a0b09 55%, transparent);
  border: 1px solid color-mix(in srgb, var(--color-accent) 55%, transparent);
  border-radius: 999px;
  padding: 4px 9px;
  white-space: nowrap;
  backdrop-filter: blur(6px) saturate(140%);
  -webkit-backdrop-filter: blur(6px) saturate(140%);
}

.s1-tile.is-recommended .s1-tile__badge {
  display: inline-block;
}

/* ==========================================================================
   Hero glass (S0) — full-height frosted-glass panel, left-aligned, straight
   right edge dissolving into the photo via mask-image.

   Previously a sine-wave edge cut with SVG clip-path (two layers: a blurred
   outer copy + crisp inner copy — see the commented-out block below). That
   approach always left a visible seam ("sek") no matter how far the
   background-color gradient faded toward transparent, because clip-path
   cuts backdrop-filter's blur to a hard vector edge — the blur itself
   cannot fade, it just stops dead at the curve. mask-image instead applies
   a real alpha gradient to the WHOLE element (background + backdrop-filter
   blur + box-shadow together), so the blurred photo underneath actually
   dissolves toward full sharpness instead of cutting off. That also means
   a single glass layer is enough — no separate blurred "soft edge" copy
   needed to fake the dissolve.
   ========================================================================== */
.hero-glass__defs {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

.hero-glass {
  position: absolute;
  inset: 0;
  width: clamp(410px, 75vw, 1300px);
  pointer-events: auto;
}

/* Old two-layer wave edge (blurred outer copy + crisp inner copy via SVG
   clip-path). Kept for reference, not deleted — see the comment above for
   why it was replaced by the single mask-image-faded .hero-glass__surface
   below.
.hero-glass__soft-edge-wrap {
  position: absolute;
  inset: 0;
  pointer-events: none;
  filter: blur(24px);
  -webkit-filter: blur(24px);
}

.hero-glass__soft-edge {
  position: absolute;
  inset: 0;
  clip-path: url(#s0GlassWave);
  -webkit-clip-path: url(#s0GlassWave);
  background: linear-gradient(
    to right,
    var(--hero-glass-bg-opaque) 0%,
    var(--hero-glass-bg-opaque) 90%,
    var(--hero-glass-bg-edge) 100%
  );
}
*/

.hero-glass__surface {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;

  background: var(--hero-glass-bg-opaque);

  mask-image: linear-gradient(
          to right,
          #000 0%,
          #000 55%,
          rgba(0, 0, 0, 0.98) 60%,
          rgba(0, 0, 0, 0.90) 66%,
          rgba(0, 0, 0, 0.72) 73%,
          rgba(0, 0, 0, 0.48) 81%,
          rgba(0, 0, 0, 0.25) 89%,
          rgba(0, 0, 0, 0.08) 96%,
          transparent 100%
  );

  -webkit-mask-image: linear-gradient(
          to right,
          #000 0%,
          #000 55%,
          rgba(0, 0, 0, 0.98) 60%,
          rgba(0, 0, 0, 0.90) 66%,
          rgba(0, 0, 0, 0.72) 73%,
          rgba(0, 0, 0, 0.48) 81%,
          rgba(0, 0, 0, 0.25) 89%,
          rgba(0, 0, 0, 0.08) 96%,
          transparent 100%
  );

  backdrop-filter: blur(16px) saturate(110%);
  -webkit-backdrop-filter: blur(16px) saturate(110%);

  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.05);
  /*position: absolute;*/
  /*inset: 0;*/

  /*display: flex;*/
  /*align-items: center;*/

  /*!* Flat single color — the edge fade is entirely mask-image's job now,*/
  /*   not a background-gradient stop list (see block comment above). *!*/
  /*background: var(--hero-glass-bg-opaque);*/

  /*!* Straight edge fade: fully opaque 0-75% of the panel's own width, then*/
  /*   dissolves to fully transparent by 100%. .hero-glass__content has*/
  /*   enough padding-right (see below) to stay inside the opaque 0-75%*/
  /*   zone, so real text/buttons never get caught fading out. *!*/
  /*mask-image: linear-gradient(to right, #000 0%, #000 75%, transparent 100%);*/
  /*-webkit-mask-image: linear-gradient(*/
  /*  to right,*/
  /*  #000 0%,*/
  /*  #000 75%,*/
  /*  transparent 100%*/
  /*);*/

  /*backdrop-filter: blur(16px) saturate(110%);*/
  /*-webkit-backdrop-filter: blur(16px) saturate(110%);*/

  /*box-shadow:*/
  /*        inset 0 1px 0 rgba(255, 255, 255, 0.05);*/
}

/* Edge line + inward glow disabled (2026-08) — glass keeps its wavy
   silhouette (.hero-glass__soft-edge/.hero-glass__surface clip-path), just
   the highlighted rim on top of it (crisp 1px stroke + blurred glow band)
   is gone. What's left is a plain fade to fully transparent driven by
   --hero-glass-bg-edge alone (already ~0 opacity at the curve). Original
   rules kept below, commented out, not deleted, in case this comes back. */
.hero-glass__edge,
.hero-glass__edge-glow {
  display: none;
}

/*
Edge line — thin white stroke tracing the exact wave curve (the glass
surface's own clip-path), so it bends with the amplitude instead of
fragmenting like a plain CSS `border` would on a clip-path'd box.

.hero-glass__edge {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
}

.hero-glass__edge-path {
  fill: none;
  stroke: var(--hero-glass-edge-glow);
  stroke-width: 1;
  opacity: 0.1;
  display: none;
}

.hero-glass__edge-path--horizontal {
  display: block;
}

Inward glow — white-to-transparent fade running from the edge line back
toward the text (~10-15px). Built as three nested layers so the blur and
the clip never sit on the same element (see the .hero-glass__soft-edge
comment above for why that combination is unreliable):
  1. .hero-glass__edge-glow-svg draws a crisp white line on the curve.
  2. .hero-glass__edge-glow-blur (parent, filter only) blurs it in every
     direction, turning the line into a soft band straddling the curve.
  3. .hero-glass__edge-glow (outer parent, clip-path only, same inner
     curve as .hero-glass__surface) then cuts away the outward half of
     that band, leaving only the half fading inward into the glass.

.hero-glass__edge-glow {
  position: absolute;
  inset: 0;
  clip-path: url(#s0GlassWaveInner);
  -webkit-clip-path: url(#s0GlassWaveInner);
  pointer-events: none;
}

.hero-glass__edge-glow-blur {
  position: absolute;
  inset: 0;
  display: none;
}

.hero-glass__edge-glow-blur--horizontal {
  display: block;
  filter: blur(11px);
  -webkit-filter: blur(11px);
}

.hero-glass__edge-glow-svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}

.hero-glass__edge-glow-blur--horizontal .hero-glass__edge-glow-path {
  stroke-width: 5;
}

.hero-glass__edge-glow-path {
  fill: none;
  stroke: var(--hero-glass-edge-glow);
  stroke-width: 2;
}
*/

.hero-glass__content {
  max-width: 83%;
  padding: clamp(48px, 4vw, 90px);
  padding-right: clamp(64px, 14vw, 220px);
  /* S0 and S1 screens stack in the same grid cell (the same technique
     .journey uses for its sticky-background/scrolling-foreground overlay)
     instead of position:absolute — an absolutely positioned screen has
     nothing to size .hero-glass__content against, since it would no longer
     contribute to its parent's height. Grid keeps .hero-glass__content
     sized to the taller of the two screens for free. */
  display: grid;
}

.hero-glass__screen {
  grid-column: 1;
  grid-row: 1;
}

/* S0 fades/lifts out as the user scrolls into S1, and reverses cleanly on
   the way back up since --s0-fade is a pure function of scroll position,
   not a one-shot animation. Fallback (1) matches the resting/no-JS state:
   fully visible. `visibility` (not just pointer-events) so the S0 CTA drops
   out of the tab order once it's faded away instead of staying keyboard-
   reachable-but-invisible. */
.hero-glass__screen--s0 {
  opacity: var(--s0-fade, 1);
  transform: translateY(calc((1 - var(--s0-fade, 1)) * -10px));
  visibility: var(--s0-visibility, visible);
}

/* S1 is the mirror: hidden until --s1-reveal climbs off 0 late in the
   scroll. Holds the real season-picker UI (moved in from .panel--question
   in KROK 2), so — unlike a purely decorative layer — it needs to become
   properly reachable (not just visually faded in) once revealed: same
   `visibility` treatment as S0, flipped. */
.hero-glass__screen--s1 {
  opacity: var(--s1-reveal, 0);
  transform: translateY(calc((1 - var(--s1-reveal, 0)) * 10px));
  visibility: var(--s1-visibility, hidden);
}

.hero-glass .eyebrow {
  color: var(--color-accent);
}

.hero-glass .panel__title {
  color: var(--hero-glass-text);
  font-weight: 700;
  letter-spacing: -0.015em;
}

.hero-glass__highlight {
  color: var(--color-accent);
}

.hero-glass__divider {
  width: clamp(64px, 6vw, 100px);
  height: 2px;
  background: var(--color-accent);
  margin: 32px 0 40px;
}

.hero-glass .panel__body {
  color: var(--hero-glass-text-soft);
  max-width: 38ch;
  margin-top: 0;
}

/* .panel__status is rendered by wizard.js inside .s1-variant--tiles (i.e.
   inside .hero-glass now) — needs the dark-bg-appropriate soft color like
   everything else in here, same as .panel__body. */
.hero-glass .panel__status {
  color: var(--hero-glass-text-soft);
}

.hero-glass__benefits {
  display: flex;
  flex-wrap: wrap;
  row-gap: 18px;
  list-style: none;
  margin: 28px 0 0;
  padding: 0;
}

.hero-glass__benefit {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
  padding: 0 20px;
}

.hero-glass__benefit:first-child {
  padding-left: 0;
}

.hero-glass__benefit + .hero-glass__benefit {
  border-left: 1px solid var(--hero-glass-benefit-divider);
}

.hero-glass__benefit-icon {
  flex: none;
  width: 40px;
  height: 35px;
  color: var(--color-accent);
}

.hero-glass__benefit span {
  font-size: 0.85rem;
  line-height: 1.35;
  color: var(--hero-glass-text-soft);
}

.panel__scrim {
  pointer-events: auto;
  width: var(--scrim-width);
  max-width: calc(100vw - 40px);
  padding: clamp(24px, 5vw, 64px);
  margin-left: clamp(16px, 5vw, 72px);
  background: linear-gradient(
    90deg,
    var(--color-bg) 0%,
    color-mix(in srgb, var(--color-bg) 85%, transparent) 62%,
    transparent 100%
  );
}

/* Question panel: UI is secondary to the environment, so its scrim is
   compact and bottom-anchored rather than a tall side panel. */
.panel__scrim--compact {
  width: auto;
  max-width: min(620px, 92vw);
  margin: 0 0 clamp(28px, 7vh, 72px) clamp(16px, 5vw, 72px);
  padding: clamp(20px, 3.5vw, 32px);
  background: linear-gradient(
    0deg,
    var(--color-bg) 0%,
    color-mix(in srgb, var(--color-bg) 90%, transparent) 62%,
    transparent 100%
  );
}

.eyebrow {
  display: flex;
  align-items: center;
  gap: 9px;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 12px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--color-accent-strong);
  margin: 0 0 14px;
}

.eyebrow__icon {
  flex: none;
  width: 35px;
  height: 35px;
}

.panel__title {
  font-family: var(--font-display);
  font-weight: 800;
  letter-spacing: -0.01em;
  color: var(--color-ink);
}

.panel__title--hero {
  font-size: clamp(2.3rem, 2.6vw, 3.2rem);
  line-height: 1.13;
}

.panel__title--question {
  font-size: clamp(1.4rem, 2.6vw, 1.9rem);
  line-height: 1.15;
}

.panel__body {
  margin-top: 18px;
  max-width: 42ch;
  font-size: clamp(1rem, 1.2vw, 1.1rem);
  color: color-mix(in srgb, var(--color-ink) 78%, var(--color-ink-soft));
}

/* ==========================================================================
   Buttons
   ========================================================================== */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 30px;
  padding: 14px 28px;
  border-radius: var(--radius);
  border: none;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1rem;
  cursor: pointer;
  transition: transform 0.15s ease, background-color 0.15s ease;
}
.btn:active {
  transform: translateY(1px) scale(0.98);
}
.btn--primary {
  background: var(--color-accent-strong);
  color: #ffffff;
}
.btn--primary:hover {
  background: color-mix(in srgb, var(--color-accent-strong) 88%, black);
}
.btn__arrow {
  transition: transform 0.15s ease;
}
.btn--primary:hover .btn__arrow {
  transform: translateX(3px);
}

/* S1 "Pokračovať" — same .btn/.btn--primary visual language as S0's
   "Začať výber" (KROK 1's own accent, not a --hero-glass-* token, so it
   reads identically in both themes already). Faded out (not display:none)
   until a season is picked (js/wizard.js adds .is-visible): .hero-glass__
   surface vertically centers .hero-glass__content by height, so a
   display:none -> flex switch would change that height and visibly shift
   the whole centered stack up when the button appeared. Reserving its
   layout space from the start avoids that jump entirely — same technique
   already used for the S0<->S1 crossfade itself (opacity/visibility, never
   display). visibility (not just opacity) keeps it out of the tab order
   and off screen readers while hidden. */
.s1-continue {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: opacity 0.2s ease, transform 0.15s ease, background-color 0.15s ease;
}
.s1-continue.is-visible {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}

/* ==========================================================================
   Question options — rendered by js/wizard.js from data/steps.js.
   Compact row, environment stays the dominant visual.
   ========================================================================== */
.panel__status {
  margin-top: 16px;
  min-height: 1.4em;
  font-size: 0.9rem;
  color: var(--color-ink-soft);
}

.options {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 22px;
}

.option {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 12px 16px;
  background: color-mix(in srgb, var(--color-surface) 92%, transparent);
  border: 2px solid var(--color-border);
  border-radius: var(--radius);
  cursor: pointer;
  text-align: left;
  transition: border-color 0.15s ease, background-color 0.15s ease, transform 0.15s ease;
}
.option:hover {
  border-color: var(--color-accent);
}
.option:active {
  transform: translateY(1px) scale(0.98);
}
.option__icon {
  flex: none;
  width: 20px;
  height: 20px;
  color: var(--color-accent-strong);
}
.option__icon svg {
  width: 100%;
  height: 100%;
}
.option__label {
  font-weight: 600;
  font-size: 0.95rem;
}
.option.is-selected {
  background: var(--color-accent-strong);
  border-color: var(--color-accent-strong);
  color: #ffffff;
}
.option.is-selected .option__icon {
  color: #ffffff;
}

/* ==========================================================================
   Motion — subtle premium drift only. Gated behind reduced-motion so the
   default (no-JS-scroll-math) state is always a clean static frame.
   ========================================================================== */
@media (prefers-reduced-motion: no-preference) {
  .env-stack {
    /* Additive approximation of (1+travel-drift)*(1+transition-bump) — both
       terms are small (<=3.5%), so summing instead of multiplying is
       visually indistinguishable and keeps this a single calc(). The bump
       is 0 outside the S0->S1 handoff (see js/parallax.js), so this reduces
       to the original travel-only drift the rest of the time. */
    transform: scale(
      calc(1 + var(--travel, 0) * 0.035 + var(--bg-scale-bump, 0) * 0.028)
    );
    filter: blur(calc(var(--bg-blur, 0) * 6px));
    transition: transform 0.05s linear, filter 0.05s linear;
  }

  .hero-glass__screen {
    transition: opacity 0.05s linear, transform 0.05s linear;
  }

  /* S0 entrance — plays once on load (plain @keyframes, no scroll/JS
     trigger involved), so scrolling away and back to S0 never replays it.
     Background fades/zooms in first; the glass panel starts sliding in 1s
     later, still mid-zoom; its content staggers in during the slide. Total
     sequence lands ~3s, comfortably under the 5s ceiling. */
  @keyframes hero-intro-bg {
    from {
      transform: scale(1.05);
      opacity: 0;
    }
    to {
      transform: scale(1);
      opacity: 1;
    }
  }

  /* Transform only, deliberately no opacity here: animating opacity on
     .hero-glass (the wrapper) multiplies with the alpha already baked into
     --hero-glass-bg-opaque on its child, so any animation hiccup reads as
     "the glass got more transparent" instead of just "it's still sliding
     in". Keeping this to a pure transform means the configured background
     opacity is correct the instant the panel is in view, no compounding. */
  @keyframes hero-intro-glass {
    from {
      transform: translateX(-105%);
      /*opacity: 0.7;*/
    }
    to {
      transform: translateX(0);
      /*opacity: 1;*/
    }
  }

  /* Mobile fades only — no transform. The vh-based band height is prone to
     shifting slightly right after load as mobile browsers settle their
     address-bar chrome; pairing that with a translateY entrance risked the
     panel visibly resettling a second time after the animation had already
     finished. A plain fade can't produce that kind of positional jump. */
  @keyframes hero-intro-glass-vertical {
    from {
      opacity: 0;
    }
    to {
      opacity: 1;
    }
  }

  @keyframes hero-intro-content {
    from {
      opacity: 0;
      transform: translateY(12px);
    }
    to {
      opacity: 1;
      transform: translateY(0);
    }
  }

  .env-layer[data-env="default"] picture,
  .env-layer[data-env="default"] img {
    animation: hero-intro-bg 2.8s cubic-bezier(0.16, 1, 0.3, 1) both;
  }

  .hero-glass {
    animation: hero-intro-glass 1.7s cubic-bezier(0.16, 1, 0.3, 1) 1s both;
  }

  .hero-glass__screen--s0 .eyebrow {
    animation: hero-intro-content 0.9s cubic-bezier(0.16, 1, 0.3, 1) 1.3s both;
  }
  .hero-glass__screen--s0 .panel__title--hero {
    animation: hero-intro-content 0.9s cubic-bezier(0.16, 1, 0.3, 1) 1.46s both;
  }
  .hero-glass__divider {
    animation: hero-intro-content 0.9s cubic-bezier(0.16, 1, 0.3, 1) 1.62s both;
  }
  .hero-glass__screen--s0 .panel__body {
    animation: hero-intro-content 0.9s cubic-bezier(0.16, 1, 0.3, 1) 1.78s both;
  }
  .hero-glass__benefits {
    animation: hero-intro-content 0.9s cubic-bezier(0.16, 1, 0.3, 1) 1.94s both;
  }
  /* Scoped to S0 specifically (not plain .hero-glass .btn--primary) — S1's
     "Pokračovať" button reuses the .btn--primary class too, and would
     otherwise inherit this same page-load entrance timeline. Since it's
     display:none (via [hidden]) until a season is picked, an animation
     restarts its delay from whenever it *becomes* displayed, not from page
     load — so it'd sit invisible for 2.1s+0.9s after every reveal instead
     of appearing immediately. */
  .hero-glass__screen--s0 .btn--primary {
    animation: hero-intro-content 0.9s cubic-bezier(0.16, 1, 0.3, 1) 2.1s both;
  }

  /* Variant B tiles — short staggered arrival, replayed harmlessly every
     time [data-active-variant] flips to "tiles" (display:none -> block
     restarts a CSS animation from scratch). "backwards" fill only holds the
     `from` state during the delay, then hands off to the normal cascade —
     unlike "both", it never keeps overriding transform afterward, so the
     :hover/:focus-visible translateY above still works once this settles. */
  @keyframes s1-tile-in {
    from {
      opacity: 0;
      transform: translateY(10px);
    }
    to {
      opacity: 1;
      transform: translateY(0);
    }
  }
  .s1-tile {
    animation: s1-tile-in 0.4s cubic-bezier(0.16, 1, 0.3, 1) backwards;
  }
  .s1-tile:nth-child(1) {
    animation-delay: 0s;
  }
  .s1-tile:nth-child(2) {
    animation-delay: 0.08s;
  }
  .s1-tile:nth-child(3) {
    animation-delay: 0.16s;
  }
  .s1-tile:nth-child(4) {
    animation-delay: 0.24s;
  }
}

/* Mobile: the glass is a full-width bottom band, not a left-side panel, so
   sliding it in horizontally would just reveal a gap on one side instead of
   reading as an arrival. Swap to the vertical keyframe (same timing) so it
   rises into place — consistent with the "emerges from below the photo"
   framing already used for this band elsewhere in the file. */
@media (max-width: 720px) and (prefers-reduced-motion: no-preference) {
  .hero-glass {
    animation-name: hero-intro-glass-vertical;
  }
}

/* ==========================================================================
   Reduced motion — no sticky-driven scale/zoom, faster (not zero) crossfade,
   no snow. Panels stack in plain flow under a static banner.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  :root {
    --env-transition: 150ms;
  }
  .journey {
    display: block;
  }
  .journey__stage {
    position: relative;
    height: 60vh;
  }
  .journey__glass {
    position: static;
  }
  .journey__content {
    pointer-events: auto;
  }
  .panel {
    min-height: auto;
    padding: 48px 0;
  }
  .panel--hero {
    padding: 48px 0;
  }
  .hero-glass {
    position: static;
    width: 100%;
  }
  .hero-glass__surface {
    position: static;
    clip-path: none;
    -webkit-clip-path: none;
    /* Static stacked layout has no photo bleeding through the edge to
       dissolve into — without this reset, the last 25% of the panel's
       width would still fade text/content to transparent for no reason. */
    mask-image: none;
    -webkit-mask-image: none;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
  .hero-glass__content {
    /* Sequential, not stacked: S0 then S1 read top to bottom in one glass
       panel, both fully visible. There's no scroll-scrub to crossfade
       between them here, so overlapping via grid would just hide S1's
       real season-picker UI (moved inside .hero-glass__screen--s1 in
       KROK 2) permanently — display:grid is a no-preference-only trick. */
    display: block;
    padding: 32px 20px;
    max-width: none;
  }
  .hero-glass__screen--s0,
  .hero-glass__screen--s1 {
    opacity: 1;
    transform: none;
    visibility: visible;
  }
  .hero-glass__screen--s1 {
    margin-top: 40px;
    padding-top: 32px;
    border-top: 1px solid rgba(245, 245, 243, 0.18);
  }
  .hero-glass__soft-edge-wrap,
  .hero-glass__edge-glow,
  .hero-glass__edge {
    display: none;
  }
  /* .s1-list__row's entrance reads --s1-reveal directly (KROK 3), which
     js/parallax.js never sets here — without this it would fall back to
     the property's own default (0) and stay invisible forever. */
  .s1-list__row {
    opacity: 1;
    transform: none;
  }
  .btn,
  .option,
  .s1-list__control,
  .s1-tile,
  .s1-tile__overlay,
  .s1-tile__media img {
    transition: none;
  }
  .snow-particle {
    animation: none !important;
  }
}

/* ==========================================================================
   Desktop only (min-width: 901px) — scoped so these overrides can never
   leak into the tablet/mobile crops below, which are deliberately left
   untouched here.
   ========================================================================== */
@media (min-width: 901px) {
  /* 1. Tiles crop — the shared (all-breakpoint) zoom/pan values in the
     Variant B section above were a first pass; on desktop specifically
     there's still too much sky/mountain and not enough road, especially
     on summer/winter. Pushed further here: more zoom (safe — it only ever
     tightens the crop) and a bigger upward pan, kept inside each season's
     own overflow budget so the photo's edges never lift past the tile's
     edges (which would show a gap — unlike the full-background layers
     below, a tile has no opaque panel hiding any part of it, so every
     edge has to stay genuinely covered). For transform: scale(S)
     translate(Tx%, Ty%) with the default center origin, the precise
     budget is (S-1)/(2S) — NOT the simpler (S-1)/2 an earlier pass here
     used, which overestimates it. All values below are checked against
     the precise formula with margin to spare. --s1-tile-pan-x is left
     alone (inherits the shared value) except on allseason. */
  .s1-tile[data-season-id="summer"] .s1-tile__media img {
    --s1-tile-zoom: 1.8;
    --s1-tile-pan-y: -20%;
  }
  .s1-tile[data-season-id="winter"] .s1-tile__media img {
    --s1-tile-zoom: 1.8;
    --s1-tile-pan-y: -20%;
  }
  .s1-tile[data-season-id="allseason"] .s1-tile__media img {
    --s1-tile-zoom: 2.45;
    --s1-tile-pan-y: -28%;
    --s1-tile-pan-x: -6%;
  }
  .s1-tile[data-season-id="unsure"] .s1-tile__media img {
    --s1-tile-zoom: 2.05;
    --s1-tile-pan-y: -24%;
  }

  /* 2. All-season full S1 background — .hero-glass covers roughly the left
     55vw on desktop, and the split image's seam sits near the horizontal
     middle of the source, so a plain centered crop left almost nothing but
     the winter half exposed to the right of the glass (reads as "just
     winter", not "summer+winter"). A plain object-position nudge isn't
     reliable here — on wide-enough monitors object-fit:cover already shows
     the photo's full width with zero horizontal crop slack, so there'd be
     nothing left for object-position to redistribute. Using transform:
     scale() + transform-origin instead guarantees a real, viewport-
     independent shift: scaling up always creates its own overflow budget
     to work with (never a gap — .journey__stage already clips overflow),
     regardless of how much native cover-cropping happened underneath.
     Origin pinned near the photo's left edge (7%) so scaling up stretches
     everything to its right further rightward/off-screen — pulling the
     seam (source ~50%) and a clear stretch of both the warm (summer) and
     cool (winter) sides into the strip beyond the glass, while the actual
     summer/winter edges (needed least) fall off-screen or under the glass.
     Summer/winter/unsure backgrounds are untouched. */
  /*.env-layer[data-env="allseason"] img {*/
  /*  transform: scale(1.6);*/
  /*  transform-origin: 7% 42%;*/
  /*}*/
  .env-layer[data-env="allseason"] img {
    transform: scale(1.4);
    /*transform-origin: -50% 85%;*/
    transform-origin: -0% 85%;
  }
}

/* ==========================================================================
   Tablet only (721px–900px) — a genuine min+max range, not the cascading
   max-width pattern the rest of this file uses (where a @media(max-width:
   900px) block also silently applies to mobile unless a later @media
   (max-width:720px) block overrides it). That cascade is fine for the
   spacing/typography tweaks already scoped that way below, but the crop
   values here are per-device tuned and must NOT leak into mobile, so they
   get their own explicit min+max range instead.
   ========================================================================== */
@media (min-width: 721px) and (max-width: 900px) {
  /* 1. Tiles crop — same "too much sky, not enough road" issue as desktop
     had, on tablet's shared (all-breakpoint) zoom/pan values from the
     Variant B section. Tablet tiles are 3:4 (taller than desktop's 1:1,
     set in the existing @media max-width:900px block below), but the
     overflow-budget math is a plain percentage of the img's own box
     regardless of aspect ratio, so the same style of fix applies directly.
     Precise budget for transform: scale(S) translate(Tx%, Ty%) is
     (S-1)/(2S) — corrected from the simpler (S-1)/2 an earlier pass here
     used, which overestimates it; values below are re-checked against the
     precise formula with margin to spare. Priority per season: road
     first, then the seasonal environment detail (snow/summer
     greenery/transition/fog), sky last. */
  .s1-tile[data-season-id="summer"] .s1-tile__media img {
    --s1-tile-zoom: 1.7;
    --s1-tile-pan-y: -19%;
  }
  .s1-tile[data-season-id="winter"] .s1-tile__media img {
    --s1-tile-zoom: 1.7;
    --s1-tile-pan-y: -19%;
  }
  .s1-tile[data-season-id="allseason"] .s1-tile__media img {
    --s1-tile-zoom: 2.7;
    --s1-tile-pan-y: -30%;
    --s1-tile-pan-x: -6%;
  }
  .s1-tile[data-season-id="unsure"] .s1-tile__media img {
    --s1-tile-zoom: 2.15;
    --s1-tile-pan-y: -25%;
  }

  /* 2. All-season full S1 background — same root cause as desktop (glass
     hides the source's summer-left side, leaving only winter visible
     beyond it), scoped separately per the instruction that tablet values
     must never move desktop/mobile. .hero-glass is clamp(360px, 58vw,
     520px) here — a similar viewport-width proportion to desktop's 55vw —
     so the same scale+transform-origin technique (viewport-independent,
     never creates a gap since .journey__stage clips overflow) applies,
     solved for this range's own target: pulling the seam and a clear
     stretch of both the warm and cool sides into the strip beyond the
     glass, minus the source's least-needed extreme edges. */
  /*.env-layer[data-env="allseason"] img {*/
  /*  transform: scale(1.4);*/
  /*  transform-origin: -22.5% 42%;*/
  /*}*/
  .env-layer[data-env="allseason"] img {
    transform: scale(1.2);
    transform-origin: -40% 90%;
  }
}

/* ==========================================================================
   Responsive — explicit collapse per breakpoint, not a shrunk desktop copy.
   ========================================================================== */
/* Eyebrow width fix only — narrower desktop/small-laptop widths (e.g. 1024px)
   still use the full desktop .hero-glass composition, but the desktop
   padding-right reserve (up to 104px) left too little room for the eyebrow
   icon + label on one line. Scoped to just this property so it doesn't
   touch the wave/width switch that starts at the 900px tablet breakpoint
   below. */
@media (max-width: 1024px) {
  .hero-glass__content {
    max-width: 94%;
    padding-right: clamp(40px, 11vw, 116px);
  }
}

@media (max-width: 900px) {
  .panel__scrim--compact {
    max-width: min(560px, 94vw);
  }

  /* Tablet: same left-panel composition as desktop, just narrower — no
     separate wave override needed anymore. .hero-glass__surface's
     mask-image fade is percentage-based (0-75%/100% of its OWN box), so it
     already scales correctly to this narrower width on its own.
  .hero-glass__soft-edge {
    clip-path: url(#s0GlassWaveTablet);
    -webkit-clip-path: url(#s0GlassWaveTablet);
  }
  .hero-glass__surface {
    clip-path: url(#s0GlassWaveTabletInner);
    -webkit-clip-path: url(#s0GlassWaveTabletInner);
  }
  */
  .hero-glass {
    width: clamp(360px, 70vw, 520px);
  }
  .hero-glass__content {
    max-width: 94%;
    padding-right: clamp(40px, 10vw, 116px);
  }
  .eyebrow {
    font-size: 10px;
  }
  .eyebrow__icon {
    width: 30px;
    height: 30px;
  }
  .panel__title--hero {
    font-size: 1.7rem;
    line-height: 1.25;
  }
  .hero-glass__divider {
    margin: 25px 0 30px;
  }
  .hero-glass .panel__body {
    font-size: 0.8rem;
  }
  .hero-glass__benefit {
    padding: 0 15px;
  }
  .hero-glass__benefit span {
    font-size: 0.7rem;
  }

  .s1-tiles {
    gap: 8px;
  }
  /* Tablet's narrower hero-glass width (58vw) makes a 1:1 tile quite small
     — at panel widths in the ~360-520px range that's a ~150-190px square,
     leaving the photo barely visible under the overlay and the whole grid
     centered inside .hero-glass__surface's full-height flex with big empty
     bands above/below. Taller (3:4) tiles use more of that vertical room
     directly instead, without touching the flex-centering itself. A
     tighter grid gap (was 12px) hands the saved space back to tile width. */
  .s1-tile {
    aspect-ratio: 3 / 4;
  }
  /* Overlay/icon/text all sized down from desktop — at tablet tile widths
     the desktop sizing left "Celoročné" too wide for [icon] + title to
     share one line, wrapping the title under the icon. */
  .s1-tile__overlay {
    padding: 10px 10px;
    gap: 3px;
  }
  .s1-tile__header {
    gap: 6px;
  }
  .s1-tile__icon {
    width: 19px;
    height: 19px;
  }
  .s1-tile__title {
    font-size: 0.8rem;
  }
  .s1-tile__desc {
    font-size: 0.68rem;
    line-height: 1.3;
  }
}

@media (max-width: 720px) {
  .panel__scrim {
    width: 100%;
    max-width: none;
    margin-left: 0;
    padding: 24px 20px;
    background: linear-gradient(
      0deg,
      var(--color-bg) 55%,
      color-mix(in srgb, var(--color-bg) 40%, transparent) 100%
    );
  }

  /* Mobile: the left-panel split stops making sense in portrait — the hero
     photo needs the top of the screen. Glass becomes a full-width band
     anchored to the bottom, with the same straight mask-image fade rotated
     onto its top edge, so the photo still reads as continuing underneath
     it. Old wave version kept for reference, not deleted.
  .hero-glass__soft-edge {
    clip-path: url(#s0GlassWaveMobile);
    -webkit-clip-path: url(#s0GlassWaveMobile);
    background: linear-gradient(
      to top,
      var(--hero-glass-bg-opaque) 0%,
      var(--hero-glass-bg-opaque) 90%,
      var(--hero-glass-bg-edge) 100%
    );
  }
  */
  .hero-glass {
    inset: auto 0 0 0;
    width: 100%;
    height: 75vh;
  }
  .hero-glass__surface {
    align-items: flex-start;
    /* Rotated 90° from the desktop/tablet version: solid near the
       bottom/text, fades to transparent toward the top/photo.
       `0deg` (NOT the `to top` keyword) is deliberate — with
       backdrop-filter also present on this element, Chromium fails to
       render the mask (and everything under it: background AND
       backdrop-filter blur) at all when the gradient uses the `to top`/
       `to bottom` keyword form. The numeric angle is the exact same
       gradient direction per spec, but sidesteps whatever internal code
       path the keyword form hits. Horizontal keywords (`to right`, used
       above) aren't affected — only reproduced on the vertical axis. */
    mask-image: linear-gradient(0deg, #000 0%, #000 75%, transparent 100%);
    -webkit-mask-image: linear-gradient(
      0deg,
      #000 0%,
      #000 75%,
      transparent 100%
    );
  }
  .hero-glass__content {
    max-width: none;
    padding: calc(clamp(28px, 9vh, 56px) + 100px) 16px clamp(24px, 6vh, 40px);
  }
  /* Let the headline reflow naturally against the available width instead
     of forcing the desktop 3-line composition. */
  .hero-glass__break {
    display: none;
  }
  .hero-glass__edge-path--horizontal {
    display: none;
  }
  .hero-glass__edge-path--mobile {
    display: block;
  }
  .hero-glass__edge-glow-blur--horizontal {
    display: none;
  }
  .hero-glass__edge-glow-blur--mobile {
    display: block;
    filter: blur(6px);
    -webkit-filter: blur(6px);
  }
  .eyebrow {
    font-size: 9px;
  }
  .eyebrow__icon {
    width: 30px;
    height: 30px;
  }
  .panel__title--hero {
    font-size: 1.3rem;
    line-height: 1.9rem;
  }
  .hero-glass__divider {
    margin: 16px 0 20px;
  }
  .hero-glass .panel__body {
    font-size: 0.8rem;
  }
  .hero-glass__benefits {
    justify-content: center;
  }
  .hero-glass__benefit {
    flex: 0 1 110px;
    align-items: center;
    padding: 0 14px;
  }
  .hero-glass__benefit:first-child {
    padding-left: 14px;
  }
  .hero-glass__benefit-icon {
    width: 40px;
    height: 30px;
  }
  .hero-glass__benefit span {
    font-size: 0.7rem;
    text-align: center;
  }

  /* S1 "Pokračovať" on mobile — the desktop/tablet full-width pill below
     the list/tiles has nowhere to go once the glass shrinks to a 70vh
     bottom band (not enough height left under 4 rows/tiles for a second
     block). Collapsed to an arrow-only round button instead, sat next to
     the KROK 1 eyebrow/heading rather than pushed below the options.
     A 2-column grid (heading | button) on row 1, options spanning both
     columns on row 2 — grid placement doesn't care that .s1-continue is
     later in source order than .s1-variants, and align-items: center
     vertically centers the button against the heading block's height
     (multi-line title + body) without any position:absolute guesswork. */
  .hero-glass__screen--s1 {
    display: grid;
    grid-template-columns: 1fr auto;
    align-items: center;
    column-gap: 12px;
  }
  .s1-heading {
    grid-column: 1;
    grid-row: 1;
  }
  .s1-variants {
    grid-column: 1 / -1;
    grid-row: 2;
  }
  .s1-continue {
    grid-column: 2;
    grid-row: 1;
    align-self: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    margin-top: 0;
    padding: 0;
    gap: 0;
    border-radius: 999px;
  }
  .s1-continue__label {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
  }
  /* Arrow glyph's own line-box doesn't sit centered on its font-size in
     this round, padding-less button the way it does in the padded pill
     buttons elsewhere — bumped size (matches the bigger 44px tap target)
     plus a manual nudge to actually land it in the middle of the circle. */
  .s1-continue__arrow {
    position: relative;
    bottom: 6px;
    font-size: 2rem;
  }
  .panel__scrim--compact {
    width: 100%;
    max-width: none;
    margin: 0 0 4vh;
    padding: 20px;
    background: linear-gradient(
      0deg,
      var(--color-bg) 62%,
      color-mix(in srgb, var(--color-bg) 30%, transparent) 100%
    );
  }
  .env-layer img {
    object-position: 62% center;
  }
  /* S1 full backgrounds — mobile's .hero-glass is a full-width BOTTOM band
     (70vh), not a side panel like desktop/tablet, so it hides the BOTTOM of
     the viewport instead of a side. The source photos' road sits in their
     own bottom half too, so by default it ends up almost entirely covered,
     leaving only the sky/mountain sliver above the glass exposed. Same
     scale+translate technique used for the tiles below (see that comment
     for the corrected overflow-budget formula), applied vertically here
     first. Default (S0) hero is untouched — these only target the 4 S1
     season layers, each shifted individually per its own composition. */
  .env-layer[data-env="summer"] img {
    transform: scale(1.1) translateY(-24%);
  }
  .env-layer[data-env="winter"] img {
    transform: scale(1.1) translateY(-24%);
  }
  /* Unsure also needs a horizontal nudge toward the question-sign post
     (right side of the source), not just vertical — it's the "main point
     of interest" the mobile brief calls out alongside the road. */
  .env-layer[data-env="unsure"] img {
    transform: scale(1.55) translate(-10%, -22%);
  }
  /* All-season additionally needs a strong horizontal pull — same
     summer-hidden-under-the-glass problem as desktop/tablet, just solved
     inside mobile's much narrower/portrait crop window. */
  .env-layer[data-env="allseason"] img {
    transform: scale(1.4) translate(10%, -28%);
  }
  .options {
    gap: 8px;
  }
  .option {
    padding: 11px 14px;
  }

  /* Variant A stays a list on every breakpoint (never switches to a grid)
     — just tighter spacing/sizing, so all 4 rows have a realistic chance
     of fitting the 70vh band without needing the overflow-y scroll above. */
  .s1-variants {
    margin-top: 16px;
  }
  .s1-list__row {
    margin-bottom: 6px;
  }
  .s1-list__control {
    gap: 10px;
    min-height: 50px;
    padding: 7px 10px;
  }
  .s1-list__icon {
    width: 21px;
    height: 21px;
  }
  .s1-list__body {
    gap: 2px;
  }
  .s1-list__title {
    font-size: 0.88rem;
    gap: 6px;
  }
  .s1-list__desc {
    font-size: 0.72rem;
    line-height: 1.3;
  }
  .s1-list__chip {
    font-size: 0.55rem;
    padding: 2px 6px;
  }
  /* No font-size override here anymore — .s1-list__arrow's 1.8rem base is
     the floor on every breakpoint, mobile included. Same for the ul
     padding-reset — it's unconditional now (see ul.s1-list above), so no
     mobile-only duplicate is needed here either. */

  /* Variant B stays a 2x2 grid on mobile too (never 4x1) — only sizing
     changes. The .hero-glass band is a tight 70vh here, so tiles trade the
     desktop 1:1 square for a shorter 4:3 to leave room for both rows. */
  .s1-tiles {
    gap: 8px;
  }
  .s1-tile {
    aspect-ratio: 4 / 3;
  }
  .s1-tile__overlay {
    min-height: 44%;
    padding: 8px 10px;
    gap: 2px;
  }
  .s1-tile__header {
    gap: 6px;
  }
  .s1-tile__icon {
    width: 18px;
    height: 18px;
  }
  .s1-tile__title {
    font-size: 0.8rem;
  }
  .s1-tile__desc {
    font-size: 0.66rem;
    line-height: 1.25;
  }

  /* Per-season crop — mobile tiles are 4:3 with a 44% overlay (both
     shorter and covering proportionally more of the tile than desktop's
     1:1/36% combo), so the shared base zoom/pan values leave even more of
     the visible photo as sky. Correct overflow-budget formula for
     scale(S) translate(Tx%, Ty%) with the default center transform-origin
     is (S-1)/(2S) — not the simpler (S-1)/2 loosely used in earlier
     desktop/tablet comments, which is a slight overestimate. All values
     below are checked against the precise formula with margin to spare. */
  .s1-tile[data-season-id="summer"] .s1-tile__media img {
    --s1-tile-zoom: 2.1;
    --s1-tile-pan-y: -24%;
  }
  .s1-tile[data-season-id="winter"] .s1-tile__media img {
    --s1-tile-zoom: 2.1;
    --s1-tile-pan-y: -24%;
  }
  .s1-tile[data-season-id="allseason"] .s1-tile__media img {
    --s1-tile-zoom: 2.2;
    --s1-tile-pan-y: -26%;
    --s1-tile-pan-x: -6%;
  }
  .s1-tile[data-season-id="unsure"] .s1-tile__media img {
    --s1-tile-zoom: 1.95;
    --s1-tile-pan-y: -22%;
  }
}

/* ==========================================================================
   Wizard shell (S2+) — reusable 3-column layout (sidebar / content /
   visual panel) shared by every step from S2 onward. Independent of the
   S0/S1 scroll-scrubbed journey above: plain static flow, no sticky/
   parallax mechanics, own breakpoints (768px mobile / 1439px tablet
   ceiling — the S2 spec's own numbers, not S0/S1's 720/900/1024 set,
   since this is a genuinely different layout system, not a continuation
   of the hero scenes). Light-mode only per the S2 spec (--wizard-* tokens
   near the top of this file) — dark mode isn't redesigned for it, but
   nothing here reads a --hero-glass-* / --selection-glass-* token, so the
   global [data-theme] flip simply doesn't touch this section yet.
   ========================================================================== */
.wizard {
  position: relative;
  /* Configurator always fills the viewport (explicit request, 2026-08-11) —
     a fixed frame with its own internally-scrolling columns (sidebar/
     content below), not a normal page section that grows with content. */
  height: 100vh;
  background: var(--wizard-bg);
  /*padding: clamp(20px, 3vh, 40px) 0;*/
}

.wizard__shell {
  display: grid;
  grid-template-columns: 300px minmax(0, 1fr) clamp(260px, 22vw, 360px);
  align-items: stretch;
  /* Full-bleed edge-to-edge (2026-08-11) — was a centered max-width:1600px
     card with its own border/radius; now stretches across the whole
     viewport width instead, framed by nothing. */
  width: 100%;
  height: 100%;
  overflow: hidden;
}

/* Hamburger — mobile-only (see max-width:767px block), hidden by default
   so it never appears at tablet/desktop where the sidebar stays static. */
.wizard__menu-toggle {
  display: none;
}

.wizard__scrim {
  display: none;
}

/* --------------------------------------------------------------------------
   Sidebar
   -------------------------------------------------------------------------- */
/* Sidebar is now two layers (2026-08-11): .wizard__sidebar is just the
   outer frame (its own background peeks through as a border/gutter around
   the inner panel), .wizard__step-nav below holds the actual heading/
   steps/helper content on its own, different background. Split out on
   request so the two backgrounds can be tuned independently — values
   below are a starting point, not final. */
.wizard__sidebar {
  background: var(--wizard-sidebar-bg);
  /* Near-invisible divider (2026-08-11, was 7%) — the gradient itself
     should read as the separation between panels, not a border line. */
  border-right: 1px solid color-mix(in srgb, var(--wizard-text) 4%, transparent);
  padding: 20px 10px 0 20px;
  /* .wizard is a fixed 100vh frame now — a sidebar taller than the frame
     (many steps + helper box on a short screen) scrolls internally instead
     of being clipped by .wizard__shell's overflow:hidden. */
  overflow-y: auto;
}

.wizard__step-nav {
  height: 100%;
  min-height: 0;
  display: flex;
  flex-direction: column;
  background: var(--wizard-step-nav-bg);
  border-radius: 15px 15px 0 0;
  padding: 25px 10px;
}

.wizard__sidebar-heading {
  margin: 0 0 22px;
  padding: 0 0 0 20px;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--wizard-text);
}

.wizard__steps {
  list-style: none;
  margin: 0 0 24px;
  padding: 0;
  display: flex;
  flex-direction: column;
}

.wizard__step {
  position: relative;
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 12px 10px;
  margin-left: 2px;
  border-left: 4px solid transparent;
  border-radius: 0 10px 10px 0;
  margin-bottom: 5px;
}

.wizard__step.is-completed,
.wizard__step.is-active {
  border-left-color: var(--wizard-primary);
}

.wizard__step.is-active {
  background: var(--wizard-primary-surface);
}

.wizard__step-marker {
  flex: none;
  position: relative;
  width: 26px;
  height: 26px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1.5px solid var(--wizard-border);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.8rem;
  color: var(--wizard-text-muted);
  background: var(--wizard-surface);
}

.wizard__step.is-active .wizard__step-marker {
  border-color: var(--wizard-primary);
  color: var(--wizard-primary);
}

.wizard__step.is-completed .wizard__step-marker {
  border-color: var(--wizard-primary);
  background: var(--wizard-primary);
  color: #ffffff;
}

.wizard__step-check {
  width: 15px;
  height: 15px;
}

/* Completed marker shows the check, not the number — both sit in the
   same grid cell so swapping is just a visibility toggle, no layout. */
.wizard__step-number {
  grid-area: 1 / 1;
}
.wizard__step-check {
  grid-area: 1 / 1;
  display: none;
}
.wizard__step.is-completed .wizard__step-number {
  display: none;
}
.wizard__step.is-completed .wizard__step-check {
  display: block;
}

.wizard__step-body {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding-top: 2px;
}

.wizard__step-title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.86rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--wizard-text);
}

.wizard__step-value {
  font-size: 0.8rem;
  color: var(--wizard-text-secondary);
}

.wizard__step:not(.is-completed):not(.is-active) .wizard__step-title {
  color: var(--wizard-text-secondary);
}
.wizard__step:not(.is-completed):not(.is-active) .wizard__step-value {
  color: var(--wizard-text-muted);
}

.wizard__step-edit {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  align-self: center;
  padding: 4px 6px;
  border-radius: 8px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.72rem;
  color: var(--wizard-primary);
  text-decoration: none;
  transition: background-color 0.15s ease;
}
.wizard__step-edit:hover {
  background: color-mix(in srgb, var(--wizard-primary) 10%, transparent);
}
.wizard__step-edit svg {
  width: 13px;
  height: 13px;
}

/* S5 sidebar summary (2026-08-13) — small icon row instead of a text line
   (per spec: a long "Ticho priorita | Spotreba dôležité | ..." string would
   overload the sidebar). Sits where .wizard__step-value normally would;
   kept as its own class rather than reusing .wizard__step-value so other
   steps' plain-text rows are untouched. */
.wizard__step-factors {
  display: flex;
  align-items: center;
  gap: 6px;
}
.wizard__step-factor-icon {
  flex: none;
  width: 13px;
  height: 13px;
  color: var(--wizard-text-muted);
}
/* Only the 4 "ďalší faktor" icons carry [data-sidebar-factor] and get this
   live recolor (js/wizard-preferences.js) — the 3 priority icons before
   them in the row have no active/inactive state, so they stay this same
   muted color permanently. */
.wizard__step-factor-icon.is-active {
  color: var(--wizard-primary);
}

.wizard__helper {
  margin-top: auto;
  padding: 18px 16px;
  border-radius: var(--radius);
  background: var(--wizard-helper-bg);
}

.wizard__helper-title {
  margin: 0 0 6px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.88rem;
  color: var(--wizard-text);
}

.wizard__helper-text {
  margin: 0 0 14px;
  font-size: 0.8rem;
  line-height: 1.4;
  color: var(--wizard-text-secondary);
}

.wizard__helper-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 9px 16px;
  border-radius: 999px;
  border: 1px solid var(--wizard-border);
  background: var(--wizard-surface);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.8rem;
  color: var(--wizard-text);
  cursor: pointer;
  transition: border-color 0.15s ease, background-color 0.15s ease;
}
.wizard__helper-btn:hover {
  border-color: color-mix(in srgb, var(--wizard-primary) 40%, transparent);
}
.wizard__helper-btn svg {
  width: 17px;
  height: 17px;
  color: var(--wizard-primary);
}

/* --------------------------------------------------------------------------
   Content
   -------------------------------------------------------------------------- */
.wizard__content {
  display: flex;
  flex-direction: column;
  padding: 40px clamp(28px, 4vw, 56px);
  background: var(--wizard-content-bg);
  min-width: 0;
  /* Same reasoning as .wizard__sidebar above — content scrolls internally
     within the fixed 100vh frame rather than getting clipped. */
  overflow-y: auto;
}

.wizard__content-header {
  margin-bottom: 28px;
}
/* S6 only (2026-08-13) — the compact result cards sit right under the
   subtitle with no extra breathing room needed, unlike S1-S5's shared 28px
   gap. .wizard__content-header itself doesn't carry a per-step id, so this
   is scoped via :has() on the currently-visible heading rather than a new
   class — same "no separate mobile DOM" spirit as the rest of the wizard's
   step-toggling (:not([hidden]) is the actual visibility source of truth,
   js/wizard-shell.js goToStep() only ever unhides one heading at a time). */
.wizard__content-header:has(> [data-wizard-heading="result"]:not([hidden])) {
  margin-bottom: 0;
}

/* Per-step title/subtitle wrapper — lives inside the header (see markup
   comment in index.html) so it keeps the exact same vertical position
   across every step. margin-top recreates the 28px gap that used to be
   .wizard__content-header's own margin-bottom before title/subtitle moved
   in here from the top of .wizard__panel; .wizard__subtitle's own
   margin-bottom (below) still collapses with the header's margin-bottom to
   produce the matching 28px gap before the body, so both gaps stay
   identical to the pre-refactor layout. */
.wizard__content-heading {
  margin-top: 28px;
}

.wizard__kicker {
  margin: 0 0 10px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.75rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--wizard-text-muted);
}

.wizard__progress {
  height: 4px;
  border-radius: 999px;
  background: var(--wizard-border);
  overflow: hidden;
}

.wizard__progress-fill {
  height: 100%;
  border-radius: inherit;
  background: var(--wizard-primary);
  transition: width 0.3s ease;
}

/* Compact step-dot progress — mobile-only alternative to the linear bar
   above (see max-width:767px block). */
.wizard__dots {
  display: none;
}

/* The three structural regions of .wizard__content (see markup comments in
   index.html): header above is fixed-height, body is the only one that
   grows to absorb leftover space, footer is a plain flex sibling that
   naturally sits at its own (fixed) height right after body — which, since
   body has already claimed all the extra room, means footer always lands
   at the bottom of the panel instead of drifting up/down with how tall a
   given step's content happens to be. .wizard__panel itself no longer
   needs its own flex sizing (that used to live here pre-refactor) — only
   one panel is ever visible at a time and it just takes its natural
   content height inside the now-stretchy body. */
/* No min-height: 0 here on purpose — that would let this flex item shrink
   *below* its own content's natural height whenever a step's content is
   taller than the space available (e.g. the 2x2 vehicle-card grid at
   tablet widths), which doesn't scroll the overflow, it makes the cards
   visually spill out past this box and paint over .wizard__content-footer
   below. Leaving min-height at its default (auto == content size) means
   .wizard__content's own overflow-y: auto takes over instead in that case
   — the panel scrolls as a whole, nothing overlaps. flex-grow still fills
   leftover space normally for short content (e.g. S3), which is the only
   behavior this rule needs to provide. */
.wizard__content-body {
  flex: 1 1 auto;
  /* Flex column so the visible .wizard__panel below (its only real child —
     hidden panels are removed from layout entirely) can itself stretch to
     fill this box, which in turn lets that panel's own last child anchor
     to the bottom via margin-top: auto (see .wizard-dim-summary, 2026-08-
     12) instead of just sitting wherever its content happens to end. */
  display: flex;
  flex-direction: column;
}

/* Lets a panel's own last child pin to the bottom of the available body
   height (e.g. S3's .wizard-dim-summary) via margin-top: auto, instead of
   needing position: absolute. Same "no min-height: 0" reasoning as
   .wizard__content-body above — content taller than available space
   should make .wizard__content scroll, not shrink/overlap. Harmless for
   panels that don't need bottom-anchoring (S2's single .wizard__cards
   child just renders at its natural top-aligned height either way). */
.wizard__panel {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
}
/* Same equal-specificity fight as .wizard__footer[hidden]/.wizard__scrim
   [hidden]/.wizard-dim-note[hidden] elsewhere in this file: this rule sets
   `display`, so without this override the native `hidden` attribute
   js/wizard-shell.js's goToStep() toggles does nothing — both S2's and
   S3's panels render at once instead of just the active one. */
.wizard__panel[hidden] {
  display: none;
}

.wizard__content-footer {
  flex: none;
}

.wizard__title {
  margin: 0 0 10px;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(1.5rem, 1.1rem + 1.4vw, 2.2rem);
  color: var(--wizard-text);
}

.wizard__subtitle {
  margin: 0 0 28px;
  font-size: 1.2rem;
  color: var(--wizard-text-secondary);
  font-weight: 600;
}

/* --------------------------------------------------------------------------
   Vehicle selection cards — single responsive component, restyled (not
   duplicated) between the desktop/tablet grid and the mobile compact-row
   list via the breakpoints below.
   -------------------------------------------------------------------------- */
.wizard__cards {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 18px;
}

.wizard-card {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 14px;
  padding: 26px 18px 22px;
  border: 1px solid var(--wizard-border);
  border-radius: var(--radius);
  background: var(--wizard-surface);
  box-shadow: 0 4px 18px color-mix(in srgb, var(--wizard-text) 5%, transparent);
  font: inherit;
  color: inherit;
  cursor: pointer;
  transition: border-color 0.15s ease, background-color 0.15s ease,
    box-shadow 0.2s ease, transform 0.15s ease;
}

.wizard-card:hover {
  border-color: color-mix(in srgb, var(--wizard-primary) 25%, transparent);
  box-shadow: 0 6px 22px color-mix(in srgb, var(--wizard-text) 7%, transparent);
  transform: translateY(-2px);
}

.wizard-card.is-selected {
  background: var(--wizard-card-selected-bg);
  border-color: color-mix(in srgb, var(--wizard-primary) 50%, transparent);
}

.wizard-card__check {
  position: absolute;
  top: 14px;
  right: 14px;
  width: 22px;
  height: 22px;
  display: none;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--wizard-primary);
  color: #ffffff;
}
.wizard-card__check svg {
  width: 13px;
  height: 13px;
}
.wizard-card.is-selected .wizard-card__check {
  display: flex;
}

/* Photo tile, not a centered icon box: source photos are studio shots with
   a real transparent/fading-glow background (checked — alpha channel goes
   to 0 at the corners, not a baked-in solid color), so no fill color is
   needed behind them — the card's own white background shows straight
   through. aspect-ratio matches the source images (1536x1024 = 3:2) so
   object-fit: cover never crops the car itself, only trims a sliver of
   the transparent margin. */
.wizard-card__media {
  width: 100%;
  aspect-ratio: 3 / 2;
  border-radius: calc(var(--radius) - 6px);
  overflow: hidden;
  color: var(--wizard-text);
}
.wizard-card__media picture,
.wizard-card__media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.wizard-card__media svg {
  width: 100%;
  height: 100%;
}

.wizard-card__body {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.wizard-card__title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.95rem;
  color: var(--wizard-text);
  padding: 25px 0;
}

.wizard-card__desc {
  font-size: 0.78rem;
  line-height: 1.35;
  color: var(--wizard-text-secondary);
  margin-bottom: 15px;
}

/* --------------------------------------------------------------------------
   Footer
   -------------------------------------------------------------------------- */
.wizard__footer {
  margin-top: 32px;
  padding-top: 24px;
  border-top: 1px solid color-mix(in srgb, var(--wizard-text) 7%, transparent);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
}
/* Same specificity fight as .wizard__scrim[hidden] above: `[hidden]` and
   `.wizard__footer` are both single-selector rules, so without this the
   later `display: flex` here would win over the native `hidden` attribute
   js/wizard-shell.js's goToStep() toggles when switching steps. */
.wizard__footer[hidden] {
  display: none;
}

.wizard__footer-note {
  margin: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.82rem;
  color: var(--wizard-text-secondary);
}
/* S4's footer note (index.html, [data-wizard-footer="usage"]) is toggled
   directly on this element via `hidden` — same equal-specificity fight as
   .wizard__footer[hidden] above, since this rule also sets `display`. */
.wizard__footer-note[hidden] {
  display: none;
}
.wizard__footer-note svg {
  flex: none;
  width: 16px;
  height: 16px;
  color: var(--wizard-text-muted);
}

/* Wizard buttons use the existing .btn/.btn--primary shape (padding,
   radius, arrow hover motion) but the S2 spec's own primary green, not
   --color-accent-strong — scoped to .wizard so nothing outside it changes. */
.wizard .btn {
  margin-top: 0;
}
.wizard .btn--primary {
  background: var(--wizard-primary);
  box-shadow: 0 5px 14px color-mix(in srgb, var(--wizard-primary) 18%, transparent);
}
.wizard .btn--primary:hover {
  background: var(--wizard-primary-hover);
}
.wizard .btn--primary:active {
  background: var(--wizard-primary-active);
}
.wizard__continue[disabled] {
  opacity: 0.45;
  cursor: not-allowed;
  pointer-events: none;
  box-shadow: none;
}

/* Späť/Pokračovať action row (S4+, 2026-08-12) — lives in a step's own
   .wizard__panel body (not .wizard__content-footer, that's reserved for
   the small note), reusing .wizard__footer's shape (divider/spacing/flex
   space-between, including its existing mobile stack-and-center override)
   for the visual chrome. This class only overrides margin-top so the row
   anchors to the bottom of the panel via the same flex chain
   .wizard-dim-summary uses in S3, instead of .wizard__footer's own fixed
   32px. */
.wizard-step-actions {
  margin-top: auto;
}

.wizard-step-back {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  border: none;
  background: none;
  padding: 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.9rem;
  color: var(--wizard-text-secondary);
  cursor: pointer;
  transition: color 0.15s ease;
}
.wizard-step-back:hover {
  color: var(--wizard-text);
}
.wizard-step-back__arrow {
  transition: transform 0.15s ease;
}
.wizard-step-back:hover .wizard-step-back__arrow {
  transform: translateX(-3px);
}

/* --------------------------------------------------------------------------
   S3 — dimension controls (Šírka/Profil/Priemer disku/Nosnosť/Rýchlostný
   index). Same card language as .wizard-card above (border/surface/radius/
   shadow tokens) but compact — these are value pickers, not a single big
   choice, so five need to fit one row on desktop.
   -------------------------------------------------------------------------- */
.wizard-dim-grid {
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  gap: 14px;
  margin-bottom: 28px;
}

.wizard-dim-card {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 16px 14px;
  border: 1px solid var(--wizard-border);
  border-radius: calc(var(--radius) - 4px);
  background: var(--wizard-surface);
  box-shadow: 0 4px 18px color-mix(in srgb, var(--wizard-text) 5%, transparent);
}

.wizard-dim-card__label {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 0.82rem;
  color: var(--wizard-text-secondary);
}

/* Stepper cards (Šírka/Profil/Priemer disku): value+unit read left-aligned
   as one line (not centered), actions row pinned to the card's bottom via
   margin-top: auto — CSS Grid stretches every .wizard-dim-card in a row to
   the tallest one by default, so this keeps the +/- buttons level across
   all 5 cards regardless of small content-height differences between the
   stepper and select variants. */
.wizard-dim-card__value-row {
  display: flex;
  align-items: baseline;
  gap: 6px;
}

.wizard-dim-card__value {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1.3rem;
  color: var(--wizard-text);
}

.wizard-dim-card__unit {
  font-size: 0.72rem;
  color: var(--wizard-text-muted);
}

.wizard-dim-card__actions {
  margin-top: auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.wizard-dim-card__btn {
  flex: none;
  width: 32px;
  height: 32px;
  display: grid;
  place-items: center;
  border: 1px solid var(--wizard-border);
  border-radius: calc(var(--radius) - 6px);
  /* Light neutral gray, not the card's own white surface — reused from
     .wizard__helper so these read as real pressable controls rather than
     blending into the card background. */
  background: var(--wizard-helper-bg);
  font-family: var(--font-display);
  font-size: 1.05rem;
  line-height: 1;
  color: var(--wizard-text);
  cursor: pointer;
  transition: border-color 0.15s ease, background-color 0.15s ease,
    color 0.15s ease;
}
.wizard-dim-card__btn:hover {
  border-color: color-mix(in srgb, var(--wizard-primary) 40%, transparent);
  background: var(--wizard-primary-surface);
  color: var(--wizard-primary);
}

/* Select cards (Nosnosť/Rýchlostný index) — custom dropdown (2026-08-12),
   replacing the earlier invisible-<select>-overlay technique: a native
   <select>'s open picker is styled entirely by the OS/browser, which read
   as a jarring, un-themed popup dropped on top of the wizard. Structure
   now (see markup): .wizard-dim-card--select > .wizard-dim-card__trigger
   (a <button> reset to look like the card's own content — label/value/
   meta-row all live inside it, so the whole card is one accessible click
   target) + .wizard-dim-dropdown (a custom role="listbox" panel, absolute-
   positioned below the card, wired up in js/wizard-dimension.js). The
   load/speed index itself (e.g. "94", "V") is the value — the kg/km-h note
   is an explanatory sub-line, not a paired unit, so it does NOT sit next to
   .wizard-dim-card__value like the stepper cards' unit does. */
.wizard-dim-card--select {
  position: relative;
  /* Card's own padding/gap (from .wizard-dim-card) stay as the outer box;
     the trigger button fills that box and re-declares the same column
     layout internally so label/value/meta-row space consistently with the
     stepper cards' label/value-row/actions. */
  padding: 0;
}

.wizard-dim-card__trigger {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  gap: 12px;
  width: 100%;
  padding: 16px 14px;
  border: none;
  background: none;
  font: inherit;
  text-align: left;
  color: inherit;
  cursor: pointer;
}

.wizard-dim-card__meta-row {
  margin-top: auto;
  display: flex;
  align-items: center;
  gap: 6px;
}

.wizard-dim-card__chevron {
  flex: none;
  width: 14px;
  height: 14px;
  margin-left: auto;
  color: var(--wizard-text-muted);
  transition: transform 0.15s ease;
}
.wizard-dim-card__trigger[aria-expanded="true"] .wizard-dim-card__chevron {
  transform: rotate(180deg);
}

/* Custom dropdown panel — positioned relative to the card (not the
   trigger), so it lines up with the card's own edges regardless of the
   trigger's internal padding. Painted above .wizard-dim-summary below by
   default stacking order (it's position:absolute, summary is static) —
   the explicit z-index is just defensive. */
.wizard-dim-dropdown {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  z-index: 20;
  margin: 0;
  padding: 6px;
  list-style: none;
  background: var(--wizard-surface);
  border: 1px solid var(--wizard-border);
  border-radius: calc(var(--radius) - 4px);
  box-shadow: 0 10px 30px color-mix(in srgb, var(--wizard-text) 14%, transparent);
  max-height: 240px;
  overflow-y: auto;
}
.wizard-dim-dropdown[hidden] {
  display: none;
}
/* No outline on the listbox itself — keyboard navigation highlights the
   active row via .is-active instead (standard aria-activedescendant
   pattern: the listbox holds real focus, the option only looks focused). */
.wizard-dim-dropdown:focus {
  outline: none;
}

.wizard-dim-dropdown__option {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 10px;
  border-radius: calc(var(--radius) - 8px);
  cursor: pointer;
  transition: background-color 0.15s ease;
}
.wizard-dim-dropdown__option:hover,
.wizard-dim-dropdown__option.is-active {
  background: var(--wizard-helper-bg);
}
.wizard-dim-dropdown__option.is-selected {
  background: var(--wizard-primary-surface);
}

.wizard-dim-dropdown__index {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.92rem;
  color: var(--wizard-text);
}
.wizard-dim-dropdown__option.is-selected .wizard-dim-dropdown__index {
  color: var(--wizard-primary);
}

.wizard-dim-dropdown__desc {
  margin-left: auto;
  font-size: 0.82rem;
  color: var(--wizard-text-secondary);
}

.wizard-dim-dropdown__check {
  flex: none;
  width: 14px;
  height: 14px;
  color: var(--wizard-primary);
  opacity: 0;
}
.wizard-dim-dropdown__option.is-selected .wizard-dim-dropdown__check {
  opacity: 1;
}

/* Anchored to the bottom of the (flex-column) dimension panel via
   margin-top: auto — see .wizard__panel/.wizard__content-body above —
   instead of just following .wizard-dim-grid wherever its content ends.
   Background is the shared --wizard-summary-bg gradient (a plain summary
   area, not a success state — see its definition near the top of this
   file for why it's not green anymore) plus a card-level shadow reused
   from .wizard-dim-card, so it reads as "more of the same surface", not a
   separate alert box. */
.wizard-dim-summary {
  margin-top: auto;
  margin-bottom: 20px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 16px;
  padding: 20px 24px;
  border: 1px solid var(--wizard-border);
  border-radius: var(--radius);
  background: var(--wizard-summary-bg);
  box-shadow: 0 4px 18px color-mix(in srgb, var(--wizard-text) 5%, transparent);
}

.wizard-dim-summary__text {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.wizard-dim-summary__label {
  font-size: 0.82rem;
  color: var(--wizard-text-secondary);
}

.wizard-dim-summary__value {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1.5rem;
  color: var(--wizard-text);
}

.wizard-dim-summary__actions {
  display: flex;
  align-items: center;
  gap: 20px;
}

/* Primary green by default now, not gray-until-hover (2026-08-12) — still
   text-only (no fill/background), just visible enough not to lose to
   "Pokračovať" as the secondary action it is. 700 matches the weight this
   component family already uses for small link-style actions
   (.wizard__step-edit), reused rather than introducing 600 as a one-off. */
.wizard-dim-summary__link {
  border: none;
  background: none;
  padding: 0;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.85rem;
  color: var(--wizard-primary);
  cursor: pointer;
  transition: color 0.15s ease;
}
.wizard-dim-summary__link:hover {
  color: var(--wizard-primary-hover);
}
.wizard-dim-summary__link:hover .btn__arrow {
  transform: translateX(3px);
}

.wizard-dim-note {
  margin: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.82rem;
  color: var(--wizard-text-secondary);
}
/* Now toggled via the native `hidden` attribute (it's S3's
   [data-wizard-footer="dimension"] child) — same equal-specificity fight
   as .wizard__footer[hidden]/.wizard__scrim[hidden] above, since this rule
   also sets `display`. See feedback memory: any class rule setting
   `display` needs this pairing or `hidden` silently does nothing. */
.wizard-dim-note[hidden] {
  display: none;
}
.wizard-dim-note svg {
  flex: none;
  width: 16px;
  height: 16px;
  color: var(--wizard-text-muted);
}

/* --------------------------------------------------------------------------
   S5 — preferences (Hlučnosť/Spotreba paliva/Brzdenie na mokre). Same card
   language as .wizard-dim-card above (border/surface/radius/shadow tokens)
   — three cards fit one row on desktop instead of five, so more room per
   card than S3's compact value pickers.
   -------------------------------------------------------------------------- */
.wizard-pref-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 14px;
  margin-bottom: 28px;
}

.wizard-pref-card {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 18px 16px;
  border: 1px solid var(--wizard-border);
  border-radius: calc(var(--radius) - 4px);
  background: var(--wizard-surface);
  box-shadow: 0 4px 18px color-mix(in srgb, var(--wizard-text) 5%, transparent);
}

.wizard-pref-card__title {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.95rem;
  color: var(--wizard-text);
}

.wizard-pref-card__desc {
  margin: 0;
  font-size: 0.82rem;
  line-height: 1.4;
  color: var(--wizard-text-secondary);
}

/* Reference design (S5-preferencie-reference.png) uses a slider here —
   replaced with a clear 3-state segmented control per spec: no ambiguous
   drag interaction, every value is its own directly-clickable target
   (comfortable on mobile too, see the >=767px block below). */
.wizard-pref-selector {
  display: flex;
  gap: 6px;
  margin-top: auto;
}

.wizard-pref-selector__btn {
  flex: 1 1 0;
  padding: 9px 6px;
  border: 1px solid var(--wizard-border);
  border-radius: calc(var(--radius) - 8px);
  background: var(--wizard-helper-bg);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 0.72rem;
  line-height: 1.25;
  color: var(--wizard-text-secondary);
  text-align: center;
  cursor: pointer;
  transition: border-color 0.15s ease, background-color 0.15s ease,
    color 0.15s ease;
}
.wizard-pref-selector__btn:hover {
  border-color: color-mix(in srgb, var(--wizard-primary) 40%, transparent);
  color: var(--wizard-text);
}
.wizard-pref-selector__btn.is-selected {
  border-color: var(--wizard-primary);
  background: var(--wizard-primary);
  color: #ffffff;
}
.wizard-pref-selector__btn.is-selected:hover {
  color: #ffffff;
}

/* "Ďalšie faktory" — ON/OFF strip, deliberately not checkboxes (per spec):
   each factor is one accessible <button> whose icon+label both recolor via
   currentColor, so a single class toggle (js/wizard-preferences.js) handles
   both at once. No fill background on the active state — "jemný a
   elegantný", the color change alone is the affordance. */
/* Same box as S3's "Zvolený rozmer" (.wizard-dim-summary) — gradient
   surface, border, shadow, and margin-top: auto pushing it to the bottom
   of the (flex-column) panel, directly above the Späť/Pokračovať row —
   not just another plain content section. Unlike S3 (where the CTA lives
   *inside* .wizard-dim-summary, making it the panel's last child), S5's
   Späť/Pokračovať is its own separate .wizard-step-actions row that
   follows this box — and .wizard-step-actions already carries its own
   margin-top: auto (reused from S4). Two auto margins in the same flex
   column split the free space between them instead of one absorbing it
   all, which left this box floating mid-panel instead of hugging the
   bottom — the override right below cancels the second one so this box's
   own auto margin is the only one doing the push. */
.wizard-pref-factors {
  margin-top: auto;
  margin-bottom: 20px;
  padding: 20px 24px;
  border: 1px solid var(--wizard-border);
  border-radius: var(--radius);
  background: var(--wizard-summary-bg);
  box-shadow: 0 4px 18px color-mix(in srgb, var(--wizard-text) 5%, transparent);
}
.wizard-pref-factors + .wizard-step-actions {
  margin-top: 0;
}

.wizard-pref-factors__heading {
  margin: 0 0 14px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.86rem;
  color: var(--wizard-text);
}

.wizard-pref-factors__list {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 28px;
}

.wizard-pref-factor {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 4px;
  border: none;
  border-radius: calc(var(--radius) - 8px);
  background: none;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 0.84rem;
  color: var(--wizard-text-muted);
  cursor: pointer;
  transition: color 0.15s ease, background-color 0.15s ease;
}
.wizard-pref-factor:hover {
  background: color-mix(in srgb, var(--wizard-text) 4%, transparent);
}
.wizard-pref-factor:focus-visible {
  outline: 2px solid var(--wizard-primary);
  outline-offset: 2px;
}
.wizard-pref-factor.is-active {
  color: var(--wizard-primary);
}
.wizard-pref-factor__icon {
  flex: none;
  width: 19px;
  height: 19px;
}
.wizard-pref-factor__icon svg {
  width: 100%;
  height: 100%;
}

/* --------------------------------------------------------------------------
   S6 — results (3 mock product cards, js/wizard-result.js). CENTER CONTENT
   only, per spec — LEFT sidebar/RIGHT visual panel are the existing S2-S5
   components, completely untouched by this section.
   -------------------------------------------------------------------------- */
.wizard-result-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 14px;
  margin-bottom: 16px;
}

.wizard-result-info {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 18px;
}

.wizard-result-info__item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 0.82rem;
  color: var(--wizard-text-secondary);
}
.wizard-result-info__item svg {
  flex: none;
  width: 15px;
  height: 15px;
  color: var(--wizard-text-muted);
}

/* Secondary/outline pill — this project's buttons were all filled
   .btn--primary until now (Pokračovať/Zmeniť), so there's no existing
   secondary variant to reuse; still built from the same tokens
   (--wizard-primary, --radius, --font-display), not a new palette. Dead
   button (per spec) — no click handler, visual/hover/focus only. */
.wizard-result-all-btn {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 18px;
  border: 1px solid var(--wizard-primary);
  border-radius: 999px;
  background: var(--wizard-surface);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.72rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--wizard-primary);
  cursor: pointer;
  transition: background-color 0.15s ease;
}
.wizard-result-all-btn:hover {
  background: var(--wizard-primary-surface);
}
.wizard-result-all-btn .btn__arrow {
  transition: transform 0.15s ease;
}
.wizard-result-all-btn:hover .btn__arrow {
  transform: translateX(3px);
}

/* Same grid convention as .wizard-dim-grid/.wizard-pref-grid — 3 columns
   on desktop, each row's items auto-stretch to equal height (CSS Grid's
   own default align-items: stretch), which is what keeps all 3 cards the
   same height regardless of product-name length, no extra JS/CSS needed
   for that beyond this grid + each card's own flex-column footer anchor
   below. */
.wizard-result-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
  margin-bottom: 14px;
}

.wizard-result-card {
  display: flex;
  flex-direction: column;
  padding: 18px 18px;
  border: 1px solid var(--wizard-border);
  border-radius: var(--radius);
  background: var(--wizard-surface);
  box-shadow: 0 4px 18px color-mix(in srgb, var(--wizard-text) 5%, transparent);
}

.wizard-result-card__header {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 8px;
  min-height: 24px;
}

.wizard-result-card__rank {
  flex: none;
  width: 26px;
  height: 26px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--wizard-helper-bg);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.8rem;
  color: var(--wizard-text);
}

/* "Jemný, zelený accent, nie agresívny" (per spec) — tint background +
   green text, same light-fill language as .wizard-card__media's
   selected-tint tokens, not a solid/loud green. */
.wizard-result-card__badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 5px 10px;
  border-radius: 999px;
  background: var(--wizard-primary-surface);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.66rem;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--wizard-primary);
}
.wizard-result-card__badge svg {
  flex: none;
  width: 11px;
  height: 11px;
}

.wizard-result-card__info {
  margin-bottom: 10px;
}

.wizard-result-card__brand {
  margin: 0 0 2px;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--wizard-text-secondary);
}

.wizard-result-card__model {
  margin: 0 0 4px;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1.05rem;
  color: var(--wizard-text);
}

.wizard-result-card__rating {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.78rem;
}

.wizard-result-card__rating-value {
  font-family: var(--font-display);
  font-weight: 700;
  color: var(--wizard-text);
}

.wizard-result-card__stars {
  display: inline-flex;
  align-items: center;
  gap: 1px;
  color: var(--wizard-text-muted);
}
.wizard-result-card__stars svg {
  width: 13px;
  height: 13px;
}
.wizard-result-card__stars svg.is-filled {
  color: #f2b400;
}

.wizard-result-card__reviews {
  color: var(--wizard-text-muted);
}

/* Middle block split (2026-08-13, was image stacked above the params list)
   — media left / specs right, side by side. Same overall card height
   budget as the stacked version (fixed height cap, per the earlier
   overflow fix) — this only changes how that height is laid out
   horizontally, not how tall it is. */
/* CSS Grid, not flex (2026-08-13) — fixed 35/65 track proportions so the
   split holds steady regardless of content, instead of flex-basis letting
   either side creep wider/narrower with its own content size. */
.wizard-result-card__middle {
  display: grid;
  grid-template-columns: minmax(0, 35%) minmax(0, 65%);
  align-items: center;
  gap: 10px;
  margin-bottom: 12px;
}

/* Fixed height cap (was aspect-ratio scaling to 100% card width — the
   single biggest cause of S6's cards overflowing the wizard shell's
   height, since a width-driven aspect-ratio box grows with the grid
   column instead of staying a predictable size); height-based media query
   below shrinks this further on short viewports (1366x768 etc). Tire stays
   large/prominent (justify-content: flex-start + a small negative margin
   lets it bleed slightly past the card's own left edge, same "intentional
   overflow" language as the RIGHT-SIDE hero tire) instead of shrinking to
   fit next to the specs column — the fade below handles the transition
   instead. overflow: hidden clips that bleed/fade cleanly at the card's
   rounded corners. */
.wizard-result-card__media {
  position: relative;
  height: 150px;
  margin-left: -6px;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  overflow: hidden;
}
/* Subtle white fade over the image's own right edge, where the specs
   column begins — text must never sit directly on the tire's tread
   pattern (per spec), so this guarantees a clean, flat background behind
   it regardless of how far the tire art extends. var(--wizard-surface),
   not a hardcoded white, so it still matches the card's own background
   exactly. */
.wizard-result-card__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    to right,
    transparent 55%,
    var(--wizard-surface) 100%
  );
  pointer-events: none;
}
.wizard-result-card__media picture,
.wizard-result-card__media img {
  position: relative;
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: 100%;
  object-fit: contain;
}

.wizard-result-card__params {
  min-width: 0;
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.wizard-result-card__param {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.7rem;
  line-height: 1.2;
  color: var(--wizard-text-secondary);
}
.wizard-result-card__param svg {
  flex: none;
  width: 12px;
  height: 12px;
  color: var(--wizard-text-muted);
}

.wizard-result-card__param-value {
  margin-left: auto;
  font-family: var(--font-display);
  font-weight: 700;
  color: var(--wizard-text);
}
.wizard-result-card__param-value .wizard-result-card__stars {
  gap: 1px;
}
.wizard-result-card__param-value .wizard-result-card__stars svg {
  width: 12px;
  height: 12px;
}

/* Price + CTA anchored to the bottom of the (flex-column) card via
   margin-top: auto — same "stable bottom regardless of title length above
   it" mechanism as .wizard-dim-summary/.wizard-pref-factors elsewhere. */
.wizard-result-card__footer {
  margin-top: auto;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.wizard-result-card__price {
  margin: 0;
  text-align: right;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1.15rem;
  color: var(--wizard-text);
}

.wizard-result-card__unit {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 0.78rem;
  color: var(--wizard-text-muted);
}

/* Dead CTA (per spec) — visual/hover/focus only, reuses .wizard
   .btn--primary's color/radius/shadow tokens, just its OWN compact padding
   (2026-08-13, was .btn's full 14px/28px — read as an oversized e-shop
   button at card width) instead of the shared size, full-width inside the
   card. Uppercase is a scoped addition (S6-vysledok.png's own button
   treatment) — Pokračovať/Zmeniť elsewhere stay sentence-case, unaffected
   since this only targets this specific class. */
.wizard-result-card__cta {
  width: 100%;
  justify-content: center;
  padding: 9px 16px;
  font-size: 0.78rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
}

/* Shorter desktop viewports (2026-08-13) — e.g. 1366x768/1440x900 laptops
   have noticeably less height than a 1920x1080/1680x1050 monitor once the
   browser's own chrome is subtracted. Height (not width) media query on
   purpose — this has nothing to do with how wide the screen is. Shrinks
   the tallest single element (the tire image) further plus a bit of
   padding/gap, not a global scale/zoom hack (per spec, explicitly ruled
   out) and not font-size changes elsewhere in the wizard. */
@media (max-height: 820px) {
  .wizard-result-card {
    padding: 14px 16px;
  }
  .wizard-result-card__middle {
    margin-bottom: 8px;
  }
  .wizard-result-card__media {
    height: 110px;
  }
  .wizard-result-card__params {
    gap: 4px;
  }
  .wizard-result-grid {
    gap: 12px;
    margin-bottom: 10px;
  }
  .wizard-result-header {
    margin-bottom: 12px;
  }
}

/* --------------------------------------------------------------------------
   Visual panel — clean, no dimension bubbles yet (S3 will add those; see
   docs/02-wizard-flow.md). Tire bleeds off the panel's own right edge on
   purpose (crop is intentional, not a bug — see comment on the markup).
   -------------------------------------------------------------------------- */
.wizard__visual {
  position: relative;
  background: var(--wizard-visual-bg);
  overflow: hidden;
}

/* Explicit stacking so future S3 dimension boxes land above the tire
   without a z-index fight: background (auto) < tire (1) < info boxes (2). */
.wizard-visual-tire-img {
  z-index: 1;
}

/* Prep layer (see markup comment) — reserves the stacking position above
   the tire. Still pointer-events: none itself (most of the panel stays
   decorative/non-interactive), .wizard-visual-summary/.wizard-visual-pref
   below opt back into pointer-events for their own interactive bits.
   justify-content: center vertically centers the whole box stack
   (dimension + S5+ preferences) in the panel's full height. */
.wizard__visual-info {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-start;
  padding: 28px 20px;
  pointer-events: none;
}

/* S4+ dimension recap (2026-08-13) — tire image stays visible around it.
   Hidden via the native `hidden` attribute for S1-S3 (js/wizard-shell.js
   goToStep()) — explicit [hidden] override required since this rule sets
   `display`, see feedback memory on hidden + class-set-display specificity
   (bit us 4x already). No heading (removed 2026-08-13) — "Zmeniť" now sits
   below the box list as its own action instead. */
.wizard-visual-summary {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 14px;
  pointer-events: auto;
}
.wizard-visual-summary[hidden] {
  display: none;
}

.wizard-visual-summary__list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

/* Same card language as .wizard-dim-card (border/radius/background/shadow
   tokens) at a smaller scale for this narrower panel — left-aligned, no
   centering, "clean summary card" not "heavy card". Fixed width (2026-08-
   13, ~40% of the panel) instead of stretching full-width — sized to fit
   the longest label ("Rýchlostný index") on one line; all 5 boxes share it
   so they read as one aligned column rather than ragged widths. All 5 are
   naturally the same 2-line height (label + value row) since Nosnosť/
   Rýchlostný index's kg/km-h note moved onto the value row (see
   .wizard-visual-summary__value-row below) instead of its own third line —
   no min-height/centering hack needed to equalize them anymore. */
.wizard-visual-summary__item {
  display: flex;
  flex-direction: column;
  gap: 2px;
  width: 152px;
  padding: 12px 14px;
  border: 1px solid var(--wizard-border);
  border-radius: calc(var(--radius) - 6px);
  background: var(--wizard-surface);
  box-shadow: 0 4px 18px color-mix(in srgb, var(--wizard-text) 5%, transparent);
  text-align: left;
}

.wizard-visual-summary__label {
  margin: 0;
  font-size: 0.72rem;
  color: var(--wizard-text-secondary);
  white-space: nowrap;
}

/* Nosnosť/Rýchlostný index only (2026-08-13) — value float-left, kg/km-h
   note float-right on the same line (space-between), instead of
   __secondary sitting on its own third line below. */
.wizard-visual-summary__value-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
}

.wizard-visual-summary__value {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: 1.05rem;
  color: var(--wizard-text);
}

/* Filled-green "like Pokračovať" (2026-08-13) — same color/hover/active
   tokens as .wizard .btn--primary (css comment near .wizard__continue), but
   its own compact padding/font-size rather than .btn's larger 14px/28px —
   this stays a secondary, smaller action, not full CTA size. Sized to its
   own text+icon content (align-self: flex-start overrides the parent's
   align-items: stretch), not stretched to the boxes' width above — ~10px
   horizontal breathing room around the label, pencil icon reuses the exact
   same path as .wizard__step-edit's (sidebar Sezóna/Vozidlo/Rozmer "Zmeniť"
   links) so the "this can be edited" glyph reads as the same affordance
   everywhere, not a second icon language. */
.wizard-visual-summary__edit {
  align-self: flex-start;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  border: none;
  border-radius: calc(var(--radius) - 6px);
  padding: 5px 10px;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.8rem;
  color: #ffffff;
  background: var(--wizard-primary);
  box-shadow: 0 5px 14px color-mix(in srgb, var(--wizard-primary) 18%, transparent);
  cursor: pointer;
  transition: background-color 0.15s ease, transform 0.15s ease;
}
.wizard-visual-summary__edit svg {
  flex: none;
  width: 14px;
  height: 14px;
}
.wizard-visual-summary__edit:hover {
  background: var(--wizard-primary-hover);
}
.wizard-visual-summary__edit:active {
  transform: translateY(1px) scale(0.98);
  background: var(--wizard-primary-active);
}

/* Nosnosť/Rýchlostný index only (kg/km-h) — smaller and greyer than
   __value, same "secondary meta" role as .wizard-dim-card__unit in S3.
   Right-aligned on the value row (see .wizard-visual-summary__value-row's
   space-between) — nowrap so "(670 kg)" can't wrap inside the 152px box. */
.wizard-visual-summary__secondary {
  margin: 0;
  font-size: 0.72rem;
  color: var(--wizard-text-muted);
  white-space: nowrap;
}

/* S5+ preferences recap (2026-08-13) — sibling box below
   .wizard-visual-summary, same pointer-events/hidden pattern. Deliberately
   wider than the 152px dimension box (align-self: stretch fills
   .wizard__visual-info's own content width) since it needs 3 side-by-side
   columns rather than a single value line — "loosely evokes a tyre label"
   per spec via the card border/shadow + 3-column layout, without copying
   its colored bars. */
.wizard-visual-pref {
  align-self: stretch;
  margin-top: 10px;
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 16px 14px;
  border: 1px solid var(--wizard-border);
  border-radius: calc(var(--radius) - 4px);
  background: var(--wizard-surface);
  box-shadow: 0 4px 18px color-mix(in srgb, var(--wizard-text) 5%, transparent);
  pointer-events: auto;
}
.wizard-visual-pref[hidden] {
  display: none;
}

.wizard-visual-pref__heading {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.68rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  text-align: center;
  color: var(--wizard-text-secondary);
}

.wizard-visual-pref__row {
  display: flex;
  align-items: flex-start;
}

.wizard-visual-pref__col {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 0 6px;
  text-align: center;
}
/* Very subtle column separators (per spec) — same near-invisible divider
   strength as .wizard__sidebar's own border-right. */
.wizard-visual-pref__col + .wizard-visual-pref__col {
  border-left: 1px solid color-mix(in srgb, var(--wizard-text) 8%, transparent);
}

.wizard-visual-pref__icon {
  width: 18px;
  height: 18px;
  color: var(--wizard-text-secondary);
}
.wizard-visual-pref__icon svg {
  width: 100%;
  height: 100%;
}

.wizard-visual-pref__label {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 0.7rem;
  color: var(--wizard-text);
}

.wizard-visual-pref__value {
  margin: 0;
  font-size: 0.66rem;
  line-height: 1.3;
  color: var(--wizard-text-secondary);
}

/* All 4 factors always render here (see markup comment) — active/inactive
   is a color change (green/muted, currentColor via .is-active below), same
   recolor-only affordance as the main content's own toggle buttons; a
   subtle top divider separates this row from the priority row above. */
.wizard-visual-pref__factors {
  display: flex;
  justify-content: center;
  gap: 14px;
  padding-top: 12px;
  border-top: 1px solid color-mix(in srgb, var(--wizard-text) 8%, transparent);
}

.wizard-visual-pref__factor-icon {
  width: 15px;
  height: 15px;
  color: var(--wizard-text-muted);
}
.wizard-visual-pref__factor-icon.is-active {
  color: var(--wizard-primary);
}
.wizard-visual-pref__factor-icon svg {
  width: 100%;
  height: 100%;
}

/* Real product photo (see PLACEHOLDER comment on the markup) — replaces the
   pure-CSS ring/rim placeholder that used to live here (kept below,
   commented, in case this asset has to come out before a licensed
   replacement exists).
   Positioning (2026-08-11): object-fit: contain on an oversized box
   instead of sizing the <img> itself by height/width — the box is 100%
   of the panel's width shifted right (right: -15%), so part of the box
   always extends past the panel's real right edge (.wizard__visual's
   overflow: hidden crops it there, intentional). object-position: right
   bottom then pins the actual (aspect-ratio-preserved) image to that
   box's right/bottom corner, so it reads as anchored to the panel's
   right edge and sits close to the bottom, without ever stretching or
   distorting — contain guarantees the ratio regardless of box shape.
   Reflection via -webkit-box-reflect (Chrome/Safari/Edge) with a
   graceful no-reflection fallback everywhere else (Firefox has no
   equivalent). */
.wizard-visual-tire-img {
  position: absolute;
  right: -30%;
  bottom: 0;
  width: 100%;
  height: 78%;
  object-fit: contain;
  object-position: right bottom;
  /* Global `img { max-width: 100% }` reset (near the top of this file)
     would otherwise clamp this box's width and defeat the intentional
     right-edge overflow above. */
  max-width: none;
  -webkit-box-reflect: below 6px
    linear-gradient(rgba(255, 255, 255, 0.28), transparent 65%);
}

/*
.wizard-visual-tire {
  position: absolute;
  top: 50%;
  right: -12%;
  transform: translateY(-50%);
  width: min(56vw, 540px);
  aspect-ratio: 1;
}

.wizard-visual-tire__tread {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background-image: repeating-conic-gradient(
      rgba(0, 0, 0, 0.4) 0deg 2.6deg,
      rgba(0, 0, 0, 0) 2.6deg 5.2deg,
      rgba(255, 255, 255, 0.05) 5.2deg 6.4deg,
      rgba(0, 0, 0, 0) 6.4deg 8deg
    ),
    radial-gradient(circle at 36% 32%, #565656 0%, #2a2a2a 55%, #141414 100%);
  box-shadow: inset 0 0 46px rgba(0, 0, 0, 0.55),
    0 30px 60px color-mix(in srgb, var(--wizard-text) 18%, transparent);
}

.wizard-visual-tire__rim {
  position: absolute;
  inset: 23%;
  border-radius: 50%;
  background: conic-gradient(
    from 0deg,
    #e6e9e7,
    #aeb4b1 8%,
    #e6e9e7 18%,
    #888e8b 28%,
    #e6e9e7 38%,
    #aeb4b1 48%,
    #e6e9e7 58%,
    #888e8b 68%,
    #e6e9e7 78%,
    #aeb4b1 88%,
    #e6e9e7 100%
  );
  box-shadow: inset 0 0 0 2px rgba(0, 0, 0, 0.15),
    inset 0 12px 22px rgba(255, 255, 255, 0.3),
    inset 0 -16px 26px rgba(0, 0, 0, 0.35);
}

.wizard-visual-tire__hub {
  position: absolute;
  inset: 38%;
  border-radius: 50%;
  background: radial-gradient(circle at 38% 34%, #f4f5f3, #9a9f9c 70%, #6d726f 100%);
  box-shadow: inset 0 0 0 2px rgba(0, 0, 0, 0.2), 0 2px 8px rgba(0, 0, 0, 0.3);
}
*/

/* --------------------------------------------------------------------------
   Tablet — 768px to 1439px. Narrower sidebar/visual panel, content gets
   priority, 2x2 card grid, no horizontal overflow.
   -------------------------------------------------------------------------- */
@media (max-width: 1439px) {
  .wizard__shell {
    grid-template-columns: 232px minmax(0, 1fr) clamp(180px, 18vw, 260px);
    min-height: 0;
  }
  .wizard__sidebar {
    padding: 26px 18px;
  }
  .wizard__content {
    padding: 32px clamp(22px, 3vw, 40px);
  }
  .wizard__cards {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  /* No .wizard-visual-tire-img override needed here — its sizing (height:
     70%, translateX(70%)) is already relative to the panel/image's own
     box, so it scales correctly to the narrower tablet panel on its own. */
  .wizard__visual-info {
    padding: 20px 14px;
  }
  .wizard-visual-summary__item {
    width: 132px;
    padding: 10px 12px;
  }
  .wizard-visual-summary__label {
    font-size: 0.68rem;
  }
  .wizard-visual-pref {
    padding: 12px 10px;
    gap: 10px;
  }
  .wizard-visual-pref__icon {
    width: 16px;
    height: 16px;
  }
  .wizard-visual-pref__label {
    font-size: 0.64rem;
  }
  .wizard-visual-pref__value {
    font-size: 0.6rem;
  }
  .wizard-visual-pref__factors {
    gap: 10px;
  }
  .wizard-visual-pref__factor-icon {
    width: 13px;
    height: 13px;
  }

  .wizard-dim-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  /* S6 — narrower tablet content column keeps 3 cards (per spec) but with
     tighter padding/image so they don't feel cramped. */
  .wizard-result-card {
    padding: 14px 12px;
  }
  .wizard-result-card__middle {
    gap: 8px;
    margin-bottom: 8px;
  }
  .wizard-result-card__media {
    height: 120px;
  }
  .wizard-result-all-btn {
    padding: 8px 14px;
    font-size: 0.66rem;
  }
}

/* --------------------------------------------------------------------------
   Compact desktop — roughly 1025-1500px (1366x768/1440x900/1536x864
   laptops), 2026-08-13. This is NOT the tablet layout above: LEFT sidebar
   keeps its full content/nav/completed-states, S6 cards keep all 5 params
   and full text. The one real problem this range has is RIGHT-SIDE's
   large-desktop width (300px sidebar + clamp(260px,22vw,360px) visual —
   sized for 1920px+ monitors) squeezing CENTER disproportionately at
   medium widths, which is what made S6's cards look cramped even though
   nothing in the card CSS itself targets this range. Fix: narrow RIGHT-
   SIDE here specifically, CENTER (minmax(0,1fr)) absorbs what it frees up.

   grid-template-columns is one atomic shorthand — it can't be partially
   overridden, so the left-column value has to match whichever tier (tablet
   vs large-desktop) actually applies at a given width in this range. Split
   into two width bands purely for that reason; every other rule below is
   shared across the whole 1025-1500px range in one block, since padding/
   gap/image-size don't depend on the sidebar's own width. */
@media (min-width: 1025px) and (max-width: 1439px) {
  /* Overlaps the tablet block above (which already sets 232px/tablet's
     own right clamp) — this narrows the right column further; source
     order makes this rule win for the shared .wizard__shell selector. */
  .wizard__shell {
    grid-template-columns: 232px minmax(0, 1fr) clamp(220px, 17vw, 250px);
  }
}
@media (min-width: 1440px) and (max-width: 1500px) {
  /* Above the tablet cutoff — left sidebar stays at large-desktop's own
     300px (untouched, per spec), only the right column narrows. */
  .wizard__shell {
    grid-template-columns: 300px minmax(0, 1fr) clamp(220px, 17vw, 250px);
  }
}
@media (min-width: 1025px) and (max-width: 1500px) {
  .wizard__visual-info {
    padding: 14px 14px;
  }
  /* Decorative only (per spec) — pushed further off the panel's right
     edge so it can't compete with CENTER for width; same asset, same
     other properties (height/object-fit/reflection), just a bigger crop. */
  .wizard-visual-tire-img {
    right: -55%;
  }
  .wizard-visual-pref {
    padding: 12px 10px;
    gap: 10px;
  }
  .wizard-visual-pref__icon {
    width: 16px;
    height: 16px;
  }
  .wizard-visual-pref__label {
    font-size: 0.64rem;
  }
  .wizard-visual-pref__value {
    font-size: 0.6rem;
  }

  /* S6 — CENTER is wider now (RIGHT-SIDE freed up above), so cards get
     real desktop treatment: full padding/gaps only trimmed a little (not
     tablet's aggressive cut), all 5 params stay at readable size, image
     shrinks just enough to match its own (square-asset) column width
     instead of wasting height in a box the image can't fill sideways. */
  .wizard-result-grid {
    gap: 14px;
  }
  .wizard-result-card {
    padding: 16px 16px;
  }
  .wizard-result-card__media {
    height: 130px;
  }
}

/* --------------------------------------------------------------------------
   Mobile — below 768px. Sidebar becomes a slide-in drawer behind the
   hamburger, linear progress swaps for compact step dots, cards become a
   single column of compact rows, visual panel is hidden entirely.
   -------------------------------------------------------------------------- */
@media (max-width: 767px) {
  .wizard {
    padding: 0;
  }
  .wizard__shell {
    display: block;
    border: none;
    border-radius: 0;
    max-width: none;
  }

  .wizard__menu-toggle {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin: 14px 0 14px 16px;
    padding: 9px 14px 9px 10px;
    border: 1px solid var(--wizard-border);
    border-radius: 999px;
    background: var(--wizard-surface);
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 0.78rem;
    color: var(--wizard-text);
    cursor: pointer;
  }
  .wizard__menu-icon {
    display: flex;
    flex-direction: column;
    gap: 3px;
    width: 16px;
  }
  .wizard__menu-icon span {
    display: block;
    height: 2px;
    border-radius: 1px;
    background: currentColor;
  }

  .wizard__sidebar {
    position: fixed;
    inset: 0 22% 0 0;
    z-index: 40;
    overflow-y: auto;
    transform: translateX(-100%);
    transition: transform 0.25s ease;
    border-right: 1px solid var(--wizard-border);
    box-shadow: 12px 0 32px rgba(0, 0, 0, 0.18);
  }
  .wizard[data-menu-open] .wizard__sidebar {
    transform: translateX(0);
  }

  .wizard__scrim {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 35;
    background: rgba(10, 12, 10, 0.35);
  }
  .wizard[data-menu-open] .wizard__scrim {
    display: block;
  }
  .wizard__scrim[hidden] {
    display: none;
  }

  .wizard__content {
    padding: 4px 18px 28px;
  }

  /* Content-driven on mobile (per spec) — body no longer stretches to push
     footer to the viewport's bottom edge; footer just follows directly
     after whatever height that step's content naturally has. Header/body/
     footer still exist as the same three regions, just without desktop's
     "footer pinned to bottom" behavior. */
  .wizard__content-body {
    flex: none;
  }

  .wizard__progress {
    display: none;
  }
  .wizard__dots {
    display: flex;
    gap: 8px;
    list-style: none;
    margin: 0;
    padding: 0;
  }
  .wizard__dot {
    width: 24px;
    height: 24px;
    display: grid;
    place-items: center;
    border-radius: 50%;
    border: 1.5px solid var(--wizard-border);
    font-family: var(--font-display);
    font-weight: 700;
    font-size: 0.68rem;
    color: var(--wizard-text-muted);
  }
  .wizard__dot.is-active {
    border-color: var(--wizard-primary);
    color: var(--wizard-primary);
  }
  .wizard__dot.is-completed {
    border-color: var(--wizard-primary);
    background: var(--wizard-primary);
    color: #ffffff;
  }

  .wizard__title {
    font-size: 1.4rem;
  }
  .wizard__subtitle {
    margin-bottom: 20px;
  }

  .wizard__cards {
    display: flex;
    flex-direction: column;
    gap: 10px;
  }

  .wizard-card {
    flex-direction: row;
    align-items: center;
    text-align: left;
    gap: 12px;
    padding: 12px 14px;
  }
  .wizard-card__media {
    width: 40px;
    height: 40px;
    flex: none;
  }
  .wizard-card__body {
    flex: 1 1 auto;
    gap: 0;
  }
  .wizard-card__desc {
    display: none;
  }
  .wizard-card__check {
    position: static;
    margin-left: auto;
  }

  .wizard__footer {
    flex-direction: column;
    align-items: stretch;
    margin-top: 20px;
    padding-top: 18px;
  }
  .wizard__footer-note {
    justify-content: center;
    text-align: center;
  }
  .wizard-step-back {
    justify-content: center;
  }
  .wizard__continue {
    width: 100%;
    justify-content: center;
  }

  .wizard__visual {
    display: none;
  }

  .wizard-dim-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
  }
  .wizard-dim-card {
    padding: 14px 10px;
  }
  .wizard-dim-card__btn {
    width: 34px;
    height: 34px;
  }

  .wizard-dim-summary {
    flex-direction: column;
    align-items: stretch;
    padding: 16px 18px;
  }
  .wizard-dim-summary__actions {
    flex-direction: column;
    align-items: stretch;
    gap: 12px;
  }
  .wizard-dim-summary__link {
    justify-content: center;
  }

  /* S5 — cards stack (per spec), 3-state selector keeps its full labels
     ("Nezáleží"/"Dôležité"/"Veľmi dôležité" — not abbreviated) just with
     tighter padding/font so all three stay comfortably tappable at flex:1
     (already the desktop default, unchanged here). Factors wrap 2x2. */
  .wizard-pref-grid {
    grid-template-columns: 1fr;
    gap: 12px;
  }
  .wizard-pref-card {
    padding: 16px 14px;
  }
  .wizard-pref-selector__btn {
    padding: 10px 4px;
    font-size: 0.7rem;
  }
  .wizard-pref-factors__list {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px 12px;
  }

  /* S6 — tall desktop cards become compact horizontal rows (per spec's
     mobile variant of S6-vysledok.png) — same "flex-direction switch on
     the same markup, no separate mobile DOM" technique .wizard-card above
     already uses. Detailed param list is dropped here (per spec, priority
     is model/price/rating/CTA/image). */
  .wizard-result-header {
    flex-direction: column;
    align-items: stretch;
  }
  .wizard-result-all-btn {
    justify-content: center;
  }

  .wizard-result-grid {
    grid-template-columns: 1fr;
    gap: 12px;
  }

  .wizard-result-card {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    padding: 14px;
    gap: 4px 12px;
  }
  .wizard-result-card__header {
    flex: 1 0 100%;
    order: 0;
    margin-bottom: 4px;
    min-height: 0;
  }
  /* Unwraps .wizard-result-card__middle (display: contents) so
     __media/__params go back to being direct flex items of the row-flex
     .wizard-result-card above, exactly like before the desktop
     media+specs split existed — same order/flex overrides below still
     apply unchanged. */
  .wizard-result-card__middle {
    display: contents;
  }
  .wizard-result-card__media {
    order: 1;
    flex: 0 0 auto;
    width: 64px;
    height: 64px;
    margin-left: 0;
    justify-content: center;
    overflow: visible;
  }
  /* Desktop's image->specs fade doesn't apply to this tiny thumbnail-sized
     image — specs are hidden on mobile anyway (below). */
  .wizard-result-card__media::after {
    content: none;
  }
  .wizard-result-card__info {
    order: 2;
    flex: 1 1 auto;
    min-width: 0;
    margin-bottom: 0;
  }
  .wizard-result-card__model {
    font-size: 0.95rem;
    margin-bottom: 4px;
  }
  .wizard-result-card__params {
    display: none;
  }
  .wizard-result-card__footer {
    order: 3;
    flex: 1 0 100%;
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    margin-top: 8px;
    padding-top: 12px;
    border-top: 1px solid var(--wizard-border);
  }
  .wizard-result-card__price {
    font-size: 1.05rem;
  }
  .wizard-result-card__cta {
    width: auto;
    padding: 10px 16px;
    font-size: 0.82rem;
  }
}
