/* ==========================================================================
   ozhiv.css — the ozhiv.ai figure: a flat scheme, and one thing in it with
   depth.

   The scheme: boxes are HTML, wires are SVG, cargo runs the wires. A photo
   goes past the template rack into the generation box; a credit goes in
   first; the clip comes out and lands in the gallery. Below, the money: the
   credits, and the Tinkoff box whose webhook runs back to them.

   The one thing with depth is the clip: a 9:16 card with a scene playing
   in it, in a CSS perspective, its layers at three depths and a stack of
   frames behind it. Where it is, how it tilts and when the frames stack up
   are in ozhiv-timeline.css, generated from tools/ozhiv.py; the scene's own
   loops — hooves, clouds, grass, the astronaut's drift — are here, on short
   cycles of their own, because nothing waits on them.

   Layering: the drawing sits over the boxes (z 1 over z 0), because the
   photo, the coins and the block all have to be seen inside them. Labels
   sit over both.

   The static values below are the figure's LAST frame — two clips flat in
   the gallery, two coins left, one tile lit — so with the animations off
   (prefers-reduced-motion) the picture holds the end of the story.

   Below 1000px the wires and the cargo go, and the boxes stack in reading
   order with what they hold: the tiles, the two bars full, two thumbnails,
   the credit count.
   ========================================================================== */

.ozv {
  --ozv-cycle: 27s;               /* ozhiv-timeline.css sets the real ones */
  --ozv-ratio: 1000 / 430;
  --c: var(--c-blue);
  margin: var(--s-5) 0 var(--s-6);
}
.ozv, .ozv figure { margin-inline: 0; }

/* --- the caption ---------------------------------------------------------- */
.ozv__cap {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s-2);
  margin-bottom: var(--s-4);
}
.ozv__h {
  font-weight: 640; font-size: var(--fs-md); letter-spacing: -.015em;
  color: var(--ink);
}
.ozv__note {
  flex: 1 1 22ch; min-width: 0;
  font-size: var(--fs-3xs); line-height: 1.45; color: var(--ink-3);
}

/* --- the stage ------------------------------------------------------------ */
.ozv__body { position: relative; aspect-ratio: var(--ozv-ratio); }
.ozv__art {
  position: absolute; inset: 0; z-index: 1;
  width: 100%; height: 100%; pointer-events: none; overflow: visible;
}

/* --- the boxes ------------------------------------------------------------ */
.ozv__box {
  position: absolute; left: var(--x); top: var(--y);
  width: var(--w); height: var(--h);
  z-index: 0;
  border: 1px solid var(--line); border-radius: var(--r-lg);
  background: var(--surface);
}
.ozv__box-h {
  position: absolute; left: var(--s-3); top: var(--s-2);
  font-family: var(--font-mono); font-weight: 500; font-size: var(--fs-3xs);
  letter-spacing: .04em; color: var(--ink-2); white-space: nowrap;
}
.ozv__box--gen { --c: var(--c-violet); }
.ozv__box--tnk { --c: var(--c-coral); }

/* The rack: eleven tiles in the ramp's colours, placed in the box's own
   percentages so the dot that leaves one lands where it is drawn. */
