/*
 * doc-mermaid-motion.css — Diagram motion: dots that travel a diagram's edges, the diagram building
 * itself (Reveal), following one node's paths (Trace) and, in fullscreen, told a message at a time
 * (Steps) (CH-REQ-20260929-A).
 *
 * The runtime (src/modules/markdown-engine/elements/mermaid/motion.js) puts a
 * `<g class="doc-mermaid-motion">` after each edge of a drawn diagram, carrying the edge's route as
 * `--mermaid-motion-path` and its crossing time as `--mermaid-motion-duration`; each dot carries its
 * own `--mermaid-motion-delay`, so the dots on one edge are spread along it rather than stacked.
 * Everything visual is here, so the workspace and an exported page draw the same dot.
 *
 * Loaded by doc-framework.css, and on its own by the precompiled pages (/help, the blog) beside
 * doc-mermaid.css — like that file it has no @import and every selector is mermaid-scoped.
 *
 * The dot is Mermaid's colour, not the document's: a diagram is drawn in Mermaid's stock theme and its
 * frame follows the scheme the diagram is drawn in (`data-mermaid-scheme` or `data-doc-scheme`, as
 * doc-mermaid-spectrum.css says), never the document's accent (doc-mermaid.css, and `NATIVE_CHROME` in
 * scripts/verification/exemptions.mjs). An accent-coloured dot put a pink bead on a stock
 * purple-and-grey drawing for anyone with a pink accent. So: the stock light theme's own node border
 * in light, and a lighter shade of it on the dark canvas.
 */

.doc-mermaid-viewer {
  --mermaid-motion-dot: #9370db;
}

:root:is([data-mermaid-scheme='dark'], [data-doc-scheme='dark']) .doc-mermaid-viewer {
  --mermaid-motion-dot: #b9a3eb;
}

/* Where a browser cannot move a dot along a path, it is not drawn at all — rather than parked at the
   drawing's top-left corner. */
.doc-mermaid-motion {
  display: none;
  pointer-events: none;
}

@supports (offset-path: path("M 0 0 L 1 1")) {
  .doc-mermaid-motion {
    display: inline;
  }

  /* `!important` because Mermaid's own <style> reaches circles through the diagram's #id. A dot in
     a Spectrum (doc-mermaid-spectrum.css) animates its fill instead, which an `!important` would stop. */
  .doc-mermaid-motion:not([data-spectrum-motion]) .doc-mermaid-motion-dot {
    fill: var(--mermaid-motion-dot) !important;
  }

  .doc-mermaid-motion-dot {
    stroke: none !important;
    offset-path: var(--mermaid-motion-path, none);
    offset-rotate: 0deg;
    opacity: 0;
    animation: doc-mermaid-motion var(--mermaid-motion-duration, 0s) linear var(--mermaid-motion-delay, 0s) infinite;
  }

  /* An edge whose only arrowhead is at its start points back along its path. */
  .doc-mermaid-motion[data-reverse] .doc-mermaid-motion-dot {
    animation-direction: reverse;
  }

  /* Current: dashes streaming along the line, one pattern (motion.js CURRENT_PATTERN) per cycle. Current
     and Signal are lines on a line, so both are lifted toward the canvas's opposite (the bead,
     doc-mermaid-spectrum.css): a theme's accent is a shade of its own lines, and in it they vanished. */
  .doc-mermaid-motion-current {
    fill: none !important;
    stroke: color-mix(in oklab, var(--mermaid-motion-dot) 55%, var(--mermaid-spectrum-bead, currentColor)) !important;
    stroke-width: 2.5px !important;
    stroke-linecap: round;
    stroke-dasharray: 5 11 !important;
    opacity: 0.9;
    animation: doc-mermaid-motion-current var(--mermaid-motion-duration, 0s) linear infinite;
  }

  /* Signal: a bright segment sweeping the line once per crossing — measured 0–100 (`pathLength`). */
  .doc-mermaid-motion-signal {
    fill: none !important;
    stroke: color-mix(in oklab, var(--mermaid-motion-dot) 45%, var(--mermaid-spectrum-bead, currentColor)) !important;
    stroke-width: 3.5px !important;
    stroke-linecap: round;
    stroke-dasharray: 16 100 !important;
    stroke-dashoffset: 16;
    animation: doc-mermaid-motion-signal var(--mermaid-motion-duration, 0s) linear infinite;
  }

  .doc-mermaid-motion[data-reverse] .doc-mermaid-motion-current,
  .doc-mermaid-motion[data-reverse] .doc-mermaid-motion-signal {
    animation-direction: reverse;
  }

  /* Out of sight — the runtime marks the viewer, so nobody's battery animates what nobody sees. Held by
     the reader's Pause (playback.js) — with a build in progress — until they press Play. */
  [data-motion-paused] .doc-mermaid-motion > *,
  [data-motion-held] .doc-mermaid-motion > *,
  [data-motion-held] svg[data-reveal='playing'] [data-reveal-step] {
    animation-play-state: paused;
  }
}

@keyframes doc-mermaid-motion-current {
  from {
    stroke-dashoffset: 16;
  }
  to {
    stroke-dashoffset: 0;
  }
}

