/* =========================================================================
   sections.css — per-section composition.
   Stage 1: §2 hero + the flavour marquee bar.
   §3–§12 land in Stages 2–3.
   ========================================================================= */

/* =========================================================================
   §2 HERO
   Sticky so the following content slides up over the scrubbed bottom
   corners — the signature move borrowed from the reference.
   ========================================================================= */
.hero {
  position: sticky;
  top: 0;
  z-index: var(--z-below);
  height: 100vh;
  height: 100svh;
  min-height: 560px;
  overflow: hidden;
  display: grid;
  grid-template-rows: 1fr auto;
  isolation: isolate;
  /* Scrubbed 0 -> --r-lg across the first 100vh. One of the four sanctioned
     non-transform animations (C5); isolated on its own layer. */
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
  will-change: border-radius;
  background: var(--sand);
}

/* ---- Photo + its designed fallback --------------------------------------
   The fallback is NOT the product placeholder. It is a composed layer that
   must look deliberate: a cream -> sand radial wash plus an oversized
   low-opacity line-art roll offset to the right. It sits underneath the
   photo at all times, so a failed load reveals a finished design. */
.hero__fallback {
  position: absolute;
  inset: 0;
  z-index: 0;
  background:
    radial-gradient(120% 90% at 18% 15%, var(--cream) 0%, rgba(var(--cream-rgb), 0) 62%),
    radial-gradient(100% 100% at 78% 78%, var(--sand) 0%, #EBD3B4 100%);
  overflow: hidden;
}
.hero__fallback-art {
  position: absolute;
  top: 50%;
  right: -8vw;
  width: min(78vh, 72vw);
  aspect-ratio: 1;
  transform: translateY(-50%) rotate(-8deg);
  color: var(--cocoa);
  opacity: .13;
}
.hero__fallback-art svg { width: 100%; height: 100%; }

/* ---- Slide stack --------------------------------------------------------
   The parallax and the Ken Burns must not contest one property. The STACK
   carries the parallax on `transform` plus a fixed 1.06 overscan on `scale`
   so the ±15px never exposes an edge; each SLIDE IMAGE carries the Ken
   Burns on its own independent `scale`. Two elements, two properties,
   no fight. */
.hero__slides {
  position: absolute;
  inset: 0;
  z-index: 1;
  will-change: transform;
  scale: 1.06;
}
.hero__slide {
  position: absolute;
  inset: 0;
  opacity: 0;
  /* Crossfade. Slower in than out is what makes it read as a dissolve
     rather than a cut. */
  transition: opacity 1.2s var(--ease-in-out);
}
.hero__slide.is-active { opacity: 1; }
/* A slide whose image 404s is skipped by the slider and never faded to. */
.hero__slide.is-broken { display: none; }

.hero__slide picture { display: contents; }
.hero__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  /* Ken Burns: 1.0 -> 1.06 across the slide's full visible life
     (1.2s crossfade + 6s dwell). Reset is DELAYED by the crossfade
     duration so the outgoing slide snaps back only once it is invisible —
     resetting immediately would pop while it is still 60% opaque. */
  scale: 1;
  transition: scale 0s linear 1.2s;
}
.hero__slide.is-active .hero__img {
  scale: 1.06;
  transition: scale 7.2s linear 0s;
}
/* Paused: freeze the zoom where it is rather than letting it run on
   under a pointer that has stopped the carousel. */
.hero__slides.is-paused .hero__slide.is-active .hero__img { transition: none; }

.hero.is-photoless .hero__slides { display: none; }

/* ---- Slide indicators ---------------------------------------------------
   Hidden without JS: the slider cannot run, so these would be controls
   that do nothing. Same rule the widgets follow. */
.hero__dots { display: none; }
html.js .hero__dots {
  position: absolute;
  z-index: 5;
  right: var(--pad-gutter);
  bottom: clamp(48px, 8vh, 110px);
  display: flex;
  gap: 0;
}
/* The BUTTON is the hit target and the ::after is the visible dot.
   The obvious alternative — a 10px button with a negative-inset ::before
   for reach — is wrong: an inset larger than half the gap makes each
   target overlap its neighbour, and the click lands on the wrong dot.
   Sizing the button itself makes overlap impossible by construction, and
   28px clears the 24px minimum target size without forcing the dots so
   far apart that they stop reading as a pair. */
