/* ============================================================
   Zdorovo Dental — Universal Service Page
   VISUAL PASS (round 2 — hero appearance + new block controls)

   Loads AFTER assets/css/zd-blocks.css (the structural layer).
   It only RESTYLES the classes the WP markup already emits — no
   class/field renames, no new required markup. Every rule below
   maps to a class in the DESIGN_REQUEST contract.

   Brand tokens come from zd-blocks.css :root
   (--zd-accent #1BAE70, --zd-tint, --ink-*, --font-*, --radius-*).

   ⚑ MARKUP ADDITIONS FLAGGED FOR THE WP TEAM: none.
     The benefit "badge" disc is painted on the icon-library <svg>
     itself (it is the direct child of .zd-hero__benefit),
     so no wrapper element is needed and the PHP stays as-is.
   ============================================================ */

/* ============================================================
   1a. HERO BENEFITS CHECKLIST — hero_benefits only.
   The row treatment is BASED ON the intro module's list, but the
   intro module (.zd-prose li) is a SEPARATE component and is NOT
   touched here — it keeps its own structural styling.
   Reference: a soft green DISC with the tick centred inside.
   ============================================================ */
.zd-hero__benefits {
  margin: 24px 0 0;
  gap: 14px;
  max-width: 520px;
}
.zd-hero__benefit {
  align-items: center;
  gap: 13px;
  font-size: 16.5px;
  line-height: 1.45;
  font-weight: 500;
  color: var(--ink-700);
}

/* The badge: the marker <svg> becomes a circled tick.
   Icon-library SVGs carry a viewBox but no width/height, so the
   box + look are set here (sizing them in CSS is mandatory). */
.zd-hero__benefit svg {
  flex: none;
  box-sizing: border-box;
  width: 28px;
  height: 28px;
  margin-top: 0;
  padding: 5px;
  border-radius: 50%;
  background: var(--zd-tint-2);           /* soft green disc */
  color: var(--zd-accent-strong);         /* tick colour */
  stroke-width: 2.4;                       /* crisper tick inside the disc */
  box-shadow: inset 0 0 0 1px rgba(27,174,112,.12);
}

/* Dark hero variants (v2 / v3): translucent disc that stays legible
   over the photo + scrim without fighting it. */
.zd-hero__benefits--light .zd-hero__benefit {
  color: rgba(255,255,255,.92);
}
.zd-hero__benefits--light .zd-hero__benefit svg {
  background: rgba(255,255,255,.16);
  color: #fff;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,.22);
}

/* ============================================================
   1c. STAT CARDS (.zd-stat, light v1) + CHIPS (.zd-hero__chip, dark)
   Reference: compact rounded pills — bold value, muted label.
   ============================================================ */
