  /* ---- scroll zone ---- */
  .scroll-zone {
    position: relative;
    /* Five settled states × four transitions. Keeping each leg at ~180svh of
       scroll travel matches the pacing the 3-state version had. */
    height: 820svh;
  }

  /* Every height in the choreography is svh, never vh. On iOS Safari and
     Chrome Android `vh` resolves against the LARGE viewport — the one you
     only get once the browser retracts its toolbar — so a 100vh hero is
     ~110px taller than what the phone actually shows, and everything
     anchored near its bottom edge (state E's Kontakt block, the scroll
     arrow) sits behind the toolbar. svh is the toolbar-visible height, so
     the composition always fits; when the bar retracts the extra strip
     below the sticky hero is plain page background. dvh would fit both
     bar states but resizes mid-scroll, which re-lays-out the big halves
     exactly while they are animating. */
  .hero {
    position: sticky;
    top: 0;
    height: 100svh;
    width: 100%;
    overflow: hidden;
    display: grid;
    grid-template-rows: 1fr auto 1fr;
    place-items: center;
  }

  /* ---- the logo ---- */
  .logo-wrap {
    grid-row: 2;
    position: relative;
    /* Sized so the layout always "breathes": the halves translate ±18svh
       at state B, the logo is capped at 50svh, and text is anchored on
       the half centers (32svh from top/bottom — fixed by V=0.18, NOT by
       the logo cap). The top/bottom edge-to-half margin is ~9.4% of
       viewport height at every aspect ratio — solved from the closed
       form margin = 0.5 − 0.4525·K − V, with K = 0.50 and V = 0.18. */
    width: var(--logo-w);
    aspect-ratio: 1 / 1;
    /* .logo-wrap (assembled small parts) is the visible logo ONLY for
       states A and B. From state C onward the big halves take over and
       carry the logo all the way to state E — no crossfade. This element
       fades out across the first half of B→C and stays at 0 thereafter.
       The slide-left during B→C plays under the opacity fade, then is
       reset to 0 once we're past E (pBC - pDE*2 hits zero), so when the
       big halves take over they get a clean stage. */
    transform:
      translate(
        calc(max(0, var(--pBC) - var(--pDE) * 2) * -80vw),
        0
      );
    opacity: calc(max(0, 1 - var(--pBC) * 2));
    will-change: transform, opacity;
    color: var(--ink);
  }

  /* Layered logo parts — each pinned to its position in the 1500x1500
     coordinate space of Full.svg so they overlap into the assembled mark.
     SVGs are inlined and inherit color via fill="currentColor". */
  .part {
    position: absolute;
    color: var(--ink);
    will-change: transform;
    transition: color 0.4s ease;
    display: block;
  }
  .part-left {
    left: 3.81%;   top: 4.75%;
    width: 43.46%; height: 91.59%;
    /* Cap horizontal spread by vh as well so on wide-but-short windows
       the halves don't end up far apart in pixels while the logo itself
       has been height-capped — keeps the H:V spread ratio consistent.
       V is 18svh, which combined with the 50svh logo cap gives ~9.4%
       margin between the half and the top of the viewport.
       Half also shrinks to 0.80 across the A→B split so the bigger
       state-A logo doesn't leave the halves crowding the side text
       in state B — they settle back into their lanes. The shrink is
       around each half's own centre, so half-centres (and the side-
       text anchors at 32svh) stay put. */
    transform:
      translate(calc(var(--p2) * -1 * min(4vw, 7svh)), calc(var(--p1) * -18svh))
      scale(calc(1 - var(--p1) * 0.20));
  }
  .part-middle {
    /* `left` is nudged right by --mast-shift-a so the mast bar reads
       as separated from the clock arc — see comment on --mast-shift-a
       in base.css. SVG-pinned base is 17.83%. */
    left: calc(17.83% + var(--mast-shift-a));
    top: 24.32%;
    width: 36.44%; height: 45.90%;
    /* Continuous, gentle transform across the entire vertical-split phase:
       rotates counter-clockwise 0 → -90°, shrinks to 50%, fades to 0,
       all anchored on the circular bulge in the middle of the mast.
       Linear over --p1 so the motion feels calm and tied to the halves. */
    opacity: calc(1 - var(--p1));
    transform:
      rotate(calc(var(--p1) * -90deg))
      scale(calc(1 - var(--p1) * 0.5));
    transform-origin: 87.55% 56.68%;
  }
  .part-right {
    /* `left` is nudged right by --smiley-shift-a so the smiley arc
       reads as separated from the mast bar — see comment on
       --smiley-shift-a in base.css. SVG-pinned base is 17.83%. */
    left: calc(17.83% + var(--smiley-shift-a));
    top: 4.75%;
    width: 77.71%; height: 91.60%;
    /* Mirror of .part-left — shrinks to 0.80 at state B around its own
       centre so the smiley settles into the bottom-right lane instead
       of overlapping the side text. */
    transform:
      translate(calc(var(--p2) * min(4vw, 7svh)), calc(var(--p1) *  18svh))
      scale(calc(1 - var(--p1) * 0.20));
  }

  /* ---- side reveal text blocks ---- */
  .story {
    position: absolute;
    /* The vw term keeps a side gutter on portrait-ish windows: the block is
       anchored from the centre line, so on a ~820px-wide tablet the full
       380px reaches the viewport edge and the lines sit flush against it. */
    max-width: min(380px, 40vw);
    z-index: 2;
    pointer-events: none;
    /* Rises with the B-reveal (p2) and fades out together with the logo
       during B→C's first half — same `max(0, 1 - pBC*2)` envelope as
       .logo-wrap so they stay in lockstep. */
    opacity: calc(var(--p2) * max(0, 1 - var(--pBC) * 2));
  }
  .story.active { pointer-events: auto; }
  .story .kicker {
    display: block;
    font-size: 11px;
    letter-spacing: 0.4em;
    text-transform: uppercase;
    color: var(--ink-soft);
    margin-bottom: 18px;
  }
  .story h2 {
    /* Cap font-size by vh as well so on wide-but-short windows the
       heading doesn't crash into the nav. Same min()-inside-clamp()
       pattern used on the logo cap. */
    font-size: var(--story-fs-h2);
    font-weight: 400;
    letter-spacing: -0.01em;
    line-height: 1.18;
    margin-bottom: clamp(8px, 1.6svh, 18px);
  }
  .story p {
    font-size: var(--story-fs-p);
    color: var(--ink-soft);
    line-height: 1.5;
    margin: 0;
    padding: 0;
    font-weight: 400;
    letter-spacing: 0.5px;
  }
  /* anchor each block right beside its half, vertically centered on the
     semicircle's visual middle. The halves translate ±18svh from center,
     so each half-center sits at 32svh from the top/bottom edge. Anchor
     the text's own midline there with translateY(±50%) so its visual
     centre lines up with the half regardless of paragraph length. */
  .story-top {
    top: 32svh;
    left: calc(50% + 3vw);
    text-align: left;
    /* Same B→C slide-left envelope as .logo-wrap so the whole B-state
       composition exits as one piece. */
    transform: translate(
      calc(
        (1 - var(--p2)) * -60px
        + max(0, var(--pBC) - var(--pDE) * 2) * -80vw
      ),
      -50%
    );
  }
  .story-top h2 {
    width: 400px;
    max-width: 100%;
    font-size: calc(var(--story-fs-h2) * 1.35);
    font-weight: 600;
  }
  .story-top p {
    width: 380px;
    max-width: 100%;
    text-align: left;
    font-size: calc(var(--story-fs-p) * 1.3);
  }
  .story-bottom {
    bottom: 32svh;
    right: calc(50% + 3vw);
    text-align: right;
    transform: translate(
      calc(
        (1 - var(--p2)) * 60px
        + max(0, var(--pBC) - var(--pDE) * 2) * -80vw
      ),
      50%
    );
  }
  .story-bottom p {
    text-align: right;
    font-size: var(--story-fs-p-lg);
    max-width: 34ch;
    margin-left: auto;
  }
  .story-bottom p strong { font-weight: 600; color: var(--ink); }

  /* ---- states C + E + (assembled) C: the big halves carry the logo ----
     The same two .big-half elements are visible from state C through to
     state E — they slide in from their viewport edges (D, E), then
     re-converge on the assembled-logo offsets (D→E first half), then
     scale + lift + shift down to the state-E small-logo pose (D→E
     second half). No crossfade with .logo-wrap; the small parts stay
     hidden from state C onward.
     The transform reads top-to-bottom as a stack of independent motions:
       1. side-offset   slide off / on the viewport edge   (D, E)
       2. pull          ride into the assembled-logo offset (D→E 0→0.5)
       3. shift         move with the logo to make room for the wordmark
       4. shrink-dx     re-snap the inter-half spacing as the pair scales
                        (otherwise scaling around each half's own centre
                        leaves a gap between clock and smiley)
       5. lift (Y)      raise the pair to the state-E Y
       6. scale         shrink to the state-E size
  */
  .big-half {
    position: absolute;
    top: 50%;
    height: var(--big-half-h);
    width: auto;
    z-index: 2;
    pointer-events: none;
    color: var(--ink);
    display: block;
    will-change: transform, opacity;
  }
  .big-half-right {
    right: 0;
    aspect-ratio: 1165.66 / 1374.02;
    transform:
      translate(
        calc(
          var(--bigR-side) * (120% + var(--big-half-inset))
          - var(--big-half-inset)
          - var(--bigR-pull) * var(--big-pull-r)
          - var(--pShift) * var(--e-shift-x)
          - var(--pShrink) * var(--big-shrink-dx-r)
        ),
        calc(
          -50%
          - var(--pLift) * var(--e-lift)
        )
      )
      scale(calc(1 - var(--pShrink) * (1 - var(--big-final-scale))));
    opacity: 1;
  }
  .big-half-left {
    left: 0;
    aspect-ratio: 651.94 / 1373.9;
    transform:
      translate(
        calc(
          -1 * var(--bigL-side) * (120% + var(--big-half-inset))
          + var(--big-half-inset)
          + var(--bigL-pull) * var(--big-pull-l)
          - var(--pShift) * var(--e-shift-x)
          + var(--pShrink) * var(--big-shrink-dx-l)
        ),
        calc(
          -50%
          - var(--pLift) * var(--e-lift)
        )
      )
      scale(calc(1 - var(--pShrink) * (1 - var(--big-final-scale))));
    opacity: 1;
  }

  /* Mast (part-middle, big version). Hidden until D→E; fades in alongside
     the halves' assembly so the completed logo reads as one mark. It
     never lives at a viewport edge — its only "rest" is the assembled
     position relative to the big logo centre, then it tracks the same
     shrink/lift/shift as the two halves. */
  .big-half-middle {
    top: 50%;
    left: 50%;
    height: var(--big-middle-h);
    width: auto;
    aspect-ratio: 546.53 / 688.51;
    transform:
      translate(
        calc(
          -50%
          + var(--big-middle-dx)
          + var(--pShrink) * var(--big-shrink-dx-mid)
          - var(--pShift) * var(--e-shift-x)
        ),
        calc(
          -50%
          + var(--big-middle-dy)
          + var(--pShrink) * var(--big-shrink-dy-mid)
          - var(--pLift) * var(--e-lift)
        )
      )
      scale(calc(1 - var(--pShrink) * (1 - var(--big-final-scale))));
    /* Fades in across pDE 0.15 → 0.45 so it appears alongside the
       halves converging on the assembled position. */
    opacity: calc(min(1, max(0, (var(--pDE) - 0.15) * 3.33)));
  }

  /* C-state showreel — sits to the LEFT of the big right-half. */
  .story-c {
    position: absolute;
    top: 50%;
    /* Pulled in from the rim (was clamp(24px, 6vw, 80px)) so the column
       reads as a centred block rather than hugging the left edge. */
    left: clamp(32px, 6vw, 96px);
    /* Reserve is measured to the VISIBLE arc, not to big-right's SVG box:
       the paths start ~44% into a 1165.66-wide viewBox, so of the box's
       ~67.9svh (= 0.8484 * --big-half-h) only the right ~38svh carries ink.
       38svh + the 3vw rim inset + a 4vw gap. */
    right: calc(38svh + 7vw);
    /* The 107svh term caps the 16:9 player at ~60svh tall so it keeps air
       above and below on short desktop windows. */
    max-width: min(960px, 107svh);
    z-index: 2;
    pointer-events: none;
    color: var(--ink);
    transform: translate(
      calc((1 - min(1, max(0, var(--pBC) - 0.4) * 1.67)) * -40px),
      -50%
    );
    /* Fades in over the second half of B→C, fades out in the first
       third of C→D. */
    opacity: calc(
      min(1, max(0, var(--pBC) - 0.5) * 2)
      * max(0, 1 - var(--pCD) * 3.33)
    );
  }
  .story-c.active { pointer-events: auto; }
  .showreel-stage { position: relative; display: block; }
  .showreel video {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 16 / 9;
    object-fit: cover;
    background: #000;
    cursor: pointer;
  }

  /* D-state manifesto text — mirrored layout, sits to the RIGHT of the
     big left-half. */
  .story-d {
    position: absolute;
    top: 50%;
    /* big-left is now inset by 3vw from the left rim; reserve that +
       its ~38svh width + a 4vw gap. */
    left: calc(38svh + 7vw);
    right: clamp(24px, 6vw, 80px);
    max-width: 700px;
    z-index: 2;
    pointer-events: none;
    color: var(--ink);
    text-align: left;
    transform: translate(
      calc((1 - min(1, max(0, var(--pCD) - 0.4) * 1.67)) * 40px),
      -50%
    );
    /* Fades in over the second half of C→D, fades out in the first
       third of D→E. */
    opacity: calc(
      min(1, max(0, var(--pCD) - 0.5) * 2)
      * max(0, 1 - var(--pDE) * 3.33)
    );
  }
  .story-d.active { pointer-events: auto; }
  .story-d p {
    font-size: clamp(18px, min(1.55vw, 2.5svh), 28px);
    color: var(--ink);
    line-height: 1.65;
    letter-spacing: 0.2px;
    margin: 0 0 1.15em 0;
    font-weight: 400;
  }
  /* Opening paragraph carries the block: larger, tighter, a shade heavier,
     so the manifesto reads as lead + body rather than four equal slabs. */
  .story-d p.story-d-lead {
    font-size: clamp(21px, min(1.95vw, 3.1svh), 34px);
    line-height: 1.4;
    font-weight: 500;
    margin-bottom: 1.3em;
  }
  .story-d p:last-child { margin-bottom: 0; }

  /* ---- state E: wordmark sits just to the right of the logo, slightly up ---- */
  .contact-reveal {
    position: absolute;
    top: 50%;
    left: var(--e-wordmark-x);
    /* Cap by vh too so on short-and-wide windows the wordmark stays
       proportional to the logo (which is also vh-capped). */
    width: clamp(110px, min(22vw, 38svh), 340px);
    z-index: 2;
    pointer-events: none;
    opacity: var(--p3);
    /* Lift is keyed on pLift (vertical-merge phase) so the wordmark
       fades in at the already-lifted Y rather than sliding diagonally
       into it during pShift. */
    transform: translate(calc((1 - var(--p3)) * 30px), calc(-50% - var(--pLift) * var(--e-lift)));
    color: var(--ink);
  }
  .contact-reveal.active { pointer-events: auto; }
  .wordmark {
    display: block;
    width: 100%;
    height: auto;
  }

  /* ---- state E: “Spojme se” + email centered below the logo + wordmark ---- */
  .below-logo {
    position: absolute;
    top: var(--e-contact-y);
    left: 50%;
    z-index: 2;
    text-align: center;
    pointer-events: none;
    opacity: var(--p3);
    /* Shift the whole state-E group up so the logo+wordmark cluster sits
       closer to the nav title. Keyed on pLift so the lift happens during
       the vertical-merge phase, in lockstep with the logo and wordmark. */
    transform: translate(-50%, calc(-50% + (1 - var(--p3)) * 12px - var(--pLift) * var(--e-lift)));
    color: var(--ink);
  }
  .below-logo.active { pointer-events: auto; }
  .below-logo h3 {
    font-size: var(--below-h3-fs);
    font-weight: 300;
    letter-spacing: -0.01em;
    margin-bottom: 18px;
  }
  .below-logo .mail {
    color: var(--ink);
    text-decoration: none;
    font-size: clamp(15px, 1.1vw, 18px);
    letter-spacing: 0.04em;
    border-bottom: 1px solid var(--ink-soft);
    padding-bottom: 3px;
    transition: border-color 0.2s ease;
  }
  .below-logo .mail:hover { border-color: var(--ink); }
  /* Own line under the email; .mail is inline, so this needs its own box. */
  .below-logo .tel { display: block; width: fit-content; margin: 14px auto 0; }
  .below-logo .instagram {
    display: flex;
    align-items: center;
    justify-content: center;
    width: fit-content;
    margin: 18px auto 0;
    color: var(--ink);
    transition: color 0.2s ease, transform 0.2s ease;
  }
  .below-logo .instagram:hover {
    color: var(--ink);
    transform: scale(1.08);
  }

  /* ---- scroll hints (clickable arrows for forward / back) ---- */
  .hint {
    grid-row: 3;
    align-self: end;
    padding-bottom: clamp(40px, 8svh, 90px);
    display: flex;
    flex-direction: column;
    align-items: center;
    background: transparent;
    border: none;
    color: var(--ink);
    cursor: pointer;
    font: inherit;
    z-index: 3;
    opacity: 1; /* JS sets this per state */
    transition: opacity 0.4s cubic-bezier(.2,.7,.2,1);
    pointer-events: auto;
  }
  .hint.hint-up {
    grid-row: 1;
    align-self: start;
    padding-top: clamp(80px, 12svh, 130px);
    padding-bottom: 0;
  }
  .hint.hint-up .hint-arrow { animation: nudgeUp 2.6s cubic-bezier(.4,.0,.2,1) infinite; }
  @keyframes nudgeUp {
    0%, 60%, 100% { transform: translateY(0); }
    30%           { transform: translateY(-7px); }
  }
  .hint[disabled] { pointer-events: none; }
  .hint .hint-arrow {
    width: 48px;
    height: 48px;
    border-radius: 9999px;
    border: 1px solid var(--line);
    display: grid;
    place-items: center;
    color: var(--ink);
    animation: nudge 2.6s cubic-bezier(.4,.0,.2,1) infinite;
    transition: border-color 0.2s ease, background 0.2s ease, color 0.2s ease;
  }
  .hint:hover .hint-arrow {
    background: var(--ink);
    color: var(--bg);
    border-color: var(--ink);
    animation-play-state: paused;
  }
  .hint:focus-visible { outline: none; }
  .hint:focus-visible .hint-arrow { border-color: var(--ink); }
  @keyframes nudge {
    0%, 60%, 100% { transform: translateY(0); }
    30%           { transform: translateY(7px); }
  }