.ozv-tiles { position: absolute; inset: 0; }
.ozv-tile {
  position: absolute; display: block;
  border-radius: 2px; background: var(--tc);
}
.ozv-tile > b { position: absolute; inset: 0; border-radius: 2px; background: #fff; opacity: 0; }
.ozv-tile--0 { --tc: var(--c-teal); }   .ozv-tile--1 { --tc: var(--c-cyan); }
.ozv-tile--2 { --tc: var(--c-blue); }   .ozv-tile--3 { --tc: var(--c-indigo); }
.ozv-tile--4 { --tc: var(--c-violet); } .ozv-tile--5 { --tc: var(--c-purple); }
.ozv-tile--6 { --tc: var(--c-mauve); }  .ozv-tile--7 { --tc: var(--c-pink); }
.ozv-tile--8 { --tc: var(--c-coral); }  .ozv-tile--9 { --tc: var(--c-teal); }
.ozv-tile--10 { --tc: var(--c-blue); }
.ozv-tile--10 { transform: translate(0, -7px); }
.ozv-tile--10 > b { opacity: .3; }

/* The template's name, under the tiles: each is in the same place, and the
   timeline shows the one the wave is on, then the one chosen. */
.ozv-tnames { position: absolute; left: var(--s-3); right: var(--s-3); bottom: var(--s-2); height: 1.3em; }
.ozv-tname {
  position: absolute; left: 0; top: 0; opacity: 0;
  font-family: var(--font-mono); font-size: var(--fs-3xs); letter-spacing: .04em;
  color: var(--ink);
}
.ozv-tname--10 { opacity: 1; }

/* The two stages of generation, as bars that fill while they run. */
.ozv-bars { position: absolute; display: grid; gap: 7px; }
.ozv-bar {
  display: grid; gap: 4px;
  font-family: var(--font-mono); font-size: var(--fs-3xs); letter-spacing: .03em;
  color: var(--ink-3);
}
.ozv-bar__t { display: block; height: 4px; border-radius: 2px; background: var(--line); overflow: hidden; }
.ozv-bar__i {
  display: block; height: 100%; border-radius: 2px; background: var(--c);
  transform-origin: 0 50%; transform: scaleX(1);
}

/* --- the drawing ---------------------------------------------------------- */
.ozv-user { fill: var(--c-blue); }
.ozv-wire { fill: none; stroke-width: 1.25; stroke-linecap: round; stroke-linejoin: round; opacity: .3; }
.ozv-wire--lane { stroke: var(--ink-3); }
.ozv-wire--credit, .ozv-wire--webhook { stroke: var(--c-coral); }
.ozv-slot { fill: none; stroke: var(--line-strong); stroke-width: 1; stroke-dasharray: 3 3; }
.ozv-coinslot { fill: none; stroke: var(--line-strong); stroke-width: 1; stroke-dasharray: 2 3; }
.ozv-coin { fill: var(--c-coral); }
.ozv-coin--a, .ozv-coin--c, .ozv-coin--d { opacity: 0; }
.ozv-dot { opacity: 0; }
.ozv-photo { opacity: 0; }

/* --- the clip ------------------------------------------------------------- */
/* A 9:16 card, sized in pixels because a scene is drawn at one size, placed
   in stage percentages by the timeline. The wrapper holds the perspective
   and the place; the card inside it tilts, rocks and shrinks; the layers in
   the card stand at three depths, so a tilt slides them against each other;
   and behind the card a stack of frames stands off in z. */
.ozv-clip {
  position: absolute; left: var(--x); top: var(--y); z-index: 2;
  width: 72px; height: 128px; margin: -64px 0 0 -36px;
  perspective: 420px; pointer-events: none;
}
.ozv-clip__card {
  position: absolute; inset: 0;
  transform-style: preserve-3d;
  transform: rotateY(0deg) rotateX(0deg) scale(.58);
}
.ozv-clip__frame {
  position: absolute; inset: 0; border-radius: 6px;
  background: color-mix(in oklab, var(--tc) 35%, var(--bg-2));
  border: 1px solid color-mix(in oklab, var(--tc) 55%, transparent);
  opacity: 0;
}
.ozv-clip__face {
  position: absolute; inset: 0; border-radius: 6px; overflow: hidden;
  box-shadow: 0 0 0 1px rgba(237, 243, 245, .12), 0 18px 40px rgba(0, 0, 0, .5);
  background: var(--sky);
}
.ozv-clip--horse { --tc: var(--c-violet); --sky: linear-gradient(180deg, #3B4FA6 0%, #8480D4 45%, #E08A8A 100%); }
.ozv-clip--space { --tc: var(--c-pink); --sky: linear-gradient(180deg, #060A14 0%, #141C3A 60%, #2A1E3E 100%); }
.ozv-clip--surf  { --tc: var(--c-blue); --sky: linear-gradient(180deg, #24969B 0%, #6FB7D6 55%, #CFE6EE 100%); }

/* The three depths. The back sits behind the screen plane and the front in
   front of it, so a tilt of the card parallaxes them. */
/* Each layer reaches 14px past the card on either side, and slides against
   the others by an amount the timeline works out from the card's tilt. */
.ozv-scn__l { position: absolute; top: 0; left: -14px; width: 100px; height: 100%; display: block; }
.ozv-scn__cap {
  position: absolute; left: 4px; right: 4px; top: 6px;
  font-family: var(--font-sans); font-weight: 800; font-size: 8px; line-height: 1.1;
  letter-spacing: .02em; text-transform: uppercase; text-align: center;
  color: #fff; text-shadow: 0 1px 0 #000, 0 0 3px #000, 0 0 1px #000;
}
.ozv-scn__bar {
  position: absolute; left: 6px; right: 6px; bottom: 5px; height: 2px;
  border-radius: 1px;
  background: rgba(237, 243, 245, .3);
}
.ozv-scn__bar > i {
  position: absolute; inset: 0; border-radius: 1px; background: #fff;
  transform-origin: 0 50%; animation: ozv-play 4.2s linear infinite;
}
@keyframes ozv-play { from { transform: scaleX(0); } to { transform: scaleX(1); } }
.ozv-clip__mark {
  position: absolute; right: 5px; bottom: 10px; width: 9px; height: 9px;
  opacity: 1;
  filter: drop-shadow(0 0 2px #000);
}
.ozv-scn__motion { opacity: 1; }
.ozv-scn__still { opacity: 0; }

/* What moves inside a scene, on loops of its own. */
.ozv-scn__clouds { animation: ozv-slide 9s linear infinite; }
.ozv-scn__grass  { animation: ozv-slide 1.4s linear infinite; }
@keyframes ozv-slide { from { transform: translateX(0); } to { transform: translateX(-100px); } }
.ozv-scn__leg { transform-box: view-box; animation: ozv-gallop .62s ease-in-out infinite; }
.ozv-scn__leg--1, .ozv-scn__leg--3 { animation-delay: -.31s; }
.ozv-scn__leg--2 { animation-delay: -.15s; }
@keyframes ozv-gallop { 0%, 100% { transform: rotate(-28deg); } 50% { transform: rotate(26deg); } }
.ozv-scn__dust { animation: ozv-dust .62s ease-out infinite; transform-box: fill-box; transform-origin: 50% 100%; }
@keyframes ozv-dust { 0% { transform: scale(.4); opacity: 0; } 40% { opacity: .5; } 100% { transform: scale(1.4) translateX(-6px); opacity: 0; } }
.ozv-scn__stars--far  { animation: ozv-fall 14s linear infinite; }
.ozv-scn__stars--near { animation: ozv-fall 5s linear infinite; }
@keyframes ozv-fall { from { transform: translateY(-128px); } to { transform: translateY(0); } }
.ozv-scn__drift { transform-box: fill-box; transform-origin: 50% 50%; animation: ozv-drift 5.5s ease-in-out infinite; }
.ozv-scn__wave { animation: ozv-slide 2.6s linear infinite; }
.ozv-scn__ride { transform-box: fill-box; transform-origin: 50% 90%; animation: ozv-ride 1.3s ease-in-out infinite; }
@keyframes ozv-ride {
  0%, 100% { transform: translate(0, 0) rotate(-4deg); }
  50% { transform: translate(-2px, -5px) rotate(5deg); }
}
@keyframes ozv-drift {
  0%, 100% { transform: translate(0, 0) rotate(-5deg); }
  50% { transform: translate(2px, -6px) rotate(6deg); }
}

/* --- the labels ----------------------------------------------------------- */
.ozv__tag {
  position: absolute; left: var(--x); top: var(--y); z-index: 2;
  font-family: var(--font-mono); font-size: var(--fs-3xs); line-height: 1.3;
  letter-spacing: .04em; white-space: nowrap;
  color: var(--ink-3); pointer-events: none;
}
.ozv__tag--above { transform: translate(-50%, -100%); }
.ozv__tag--below { transform: translate(-50%, 0); text-align: center; }
.ozv__tag--right { transform: translate(0, -50%); }
.ozv__tag--left  { transform: translate(-100%, -50%); }
.ozv__tag--webhook, .ozv__tag--credit { color: var(--c-coral); }

/* --- what only the stacked layout shows ----------------------------------- */
.ozv-mgal, .ozv-mcred { display: none; }

@media (max-width: 1000px) {
  .ozv__body { aspect-ratio: auto; display: grid; gap: var(--s-3); }
  .ozv__art, .ozv__tag, .ozv-clip { display: none; }
  .ozv__box, .ozv__box * { animation: none !important; }
  .ozv__box {
    position: relative; left: auto; top: auto; width: auto; height: auto;
    padding: var(--s-5) var(--s-3) var(--s-3);
  }
  .ozv-tiles { position: relative; inset: auto; display: flex; gap: 5px; height: 34px; }
  .ozv-tnames { position: relative; inset: auto; margin-top: 6px; }
  .ozv-tile { position: relative; left: auto !important; top: auto !important; width: 12px !important; height: 34px !important; }
  .ozv-bars { position: relative; left: 0 !important; top: 0 !important; width: min(100%, 320px) !important; }
  .ozv-mgal { display: flex; gap: 8px; }
  .ozv-mthumb {
    display: block; width: 30px; height: 56px; border-radius: 2px; overflow: hidden;
    background: var(--c-violet);
  }
  .ozv-mthumb--1 { background: var(--c-pink); }
  .ozv-mthumb--2 { background: var(--c-blue); }
  .ozv-mthumb > svg { display: block; width: 100%; height: 100%; }
  .ozv-mcred {
    display: block; font-family: var(--font-mono); font-size: var(--fs-3xs);
    letter-spacing: .03em; color: var(--ink-3);
  }
}

/* --------------------------------------------------------------------------
   The last frame, held: the animations off, the statics above showing.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .ozv__body *, .ozv__body { animation: none !important; }
  .ozv-scn__bar > i { transform: scaleX(.6); }
}
