/* Investigation map on the light hero canvas.
   Reliability model: the COMPLETED map is the default CSS state —
   nodes, labels, capsules, base lines, full trace, arrowheads, and
   the finding annotation all render with no JavaScript and no
   animation. When motion is allowed, one ~6s pass replays the trace:
   each segment draws linearly over its quiet base line, its arrowhead
   and destination node activate exactly when the segment completes
   (delay = segment start + duration), and the Delivery→Invoice
   segment draws black then flips red inside its own keyframes when
   it reaches the invoice. No loop, no hover pause, no essential
   content at opacity zero. Reduced motion and print show the
   completed state immediately. */

:root{--tr-quiet:hsl(0 0% 72%)}

.tr-svg{display:block;width:100%;height:auto}
.tr-svg-mobile{display:none;max-width:24rem;margin:0 auto}
@media(max-width:999.98px){
  .tr-svg-desktop{display:none}
  .tr-svg-mobile{display:block}
}

/* ── connections (final state: fully drawn) ───────────────────── */
.tr-under path,.tr-bg path{fill:none;stroke:var(--border);stroke-width:1.5}
.tr-far circle{fill:hsl(0 0% 85%)}
.tr-active path{
  fill:none;stroke-width:2.5;stroke-linecap:round;
  stroke-dasharray:1;stroke-dashoffset:0;
}
.tr-s1,.tr-s2{stroke:var(--foreground)}
.tr-s3,.tr-s4{stroke:var(--status-red)}
.tr-arrows polygon{opacity:1}
.tr-a1,.tr-a2{fill:var(--foreground)}
.tr-a3,.tr-a4{fill:var(--status-red)}

/* ── nodes (final state: active colours) ──────────────────────── */
.tn{color:var(--foreground)}
.tn-inv{color:var(--status-red)}
.tn circle{fill:currentColor}
.tn-po > rect{fill:currentColor}
.tn use{
  stroke:#fff;fill:none;stroke-width:2;
  stroke-linecap:round;stroke-linejoin:round;
}
.tn text{font-family:var(--font-sans)}
.tr-svg-desktop .tn text{text-anchor:middle}
.tn-name{font-size:17px;font-weight:600;fill:var(--foreground);
  letter-spacing:-.1px}
.tn-name-lg{font-size:19px}
.tn-id{font-family:var(--font-mono);font-size:13px;
  fill:var(--muted-foreground);letter-spacing:.1px}

/* value capsules: neutral grey; pale red only for the discrepancy */
.tn-cap rect{fill:var(--secondary);stroke:var(--border)}
.tn-cap text{
  font-size:13px;font-weight:500;fill:var(--foreground);
  text-anchor:middle;
}
.tn-cap-bad rect{fill:var(--status-red-bg);stroke:var(--status-red-border)}
.tn-cap-bad text{fill:var(--status-red);font-weight:600}

/* supporting records: quiet but readable */
.tn-quiet{color:hsl(0 0% 80%)}
.tn-hollow{color:var(--border-strong)}
.tn-hollow circle{
  fill:var(--background);stroke:currentColor;
  stroke-width:1.5;stroke-dasharray:4 4;
}
.tn-quiet .tn-name,.tn-hollow .tn-name{
  font-size:13.5px;font-weight:500;fill:var(--muted-foreground)}
.tn-sub{font-size:12px;fill:var(--muted-foreground)}

/* ── finding annotation: always fully readable ────────────────── */
.trp text{text-anchor:start;font-family:var(--font-sans)}
.tr-svg-desktop .trp text{text-anchor:middle}
.trp-link{fill:none;stroke:var(--status-red);stroke-width:1.5}
.trp-rule{fill:none;stroke:var(--border-strong);stroke-width:2}
.trp-l1{font-size:16px;font-weight:600;fill:var(--foreground);
  letter-spacing:-.1px}
.trp-amt{font-family:var(--font-mono);font-size:15px;font-weight:600;
  fill:var(--foreground)}
.trp-src{font-family:var(--font-mono);font-size:13px;
  fill:var(--muted-foreground)}

/* mobile scene renders near 1:1 — keep glyphs compact */
.tr-svg-mobile .tn-name{font-size:15px}
.tr-svg-mobile .tn-id{font-size:11.5px}
.tr-svg-mobile .tn-cap text{font-size:12px}
.tr-svg-mobile .tn-quiet .tn-name,
.tr-svg-mobile .tn-hollow .tn-name{font-size:11.5px}
.tr-svg-mobile .tn-sub{font-size:11px}
.tr-svg-mobile .tn-quiet text,
.tr-svg-mobile .tn-hollow text{text-anchor:middle}
.tr-svg-mobile .trp-l1{font-size:14px}
.tr-svg-mobile .trp-amt{font-size:13.5px}
.tr-svg-mobile .trp-src{font-size:10.5px}

/* ── one-run sequenced trace (motion-allowed only) ────────────── */
@media(prefers-reduced-motion:no-preference){
  @keyframes tr-draw{from{stroke-dashoffset:1}}
  @keyframes tr-colorize{from{color:var(--tr-quiet)}}
  @keyframes tr-arrow-in{from{opacity:0}}
  /* draw black for 5/6 of the run, then flip red on arrival */
  @keyframes tr-seg-red{
    0%{stroke-dashoffset:1;stroke:var(--foreground)}
    83%{stroke-dashoffset:0;stroke:var(--foreground)}
    100%{stroke-dashoffset:0;stroke:var(--status-red)}
  }
  @keyframes tr-link-em{from{stroke:var(--status-red-border)}}
  @keyframes tr-amt-em{from{fill:var(--muted-foreground)}}

  /* Approval is the active start node: static dark. Downstream
     nodes hold quiet grey until their incoming segment completes. */
  .tn-po,.tn-del,.tn-inv,.tn-pay{
    animation:tr-colorize .35s linear both;
  }
  .tr-s1,.tr-s2,.tr-s4{animation:tr-draw 1s linear both}
  .tr-s3{animation:tr-seg-red 1.2s linear both}
  .tr-a1,.tr-a2,.tr-a3,.tr-a4{animation:tr-arrow-in .2s linear both}
  .trp-link{animation:tr-link-em .4s linear both}
  .trp-amt{animation:tr-amt-em .5s linear both}

  /* delay = exact end of the incoming segment (linear draws) */
  .tr-s1{animation-delay:.3s}                 /* ends 1.3s  */
  .tr-a1,.tn-po{animation-delay:1.3s}
  .tr-s2{animation-delay:1.55s}               /* ends 2.55s */
  .tr-a2,.tn-del{animation-delay:2.55s}
  .tr-s3{animation-delay:2.8s}                /* tip arrives 3.8s */
  .tr-a3,.tn-inv{animation-delay:3.8s}
  .trp-link{animation-delay:3.9s}
  .tr-s4{animation-delay:4.1s}                /* ends 5.1s  */
  .tr-a4,.tn-pay{animation-delay:5.1s}
  .trp-amt{animation-delay:5.4s}
}

/* print: completed state, no motion */
@media print{
  .tn,.tr-active path,.tr-arrows polygon,.trp-link,.trp-amt{
    animation:none !important;
  }
}
