/* ==========================================================================
   Workflow Studio — showreel
   backdrop.css
   The graph the page sits on: long wires, their ports, and the signals the
   scroll pushes through them. Three screens of graph seen one screen at a
   time.
   ========================================================================== */

/* --- The backdrop layer ----------------------------------------------------
   Wires rather than boxes. A tiled sheet of little node cards was the product
   drawn literally, and at the opacity a backdrop can afford, the rectangles
   read as wallpaper. What survives being nearly invisible is the line work:
   curves crossing the page, a port where two segments meet, and a signal
   travelling the wire.

   Real SVG in the page, not a background-image: a data URI is a separate
   document, so nothing inside it animates from the sheet and no var() of ours
   resolves. Inline, the wires take --port and --accent straight from tokens.

   The layer is fixed and clips; the graph inside it is three viewports tall
   and slides. Same thing to look at as a graph laid down the whole document —
   scroll and the wires you had are gone, replaced by ones you have not seen —
   but it is a transform on one small box rather than a page-tall element the
   browser has to keep composited, and it needs no measuring: the travel is
   written in vh and CSS already knows what those are.

   z-index -1 keeps it under the content while still painting over the body
   background.
   -------------------------------------------------------------------------- */

.backdrop {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  /* The window the taller graph slides behind. */
  overflow: hidden;

  /* 0 to 1 down the page, written by backdrop.js and read by everything below.
     Declared here so the graph is drawn at rest before the first scroll frame,
     and so it degrades to a still image with no script. */
  --scroll: 0;

  /* Felt rather than seen. The page is a dark surface with text over it, and a
     line that can be followed across the page is a line being read instead of
     the copy. */
  opacity: 0.26;
  transition: opacity 0.7s ease;
}

.backdrop svg {
  width: 100%;
  /* Three screens of graph, two of which are always off the window: the top of
     the page shows the first third, the foot of it the last. The translate and
     this height are one number apart on purpose — 300vh of graph minus the
     100vh on show is exactly how far it may travel. */
  height: 300vh;
  display: block;
  transform: translate3d(0, calc(var(--scroll) * -200vh), 0);
}

/* Set by backdrop.js while a section that owns its own surface holds the
   middle of the viewport. Opacity rather than display: the two states are a
   fade into and out of the page, and a section boundary crossed at speed would
   otherwise blink. */
body.is-backdrop-off .backdrop {
  opacity: 0;
}

/* --- Wires, ports, signals -------------------------------------------------
   Every path carries pathLength="1", so a dash pattern is written in fractions
   of the curve instead of in user units nobody can measure off a bezier. That
   is what turns one scroll fraction into eight wires advancing together, each
   at its own rate, without knowing how long any of them is.
   -------------------------------------------------------------------------- */

.backdrop-wire {
  fill: none;
  stroke: var(--border-strong);
  stroke-width: 1;
  opacity: 0.42;
}

/* The signal: a short dash chasing the wire, gold on the trunk lines and pink
   on the branches, the same split the product makes between a workflow and the
   connections inside it. It moves only because the page moves — nothing here
   animates on its own, so a page left alone is a still page. */
.backdrop-signal {
  fill: none;
  stroke: var(--accent);
  stroke-width: 1.25;
  stroke-linecap: round;
  stroke-dasharray: 0.13 0.87;
  opacity: 0.4;
  /* Offset 1 at the top of the page, down to 1 - --speed at the bottom: the
     dash pattern sums to exactly 1, so every whole unit of travel is one clean
     lap of the wire and the signal never jumps. */
  stroke-dashoffset: calc(1 - var(--scroll) * var(--speed, 2));
}

.backdrop-signal.alt {
  stroke: var(--port);
}

/* The head of the signal, on the same path so it cannot drift off the curve: a
   dash short enough to read as a dot. */
.backdrop-head {
  fill: none;
  stroke: var(--accent);
  stroke-width: 2.75;
  stroke-linecap: round;
  stroke-dasharray: 0.003 0.997;
  opacity: 0.5;
  stroke-dashoffset: calc(1 - var(--scroll) * var(--speed, 2));
}

.backdrop-head.alt {
  stroke: var(--port);
}

/* Whole numbers, and no two neighbours alike: a fractional rate leaves the
   signal mid-wire at the foot of the page, and equal rates make the wires read
   as one thing moving. */
.backdrop-w1 {
  --speed: 2;
}

.backdrop-w2 {
  --speed: 3;
}

.backdrop-w3 {
  --speed: 5;
}

.backdrop-w4 {
  --speed: 4;
}

.backdrop-w5 {
  --speed: 3;
}

.backdrop-w6 {
  --speed: 5;
}

.backdrop-w7 {
  --speed: 2;
}

.backdrop-w8 {
  --speed: 4;
}

/* The ports sit on the exact end of a curve segment, which is the one point of
   a bezier that is guaranteed to be on it — a dot placed by eye near a curve
   is a dot visibly off it. */
.backdrop-port {
  fill: none;
  stroke: var(--port);
  stroke-width: 1.25;
  opacity: 0.3;
}

/* A layout may still change in one step; a motion may not. The graph holds
   still at its first screen and the signals hold their place — a still wire is
   still a wire. */
@media (prefers-reduced-motion: reduce) {
  .backdrop svg {
    transform: none;
  }

  .backdrop-signal,
  .backdrop-head {
    stroke-dashoffset: 1;
  }
}
