/* =====================================================
   Starter — the parametric flagship theme
   -----------------------------------------------------
   NO colors or fonts live in this file. Every value comes
   from the CSS custom properties that layouts/layout.twig
   renders out of config.yml > tokens/fonts. Change config,
   the whole site re-dresses itself — this file never needs
   an edit for a restyle.
   ===================================================== */

:root {
  /* Derived tones — computed from the injected tokens so a palette swap
     keeps every tint in step automatically. */
  --primary-soft: color-mix(in srgb, var(--primary) 10%, var(--bg));
  /* Hover must be visible on EVERY palette, so it moves toward --ink: the one
     colour guaranteed to contrast with the background, because that is what
     --ink is for. Deriving hover from --primary looked fine on light themes
     and vanished on dark-brand ones — a black shadow on a black page, a 10%
     black tint on a near-black background. Reported live: buttons and the
     language switcher had no visible hover at all. */
  --hover-lift: color-mix(in srgb, var(--primary) 82%, var(--ink));
  --hover-wash: color-mix(in srgb, var(--bg) 88%, var(--ink));
  --tint: color-mix(in srgb, var(--primary) 5%, var(--bg));
  --body-text: color-mix(in srgb, var(--ink) 80%, var(--bg));
  --accent-soft: color-mix(in srgb, var(--accent) 14%, var(--bg));
  --danger: #b3423f;
  --danger-soft: #f7e8e7;
  --container: 1140px;
}

* { box-sizing: border-box; }

/* Type scale the multiplier belongs on the ROOT, not
   on body. Headings and most text are sized in rem — and rem resolves against
   <html> — so a body-level scale moved almost nothing (found live: "Text size"
   looked broken). 16px is the browser default this theme was drawn against. */
html {
  scroll-behavior: smooth;
  font-size: calc(16px * var(--font-scale, 1));
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--body-text);
  font-family: var(--font-body);
  font-size: 1.03rem; /* 16.5px at scale 1 — now inherits the root scale */
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

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

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 600;
  color: var(--ink);
  line-height: 1.15;
  margin: 0 0 .5em;
  letter-spacing: -0.01em;
}

h1 { font-size: clamp(2.4rem, 5vw, 3.6rem); }
/* Section headings at ~3x the body, not 2.4x. Measured against the reference
   set: the timid step between body and heading is what reads as "safe", and
   safe reads as generated. h1 was already at 3.5x — these were the ones
   lagging behind it, and there are ten of them per page to h1's one. */
h2 { font-size: clamp(2rem, 4.2vw, 3.2rem); }
h3 { font-size: 1.35rem; }

p { margin: 0 0 1em; }

a { color: inherit; text-decoration: none; }

.container {
  width: 100%;
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 24px;
}

.container--narrow { max-width: 860px; }

/* Escape the container for one section: its heading stays in the column, its
   content runs edge to edge. Every block sitting in the same centred column is
   the single loudest "this is a template" signal a page can send — measured on
   a generated page, where all eleven sections came out at exactly 1320px.

   Done by widening the container rather than the usual `width: 100vw` +
   negative-margin trick: 100vw counts the scrollbar, so that version overflows
   horizontally by ~15px on any page long enough to have one — which is every
   page this would be used on. */
/* Not padding:0 — edge to edge with the content literally touching the
   viewport reads as unfinished rather than wide. A small gutter keeps
   the block full-bleed and still lets it breathe. */
.section--bleed > .container { max-width: none; padding: 0 clamp(16px, 2.5vw, 40px); }
.section--bleed .section-head {
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 24px;
}

.lead {
  font-size: 1.16rem;
  color: var(--body-text);
  max-width: 620px;
}

.kicker, .eyebrow {
  display: block;
  text-transform: uppercase;
  letter-spacing: .22em;
  font-size: .76rem;
  font-weight: 600;
  color: var(--mark, var(--primary));
  margin-bottom: 1rem;
}

/* ---------- Buttons & links ---------- */
.btn {
  display: inline-block;
  padding: .95rem 2.1rem;
  border-radius: 999px;
  background: var(--primary);
  color: var(--primary-ink);
  font-weight: 600;
  font-size: .95rem;
  border: 1.5px solid var(--mark, var(--primary));
  cursor: pointer;
  font-family: var(--font-body);
  transition: transform .2s ease, box-shadow .2s ease, background .2s ease;
}

.btn:hover { transform: translateY(-2px); background: var(--hover-lift); box-shadow: 0 10px 24px -14px var(--ink); }

.btn-ghost { background: transparent; color: var(--mark, var(--primary)); }
.btn-ghost:hover { background: var(--hover-wash); border-color: var(--ink); color: var(--ink); box-shadow: none; }

.btn-light, .btn-inverse { background: var(--bg); border-color: var(--bg); color: var(--ink); }
/* On the primary-coloured band the inverse button must be the band's INK, not
   the page background: with a dark palette --bg and --primary are both near
   black, and the call to action rendered as plain text (seen on the first
   generated site, seed 355684). */
.cta--band .btn-inverse { background: var(--primary-ink); border-color: var(--primary-ink); color: var(--primary); }
.cta--band .btn-inverse:hover { background: color-mix(in srgb, var(--primary-ink) 88%, var(--primary)); }

.btn-small { padding: .55rem 1.3rem; font-size: .85rem; }

.link-arrow {
  font-weight: 600;
  color: var(--mark, var(--primary));
  white-space: nowrap;
}
.link-arrow::after { content: ' →'; transition: margin .2s ease; }
.link-arrow:hover::after { margin-left: 4px; }

/* The `--back` modifier was used in pages/product.twig and never styled, so a
   link reading «Назад до магазину» carried the base arrow — pointing forward.
   The arrow leads: before the text, and to the left. */
.link-arrow--back::after { content: none; }
.link-arrow--back::before { content: '← '; transition: margin .2s ease; }
.link-arrow--back:hover::before { margin-right: 4px; }

.link-back {
  display: inline-block;
  color: var(--muted);
  font-size: .9rem;
  margin-bottom: 2rem;
}
.link-back:hover { color: var(--mark, var(--primary)); }

/* ---------- Header ---------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: color-mix(in srgb, var(--bg) 92%, transparent);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--line);
}

.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: 78px;
  gap: 1.5rem;
}

.logo {
  font-family: var(--font-display);
  font-size: 1.35rem;
  font-weight: 700;
  color: var(--ink);
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  white-space: nowrap;
}

.logo-dot {
  width: .62em;
  height: .62em;
  border-radius: 50%;
  background: var(--primary);
  display: inline-block;
}

.logo-mark { display: inline-flex; color: var(--ink); }
.logo-mark svg { width: 34px; height: 34px; display: block; }

.site-nav {
  display: flex;
  align-items: center;
  gap: 1.8rem;
}

.nav-link {
  font-size: .93rem;
  font-weight: 500;
  color: var(--body-text);
  padding: .3rem 0;
  border-bottom: 2px solid transparent;
  transition: color .2s ease;
}

.nav-link:hover { color: var(--mark, var(--primary)); }
.nav-link.is-active { color: var(--mark, var(--primary)); border-bottom-color: var(--mark, var(--primary)); }

/* A label never wraps: two-line items are what broke the header first. */
.nav-links .nav-link { white-space: nowrap; }

/* «More» — items past the fourth (partials/header.twig). Hover or keyboard
   focus opens it; no script. The panel is a plain block on mobile (below). */
.nav-more { position: relative; display: inline-flex; }
.nav-more__toggle {
  background: none; border: 0; border-bottom: 2px solid transparent; cursor: pointer;
  font: inherit; font-size: .93rem; font-weight: 500; display: inline-flex; align-items: center; gap: .35rem;
}
.nav-more__toggle::after { content: ''; width: .45em; height: .45em; border: solid currentColor; border-width: 0 1.5px 1.5px 0; transform: translateY(-.15em) rotate(45deg); }
.nav-more__panel {
  display: none; position: absolute; top: calc(100% + .5rem); left: 0; z-index: 60;
  min-width: 15rem; padding: .45rem; background: var(--bg); border: 1px solid var(--line);
  border-radius: .8rem; box-shadow: 0 14px 34px color-mix(in srgb, var(--ink) 14%, transparent);
}
.nav-more:hover .nav-more__panel, .nav-more:focus-within .nav-more__panel { display: grid; gap: .1rem; }
.nav-more::after { content: ''; position: absolute; left: 0; right: 0; top: 100%; height: .6rem; } /* hover bridge to the panel */
.nav-more__panel .nav-link { display: block; padding: .55rem .8rem; border-bottom: 0; border-radius: .5rem; white-space: normal; }
.nav-more__panel .nav-link:hover { background: color-mix(in srgb, var(--ink) 6%, transparent); }

.lang-switch {
  display: flex;
  gap: .6rem;
  font-size: .8rem;
  font-weight: 600;
  letter-spacing: .06em;
}
.lang-switch a { color: var(--muted); }
.lang-switch a.is-active { color: var(--mark, var(--primary)); }
/* --ink, not --mark: on a dark palette the derived readable colour
   lands in the same grey as --muted, so hover changed nothing you could see. */
.lang-switch a:hover { color: var(--ink); }

.nav-checkbox { display: none; }
.nav-toggle { display: none; }

/* ---------- Hero ---------- */
.hero {
  position: relative;
  overflow: hidden;
  padding: clamp(4.5rem, 10vw, 8rem) 0 clamp(4rem, 9vw, 7rem);
  border-bottom: 1px solid var(--line);
}

.hero--split .hero-inner {
  display: grid;
  grid-template-columns: 1.2fr .8fr;
  gap: 3rem;
  align-items: center;
}

.hero--centered .hero-inner { text-align: center; }
.hero--centered .hero-title, .hero--centered .lead { margin-left: auto; margin-right: auto; }
.hero--centered .hero-actions { justify-content: center; }
.hero--centered .hero-stats { justify-content: center; }

/* --- hero photo -----------------------------------------------------------
   `background` covers the whole section; `side` puts the photo where the drawn
   mark otherwise sits. Both keep the section's own padding and grid, so the
   layout knobs stay in charge of shape and only the surface changes.

   The scrim is a LITERAL colour on purpose — it is not a brand colour, no token
   expresses "darken whatever is underneath", and tinting it with --primary
   would stain every photo with the palette. `auto` resolves through
   color-mix against --bg, which is the only thing that knows whether this theme
   is light or dark. */
.hero--media-background {
  background-size: cover;
  background-position: center;
  border-bottom: 0;
}
/* A GRADIENT, not a flat wash. An even 78% veil is safe and pointless: it
   makes the photograph read as a faint texture, so the hero costs a download
   and a decision and gains nothing a plain background would not have given.
   The copy sits on the left, so that is the only side that needs covering —
   the far side can open up and let the picture actually be a picture. */
.hero--media-background::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(100deg,
    color-mix(in srgb, var(--bg) 90%, transparent) 0%,
    color-mix(in srgb, var(--bg) 84%, transparent) 46%,
    color-mix(in srgb, var(--bg) 34%, transparent) 100%);
}
.hero--media-background.hero--overlay-none::before { background: none; }
.hero--media-background.hero--overlay-light::before { background: rgba(255, 255, 255, .72); }
.hero--media-background.hero--overlay-dark::before  { background: rgba(0, 0, 0, .58); }

/* A scrim changes the GROUND — so it has to change what is written on it.
   Without the two blocks below, `overlay: dark` laid a black veil over the
   photo and left the copy in the palette's dark ink: dark text on a darkened
   picture. Measured on a real page: 1.4:1, against the 4.5:1 the guidelines
   ask for. `overlay: light` fails the same way in reverse on a dark palette.

   The colours here are literals, and deliberately so — for the same reason
   the scrim above is one. A veil is not a brand colour: black-with-white-on-it
   is what "dark overlay" MEANS, and a token cannot promise that, because the
   same token is light in one palette and dark in another. The accent keeps
   its token: it stays vivid in every palette we ship.

   Worst cases were worked out rather than eyeballed. A white photo under the
   dark veil gives 4.8:1; a black photo under the light veil gives 8.7:1. */
