/* DATA FLOW (L1) — js/tuhi/dataflow.js. Tuhi's Data Flow look (lanes, tinted nodes, curved edges, flowing dots, the live bar and
   ticker), built on this console's tokens (tuhi-shell.css: --surface, --bd, --fg, --mut, --acc …) so both themes follow. */
.dfx{ position:relative; }
.dfx-bar{ display:flex; flex-wrap:wrap; align-items:center; gap:8px 10px; margin:0 0 10px; }
.dfx-seg{ display:inline-flex; border:1px solid var(--bd); border-radius:9px; overflow:hidden; }
.dfx-seg button{ border:0; border-radius:0; height:30px; padding:0 10px; display:inline-flex; align-items:center; gap:5px; font-size:12.5px; }
.dfx-seg button[aria-pressed="true"]{ background:var(--acc-soft); color:var(--acc-fg, var(--acc)); font-weight:700; }
.dfx-f{ display:inline-flex; align-items:center; gap:5px; font-size:12px; color:var(--mut); }
.dfx-f .ctl{ height:30px; padding:0 6px; font-size:12.5px; max-width:160px; }
.dfx-search{ display:inline-flex; gap:4px; margin:0; } .dfx-search .ctl{ height:30px; width:230px; max-width:60vw; font-size:12.5px; }
#dfPause{ height:30px; display:inline-flex; align-items:center; gap:5px; }
#dfPause[aria-pressed="true"]{ border-color:var(--warn); color:var(--warn-fg, var(--warn)); }
.dfx-legend{ display:flex; flex-wrap:wrap; gap:10px 14px; margin:2px 0 10px; font-size:12px; color:var(--fg-2); }
.dfx-lg{ display:inline-flex; align-items:center; gap:6px; } .dfx-lg i{ width:11px; height:11px; border-radius:3px; display:inline-block; }
.dfx-lgsep{ width:1px; height:14px; background:var(--bd); }
.dfx-lg i.dfx-lg-acted{ background:rgba(229,72,77,.32); border:2px solid #e5484d; box-shadow:inset 3px 0 0 #e5484d; }
.dfx-lg i.dfx-lg-passed{ background:rgba(229,72,77,.06); border:1px solid rgba(229,72,77,.75); }
.dfx-lg i.dfx-lg-none{ background:transparent; border:1px dashed var(--mut); opacity:.7; }
.dfx-lg i.dfx-lg-edge{ width:22px; height:5px; border-radius:3px; background:var(--mut); }
.dfx-lg i.dfx-lg-chain{ width:12px; height:14px; border-radius:0; border-left:1.5px solid var(--mut); border-top:1.5px solid var(--mut); border-bottom:1.5px solid var(--mut); background:transparent; opacity:.7; }
.dfx-kpi{ cursor:help; } .dfx-kpi:focus-visible{ outline:2px solid var(--acc); } .dfx-i{ font-weight:400; opacity:.7; }
.dfx-card{ background:var(--surface); border:1px solid var(--bd); border-radius:12px; padding:12px 14px; box-shadow:var(--shadow-sm); min-width:0; }
.dfx-card.full{ position:fixed; inset:0; z-index:9999; margin:0; border-radius:0; overflow:auto; background:var(--bg); padding:18px 22px; }

/* the map scrolls SIDEWAYS inside its own box on a phone — never the page */
.dfx-canvas{ width:100%; overflow-x:auto; overflow-y:hidden; -webkit-overflow-scrolling:touch; touch-action:pan-x pan-y; outline:none; }
/* the svg is laid out at the box's own width (wider when the columns need it — then the box scrolls, never the page) */
.dfx-canvas svg{ display:block; max-width:none; cursor:grab; user-select:none; }
.dfx-colhdr{ fill:var(--mut); font-weight:650; letter-spacing:.3px; pointer-events:none; }
.dfx-colg{ cursor:help; }
.dfx-lbl{ fill:var(--fg); pointer-events:none; } .dfx-val{ fill:var(--mut); pointer-events:none; } .dfx-sub{ fill:var(--mut); pointer-events:none; }
.dfx-colfoot{ fill:var(--mut); pointer-events:none; } .dfx-colfoot.b{ fill:var(--fg-2); font-weight:650; }
.dfx-strip rect{ fill:var(--surface-2); stroke:var(--bd); stroke-dasharray:4 3; } .dfx-strip text{ fill:var(--mut); pointer-events:none; } .dfx-strip{ cursor:help; }
.dfx-node rect.bx{ fill-opacity:.13; stroke-width:1.4px; }
/* a gate's three states — acted (held, refused, masked) · checked and passed · not consulted */
.dfx-node.g-acted rect.bx{ fill-opacity:.32; stroke-width:2.6px; } .dfx-actbar{ fill:#e5484d; pointer-events:none; }
.dfx-node.g-acted .dfx-val{ fill:var(--fg); font-weight:700; }
.dfx-node.g-passed rect.bx{ fill-opacity:.06; stroke-width:1px; stroke-opacity:.75; }
.dfx-node.g-none, .dfx-node.zero{ opacity:.5; } .dfx-node.g-none rect.bx, .dfx-node.zero rect.bx{ fill-opacity:.02; stroke-width:1px; stroke-dasharray:4 3; }
.dfx-node.fold rect.bx{ fill:var(--surface-2) !important; fill-opacity:1; stroke:var(--bd) !important; stroke-dasharray:4 3; }
.dfx-node.fold .dfx-lbl{ fill:var(--fg-2); }
.dfx-chain{ stroke-opacity:.45; stroke-linejoin:round; pointer-events:stroke; }
.dfx-tick-acted{ stroke:#e5484d; stroke-width:3.6px; stroke-linecap:round; pointer-events:none; }
.dfx-tick-passed{ stroke:var(--mut); stroke-width:1.2px; stroke-opacity:.7; pointer-events:none; }
/* replay: the request's own path is drawn over a dimmed map */
svg.rp-mode .dfx-edge, svg.rp-mode .dfx-chain, svg.rp-mode [class^="dfx-tick-"]{ opacity:.12; } svg.rp-mode .dfx-flow{ display:none; }
.dfx-rp-edge{ stroke:var(--acc); stroke-width:4px; stroke-opacity:.9; stroke-linecap:round; pointer-events:none; }
.dfx-rp-chain{ stroke:var(--acc); stroke-width:2.2px; stroke-opacity:.9; stroke-linejoin:round; pointer-events:none; }
.dfx-rpv{ fill:var(--acc); font-weight:700; pointer-events:none; }
/* in a replay a gate looks like what it did to THIS request, not to the window */
svg.rp-mode .dfx-node.g-acted:not(.rp-acted) rect.bx{ fill-opacity:.13; stroke-width:1.4px; } svg.rp-mode .dfx-node.g-acted:not(.rp-acted) .dfx-actbar{ display:none; }
svg.rp-mode .dfx-node.rp-acted rect.bx{ fill-opacity:.36; stroke-width:2.6px; } .dfx-node.rp-acted .dfx-rpv{ fill:#e5484d; }
.dfx-node{ cursor:pointer; transition:opacity .15s; outline:none; }
.dfx-node:hover rect.bx, .dfx-node:focus rect.bx{ stroke-width:2.6px; }
.dfx-node:focus-visible rect.bx{ stroke:var(--acc) !important; stroke-width:3px !important; }
.dfx-st{ fill:var(--mut); }
.dfx-node.st-ok .dfx-st{ fill:#43c07d; } .dfx-node.st-warn .dfx-st{ fill:#f5a623; } .dfx-node.st-hold .dfx-st{ fill:#a879ff; }
.dfx-node.st-failing .dfx-st, .dfx-node.st-closed .dfx-st{ fill:#e5484d; } .dfx-node.st-off .dfx-st{ fill:var(--bd); } .dfx-node.st-unknown .dfx-st{ fill:none; stroke:var(--mut); stroke-dasharray:2 2; }
.dfx-flow{ opacity:.85; pointer-events:none; }
.dfx-hop{ fill:#5a86ff; filter:drop-shadow(0 0 4px rgba(90,134,255,.9)); pointer-events:none; }
/* a node that just did something: short and non-looping — it marks an EVENT (Tuhi) */
.dfx-node.hot rect.bx{ stroke:#5a86ff !important; stroke-width:2.8px !important; } .dfx-node.hot{ animation:dfxHot 1.4s ease-out 1; }
.dfx-node.hot-bad rect.bx{ stroke:#e5484d !important; stroke-width:2.8px !important; } .dfx-node.hot-bad{ animation:dfxBad 1.4s ease-out 1; }
@keyframes dfxHot{ 0%{ filter:drop-shadow(0 0 0 rgba(90,134,255,.9)); } 30%{ filter:drop-shadow(0 0 12px rgba(90,134,255,.95)); } 100%{ filter:none; } }
@keyframes dfxBad{ 0%{ filter:drop-shadow(0 0 0 rgba(229,72,77,.9)); } 30%{ filter:drop-shadow(0 0 12px rgba(229,72,77,.95)); } 100%{ filter:none; } }
.dfx-node.rp-dim{ opacity:.25; } .dfx-node.rp-on{ opacity:1; } .dfx-node.rp-on rect.bx{ fill-opacity:.3; stroke-width:2.2px; }
@media (prefers-reduced-motion: reduce){ .dfx-flow, .dfx-hop{ display:none; } .dfx-node.hot, .dfx-node.hot-bad{ animation:none; } .dfx-dot{ animation:none !important; } }
.dfx-ctrl{ display:flex; align-items:center; gap:10px; margin-top:12px; flex-wrap:wrap; }
.dfx-pills{ flex:1; min-width:240px; display:flex; gap:6px; flex-wrap:wrap; }
.dfx-pill{ display:inline-flex; align-items:center; gap:6px; padding:4px 10px; border:1px solid var(--bd); border-radius:999px; font-size:11.5px; }
.dfx-pill i{ width:7px; height:7px; border-radius:99px; display:inline-block; }
.dfx-zoom{ flex:none; display:inline-flex; gap:6px; align-items:center; }
.dfx-zoom button{ padding:4px 9px; line-height:1; } .dfx-zoom input{ width:120px; accent-color:var(--acc); cursor:pointer; }
.dfx-zoom .muted{ min-width:38px; text-align:right; font-size:11.5px; }
.dfx-kpis{ margin:12px 0 0; }
.dfx-livebar{ display:flex; align-items:center; gap:8px; margin-top:12px; font-size:12.5px; flex-wrap:wrap; }
.dfx-dot{ width:8px; height:8px; border-radius:50%; background:#43c07d; box-shadow:0 0 0 0 rgba(67,192,125,.7); animation:dfxBeat 2s infinite; }
.dfx-dot.off{ background:var(--mut); animation:none; }
@keyframes dfxBeat{ 70%{ box-shadow:0 0 0 7px rgba(67,192,125,0); } 100%{ box-shadow:0 0 0 0 rgba(67,192,125,0); } }
.dfx-ticker{ margin-top:6px; max-height:220px; overflow:auto; font-size:12px; border:1px solid var(--bd); border-radius:10px; }
.dfx-tick{ display:flex; gap:8px; padding:5px 10px; border-bottom:1px solid var(--bd-soft, var(--bd)); align-items:center; cursor:pointer; flex-wrap:wrap; }
.dfx-tick:last-child{ border-bottom:none; } .dfx-tick:hover, .dfx-tick:focus{ background:var(--surface-2); outline:none; }
.dfx-tick .tk-t{ color:var(--mut); font-variant-numeric:tabular-nums; } .dfx-tick .tk-n{ color:#5a86ff; font-weight:650; min-width:110px; }
.dfx-tick .tk-l{ flex:1; min-width:140px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; } .dfx-tick .tk-r{ font-size:11px; color:var(--mut); }
.dfx-small{ font-size:11.5px; margin-top:6px; }
.dfx-tip{ position:fixed; z-index:10050; max-width:360px; padding:9px 11px; border:1px solid var(--bd); border-radius:9px; background:var(--surface); color:var(--fg);
  font-size:11.5px; line-height:1.45; box-shadow:var(--shadow-lg); pointer-events:none; display:none; }
.dfx-tip .dfx-tipv{ margin:3px 0; }
.dfx-drawer{ position:fixed; top:0; right:0; bottom:0; width:min(560px, 100vw); z-index:10040; overflow:auto; background:var(--surface); border-left:1px solid var(--bd);
  box-shadow:var(--shadow-lg); padding:14px 16px 24px; }
.dfx-dh{ display:flex; align-items:center; gap:8px; margin-bottom:10px; flex-wrap:wrap; } .dfx-dh [data-close]{ margin-left:auto; }
.dfx-kv{ display:grid; grid-template-columns:110px minmax(0,1fr); gap:5px 10px; font-size:12.5px; margin:6px 0 10px; } .dfx-kv span{ color:var(--mut); } .dfx-kv b{ overflow-wrap:anywhere; font-weight:600; }
.dfx-integ{ padding:8px 10px; border-radius:9px; font-size:12.5px; margin:8px 0; border:1px solid var(--bd); display:block; }
.dfx-integ.ok{ background:var(--ok-bg); color:var(--ok-fg); border-color:var(--ok-bd); } .dfx-integ.warn{ background:var(--warn-bg); color:var(--warn-fg); border-color:var(--warn-bd); }
.dfx-player{ display:flex; align-items:center; gap:6px; flex-wrap:wrap; margin:8px 0; position:sticky; top:-14px; background:var(--surface); padding:6px 0; z-index:1; }
.dfx-player button{ height:28px; padding:0 9px; } .dfx-player .ctl{ height:28px; } #dfScrub{ flex:1; min-width:140px; accent-color:var(--acc); }
.dfx-steps{ list-style:none; margin:0; padding:0; } .dfx-steps li{ padding:7px 8px; border-bottom:1px solid var(--bd-soft, var(--bd)); cursor:pointer; font-size:12.5px; border-radius:6px; }
.dfx-steps li.on{ background:var(--acc-soft); box-shadow:inset 3px 0 0 var(--acc); } .dfx-steps li:focus{ outline:2px solid var(--acc); }
.dfx-steps .t{ display:inline-block; min-width:70px; color:var(--mut); font-variant-numeric:tabular-nums; }
.dfx-sd{ color:var(--fg-2); margin:2px 0 0 70px; overflow-wrap:anywhere; } .dfx-src{ margin:3px 0 0 70px; font-size:11.5px; }
.dfx-table{ width:100%; border-collapse:collapse; font-size:12px; } .dfx-table th{ text-align:left; color:var(--mut); font-size:11px; padding:5px 6px; border-bottom:1px solid var(--bd); }
.dfx-table td{ padding:6px; border-bottom:1px solid var(--bd-soft, var(--bd)); } .dfx-table tr[data-rid]{ cursor:pointer; } .dfx-table tr[data-rid]:hover, .dfx-table tr[data-rid]:focus{ background:var(--surface-2); outline:none; }
.dfx-table .n{ text-align:right; font-variant-numeric:tabular-nums; }
.dfx-hit{ padding:6px 4px; cursor:pointer; border-bottom:1px solid var(--bd-soft, var(--bd)); }
@media (max-width:640px){ .dfx-f .ctl{ max-width:120px; } .dfx-sd, .dfx-src{ margin-left:0; } .dfx-zoom input{ width:90px; } }
