/* archviz — dark-first, follows the viewer's colour scheme. */

.archviz *, .archviz *::before, .archviz *::after { box-sizing: border-box; }

.archviz {
  --bg: #0f1115;
  --surface: #171a21;
  --surface-2: #1d212a;
  --line: #2b313d;
  --line-soft: #232833;
  --text: #e6e9ef;
  --text-dim: #98a1b3;
  --text-faint: #6b7385;
  --accent: #6aa9ff;
  --accent-soft: #1e3354;
  --ok: #4ec9a0;
  --warn: #e0a458;
  --err: #e5766a;
  --mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  color-scheme: dark;
  display: flex; flex-direction: column;
  height: 100%; min-height: 0;
  background: var(--bg); color: var(--text);
  font: 14px/1.5 ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

@media (prefers-color-scheme: light) {
  .archviz {
    --bg: #f6f7f9; --surface: #ffffff; --surface-2: #f0f2f6;
    --line: #d8dde6; --line-soft: #e6e9ef;
    --text: #1a1e26; --text-dim: #5b6474; --text-faint: #8a93a3;
    --accent: #2f6fdb; --accent-soft: #dce8fb;
    --ok: #1d9c76; --warn: #b3762a; --err: #c2483c;
    color-scheme: light;
  }
}

/* ---------- chrome ---------- */

.av-top-right { display: flex; align-items: center; }
.av-top {
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
  padding: 10px 16px; border-bottom: 1px solid var(--line);
  background: var(--surface); flex: 0 0 auto;
}
.av-crumbs { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.crumb {
  background: none; border: 0; padding: 2px 4px; border-radius: 5px;
  color: var(--text-dim); font: inherit; font-size: 13px; cursor: pointer;
}
button.crumb:hover { color: var(--accent); background: var(--surface-2); }
.crumb.current { color: var(--text); font-weight: 600; cursor: default; }
.crumb-sep { color: var(--text-faint); font-size: 12px; }

.av-body { display: flex; flex: 1 1 auto; min-height: 0; }
.av-stage {
  flex: 1 1 auto; min-width: 0; position: relative;
  overflow: hidden;              /* panning is a transform, not a scroll */
  touch-action: none;
  cursor: grab;
}
.av-stage.panning { cursor: grabbing; }
.av-canvas {
  position: absolute; top: 0; left: 0;
  transform-origin: 0 0; will-change: transform; user-select: none;
}
.av-svg { display: block; }

.av-panel {
  flex: 0 0 320px; border-left: 1px solid var(--line); background: var(--surface);
  padding: 16px; overflow: auto; display: flex; flex-direction: column; gap: 14px;
}
.av-panel-head h2 { margin: 0 0 6px; font-size: 15px; letter-spacing: -0.01em; }
.av-summary { margin: 0; color: var(--text-dim); font-size: 12.5px; }
.av-shared {
  margin: 8px 0 0; font-size: 12px; color: var(--warn);
  border-left: 2px solid var(--warn); padding-left: 8px;
}
.av-empty { color: var(--text-faint); font-size: 12.5px; margin: 0; }

.av-steps { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 1px; }
.av-step button {
  display: flex; gap: 9px; align-items: baseline; width: 100%; text-align: left;
  background: none; border: 0; color: var(--text-dim); font: inherit; font-size: 12.5px;
  padding: 6px 8px; border-radius: 6px; cursor: pointer;
}
.av-step button:hover { background: var(--surface-2); color: var(--text); }
.av-step.current button { background: var(--accent-soft); color: var(--text); font-weight: 600; }
.av-step.done button { color: var(--text-faint); }
.av-step-n {
  font: 600 10.5px/1.6 var(--mono); min-width: 17px; height: 17px; text-align: center;
  border-radius: 5px; background: var(--surface-2); color: var(--text-faint); flex: 0 0 auto;
}
.av-step.current .av-step-n { background: var(--accent); color: #08121f; }
.av-step-n.big { font-size: 11px; min-width: 19px; height: 19px; line-height: 1.75; }

.av-step-body {
  border-top: 1px solid var(--line-soft); padding-top: 12px;
  display: flex; flex-direction: column; gap: 9px;
}
.av-step-title { display: flex; gap: 9px; align-items: baseline; font-weight: 650; font-size: 13.5px; }
.av-step-body p { margin: 0; color: var(--text-dim); font-size: 12.5px; }
.av-step-body code, .av-summary code {
  font: 11.5px var(--mono); background: var(--surface-2);
  padding: 1px 4px; border-radius: 4px; color: var(--text);
}

.av-controls { display: flex; align-items: center; gap: 8px; margin-top: auto; padding-top: 10px; }
.av-count { font: 11.5px var(--mono); color: var(--text-faint); }
.av-btn {
  background: var(--surface-2); border: 1px solid var(--line); color: var(--text);
  border-radius: 7px; padding: 5px 11px; font: inherit; font-size: 12.5px; cursor: pointer;
}
.av-btn:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.av-btn:disabled { opacity: 0.4; cursor: default; }
.av-btn.ghost { background: none; }
.av-btn.drill {
  align-self: flex-start; border-color: var(--accent);
  color: var(--accent); background: var(--accent-soft);
}

.av-errors {
  background: color-mix(in srgb, var(--err) 16%, var(--bg));
  border-bottom: 1px solid var(--err); padding: 10px 16px; font-size: 12.5px;
}
.av-errors ul { margin: 6px 0 0; padding-left: 18px; font-family: var(--mono); font-size: 11.5px; }

/* ---------- diagram ---------- */

/* ---------- boundaries ---------- */

/* Three group kinds, because three genuinely different things get drawn as a
   box around some nodes:
     logical  a grouping the reader should notice   (default)
     zone     a deployment boundary — VPC, subnet, AZ, namespace, cluster
     trust    a security boundary — crossing it changes who you are
   The label sits on the border, not inside, so a nested group's title is never
   mistaken for one of its parent's members. */
.av-svg .group-box { fill: var(--surface); stroke: var(--line-soft); stroke-dasharray: 4 4; }
.av-svg .group-tag { fill: var(--bg); stroke: none; }
.av-svg .group-label {
  fill: var(--text-faint); font-size: 10.5px; letter-spacing: 0.07em;
  text-transform: uppercase; text-anchor: middle;
}

.av-svg .group-zone .group-box {
  fill: color-mix(in srgb, var(--accent) 5%, var(--surface));
  stroke: color-mix(in srgb, var(--accent) 40%, var(--line));
  stroke-dasharray: 7 5;
}
.av-svg .group-zone .group-label { fill: color-mix(in srgb, var(--accent) 70%, var(--text-faint)); }

.av-svg .group-trust .group-box {
  fill: color-mix(in srgb, var(--warn) 6%, var(--surface));
  stroke: color-mix(in srgb, var(--warn) 60%, var(--line));
  stroke-dasharray: 11 4 3 4;
}
.av-svg .group-trust .group-label { fill: var(--warn); }

.av-svg .node { cursor: default; transition: opacity 0.25s ease; }
.av-svg .node.has-detail { cursor: pointer; }
.av-svg .node-bg { fill: var(--surface-2); stroke: var(--line); stroke-width: 1; }
.av-svg .node-stripe { fill: var(--text-faint); }
.av-svg .node-inner { fill: none; stroke: var(--line); stroke-dasharray: 3 3; opacity: 0.7; }
.av-svg .node-label { fill: var(--text); font-size: 13px; font-weight: 600; text-anchor: middle; }
.av-svg .node-sub { fill: var(--text-dim); font-size: 11px; text-anchor: middle; }
.av-svg .node-drill { fill: var(--text-faint); font-size: 9.5px; text-anchor: end; letter-spacing: 0.04em; }
.av-svg .node.has-detail:hover .node-bg { stroke: var(--accent); }
.av-svg .node.has-detail:hover .node-drill { fill: var(--accent); }
.av-svg .node:focus { outline: none; }
.av-svg .node:focus-visible .node-bg { stroke: var(--accent); stroke-width: 2; }
.av-svg .node.dim { opacity: 0.28; }
.av-svg .node.is-focus .node-bg { stroke: var(--accent); stroke-width: 1.8; }

.av-svg .kind-actor .node-stripe { fill: var(--text-dim); }
.av-svg .kind-service .node-stripe { fill: var(--accent); }
.av-svg .kind-store .node-stripe { fill: var(--ok); }
.av-svg .kind-process .node-stripe { fill: var(--warn); }
.av-svg .kind-external .node-bg { fill: none; stroke-dasharray: 5 4; }
.av-svg .kind-external .node-label { fill: var(--text-dim); font-weight: 500; }
.av-svg .kind-external .node-stripe { fill: none; }

.av-svg .tone-active .node-bg { stroke: var(--accent); stroke-width: 1.8; fill: color-mix(in srgb, var(--accent) 12%, var(--surface-2)); }
.av-svg .tone-new .node-bg { stroke: var(--ok); stroke-width: 1.8; fill: color-mix(in srgb, var(--ok) 12%, var(--surface-2)); }
.av-svg .tone-error .node-bg { stroke: var(--err); stroke-width: 1.8; fill: color-mix(in srgb, var(--err) 12%, var(--surface-2)); }
.av-svg .tone-stale .node-bg { stroke-dasharray: 4 3; }
.av-svg .tone-stale .node-label, .av-svg .tone-stale .node-sub { fill: var(--text-faint); }

.av-svg .node-badge rect { fill: var(--accent); }
.av-svg .node-badge text { fill: #08121f; font: 600 10px var(--mono); text-anchor: middle; }
/* Badges inherit the tone of the card they sit on. */
.av-svg .tone-new .node-badge rect { fill: var(--ok); }
.av-svg .tone-error .node-badge rect { fill: var(--err); }
.av-svg .tone-stale .node-badge rect { fill: var(--text-faint); }

.av-svg .edge-path { fill: none; stroke: var(--line); stroke-width: 1.6; }
.av-svg .arrowhead { fill: var(--line); }
.av-svg .edge-label rect { fill: var(--bg); stroke: none; }
.av-svg .edge-label text { fill: var(--text-faint); font: 10.5px var(--mono); text-anchor: middle; }
.av-svg .edge.dim { opacity: 0.22; }
.av-svg .edge.ghost { opacity: 0.14; }
.av-svg .edge.flow .edge-path {
  stroke: var(--accent); stroke-width: 2; stroke-dasharray: 7 5;
  animation: av-march 0.7s linear infinite;
}
.av-svg .edge.flow .arrowhead, .av-svg .arrowhead.flow { fill: var(--accent); }
.av-svg .edge.flow .edge-label text { fill: var(--accent); }
.av-svg .token { fill: var(--accent); }
@keyframes av-march { to { stroke-dashoffset: -12; } }

.av-svg .callout rect { fill: var(--surface); stroke: var(--accent); stroke-width: 1; }
.av-svg .callout text { fill: var(--text); font-size: 11.5px; }
.av-svg .callout-leader { stroke: var(--accent); stroke-width: 1; stroke-dasharray: 3 3; fill: none; }

@media (prefers-reduced-motion: reduce) {
  .av-svg .edge.flow .edge-path { animation: none; }
  .av-svg .token { display: none; }
}

@media (max-width: 900px) {
  .av-body { flex-direction: column; }
  .av-panel { flex: 0 0 auto; border-left: 0; border-top: 1px solid var(--line); }
}

/* ---------- edit mode ---------- */

.av-edit-toggle.on { border-color: var(--accent); color: var(--accent); background: var(--accent-soft); }

.archviz[data-editing="on"] .av-svg .node { cursor: move; }
.archviz[data-editing="on"] .av-svg .node-drill { display: none; }
.archviz[data-editing="on"] .av-svg .edge-path { stroke-width: 2.4; }
/* Wires must be visible and clickable while editing, even transient ones. */
.archviz[data-editing="on"] .av-svg .edge { opacity: 1; }

.av-svg .node.is-selected .node-bg { stroke: var(--accent); stroke-width: 2.2; }
.av-svg .edge.is-selected .edge-path { stroke: var(--accent); stroke-width: 3; }
/* Must not be hit-testable: it sits under the cursor, and the drag uses
   elementFromPoint to find the node being wired to. */
.av-svg .av-wire { stroke: var(--accent); stroke-width: 2; stroke-dasharray: 5 4; pointer-events: none; }
.av-svg .av-wire.locked { stroke-dasharray: none; }

.av-edit { display: flex; flex-direction: column; gap: 9px; }
.av-field { display: flex; flex-direction: column; gap: 3px; }
.av-field.two { flex-direction: row; gap: 8px; }
.av-field.two .av-field { flex: 1; }
.av-field label {
  font: 10.5px/1.4 var(--mono); color: var(--text-faint);
  text-transform: uppercase; letter-spacing: 0.06em;
}
.av-field output { font: 12px var(--mono); color: var(--text-dim); padding: 3px 0; }
.av-field input, .av-field select {
  background: var(--bg); border: 1px solid var(--line); color: var(--text);
  border-radius: 6px; padding: 5px 8px; font: inherit; font-size: 12.5px; width: 100%;
}
.av-field input:focus, .av-field select:focus { outline: none; border-color: var(--accent); }
.av-check { display: flex; gap: 7px; align-items: center; font-size: 12px; color: var(--text-dim); }
.av-btn.danger { align-self: flex-start; border-color: var(--err); color: var(--err); }
.av-btn.danger:hover { background: color-mix(in srgb, var(--err) 15%, transparent); color: var(--err); }

/* editor: history, snap toggle, palette */
.av-tools { display: flex; gap: 5px; }
.av-tools .av-btn { padding: 4px 9px; }
.av-snap.on { border-color: var(--accent); color: var(--accent); }

/* The wire tool. It lives with the palette because that is where you go looking
   for something to add, and an arrow is the one thing you add that is not a
   shape. Armed, it turns the whole canvas into a two-click gesture. */
.av-wire-tool {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  width: 100%; background: var(--surface-2); border: 1px solid var(--line);
  color: var(--text-dim); border-radius: 7px; padding: 7px 9px;
  font: inherit; font-size: 11.5px; cursor: pointer;
}
.av-wire-tool:hover { color: var(--text); border-color: var(--accent); }
.av-wire-tool.on { border-color: var(--accent); color: var(--accent); background: color-mix(in srgb, var(--accent) 14%, var(--surface-2)); }
.av-wire-tool .av-wire-glyph { stroke: currentColor; stroke-width: 1.6; fill: none; }
.av-wire-tool .av-wire-head { fill: currentColor; }

/* While armed, every card is a target and nothing else should look draggable. */
.archviz[data-connecting="on"] .av-svg .node { cursor: crosshair; }
.archviz[data-connecting="on"] .av-svg .node:hover .node-bg { stroke: var(--accent); stroke-width: 2; }
.archviz[data-connecting="on"] .av-svg .node-nub { display: none; }
.av-svg .node.is-wire-source .node-bg { stroke: var(--accent); stroke-width: 2.4; }

/* A chip draws itself with the canvas's own shape table, so it cannot promise
   a silhouette the dropped card will not have. That also makes the old
   border-left colour redundant — the shape carries the kind now. */
.av-palette { display: grid; grid-template-columns: repeat(3, 1fr); gap: 5px; }
.av-chip {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  background: var(--surface-2); border: 1px solid var(--line); color: var(--text-dim);
  border-radius: 7px; padding: 7px 4px 5px;
  font: inherit; font-size: 10.5px; cursor: grab; touch-action: none;
}
.av-chip:hover { color: var(--text); border-color: var(--accent); }
.av-chip .av-shape { display: block; pointer-events: none; overflow: visible; }

/* The ghost is the same silhouette at the size the card will really be,
   centred on the pointer because dropNode() treats the pointer as its centre. */
.av-ghost {
  position: fixed; z-index: 50; pointer-events: none; opacity: 0.9;
  transform: translate(-50%, -50%) scale(var(--av-ghost-scale, 1));
  filter: drop-shadow(0 5px 16px rgb(0 0 0 / 0.4));
}
.av-ghost .av-shape { display: block; overflow: visible; }
.av-ghost .node-bg { stroke: var(--accent); stroke-width: 2; }

/* Connection nubs: four points to drag a wire out of. Hidden until the card is
   hovered or selected, and inert while hidden so they cannot steal a drag. */
.av-svg .node-nub {
  fill: var(--accent); stroke: transparent; stroke-width: 12;
  opacity: 0; pointer-events: none; transition: opacity 0.12s ease;
}
.archviz[data-editing="on"] .av-svg .node:hover .node-nub,
.archviz[data-editing="on"] .av-svg .node.is-selected .node-nub {
  opacity: 1; pointer-events: all; cursor: crosshair;
}
.av-svg .node-nub:hover { fill: var(--text); }
.archviz[data-editing="on"] .av-svg .node.is-wire-target .node-bg {
  stroke: var(--accent); stroke-width: 2.4;
}

/* The grips on a selected wire's two ends. Filled means attached to a card,
   hollow-amber means loose — so you can see what a wire is actually holding on
   to without dragging it to find out. */
.av-svg .av-endpoint {
  fill: var(--accent); stroke: var(--bg); stroke-width: 1.5;
  cursor: crosshair; touch-action: none;
}
.av-svg .av-endpoint.is-loose { fill: var(--bg); stroke: var(--warn); stroke-width: 2.2; }
.av-svg .av-endpoint:hover { fill: var(--text); }
.av-svg .av-endpoint.is-loose:hover { fill: var(--warn); }
.archviz[data-editing="on"] .av-svg .edge-path { cursor: move; }

/* A hollow dot on each gap: drag it to bend the wire there. A placed bend is
   solid, and a double-click drops it. */
.av-svg .av-bend {
  fill: var(--bg); stroke: var(--text-faint); stroke-width: 1.6;
  opacity: 0.55; cursor: grab; touch-action: none;
}
.av-svg .av-bend:hover { opacity: 1; stroke: var(--accent); }
.av-svg .av-waypoint {
  fill: var(--accent); stroke: var(--bg); stroke-width: 1.5;
  cursor: grab; touch-action: none;
}
.av-svg .av-waypoint:hover { fill: var(--text); }
.av-field .av-coord { font: 10.5px var(--mono); color: var(--text-faint); padding-top: 2px; }

/* The arrow you drag out of the palette. */
.av-ghost-wire .av-ghost-line { stroke: var(--accent); stroke-width: 2; fill: none; }
.av-ghost-wire .av-ghost-head { fill: var(--accent); }

.av-hint { margin: 0; font-size: 11px; color: var(--text-faint); line-height: 1.45; }

/* resize handles */
.av-svg .av-handle {
  fill: var(--bg); stroke: var(--accent); stroke-width: 1.5;
  cursor: pointer; touch-action: none;
}
.av-svg .av-handle:hover { fill: var(--accent); }
.av-svg .av-handle-n, .av-svg .av-handle-s { cursor: ns-resize; }
.av-svg .av-handle-e, .av-svg .av-handle-w { cursor: ew-resize; }
.av-svg .av-handle-nw, .av-svg .av-handle-se { cursor: nwse-resize; }
.av-svg .av-handle-ne, .av-svg .av-handle-sw { cursor: nesw-resize; }
.av-svg .node.is-free .node-bg { stroke-dasharray: 2 2; }

/* ---------- steps composer ---------- */

.av-tabs { display: flex; gap: 2px; border-bottom: 1px solid var(--line); }
.av-tab {
  background: none; border: 0; border-bottom: 2px solid transparent; color: var(--text-faint);
  font: inherit; font-size: 12.5px; padding: 5px 10px; cursor: pointer;
}
.av-tab:hover { color: var(--text); }
.av-tab.on { color: var(--accent); border-bottom-color: var(--accent); }

.av-steps.composing .av-step { display: flex; align-items: center; gap: 2px; }
.av-steps.composing .av-step > button { flex: 1; min-width: 0; }
.av-steps.composing .av-step > button span:last-child { overflow: hidden; text-overflow: ellipsis; }
.av-step-ops { display: flex; gap: 1px; opacity: 0; transition: opacity 0.12s; }
.av-steps.composing .av-step:hover .av-step-ops,
.av-steps.composing .av-step.current .av-step-ops { opacity: 1; }
.av-step-ops button {
  background: none; border: 0; color: var(--text-faint); cursor: pointer;
  font: 11px var(--mono); padding: 3px 4px; border-radius: 4px;
}
.av-step-ops button:hover:not(:disabled) { color: var(--accent); background: var(--surface-2); }
.av-step-ops button:disabled { opacity: 0.25; cursor: default; }

.av-field textarea {
  background: var(--bg); border: 1px solid var(--line); color: var(--text);
  border-radius: 6px; padding: 6px 8px; font: inherit; font-size: 12.5px;
  width: 100%; resize: vertical; line-height: 1.5;
}
.av-field textarea:focus { outline: none; border-color: var(--accent); }

.av-refs { display: flex; flex-wrap: wrap; gap: 4px; }
.av-none { color: var(--text-faint); font-size: 12px; font-style: italic; }
.av-ref {
  background: var(--accent-soft); border: 1px solid var(--accent); color: var(--accent);
  border-radius: 5px; padding: 2px 7px; font: 11px var(--mono); cursor: pointer;
}
.av-ref:hover { background: var(--accent); color: var(--bg); }

.av-setrow { display: flex; gap: 5px; align-items: center; margin-top: 5px; }
.av-setid { font: 11px var(--mono); color: var(--text-dim); flex: 0 0 68px;
  overflow: hidden; text-overflow: ellipsis; }
.av-setrow select { flex: 0 0 78px; }
.av-setrow input { flex: 1; min-width: 0; }

.av-problems {
  background: color-mix(in srgb, var(--err) 12%, transparent);
  border-left: 2px solid var(--err); padding: 7px 10px; font-size: 11.5px; border-radius: 0 6px 6px 0;
}
.av-problems ul { margin: 4px 0 0; padding-left: 15px; font: 10.5px/1.5 var(--mono); }

/* ---------- find ---------- */

.av-find { position: relative; margin-right: 8px; }
.av-find-input {
  background: var(--bg); border: 1px solid var(--line); color: var(--text);
  border-radius: 7px; padding: 5px 10px; font: inherit; font-size: 12.5px; width: 150px;
}
.av-find-input:focus { outline: none; border-color: var(--accent); width: 210px; }
.av-find-hits {
  position: absolute; top: calc(100% + 5px); right: 0; z-index: 20; width: 300px;
  max-height: 320px; overflow: auto; background: var(--surface); border: 1px solid var(--line);
  border-radius: 9px; box-shadow: 0 8px 26px rgb(0 0 0 / 0.4); padding: 4px;
}
.av-hit {
  display: block; width: 100%; text-align: left; background: none; border: 0;
  color: var(--text); font: inherit; font-size: 12.5px; padding: 6px 9px;
  border-radius: 6px; cursor: pointer;
}
.av-hit:hover { background: var(--surface-2); }
.av-hit-label { display: block; }
.av-hit-path { display: block; font-size: 11px; color: var(--text-faint); }
.av-svg .node.is-found .node-bg {
  stroke: var(--warn); stroke-width: 2.5;
  animation: av-pulse 0.5s ease-in-out 3;
}
@keyframes av-pulse { 50% { stroke-width: 4; } }

/* ---------- canvas ---------- */

.av-svg .av-grid-dot { fill: var(--line); opacity: 0.5; }


/* ---------- silhouettes ---------- */

/* Where a shape carries the identity, the outline carries the colour and the
   left stripe is dropped — two signals for one thing is one too many. */
.av-svg .node-rim { fill: none; stroke: var(--line); stroke-width: 1; }
.av-svg .node-slot { stroke: var(--line); stroke-width: 1; }
.av-svg .node-plate-bg { fill: var(--surface-2); stroke: var(--line); stroke-width: 1; }
.av-svg .node-plate { opacity: 0.55; }

.av-svg .kind-database .node-bg,
.av-svg .kind-database .node-rim { stroke: color-mix(in srgb, var(--ok) 55%, var(--line)); }
.av-svg .kind-queue .node-bg { stroke: color-mix(in srgb, var(--warn) 55%, var(--line)); }
.av-svg .kind-queue .node-slot { stroke: color-mix(in srgb, var(--warn) 50%, var(--line)); }
.av-svg .kind-gateway .node-bg { stroke: color-mix(in srgb, var(--accent) 60%, var(--line)); }

/* Tone still wins: a failing database must read as failing, not as a database. */
.av-svg .is-shaped.tone-active .node-bg { stroke: var(--accent); }
.av-svg .is-shaped.tone-new .node-bg { stroke: var(--ok); }
.av-svg .is-shaped.tone-error .node-bg { stroke: var(--err); }
.av-svg .is-shaped.is-focus .node-bg,
.av-svg .is-shaped.is-selected .node-bg { stroke: var(--accent); }

/* ---------- triggers ---------- */

/* How work arrives, marked on the leading corner. A modifier like replicas, so
   it composes with every silhouette rather than needing its own shape. */
.av-svg .node-trigger circle { fill: var(--surface); stroke: var(--text-faint); stroke-width: 1.2; }
.av-svg .trigger-hand { fill: none; stroke: var(--text-dim); stroke-width: 1.3; stroke-linecap: round; }
.av-svg .trigger-bolt { fill: var(--warn); stroke: none; }
.av-svg .trigger-play { fill: var(--ok); stroke: none; }
.av-svg .trig-schedule .node-trigger circle { stroke: var(--accent); }
.av-svg .trig-schedule .trigger-hand { stroke: var(--accent); }

/* Sweep a rectangle over the canvas to select what it touches. */
.av-svg .av-marquee {
  fill: color-mix(in srgb, var(--accent) 12%, transparent);
  stroke: var(--accent); stroke-width: 1; stroke-dasharray: 4 3; pointer-events: none;
}

/* Transient feedback while free-positioning: where this card lines up with
   others. Never drawn on the grid, where alignment is guaranteed anyway. */
.av-svg .av-guide {
  stroke: var(--warn); stroke-width: 1; stroke-dasharray: 3 3;
  pointer-events: none; opacity: 0.9;
}