.hero--media-background.hero--overlay-dark .hero-title,
.hero--media-background.hero--overlay-dark .lead {
  color: #f7f5f2;
}
.hero--media-background.hero--overlay-dark .eyebrow { color: var(--accent); }
.hero--media-background.hero--overlay-dark .btn-ghost {
  color: #f7f5f2;
  border-color: rgba(247, 245, 242, .55);
}
.hero--media-background.hero--overlay-dark .btn-ghost:hover {
  background: rgba(247, 245, 242, .12);
}

.hero--media-background.hero--overlay-light .hero-title,
.hero--media-background.hero--overlay-light .lead {
  color: #1c1a18;
}
.hero--media-background.hero--overlay-light .btn-ghost {
  color: #1c1a18;
  border-color: rgba(28, 26, 24, .45);
}
.hero--media-background.hero--overlay-light .btn-ghost:hover {
  background: rgba(28, 26, 24, .08);
}

/* The transparent header sits OVER that same first section, so it inherits
   the same problem: dark links on a darkened photo all but disappeared.
   `:has()` keys it on the actual neighbour — the header only lightens when a
   dark veil is underneath it, and stays untouched on every other page. */
body.header-transparent:has(.hero--overlay-dark) .site-header .nav-link,
body.header-transparent:has(.hero--overlay-dark) .site-header .lang-switch a,
body.header-transparent:has(.hero--overlay-dark) .site-header .logo,
body.header-transparent:has(.hero--overlay-dark) .site-header .logo-word,
body.header-transparent:has(.hero--overlay-dark) .site-header .nav-toggle span {
  color: #f7f5f2;
}
/* The mark is an inline SVG on currentColor, so it follows the rule above —
   except the accent dot, which carries its own fill and must stay accent. */
body.header-transparent:has(.hero--overlay-dark) .site-header .nav-toggle span {
  background: #f7f5f2;
}
body.header-transparent:has(.hero--overlay-dark) .site-header .nav-link:hover,
body.header-transparent:has(.hero--overlay-dark) .site-header .nav-link.is-active {
  color: var(--accent);
}
body.header-transparent:has(.hero--overlay-dark) .site-header .logo img {
  filter: brightness(0) invert(1);
}

/* The pill language switcher hovers to `--hover-wash`, which is derived from
   the LIGHT page ground — correct everywhere except right here, where these
   same rules have already turned the text light. Light text on a light wash:
   the hovered code all but disappears while its neighbour stays readable. On
   this ground the veil has to come from the light side too. */
body.header-transparent:has(.hero--overlay-dark) .site-header .lang-switch--pills a:hover {
  background: color-mix(in srgb, #f7f5f2 16%, transparent);
  color: #f7f5f2;
}

/* Above the scrim. Without this the copy sits under it and the whole thing
   looks like a fogged window. */
.hero--media-background .hero-inner { position: relative; z-index: 1; }

.hero-visual--photo { pointer-events: auto; }
.hero-visual--photo img {
  width: 100%;
  height: 100%;
  max-height: 420px;
  object-fit: cover;
  border-radius: var(--radius);
  display: block;
}

.hero-visual {
  color: var(--mark, var(--primary));
  pointer-events: none;
}
.hero-visual svg { width: 100%; max-width: 460px; height: auto; margin-left: auto; }

.hero-title { max-width: 780px; margin-bottom: 1.2rem; }

.hero .lead { margin-bottom: 2.4rem; }

.hero-actions { display: flex; gap: .9rem; flex-wrap: wrap; }

.hero-stats {
  display: flex;
  gap: 2.6rem;
  margin: 2.6rem 0 0;
  padding-top: 1.8rem;
  border-top: 1px solid var(--line);
}
.hero-stats > div { display: flex; flex-direction: column; }
.hero-stats dd {
  margin: 0;
  font-family: var(--font-display);
  font-size: 1.7rem;
  font-weight: 600;
  color: var(--ink);
}
.hero-stats dt { font-size: .82rem; color: var(--muted); }

/* ---------- Sections ---------- */
.section { padding: clamp(3.8rem, 8vw, 6.5rem) 0; }

.section--alt, .section-tinted {
  background: var(--tint);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

.section-head {
  display: flex;
  align-items: end;
  justify-content: space-between;
  gap: 2rem;
  margin-bottom: 2.6rem;
}
.section-head h2 { margin-bottom: 0; }

.page-head {
  padding: clamp(3.6rem, 7vw, 5.5rem) 0 0;
}
.page-head h1 { max-width: 720px; }
.page-head .lead { margin-bottom: 0; }

/* ---------- Feature cards (sections/features) ---------- */
.features-grid { display: grid; gap: 1.4rem; }
.features-grid--2 { grid-template-columns: repeat(2, 1fr); }
.features-grid--3 { grid-template-columns: repeat(3, 1fr); }
.features-grid--4 { grid-template-columns: repeat(4, 1fr); }

.feature-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.8rem;
}

.feature-index {
  font-family: var(--font-display);
  font-size: 1rem;
  color: var(--accent);
  display: block;
  margin-bottom: 1rem;
}

.feature-card h3 { font-size: 1.15rem; margin-bottom: .4rem; }
.feature-card p { font-size: .95rem; margin: 0; }

/* ---------- Service cards ---------- */
.cards-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.4rem;
}

/* Column count is decided per render from the item count, so the last row is
   never a single orphaned card — see partials/sections/services.twig. */
/* Count beside a filter chip: quieter than the label it follows — it answers
   "is there anything here", it is not the thing being chosen. */
.chip-count { opacity: .55; font-variant-numeric: tabular-nums; margin-left: .15rem; }

.cards-grid--cols-1 { grid-template-columns: 1fr; }
.cards-grid--cols-2 { grid-template-columns: repeat(2, 1fr); }
.cards-grid--cols-3 { grid-template-columns: repeat(3, 1fr); }

.card {
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.8rem;
  transition: transform .25s ease, box-shadow .25s ease, border-color .25s ease;
}

.card:hover {
  transform: translateY(-4px);
  border-color: var(--mark, var(--primary));
  box-shadow: 0 18px 34px -24px color-mix(in srgb, var(--ink) 35%, transparent);
}

.card-index {
  font-family: var(--font-display);
  font-size: 1rem;
  color: var(--muted);
  margin-bottom: 1.1rem;
}

.card h3 { margin-bottom: .5rem; }
.card p { font-size: .95rem; flex: 1; }

.card-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 1.2rem;
}

.price-chip {
  background: var(--accent-soft);
  color: color-mix(in srgb, var(--accent) 75%, var(--ink));
  font-weight: 600;
  font-size: .85rem;
  padding: .3rem .8rem;
  border-radius: 999px;
  white-space: nowrap;
}

/* Duration sits next to the price and reads as secondary to it — a booking
   detail, not the offer. */
.meta-chip {
  color: var(--muted);
  font-size: .85rem;
  white-space: nowrap;
}

.card-media { display: none; }
.card-media img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ---------- Pricing list (sections/pricing) ---------- */
.rate-list { list-style: none; margin: 0; padding: 0; }

.rate-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 2rem;
  padding: 1.3rem 0;
  border-bottom: 1px dashed var(--line);
}
.rate-row:last-child { border-bottom: none; }

.rate-name { font-family: var(--font-display); font-size: 1.15rem; font-weight: 600; color: var(--ink); }
.rate-name:hover { color: var(--mark, var(--primary)); }
.rate-desc { font-size: .9rem; color: var(--muted); margin: .2rem 0 0; max-width: 46ch; }
.rate-price { font-weight: 600; color: var(--ink); white-space: nowrap; }

/* ---------- About strip / values / steps ---------- */
.about-strip {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 3.5rem;
  align-items: start;
}
.about-strip h2 { margin-bottom: 0; }

.values-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2.5rem;
}

.value-num {
  font-family: var(--font-display);
  font-size: 2.6rem;
  color: var(--mark, var(--primary));
  display: block;
  margin-bottom: .6rem;
}

.steps {
  margin: 0;
  padding: 0 0 0 1.2rem;
  display: grid;
  gap: .9rem;
}
.steps li::marker { color: var(--mark, var(--primary)); font-weight: 700; }

/* ---------- Posts ---------- */
.posts-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.4rem;
}

.post-card {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--surface);
  transition: transform .25s ease, box-shadow .25s ease, border-color .25s ease;
}

.post-card:hover {
  transform: translateY(-4px);
  border-color: var(--mark, var(--primary));
  box-shadow: 0 18px 34px -24px color-mix(in srgb, var(--ink) 35%, transparent);
}

.post-card img,
.post-ph {
  width: 100%;
  aspect-ratio: 16/9;
  object-fit: cover;
}

.post-ph {
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, var(--primary-soft), var(--tint));
  color: var(--mark, var(--primary));
  font-family: var(--font-display);
  font-size: 3.4rem;
  font-weight: 600;
}

.post-body { padding: 1.3rem 1.5rem 1.6rem; display: block; }

.post-date {
  display: block;
  font-size: .78rem;
  text-transform: uppercase;
  letter-spacing: .14em;
  color: var(--muted);
  margin-bottom: .5rem;
}

.post-body h3 { font-size: 1.15rem; margin-bottom: .4rem; }
.post-body p { font-size: .92rem; margin: 0; color: var(--body-text); }

/* ---------- Category chips ---------- */
.chip-row { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: 1.4rem; }

.chip {
  padding: .4rem 1rem;
  border-radius: 999px;
  border: 1px solid var(--line);
  font-size: .85rem;
  font-weight: 500;
  color: var(--body-text);
  transition: all .2s ease;
}
.chip:hover { border-color: var(--mark, var(--primary)); color: var(--mark, var(--primary)); }
.chip.is-active { background: var(--primary); border-color: var(--primary); color: var(--primary-ink); }

/* ---------- Article ---------- */
.article { padding: clamp(3rem, 6vw, 5rem) 0; }

.article-narrow { max-width: 760px; }

.article-photo {
  border-radius: var(--radius);
  margin: 2rem 0;
}

.prose { color: var(--body-text); }
.prose h2 { font-size: 1.6rem; margin-top: 2.2rem; }
.prose h3 { margin-top: 1.8rem; }
.prose ul, .prose ol { padding-left: 1.3rem; }
.prose li { margin-bottom: .4rem; }
.prose li::marker { color: var(--mark, var(--primary)); }
.prose img { border-radius: var(--radius); margin: 1.5rem 0; }
.prose a { color: var(--mark, var(--primary)); text-decoration: underline; text-underline-offset: 3px; }
.prose blockquote {
  margin: 1.8rem 0;
  padding: .3rem 0 .3rem 1.4rem;
  border-left: 3px solid var(--mark, var(--primary));
  font-family: var(--font-display);
  font-size: 1.15rem;
  color: var(--ink);
}

