/**
 * roots.css — the visit's root system (js/roots.js): the plant in the left
 * gutter, its runners across the page.
 * Lives in .bg-layer, so it sits behind all content. Every colour is a
 * token: it follows the theme with nothing extra.
 */

.roots { position: absolute; pointer-events: none; }
.roots[hidden] { display: none; }
.roots-svg { display: block; overflow: visible; }

/* arrives after the page's own arrival */
.roots { animation: roots-in var(--dur-slow) var(--ease-out-quart) 500ms both; }
@keyframes roots-in { from { opacity: 0; } to { opacity: 1; } }

/* ── paints ── */
.rs-navy   { stop-color: var(--navy); }
.rs-blue   { stop-color: var(--blue); }
.rs-accent { stop-color: var(--accent); }
.rs-glow-in  { stop-color: var(--accent); stop-opacity: .16; }
.rs-glow-out { stop-color: var(--accent); stop-opacity: 0; }
.rs-tipglow-in  { stop-color: var(--accent); stop-opacity: .45; }
.rs-tipglow-out { stop-color: var(--accent); stop-opacity: 0; }
.rs-soil-top { stop-color: var(--text-faint); stop-opacity: .16; }
.rs-soil-end { stop-color: var(--text-faint); stop-opacity: 0; }

/* ── soil: a soft mound, its surface, a few pebbles ── */
.roots-mound { fill: url(#roots-soil-grad); }
.roots-soil { fill: none; stroke: var(--text-faint); stroke-width: 1; stroke-linecap: round; opacity: .55; }
.roots-grain { fill: var(--text-faint); opacity: .32; }

/* the path ahead: a faint dotted trace, like the route on the lab model */
.roots-ghost {
  fill: none; stroke: var(--text-faint); stroke-width: 1;
  stroke-linecap: round; stroke-dasharray: .5 7; opacity: .45;
}
.roots-halo {
  fill: none; stroke: var(--accent-dim); stroke-width: 12; stroke-linecap: round;
  stroke-dasharray: 1 1; stroke-dashoffset: 1;
}

/* ── the grown roots: tapered ribbons, redrawn as they grow ── */
.roots-reveal {
  fill: none; stroke: #fff; stroke-linecap: round; stroke-linejoin: round;
  stroke-dasharray: 1 1; stroke-dashoffset: 1;
}
/* the whole root system sits back behind the page; the plant and the
   chapter nodes keep full strength */
.roots-grown { opacity: .72; }
.roots-ends, .roots-halo { opacity: .55; }
.roots-fill { fill: url(#roots-depth); }
/* the orders lighten as they fine down: laterals, side roots, fibres */
.roots-tier.is-t1 { opacity: .92; }
.roots-tier.is-t2 { opacity: .7; }
.roots-tier.is-t3 { opacity: .5; }
/* the taproot's lit flank: it reads as round, not flat */
.roots-shine {
  fill: none; stroke: var(--sphere-spec); stroke-width: .7; stroke-linecap: round; opacity: .5;
}
/* the runners cross the page under the content: present, never in the way.
   Each leaves the taproot as strong as a lateral and fines and fades as it
   goes (width and stroke-opacity per stroke, from roots.js), in a flat
   colour: a gradient stroke this size is far dearer to repaint. Strokes of
   one root meet butt to butt (no beads at the joins); the tip is rounded.
   The orders cool as they fine down: runner, side root, its branches,
   rootlets. */
.roots-run {
  fill: none; stroke: var(--blue); stroke-linecap: butt; stroke-linejoin: round;
  stroke-dasharray: 1 1; stroke-dashoffset: 1;
}
.roots-run.is-tip { stroke-linecap: round; }
.roots-run:is(.is-o2, .is-o3) { stroke: var(--accent); }

/* sap: light pulses climbing the grown taproot toward the plant */
.roots-sap {
  fill: none; stroke: var(--sphere-spec); stroke-width: 1.1; stroke-linecap: round;
  stroke-dasharray: 1.5 26; opacity: .8;
  animation: roots-sap 2.6s linear infinite;
}
@keyframes roots-sap { to { stroke-dashoffset: 55; } }

.roots-end {
  fill: var(--accent); opacity: 0; transform-box: fill-box; transform-origin: center; transform: scale(0);
  transition: opacity var(--dur-base) var(--ease-out-quart), transform var(--dur-base) var(--ease-spring-physical);
}
.roots-end.is-on { opacity: .95; transform: scale(1); }
.roots-end.is-run.is-on { opacity: .15; }   /* a runner's tip: as faint as the runner there (× the group's .55) */

/* ── chapter nodes: hollow ahead, filled once reached, ringed and
   pulsing for the chapter being read ── */
.roots-node-dot {
  fill: var(--surface); stroke: var(--text-faint); stroke-width: 1.2;
  transition: fill var(--dur-fast) var(--ease-out-quart), stroke var(--dur-fast) var(--ease-out-quart);
}
.roots-node.is-reached .roots-node-dot { fill: var(--accent); stroke: var(--surface); stroke-width: 1.5; }
.roots-node-ring, .roots-node-pulse {
  fill: none; stroke: var(--accent); stroke-width: 1.2; opacity: 0;
  transform-box: fill-box; transform-origin: center; transform: scale(.4);
  transition: opacity var(--dur-base) var(--ease-out-quart), transform var(--dur-base) var(--ease-spring-physical);
}
.roots-node.is-current .roots-node-ring { opacity: .5; transform: scale(1); }
.roots-node.is-current .roots-node-pulse { animation: roots-pulse 2.4s var(--ease-out-quart) infinite; }
@keyframes roots-pulse {
  0% { opacity: .45; transform: scale(1); }
  70%, 100% { opacity: 0; transform: scale(1.9); }
}
.roots-node-num {
  font-family: var(--font-mono); font-size: 9.5px; letter-spacing: .02em;
  fill: var(--text-faint); transition: fill var(--dur-fast) var(--ease-out-quart);
  /* a halo of page colour keeps it legible over the rootlets */
  paint-order: stroke; stroke: var(--bg); stroke-width: 3px; stroke-linejoin: round;
}
.roots-node.is-reached .roots-node-num { fill: var(--text-muted); }
.roots-node.is-current .roots-node-num { fill: var(--accent); font-weight: 700; }

/* the root cap: a bright point in a soft glow, breathing gently */
.roots-tip-dot { fill: var(--accent); stroke: var(--surface); stroke-width: .8; }
.roots-tip-halo {
  transform-box: fill-box; transform-origin: center;
  animation: roots-breathe 2.8s var(--ease-in-out-smooth) infinite alternate;
}
@keyframes roots-breathe { from { transform: scale(.7); opacity: .7; } to { transform: scale(1.25); opacity: 1; } }

/* ── the plant ── */
.roots-tulip { --p: 0; }
.roots-tulip * { transform-box: view-box; transform-origin: 0 0; }

.roots-stem { fill: none; stroke: url(#roots-stem-grad); stroke-width: 1.8; stroke-linecap: round; }
/* the leaves unfurl from the stem as the root deepens */
.roots-leaf { transition: transform var(--dur-slow) var(--ease-out-quart); }
.roots-leaf.is-left  { transform: rotate(calc((1 - var(--p)) * 26deg)); }
.roots-leaf.is-right { transform: rotate(calc((1 - var(--p)) * -28deg)); }
/* a cupped blade: the outer half lit, the inner half in shade, a fine midrib */
.roots-blade.is-lit   { fill: url(#roots-leaf-lit); }
.roots-blade.is-shade { fill: url(#roots-leaf-shade); opacity: .85; }
.roots-midrib { fill: none; stroke: var(--sphere-spec-soft); stroke-width: .45; stroke-linecap: round; }

/* the head: the Tulip mark, growing as the visit goes on */
.roots-head {
  transform: scale(calc(.72 + .28 * var(--p)));
  transition: transform var(--dur-slow) var(--ease-out-quart);
}
.roots-petal { transition: transform var(--dur-slow) var(--ease-spring-physical); }
.roots-petal-body { stroke-linejoin: round; }
.roots-petal.is-top   .roots-petal-body { fill: url(#roots-petal-grad); }
.roots-petal.is-left  .roots-petal-body { fill: url(#roots-facet-l); }
.roots-petal.is-right .roots-petal-body { fill: url(#roots-facet-r); }
/* a glint along the lit edges */
.roots-petal-edge { fill: none; stroke: var(--sphere-spec); stroke-width: .7; stroke-linecap: round; opacity: .6; }

.roots-bloom-glow {
  opacity: 0; transform-box: fill-box; transform-origin: center; transform: scale(.3);
  transition: opacity var(--dur-slow) var(--ease-out-quart), transform var(--dur-slow) var(--ease-out-quart);
}
.roots-ray {
  fill: none; stroke: var(--accent); stroke-width: 1.1; stroke-linecap: round;
  opacity: 0; transform-box: fill-box; transform-origin: center; transform: scale(.2);
  transition: opacity var(--dur-base) var(--ease-out-quart), transform var(--dur-base) var(--ease-spring-physical);
  transition-delay: calc(var(--i) * 40ms + 150ms);
}
.roots-pollen circle { fill: var(--accent); opacity: 0; }

/* bloom: the mark's facets part (the sides lean out, the diamond lifts),
   light breaks around the head and pollen drifts up */
.roots-tulip.is-bloom .roots-petal.is-left  { transform: translate(-1.6px, .4px) rotate(-9deg); }
.roots-tulip.is-bloom .roots-petal.is-right { transform: translate(1.6px, .4px) rotate(9deg); }
.roots-tulip.is-bloom .roots-petal.is-top   { transform: translateY(-3.2px); }
.roots-tulip.is-bloom .roots-bloom-glow { opacity: 1; transform: scale(1); }
.roots-tulip.is-bloom .roots-ray { opacity: .65; transform: scale(1); }
.roots-tulip.is-bloom .roots-pollen circle {
  transform-box: fill-box; transform-origin: center;
  animation: roots-pollen 3.2s var(--ease-out-quart) infinite;
  animation-delay: calc(var(--i) * 1.05s + .4s);
}
@keyframes roots-pollen {
  0% { opacity: 0; transform: translate(0, 4px) scale(.6); }
  25% { opacity: .8; }
  100% { opacity: 0; transform: translate(3px, -10px) scale(1); }
}

@media (prefers-reduced-motion: reduce) {
  .roots, .roots-tip-halo, .roots-node-pulse, .roots-tulip.is-bloom .roots-pollen circle { animation: none; }
  .roots-sap { display: none; }
}
@media print { .roots { display: none; } }
