/* THE FLOW LAYER. Added 7 Oct 2026 for the owner's brief: "there is some still images on the page
   i need the design to flow perfectly". The direction, its research and why it won over the louder
   option are in the preview folder, redesign/DIRECTION.md ("A. Holo Stream").

   FOUR MOVES, ALL CSS, NO LIBRARY AND NO SCROLL LISTENER:
     1. ONE BACKDROP. A soft holo glow fixed behind the whole page, and the sections made see-through
        so they dissolve into each other instead of stacking as hard-edged bands.
     2. THE THREAD. A thin holo line down the left edge that fills as you scroll, on the browser's
        own scroll timeline. Decoration only, aria-hidden, and only where scroll timelines exist.
     3. CAMERA MOVES ON THE STILLS. The welcome photos breathe and drift, the two illustrations get a
        slow push-in as they cross the screen, the background textures pan, his artwork floats.
     4. A SHEEN. A light sweep across the framed pictures now and then, like light across a foil card.

   THE SAME RULES AS motion.css (test/site-flow.test.js holds them):
     - every moving or hidden start state is behind .motion-on / .motion-scroll / .motion-reveal, which
       motion.js sets only when script runs and the visitor has not asked for reduced motion;
     - transform, opacity and the individual scale/translate/rotate properties only, so the compositor
       does the work;
     - the reduced-motion block at the bottom stops everything, including the time-based loops.
   With script off, the page gets the backdrop and the see-through sections, and nothing moves. */

/* ------------------------------------------------------------ 1. one backdrop */
/* Fixed, behind everything, inside the viewport (inset 0, so it can never widen the page). The body
   keeps its own ground colour, which paints the canvas; this sits above that and below the content. */
body::before {
  content: ''; position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background:
    radial-gradient(42% 38% at 18% 22%, rgba(182, 120, 255, .20), transparent 70%),
    radial-gradient(36% 32% at 86% 48%, rgba(97, 226, 196, .11), transparent 70%),
    radial-gradient(44% 36% at 42% 92%, rgba(255, 180, 84, .08), transparent 72%);
}

/* The bands stop being bands. No ruled line between them, no alternating flat colour; every other
   section gets a wash that fades in and out at its own edges, so one runs into the next. */