/* ---------- Buy box ---------- */
.buy-box {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 1.5rem;
  margin-top: 2.5rem;
  padding: 1.6rem 1.8rem;
  background: var(--tint);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

/* Facts column: price is the headline, duration the supporting line. Both
   render without any commerce feature being on. */
.buy-facts { display: flex; flex-direction: column; gap: .15rem; }

.buy-duration {
  font-size: .9rem;
  color: var(--muted);
}

.buy-label {
  display: block;
  font-size: .78rem;
  text-transform: uppercase;
  letter-spacing: .14em;
  color: var(--muted);
}

.buy-price {
  font-family: var(--font-display);
  font-size: 1.9rem;
  font-weight: 600;
  color: var(--ink);
}

.buy-form { display: flex; align-items: center; gap: .8rem; }

.buy-qty {
  width: 74px;
  height: 48px;
  text-align: center;
  border: 1px solid var(--line);
  border-radius: var(--radius-small);
  font-family: var(--font-body);
  font-size: 1rem;
  font-weight: 600;
  color: var(--ink);
  background: var(--surface);
}
.buy-qty:focus { outline: none; border-color: var(--mark, var(--primary)); }

.cta-inline {
  margin-top: 2.5rem;
  padding: 1.6rem 1.8rem;
  background: var(--primary-soft);
  border-radius: var(--radius);
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 1.2rem;
}
.cta-inline p { margin: 0; color: var(--ink); font-weight: 500; }

/* ---------- Booking box (pages/service) ---------- */
.book-box {
  margin-top: 2.5rem;
  padding: 1.8rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.book-box h2 { font-size: 1.5rem; }
.book-hint { font-size: .92rem; color: var(--muted); }

.book-date-form { margin: 1.2rem 0; display: flex; align-items: center; gap: .8rem; flex-wrap: wrap; }
.book-label { font-size: .85rem; font-weight: 600; color: var(--ink); }

.book-date-form input[type='date'] {
  padding: .7rem 1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-small);
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: .95rem;
}
.book-date-form input[type='date']:focus { outline: none; border-color: var(--mark, var(--primary)); }

.slot-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(86px, 1fr));
  gap: .55rem;
  margin-bottom: 1.4rem;
}

.slot input { position: absolute; opacity: 0; pointer-events: none; }

.slot span {
  display: block;
  text-align: center;
  padding: .6rem 0;
  border: 1.5px solid var(--line);
  border-radius: var(--radius-small);
  font-size: .92rem;
  font-weight: 600;
  color: var(--ink);
  cursor: pointer;
  transition: all .15s ease;
}

.slot:hover span { border-color: var(--mark, var(--primary)); }
.slot input:checked + span {
  background: var(--primary);
  border-color: var(--mark, var(--primary));
  color: var(--primary-ink);
}
.slot input:focus-visible + span { outline: 2px solid var(--primary); outline-offset: 2px; }

.book-fields { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: .8rem; margin-bottom: .9rem; }

.book-fields input, .book-notes {
  width: 100%;
  padding: .85rem 1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-small);
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: .95rem;
}
.book-fields input:focus, .book-notes:focus { outline: none; border-color: var(--mark, var(--primary)); }

.book-notes { display: block; margin-bottom: 1.2rem; resize: vertical; }

.book-empty {
  padding: 1.2rem;
  background: var(--tint);
  border-radius: var(--radius-small);
  color: var(--muted);
  text-align: center;
}

/* ---------- Testimonials (sections/testimonials) ---------- */
.quotes-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 1.4rem;
}

.quote-card {
  margin: 0;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.8rem;
}

.quote-card blockquote {
  margin: 0 0 1.2rem;
  font-family: var(--font-display);
  font-size: 1.12rem;
  color: var(--ink);
  line-height: 1.5;
}
.quote-card blockquote::before { content: '\201C'; color: var(--accent); margin-right: .15em; }

.quote-card figcaption {
  display: flex;
  align-items: center;
  gap: .7rem;
  font-size: .9rem;
  font-weight: 600;
  color: var(--muted);
}

.quote-avatar {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--primary-soft);
  color: var(--mark, var(--primary));
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-weight: 600;
}

/* ---------- FAQ (sections/faq) ---------- */
.faq-list { display: grid; gap: .6rem; }

.faq-item {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-small);
  padding: 0 1.3rem;
}

.faq-item summary {
  cursor: pointer;
  list-style: none;
  padding: 1.05rem 0;
  font-weight: 600;
  color: var(--ink);
  position: relative;
  padding-right: 2rem;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after {
  content: '+';
  position: absolute;
  right: .2rem;
  top: 50%;
  transform: translateY(-50%);
  font-family: var(--font-display);
  font-size: 1.3rem;
  color: var(--mark, var(--primary));
  transition: transform .2s ease;
}
.faq-item[open] summary::after { transform: translateY(-50%) rotate(45deg); }

.faq-item p { margin: 0; padding: 0 0 1.2rem; color: var(--body-text); font-size: .96rem; }

/* ---------- Team (sections/team) ---------- */
.team-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1.4rem;
}

.team-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.8rem 1.5rem;
  text-align: center;
}

.team-avatar {
  width: 72px;
  height: 72px;
  border-radius: 50%;
  margin: 0 auto 1rem;
  background: linear-gradient(135deg, var(--primary-soft), var(--accent-soft));
  color: var(--mark, var(--primary));
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-size: 1.8rem;
  font-weight: 600;
}

.team-card h3 { font-size: 1.08rem; margin-bottom: .2rem; }
.team-card p { margin: 0; font-size: .88rem; color: var(--muted); }

/* ---------- Gallery (sections/gallery) ---------- */
.gallery-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: .9rem;
}

.gallery-item {
  margin: 0;
  border-radius: var(--radius-small);
  overflow: hidden;
  aspect-ratio: 1;
}

.gallery-item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform .3s ease;
}
.gallery-item:hover img { transform: scale(1.04); }

/* ---------- CTA section (sections/cta) ---------- */
.cta--band {
  background: var(--primary);
  color: var(--primary-ink);
  padding: clamp(3.5rem, 7vw, 5.5rem) 0;
}
.cta--band .cta-inner h2 { color: var(--primary-ink); }
.cta--band .cta-inner p { color: color-mix(in srgb, var(--primary-ink) 82%, transparent); margin-bottom: 2rem; }

.cta--plain { padding: clamp(3rem, 6vw, 5rem) 0; }
.cta--plain .cta-inner p { color: var(--body-text); margin-bottom: 2rem; }

.cta-inner { text-align: center; max-width: 640px; margin: 0 auto; }

/* legacy alias (about page band) */
.cta-band {
  background: var(--primary);
  color: var(--primary-ink);
  padding: clamp(3.5rem, 7vw, 5.5rem) 0;
}
.cta-band .cta-inner h2 { color: var(--primary-ink); }
.cta-band .cta-inner p { color: color-mix(in srgb, var(--primary-ink) 82%, transparent); margin-bottom: 2rem; }

/* ---------- Contact cards (sections/contacts) ---------- */
.contact-cards {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.4rem;
}

.contact-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.5rem 1.8rem;
  display: flex;
  flex-direction: column;
  gap: .3rem;
}

.contact-label {
  font-size: .76rem;
  text-transform: uppercase;
  letter-spacing: .16em;
  color: var(--muted);
}
.contact-value { font-weight: 600; color: var(--ink); }
a.contact-value:hover { color: var(--mark, var(--primary)); }

/* ---------- Contact page ---------- */
.contact-grid {
  display: grid;
  grid-template-columns: .8fr 1.2fr;
  gap: 3.5rem;
  align-items: start;
}

.info-item { padding: 1.1rem 0; border-bottom: 1px solid var(--line); }
.info-item a:hover { color: var(--mark, var(--primary)); }
/* Social rows on the contact page: network name, then the handle. */
.contact-socials { list-style: none; margin: .35rem 0 0; padding: 0; display: grid; gap: .45rem; }
.contact-socials li { display: flex; gap: .75rem; align-items: baseline; }
.contact-socials__network { flex: 0 0 5.5rem; font-size: .8rem; letter-spacing: .04em; text-transform: uppercase; color: var(--muted, var(--body-text)); }
.contact-socials a { text-decoration: underline; text-underline-offset: .2em; }

.info-label {
  display: block;
  font-size: .76rem;
  text-transform: uppercase;
  letter-spacing: .16em;
  color: var(--muted);
  margin-bottom: .25rem;
}

.contact-form-wrap label {
  display: block;
  font-size: .85rem;
  font-weight: 600;
  color: var(--ink);
  margin-bottom: .4rem;
}

.contact-form-wrap input,
.contact-form-wrap textarea {
  width: 100%;
  padding: .85rem 1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-small);
  background: var(--surface);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: .97rem;
  margin-bottom: .35rem;
}

.contact-form-wrap input:focus,
.contact-form-wrap textarea:focus {
  outline: none;
  border-color: var(--mark, var(--primary));
  box-shadow: 0 0 0 3px var(--primary-soft);
}

.contact-form-wrap textarea { resize: vertical; min-height: 130px; }

.contact-form-wrap .btn { margin-top: .8rem; }

.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 1.2rem; }

.field-error { min-height: 1.1rem; font-size: .82rem; color: var(--danger); margin-bottom: .6rem; }

.form-success, .form-error {
  padding: 1rem 1.2rem;
  border-radius: var(--radius-small);
  font-weight: 500;
  margin-bottom: 1.4rem;
}
.form-success { background: var(--primary-soft); color: var(--mark, var(--primary)); }
.form-error { background: var(--danger-soft); color: var(--danger); }

/* ---------- Auth pages (account/login, account/register) ---------- */
.auth-inner { max-width: 460px; margin: 0 auto; }

.auth-form label {
  display: block;
  font-size: .85rem;
  font-weight: 600;
  color: var(--ink);
  margin-bottom: .4rem;
}

.auth-form input[type='email'],
.auth-form input[type='password'],
.auth-form input[type='text'] {
  width: 100%;
  padding: .85rem 1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-small);
  background: var(--surface);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: .97rem;
  margin-bottom: .35rem;
}

.auth-form input:focus {
  outline: none;
  border-color: var(--mark, var(--primary));
  box-shadow: 0 0 0 3px var(--primary-soft);
}

.auth-remember {
  display: flex;
  align-items: center;
  gap: .5rem;
  font-size: .9rem;
  margin: .6rem 0 1.2rem;
  cursor: pointer;
}
.auth-remember input { accent-color: var(--mark, var(--primary)); }

.auth-form .btn { width: 100%; }

.auth-switch { margin-top: 1.6rem; text-align: center; font-size: .92rem; color: var(--muted); }
.auth-switch a { color: var(--mark, var(--primary)); font-weight: 600; }

/* ---------- Account page ---------- */
.account-grid { display: grid; gap: 2.2rem; max-width: 760px; }

.account-block h2 { font-size: 1.4rem; margin-bottom: 1rem; }

.account-list { list-style: none; margin: 0; padding: 0; }

.account-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.4rem;
  padding: 1rem 1.2rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-small);
  background: var(--surface);
  margin-bottom: .6rem;
}

.account-row-title { display: block; font-weight: 600; color: var(--ink); }
.account-row-sub { display: block; font-size: .85rem; color: var(--muted); }
.account-row-side { display: flex; align-items: center; gap: .9rem; flex-shrink: 0; }
.account-row-price { font-weight: 600; color: var(--ink); }

.account-cancel { font-size: .85rem; color: var(--danger); }
.account-cancel:hover { text-decoration: underline; }

.status {
  font-size: .76rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .08em;
  padding: .3rem .7rem;
  border-radius: 999px;
  background: var(--tint);
  color: var(--muted);
}
.status--confirmed, .status--paid { background: var(--primary-soft); color: var(--mark, var(--primary)); }
.status--new { background: var(--accent-soft); color: color-mix(in srgb, var(--accent) 75%, var(--ink)); }
.status--cancelled { background: var(--danger-soft); color: var(--danger); }

.account-actions { padding-top: .5rem; }

/* ---------- Thanks ---------- */
.thanks-inner { text-align: center; max-width: 560px; padding-top: 2rem; margin: 0 auto; }

.thanks-mark {
  width: 64px;
  height: 64px;
  margin: 0 auto 1.6rem;
  border-radius: 50%;
  background: var(--primary-soft);
  color: var(--mark, var(--primary));
  display: flex;
  align-items: center;
  justify-content: center;
}
.thanks-mark svg { width: 30px; height: 30px; }

.thanks-inner .lead { margin: 0 auto 2.2rem; }

