/* Thread · the line layer, its stacking and the loop hook (docs/thread-spec.md §4).
   Knots and stations are styled by each page through [data-reached]; nothing about them here. */

/* Registered so the loop can animate from 0 to 1. It inherits: thread.js sets it on the root,
   and the shell's footer hover (--loop-draw: 1 on the footer) still wins inside the footer. */
@property --loop-draw {
  syntax: "<number>";
  inherits: true;
  initial-value: 0;
}

[data-thread-root] { position: relative; }

/* The line is always behind everything */
.thread-layer {
  position: absolute;
  left: 0;
  top: 0;
  z-index: 0;
  pointer-events: none;
  overflow: visible;
}
/* Hidden until the first build, so a line never starts in the wrong place */
.thread-layer:not([data-thread-ready]) { visibility: hidden; }

.thread-layer path {
  fill: none;
  stroke: var(--color-line-exact);
  stroke-width: var(--stroke-exact);
  vector-effect: non-scaling-stroke;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Every other direct child of the root sits above the line.
   :where() keeps this weak, so the sticky nav (and anything placed on purpose) keeps its own position and z-index. */
:where([data-thread-root]) > :where(:not(.thread-layer):not([data-shell="nav"])) {
  position: relative;
  z-index: 1;
}

/* Measured once per build, never during scroll: its height is the small viewport height (100svh)
   and its width is --thread-x in px (the token is a calc(), so it can't be read as a number) */
.thread-probe {
  position: fixed;
  left: 0;
  top: 0;
  width: var(--thread-x);
  height: 100svh;
  visibility: hidden;
  pointer-events: none;
}

/* The loop closes over 0.7s when the line arrives */
.footer-talk__loop { transition: --loop-draw 0.7s cubic-bezier(0.5, 0, 0.2, 1); }

/* drawAll(true) and reduced motion: everything at once, no transitions */
[data-thread-static] .footer-talk__loop { transition: none; }
@media (prefers-reduced-motion: reduce) {
  .footer-talk__loop { transition: none; }
}