.hero__dot {
  position: relative;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 0;
  background: none;
  border-radius: 50%;
  cursor: pointer;
}
.hero__dot::after {
  content: '';
  position: absolute;
  inset: 9px;                 /* 28 - 2*9 = 10px dot */
  border-radius: 50%;
  background: rgba(var(--cream-rgb), .4);
  transition: background-color var(--dur-fast) var(--ease-out),
              scale var(--dur-fast) var(--ease-spring);
}
.hero__dot:hover::after { background: rgba(var(--cream-rgb), .7); }
.hero__dot.is-active::after { background: var(--cream); scale: 1.2; }
.hero__dot:active::after { scale: .85; }
.hero__dot:focus-visible {
  outline: var(--focus-ring);
  outline-offset: var(--focus-offset);
  box-shadow: var(--focus-halo);
}

/* ---- Overlays -----------------------------------------------------------
   Two layers, deliberately: a cream wash warms the whole photo, and a
   bottom ink scrim carries the text. Alpha .88 is computed, not guessed —
   see --hero-scrim in tokens.css. */
.hero__wash {
  position: absolute;
  inset: 0;
  z-index: 2;
  background: rgba(var(--cream-rgb), .18);
  pointer-events: none;
}
/* TWO bands, not one. The bottom carries the headline; the top carries the
   nav — which is cream-on-transparent over a hero whose top is light
   whenever the photo is missing or bright. Without the top band the nav
   links measured 1.5:1 against the CSS fallback. At the nav's centreline
   (~5.6% of viewport height) the top band composites to ~.68 alpha, giving
   cream 6.3:1. Computed, not guessed. */
.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  background:
    linear-gradient(
      to bottom,
      rgba(var(--ink-rgb), .78) 0%,
      rgba(var(--ink-rgb), .62) 9%,
      rgba(var(--ink-rgb), .22) 18%,
      rgba(var(--ink-rgb), 0) 30%
    ),
    linear-gradient(
      to top,
      rgba(var(--ink-rgb), var(--hero-scrim)) 0%,
      rgba(var(--ink-rgb), .55) 30%,
      rgba(var(--ink-rgb), .12) 52%,
      rgba(var(--ink-rgb), 0) 68%
    );
}

/* ---- Headline scrim -----------------------------------------------------
   The vertical band above is tuned for the BOTTOM of the hero. A two-line
   158px headline reaches up to 45% of the viewport, where that gradient has
   faded to ~.12 — and cream on a high-key photograph at .12 measures
   1.28:1. Invisible.

   Cranking the vertical band would work and would also turn the middle of
   the photograph to mud, which is the whole subject. The headline is
   left-aligned and occupies roughly the left half, so the fix is
   two-dimensional: darken the LEFT of the lower frame and leave the right
   — where the rolls are — clear. The mask fades this layer's own top edge
   so it never shows as a horizontal seam. */
.hero__scrim::after {
  content: '';
  position: absolute;
  inset: 30% 0 0 0;
  background: linear-gradient(
    to right,
    rgba(var(--ink-rgb), var(--hero-scrim-text)) 0%,
    rgba(var(--ink-rgb), calc(var(--hero-scrim-text) - .04)) 36%,
    rgba(var(--ink-rgb), calc(var(--hero-scrim-text) * .42)) 58%,
    rgba(var(--ink-rgb), 0) 76%
  );
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 14%);
          mask-image: linear-gradient(to bottom, transparent 0%, #000 14%);
}

/* ---- Content ------------------------------------------------------------ */
.hero__content {
  position: relative;
  z-index: 4;
  grid-row: 1 / -1;
  align-self: end;
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--pad-gutter);
  /* 104px floor, same clearance the footer uses. The assistant launcher is
     fixed at bottom 24px and 60px tall, on the LEFT — exactly where this
     left-aligned text sits. At a 900px-tall viewport the tagline's first
     letter ran under it. Measured, not predicted: the contrast probe kept
     reporting the launcher's hot pink as the tagline's background. */
  padding-bottom: max(clamp(48px, 8vh, 110px), 104px);
}

.hero__title {
  color: var(--cream);
  margin: 0;
  /* Each line is a mask the chars rise out of. */
}
.hero__line {
  display: block;
  overflow: hidden;
  padding-block: .04em; /* stops descenders being clipped by the mask */
}
.hero__line-in { display: block; }
/* SplitText writes its own inline styles; this only adds the layer hint,
   which animations.js clears on completion. */
.hero__char { will-change: transform; }
.hero__script {
  display: block;
  margin-top: clamp(var(--s-3), 1.4vw, var(--s-6));
  color: var(--hot-pink);
  /* 4.43:1 on the .88 ink scrim — computed. Held at large-text sizes only. */
}

/* ---- Rotating badge, top-right ------------------------------------------
   Three nested elements on purpose:
     .hero__badge      — position + magnetic translate (JS writes transform)
     .hero__badge-spin — the CSS rotation
     svg               — never transformed; rotating the SVG node instead of a
                         wrapper spins about the user-space origin, not the
                         glyph circle, and throws the badge off-screen. */