/* ---------- Empty state ---------- */
.empty-state {
  text-align: center;
  padding: 3.5rem 1.5rem;
  border: 1.5px dashed var(--line);
  border-radius: var(--radius);
  color: var(--muted);
}

/* ---------- Pagination (partials/pagination.twig) ---------- */
.pagination {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: .45rem;
  margin-top: 3.2rem;
}

.page-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  height: 44px;
  padding: 0 .7rem;
  border-radius: var(--radius-small);
  border: 1.5px solid var(--line);
  background: var(--surface);
  font-size: .92rem;
  font-weight: 600;
  color: var(--body-text);
  transition: all .2s ease;
}

a.page-btn:hover {
  border-color: var(--ink);
  color: var(--ink);
  transform: translateY(-1px);
  box-shadow: 0 8px 18px -12px var(--ink);
}

.page-btn.is-current {
  background: var(--primary);
  border-color: var(--mark, var(--primary));
  color: var(--primary-ink);
}

.page-btn.is-gap { border-color: transparent; color: var(--muted); }

.page-arrow { font-size: 1.05rem; }
.page-arrow.is-disabled { opacity: .35; }

/* ---------- Footer ---------- */
.site-footer {
  background: var(--tint);
  border-top: 1px solid var(--line);
  padding: 3.5rem 0 0;
  margin-top: 0;
}

.footer-grid {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr;
  gap: 2.5rem;
  padding-bottom: 2.5rem;
}

.footer-about { font-size: .92rem; color: var(--muted); margin-top: 1rem; max-width: 320px; }

.footer-title {
  display: block;
  font-size: .76rem;
  text-transform: uppercase;
  letter-spacing: .16em;
  color: var(--muted);
  margin-bottom: 1rem;
}

.footer-nav, .footer-contacts { display: flex; flex-direction: column; gap: .55rem; font-size: .95rem; }
.footer-nav a:hover, .footer-contacts a:hover { color: var(--mark, var(--primary)); }

.footer-bottom {
  border-top: 1px solid var(--line);
  padding-top: 1.4rem;
  padding-bottom: 1.6rem;
  font-size: .85rem;
  color: var(--muted);
}

/* ---------- Responsive ---------- */
@media (max-width: 960px) {
  .cards-grid, .posts-grid, .values-grid, .contact-cards, .team-grid, .gallery-grid,
  .features-grid--3, .features-grid--4 { grid-template-columns: repeat(2, 1fr); }
  .quotes-grid { grid-template-columns: 1fr; }
  .about-strip, .contact-grid { grid-template-columns: 1fr; gap: 2rem; }
  .footer-grid { grid-template-columns: 1fr 1fr; }
  .hero--split .hero-inner { grid-template-columns: 1fr; }
  /* The drawn mark is decoration and goes; a PHOTOGRAPH is content and stays.
     This rule predates hero photos, so it hid them too — and the builder's own
     preview pane is narrower than this breakpoint, which meant an owner who had
     just been given a hero image saw no image at all while looking straight at
     the site. Shorter here, because it now sits under the copy instead of
     beside it. */
  .hero-visual:not(.hero-visual--photo) { display: none; }
  .hero-visual--photo img { max-height: 280px; }
  /* The copy stops being a left column here and spans the whole width, so it
     lands on the open side of the gradient — measured at 6.2:1 on a mid-tone
     photo, and a darker one goes under the line. No far side to spare means
     an even veil, which is the one place the flat wash is the right answer. */
  .hero--media-background::before {
    background: color-mix(in srgb, var(--bg) 86%, transparent);
  }
  .book-fields { grid-template-columns: 1fr; }
}

@media (max-width: 640px) {
  .cards-grid, .posts-grid, .values-grid, .contact-cards, .form-row, .footer-grid, .team-grid,
  .features-grid--2, .features-grid--3, .features-grid--4 { grid-template-columns: 1fr; }
  .gallery-grid { grid-template-columns: repeat(2, 1fr); }

  .section-head { flex-direction: column; align-items: start; gap: .8rem; }

  .hero-stats { flex-wrap: wrap; gap: 1.4rem 2.2rem; }

  .account-row { flex-direction: column; align-items: flex-start; gap: .6rem; }
  .account-row-side { width: 100%; justify-content: space-between; }

  .rate-row { flex-direction: column; gap: .3rem; }

  /* Mobile nav: checkbox-driven, no JS */
  .nav-toggle {
    display: flex;
    flex-direction: column;
    gap: 5px;
    cursor: pointer;
    padding: 6px 2px;
  }
  .nav-toggle span {
    width: 22px;
    height: 2px;
    background: var(--ink);
    border-radius: 2px;
    transition: transform .25s ease, opacity .25s ease;
  }

  .site-nav {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: flex-start;
    gap: 1.1rem;
    background: var(--bg);
    border-bottom: 1px solid var(--line);
    padding: 1.4rem 24px 1.8rem;
  }

  .nav-checkbox:checked ~ .site-nav { display: flex; }

  /* In the burger the fold is pointless: show every page as one list. */
  .nav-more { display: contents; }
  .nav-more__toggle { display: none; }
  .nav-more__panel, .nav-more:hover .nav-more__panel, .nav-more:focus-within .nav-more__panel {
    display: contents; position: static; border: 0; box-shadow: none; padding: 0; background: none;
  }
  .nav-more__panel .nav-link { padding: .3rem 0; border-radius: 0; }
  .nav-checkbox:checked ~ .nav-toggle span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
  .nav-checkbox:checked ~ .nav-toggle span:nth-child(2) { opacity: 0; }
  .nav-checkbox:checked ~ .nav-toggle span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }
}

/* ---------- Layout knobs ----------
   Body classes rendered from config.yml `layout:` — see layouts/layout.twig.
   Every rule keys on tokens, so palettes keep working under any frame. */

/* width: wide — the container token cascades from body */
body.width-wide { --container: 1320px; }

/* header: solid — opaque, in-flow (no sticky, no blur) */
body.header-solid .site-header {
  position: static;
  background: var(--bg);
  backdrop-filter: none;
}

/* header: transparent — floats over the hero, no ground of its own */
body.header-transparent .site-header {
  position: absolute;
  left: 0;
  right: 0;
  background: transparent;
  border-bottom-color: transparent;
  backdrop-filter: none;
}
body.header-transparent main { padding-top: 0; }

/* footer: minimal — just the legal line, no link grid */
body.footer-minimal .footer-grid { display: none; }
body.footer-minimal .site-footer { padding-top: 0; }

/* nav: left — desktop sidebar; below 960px the burger takes over as usual */
@media (min-width: 960px) {
  body.nav-left {
    display: grid;
    grid-template-columns: 264px minmax(0, 1fr);
  }
  body.nav-left .site-header {
    grid-row: 1 / span 2;
    position: sticky;
    top: 0;
    height: 100vh;
    border-bottom: 0;
    border-right: 1px solid var(--line);
    background: var(--bg);
    backdrop-filter: none;
  }
  body.nav-left .header-inner {
    flex-direction: column;
    align-items: flex-start;
    justify-content: flex-start;
    min-height: 0;
    height: 100%;
    padding-top: 30px;
    padding-bottom: 30px;
    gap: 2.2rem;
  }
  body.nav-left .site-nav {
    flex-direction: column;
    align-items: flex-start;
    gap: .4rem;
    width: 100%;
  }
  body.nav-left .site-nav .btn.btn-small { margin-top: .6rem; }
  body.nav-left .lang-switch { margin-top: auto; }
  body.nav-left main,
  body.nav-left .site-footer { grid-column: 2; min-width: 0; }
}

/* ---------- Section variants ----------
   Deliberately near the END of the file, right before their media
   queries. Variant classes carry the same specificity as the base
   `.cards-grid` / `.quotes-grid` they override, so at equal weight the
   later rule wins — defined up beside the base grids, the spotlight
   column count silently lost and rendered two columns instead of three.
   Keep the whole variant layer down here. */

/* ---------- Services variants ----------
   One markup shape, three layouts. Everything below re-arranges the SAME
   elements the cards variant uses — no variant owns markup or copy of its
   own, which is what keeps the translation-key scan whole. */

/* list — one row per service, price and link pushed to the right edge. Reads
   as a price list, which is what a salon or a workshop actually wants. */
.cards-grid--list { grid-template-columns: 1fr; gap: 0; }

.cards-grid--list .card {
  flex-direction: row;
  align-items: center;
  gap: 1.5rem;
  border-radius: 0;
  border-width: 0 0 1px;
  padding: 1.4rem .4rem;
}
.cards-grid--list .card:first-child { border-top: 1px solid var(--line); }
.cards-grid--list .card:hover {
  transform: none;
  border-color: var(--line);
  box-shadow: none;
  background: var(--surface);
}
.cards-grid--list .card-body { flex: 1; min-width: 0; }
.cards-grid--list .card-index {
  margin-bottom: 0;
  margin-right: .2rem;
  display: inline-block;
}
.cards-grid--list .card h3 { display: inline; margin: 0; }
.cards-grid--list .card p {
  margin: .35rem 0 0;
  color: var(--muted);
  font-size: .9rem;
}
.cards-grid--list .card-foot { margin-top: 0; flex: 0 0 auto; }

/* alternating — image beside text, sides swapping row to row.

   Grid, not flex-direction: row-reverse. Reversing the row flips ALL three
   children, so on even rows the price and the "Details" link detached from
   their own text and floated to the far left of the card — the layout read as
   two unrelated columns. Explicit placement moves only the image, which is the
   one thing that is supposed to alternate. */
.cards-grid--alternating { grid-template-columns: 1fr; gap: 1.2rem; }

.cards-grid--alternating .card {
  display: grid;
  grid-template-columns: minmax(0, 34%) minmax(0, 1fr);
  grid-template-rows: auto auto;
  align-items: center;
  gap: .5rem 2rem;
  padding: 1.4rem;
}
.cards-grid--alternating .card-media {
  display: block;
  grid-row: 1 / 3;
  grid-column: 1;
  aspect-ratio: 3 / 2;
  max-height: 14rem;
  border-radius: var(--radius);
  overflow: hidden;
}
.cards-grid--alternating .card-body {
  grid-row: 1;
  grid-column: 2;
  align-self: end;
  min-width: 0;
}
.cards-grid--alternating .card-body p { margin-bottom: 0; }
.cards-grid--alternating .card-foot {
  grid-row: 2;
  grid-column: 2;
  align-self: start;
  justify-content: flex-start;
  margin-top: .4rem;
}

/* Swap the TRACKS as well as the placement: moving the image to column 2
   without this leaves it floating in the wide text track with dead space
   beside it, and squeezes the copy into the narrow one. */
.cards-grid--alternating .card:nth-child(even) {
  grid-template-columns: minmax(0, 1fr) minmax(0, 34%);
}
.cards-grid--alternating .card:nth-child(even) .card-media { grid-column: 2; }
.cards-grid--alternating .card:nth-child(even) .card-body,
.cards-grid--alternating .card:nth-child(even) .card-foot { grid-column: 1; }

/* A record without a photo gets the full width instead of an empty column —
   a half-illustrated area is the normal state, not an edge case. */
.cards-grid--alternating .card:not(:has(.card-media)) { grid-template-columns: minmax(0, 1fr); }
.cards-grid--alternating .card:not(:has(.card-media)) .card-body,
.cards-grid--alternating .card:not(:has(.card-media)) .card-foot { grid-column: 1; }

/* ---------- Testimonials variants ---------- */

/* spotlight — the first quote carries the section, the rest support it. */
.quotes-grid--spotlight { grid-template-columns: repeat(3, 1fr); }
.quotes-grid--spotlight .quote-card:first-child {
  grid-column: 1 / -1;
  padding: 2.4rem;
  text-align: center;
}
.quotes-grid--spotlight .quote-card:first-child blockquote {
  font-size: 1.6rem;
  line-height: 1.4;
  max-width: 46ch;
  margin-inline: auto;
}
.quotes-grid--spotlight .quote-card:first-child figcaption { justify-content: center; }