.slab, .band { background: transparent; border-top-color: transparent; }
main > :is(.slab, .band):nth-of-type(even) {
  background: linear-gradient(180deg, rgba(19, 14, 29, 0) 0%, rgba(19, 14, 29, .78) 16%, rgba(19, 14, 29, .78) 84%, rgba(19, 14, 29, 0) 100%);
}
/* The story keeps its deep violet middle and loses its two hard ends. */
.story-band {
  background: linear-gradient(180deg, rgba(22, 11, 39, 0) 0%, #160b27 18%, #221040 52%, #120a20 84%, rgba(18, 10, 32, 0) 100%);
}
/* The hero's gradient fades out at the top and the bottom instead of stopping on a line. The fade is
   shorter than the hero's own padding, so no word or button is ever inside it. */
.hero {
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 48px, #000 calc(100% - 48px), transparent 100%);
          mask-image: linear-gradient(180deg, transparent 0, #000 48px, #000 calc(100% - 48px), transparent 100%);
}
/* The background textures behind three slabs pan with the scroll, so they are clipped to their own
   section; without the clip a panned texture would hang over its neighbour. */
.slab-shot { overflow: clip; }
/* ...and the texture fades out at the bottom as well as the top, so the section ends in the backdrop
   rather than on the edge of a photo (seen on the 1440 shot of #before, 7 Oct). */
.slab-shot::before {
  -webkit-mask-image: linear-gradient(180deg, transparent 0, #000 38%, #000 60%, transparent 88%);
          mask-image: linear-gradient(180deg, transparent 0, #000 38%, #000 60%, transparent 88%);
}

/* The header: the flat rule under it becomes a faint holo line, the same three colours as the thread. */
.topbar { border-bottom-color: transparent; }
.topbar::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: -1px; height: 1px; pointer-events: none;
  background: linear-gradient(90deg, transparent, rgba(182, 120, 255, .55), rgba(97, 226, 196, .45), rgba(255, 180, 84, .4), transparent);
}

/* The footer rises out of a low glow instead of sitting in a box: the last thing on the page is lit
   the same way as the first. Static, so it needs no motion tier. */
.footer { position: relative; isolation: isolate; }
.footer::before {
  content: ''; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: radial-gradient(70% 90% at 50% 100%, rgba(182, 120, 255, .16), transparent 70%);
}

/* ------------------------------------------------------------ 2. the thread */
.flow-thread { display: none; }

/* ------------------------------------------------------------ 3. camera hooks, at rest */
/* The illustration frame. overflow: clip, NOT hidden: hidden would make the frame a scroll container,
   and the push-in below would then measure its view() against a box that never scrolls. */
.scene-cam {
  width: min(560px, 92vw); margin: 26px auto 0; position: relative; overflow: clip;
  border: 1px solid var(--line); border-radius: 14px; box-shadow: 0 22px 50px rgba(0, 0, 0, .5);
}
.scene-cam .scene-art { width: 100%; margin: 0; border: 0; border-radius: 0; box-shadow: none; }
/* The welcome window: real footage of two packs opened on the 3 Oct show, framed like a screen. */
.welcome-window { margin: 0; align-self: center; }
.welcome-window .scene-reel--pulls {
  width: 100%; aspect-ratio: 560 / 400; margin: 0; border-radius: 22px;
  border: 1px solid rgba(255, 255, 255, .14); box-shadow: 0 34px 80px rgba(80, 30, 160, .45);
}
.welcome-window-cap {
  margin: 12px 0 0; font-family: var(--labelface); font-weight: 700; font-size: 12px;
  letter-spacing: .14em; text-transform: uppercase; color: var(--dim);
}

/* ------------------------------------------------------------ the keyframes */
@keyframes flow-drift {
  0% { translate: 0 0; scale: 1; }
  100% { translate: 3vw -4vh; scale: 1.08; }
}
@keyframes flow-fill { from { transform: scaleY(0); } to { transform: scaleY(1); } }
@keyframes flow-push { from { transform: scale(1.16) translate(2%, 3%); } to { transform: scale(1.02) translate(-1%, -1%); } }
@keyframes flow-kb { from { transform: scale(1.02); } to { transform: scale(1.14) translate(-2%, -2%); } }
@keyframes flow-breathe { 0%, 100% { scale: 1; translate: 0 0; } 50% { scale: 1.035; translate: 0 -6px; } }
@keyframes flow-float { 0%, 100% { translate: 0 0; rotate: 0deg; } 50% { translate: 0 -10px; rotate: -1.5deg; } }
@keyframes flow-sheen { 0%, 62% { transform: translateX(-120%) skewX(-18deg); } 100% { transform: translateX(220%) skewX(-18deg); } }
@keyframes flow-handover { from { opacity: .25; transform: translateY(48px) scale(.98); } to { opacity: 1; transform: none; } }
@keyframes flow-pan { from { transform: translateY(-3%) scale(1.06); } to { transform: translateY(3%) scale(1.06); } }

/* ------------------------------------------------------------ both motion tiers */
/* The glow drifts slowly on its own clock: alive, never busy. Forty seconds a cycle. */
.motion-on body::before { animation: flow-drift 40s ease-in-out infinite alternate; }

/* The welcome window leans in like a screen on a desk and breathes a little. The lean is on the video,
   not the figure, because the figure's own transform belongs to its data-rise arrival. */
@media (min-width: 761px) {
  .motion-on .welcome-window .scene-reel--pulls { transform: perspective(1200px) rotateY(-7deg) rotateX(2deg); }
}
.motion-on .welcome-window .scene-reel--pulls { animation: flow-breathe 12s ease-in-out infinite; }

/* The two photos of him breathe slowly while they cross-fade (the fade is motion.css; this is the
   frame as a whole, so the two animations never touch the same property). */
.motion-on .who-shot { animation: flow-breathe 14s ease-in-out infinite; }

/* His artwork floats a little. */
.motion-on .who-art img { animation: flow-float 7s ease-in-out infinite; }

/* The sheen: a soft light sweep across each illustration every few seconds. */
.motion-on .scene-cam::after {
  content: ''; position: absolute; inset: -10% auto -10% 0; width: 40%; pointer-events: none;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .16), transparent);
  animation: flow-sheen 6.5s ease-in-out infinite;
}

/* ------------------------------------------------------------ the scroll tier */
@supports (animation-timeline: scroll()) {
  .motion-scroll .flow-thread {
    display: block; position: fixed; left: 0; top: 0; bottom: 0; width: 3px; z-index: 40; pointer-events: none;
    background: rgba(255, 255, 255, .05);
  }
  .motion-scroll .flow-thread::after {
    content: ''; position: absolute; inset: 0; transform-origin: 50% 0;
    background: linear-gradient(180deg, #b678ff, #61e2c4 50%, #ffb454);
    box-shadow: 0 0 14px rgba(182, 120, 255, .55);
    animation: flow-fill linear both; animation-timeline: scroll(root);
  }
  /* Each illustration pushes in as it crosses the screen, so the picture moves when the finger does. */
  .motion-scroll .scene-cam .scene-art { animation: flow-push linear both; animation-timeline: view(); animation-range: cover 0% cover 100%; }
  /* THE HAND-OVER BETWEEN SECTIONS. Each section's content rises into place and comes up from a
     quarter opacity as it enters, so the eye is carried from one into the next. It starts at .25,
     not 0, and finishes before the section is half on screen, so nothing is ever unreadable where
     somebody is actually reading. */
  .motion-scroll main > :is(.slab, .band) > :is(.wrap, .window) { animation: flow-handover linear both; animation-timeline: view(); animation-range: entry 0% entry 70%; }
  /* The faint photos behind three slabs pan against the scroll. */
  .motion-scroll .slab-shot::before { animation: flow-pan linear both; animation-timeline: view(); animation-range: cover 0% cover 100%; }
}

/* ------------------------------------------------------------ the fallback tier */
/* No scroll timelines: the illustrations get a slow time-based camera move instead of the push-in. */
.motion-reveal .scene-cam .scene-art { animation: flow-kb 18s ease-in-out infinite alternate; }

/* ------------------------------------------------------------ reduced motion */
@media (prefers-reduced-motion: reduce) {
  body::before, .flow-thread, .flow-thread::after, .scene-cam .scene-art, .scene-cam::after,
  .welcome-window .scene-reel--pulls, .who-shot, .who-art img, .slab-shot::before,
  main > :is(.slab, .band) > :is(.wrap, .window) {
    animation: none !important;
  }
  .flow-thread, .scene-cam::after { display: none !important; }
  .welcome-window .scene-reel--pulls { transform: none !important; }
}
/* Reduced motion shows the reel's own still. styles.css gives every .scene-reel the opening reel's
   poster; this sheet loads later, so the welcome window gets its own. */
@media (prefers-reduced-motion: reduce) {
  .scene-reel--pulls { content: url('reel-pulls-poster.jpg'); }
}