.hero__badge {
  display: block;
  position: absolute;
  z-index: 5;
  top: calc(var(--nav-h) + clamp(var(--s-4), 3vh, var(--s-12)));
  right: var(--pad-gutter);
  width: clamp(104px, 12vw, 168px);
  aspect-ratio: 1;
  border-radius: 50%;
  will-change: transform;
}
.hero__badge-spin {
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background: var(--hot-pink);
  display: grid;
  place-items: center;
  animation: cb-spin 20s linear infinite;
  transition: scale var(--dur-mid) var(--ease-spring);
}
.hero__badge:hover .hero__badge-spin,
.hero__badge:focus-visible .hero__badge-spin {
  animation-play-state: paused;
  scale: 1.08;
}
.hero__badge svg { width: 100%; height: 100%; overflow: visible; }
.hero__badge text {
  font-family: var(--font-ui);
  font-size: 15px;
  font-weight: 700;
  letter-spacing: .04em;
  fill: var(--ink); /* 6.07:1 on hot pink */
  text-transform: uppercase;
}
/* Sibling of the spinner, not a child — the mark must stay upright while
   the ring rotates around it. */
.hero__badge-mark {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 42%;
  color: var(--ink); /* 6.07:1 on hot pink */
  pointer-events: none;
}

/* ---- Scroll cue ---------------------------------------------------------- */
.hero__cue {
  position: absolute;
  z-index: 5;
  left: 50%;
  bottom: clamp(var(--s-4), 2.4vh, var(--s-8));
  transform: translateX(-50%);
  display: grid;
  justify-items: center;
  gap: var(--s-2);
  color: var(--cream);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .22em;
  text-transform: uppercase;
  pointer-events: none;
}
.hero__cue-line {
  width: 1px;
  height: 42px;
  background: linear-gradient(to bottom, rgba(var(--cream-rgb), .9), rgba(var(--cream-rgb), 0));
  transform-origin: top center;
  animation: cb-cue 2.2s var(--ease-in-out) infinite;
}

@media (max-width: 600px) {
  /* Kept top-right rather than dropped down the hero: at 360 a bottom-anchored
     badge lands directly on top of "ROLNICE". */
  .hero__badge {
    width: 88px;
    top: calc(var(--nav-h) + var(--s-3));
    right: var(--pad-gutter);
    bottom: auto;
  }
  .hero__badge text { font-size: 17px; }
  .hero__cue { display: none; }
}

/* =========================================================================
   FLAVOUR MARQUEE BAR — between hero and intro
   ========================================================================= */
.marquee {
  position: relative;
  overflow: hidden;
  background: var(--ink);
  color: var(--cream);
  padding-block: clamp(var(--s-4), 1.6vw, var(--s-6));
  border-block: 1px solid rgba(var(--cream-rgb), .08);
  user-select: none;
}
.marquee__row {
  display: flex;
  width: max-content;
  will-change: transform;
}
.marquee__group {
  display: flex;
  align-items: center;
  flex: 0 0 auto;
}
.marquee__item {
  display: flex;
  align-items: center;
  gap: clamp(var(--s-6), 3vw, var(--s-12));
  padding-right: clamp(var(--s-6), 3vw, var(--s-12));
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(20px, 2.6vw, 40px);
  letter-spacing: -.02em;
  line-height: 1.1;
  white-space: nowrap;
  font-variation-settings: var(--wonk-sub);
}
.marquee__sep {
  color: var(--hot-pink); /* 6.07:1 on ink */
  font-size: .58em;
  line-height: 1;
}

/* =========================================================================
   §3 INTRO STATEMENT
   ========================================================================= */
.intro {
  display: grid;
  grid-template-columns: 1.15fr .85fr;
  /* Column gap only. The 5vw row-gap contributed 72px to the stacked
     layout on top of an already generous section padding. */
  column-gap: clamp(var(--s-8), 5vw, var(--s-20));
  row-gap: var(--s-10);
  align-items: start;
}
.intro__title {
  color: var(--teal-deep); /* 11.08:1 on cream */
  max-width: 15ch;
}
/* SplitText's own `mask: 'lines'` wrapper does the clipping, so the line
   element itself must NOT clip — it is the thing that moves. */
.intro__line { display: block; padding-block: .04em; }
/* Anchored to the paragraph above it, not floating in a field of its own.
   The client's screenshot showed ~250px of empty cream beneath this. */
.intro__art {
  margin-top: clamp(var(--s-5), 2vw, var(--s-8));
  width: clamp(120px, 15vw, 210px);
  color: var(--ink);
}
.intro__art svg { width: 100%; height: auto; }
/* pathLength="1" normalises the draw-on — no JS measuring needed. */
.intro__art path[data-draw] { stroke-dasharray: 1; stroke-dashoffset: 1; }
html.no-gsap .intro__art path[data-draw],
html.is-reduced .intro__art path[data-draw] { stroke-dashoffset: 0; }