/* strip — one horizontal row, scroll-snapped. Deliberately NOT an
   auto-playing marquee: text that slides away mid-sentence is unreadable,
   and an animation nobody can pause is an accessibility problem. */
.quotes-grid--strip {
  display: flex;
  gap: 1.4rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  padding-bottom: .6rem;
  scrollbar-width: thin;
}
.quotes-grid--strip .quote-card {
  flex: 0 0 min(23rem, 78vw);
  scroll-snap-align: start;
}


/* ---------- Features variants ---------- */

/* numbered — the figure carries the eye, the card chrome gets out of the way. */
.features-grid--numbered .feature-card {
  background: none;
  border: 0;
  padding: 0 1.4rem 0 0;
}
.features-grid--numbered .feature-index {
  font-size: 2.4rem;
  line-height: 1;
  color: color-mix(in srgb, var(--primary) 35%, var(--bg));
  margin-bottom: .6rem;
}

/* checkerboard — alternating tint instead of borders; reads denser and less
   "three boxes in a row". */
.features-grid--checkerboard { gap: 0; }
.features-grid--checkerboard .feature-card {
  border: 0;
  border-radius: 0;
  background: var(--bg);
  padding: 1.9rem;
}
.features-grid--checkerboard .feature-card:nth-child(odd) { background: var(--tint); }

/* ---------- Team variants ---------- */

/* list — avatar left, name and role beside it. Suits a long roster where the
   grid of faces turns into wallpaper. */
.team-grid--list { grid-template-columns: 1fr; gap: 0; }
.team-grid--list .team-card {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  grid-template-rows: auto auto;
  align-items: center;
  gap: .1rem 1.2rem;
  text-align: left;
  background: none;
  border: 0;
  border-bottom: 1px solid var(--line);
  border-radius: 0;
  padding: 1.1rem .2rem;
}
.team-grid--list .team-avatar { grid-row: 1 / 3; margin: 0; width: 56px; height: 56px; }
.team-grid--list .team-card h3 { grid-column: 2; margin: 0; }
.team-grid--list .team-card p { grid-column: 2; margin: 0; color: var(--muted); font-size: .92rem; }

/* strip — one scrolling row of faces; scroll-snap, no autoplay. */
.team-grid--strip {
  display: flex;
  gap: 1.2rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  padding-bottom: .6rem;
}
.team-grid--strip .team-card { flex: 0 0 min(15rem, 60vw); scroll-snap-align: start; }

/* ---------- FAQ variants ---------- */

/* columns — everything expanded in two columns. The template also renders the
   `open` attribute for this variant: a closed <details> cannot be forced open
   from CSS, and faking it with height tricks breaks the built-in semantics
   screen readers rely on. */
.faq-list--columns {
  columns: 2;
  column-gap: 2.4rem;
}
.faq-list--columns .faq-item {
  break-inside: avoid;
  border-bottom: 0;
  margin-bottom: 1.4rem;
}
.faq-list--columns .faq-item summary { cursor: default; list-style: none; pointer-events: none; }
.faq-list--columns .faq-item summary::-webkit-details-marker { display: none; }
.faq-list--columns .faq-item summary::after { content: none; }

/* ---------- Gallery variants ---------- */

/* masonry — natural heights instead of a uniform crop; portrait shots stop
   losing their tops and bottoms. */
.gallery-grid--masonry {
  display: block;
  columns: 4;
  column-gap: 1rem;
}
.gallery-grid--masonry .gallery-item {
  break-inside: avoid;
  margin: 0 0 1rem;
}
.gallery-grid--masonry .gallery-item img { height: auto; aspect-ratio: auto; }

/* strip — one scrolling row. */
.gallery-grid--strip {
  display: flex;
  gap: 1rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  padding-bottom: .6rem;
}
.gallery-grid--strip .gallery-item { flex: 0 0 min(20rem, 70vw); scroll-snap-align: start; }

/* ---------- Pricing variants ---------- */

/* cards — a tile per rate, for short menus where rows look thin. */
.rate-list--cards {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1.2rem;
}
.rate-list--cards .rate-row {
  flex-direction: column;
  align-items: flex-start;
  gap: .6rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.5rem;
}
.rate-list--cards .rate-price {
  font-size: 1.5rem;
  color: var(--mark, var(--primary));
}

/* ---------- Hero: minimal ----------
   Typography only. No visual, no stats row — for a business whose first
   screen should say one thing. */
.hero--minimal { padding: clamp(3.5rem, 7vw, 5.5rem) 0; }
.hero--minimal .hero-inner { text-align: center; }
.hero--minimal .hero-visual { display: none; }
.hero--minimal .hero-stats { display: none; }
.hero--minimal .hero-title,
.hero--minimal .lead { margin-left: auto; margin-right: auto; }
.hero--minimal .hero-actions { justify-content: center; }
.hero--minimal .eyebrow { letter-spacing: .3em; }

/* ---------- Density ----------
   A body-level knob, like the other layout knobs. Section rhythm and
   card padding change together — the same blocks in a tighter or airier grid
   read as a different site, which is the cheapest variety there is. */
body.density-compact .section { padding: clamp(2.4rem, 5vw, 4rem) 0; }
body.density-compact .section-head { margin-bottom: 1.7rem; }
body.density-compact .card,
body.density-compact .feature-card,
body.density-compact .quote-card,
body.density-compact .team-card { padding: 1.2rem; }
body.density-compact .cards-grid,
body.density-compact .features-grid,
body.density-compact .quotes-grid,
body.density-compact .team-grid { gap: .9rem; }

body.density-airy .section { padding: clamp(5rem, 11vw, 9rem) 0; }
body.density-airy .section-head { margin-bottom: 3.6rem; }
body.density-airy .card,
body.density-airy .feature-card,
body.density-airy .quote-card,
body.density-airy .team-card { padding: 2.4rem; }
body.density-airy .cards-grid,
body.density-airy .features-grid,
body.density-airy .quotes-grid,
body.density-airy .team-grid { gap: 2rem; }

/* ---------- Header layouts ----------
   The header is the first thing anyone sees and the one block every page
   shares, so a single composition made every site look related. Four layouts
   re-arrange the SAME two groups the markup ships — .nav-links (the pages)
   and .nav-utils (contact, account, language) — with no variant owning markup
   or copy of its own.

   Deliberately below the base header rules and above the responsive block:
   equal specificity means source order decides, and everything here is undone
   at mobile width where the burger takes over. */

.nav-links,
.nav-utils {
  display: inline-flex;
  align-items: center;
  gap: inherit;
}

/* classic — logo left, everything else right (the original). Nothing to do. */

/* split — logo in the middle, pages on the left, utilities on the right.
   The most "designed" of the four; wants a short nav, which is why the
   catalog structures keep 4–5 items. */
.header-layout--split .header-inner { position: relative; }
.header-layout--split .logo {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
}
.header-layout--split .site-nav {
  flex: 1;
  justify-content: space-between;
}
/* Neither group may reach the absolutely-centred logo. */
.header-layout--split .nav-links,
.header-layout--split .nav-utils { max-width: calc(50% - 2.5rem); }

/* utility-bar — a thin top row for language and account, the main row below
   with the pages and the contact button. Reads as a business that expects to
   be phoned: the utilities stop competing with navigation. */
.header-layout--utility-bar .header-inner {
  flex-wrap: wrap;
  align-items: center;
  padding-top: 0;
  padding-bottom: 0;
  min-height: 0;
  row-gap: 0;
}
/* `.site-nav` dissolves so its two groups become children of .header-inner —
   otherwise `width: 100%` on the utility strip measures the nav box and the
   "two rows" collapse back into one (which is exactly what happened first
   time round, and only geometry showed it). */
.header-layout--utility-bar .site-nav { display: contents; }
.header-layout--utility-bar .nav-utils {
  order: -1;
  width: 100%;
  justify-content: flex-end;
  gap: 1.1rem;
  padding: .45rem 0;
  border-bottom: 1px solid var(--line);
  font-size: .85rem;
}
.header-layout--utility-bar .nav-links {
  flex: 1;
  justify-content: flex-end;
  gap: 1.8rem;
  min-height: 64px;
}
/* The contact button stays IN the strip rather than the main row: it lives
   inside .nav-utils, and CSS cannot lift a child out of its group — the first
   attempt "moved" it by hiding it, which simply lost the call to action.
   Contact + account + language together read as one coherent utility strip
   anyway, with the pages left alone below. */
.header-layout--utility-bar .nav-utils .btn.btn-small {
  padding: .35rem 1rem;
  font-size: .8rem;
}

/* centered — logo on its own line, navigation centred beneath it. Editorial
   and calm; suits portfolios and restaurants more than a service business. */
.header-layout--centered .header-inner {
  flex-direction: column;
  gap: .2rem;
  padding-top: 1.1rem;
  padding-bottom: .8rem;
  min-height: 0;
}
.header-layout--centered .site-nav {
  width: 100%;
  justify-content: center;
  flex-wrap: wrap;
  gap: 1.4rem;
}
.header-layout--centered .logo-mark svg { width: 40px; height: 40px; }

/* ---------- Language switcher looks ----------
   Same markup — a flat list of codes — dressed four ways. It sits in the
   header next to everything else that repeats site to site, and two letters
   in the corner are exactly the kind of detail people register without
   noticing. */

/* plain — bare codes, active in the brand colour (the original). */

/* pills — each code its own chip; the active one filled. Reads deliberate,
   suits sites where the language choice actually matters to visitors. */
.lang-switch--pills { gap: .35rem; }
.lang-switch--pills a {
  padding: .2rem .55rem;
  border-radius: 999px;
  line-height: 1.5;
}
.lang-switch--pills a:hover { background: var(--hover-wash); color: var(--ink); }
.lang-switch--pills a.is-active {
  background: var(--primary);
  color: var(--primary-ink);
}

/* divided — codes split by a hairline, the quietest way to group them. */
.lang-switch--divided { gap: .5rem; }
.lang-switch--divided a + a { position: relative; padding-left: .6rem; }
.lang-switch--divided a + a::before {
  content: '';
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 1px;
  height: .9em;
  background: var(--line);
}

/* boxed — one segmented control. The most "app-like" of the four; good when
   the header is otherwise sparse and needs an anchor on the right. */
.lang-switch--boxed {
  gap: 0;
  border: 1px solid var(--line);
  border-radius: var(--radius-small, 8px);
  overflow: hidden;
}
.lang-switch--boxed a {
  padding: .2rem .6rem;
  line-height: 1.6;
}
.lang-switch--boxed a + a { border-left: 1px solid var(--line); }
.lang-switch--boxed a.is-active {
  background: var(--primary);
  color: var(--primary-ink);
}

/* ---------- Contact page layouts ----------
   The form is where a visitor actually acts, and one arrangement everywhere
   made every site's most important page identical. Same markup — an info
   column and a form column — arranged four ways. */

/* split — info left, form right (the original). */

/* form-first — the form leads and takes the width; details sit beside it.
   For businesses whose visitors already know they want to write. */
.contact-grid--form-first { grid-template-columns: 1.2fr .8fr; }
.contact-grid--form-first .contact-info { order: 2; }
.contact-grid--form-first .contact-form-wrap { order: 1; }

/* stacked — details as one quiet row on top, full-width form below. The
   calmest option and the one that reads best on a narrow screen. */
.contact-grid--stacked { grid-template-columns: 1fr; gap: 2.4rem; }
.contact-grid--stacked .contact-info {
  display: flex;
  flex-wrap: wrap;
  gap: 0 2.6rem;
}
.contact-grid--stacked .info-item {
  border-bottom: 0;
  padding: 0;
  min-width: 12rem;
}

/* card — the form raised on the section tint; details centred above it.
   Draws the eye to the form without moving anything else. */
