/* chain.css — shared connecting-thread motif, loaded by /, /product/, and
   /studio/. Draws a thin Bezier rail down the page's left gutter, linking
   [data-chain] headings with small node dots and (sparingly) a sparkle-icon
   accent. Geometry ported from the retired hero-chain.{css,js} dense-hero
   experiment; recolored per page via --chain-* custom properties (each
   page sets these in its own <style> block — the site has two unrelated
   token systems: base.css's cyan/cobalt glow on /studio/, jamos.css's
   oxblood/brass editorial palette on / and /product/, so chain.css can't
   reference either directly and stays token-agnostic itself). */

:root{
  --chain-gutter:24px;
  --chain-a:#2de2ff;
  --chain-b:#3a5bff;
  --chain-c:#a582ff;
}

.chain-rail{
  position:absolute;
  top:0;
  left:0;
  /* Exactly the width of the page's own left margin — content starts at
     var(--chain-gutter), so ending the box there (not starting there,
     an earlier version's bug) guarantees the rail never touches text. */
  width:var(--chain-gutter);
  pointer-events:none;
  overflow:visible;
  z-index:1;
}

.chain-seg{
  fill:none;
  stroke:color-mix(in oklab, var(--chain-b) 55%, transparent);
  stroke-width:1.6;
  stroke-linecap:round;
  stroke-dasharray:1;
  stroke-dashoffset:1;
  transition:stroke-dashoffset .9s cubic-bezier(.33,0,.16,1);
}
.chain-seg.in{ stroke-dashoffset:0; }

.chain-node{
  opacity:0;
  transform-box:fill-box;
  transform-origin:center;
  transform:scale(.4);
  transition:opacity .5s cubic-bezier(.33,0,.16,1), transform .5s cubic-bezier(.33,0,.16,1);
}
.chain-node.in{ opacity:1; transform:scale(1); }

.chain-node--dot{ fill:var(--chain-a); }

.chain-node--sparkle{ filter:drop-shadow(0 0 10px color-mix(in oklab, var(--chain-a) 60%, transparent)); }
.chain-node--sparkle path{
  fill:none;
  stroke-width:2.4;
  stroke-linejoin:round;
}

/* Progressive enhancement: where CSS scroll-driven animations exist
   (html.st, set by base.js/jamos.js), each node/segment reveals on its
   OWN scroll-into-view progress via animation-timeline:view() — no
   per-element tuning needed, unlike the reveal-on-scroll stagger classes,
   since these are scattered down the page rather than clustered in one
   view. Self-contained under chain.js's own classes, not grafted onto
   the site's .reveal/.rv engines (different class names, different
   pages use different ones). Falls back to the .in class above, toggled
   by chain.js's IntersectionObserver, everywhere else. */
@supports (animation-timeline: view()){
  .st .chain-seg{
    transition:none;
    animation:chain-seg-draw linear both;
    animation-timeline:view();
    animation-range:entry 0% cover 45%;
  }
  .st .chain-node{
    transition:none;
    animation:chain-node-pop linear both;
    animation-timeline:view();
    animation-range:entry 0% cover 35%;
  }
  @keyframes chain-seg-draw{ from{ stroke-dashoffset:1; } to{ stroke-dashoffset:0; } }
  @keyframes chain-node-pop{ from{ opacity:0; transform:scale(.4); } to{ opacity:1; transform:scale(1); } }
}

/* CSS-only guarantee: OS-level reduced motion always renders the finished
   rail immediately, independent of whether chain.js ran, mirrors the
   retired hero-chain.css's own guarantee. */
@media (prefers-reduced-motion: reduce){
  /* .st .chain-seg (two classes) outscores the plain .chain-seg selector,
     so the @supports block above would otherwise still win and run the
     scroll-tied draw-in — match its specificity explicitly here too. */
  .chain-seg, .st .chain-seg{ stroke-dashoffset:0; transition:none; animation:none; }
  .chain-node, .st .chain-node{ opacity:1; transform:none; transition:none; animation:none; }
}

/* /studio/'s manual footer toggle (base.js). Mirrors base.css's own
   html.motion-off convention for its own classes, not a shared rule. */
html.motion-off .chain-seg{ stroke-dashoffset:0; transition:none; animation:none; }
html.motion-off .chain-node{ opacity:1; transform:none; transition:none; animation:none; }