.intro__right { padding-top: clamp(var(--s-2), 1.4vw, var(--s-6)); }
.intro__right p + p { margin-top: var(--s-5); }
.intro__tel {
  color: var(--teal-deep); /* 11.08:1 on cream */
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1.5px;
}
.intro__tel:hover { color: var(--ink); }

@media (max-width: 900px) {
  .intro { grid-template-columns: 1fr; }
  .intro__title { max-width: 20ch; }
}

/* =========================================================================
   §4 BESTSELLERS — NAJPRODAVANIJE
   ========================================================================= */
/* The visible title of this section IS the arc — its <h2> is u-sr-only. So
   the space above the cards is not decorative padding, it is the title's
   line box, and it has to be reserved. It was not: only 96-126px existed
   between the ring's top and the card grid, and the letters ran through the
   cards. Reserving --arc-band here guarantees clearance at every width by
   construction rather than at the widths that happened to be measured. */
.section--best {
  position: relative;
  overflow: hidden;
  padding-top: calc(var(--pad-section) + var(--arc-band) - 40px);
}

/* The arc rotates the wrapping DIV, never the SVG node: CSS rotate() on an
   SVG child spins about the user-space origin rather than the glyph circle
   and throws the arc off-screen. Same three-layer trick as the hero badge. */
/* Sizing note: a 1500px circle centred in a ~1020px section puts its top
   edge 240px ABOVE the section, so overflow:hidden clipped away the only
   part that reads as words and left rotated slivers at the left and right
   edges. The ring is now sized and offset so its TOP arc lands just above
   the cards, with the sides sweeping behind them as intended. */
/* Width cap raised from 1240px. At 1440 the card row is 1319px wide, so a
   1240px ring put its vertical sides INSIDE the grid and the letters ran
   straight through the card row — the collision in the client's screenshot.
   The ring must always be wider than the content it sweeps around; the
   104vw term already guarantees that below ~1500px, and the cap now does
   too. The sides then fall outside the viewport and are clipped, leaving
   the top arc, which is the part that reads as words. */
.arc {
  position: absolute;
  z-index: 0;
  top: -40px;
  left: 50%;
  width: min(104vw, 1560px);
  aspect-ratio: 1;
  transform: translateX(-50%);
  pointer-events: none;
  /* Width alone is not sufficient. A ring wider than the card row still
     re-enters the row's x-range near its own top and bottom, and at 1200px
     the section was short enough for the BOTTOM arc to cross the cards.
     Masking to the top band makes the collision impossible at every width
     rather than at the ones that happened to be measured, and it shows only
     the part of the ring that reads as words. Layout and the SVG geometry
     are untouched, so the scrubbed rotation still works. */
  -webkit-mask-image: linear-gradient(to bottom, #000 0 var(--arc-band), transparent var(--arc-band));
          mask-image: linear-gradient(to bottom, #000 0 var(--arc-band), transparent var(--arc-band));
}
/* The CTA ring is centred in its own section with nothing to collide with,
   and it is meant to be seen whole. */
.arc--cta {
  -webkit-mask-image: none;
          mask-image: none;
}
.arc__spin { width: 100%; height: 100%; will-change: transform; }
.arc__spin svg { width: 100%; height: 100%; overflow: visible; }
.arc text {
  font-family: var(--font-display);
  font-size: 30px;   /* SVG user units — the viewBox scales this up ~3x */
  font-weight: 800;
  letter-spacing: .02em;
  fill: none;
  stroke: var(--teal);
  stroke-width: 1.1;
  opacity: .55;
  text-transform: uppercase;
  /* Glyphs hang INSIDE the ring. On the default baseline they ascend
     outward and the top of the word is clipped off. */
  dominant-baseline: hanging;
}

@media (max-width: 900px) {
  .arc { top: -40px; width: min(150vw, 760px); }
  .arc text { font-size: 26px; }
}

.best__grid {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(var(--s-4), 2.4vw, var(--s-10));
}
@media (max-width: 900px) { .best__grid { grid-template-columns: 1fr; max-width: 460px; margin-inline: auto; } }

/* =========================================================================
   §5 STATEMENT BREAK — the whitespace is the point.
   ========================================================================= */
.section--statement {
  padding-block: var(--pad-statement);
  text-align: center;
}
.statement {
  max-width: 18ch;
  margin-inline: auto;
  color: var(--ink);
  text-wrap: balance;
}
.statement__word { display: inline-block; }