.section--contact-card { background: var(--tint); }
.contact-grid--card { grid-template-columns: 1fr; gap: 2.2rem; max-width: 720px; margin-inline: auto; }
.contact-grid--card .contact-info {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0 2.4rem;
  text-align: center;
}
.contact-grid--card .info-item { border-bottom: 0; padding: .4rem 0; }
.contact-grid--card .contact-form-wrap {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 2rem;
}

/* ---------- Contact strip (home) looks ---------- */

/* inline — no card chrome, one row split by hairlines. */
.contact-cards--inline {
  grid-template-columns: 1fr;
  display: flex;
  flex-wrap: wrap;
  gap: 0;
}
.contact-cards--inline .contact-card {
  flex: 1 1 12rem;
  background: none;
  border: 0;
  border-left: 1px solid var(--line);
  border-radius: 0;
  padding: .4rem 1.6rem;
}
.contact-cards--inline .contact-card:first-child { border-left: 0; padding-left: 0; }

/* banner — one tinted band, details centred. Reads as a closing statement
   rather than a list of fields. */
.section--contacts-banner { background: var(--tint); }
.contact-cards--banner {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 1rem 3rem;
}
.contact-cards--banner .contact-card {
  background: none;
  border: 0;
  padding: 0;
  text-align: center;
}

/* ---------- Footer layouts ----------
   The footer carries every page too, and `layout.footer` only ever switched
   the whole grid on or off. These arrange the SAME three blocks — brand, menu,
   contacts — four ways. */

/* columns — brand wide, menu and contacts beside it (the original). */

/* brand-split — brand on the left, the two link groups pushed right together.
   Reads as a company signature rather than a sitemap. */
.footer-layout--brand-split .footer-grid {
  grid-template-columns: 1fr auto auto;
  gap: 3.5rem;
}

/* centered — one column, everything centred. Quiet close to a short site. */
.footer-layout--centered .footer-grid {
  grid-template-columns: 1fr;
  justify-items: center;
  text-align: center;
  gap: 1.8rem;
}
.footer-layout--centered .footer-about { margin-inline: auto; }
.footer-layout--centered .footer-nav,
.footer-layout--centered .footer-contacts {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: center;
  gap: .5rem 1.4rem;
}
.footer-layout--centered .footer-title { width: 100%; }

/* bar — one compact line: brand, links, contacts. No titles, minimal height;
   for sites whose footer is a formality, not a directory. */
.footer-layout--bar { padding-top: 1.6rem; }
.footer-layout--bar .footer-grid {
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 2rem;
  padding-bottom: 1.4rem;
}
.footer-layout--bar .footer-title { display: none; }
.footer-layout--bar .footer-about { display: none; }
/* flex-direction is spelled out because the base rule sets `column` — without
   it the "single bar" rendered four stacked links, which is the one thing this
   layout is not. */
.footer-layout--bar .footer-nav,
.footer-layout--bar .footer-contacts {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  gap: .4rem 1.3rem;
  font-size: .9rem;
}
.footer-layout--bar .footer-nav { justify-content: center; }
.footer-layout--bar .footer-contacts { justify-content: flex-end; }

/* ---------- Steps variants ---------- */

/* timeline — a horizontal run with a connecting rule; the numbers become the
   spine of the process instead of four separate tiles. */
.steps-grid--timeline { position: relative; gap: 1rem; }
.steps-grid--timeline::before {
  content: '';
  position: absolute;
  top: 1.15rem;
  left: 8%;
  right: 8%;
  height: 2px;
  background: var(--line);
}
.steps-grid--timeline .feature-card {
  background: none;
  border: 0;
  padding: 0 .8rem;
  text-align: center;
}
.steps-grid--timeline .feature-index {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.3rem;
  height: 2.3rem;
  margin-bottom: 1rem;
  border-radius: 999px;
  background: var(--primary);
  color: var(--primary-ink);
  font-size: .95rem;
}

/* stacked — a vertical ladder, one step per row. Best when steps carry real
   sentences rather than three words. */
.steps-grid--stacked { grid-template-columns: 1fr; gap: 0; }
.steps-grid--stacked .feature-card {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: .2rem 1.4rem;
  background: none;
  border: 0;
  border-bottom: 1px solid var(--line);
  border-radius: 0;
  padding: 1.3rem .2rem;
}
.steps-grid--stacked .feature-index {
  grid-row: 1 / 3;
  align-self: center;
  margin: 0;
  font-size: 1.9rem;
  color: color-mix(in srgb, var(--primary) 40%, var(--bg));
}

/* ---------- Stats variants ---------- */

/* cards — each figure in its own tile. */
.stats-row--cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
  gap: 1.2rem;
  border-top: 0;
  padding-top: 0;
}
.stats-row--cards > div {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.5rem;
  align-items: center;
  text-align: center;
}

/* band — a tinted full-width strip; the numbers become a statement. */
.section--stats-band { background: var(--tint); }
.stats-row--band {
  justify-content: space-around;
  border-top: 0;
  padding-top: 0;
  text-align: center;
}
.stats-row--band dd { font-size: 2.4rem; }

/* ---------- Story variants ---------- */

/* narrow — a centred reading column; the calmest way to tell it. */
.story-inner--narrow { max-width: 680px; text-align: center; }
.story-inner--narrow .lead { margin-inline: auto; }

/* quote — the opening paragraph set as a pull quote. For a founder's line or
   a promise worth slowing down for. */
.story-inner--quote .lead {
  font-family: var(--font-display);
  font-size: clamp(1.3rem, 2.6vw, 1.9rem);
  line-height: 1.45;
  color: var(--ink);
  border-left: 3px solid var(--mark, var(--primary));
  padding-left: 1.6rem;
  max-width: 46ch;
}

/* ---------- Section-variant responsiveness ----------
   Deliberately LAST in the file. The shared breakpoints above reset
   `.cards-grid` / `.quotes-grid` to 2 and 1 columns, and they carry the same
   specificity as the variant classes — so at equal weight the later rule
   wins, and anything placed next to the variant definitions further up would
   quietly lose on tablet. Keep these here. */

@media (max-width: 960px) {
  /* Both variants are single-column by design; the shared reset would put
     them back into a two-column grid. */
  .cards-grid--list,
  .cards-grid--alternating { grid-template-columns: 1fr; }

  .quotes-grid--spotlight { grid-template-columns: repeat(2, 1fr); }
  .gallery-grid--masonry { columns: 3; }
  .quotes-grid--strip { display: flex; }
}

@media (max-width: 640px) {
  .cards-grid--list,
  .cards-grid--alternating { grid-template-columns: 1fr; }

  /* Image over text: side-by-side at phone width leaves neither enough room,
     and the alternating rhythm is invisible in one column anyway. */
  .cards-grid--alternating .card,
  .cards-grid--alternating .card:not(:has(.card-media)) {
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: auto auto auto;
    gap: .9rem;
  }
  .cards-grid--alternating .card-media,
  .cards-grid--alternating .card:nth-child(even) .card-media {
    grid-row: 1;
    grid-column: 1;
    max-height: 11rem;
  }
  .cards-grid--alternating .card-body,
  .cards-grid--alternating .card:nth-child(even) .card-body { grid-row: 2; grid-column: 1; }
  .cards-grid--alternating .card-foot,
  .cards-grid--alternating .card:nth-child(even) .card-foot { grid-row: 3; grid-column: 1; }

  /* The list row keeps its shape but lets the price wrap under the title
     rather than squeezing the name into two characters. */
  .cards-grid--list .card { flex-wrap: wrap; gap: .8rem; }
  .cards-grid--list .card-foot { width: 100%; justify-content: flex-start; }

  .quotes-grid--spotlight { grid-template-columns: 1fr; }

  /* Footer and step layouts collapse on a phone: three columns of links do
     not fit, and a horizontal timeline becomes a line of crushed words. */
  .footer-layout--brand-split .footer-grid,
  .footer-layout--bar .footer-grid { grid-template-columns: 1fr; gap: 1.6rem; }
  .footer-layout--bar .footer-nav,
  .footer-layout--bar .footer-contacts { justify-content: flex-start; }

  .steps-grid--timeline::before { content: none; }
  .steps-grid--timeline .feature-card { text-align: left; padding: 0; }

  .stats-row--band { justify-content: flex-start; }

  /* Contact layouts all collapse to one column on a phone — a two-column
     form is unusable there whichever side it started on. */
  .contact-grid--form-first,
  .contact-grid--stacked,
  .contact-grid--card { grid-template-columns: 1fr; }
  .contact-grid--form-first .contact-info { order: 1; }
  .contact-grid--form-first .contact-form-wrap { order: 2; }
  .contact-cards--inline .contact-card {
    border-left: 0;
    border-top: 1px solid var(--line);
    padding: .9rem 0;
  }

  /* Below the burger breakpoint every header layout collapses to the same
     thing — logo + toggle, everything else inside the dropdown. Leaving a
     variant active here produced an absolutely-positioned logo over the
     menu button, which is the kind of break only a phone shows. */
  .header-layout--split .logo,
  .header-layout--centered .logo { position: static; transform: none; }
  .header-layout--split .header-inner,
  .header-layout--centered .header-inner,
  .header-layout--utility-bar .header-inner {
    flex-direction: row;
    flex-wrap: wrap;
    padding-top: 0;
    padding-bottom: 0;
    min-height: 78px;
  }
  .header-layout--utility-bar .nav-utils {
    order: 0;
    width: auto;
    border-bottom: 0;
    padding: 0;
  }

  /* `.site-nav` must go back to being a real box: it IS the dropdown the
     burger toggles, and `display: contents` leaves nothing to position — the
     menu items scattered into the header bar instead. Desktop-only trick,
     undone here. */
  .header-layout--utility-bar .site-nav { display: none; }
  .nav-checkbox:checked ~ .header-layout--utility-bar .site-nav,
  .header-layout--utility-bar .nav-checkbox:checked ~ .site-nav { display: flex; }

  .nav-links, .nav-utils { display: contents; }

  /* The multi-column variants collapse to one column on a phone; `columns`
     and CSS `columns:` both need saying, they are different properties. */
  .faq-list--columns { columns: 1; }
  .gallery-grid--masonry { columns: 2; }
  .rate-list--cards { grid-template-columns: 1fr; }
  .features-grid--numbered .feature-card { padding-right: 0; }
  .quotes-grid--spotlight .quote-card:first-child { padding: 1.6rem; }
  .quotes-grid--spotlight .quote-card:first-child blockquote { font-size: 1.25rem; }
}

/* --- native form controls ------------------------------------------------
   Everything else in a booking box is themed — the date input, the slot
   chips, the textarea, the button — and then the master picker rendered as
   a raw operating-system dropdown in the middle of it. Blue system highlight,
   system font, square corners, next to 24px-radius cards.

   `select` was simply never styled here, and neither were checkboxes,
   radios or file inputs: a theme styles what its own pages happen to use,
   and a control that arrives with a feature (bookings, in this case) slips
   through. So this block covers the native set once, from the tokens.

   The arrow needs a wrapper because a `select` cannot carry ::after and a
   background-image would hard-code its colour outside the token system. */
.select-wrap { position: relative; display: inline-flex; }
.select-wrap::after {
  content: '';
  position: absolute; right: .85rem; top: 50%;
  width: .45rem; height: .45rem;
  border-right: 1.5px solid var(--muted);
  border-bottom: 1.5px solid var(--muted);
  transform: translateY(-70%) rotate(45deg);
  pointer-events: none;
}

select,
.select-wrap select {
  appearance: none; -webkit-appearance: none;
  padding: .7rem 2.4rem .7rem 1rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-small);
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: .95rem;
  line-height: 1.2;
  cursor: pointer;
}
select:focus-visible,
input:focus-visible,
textarea:focus-visible {
  outline: 2px solid var(--mark, var(--primary));
  outline-offset: 2px;
  border-color: var(--mark, var(--primary));
}