@keyframes doc-mermaid-motion-signal {
  from {
    stroke-dashoffset: 16;
  }
  to {
    stroke-dashoffset: -100;
  }
}

/* Each dot fades in as it leaves its source and out as it reaches its target, so none pops. */
@keyframes doc-mermaid-motion {
  0% {
    offset-distance: 0%;
    opacity: 0;
  }
  12% {
    opacity: 1;
  }
  88% {
    opacity: 1;
  }
  100% {
    offset-distance: 100%;
    opacity: 0;
  }
}

/* Play/Pause (playback.js): the icon of what a press would do. Important, and more specific than the
   blog's own `button svg { display: block !important }`, which showed both icons side by side. */
.doc-mermaid-actions [data-mermaid-action='playback'] .doc-mermaid-playback-play,
.doc-mermaid-actions [data-mermaid-action='playback']:is([data-playback='play'], [data-playback='replay']) .doc-mermaid-playback-pause {
  display: none !important;
}

.doc-mermaid-actions [data-mermaid-action='playback']:is([data-playback='play'], [data-playback='replay']) .doc-mermaid-playback-play {
  display: block !important;
}

/* Reveal (reveal.js): each piece waits hidden, then appears at its step's delay, in reading order. */
svg[data-reveal='waiting'] [data-reveal-step] {
  opacity: 0 !important;
}

svg[data-reveal='playing'] [data-reveal-step] {
  animation: doc-mermaid-reveal 450ms ease-out both;
  animation-delay: var(--mermaid-reveal-delay, 0s);
}

/* No `to`: each piece fades in to the opacity it has without the build. Glow's halo is soft by its own
   opacity, and a fade to 1 left it an opaque band until the build ended — for a whole GIF made with
   Build first (CH-REQ-20260929-A §30). */
@keyframes doc-mermaid-reveal {
  from {
    opacity: 0;
  }
}

/* Trace (trace.js): what the pointed-at node leads from and to stays lit; the rest steps back. */
svg[data-trace] g.node,
svg[data-trace] g.rough-node,
svg[data-trace] g.edgeLabel,
svg[data-trace] .edgePaths > path,
svg[data-trace] .doc-mermaid-motion,
svg[data-trace] [class*='messageLine'],
svg[data-trace] .messageText,
svg[data-trace] .actor-line {
  transition: opacity 150ms ease;
}

svg[data-tracing] [data-trace-dim] {
  opacity: 0.14 !important;
}

svg[data-tracing] [data-traced] {
  stroke: var(--mermaid-motion-dot) !important;
  stroke-width: 2.5px !important;
}

/* Steps (steps.js, CH-REQ-20260929-A §12): a sequence diagram in fullscreen, told a message at a time —
   what is ahead hidden, what has been told a little back, the newest at full strength. */
svg[data-steps] [data-step] {
  transition: opacity 200ms ease-out;
}

/* A click tells the next message, so two quick ones are two steps — not a word selected. */
svg[data-steps] {
  user-select: none;
  -webkit-user-select: none;
}

svg[data-steps] [data-step-ahead] {
  opacity: 0 !important;
  visibility: hidden !important;
}

svg[data-steps] [data-step-past] {
  opacity: 0.45;
}

@media (prefers-reduced-motion: reduce) {
  svg[data-steps] [data-step] {
    transition: none;
  }
}

/* In the toolbar: Steps, pressed while it steps; then Back, where the telling is, and Next. */
.doc-mermaid-steps {
  display: inline-flex !important;
  align-items: center !important;
  gap: 6px !important;
}

.doc-mermaid-steps[hidden],
.doc-mermaid-steps-count[hidden] {
  display: none !important;
}

.doc-mermaid-actions [data-mermaid-action='steps'][aria-pressed='true'] {
  border-color: #6366f1 !important;
  color: #4f46e5 !important;
}

.doc-mermaid-steps button:disabled {
  opacity: 0.4 !important;
  cursor: default !important;
}

.doc-mermaid-steps-count {
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
  box-sizing: border-box !important;
  min-width: 56px !important;
  height: 30px !important;
  padding: 0 8px !important;
  background: #ffffff !important;
  border: 1px solid #cbd5e1 !important;
  border-radius: 8px !important;
  color: #334155 !important;
  font: 600 12px/1 var(--font-body, system-ui, sans-serif) !important;
  font-variant-numeric: tabular-nums !important;
  white-space: nowrap !important;
}

:root:is([data-mermaid-scheme='dark'], [data-doc-scheme='dark']) .doc-mermaid-steps-count {
  background: #21262d !important;
  border-color: #30363d !important;
  color: #f1f5f9 !important;
}

:root:is([data-mermaid-scheme='dark'], [data-doc-scheme='dark']) .doc-mermaid-actions [data-mermaid-action='steps'][aria-pressed='true'] {
  border-color: #6366f1 !important;
  color: #a5b4fc !important;
}

/* Paper is still, and whole. */
@media print {
  .doc-mermaid-motion {
    display: none !important;
  }

  svg[data-reveal] [data-reveal-step],
  svg[data-tracing] [data-trace-dim],
  svg[data-steps] [data-step] {
    opacity: 1 !important;
    visibility: visible !important;
    animation: none !important;
  }
}
