/* ==========================================================================
   WHEEL — optional add-on (demo) — PURE CSS
   ==========================================================================

   Load AFTER main.css (only wheel-demo.html does). Turns the column of
   tracks and red questions into the front face of a big drum that turns
   while you scroll. Remove the <link> and everything is exactly as before;
   main.css, main.js and index.html are not touched.

   NO JAVASCRIPT is involved in the effect.


   HOW IT WORKS: SCROLL-DRIVEN ANIMATIONS
   --------------------------------------
   A normal CSS animation runs over TIME. With
       animation-timeline: view();
   it runs over the SCROLL POSITION instead: the animation's progress
   (0 % → 100 %) is tied to where the element is in the viewport. Scrolling
   down plays it forward, scrolling up plays it backwards, stopping freezes
   it. The browser updates it in the same step as the scrolling itself —
   for a transform even on the GPU thread — so the drum can never lag
   behind the page. (A JS solution has to wait for the scroll event and can
   be a frame late; that's what the first version of this demo did.)

   Browser support: Chrome/Edge 115+, Safari 26+. Firefox still has it
   behind a flag → there the whole block below is skipped (@supports) and
   the page simply stays flat, exactly like index.html.


   THE GEOMETRY
   ------------
       side view
          ___          Every track and every question is one flat facet
        /     \        of a drum whose axis is horizontal and lies behind
       |   ●   |  ←    the screen. The facet in the middle of the screen
        \ ___ /        faces you; the others are tilted away and pushed
                       back, so perspective makes them smaller — the
                       barrel shape from the sketch.

   For a facet whose centre is a distance d above/below the centre of the
   viewport (d in screen heights):
       tilt     θ = d × --wheel-tilt                 (degrees)
       depth    z = R × (cos θ − 1)                  (≤ 0 = behind the screen)
       radius   R = 1 screen height × 57.3 / --wheel-tilt
   (57.3 = degrees per radian. This R makes the drum surface move exactly
   as fast as you scroll, right in the middle of the screen.)

   The transform per facet, read from right to left:
       perspective(P)   3. look at it from distance P
       translateZ(z)    2. push it back onto the drum
       rotateX(−θ)      1. tilt it (rotateX(+a) moves the TOP edge away;
                           a facet below the centre must tilt its BOTTOM
                           edge away, hence the minus)
   All three happen around the facet's own centre, so the centre stays
   where it is in the flat layout → THE SPACING OF THE TRACKS IS EXACTLY
   THE SAME AS WITHOUT THE DRUM.


   THE ANIMATION RANGE
   -------------------
   "animation-range" says which part of the element's way through the
   viewport the 0 %–100 % of the keyframes cover:
       entry-crossing 50%  = the element's centre is at the BOTTOM edge
       exit-crossing 50%   = the element's centre is at the TOP edge
   Both are extended by one more screen height (± 100vh), so the drum keeps
   turning while a facet is still partly visible, even if its centre is
   already off screen. Result: the keyframes run from "centre 1.5 screen
   heights below the middle" (0 %) to "1.5 screen heights above" (100 %),
   the same for every facet, whatever its height. Further away than that,
   a facet is off screen anyway.

   The browser measures this range on the LAYOUT box, without the
   transform — so the transform can't influence its own animation.


   WHY THE TRACK ITSELF IS NOT TRANSFORMED
   ---------------------------------------
   The <article class="track" id="07"> is the target of the clock links.
   When jumping to #07 the browser aims at the box AS YOU SEE IT — with a
   transform, a tilted/shrunk facet made the jump land too high or too low.
   So the transform goes on the article's CHILDREN (the video and, on
   tracks 01/24, the logo). They share the article's centre, so turning
   them about their own centres looks exactly like turning the article,
   while the article — the jump target — stays untouched. The clock jump
   (scroll-margin-top in main.css) lands exactly as on index.html.
   The questions have no id, they are transformed directly.


   THE KEYFRAMES
   -------------
   The tilt changes evenly (linearly) with the scroll position. The depth
   follows a cosine curve, which the browser can't interpolate between two
   keyframes by itself — so there are 9 keyframes and the curve is drawn
   from straight pieces between them (deviation: a few pixels of DEPTH,
   which shows up as far less than a pixel on screen — invisible).
   ========================================================================== */