/* Checkbox/radio: only the accent colour, so the native control keeps its
   platform behaviour (and its keyboard handling) and just stops being blue. */
input[type='checkbox'],
input[type='radio'] { accent-color: var(--mark, var(--primary)); }

input[type='file'] { font-family: var(--font-body); font-size: .95rem; color: var(--ink); }

/* ===========================================================================
   Section library, part two.

   Seven sections that answer questions the sections above do not: who works
   here and when, what it costs read as a menu, what the result looks like,
   how to get here. Each is optional — none renders without the content it
   needs, so a theme that lists them all still shows only what the site has.

   Same rules as everything above: colours only through var(--*), so the
   Design panel drives these too.
   =========================================================================== */

/* --- trust bar ----------------------------------------------------------- */
.trust {
    background: var(--surface);
    border-top: 1px solid var(--line);
    border-bottom: 1px solid var(--line);
    padding: 2rem 0;
}
.trust--band { background: var(--primary); border-color: var(--primary); }
.trust--band .trust__figure { color: var(--accent); }
.trust--band .trust__label  { color: var(--primary-ink); opacity: .75; }

.trust__list {
    list-style: none; margin: 0; padding: 0;
    display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.5rem;
}
.trust__item { display: flex; flex-direction: column; gap: .35rem; text-align: center; }
.trust__figure {
    font-family: var(--font-display);
    font-size: 1.75rem; line-height: 1.1; color: var(--mark, var(--primary));
}
.trust__label { font-size: .85rem; color: var(--muted); }

/* --- specialists --------------------------------------------------------- */
.masters__grid {
    display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.5rem;
}
.master {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--radius);
    overflow: hidden;
    display: flex; flex-direction: column;
}
.master__photo { width: 100%; aspect-ratio: 3 / 4; object-fit: cover; display: block; }
.master__body { padding: 1.25rem; display: flex; flex-direction: column; gap: .5rem; }
.master__name { font-size: 1.1rem; margin: 0; }
.master__role { color: var(--muted); font-size: .9rem; margin: 0; }

/* The schedule is a table without being one: label left, hours right, a dotted
   leader between them. Days off are dimmed but never hidden — "nobody works
   Wednesday" is information too. */
.master__hours { list-style: none; margin: .5rem 0 0; padding: 0; font-size: .82rem; }
.master__day {
    display: flex; align-items: baseline; gap: .4rem;
    padding: .18rem 0; color: var(--ink);
}
.master__day + .master__day { border-top: 1px dotted var(--line); }
.master__day.is-off { color: var(--muted); }
.master__daylabel { text-transform: uppercase; letter-spacing: .04em; font-size: .72rem; color: var(--muted); }
.master__span { margin-left: auto; font-variant-numeric: tabular-nums; }

/* --- gift card ----------------------------------------------------------- */
.gift__inner {
    display: grid; grid-template-columns: 1.1fr .9fr; gap: 3rem; align-items: center;
}
.gift__lead { color: var(--muted); font-size: 1.05rem; }
.gift__points { list-style: none; margin: 1.25rem 0 0; padding: 0; display: grid; gap: .6rem; }
.gift__points li { position: relative; padding-left: 1.4rem; color: var(--ink); }
.gift__points li::before {
    content: '✦'; position: absolute; left: 0; top: 0; color: var(--accent);
}

/* The ticket itself is typography and tokens, not an image: change the palette
   and it changes with it, with no new asset file. */
.gift__ticket {
    background: var(--primary); color: var(--primary-ink);
    border-radius: var(--radius);
    padding: 2.5rem 2rem;
    display: flex; flex-direction: column; align-items: center; gap: .5rem;
    text-align: center;
    position: relative;
    overflow: hidden;
}
.gift__ticket::after {
    /* a thin gold rule inside — the small detail that reads as expensive */
    content: ''; position: absolute; inset: .6rem;
    border: 1px solid color-mix(in srgb, var(--accent) 55%, transparent);
    border-radius: calc(var(--radius) - .4rem);
    pointer-events: none;
}
.gift__ticket-brand {
    font-family: var(--font-display); font-size: 1.35rem; letter-spacing: .08em;
}
.gift__ticket-amount { font-family: var(--font-display); font-size: 3rem; line-height: 1; color: var(--accent); }
.gift__ticket-note { font-size: .85rem; opacity: .75; }

.gift__form { display: flex; align-items: end; gap: .75rem; margin-top: 1.25rem; }
.gift__qty-label { display: block; font-size: .78rem; color: var(--muted); margin-bottom: .25rem; }
.gift__qty {
    width: 4.5rem; padding: .7rem; border: 1px solid var(--line);
    border-radius: var(--radius-small); background: var(--surface); color: var(--ink);
}

/* --- before / after ------------------------------------------------------ */
.section-head--center { text-align: center; justify-content: center; }
.section-head--center .section-lead { color: var(--muted); max-width: 44ch; margin: .5rem auto 0; }

@media (max-width: 900px) {
    .trust__list      { grid-template-columns: repeat(2, 1fr); }
    .masters__grid    { grid-template-columns: repeat(2, 1fr); }
    .gift__inner      { grid-template-columns: 1fr; gap: 2rem; }
}
@media (max-width: 560px) {
    .masters__grid    { grid-template-columns: 1fr; }
    .gift__ticket-amount { font-size: 2.4rem; }
}
/* Before/after — platform component (shop/stubs/components/before-after).

   GEOMETRY. The whole state is one CSS variable, --ba-pos (0–100, percent of
   the container's width). The after image is clipped with
   clip-path: inset(0 0 0 var(--ba-pos)) — i.e. its LEFT part is hidden, so
   left of the divider you see "before", right of it "after". The divider
   line sits at left: var(--ba-pos). The JS only ever writes --ba-pos;
   everything that moves derives from it here, so the image and the line can
   never drift apart. */

.ba-section {
    padding: 2.8rem 0;
}

.ba {
    --ba-pos: 50%;
    position: relative;
    overflow: hidden;
    border-radius: var(--radius, 14px);
    /* Vertical drags scroll the page; horizontal ones are ours. */
    touch-action: pan-y;
    user-select: none;
    -webkit-user-select: none;
}

.ba__img {
    display: block;
    width: 100%;
    height: auto;
}

.ba__img--after {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    clip-path: inset(0 0 0 var(--ba-pos));
}

.ba__divider {
    position: absolute;
    top: 0;
    bottom: 0;
    left: var(--ba-pos);
    width: 2px;
    margin-left: -1px;
    background: #fff;
    box-shadow: 0 0 8px rgba(0, 0, 0, .45);
    pointer-events: none;
}

.ba__handle {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    display: flex;
    align-items: center;
    justify-content: center;
    width: 40px;
    height: 40px;
    border-radius: 999px;
    background: #fff;
    color: #111;
    font-size: 1.1rem;
    box-shadow: 0 2px 10px rgba(0, 0, 0, .35);
}

/* The range input is the REAL control: invisible but full-size, so it takes
   pointer events natively and stays focusable for the keyboard. Opacity 0 —
   not display:none, which would remove it from the accessibility tree. */
.ba__range {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    opacity: 0;
    cursor: ew-resize;
}

.ba__range:focus-visible ~ .ba__divider .ba__handle,
.ba:has(.ba__range:focus-visible) .ba__handle {
    outline: 2px solid var(--primary, #2563eb);
    outline-offset: 2px;
}

.ba__label {
    position: absolute;
    top: 1rem;
    padding: .25rem .7rem;
    border-radius: 999px;
    background: rgba(0, 0, 0, .55);
    color: #fff;
    font-size: .8rem;
    letter-spacing: .04em;
    text-transform: uppercase;
    pointer-events: none;
}

.ba__label--before { left: 1rem; }
.ba__label--after { right: 1rem; }

/* --- the price list as a menu -------------------------------------------- */
.price-menu__list { list-style: none; margin: 0; padding: 0; }
.price-menu__row + .price-menu__row { border-top: 1px solid var(--line); }
.price-menu__link {
    display: flex; align-items: baseline; gap: 1rem;
    padding: 1.35rem 0 .35rem;
    text-decoration: none; color: var(--ink);
}
.price-menu__name {
    font-family: var(--font-display); font-size: 1.35rem; line-height: 1.2;
    transition: color .18s ease;
}
.price-menu__link:hover .price-menu__name { color: var(--mark, var(--primary)); }
/* The dotted leader is exactly what makes this a menu rather than a table. */
.price-menu__leader {
    flex: 1 1 auto; min-width: 2rem;
    border-bottom: 1px dotted var(--line);
    transform: translateY(-.35rem);
}
.price-menu__meta { display: inline-flex; align-items: baseline; gap: .9rem; white-space: nowrap; }
.price-menu__time { font-size: .85rem; color: var(--muted); font-variant-numeric: tabular-nums; }
.price-menu__price {
    font-family: var(--font-display); font-size: 1.35rem; color: var(--mark, var(--primary));
    font-variant-numeric: tabular-nums;
}
.price-menu__note { margin: 0 0 1.35rem; color: var(--muted); font-size: .95rem; max-width: 62ch; }

/* The floating preview: fixed + transform, so its position depends on neither
   scrolling nor how deeply it is nested. */
.price-menu__preview {
    position: fixed; top: 0; left: 0; z-index: 40;
    width: 260px; pointer-events: none;
    opacity: 0; transition: opacity .18s ease;
    will-change: transform;
}
.price-menu__preview.is-on { opacity: 1; }
.price-menu__preview img {
    width: 100%; aspect-ratio: 4 / 3; object-fit: cover;
    border-radius: var(--radius); display: block;
    box-shadow: 0 18px 40px rgba(0, 0, 0, .22);
}

/* --- questions in two columns -------------------------------------------- */
.faq-split__grid { display: grid; grid-template-columns: .8fr 1.2fr; gap: 3.5rem; }
.faq-split__aside { position: sticky; top: 6rem; align-self: start; }
.faq-split__lead { color: var(--muted); margin-top: .75rem; }
.faq-split__contacts { display: flex; flex-direction: column; gap: .9rem; margin-top: 1.5rem; align-items: start; }
.faq-split__phone { font-family: var(--font-display); font-size: 1.4rem; color: var(--mark, var(--primary)); text-decoration: none; }

.faq-split__list { counter-reset: faq; }
.faq-split__item { border-top: 1px solid var(--line); }
.faq-split__item:last-child { border-bottom: 1px solid var(--line); }
.faq-split__item summary {
    display: flex; align-items: center; gap: 1rem;
    padding: 1.35rem 0; cursor: pointer; list-style: none;
}
.faq-split__item summary::-webkit-details-marker { display: none; }
/* Numbering by counter: add a question in the panel and it renumbers itself. */
.faq-split__item summary::before {
    counter-increment: faq; content: counter(faq, decimal-leading-zero);
    font-family: var(--font-display); font-size: .95rem; color: var(--accent);
}
.faq-split__q { font-size: 1.1rem; }
.faq-split__sign { margin-left: auto; width: 1.1rem; height: 1.1rem; position: relative; flex: none; }
.faq-split__sign::before, .faq-split__sign::after {
    content: ''; position: absolute; inset: 50% 0 auto 0;
    height: 1px; background: var(--ink); transition: transform .2s ease;
}
.faq-split__sign::after { transform: rotate(90deg); }
.faq-split__item[open] .faq-split__sign::after { transform: rotate(0deg); }
.faq-split__a { padding: 0 0 1.35rem 2.5rem; color: var(--muted); max-width: 62ch; }

/* --- how to get here ----------------------------------------------------- */
.visit__grid { display: grid; grid-template-columns: .85fr 1.15fr; gap: 2.5rem; align-items: stretch; }
.visit__facts { display: grid; gap: 1.75rem; align-content: start; }
.visit__fact { display: flex; flex-direction: column; gap: .35rem; }
.visit__label { text-transform: uppercase; letter-spacing: .12em; font-size: .7rem; color: var(--muted); }
.visit__value { font-size: 1.05rem; color: var(--ink); }
.visit__value--link { color: var(--mark, var(--primary)); text-decoration: none; }
.visit__value--link:hover { text-decoration: underline; }
.visit__hint { font-size: .85rem; color: var(--muted); }
.visit__cta { margin-top: .75rem; align-self: start; }

.visit__week { list-style: none; margin: .25rem 0 0; padding: 0; font-size: .9rem; max-width: 20rem; }
.visit__day { display: flex; justify-content: space-between; gap: 1rem; padding: .25rem 0; }
.visit__day + .visit__day { border-top: 1px dotted var(--line); }
.visit__day.is-off { color: var(--muted); }

.visit__map { position: relative; min-height: 340px; border-radius: var(--radius); overflow: hidden; border: 1px solid var(--line); }
.visit__map iframe { width: 100%; height: 100%; min-height: 340px; border: 0; display: block; filter: grayscale(.35) contrast(1.05); }
.visit__map-link {
    /* Top-aligned: the OpenStreetMap attribution sits along the bottom of the
       map and must not be covered — that is a licence condition, not taste. */
    position: absolute; right: .75rem; top: .75rem;
    background: var(--surface); color: var(--ink); text-decoration: none;
    padding: .5rem .85rem; border-radius: var(--radius-small);
    font-size: .8rem; box-shadow: 0 6px 18px rgba(0,0,0,.14);
}

@media (max-width: 900px) {
    .faq-split__grid { grid-template-columns: 1fr; gap: 2rem; }
    .faq-split__aside { position: static; }
    .visit__grid { grid-template-columns: 1fr; }
    .price-menu__link { flex-wrap: wrap; }
    .price-menu__leader { display: none; }
    .price-menu__meta { margin-left: auto; }
}


/* --- products -------------------------------------------------------------
   Goods, not services. The card leads with the picture and ends with a price
   that has to read as a price — which is why the price gets its own weight
   and sits on the baseline with the link rather than inside the prose.

   Everything is token-driven; a literal here would leave one shelf behind
   when the owner changes the palette. */
.products-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1.4rem;
}
.products-grid--cols-2 { grid-template-columns: repeat(2, 1fr); }
.products-grid--cols-3 { grid-template-columns: repeat(3, 1fr); }
.products-grid--cols-4 { grid-template-columns: repeat(4, 1fr); }