.zd-stat {
  min-height: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
  padding: 15px 18px;
  background: #fff;
  border: 1px solid var(--border-tint, #dcece3);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
}
.zd-stat__num {
  font-size: 27px;
}
.zd-stat__label {
  margin-top: 0;
  font-size: 12.5px;
  color: var(--ink-500);
}

/* Dark chips: tighter pill, value + label on one baseline. */
.zd-hero__chip {
  gap: 9px;
  padding: 11px 17px;
  border-radius: var(--radius-pill);
  background: rgba(255,255,255,.1);
  border-color: rgba(255,255,255,.2);
}
.zd-hero__chip b { font-size: 22px; }
.zd-hero__chip span { font-size: 12.5px; letter-spacing: .01em; }

/* ============================================================
   1b. STATS BAND (.zd-hero__band, hero_stats_pos = band)
   A designed full-width strip pinned to the hero's bottom edge.
   --hasband mechanism (row→column flip + scroll-cue hide) lives
   in the structural layer and is PRESERVED untouched.
   ============================================================ */
.zd-hero__band {
  border-top: 1px solid var(--border-tint, #dcece3);
  background: linear-gradient(180deg, rgba(255,255,255,.55), rgba(235,247,240,.75));
  backdrop-filter: blur(4px);
}
.zd-hero__band-item {
  position: relative;
  padding: 4px 4px 4px 22px;
}
/* Hairline dividers between columns (desktop = one auto-fit row). */
.zd-hero__band-item::before {
  content: "";
  position: absolute;
  left: 0; top: 50%;
  transform: translateY(-50%);
  width: 3px; height: 34px;
  border-radius: 3px;
  background: var(--zd-accent);
  opacity: .8;
}
.zd-hero__band-item b { font-size: 28px; }
.zd-hero__band-item span { font-size: 13px; }

/* Dark band: glass strip over the photo. */
.zd-hero__band--light {
  border-top-color: rgba(255,255,255,.16);
  background: rgba(9,26,17,.5);
  backdrop-filter: blur(10px);
}
.zd-hero__band--light .zd-hero__band-item::before { background: var(--green-300); opacity: .9; }

/* ============================================================
   1d. HERO PROPORTIONS + VERTICAL RHYTHM
   Full stack = eyebrow → H1 → lead → benefits → CTAs → stats.
   Give the copy column a sane measure and steady rhythm.
   ============================================================ */
.zd-hero__lead { max-width: 540px; margin-top: 18px; }
.zd-hero__bg-copy .zd-hero__lead { max-width: 560px; }
/* Slightly tighter gaps than the default 44px hero padding when the
   band is present, so the tall stack doesn't feel loose. */
.zd-hero--hasband .zd-hero__inner { padding-top: 40px; }

@media (min-width: 920px) {
  /* Split hero: copy left, media right, aligned to top so a long
     stack doesn't drag the photo down-centre. */
  .zd-hero__inner {
    grid-template-columns: 1.06fr .94fr;
    gap: 52px;
    align-items: start;
    padding: 60px 0 66px;
  }
  .zd-hero__stats { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
  /* keep the photo visually centred against the copy block */
  .zd-hero__media { align-self: center; }
}

/* ============================================================
   2. TILE GRID — .zd-grid--1 (new single-column count)
   A lone full-width tile would look stranded; lay it out
   horizontally (icon/head left, body right) and cap its width.
   ============================================================ */
@media (min-width: 720px) {
  .zd-grid--1 { max-width: 860px; margin-inline: auto; }
  .zd-grid--1 .zd-tile {
    display: grid;
    grid-template-columns: auto 1fr;
    column-gap: 28px;
    align-items: start;
    padding: 30px 34px;
  }
  .zd-grid--1 .zd-tile::after { height: 100%; width: 3px; } /* accent runs down the side */
  .zd-grid--1 .zd-tile__head { grid-column: 1; grid-row: 1 / span 3; margin-bottom: 0; }
  /* badge rides top-right, on the title's line */
  .zd-grid--1 .zd-tile__badge { position: absolute; top: 32px; right: 34px; margin: 0; }
  .zd-grid--1 .zd-tile__title,
  .zd-grid--1 .zd-tile__meta,
  .zd-grid--1 .zd-tile__text,
  .zd-grid--1 .zd-tile__list,
  .zd-grid--1 .zd-tile__more { grid-column: 2; }
  .zd-grid--1 .zd-tile__title { margin-top: 2px; }
}

/* Below the horizontal layout the structural mobile rule turns the tile into a
   cramped icon+title grid, which crowds the badge against the icon. Keep the
   lone tile as a simple stacked card: icon left, badge far right on one row. */
@media (max-width: 719px) {
  .zd-grid--1 .zd-tile:not(.zd-tile--sys) {
    display: flex;
    flex-direction: column;
    align-items: stretch;
  }
  .zd-grid--1 .zd-tile:not(.zd-tile--sys) .zd-tile__head { margin-bottom: 24px; }
  .zd-grid--1 .zd-tile__badge { margin-left: auto; }
}

/* ============================================================
   2. DOCTORS — .zd-docs--1 (new single-column count)
   A single doctor card goes horizontal so it reads deliberately
   instead of a giant lonely portrait. (--2/--3/--4 keep the grid.)
   ============================================================ */
@media (min-width: 720px) {
  .zd-docs--1 { max-width: 820px; margin-inline: auto; }
  .zd-docs--1 .zd-doc {
    flex-direction: row;
    align-items: stretch;
  }
  .zd-docs--1 .zd-doc__photo {
    flex: 0 0 240px;
    aspect-ratio: auto;
    min-height: 100%;
  }
  .zd-docs--1 .zd-doc__body {
    flex: 1;
    padding: 28px 30px;
    justify-content: center;
  }
}

/* ============================================================
   2. BEFORE / AFTER CASE CTA — .zd-ba__cta
   Now Google review OR a custom CTA (ghost/primary/secondary +
   optional library icon) OR none. Style the custom variants;
   the Google one keeps its "G" mark.
   ============================================================ */
/* The left half shows the AFTER image (clip), the right half the BEFORE image.
   The shipped CSS labels them the wrong way round (before tag on the left, hidden
   under the clip until fully swapped). Swap each tag to its own image's side,
   still inside its layer so it tracks/reveals with that image. */
.zd-ba__tag--before { left: auto; right: 12px; }
.zd-ba__tag--after { left: 12px; right: auto; }

/* Keep the button pinned to the card bottom (structural margin-top:auto), so it
   sits at the bottom regardless of case text. Guarantee a gap above it even when
   the details fill the card by spacing the content block off the button. */
.zd-ba__meta > .zd-ba__cta {
  margin-top: auto;
}
.zd-ba__meta dl,
.zd-ba__meta-desc:last-child {
  margin-bottom: 22px;
}
/* Icon-library SVG inside a custom CTA — size it (viewBox only). */
.zd-ba__cta svg { flex: none; width: 16px; height: 16px; }
/* The Google "G" is an <img>; keep it crisp and aligned. */
.zd-ba__cta img { flex: none; width: 15px; height: 15px; }
/* Ghost variant gets a hairline so a lone review link still reads
   as a button, not a floating text link. */
.zd-ba__cta.zd-btn--ghost {
  border-color: var(--border-tint, #dcece3);
  background: #fff;
}
.zd-ba__cta.zd-btn--ghost:hover {
  border-color: var(--zd-accent);
  background: var(--zd-tint);
}

/* When a band occupies the bottom edge, the promo disc (pinned bottom-right on
   the dark variants) collides with it — move it up to the top corner instead. */
.zd-hero--bg.zd-hero--hasband .zd-badge-promo,
.zd-hero--full.zd-hero--hasband .zd-badge-promo {
  top: 24px;
  bottom: auto;
  right: 24px;
}

/* --hasband stacks the dark hero as a flex COLUMN (copy → band → scroll cue) and centres
   the lot, which leaves the band floating mid-hero with dead space under it. Let the copy
   take the slack instead: the container grows and centres its own content, so the band
   (and the cue after it) settle at the bottom edge where they belong. */
.zd-hero--bg.zd-hero--hasband,
.zd-hero--full.zd-hero--hasband {
  /* NOT justify-content:center. The column (copy + band + cue) can exceed 100vh, and a
     centred flex column overflows at BOTH ends — .zd-hero has overflow:hidden, so the
     cue below the band gets silently clipped away. Stack from the top and let the copy
     container absorb the slack instead; the hero's min-height still grows to fit. */
  justify-content: flex-start;
}
.zd-hero--bg.zd-hero--hasband > .zd-container,
.zd-hero--full.zd-hero--hasband > .zd-container {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
}

/* Keep the v3 scroll cue when a band is present, but put it BELOW the stats, at the
   very bottom of the hero. It normally floats (position:absolute, bottom:22px), which
   over a band means it overlaps the strip — and any fixed offset only works for one
   band height. --hasband already makes the hero a flex COLUMN and the template emits
   the cue after the band, so dropping it into the flow lands it in the right place by
   itself, whatever the band ends up being. */
.zd-hero--full.zd-hero--hasband .zd-hero__scroll {
  display: inline-flex;
  /* relative, NOT static: .zd-hero__bg and .zd-hero__scrim are absolutely positioned, so
     they paint above every non-positioned element — a static cue renders in the right
     place but BEHIND the photo. Staying positioned (with a z-index, like .zd-container
     and .zd-hero__band already have) keeps it on top while still sitting in the flow. */
  position: relative;
  z-index: 2;
  left: auto;
  bottom: auto;
  transform: none;
  align-self: center;
  margin: 16px 0 24px;
}

/* ============================================================
   1b-ALT. STATS BAND — exploration options for the dark heroes
   (v2/v3). Add ONE modifier class alongside .zd-hero__band--light.
   The demo bar toggles them; pick a winner and drop the rest.
   Default (no modifier) = the glass strip already shipped.
   ============================================================ */

/* A · CARD — the band lifts off the bottom edge as a floating,
   rounded glass card instead of a full-bleed strip. */
.zd-hero__band--x-card {
  border-top: 0;
  background: transparent;
  backdrop-filter: none;
}
.zd-hero__band--x-card .zd-hero__band-items {
  margin-bottom: 26px;
  padding: 20px 30px;
  border-radius: var(--radius-lg);
  background: rgba(9,26,17,.55);
  backdrop-filter: blur(12px);
  border: 1px solid rgba(255,255,255,.16);
  box-shadow: var(--shadow-lg);
}

/* B · CELLS — each stat is its own glass tile with gaps between,
   no continuous bar. Reads as a row of chips. */
.zd-hero__band--x-cells {
  border-top: 0;
  background: transparent;
  backdrop-filter: none;
  padding-bottom: 24px;
}
.zd-hero__band--x-cells .zd-hero__band-items { gap: 12px; padding-top: 0; }
.zd-hero__band--x-cells .zd-hero__band-item {
  padding: 15px 20px;
  border-radius: var(--radius-md);
  background: rgba(255,255,255,.1);
  border: 1px solid rgba(255,255,255,.16);
  backdrop-filter: blur(8px);
}
.zd-hero__band--x-cells .zd-hero__band-item::before { display: none; }

/* C · SOLID — an opaque brand-green ribbon; numbers pop in white. */
.zd-hero__band--x-solid {
  border-top: 0;
  background: linear-gradient(90deg, var(--green-700), var(--green-600));
  backdrop-filter: none;
  box-shadow: 0 -8px 24px rgba(9,26,17,.35);
}
.zd-hero__band--x-solid .zd-hero__band-item::before { background: rgba(255,255,255,.4); height: 30px; opacity: 1; }
.zd-hero__band--x-solid .zd-hero__band-item b { color: #fff; }
.zd-hero__band--x-solid .zd-hero__band-item span { color: rgba(255,255,255,.85); }

/* D · UNDERLINE — no surface at all; numbers sit straight on the
   photo, separated by a thin rule under each value. */
.zd-hero__band--x-underline {
  border-top: 0;
  background: transparent;
  backdrop-filter: none;
  padding-bottom: 26px;
}
.zd-hero__band--x-underline .zd-hero__band-item { padding-left: 0; padding-bottom: 12px; border-bottom: 2px solid rgba(255,255,255,.28); }
.zd-hero__band--x-underline .zd-hero__band-item::before { display: none; }
.zd-hero__band--x-underline .zd-hero__band-item b { font-size: 32px; }

/* ============================================================
   5a. TABLET/MOBILE — v3 full-screen must not force 100vh, or the
   copy is dumped into a huge empty band. Let content set the height.
   ============================================================ */
@media (max-width: 919px) {
  .zd-hero--full { min-height: 0; }
  .zd-hero--full.zd-hero--hasband { justify-content: flex-start; }
  .zd-hero--full .zd-hero__bg-copy { padding: 44px 0 36px; }
  /* scroll cue is pointless once the hero is content-height. The --hasband variant needs
     naming explicitly: its rule above is (0,3,0) and a media query adds no specificity,
     so a plain .zd-hero--full selector here would silently lose to it. */
  .zd-hero--full .zd-hero__scroll,
  .zd-hero--full.zd-hero--hasband .zd-hero__scroll { display: none; }
  /* before/after stacks to two rows (viewer over meta) on tablet + below */
  .zd-ba-grid { grid-template-columns: 1fr; }
}

/* ============================================================
   5. ≤600px — full hero stack must hold up
   ============================================================ */
@media (max-width: 600px) {
  .zd-hero__inner { padding: 30px 0 36px; gap: 22px; }
  .zd-hero__h1 { font-size: clamp(28px, 8vw, 34px); }
  .zd-hero__lead { font-size: 15.5px; }
  .zd-hero__benefits { gap: 12px; max-width: none; }
  .zd-hero__benefit { font-size: 15.5px; }
  .zd-hero__benefit svg { width: 26px; height: 26px; }
  .zd-hero__actions { gap: 10px; }
  .zd-hero__actions .zd-btn { flex: 1 1 100%; }         /* full-width CTAs */
  /* stats: 2-up cards / chips stay readable */
  .zd-hero__stats { grid-template-columns: repeat(2, minmax(0,1fr)); }
  .zd-stat__num { font-size: 22px; }
  /* band: 2-col grid, drop the accent bars so the columns breathe */
  .zd-hero__band-items { grid-template-columns: repeat(2, 1fr); gap: 14px 18px; padding: 16px 0; }
  .zd-hero__band-item { padding-left: 0; }
  .zd-hero__band-item::before { display: none; }
  .zd-hero__band-item b { font-size: 22px; }
  /* dark copy pane a touch tighter */
  .zd-hero__bg-copy { padding: 40px 0; }
  /* v2/v3: the promo disc becomes an inline pill in the flow (no overlap).
     Force the dark hero to a column so the static badge stacks above the copy. */
  .zd-hero--bg,
  .zd-hero--full { flex-direction: column; align-items: stretch; }
  .zd-hero--bg .zd-badge-promo,
  .zd-hero--full .zd-badge-promo,
  .zd-hero--bg.zd-hero--hasband .zd-badge-promo,
  .zd-hero--full.zd-hero--hasband .zd-badge-promo {
    order: -1;
    position: static;
    width: auto; height: auto;
    flex-direction: row;
    align-items: baseline;
    gap: 6px;
    align-self: flex-start;
    margin: 20px 20px 0;
    padding: 7px 14px;
    border-radius: var(--radius-pill);
    transform: none;
    box-shadow: none;
  }
  .zd-hero--bg .zd-badge-promo__big,
  .zd-hero--full .zd-badge-promo__big { font-size: 16px; }
  .zd-hero--bg .zd-badge-promo__small,
  .zd-hero--full .zd-badge-promo__small { font-size: 10px; margin-top: 0; }
  /* no reserved top padding needed anymore */
  .zd-hero--bg .zd-hero__bg-copy,
  .zd-hero--full .zd-hero__bg-copy { padding-top: 12px; }
}


/* ============================================================
   TILE-ROW EXPANDER — tile_grid · field tiles_rows (1|2|3|all)
   ------------------------------------------------------------
   CONTRACT (already fixed by the team — mirrored, not renamed):
     <div class="zd-grid zd-grid--4 zd-grid--rows-2"> … every
        <article class="zd-tile"> always rendered … </div>
     <button class="zd-grid__more" type="button"
             aria-expanded="false" aria-controls="…">…</button>
   Expanding adds .is-expanded to the grid (drops the cap) and
   flips aria-expanded on the button.

   WHY PURE CSS PER BREAKPOINT: the grid re-columns (1/2/2, 1/2/3,
   1/2/4), so "N rows" is a different tile count at each width and
   PHP cannot slice it. Every tile is rendered; overflow rows are
   display:none per breakpoint band. Bands are BOUNDED and mutually
   exclusive (≤599 / 600–919 / ≥920) so no rule ever has to "un-
   hide" — each band states its own hidden set outright.

   Hidden index X = rows × columns + 1  (first tile past the cap).
   The SAME index drives the button's visibility: the button only
   shows when the grid actually has a tile at X — so at a width
   where the tiles already fill the cap, the button is absent
   (present at some widths, gone at others on the same page).

   display:none (not opacity/height) keeps hidden tiles and their
   "Детальніше" links out of the tab order.

   DESIGN DECISIONS (see CODE_HANDOFF.md):
   1. Ghost pill, centred under the grid (mirrors .zd-docs__all).
   2. Clean cut edge — NO gradient scrim. Over a grid of shadowed
      cards with a gutter, a scrim reads as dirt on the last row;
      the gutter already draws the row boundary and the button is
      the "there is more" signal.
   3. Two-way toggle: "Показати всі" ⇄ "Згорнути" (label swapped by
      aria-expanded, both strings gettext-translatable — no JS text).
   4. No animated height (that is the CLS offender — it needs a
      measured target). Reveal is instant; only the freshly-shown
      tiles get a cheap in-place fade (no layout measuring), and
      the chevron rotates.
   5. Count-free label — dodges Ukrainian's three plural forms.
   ============================================================ */

/* Overflow rows are hidden until expanded. Bands are exclusive.

   WP ADDITION — the whole hiding block is gated on :has() support. The button that
   reveals these rows is itself shown by a :has() rule, so in a browser without :has()
   the tiles would be hidden with NO way to reach them: silent content loss on a page
   whose tiles are real services. Gating the cap means such a browser simply shows every
   tile and no button — degraded, but nothing is ever unreachable. */
@supports (selector(:has(*))) {

/* -- Band A: ≤599px — every grid is 1 column -- */
@media (max-width: 599px) {
  .zd-grid--rows-1:not(.is-expanded) .zd-tile:nth-child(n+2),
  .zd-grid--rows-2:not(.is-expanded) .zd-tile:nth-child(n+3),
  .zd-grid--rows-3:not(.is-expanded) .zd-tile:nth-child(n+4) { display: none; }
}
/* -- Band B: 600–919px — --1 = 1 col, --2/--3/--4 = 2 cols -- */
@media (min-width: 600px) and (max-width: 919px) {
  .zd-grid--1.zd-grid--rows-1:not(.is-expanded) .zd-tile:nth-child(n+2),
  .zd-grid--1.zd-grid--rows-2:not(.is-expanded) .zd-tile:nth-child(n+3),
  .zd-grid--1.zd-grid--rows-3:not(.is-expanded) .zd-tile:nth-child(n+4),
  .zd-grid--2.zd-grid--rows-1:not(.is-expanded) .zd-tile:nth-child(n+3),
  .zd-grid--3.zd-grid--rows-1:not(.is-expanded) .zd-tile:nth-child(n+3),
  .zd-grid--4.zd-grid--rows-1:not(.is-expanded) .zd-tile:nth-child(n+3),
  .zd-grid--2.zd-grid--rows-2:not(.is-expanded) .zd-tile:nth-child(n+5),
  .zd-grid--3.zd-grid--rows-2:not(.is-expanded) .zd-tile:nth-child(n+5),
  .zd-grid--4.zd-grid--rows-2:not(.is-expanded) .zd-tile:nth-child(n+5),
  .zd-grid--2.zd-grid--rows-3:not(.is-expanded) .zd-tile:nth-child(n+7),
  .zd-grid--3.zd-grid--rows-3:not(.is-expanded) .zd-tile:nth-child(n+7),
  .zd-grid--4.zd-grid--rows-3:not(.is-expanded) .zd-tile:nth-child(n+7) { display: none; }
}
/* -- Band C: ≥920px — --1=1, --2=2, --3=3, --4=4 cols -- */
@media (min-width: 920px) {
  .zd-grid--1.zd-grid--rows-1:not(.is-expanded) .zd-tile:nth-child(n+2),
  .zd-grid--1.zd-grid--rows-2:not(.is-expanded) .zd-tile:nth-child(n+3),
  .zd-grid--1.zd-grid--rows-3:not(.is-expanded) .zd-tile:nth-child(n+4),
  .zd-grid--2.zd-grid--rows-1:not(.is-expanded) .zd-tile:nth-child(n+3),
  .zd-grid--2.zd-grid--rows-2:not(.is-expanded) .zd-tile:nth-child(n+5),
  .zd-grid--2.zd-grid--rows-3:not(.is-expanded) .zd-tile:nth-child(n+7),
  .zd-grid--3.zd-grid--rows-1:not(.is-expanded) .zd-tile:nth-child(n+4),
  .zd-grid--3.zd-grid--rows-2:not(.is-expanded) .zd-tile:nth-child(n+7),
  .zd-grid--3.zd-grid--rows-3:not(.is-expanded) .zd-tile:nth-child(n+10),
  .zd-grid--4.zd-grid--rows-1:not(.is-expanded) .zd-tile:nth-child(n+5),
  .zd-grid--4.zd-grid--rows-2:not(.is-expanded) .zd-tile:nth-child(n+9),
  .zd-grid--4.zd-grid--rows-3:not(.is-expanded) .zd-tile:nth-child(n+13) { display: none; }
}

} /* /@supports (selector(:has(*))) — end of the row-cap block */

/* THE BUTTON — hidden by default; each band shows it ONLY when the
   preceding grid still has a tile past the cap (:has at the same X).
   Independent of .is-expanded, so it stays as the "Згорнути" toggle. */
.zd-grid__more { display: none; }
@media (max-width: 599px) {
  .zd-grid--rows-1:has(.zd-tile:nth-child(n+2)) + .zd-grid__more,
  .zd-grid--rows-2:has(.zd-tile:nth-child(n+3)) + .zd-grid__more,
  .zd-grid--rows-3:has(.zd-tile:nth-child(n+4)) + .zd-grid__more { display: flex; }
}
@media (min-width: 600px) and (max-width: 919px) {
  .zd-grid--1.zd-grid--rows-1:has(.zd-tile:nth-child(n+2)) + .zd-grid__more,
  .zd-grid--1.zd-grid--rows-2:has(.zd-tile:nth-child(n+3)) + .zd-grid__more,
  .zd-grid--1.zd-grid--rows-3:has(.zd-tile:nth-child(n+4)) + .zd-grid__more,
  .zd-grid--2.zd-grid--rows-1:has(.zd-tile:nth-child(n+3)) + .zd-grid__more,
  .zd-grid--3.zd-grid--rows-1:has(.zd-tile:nth-child(n+3)) + .zd-grid__more,
  .zd-grid--4.zd-grid--rows-1:has(.zd-tile:nth-child(n+3)) + .zd-grid__more,
  .zd-grid--2.zd-grid--rows-2:has(.zd-tile:nth-child(n+5)) + .zd-grid__more,
  .zd-grid--3.zd-grid--rows-2:has(.zd-tile:nth-child(n+5)) + .zd-grid__more,
  .zd-grid--4.zd-grid--rows-2:has(.zd-tile:nth-child(n+5)) + .zd-grid__more,
  .zd-grid--2.zd-grid--rows-3:has(.zd-tile:nth-child(n+7)) + .zd-grid__more,
  .zd-grid--3.zd-grid--rows-3:has(.zd-tile:nth-child(n+7)) + .zd-grid__more,
  .zd-grid--4.zd-grid--rows-3:has(.zd-tile:nth-child(n+7)) + .zd-grid__more { display: flex; }
}
@media (min-width: 920px) {
  .zd-grid--1.zd-grid--rows-1:has(.zd-tile:nth-child(n+2)) + .zd-grid__more,
  .zd-grid--1.zd-grid--rows-2:has(.zd-tile:nth-child(n+3)) + .zd-grid__more,
  .zd-grid--1.zd-grid--rows-3:has(.zd-tile:nth-child(n+4)) + .zd-grid__more,
  .zd-grid--2.zd-grid--rows-1:has(.zd-tile:nth-child(n+3)) + .zd-grid__more,
  .zd-grid--2.zd-grid--rows-2:has(.zd-tile:nth-child(n+5)) + .zd-grid__more,
  .zd-grid--2.zd-grid--rows-3:has(.zd-tile:nth-child(n+7)) + .zd-grid__more,
  .zd-grid--3.zd-grid--rows-1:has(.zd-tile:nth-child(n+4)) + .zd-grid__more,
  .zd-grid--3.zd-grid--rows-2:has(.zd-tile:nth-child(n+7)) + .zd-grid__more,
  .zd-grid--3.zd-grid--rows-3:has(.zd-tile:nth-child(n+10)) + .zd-grid__more,
  .zd-grid--4.zd-grid--rows-1:has(.zd-tile:nth-child(n+5)) + .zd-grid__more,
  .zd-grid--4.zd-grid--rows-2:has(.zd-tile:nth-child(n+9)) + .zd-grid__more,
  .zd-grid--4.zd-grid--rows-3:has(.zd-tile:nth-child(n+13)) + .zd-grid__more { display: flex; }
}

/* Button look — ghost pill, centred (mirrors .zd-docs__all rhythm).
   Astra styles bare <button>:hover/:focus, so the paint props carry
   !important exactly like .zd-cs__step-title / .zd-cs__nav-btn. */
.zd-grid__more {
  width: fit-content;
  margin: 26px auto 0;
  -webkit-appearance: none; appearance: none;
  align-items: center; justify-content: center; gap: 9px;
  padding: 12px 24px;
  background: var(--surface) !important;
  color: var(--zd-accent-strong) !important;
  border: 1.5px solid var(--zd-line) !important;
  border-radius: var(--radius-pill) !important;
  font: 700 15px/1 var(--font-sans) !important;
  cursor: pointer;
  transition: background .18s var(--ease-out), border-color .18s var(--ease-out), color .18s var(--ease-out), transform .18s var(--ease-out), box-shadow .18s var(--ease-out);
}
.zd-grid__more:hover {
  background: var(--zd-tint) !important;
  color: var(--zd-accent-deep) !important;
  border-color: var(--zd-accent) !important;
  transform: translateY(-1px);
  box-shadow: var(--shadow-sm);
}
.zd-grid__more:active { transform: scale(.98); }
.zd-grid__more:focus-visible { outline: 3px solid rgba(27,174,112,.4); outline-offset: 2px; }
.zd-grid__more svg { width: 16px; height: 16px; flex: none; transition: transform .2s var(--ease-out); }
.zd-grid__more[aria-expanded="true"] svg { transform: rotate(180deg); }
/* label swap — no JS text, both strings translatable via gettext */
.zd-grid__more .zd-grid__more-less { display: none; }
.zd-grid__more[aria-expanded="true"] .zd-grid__more-more { display: none; }
.zd-grid__more[aria-expanded="true"] .zd-grid__more-less { display: inline; }

/* Reveal — instant reflow (no measured height animation → no CLS);
   only the tiles that were hidden fade in place. The same per-band
   index sets are reused so ALREADY-visible tiles never re-animate.
   No fill-mode: after the fade the normal cascade (incl. :hover
   lift) takes back over. */
@media (prefers-reduced-motion: no-preference) {
  @keyframes zd-tile-reveal { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
  @media (max-width: 599px) {
    .zd-grid--rows-1.is-expanded .zd-tile:nth-child(n+2),
    .zd-grid--rows-2.is-expanded .zd-tile:nth-child(n+3),
    .zd-grid--rows-3.is-expanded .zd-tile:nth-child(n+4) { animation: zd-tile-reveal .32s var(--ease-out); }
  }
  @media (min-width: 600px) and (max-width: 919px) {
    .zd-grid--1.zd-grid--rows-1.is-expanded .zd-tile:nth-child(n+2),
    .zd-grid--1.zd-grid--rows-2.is-expanded .zd-tile:nth-child(n+3),
    .zd-grid--1.zd-grid--rows-3.is-expanded .zd-tile:nth-child(n+4),
    .zd-grid--2.zd-grid--rows-1.is-expanded .zd-tile:nth-child(n+3),
    .zd-grid--3.zd-grid--rows-1.is-expanded .zd-tile:nth-child(n+3),
    .zd-grid--4.zd-grid--rows-1.is-expanded .zd-tile:nth-child(n+3),
    .zd-grid--2.zd-grid--rows-2.is-expanded .zd-tile:nth-child(n+5),
    .zd-grid--3.zd-grid--rows-2.is-expanded .zd-tile:nth-child(n+5),
    .zd-grid--4.zd-grid--rows-2.is-expanded .zd-tile:nth-child(n+5),
    .zd-grid--2.zd-grid--rows-3.is-expanded .zd-tile:nth-child(n+7),
    .zd-grid--3.zd-grid--rows-3.is-expanded .zd-tile:nth-child(n+7),
    .zd-grid--4.zd-grid--rows-3.is-expanded .zd-tile:nth-child(n+7) { animation: zd-tile-reveal .32s var(--ease-out); }
  }
  @media (min-width: 920px) {
    .zd-grid--1.zd-grid--rows-1.is-expanded .zd-tile:nth-child(n+2),
    .zd-grid--1.zd-grid--rows-2.is-expanded .zd-tile:nth-child(n+3),
    .zd-grid--1.zd-grid--rows-3.is-expanded .zd-tile:nth-child(n+4),
    .zd-grid--2.zd-grid--rows-1.is-expanded .zd-tile:nth-child(n+3),
    .zd-grid--2.zd-grid--rows-2.is-expanded .zd-tile:nth-child(n+5),
    .zd-grid--2.zd-grid--rows-3.is-expanded .zd-tile:nth-child(n+7),
    .zd-grid--3.zd-grid--rows-1.is-expanded .zd-tile:nth-child(n+4),
    .zd-grid--3.zd-grid--rows-2.is-expanded .zd-tile:nth-child(n+7),
    .zd-grid--3.zd-grid--rows-3.is-expanded .zd-tile:nth-child(n+10),
    .zd-grid--4.zd-grid--rows-1.is-expanded .zd-tile:nth-child(n+5),
    .zd-grid--4.zd-grid--rows-2.is-expanded .zd-tile:nth-child(n+9),
    .zd-grid--4.zd-grid--rows-3.is-expanded .zd-tile:nth-child(n+13) { animation: zd-tile-reveal .32s var(--ease-out); }
  }
}


/* ============================================================
   STAGES COLUMNS + ROW EXPANDER — module-stages.php
     fields stages_columns (1|2|3|4) · stages_rows (1|2|3|all)
   ------------------------------------------------------------
   Mirrors the TILE-ROW EXPANDER above bit-for-bit: same 3 bands
   (≤599 / 600–919 / ≥920) and the same "hidden index = rows×cols
   + 1". The .zd-stages grid re-columns exactly like .zd-grid, so
   every per-band nth-child cap number is identical — only the
   class names differ (.zd-stages / .zd-stage / .zd-stages__more).
   The button also carries .zd-grid__more, so its paint, chevron,
   label-swap and JS handler are inherited here, not duplicated.

   Legacy stages carry no --N modifier (older cached HTML); the
   unconditional .zd-stages rules in zd-blocks.css keep those at
   the original 1/2/4 layout. New output always emits --4 by
   default, which reproduces that same 1/2/4 — so nothing shifts.
   ============================================================ */

/* Columns — restated per band. Written as .zd-stages.zd-stages--N (two classes)
   so they always outweigh the plain .zd-stages 1/2/4 fallback in zd-blocks.css,
   independent of stylesheet load order. */
.zd-stages.zd-stages--1, .zd-stages.zd-stages--2,
.zd-stages.zd-stages--3, .zd-stages.zd-stages--4 { grid-template-columns: 1fr; }
@media (min-width: 600px) {
  .zd-stages.zd-stages--1 { grid-template-columns: 1fr; }
  .zd-stages.zd-stages--2,
  .zd-stages.zd-stages--3,
  .zd-stages.zd-stages--4 { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 920px) {
  .zd-stages.zd-stages--1 { grid-template-columns: 1fr; }
  .zd-stages.zd-stages--2 { grid-template-columns: repeat(2, 1fr); }
  .zd-stages.zd-stages--3 { grid-template-columns: repeat(3, 1fr); }
  .zd-stages.zd-stages--4 { grid-template-columns: repeat(4, 1fr); }
}

/* Overflow rows hidden until expanded — gated on :has() exactly like the tiles
   block, so a browser without :has() shows every stage and no button (it never
   hides content it cannot reveal). Bands are bounded and mutually exclusive. */
@supports (selector(:has(*))) {
/* -- Band A: ≤599px — every grid is 1 column -- */
@media (max-width: 599px) {
  .zd-stages--rows-1:not(.is-expanded) .zd-stage:nth-child(n+2),
  .zd-stages--rows-2:not(.is-expanded) .zd-stage:nth-child(n+3),
  .zd-stages--rows-3:not(.is-expanded) .zd-stage:nth-child(n+4) { display: none; }
}
/* -- Band B: 600–919px — --1 = 1 col, --2/--3/--4 = 2 cols -- */
@media (min-width: 600px) and (max-width: 919px) {
  .zd-stages--1.zd-stages--rows-1:not(.is-expanded) .zd-stage:nth-child(n+2),
  .zd-stages--1.zd-stages--rows-2:not(.is-expanded) .zd-stage:nth-child(n+3),
  .zd-stages--1.zd-stages--rows-3:not(.is-expanded) .zd-stage:nth-child(n+4),
  .zd-stages--2.zd-stages--rows-1:not(.is-expanded) .zd-stage:nth-child(n+3),
  .zd-stages--3.zd-stages--rows-1:not(.is-expanded) .zd-stage:nth-child(n+3),
  .zd-stages--4.zd-stages--rows-1:not(.is-expanded) .zd-stage:nth-child(n+3),
  .zd-stages--2.zd-stages--rows-2:not(.is-expanded) .zd-stage:nth-child(n+5),
  .zd-stages--3.zd-stages--rows-2:not(.is-expanded) .zd-stage:nth-child(n+5),
  .zd-stages--4.zd-stages--rows-2:not(.is-expanded) .zd-stage:nth-child(n+5),
  .zd-stages--2.zd-stages--rows-3:not(.is-expanded) .zd-stage:nth-child(n+7),
  .zd-stages--3.zd-stages--rows-3:not(.is-expanded) .zd-stage:nth-child(n+7),
  .zd-stages--4.zd-stages--rows-3:not(.is-expanded) .zd-stage:nth-child(n+7) { display: none; }
}
/* -- Band C: ≥920px — --1=1, --2=2, --3=3, --4=4 cols -- */
@media (min-width: 920px) {
  .zd-stages--1.zd-stages--rows-1:not(.is-expanded) .zd-stage:nth-child(n+2),
  .zd-stages--1.zd-stages--rows-2:not(.is-expanded) .zd-stage:nth-child(n+3),
  .zd-stages--1.zd-stages--rows-3:not(.is-expanded) .zd-stage:nth-child(n+4),
  .zd-stages--2.zd-stages--rows-1:not(.is-expanded) .zd-stage:nth-child(n+3),
  .zd-stages--2.zd-stages--rows-2:not(.is-expanded) .zd-stage:nth-child(n+5),
  .zd-stages--2.zd-stages--rows-3:not(.is-expanded) .zd-stage:nth-child(n+7),
  .zd-stages--3.zd-stages--rows-1:not(.is-expanded) .zd-stage:nth-child(n+4),
  .zd-stages--3.zd-stages--rows-2:not(.is-expanded) .zd-stage:nth-child(n+7),
  .zd-stages--3.zd-stages--rows-3:not(.is-expanded) .zd-stage:nth-child(n+10),
  .zd-stages--4.zd-stages--rows-1:not(.is-expanded) .zd-stage:nth-child(n+5),
  .zd-stages--4.zd-stages--rows-2:not(.is-expanded) .zd-stage:nth-child(n+9),
  .zd-stages--4.zd-stages--rows-3:not(.is-expanded) .zd-stage:nth-child(n+13) { display: none; }
}
} /* /@supports (selector(:has(*))) — end of the stages row-cap block */

/* THE BUTTON — hidden by default via .zd-grid__more{display:none}; each band
   shows it ONLY when the preceding grid still has a stage past the cap (:has at
   the same X). Independent of .is-expanded, so it stays as the "Згорнути" toggle. */
@media (max-width: 599px) {
  .zd-stages--rows-1:has(.zd-stage:nth-child(n+2)) + .zd-stages__more,
  .zd-stages--rows-2:has(.zd-stage:nth-child(n+3)) + .zd-stages__more,
  .zd-stages--rows-3:has(.zd-stage:nth-child(n+4)) + .zd-stages__more { display: flex; }
}
@media (min-width: 600px) and (max-width: 919px) {
  .zd-stages--1.zd-stages--rows-1:has(.zd-stage:nth-child(n+2)) + .zd-stages__more,
  .zd-stages--1.zd-stages--rows-2:has(.zd-stage:nth-child(n+3)) + .zd-stages__more,
  .zd-stages--1.zd-stages--rows-3:has(.zd-stage:nth-child(n+4)) + .zd-stages__more,
  .zd-stages--2.zd-stages--rows-1:has(.zd-stage:nth-child(n+3)) + .zd-stages__more,
  .zd-stages--3.zd-stages--rows-1:has(.zd-stage:nth-child(n+3)) + .zd-stages__more,
  .zd-stages--4.zd-stages--rows-1:has(.zd-stage:nth-child(n+3)) + .zd-stages__more,
  .zd-stages--2.zd-stages--rows-2:has(.zd-stage:nth-child(n+5)) + .zd-stages__more,
  .zd-stages--3.zd-stages--rows-2:has(.zd-stage:nth-child(n+5)) + .zd-stages__more,
  .zd-stages--4.zd-stages--rows-2:has(.zd-stage:nth-child(n+5)) + .zd-stages__more,
  .zd-stages--2.zd-stages--rows-3:has(.zd-stage:nth-child(n+7)) + .zd-stages__more,
  .zd-stages--3.zd-stages--rows-3:has(.zd-stage:nth-child(n+7)) + .zd-stages__more,
  .zd-stages--4.zd-stages--rows-3:has(.zd-stage:nth-child(n+7)) + .zd-stages__more { display: flex; }
}
@media (min-width: 920px) {
  .zd-stages--1.zd-stages--rows-1:has(.zd-stage:nth-child(n+2)) + .zd-stages__more,
  .zd-stages--1.zd-stages--rows-2:has(.zd-stage:nth-child(n+3)) + .zd-stages__more,
  .zd-stages--1.zd-stages--rows-3:has(.zd-stage:nth-child(n+4)) + .zd-stages__more,
  .zd-stages--2.zd-stages--rows-1:has(.zd-stage:nth-child(n+3)) + .zd-stages__more,
  .zd-stages--2.zd-stages--rows-2:has(.zd-stage:nth-child(n+5)) + .zd-stages__more,
  .zd-stages--2.zd-stages--rows-3:has(.zd-stage:nth-child(n+7)) + .zd-stages__more,
  .zd-stages--3.zd-stages--rows-1:has(.zd-stage:nth-child(n+4)) + .zd-stages__more,
  .zd-stages--3.zd-stages--rows-2:has(.zd-stage:nth-child(n+7)) + .zd-stages__more,
  .zd-stages--3.zd-stages--rows-3:has(.zd-stage:nth-child(n+10)) + .zd-stages__more,
  .zd-stages--4.zd-stages--rows-1:has(.zd-stage:nth-child(n+5)) + .zd-stages__more,
  .zd-stages--4.zd-stages--rows-2:has(.zd-stage:nth-child(n+9)) + .zd-stages__more,
  .zd-stages--4.zd-stages--rows-3:has(.zd-stage:nth-child(n+13)) + .zd-stages__more { display: flex; }
}

/* Reveal — reuse the tile keyframes; only the freshly-shown stages fade in place. */
@media (prefers-reduced-motion: no-preference) {
  @media (max-width: 599px) {
    .zd-stages--rows-1.is-expanded .zd-stage:nth-child(n+2),
    .zd-stages--rows-2.is-expanded .zd-stage:nth-child(n+3),
    .zd-stages--rows-3.is-expanded .zd-stage:nth-child(n+4) { animation: zd-tile-reveal .32s var(--ease-out); }
  }
  @media (min-width: 600px) and (max-width: 919px) {
    .zd-stages--1.zd-stages--rows-1.is-expanded .zd-stage:nth-child(n+2),
    .zd-stages--1.zd-stages--rows-2.is-expanded .zd-stage:nth-child(n+3),
    .zd-stages--1.zd-stages--rows-3.is-expanded .zd-stage:nth-child(n+4),
    .zd-stages--2.zd-stages--rows-1.is-expanded .zd-stage:nth-child(n+3),
    .zd-stages--3.zd-stages--rows-1.is-expanded .zd-stage:nth-child(n+3),
    .zd-stages--4.zd-stages--rows-1.is-expanded .zd-stage:nth-child(n+3),
    .zd-stages--2.zd-stages--rows-2.is-expanded .zd-stage:nth-child(n+5),
    .zd-stages--3.zd-stages--rows-2.is-expanded .zd-stage:nth-child(n+5),
    .zd-stages--4.zd-stages--rows-2.is-expanded .zd-stage:nth-child(n+5),
    .zd-stages--2.zd-stages--rows-3.is-expanded .zd-stage:nth-child(n+7),
    .zd-stages--3.zd-stages--rows-3.is-expanded .zd-stage:nth-child(n+7),
    .zd-stages--4.zd-stages--rows-3.is-expanded .zd-stage:nth-child(n+7) { animation: zd-tile-reveal .32s var(--ease-out); }
  }
  @media (min-width: 920px) {
    .zd-stages--1.zd-stages--rows-1.is-expanded .zd-stage:nth-child(n+2),
    .zd-stages--1.zd-stages--rows-2.is-expanded .zd-stage:nth-child(n+3),
    .zd-stages--1.zd-stages--rows-3.is-expanded .zd-stage:nth-child(n+4),
    .zd-stages--2.zd-stages--rows-1.is-expanded .zd-stage:nth-child(n+3),
    .zd-stages--2.zd-stages--rows-2.is-expanded .zd-stage:nth-child(n+5),
    .zd-stages--2.zd-stages--rows-3.is-expanded .zd-stage:nth-child(n+7),
    .zd-stages--3.zd-stages--rows-1.is-expanded .zd-stage:nth-child(n+4),
    .zd-stages--3.zd-stages--rows-2.is-expanded .zd-stage:nth-child(n+7),
    .zd-stages--3.zd-stages--rows-3.is-expanded .zd-stage:nth-child(n+10),
    .zd-stages--4.zd-stages--rows-1.is-expanded .zd-stage:nth-child(n+5),
    .zd-stages--4.zd-stages--rows-2.is-expanded .zd-stage:nth-child(n+9),
    .zd-stages--4.zd-stages--rows-3.is-expanded .zd-stage:nth-child(n+13) { animation: zd-tile-reveal .32s var(--ease-out); }
  }
}