@layer wheel {

  /* ------------------------------------------------------------------------
     1. Settings
     ------------------------------------------------------------------------
     The two knobs. Values chosen on 10.10.2026 with a (since removed)
     test panel. */
  :root {
    /* How many degrees the drum turns per screen height of scrolling.
       Bigger = stronger curvature (a smaller drum).
       14 → a neighbouring track (about 1.4 screen heights away) is
       tilted by roughly 20°. */
    --wheel-tilt: 14;

    /* Viewing distance, in screen heights. Smaller = stronger perspective
       (facets shrink faster, stronger barrel shape). */
    --wheel-perspective: 1;

    /* Derived values — don't change these directly. */
    --_radius: calc(5729.578vh / var(--wheel-tilt)); /* 57.29578 × 100vh */
    --_perspective: calc(var(--wheel-perspective) * 100vh);
  }


  /* ------------------------------------------------------------------------
     2. The facets
     ------------------------------------------------------------------------
     Only if the browser supports scroll-driven animations, and only if the
     user hasn't asked their OS for reduced motion. */
  @supports (animation-timeline: view()) {
    @media (prefers-reduced-motion: no-preference) {

      .track > *,
      .question {
        /* "linear": the tilt must follow the scroll position 1:1.
           "both": before/after the range, keep the first/last frame. */
        animation: wheel-turn linear both;
        /* Must come AFTER the "animation" shorthand, which resets it. */
        animation-timeline: view();
        animation-range:
          entry-crossing calc(50% - 100vh)
          exit-crossing calc(50% + 100vh);
      }

      /* The logo on tracks 01/24 is centred with
         "transform: translate(-50%, -50%)" (main.css). The animation would
         replace that transform, so the centring moves to the separate
         "translate" property, which is applied on top of "transform".
         Same position as before. */
      .track__logo {
        transform: none;
        translate: -50% -50%;
      }
    }
  }
}


/* ==========================================================================
   KEYFRAMES
   ==========================================================================
   0 % = facet centre 1.5 screen heights BELOW the middle of the viewport,
   100 % = 1.5 screen heights ABOVE. Between two stops: 0.375 screen heights.
   (Keyframes can't be put in a layer; they're definitions, like @font-face.)
   ========================================================================== */

@keyframes wheel-turn {
  0% { /* 1.5 screen heights below the centre */
    transform:
      perspective(var(--_perspective))
      translateZ(calc((cos(var(--wheel-tilt) * 1.5 * 1deg) - 1) * var(--_radius)))
      rotateX(calc(var(--wheel-tilt) * -1.5 * 1deg));
  }
  12.5% { /* 1.125 screen heights below the centre */
    transform:
      perspective(var(--_perspective))
      translateZ(calc((cos(var(--wheel-tilt) * 1.125 * 1deg) - 1) * var(--_radius)))
      rotateX(calc(var(--wheel-tilt) * -1.125 * 1deg));
  }
  25% { /* 0.75 screen heights below the centre */
    transform:
      perspective(var(--_perspective))
      translateZ(calc((cos(var(--wheel-tilt) * 0.75 * 1deg) - 1) * var(--_radius)))
      rotateX(calc(var(--wheel-tilt) * -0.75 * 1deg));
  }
  37.5% { /* 0.375 screen heights below the centre */
    transform:
      perspective(var(--_perspective))
      translateZ(calc((cos(var(--wheel-tilt) * 0.375 * 1deg) - 1) * var(--_radius)))
      rotateX(calc(var(--wheel-tilt) * -0.375 * 1deg));
  }
  /* Centre on the viewport centre: facing you, flat, 1:1 → razor sharp. */
  50% {
    transform: perspective(var(--_perspective)) translateZ(0) rotateX(0deg);
  }
  62.5% { /* 0.375 screen heights above the centre */
    transform:
      perspective(var(--_perspective))
      translateZ(calc((cos(var(--wheel-tilt) * -0.375 * 1deg) - 1) * var(--_radius)))
      rotateX(calc(var(--wheel-tilt) * 0.375 * 1deg));
  }
  75% { /* 0.75 screen heights above the centre */
    transform:
      perspective(var(--_perspective))
      translateZ(calc((cos(var(--wheel-tilt) * -0.75 * 1deg) - 1) * var(--_radius)))
      rotateX(calc(var(--wheel-tilt) * 0.75 * 1deg));
  }
  87.5% { /* 1.125 screen heights above the centre */
    transform:
      perspective(var(--_perspective))
      translateZ(calc((cos(var(--wheel-tilt) * -1.125 * 1deg) - 1) * var(--_radius)))
      rotateX(calc(var(--wheel-tilt) * 1.125 * 1deg));
  }
  100% { /* 1.5 screen heights above the centre */
    transform:
      perspective(var(--_perspective))
      translateZ(calc((cos(var(--wheel-tilt) * -1.5 * 1deg) - 1) * var(--_radius)))
      rotateX(calc(var(--wheel-tilt) * 1.5 * 1deg));
  }
}