.product-card { overflow: hidden; }

.product-card__media {
  display: block;
  aspect-ratio: 4 / 3;
  background: var(--hover-wash);
  overflow: hidden;
}
.product-card__media img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* No photo yet: a drawn mark on the theme's own wash. A grey box reads as a
   broken image, and a stock photo would be somebody else's product. */
.product-card__mark {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  color: var(--muted);
  opacity: .5;
}
.product-card__mark svg { width: 38%; max-width: 72px; }

.product-card h3 { font-size: 1.05rem; margin-bottom: .35rem; }
.product-card p { font-size: .92rem; color: var(--body-text); margin: 0; }

.product-card__foot {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  margin-top: auto;
  padding-top: 1rem;
}
.product-card__price {
  font-family: var(--font-display);
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--ink);
}

/* list — one per row, picture small on the left, price hard right. The shape
   a price list wants when the photographs are not the selling point. */
.products-grid--list { grid-template-columns: 1fr; gap: 0; }
.products-grid--list .product-card {
  flex-direction: row;
  align-items: center;
  gap: 1.4rem;
  border-radius: 0;
  border-width: 0 0 1px;
  padding: 1.1rem .4rem;
}
.products-grid--list .product-card:first-child { border-top: 1px solid var(--line); }
.products-grid--list .product-card__media {
  width: 96px;
  flex: 0 0 96px;
  aspect-ratio: 1;
  border-radius: var(--radius-small);
}
.products-grid--list .card-body { display: flex; align-items: center; gap: 1.4rem; flex: 1; }
.products-grid--list .product-card__foot { margin: 0; padding: 0; flex: 0 0 auto; }

/* showcase — the first item double-width. One shelf, one hero product, and
   no new section to maintain. */
.products-grid--showcase .product-card:first-child { grid-column: span 2; grid-row: span 2; }
.products-grid--showcase .product-card:first-child .product-card__media { aspect-ratio: 1; }

/* --- product page --------------------------------------------------------- */
.product-detail {
  display: grid;
  grid-template-columns: 1.1fr 1fr;
  gap: clamp(1.5rem, 4vw, 3.5rem);
  align-items: start;
}
.product-detail__media img { width: 100%; border-radius: var(--radius); display: block; }
.product-detail__thumbs {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: .6rem;
  margin-top: .6rem;
}
.product-detail__thumbs img { aspect-ratio: 1; object-fit: cover; border-radius: var(--radius-small); }
.product-detail__price {
  font-family: var(--font-display);
  font-size: clamp(1.6rem, 3vw, 2.2rem);
  font-weight: 700;
  margin-bottom: 1.2rem;
}

@media (max-width: 900px) {
  .products-grid, .products-grid--cols-3, .products-grid--cols-4 { grid-template-columns: repeat(2, 1fr); }
  .products-grid--showcase .product-card:first-child { grid-column: span 2; grid-row: auto; }
  .product-detail { grid-template-columns: 1fr; }
}
@media (max-width: 560px) {
  .products-grid, .products-grid--cols-2, .products-grid--cols-3, .products-grid--cols-4 { grid-template-columns: 1fr; }
  .products-grid--list .card-body { flex-direction: column; align-items: flex-start; gap: .6rem; }
}

/* No photograph: one column, and the body keeps a readable measure instead of
   stretching to the full container. */
.product-detail--textonly { grid-template-columns: minmax(0, 62ch); }

/* The error page's one action — spaced away from the message above and from
   whatever the layout puts below, so the page ends deliberately. */
.error-actions {
  margin: clamp(1.6rem, 3vw, 2.4rem) 0 clamp(3rem, 6vw, 5rem);
}

/* --- lightbox (platform component — the overlay only) ---------------------
   The component file also ships an example grid (`.gallery-section` /
   `.gallery-grid` / `.gallery-item`) as a demonstration host for its markup.
   Pasted in whole, that grid overrides the theme's OWN gallery: the layout
   became a five-column grid instead of masonry, and square cells holding
   height:auto images left empty bands under every photo — which is exactly what
   looked like "captions that will not display".

   So we take precisely the overlay from it. The theme keeps its own gallery
   markup, and the component's contract is just that: <a data-lightbox> around
   an <img>. */
/* --- Overlay (JS-built, lives directly under <body>) ------------------- */

.lightbox {
    position: fixed;
    inset: 0;
    z-index: 1000;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgba(0, 0, 0, .92);
    animation: lightbox-in .2s ease;
}

@keyframes lightbox-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}

.lightbox__figure {
    margin: 0;
    max-width: min(92vw, 1400px);
    max-height: 88vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: .8rem;
}

.lightbox__img {
    max-width: 100%;
    max-height: 80vh;
    object-fit: contain;
    border-radius: 6px;
}

.lightbox__caption {
    color: rgba(255, 255, 255, .85);
    font-size: .95rem;
    text-align: center;
    min-height: 1.2em;
}

.lightbox__counter {
    position: absolute;
    top: 1rem;
    left: 1.2rem;
    color: rgba(255, 255, 255, .6);
    font-size: .9rem;
    font-variant-numeric: tabular-nums;
}

/* Controls: real buttons, big hit areas, visible on keyboard focus. */
.lightbox__btn {
    position: absolute;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 46px;
    height: 46px;
    padding: 0;
    border: 0;
    border-radius: 999px;
    background: rgba(255, 255, 255, .12);
    color: #fff;
    font-size: 1.3rem;
    line-height: 1;
    cursor: pointer;
    transition: background .2s ease;
}

.lightbox__btn:hover,
.lightbox__btn:focus-visible {
    background: rgba(255, 255, 255, .28);
}

.lightbox__close {
    top: 1rem;
    right: 1.2rem;
}

.lightbox__prev,
.lightbox__next {
    top: 50%;
    transform: translateY(-50%);
}

.lightbox__prev { left: 1.2rem; }
.lightbox__next { right: 1.2rem; }

@media (max-width: 700px) {
    /* On phones the arrows would cover the photo — swipe and the keyboard
       still work, so tuck them under the image instead of hiding them. */
    .lightbox__prev,
    .lightbox__next {
        top: auto;
        bottom: 1rem;
        transform: none;
    }
    .lightbox__prev { left: 20%; }
    .lightbox__next { right: 20%; }
}

/* Body scroll lock while the overlay is open (class set by the JS). */
body.lightbox-open {
    overflow: hidden;
}

@media (prefers-reduced-motion: reduce) {
    .lightbox { animation: none; }
    .gallery-item img { transition: none; }
}


/* ── Lattice knobs: what the eye reads first ───────────────────────────── */
/* rhythm: every second section on a tint (the shapes never set --alt themselves) */
.rhythm-bands main > .section:nth-of-type(even) { background: var(--tint); }
.rhythm-flat main > .section--alt { background: transparent; }
/* cards: outline (stock) | shadow | flat */
.cards-shadow .card, .cards-shadow .feature-card, .cards-shadow .quote-card, .cards-shadow .team-card { border-color: transparent; box-shadow: 0 12px 32px -20px var(--ink), 0 1px 2px color-mix(in srgb, var(--ink) 8%, transparent); }
.cards-flat .card, .cards-flat .feature-card, .cards-flat .quote-card, .cards-flat .team-card { border: 0; background: var(--primary-soft); }
/* headings: centred section heads */
.headings-center .section-head { flex-direction: column; align-items: center; text-align: center; }
.headings-center .section-head .lead { margin-inline: auto; }
/* split with media: a photograph beside the story */
.lt-split--left .story-inner, .lt-split--right .story-inner { display: grid; grid-template-columns: 1.1fr 1fr; gap: 3rem; align-items: center; }
.lt-split--left .story-media { order: -1; }
.story-media img { width: 100%; aspect-ratio: 4/3; object-fit: cover; border-radius: var(--radius); }
@media (max-width: 860px) { .lt-split--left .story-inner, .lt-split--right .story-inner { grid-template-columns: 1fr; } .lt-split--left .story-media { order: 0; } }

/* Availability badge. Deliberately quiet: it sits beside the price, and a
   green pill shouting "In stock" on every card turns the shelf into noise.
   Colour carries the meaning only where the meaning is a warning — sold out
   and pre-order — while the ordinary case reads as plain small print.
   Built on --primary/--muted rather than hard-coded green and red, so it
   inherits whatever palette the site was generated with. */
.product-card__stock,
.product-detail__stock {
  font-size: .78rem;
  letter-spacing: .02em;
  color: var(--muted);
  white-space: nowrap;
}

/* The foot was built for two children — price left, link right — and a third
   one silently pushed «Детальніше» off the card in a four-column grid. The
   badge is the one that yields: it wraps onto its own line rather than
   squeezing the link, because a truncated call to action is a broken card
   while a badge on the next line is just a badge on the next line.
   Caught in a screenshot; the selector check called it visible and it was —
   the link beside it was not. */
.product-card__foot { flex-wrap: wrap; }
.product-card__stock { flex: 1 0 100%; order: -1; margin-bottom: .15rem; }
.product-card__stock--in_stock,
.product-detail__stock--in_stock { color: var(--mark, var(--primary)); }
.product-card__stock--out_of_stock,
.product-detail__stock--out_of_stock { opacity: .7; text-decoration: line-through; }
.product-card__stock--pre_order,
.product-detail__stock--pre_order { font-style: italic; }

.product-detail__stock {
  font-size: .9rem;
  margin: -.8rem 0 1.2rem;
}
