/* Extracted from search-query-pipeline-diagram-tool.html (plan 010, phase 1). */
/* ---------- tokens ---------- */
:root{
  --bg:#f6f7f9; --surface:#ffffff; --surface-2:#f0f2f5; --surface-3:#e7eaef;
  --border:#d8dde5; --border-strong:#b9c1cd;
  --text:#101725; --text-2:#465063; --text-3:#6d7789;
  --accent:#2563eb; --accent-soft:#e8effd;
  --core-bg:#dbeafe; --core-line:#1d4ed8; --core-text:#12275e;
  --rec-bg:#dcfce7; --rec-line:#15803d; --rec-text:#12351f;
  --opt-bg:#ede9fe; --opt-line:#6d28d9; --opt-text:#2b1a52;
  --ctrl-bg:#e8ecf2; --ctrl-line:#64748b; --ctrl-text:#27303f;
  --wire:#6f7d92; --wire-gate:#2563b8; --wire-loop:#b85f36; --wire-ctrl:#667085;
  --gate-request:var(--wire-gate); --gate-config:#7a8496;
  --wire-observe:#7b8794;
  --wire-feed:#7c3aed; --wire-train:#0f766e; --wire-update:#be185d; --wire-data:#53657d;
  --data-bg:#f7f9fc; --data-line:#7b8798; --data-text:#344054;
  --rt-edge:#64748b; --rt-inproc:#991b9f; --rt-service:#0f766e; --rt-gpu:#b45309;
  --rt-fm:#7c3aed; --rt-engine:#be123c; --rt-store:#0369a1; --rt-stream:#4d7c0f; --rt-ctrl:#6d7789;
  --warn:#b45309; --warn-bg:#fef3c7;
  --ok:#15803d;
  --shadow:0 1px 2px rgba(16,23,37,.06),0 4px 12px rgba(16,23,37,.06);
  --shadow-lg:0 12px 40px rgba(16,23,37,.18);
  --radius:10px;
  --mono:"JetBrains Mono",ui-monospace,SFMono-Regular,Menlo,monospace;
}
@media (prefers-color-scheme: dark){
  :root:not([data-theme="light"]){
      --bg:#0d1117; --surface:#151b24; --surface-2:#1b2230; --surface-3:#232c3b;
      --border:#2a3444; --border-strong:#3a4658;
      --text:#e7ecf3; --text-2:#a9b4c4; --text-3:#7d8798;
      --accent:#6ea0ff; --accent-soft:#17233c;
      --core-bg:#16294d; --core-line:#5b8def; --core-text:#cfe0ff;
      --rec-bg:#12331f; --rec-line:#4ea96e; --rec-text:#cdf0d8;
      --opt-bg:#241b47; --opt-line:#9b7ff0; --opt-text:#e0d6ff;
      --ctrl-bg:#1e2532; --ctrl-line:#7c8798; --ctrl-text:#c3ccda;
      --wire:#8290a6; --wire-gate:#60a5fa; --wire-loop:#d08b65; --wire-ctrl:#93a0b5;
      --gate-config:#93a0b5;
      --wire-observe:#8b96a8;
      --wire-feed:#a78bfa; --wire-train:#2dd4bf; --wire-update:#f472b6; --wire-data:#9aabc2;
      --data-bg:#18202b; --data-line:#6f7f95; --data-text:#c4cedc;
      --rt-edge:#93a0b5; --rt-inproc:#f0abfc; --rt-service:#2dd4bf; --rt-gpu:#e0a94a;
      --rt-fm:#a78bfa; --rt-engine:#fb7185; --rt-store:#38bdf8; --rt-stream:#a3e635; --rt-ctrl:#7d8798;
      --warn:#e0a94a; --warn-bg:#332a17;
      --ok:#4ea96e;
      --shadow:0 1px 2px rgba(0,0,0,.4),0 4px 12px rgba(0,0,0,.3);
      --shadow-lg:0 12px 40px rgba(0,0,0,.55);
  }
}
:root[data-theme="dark"]{
  --bg:#0d1117; --surface:#151b24; --surface-2:#1b2230; --surface-3:#232c3b;
  --border:#2a3444; --border-strong:#3a4658;
  --text:#e7ecf3; --text-2:#a9b4c4; --text-3:#7d8798;
  --accent:#6ea0ff; --accent-soft:#17233c;
  --core-bg:#16294d; --core-line:#5b8def; --core-text:#cfe0ff;
  --rec-bg:#12331f; --rec-line:#4ea96e; --rec-text:#cdf0d8;
  --opt-bg:#241b47; --opt-line:#9b7ff0; --opt-text:#e0d6ff;
  --ctrl-bg:#1e2532; --ctrl-line:#7c8798; --ctrl-text:#c3ccda;
  --wire:#8290a6; --wire-gate:#60a5fa; --wire-loop:#d08b65; --wire-ctrl:#93a0b5;
  --gate-config:#93a0b5;
  --wire-observe:#8b96a8;
  --wire-feed:#a78bfa; --wire-train:#2dd4bf; --wire-update:#f472b6; --wire-data:#9aabc2;
  --data-bg:#18202b; --data-line:#6f7f95; --data-text:#c4cedc;
  --rt-edge:#93a0b5; --rt-inproc:#f0abfc; --rt-service:#2dd4bf; --rt-gpu:#e0a94a;
  --rt-fm:#a78bfa; --rt-engine:#fb7185; --rt-store:#38bdf8; --rt-stream:#a3e635; --rt-ctrl:#7d8798;
  --warn:#e0a94a; --warn-bg:#332a17;
  --ok:#4ea96e;
  --shadow:0 1px 2px rgba(0,0,0,.4),0 4px 12px rgba(0,0,0,.3);
  --shadow-lg:0 12px 40px rgba(0,0,0,.55);
}

*{box-sizing:border-box}
[hidden]{display:none!important}
html,body{margin:0;padding:0}
body{
  background:var(--bg); color:var(--text);
  font-family:Inter,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,sans-serif;
  font-size:14px; line-height:1.5; -webkit-font-smoothing:antialiased;
}
button{font:inherit;color:inherit;cursor:pointer}
h1,h2,h3,h4{margin:0;font-weight:600;letter-spacing:-.01em}
a{color:var(--accent)}

/* ---------- header ---------- */
.hdr{
  position:sticky; top:0; z-index:40; background:var(--surface);
  border-bottom:1px solid var(--border); padding:10px 20px;
  display:flex; align-items:center; gap:18px; flex-wrap:wrap;
}
.hdr .brand{display:flex;flex-direction:column;gap:1px;margin-right:auto}
.hdr h1{font-size:15px}
.hdr .sub{font-size:11.5px;color:var(--text-3)}
.tabs{display:flex;gap:2px;background:var(--surface-2);padding:3px;border-radius:8px}
.tabs button{
  border:0;background:transparent;padding:6px 14px;border-radius:6px;
  font-size:13px;font-weight:500;color:var(--text-2)
}
.tabs button[aria-selected="true"]{background:var(--surface);color:var(--text);box-shadow:var(--shadow)}
.icon-btn{
  border:1px solid var(--border);background:var(--surface);width:32px;height:32px;
  border-radius:8px;display:grid;place-items:center;font-size:14px
}
.icon-btn:hover{background:var(--surface-2)}
.hdr-actions{display:flex;gap:8px}
.sr-only{
  position:absolute;width:1px;height:1px;margin:-1px;padding:0;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0
}

/* ---------- context bar ---------- */
.ctxbar{
  position:sticky; top:53px; z-index:35; background:var(--bg);
  border-bottom:1px solid var(--border); padding:12px 20px 12px;
}
.seg{display:inline-flex;background:var(--surface-2);padding:3px;border-radius:9px;border:1px solid var(--border)}
.seg button{
  position:relative;
  border:0;background:transparent;padding:7px 16px;border-radius:7px;font-size:13px;
  font-weight:500;color:var(--text-2);display:flex;align-items:center;gap:8px;white-space:nowrap
}
.seg button .n{
  display:grid;place-items:center;width:18px;height:18px;border-radius:5px;
  background:var(--surface-3);font-size:11px;font-weight:700;color:var(--text-2)
}
.seg button[aria-pressed="true"]{background:var(--surface);color:var(--text);box-shadow:var(--shadow)}
.seg button[aria-pressed="true"] .n{background:var(--accent);color:#fff}
.tpl-tip{
  position:absolute;top:calc(100% + 9px);left:50%;z-index:50;width:340px;max-width:calc(100vw - 40px);
  padding:10px 12px;border:1px solid var(--border-strong);border-radius:9px;background:var(--surface);
  box-shadow:var(--shadow-lg);color:var(--text-2);font-size:12px;font-weight:400;line-height:1.45;
  text-align:left;white-space:normal;pointer-events:none;visibility:hidden;opacity:0;
  transform:translate(-50%,-3px);transition:opacity .12s,transform .12s,visibility .12s
}
.tpl-tip b{color:var(--text);font-weight:650}
.tpl-tip::before{
  content:"";position:absolute;top:-5px;left:50%;width:9px;height:9px;background:var(--surface);
  border-left:1px solid var(--border-strong);border-top:1px solid var(--border-strong);transform:translateX(-50%) rotate(45deg)
}
.seg button[data-tpl="1"] .tpl-tip{left:0;transform:translateY(-3px)}
.seg button[data-tpl="1"] .tpl-tip::before{left:25px}
.seg button[data-tpl="3"] .tpl-tip{left:auto;right:0;transform:translateY(-3px)}
.seg button[data-tpl="3"] .tpl-tip::before{left:auto;right:25px;transform:rotate(45deg)}
.seg button:hover .tpl-tip,.seg button:focus-visible .tpl-tip{visibility:visible;opacity:1}
.seg button[data-tpl="2"]:hover .tpl-tip,.seg button[data-tpl="2"]:focus-visible .tpl-tip{transform:translate(-50%,0)}
.seg button[data-tpl="1"]:hover .tpl-tip,.seg button[data-tpl="1"]:focus-visible .tpl-tip,
.seg button[data-tpl="3"]:hover .tpl-tip,.seg button[data-tpl="3"]:focus-visible .tpl-tip{transform:translateY(0)}
.ctx-row{display:flex;align-items:center;gap:16px;flex-wrap:wrap}
.pill{
  display:inline-flex;align-items:center;gap:6px;font-size:11.5px;font-weight:500;
  padding:4px 9px;border-radius:20px;border:1px solid var(--border);background:var(--surface);color:var(--text-2)
}
.pill.new{background:var(--accent-soft);border-color:transparent;color:var(--accent)}

/* example trace */
.trace{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:11px}
.trace .q{
  font-family:var(--mono);font-size:11.5px;color:var(--text-2);background:var(--surface);
  border:1px solid var(--border);border-radius:7px;padding:5px 9px
}
.trace .lbl{font-size:11px;color:var(--text-3);text-transform:uppercase;letter-spacing:.06em;font-weight:600}
.facet{
  border:1px solid var(--border);background:var(--surface);border-radius:20px;
  padding:4px 10px;font-size:11.5px;color:var(--text-2)
}
.facet:hover{border-color:var(--border-strong);color:var(--text)}
.facet[aria-pressed="true"]{background:var(--accent);border-color:var(--accent);color:#fff}

/* ---------- layout ---------- */
.app{display:grid;grid-template-columns:288px minmax(0,1fr);gap:0;align-items:start}
.side{
  position:sticky;top:53px;max-height:calc(100vh - 53px);overflow-y:auto;
  border-right:1px solid var(--border);background:var(--surface);padding:16px 14px 60px
}
.stage-area{padding:26px 36px 120px 20px;min-width:0}

/* ---------- sidebar panels ---------- */
.panel{margin-bottom:18px}
.panel > h3,.legend-panel > summary{
  font-size:11px;text-transform:uppercase;letter-spacing:.07em;color:var(--text-3);
  margin-bottom:9px;display:flex;align-items:center;justify-content:space-between
}
.route-target:focus{outline:2px solid var(--accent);outline-offset:3px;border-radius:3px}
.legend-panel > summary{
  list-style:none;cursor:pointer;margin-bottom:0
}
.legend-panel > summary::-webkit-details-marker{display:none}
.legend-panel > summary::after{
  content:"▸";font-size:10px;color:var(--text-3);transition:transform .15s
}
.legend-panel[open] > summary{margin-bottom:9px}
.legend-panel[open] > summary::after{transform:rotate(90deg)}
.legend-panel > summary:focus-visible{
  outline:2px solid var(--accent);outline-offset:3px;border-radius:3px
}
.metric{margin-bottom:13px}
.metric .top{display:flex;align-items:baseline;justify-content:space-between;gap:8px;margin-bottom:5px}
.metric .name{font-size:12px;color:var(--text-2);font-weight:500}
.metric .val{font-size:13px;font-weight:650;font-variant-numeric:tabular-nums}
.bar{height:7px;border-radius:4px;background:var(--surface-3);overflow:hidden;display:flex}
.bar i{display:block;height:100%}
.bar i.cx{background:linear-gradient(90deg,var(--rec-line),var(--warn))}
.metric .note{font-size:11px;color:var(--text-3);margin-top:4px}
.legendrow{display:flex;flex-wrap:wrap;gap:5px 10px;margin-top:6px}
.legendrow span,.legendrow button{font-size:10.5px;color:var(--text-3);display:inline-flex;align-items:center;gap:4px}
.legendrow button{border:0;background:none;padding:2px 4px;border-radius:5px;margin:-2px -4px}
.legendrow button:hover{background:var(--surface-2);color:var(--text)}
.legendrow button[aria-pressed="true"]{background:var(--accent-soft);color:var(--accent)}
.legendrow i{width:8px;height:8px;border-radius:2px;display:inline-block}
.legendrow i.data-key{width:10px;border:1px solid var(--data-line);border-radius:50% / 24%;background:var(--data-bg)}
.legend-label{font-size:9px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;color:var(--text-3);margin-top:8px}
.gate-legend{display:grid;gap:5px;margin-top:6px}
.gate-legend button{
  display:grid;grid-template-columns:1fr auto;gap:5px 7px;align-items:center;width:100%;
  text-align:left;border:1px solid var(--border);background:var(--surface);
  border-radius:8px;padding:6px 8px
}
.gate-legend button:hover{border-color:var(--accent)}
.gate-legend button[aria-pressed="true"]{border-color:var(--accent);background:var(--accent-soft)}
.gate-legend .gk-chip{
  justify-self:start;font-size:9px;font-weight:700;letter-spacing:.03em;text-transform:uppercase;
  border:1px solid var(--gate-color);color:var(--gate-color);background:var(--surface);
  border-radius:20px;padding:1px 6px
}
.gate-legend button[data-gate-scope="deployment"] .gk-chip{border-style:dashed;font-weight:650}
.gate-legend .gk-count{
  font-size:9.5px;font-weight:700;color:var(--text-3);font-variant-numeric:tabular-nums
}
.gate-legend .gk-desc{grid-column:1/-1;font-size:10.5px;line-height:1.4;color:var(--text-3)}
.relation-legend{display:grid;grid-template-columns:1fr;gap:5px;margin-top:5px}
.relation-legend span{gap:7px;color:var(--text-2)}
.relation-legend .support-wiring-note{
  display:block;padding-top:3px;border-top:1px solid var(--border);color:var(--text-3);
  font-size:10px;line-height:1.4
}
.relation-key{width:44px;height:10px;flex:none;overflow:visible}

.focusbox{
  border:1px solid var(--accent);background:var(--accent-soft);border-radius:10px;padding:11px 12px
}
.focusbox h3{color:var(--accent);margin-bottom:6px}
.focusbox .fclear{
  border:0;background:none;color:var(--accent);font-size:10.5px;font-weight:700;
  text-transform:uppercase;letter-spacing:.05em;padding:0
}
.focusbox .fclear:hover{text-decoration:underline}
.focusbox .fdesc{font-size:11.5px;color:var(--text-2);margin:0 0 9px;line-height:1.45}
.focusbox .fdesc b{color:var(--text)}
.focusbox .ref{background:var(--surface);font-size:11px}
.focusbox .ref.isoff{opacity:.5;font-style:italic}
.focusbox .fnone{font-size:11.5px;color:var(--text-2);font-style:italic}
.complist details{border-top:1px solid var(--border)}
.complist details:last-of-type{border-bottom:1px solid var(--border)}
.complist summary{
  list-style:none;cursor:pointer;padding:8px 2px;font-size:11.5px;font-weight:600;
  color:var(--text-2);display:flex;align-items:center;gap:7px
}
.complist summary::-webkit-details-marker{display:none}
.complist summary::before{content:"▸";font-size:9px;color:var(--text-3);transition:transform .15s}
.complist details[open] summary::before{transform:rotate(90deg)}
.complist summary .count{margin-left:auto;font-size:10.5px;color:var(--text-3);font-weight:500}
.tog{
  display:flex;align-items:center;gap:8px;padding:5px 2px 5px 18px;font-size:12px;color:var(--text-2);
  width:100%;border:0;background:none;text-align:left;border-radius:6px
}
.tog:hover{background:var(--surface-2);color:var(--text)}
.tog .sw{
  width:26px;height:15px;border-radius:20px;background:var(--surface-3);position:relative;flex:none;
  transition:background .15s
}
.tog .sw::after{
  content:"";position:absolute;top:2px;left:2px;width:11px;height:11px;border-radius:50%;
  background:var(--surface);box-shadow:0 1px 2px rgba(0,0,0,.3);transition:transform .15s
}
.tog[data-on="1"] .sw{background:var(--ok)}
.tog[data-on="1"] .sw::after{transform:translateX(11px)}
.tog[data-locked="1"]{opacity:.55;cursor:not-allowed}
.tog[data-locked="1"]:hover{background:none}
.tog .nm{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.tog .tier{width:6px;height:6px;border-radius:50%;flex:none}
.btn-ghost{
  border:1px solid var(--border);background:var(--surface);border-radius:8px;
  padding:7px 10px;font-size:12px;font-weight:500;width:100%;color:var(--text-2)
}
.btn-ghost:hover{background:var(--surface-2);color:var(--text)}
.dep-toggle{
  display:inline-flex;align-items:center;gap:8px;padding:7px 10px;
  border:1px solid var(--border);border-radius:9px;background:var(--surface);color:var(--text);
  font-size:11.5px;font-weight:600;white-space:nowrap
}
.dep-toggle:hover{border-color:var(--border-strong);background:var(--surface-2)}
.dep-toggle:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.dep-toggle .dep-sw{
  width:30px;height:18px;border-radius:20px;background:var(--surface-3);
  position:relative;flex:none;transition:background .15s
}
.dep-toggle .dep-sw::after{
  content:"";position:absolute;top:3px;left:3px;width:12px;height:12px;border-radius:50%;
  background:var(--surface);box-shadow:0 1px 2px rgba(0,0,0,.28);transition:transform .15s
}
.dep-toggle[aria-pressed="true"]{border-color:var(--rec-line);background:var(--rec-bg);color:var(--rec-text)}
.dep-toggle[aria-pressed="true"] .dep-sw{background:var(--ok)}
.dep-toggle[aria-pressed="true"] .dep-sw::after{transform:translateX(12px)}

/* ---------- canvas ---------- */
.canvas{--left-spine-gap:154px;position:relative;padding-left:118px}
.wires{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;overflow:visible;z-index:0}
/* Wires are drawn under the rows, so they pass behind the cards instead of
   painting over them — which also means a row box swallows every pointer
   event before it can reach the wire underneath. Only the cards themselves
   need to be pointable; the grid around them steps out of the way. */
.row,.row .cell,.data-source-column{pointer-events:none}
.row .node,.row .data-source-node,.row button{pointer-events:auto}
/* A 1.4px stroke is a hard thing to point at, so every wire is drawn twice:
   once visibly, and once as an invisible companion wide enough to hover. */
.wires .wire-hit{fill:none;stroke:transparent;stroke-width:13;pointer-events:stroke;cursor:default}
.row{
  position:relative;display:grid;container-type:inline-size;
  grid-template-columns:minmax(0,128px) minmax(0,1fr) minmax(0,176px);
  gap:12px;align-items:center;margin-bottom:34px;z-index:1
}
/* A dashed stage boundary is drawn 28px outside its members and hangs its
   title and note pills 12px further out again, so the standard row rhythm
   leaves it touching the rows above and below. The rows on either side of a
   boundary give it the clearance instead — carried on one margin so it never
   collapses against its neighbour's. */
.row.stage-group-clearance{margin-bottom:60px}
.row .cell{display:flex;gap:11px;flex-wrap:wrap;min-width:0}
.row .cell.center{justify-content:center;column-gap:17px;row-gap:14px}
.row .cell.center > .node{flex:1 1 154px}
.row.parallel-row .cell.center{
  box-sizing:border-box;padding:16px 88px 16px 20px
}
/* A parallel band is wider than a spine node, and a left aside is placed
   against a spine node's edge — so on a row that has both, the band runs in
   under the aside. Capping the band's width is what resolves it, because the
   aside's column is the fixed thing: every other aside in the canvas sits on
   it, and moving this one row's aside out of line to clear the band trades a
   collision for a jog.

   486px is the width at which the band's boundary box clears the aside by
   34px. That clearance is the same at every canvas width and in both plane
   states, because the aside and the band are both placed from the centre of
   the same track: widening the canvas moves the two by the same half-pixel.
   The band's members give up the difference — two 250px cards become two
   180px ones — which is the right thing to spend, since a band member is
   read as one of a set and a spine node is read on its own.

   No logical row has both, so this selector never matches there. */
.row.parallel-row:has(.cell.left .node) .cell.center{
  justify-self:center;width:100%;max-width:486px
}
.row .cell.left{
  justify-content:flex-end;
  transform:translateX(max(-80px,calc(50cqw - 277px - var(--left-spine-gap))))
}
.row .cell.left > .node{width:250px;min-width:250px;max-width:250px}
/* An aside whose own members are wired to each other stacks them 11px apart,
   which is narrower than the label the wire between them carries — so every
   "on a miss" landed on a card rather than in the gap. The gap has to clear a
   label and its own clearance, and only the asides carrying a wire pay for it. */
.row .cell.wired-stack{row-gap:38px}
.row .cell.right{justify-content:flex-start}
.canvas.with-data-sources .row{
  grid-template-columns:minmax(0,206px) minmax(0,154px) 80px minmax(0,1fr) minmax(0,176px);
  width:calc(100% + 118px);margin-left:-118px
}
.canvas.with-data-sources .cell.data{grid-column:1;align-self:stretch;justify-content:flex-start}
/* An aside is 250px wide in a 154px track, so it overhangs by 96px into the
   canvas margin — and the data column is that margin. The row that had both
   used to give the overhang up and drop back into its own track, which fixed
   the collision and broke the column: the same card sat at one x on a row
   with a store and another x on the row below it, so showing the stores
   appeared to move the encoders. The pull is unconditional again, with a
   floor instead: 96px is where the aside's left edge meets the gap after the
   data column, the point past which pulling it towards the spine would start
   covering something. */
.canvas.with-data-sources .cell.left{
  grid-column:2;
  transform:translateX(max(96px,calc(50cqw - 353px - var(--left-spine-gap))))
}
.canvas.with-data-sources .cell.center{grid-column:4}
.canvas.with-data-sources .cell.right{grid-column:5}
.canvas.with-data-sources .cell:empty{display:none}

/* ---------- node ---------- */
.node{
  display:flex;flex-direction:column;align-items:stretch;
  position:relative;border-radius:var(--radius);border:1px solid var(--border);
  background:var(--surface);padding:9px 12px;min-width:154px;max-width:250px;text-align:left;
  box-shadow:var(--shadow);transition:transform .12s,box-shadow .12s,opacity .18s,filter .18s
}
.node:hover{transform:translateY(-1px);box-shadow:0 3px 6px rgba(16,23,37,.10),0 10px 22px rgba(16,23,37,.10)}
.node:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.node .nm{font-size:12.5px;font-weight:600;line-height:1.3}
.node .sb{font-size:10.5px;color:var(--text-3);margin-top:3px;line-height:1.35}
.node .meta{display:flex;gap:6px;align-items:center;flex-wrap:wrap;margin-top:7px}
.node .condchip{
  font-size:9px;font-weight:700;letter-spacing:.03em;text-transform:uppercase;
  border:1px solid var(--warn);color:var(--warn);border-radius:20px;padding:1px 6px
}
.node .gatechip{
  font-size:9px;font-weight:700;letter-spacing:.03em;text-transform:uppercase;
  border:1px solid var(--gate-color,var(--gate-request));color:var(--gate-color,var(--gate-request));
  background:var(--surface);border-radius:20px;padding:1px 6px
}
/* A deployment gate is standing configuration, not a per-query decision.
   Muted and dashed so the two kinds separate before the label is read. */
.node[data-gate-scope="deployment"] .gatechip{border-style:dashed;font-weight:650}
.node.core{background:var(--core-bg);border-color:var(--core-line);color:var(--core-text)}
.node.core .sb{color:var(--core-text);opacity:.72}
.node.recommended{background:var(--rec-bg);border-color:var(--rec-line);color:var(--rec-text)}
.node.recommended .sb{color:var(--rec-text);opacity:.72}
.node.optional{background:var(--opt-bg);border-color:var(--opt-line);color:var(--opt-text)}
.node.optional .sb{color:var(--opt-text);opacity:.72}
.node.control{background:var(--ctrl-bg);border-color:var(--ctrl-line);border-style:dashed;color:var(--ctrl-text);min-width:150px;max-width:200px}
.node.control .sb{color:var(--ctrl-text);opacity:.72}
.node.gated{box-shadow:inset 4px 0 var(--gate-color,var(--gate-request)),var(--shadow)}
.node.gated:hover{box-shadow:inset 4px 0 var(--gate-color,var(--gate-request)),0 3px 6px rgba(16,23,37,.10),0 10px 22px rgba(16,23,37,.10)}
.node.decision{border-radius:22px}
.node.io{min-width:132px;text-align:left}
.node.io .nm{font-size:12px}
.node.selected{outline:2px solid var(--accent);outline-offset:2px}
.node.off{opacity:.32;filter:grayscale(.85)}
.node.dimmed{opacity:.22}
.node.hl{outline:2px solid var(--warn);outline-offset:2px}
.node.hover-connected:not(.off){
  opacity:.88;transform:translateY(-1px);
  box-shadow:0 0 0 2px var(--accent-soft),0 5px 14px rgba(16,23,37,.10)
}
.node.gated.hover-connected:not(.off){box-shadow:inset 4px 0 var(--gate-color,var(--gate-request)),0 0 0 2px var(--accent-soft),0 5px 14px rgba(16,23,37,.10)}
.wires path.hover-connected{stroke-width:2.2!important;opacity:1!important}
/* Hovering the wire itself, rather than a card at one end of it: the wire is
   the thing being pointed at, so it is emphasised harder than a wire merely
   connected to the card under the pointer, and its label is emphasised with it. */
.wires path.hover-wire{stroke-width:3.2!important;opacity:1!important}
.elabel.hover-wire{color:var(--line-label-color,var(--text-2));font-weight:700;box-shadow:0 0 0 1px currentColor}
.node[data-id="assembly"]{text-align:left}

/* ---------- narrow-screen dependency representation ---------- */
.mobile-dependency-intro,.mobile-transition,.mobile-recovery,
.mobile-stage-marker,.mobile-selection,.mobile-dep-chips{display:none}
.mobile-connected:not(.off){outline:2px solid var(--accent-soft);outline-offset:2px}

/* ---------- serving dependencies ---------- */
.data-source-column{
  display:flex;flex-direction:column;justify-content:center;gap:9px;width:206px;max-width:100%;min-width:0
}
/* The write path draws wires between stores stacked in this column, and their
   labels have nowhere to go but the gaps between the cards. Nine pixels is
   narrower than a label, so every one of them landed on a card border. Only
   the column that carries the write path pays for the extra room. */
.data-source-column:has(.write-path){gap:28px}
.data-source-node{
  --source-line:var(--data-line);
  position:relative;display:flex;flex-direction:column;align-items:stretch;
  width:100%;min-width:0;padding:17px 12px 12px;
  border:1px solid var(--source-line);border-radius:50% / 13px;
  background:var(--surface-2);color:var(--data-text);text-align:left;box-shadow:var(--shadow);
  transition:transform .12s,box-shadow .12s,opacity .18s,filter .18s
}
.data-source-node::before{
  content:"";position:absolute;left:0;right:0;top:7px;height:11px;
  border-bottom:1px solid var(--source-line);border-radius:50%;pointer-events:none;opacity:.72
}
.data-source-node:hover{transform:translateY(-1px);box-shadow:0 3px 6px rgba(16,23,37,.10),0 10px 22px rgba(16,23,37,.10)}
.data-source-node:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.data-source-node .nm{font-size:11.5px;font-weight:600;line-height:1.3}
.data-source-node .sb{font-size:9.5px;line-height:1.35;color:var(--text-3);margin-top:3px}
.data-source-node .meta{display:flex;gap:4px;align-items:center;flex-wrap:wrap;margin-top:7px}
.data-plane-chip{
  font-size:9px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;
  padding:1px 5px;border-radius:20px;border:1px solid currentColor;opacity:.72
}
.source-serves{font-size:9.5px;line-height:1.35;margin-top:7px;color:var(--data-line)}
.source-serves b{font-weight:700;text-transform:uppercase;letter-spacing:.04em}
.data-source-node.selected{outline:2px solid var(--accent);outline-offset:2px}
.data-source-node.off{opacity:.32;filter:grayscale(.85)}
.data-source-node.dimmed{opacity:.22}
.data-source-node.hl{outline:2px solid var(--warn);outline-offset:2px}
.data-source-node.hover-connected{
  opacity:.9;transform:translateY(-1px);
  box-shadow:0 0 0 2px var(--accent-soft),0 5px 14px rgba(16,23,37,.10)
}
.tierchip{
  font-size:9px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;
  padding:1px 6px;border-radius:20px;border:1px solid currentColor;opacity:.75
}
.tierchip.core{color:var(--core-line)}
.tierchip.recommended{color:var(--rec-line)}
.tierchip.optional{color:var(--opt-line)}
.node.control .tierchip{color:var(--ctrl-line);opacity:.9}
.groupchip{
  font-size:9px;font-weight:650;letter-spacing:.04em;text-transform:uppercase;
  padding:1px 6px;border-radius:20px;border:1px solid currentColor;
  color:var(--text-3);opacity:.68
}
/* transform only: animating opacity here would win the cascade over
   .dimmed / .off and stop focus dimming from working on new nodes */
@keyframes pop{0%{transform:scale(.92)}60%{transform:scale(1.04)}100%{transform:scale(1)}}
.node.isnew{animation:pop .38s ease-out}
.node .offmark,.data-source-node .offmark{position:absolute;inset:0;pointer-events:none}
.node .offmark{border-radius:var(--radius)}
.data-source-node .offmark{border-radius:50% / 13px}
.node[data-on="0"] .offmark,.data-source-node[data-on="0"] .offmark{
  background:repeating-linear-gradient(45deg,transparent 0 6px,rgba(125,135,152,.16) 6px 12px)
}
.elabel{
  position:absolute;z-index:2;transform:translate(-50%,-50%);
  font-size:10px;font-weight:600;color:var(--line-label-color,var(--text-3));background:var(--bg);
  padding:1px 6px;border-radius:5px;white-space:nowrap;pointer-events:none
}
.elabel.hover-only{visibility:hidden;opacity:0}
.elabel.hover-only.hover-wire{visibility:visible;opacity:1}
.stage-boundary{
  position:absolute;z-index:0;border:1px dashed var(--wire-gate);border-radius:18px;
  pointer-events:none;box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--wire-gate) 9%,transparent)
}
.stage-boundary .boundary-title,.stage-boundary .boundary-note{
  position:absolute;left:14px;background:var(--surface);border:1px solid var(--wire-gate);
  color:var(--wire-gate);border-radius:20px;padding:2px 8px;white-space:nowrap
}
.stage-boundary .boundary-title{
  top:-12px;font-size:9px;font-weight:750;letter-spacing:.045em;text-transform:uppercase
}
.stage-boundary .boundary-note{bottom:-12px;font-size:9px;color:var(--text-2);border-color:var(--border)}

/* ---------- hover preview ---------- */
.hovercard{
  position:fixed;z-index:80;width:390px;max-width:calc(100vw - 24px);
  background:var(--surface);background:color-mix(in srgb,var(--surface) 72%,transparent);
  backdrop-filter:blur(5px) saturate(1.4);-webkit-backdrop-filter:blur(5px) saturate(1.4);
  border:1px solid var(--border-strong);border-radius:11px;
  box-shadow:var(--shadow-lg);padding:12px 13px;pointer-events:none;
  max-height:calc(100vh - 16px);overflow:hidden
}
.entity-summary .hc-title{
  display:flex;align-items:center;gap:7px;flex-wrap:wrap;
  font-size:13px;font-weight:700;line-height:1.3;color:var(--text);margin-bottom:7px
}
.entity-summary .hc-context{
  font-size:9.5px;font-weight:650;letter-spacing:.05em;text-transform:uppercase;
  color:var(--accent);background:var(--accent-soft);border:1px solid transparent;
  border-radius:6px;padding:2px 7px;white-space:nowrap
}
.entity-summary .hc-top{display:flex;align-items:center;gap:5px;flex-wrap:wrap;margin-bottom:9px}
.entity-summary .hc-pill{
  font-size:9.5px;font-weight:650;letter-spacing:.05em;text-transform:uppercase;
  color:var(--text-2);background:var(--surface-2);
  border:1px solid var(--border);border-radius:6px;padding:2px 7px;white-space:nowrap
}
.entity-summary .hc-capabilities{
  display:flex;align-items:center;gap:5px;flex-wrap:wrap;margin:-2px 0 9px
}
.entity-summary .hc-cap-label{
  font-size:9px;font-weight:700;letter-spacing:.065em;text-transform:uppercase;color:var(--text-3)
}
.entity-summary .hc-tag{
  appearance:none;font:inherit;font-size:9.5px;font-weight:600;line-height:1.2;
  color:var(--text-2);background:var(--surface-2);border:1px solid var(--border);
  border-radius:999px;padding:2px 7px
}
.drawer-summary .hc-tag{cursor:pointer}
.drawer-summary .hc-tag:hover{border-color:var(--accent);color:var(--accent)}
.drawer-summary .hc-tag[aria-pressed="true"]{border-color:var(--accent);background:var(--accent-soft);color:var(--accent)}
.drawer-summary .hc-tag:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.entity-summary .hc-group{color:var(--text-3)}
.entity-summary .hc-gate{
  margin:0 0 8px;font-size:11.5px;line-height:1.45;color:var(--text-2);
  border-left:3px solid var(--gate-color,var(--gate-request));padding-left:8px
}
.entity-summary .hc-gate b{
  font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--text)
}
.entity-summary .hc-condline{border-left-color:var(--warn)}
.entity-summary .hc-desc{margin:0;font-size:12px;line-height:1.5;color:var(--text)}
.entity-summary .hc-block,.entity-summary .hc-notes,.entity-summary .hc-rels{
  margin-top:10px;padding-top:9px;border-top:1px solid var(--border);
  font-size:11.5px;line-height:1.5;color:var(--text-2)
}
.entity-summary .hc-block p{margin:0}
.entity-summary .hc-comparison ul{list-style:none;margin:0;padding:0}
.entity-summary .hc-comparison li+li{margin-top:5px}
.entity-summary .hc-comparison b{font-weight:650;color:var(--text)}
.entity-summary .hc-rel+.hc-rel{margin-top:7px}
.entity-summary .hc-more{color:var(--text-3);font-style:italic}
.entity-summary .hc-notes ul{list-style:none;margin:0;padding:0}
.entity-summary .hc-notes li{margin-top:7px}
.entity-summary .hc-notes li:first-child{margin-top:0}
.entity-summary .hc-lb{
  display:block;font-size:9.5px;font-weight:700;letter-spacing:.07em;text-transform:uppercase;
  color:var(--text-3);margin-bottom:4px
}
.entity-summary .hc-ref{
  appearance:none;border:0;background:none;padding:0;color:inherit;font:inherit;text-align:left
}
.drawer-summary .hc-ref{cursor:pointer}
.drawer-summary .hc-ref:hover{text-decoration:underline;color:var(--accent)}
.drawer-summary .hc-ref:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:2px}
.drawer-summary .hc-ref[data-cross]{
  display:inline-flex;align-items:center;min-height:28px;margin:-5px -4px;padding:4px;
  color:var(--accent);font-weight:650;text-decoration:underline;text-underline-offset:2px
}
.drawer-summary .hc-ref[data-cross]::after{content:"\2192";margin-left:4px;text-decoration:none}
.entity-summary code{
  font-family:var(--mono);font-size:10.5px;background:var(--surface-2);border:1px solid var(--border);
  border-radius:4px;padding:1px 4px;color:var(--text)
}
@media (max-width:700px){ .hovercard{display:none} }

/* ---------- drawer ---------- */
.scrim{position:fixed;inset:0;background:rgba(8,12,20,.35);z-index:60;opacity:0;pointer-events:none;transition:opacity .2s}
.scrim.open{opacity:1;pointer-events:auto}
.drawer{
  position:fixed;top:0;right:0;height:100dvh;width:min(440px,100vw);background:var(--surface);
  border-left:1px solid var(--border);box-shadow:var(--shadow-lg);z-index:70;
  transform:translateX(100%);transition:transform .24s cubic-bezier(.32,.72,0,1);
  display:block;overflow-y:auto;overscroll-behavior:contain
}
.drawer.open{transform:none}
.drawer .dh{padding:16px 18px 13px;border-bottom:1px solid var(--border)}
.drawer .db{padding:16px 18px 60px;overflow:visible}
.drawer .close{position:absolute;top:12px;right:14px;border:0;background:none;font-size:19px;color:var(--text-3);line-height:1;padding:4px}
.drawer .close:hover{color:var(--text)}
.drawer-summary{padding-right:26px}
.drawer-utility{
  display:flex;gap:6px;align-items:center;flex-wrap:wrap;
  margin-top:12px;padding-top:10px;border-top:1px solid var(--border)
}
.chip{
  font-size:11px;border:1px solid var(--border);border-radius:7px;padding:4px 8px;
  color:var(--text-2);background:var(--surface-2);display:inline-flex;gap:5px;align-items:center
}
.chip b{font-variant-numeric:tabular-nums;color:var(--text)}
.enable-btn{
  margin-left:auto;border:1px solid var(--border);background:var(--surface);border-radius:7px;
  padding:5px 10px;font-size:11.5px;font-weight:600;color:var(--text-2)
}
.enable-btn[data-on="1"]{border-color:var(--ok);color:var(--ok)}
.sect{margin-top:20px}
.sect > h4{
  font-size:10.5px;text-transform:uppercase;letter-spacing:.07em;color:var(--text-3);
  margin-bottom:9px;padding-bottom:6px;border-bottom:1px solid var(--border)
}
.drawer-more{margin-top:22px;border-top:1px solid var(--border)}
.drawer-more > summary{
  cursor:pointer;list-style:none;padding:12px 2px 3px;font-size:11px;font-weight:700;
  letter-spacing:.055em;text-transform:uppercase;color:var(--text-2)
}
.drawer-more > summary::-webkit-details-marker{display:none}
.drawer-more > summary::before{
  content:"▸";display:inline-block;margin-right:7px;color:var(--text-3);transition:transform .15s
}
.drawer-more[open] > summary::before{transform:rotate(90deg)}
.drawer-more > summary:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:3px}
.drawer-more-body{padding-top:1px}
.drawer-more-body > .sect:first-child{margin-top:15px}
.dec{border:1px solid var(--border);border-radius:9px;padding:11px 12px;margin-bottom:9px;background:var(--surface-2)}
.dec .q{font-size:12.5px;font-weight:600;margin-bottom:7px}
.dec ul{margin:0 0 8px;padding-left:16px}
.dec li{font-size:12px;color:var(--text-2);margin-bottom:3px}
.dec .def{font-size:12px;color:var(--text);background:var(--surface);border-left:2px solid var(--accent);padding:6px 9px;border-radius:0 6px 6px 0}
.dec .def b{color:var(--accent)}
.iobox{font-family:var(--mono);font-size:11px;background:var(--surface-2);border:1px solid var(--border);border-radius:8px;padding:10px 11px;white-space:pre-wrap;color:var(--text-2);overflow-x:auto}
.iobox .k{color:var(--text-3)}
table.mini{width:100%;border-collapse:collapse;font-size:11.5px}
table.mini th{
  text-align:left;font-size:10px;text-transform:uppercase;letter-spacing:.05em;color:var(--text-3);
  font-weight:600;padding:0 8px 6px 0;border-bottom:1px solid var(--border)
}
table.mini td{padding:7px 8px 7px 0;border-bottom:1px solid var(--border);color:var(--text-2);vertical-align:top}
table.mini td:first-child{color:var(--text);font-weight:500;width:34%}
table.mini .met{color:var(--accent)}
.dial{display:flex;justify-content:space-between;gap:12px;padding:7px 0;border-bottom:1px solid var(--border);font-size:12px}
.dial .dn{color:var(--text);font-weight:500}
.dial .dv{font-family:var(--mono);font-size:11px;color:var(--accent);white-space:nowrap}
/* A budget or a substrate is a sentence, not a setting; it needs to wrap. */
.dial.wide{align-items:flex-start}
.dial.wide .dv{font-family:inherit;font-size:12px;color:var(--text-2);white-space:normal;text-align:right}
.dial .dnote{font-size:11px;color:var(--text-3);flex-basis:100%;margin-top:2px}
.notes{list-style:none;margin:0;padding:0}
.notes .note{
  font-size:12px;color:var(--text);background:var(--surface);
  border-left:2px solid var(--accent);border-radius:0 6px 6px 0;padding:6px 9px;margin-top:9px
}
.notes .note:first-child{margin-top:0}
.notes .note b{color:var(--accent)}
.exline{font-size:12px;color:var(--text-2);margin-top:8px}
.exline code{font-family:var(--mono);font-size:11px;background:var(--surface-2);border:1px solid var(--border);border-radius:4px;padding:1px 5px;color:var(--text)}
.reflink{
  display:block;border:1px solid var(--border);border-radius:9px;padding:9px 11px;margin-bottom:7px;
  text-decoration:none;background:var(--surface-2);transition:border-color .12s,background .12s
}
.reflink:hover{border-color:var(--accent);background:var(--accent-soft)}
.reflink .rt{display:block;font-size:12.5px;font-weight:600;color:var(--text);line-height:1.35}
.reflink .rt::after{content:" ↗";font-size:10px;color:var(--text-3);font-weight:400}
.reflink .rs{display:block;font-size:11px;color:var(--text-3);margin-top:2px}
.reflink .rw{display:block;font-size:11.5px;color:var(--text-2);margin-top:5px;line-height:1.45}
.reflist{display:flex;flex-wrap:wrap;gap:6px}
.ref{font-size:11px;border:1px solid var(--border);background:var(--surface-2);border-radius:6px;padding:4px 8px;color:var(--text-2)}
.ref:hover{border-color:var(--accent);color:var(--accent)}
.ref.isoff{opacity:.55;font-style:italic}
.refdetail{display:block;margin-top:2px;font-size:9.5px;font-weight:500;color:var(--text-3)}
.relnote{font-size:11.5px;color:var(--text-3);margin:0 0 8px;line-height:1.45}
.reldep{
  font-size:11.5px;color:var(--text-2);background:var(--warn-bg);border-left:3px solid var(--warn);
  border-radius:0 7px 7px 0;padding:8px 10px;margin:9px 0 0;line-height:1.45
}

/* ---------- export modal ----------
   The measured ladder above it: sticky header 40, context bar 35, level tooltip
   50, drawer scrim 60, drawer 70, hover card 80. The export sits on top of all
   of them, because it is the only surface a reader opens *over* a diagram they
   are still hovering. */
.export-scrim{z-index:90}
.export-modal{
  position:fixed;top:50%;left:50%;transform:translate(-50%,-50%);z-index:100;
  width:min(880px,94vw);height:min(760px,88dvh);background:var(--surface);
  border:1px solid var(--border);border-radius:14px;box-shadow:var(--shadow-lg);
  display:flex;flex-direction:column;overflow:hidden
}
.export-modal[hidden]{display:none}
.export-modal:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.ex-head{position:relative;padding:16px 18px 0;border-bottom:1px solid var(--border)}
.ex-head h2{font-size:17px;padding-right:26px}
.ex-head .close{position:absolute;top:12px;right:14px;border:0;background:none;font-size:19px;color:var(--text-3);line-height:1;padding:4px}
.ex-head .close:hover{color:var(--text)}
.ex-sub{font-size:12px;color:var(--text-3);margin-top:3px}
.ex-tabs{display:flex;gap:2px;margin-top:12px}
.ex-tabs button{
  border:0;border-bottom:2px solid transparent;background:none;padding:8px 14px;
  font-size:13px;font-weight:500;color:var(--text-2)
}
.ex-tabs button[aria-selected="true"]{color:var(--accent);border-bottom-color:var(--accent)}
.ex-opts{
  display:flex;gap:16px;align-items:center;flex-wrap:wrap;
  padding:11px 18px;border-bottom:1px solid var(--border);background:var(--surface-2)
}
.ex-opts label{display:inline-flex;gap:7px;align-items:center;font-size:12px;color:var(--text-2)}
/* Disabled, never hidden: a control that vanishes reads as a bug. */
.ex-opts label:has(input:disabled),.ex-dir:has(button:disabled){opacity:.45}
.ex-dir{margin-left:auto}
.ex-dir button{padding:5px 11px;font-size:12px}
.ex-code{
  flex:1;overflow:auto;margin:0;padding:14px 18px;background:var(--bg);
  font-family:var(--mono);font-size:11.5px;line-height:1.55;color:var(--text-2);
  white-space:pre;tab-size:2
}
.ex-foot{
  display:flex;gap:10px;align-items:center;padding:12px 18px;
  border-top:1px solid var(--border);background:var(--surface)
}
.ex-size,.ex-note{font-size:11.5px;color:var(--text-3);font-variant-numeric:tabular-nums}
/* The buttons hold the right edge whether or not the `file:` note is showing. */
.ex-foot button:first-of-type{margin-left:auto}
.ex-foot .btn-ghost{width:auto;padding:8px 16px}
.ex-primary{border-color:var(--accent);color:var(--accent);font-weight:600}
.ex-primary:hover{background:var(--accent-soft);color:var(--accent)}

/* ---------- build order ---------- */
.build{max-width:1000px;margin:0 auto;padding:28px 20px 120px}
.build-intro{font-size:13px;color:var(--text-2);max-width:70ch;margin-bottom:22px}
.step{
  display:grid;grid-template-columns:44px minmax(0,1fr);gap:16px;
  padding:16px 0;border-top:1px solid var(--border)
}
.step .num{
  width:34px;height:34px;border-radius:9px;display:grid;place-items:center;font-weight:700;font-size:13px;
  background:var(--surface-2);color:var(--text-2);border:1px solid var(--border)
}
.step[data-t="1"] .num{background:var(--core-bg);border-color:var(--core-line);color:var(--core-text)}
.step[data-t="2"] .num{background:var(--rec-bg);border-color:var(--rec-line);color:var(--rec-text)}
.step[data-t="3"] .num{background:var(--opt-bg);border-color:var(--opt-line);color:var(--opt-text)}
.step h4{font-size:14px;margin-bottom:6px}
.step .grid{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-top:8px}
.step .grid > div{font-size:12px;color:var(--text-2)}
.step .grid .lb{font-size:9.5px;text-transform:uppercase;letter-spacing:.06em;color:var(--text-3);font-weight:700;margin-bottom:3px}
.step .chips{display:flex;flex-wrap:wrap;gap:5px;margin-top:9px}
.divider{
  margin:22px 0;padding:11px 14px;border-radius:9px;background:var(--accent-soft);
  color:var(--accent);font-size:12.5px;font-weight:600
}
.view{display:none}
.view.on{display:block}

/* ---------- about ---------- */
.about{max-width:1000px;margin:0 auto;padding:34px 20px 120px}
.about-hero{
  padding:24px 26px;border:1px solid var(--border);border-radius:14px;
  background:linear-gradient(135deg,var(--surface),var(--accent-soft));box-shadow:var(--shadow)
}
.about-kicker{
  margin:0 0 8px;font-size:10.5px;font-weight:700;letter-spacing:.08em;
  text-transform:uppercase;color:var(--accent)
}
.about-hero h2{font-size:24px;line-height:1.25;max-width:28ch}
.about-hero .lead{font-size:14px;color:var(--text-2);max-width:76ch;margin:13px 0 0;line-height:1.65}
.about-section{margin-top:30px}
.about-section > h3{font-size:16px;margin-bottom:6px}
.about-section > p{font-size:13px;color:var(--text-2);max-width:78ch;margin:0 0 16px}
.about-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}
.about-card{border:1px solid var(--border);border-radius:11px;background:var(--surface);padding:15px 16px}
.about-card h4{font-size:13px;margin-bottom:5px}
.about-card p{font-size:12px;color:var(--text-2);margin:0;line-height:1.55}
.about-levels .about-card{border-top:3px solid var(--accent)}
.about-route-groups{display:grid;gap:26px}
.about-route-group{min-width:0}
.about-route-heading{margin-bottom:10px;padding-top:4px;border-top:1px solid var(--border)}
.about-route-heading h4{font-size:13.5px;margin:11px 0 4px}
.about-route-heading p{font-size:11.5px;line-height:1.5;color:var(--text-2);max-width:78ch;margin:0}
.about-routes{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px}
.about-routes-two{grid-template-columns:repeat(2,minmax(0,1fr))}
.about-route{
  min-width:0;border:1px solid var(--border);border-radius:11px;background:var(--surface);
  color:var(--text);padding:14px 15px;text-align:left;box-shadow:var(--shadow);
  display:flex;flex-direction:column;align-items:flex-start;
  transition:border-color .15s ease,background .15s ease,transform .15s ease,box-shadow .15s ease
}
.about-route:hover{border-color:var(--accent);background:var(--accent-soft);transform:translateY(-1px);box-shadow:0 7px 18px rgba(20,30,55,.12)}
.about-route:active{transform:translateY(0)}
.about-route:focus-visible{outline:2px solid var(--accent);outline-offset:3px}
.about-route .about-route-context{
  display:block;margin-bottom:7px;font-size:9.5px;font-weight:700;line-height:1.3;
  letter-spacing:.065em;text-transform:uppercase;color:var(--accent)
}
.about-route .about-route-title{display:block;font-size:12.5px;font-weight:650;line-height:1.4}
.about-route small{display:block;flex:1;margin-top:5px;color:var(--text-2);font-size:11px;line-height:1.45}
.about-steps{counter-reset:about-step;display:grid;gap:0;margin-top:8px}
.about-step{
  counter-increment:about-step;display:grid;grid-template-columns:36px minmax(0,1fr);gap:12px;
  padding:13px 0;border-top:1px solid var(--border)
}
.about-step::before{
  content:counter(about-step);display:grid;place-items:center;width:28px;height:28px;border-radius:8px;
  background:var(--accent-soft);color:var(--accent);font-size:12px;font-weight:700
}
.about-step h4{font-size:13px;margin:3px 0 4px}
.about-step p{font-size:12px;color:var(--text-2);margin:0;line-height:1.55}
.about-note{
  margin-top:26px;border-left:3px solid var(--warn);border-radius:0 9px 9px 0;
  background:var(--warn-bg);padding:12px 14px;font-size:12px;color:var(--text-2);line-height:1.55
}
.about-note b{color:var(--text)}

/* ---------- the physical level ----------
   Additive: every rule below is either a new class or a modifier on one, so
   the logical view renders through exactly the cascade it did before. */
.plane-toggles{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
/* Where a stage runs matters more on a deployment diagram than which family
   it belongs to, so this chip stands in the group chip's place. */
.node .rtchip{
  font-size:9px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;
  padding:1px 6px;border-radius:20px;border:1px solid var(--rt-color,var(--text-3));
  color:var(--rt-color,var(--text-3));opacity:.9
}
/* Keep this significant runtime label at full strength while leaving the
   card's border to communicate tier or control-plane role as before. */
.node[data-runtime="inproc"] .rtchip{opacity:1}
.node .lvlchip{
  font-size:9px;font-weight:650;letter-spacing:.03em;
  padding:1px 6px;border-radius:20px;border:1px dashed var(--border-strong);color:var(--text-3)
}
/* The write path is not the data plane. Same card, deliberately unlike enough
   that a reader does not take an ordering authority for another store. */
.data-source-node.write-path{--source-line:var(--wire-train);border-style:dashed}
.data-source-node.write-path .source-serves{color:var(--wire-train)}
.legendrow i.data-key.write-path{border-color:var(--wire-train);border-style:dashed;background:transparent}
.entity-summary .hc-rt{color:var(--rt-color,var(--text-2));border-color:var(--rt-color,var(--border))}
/* A departure from the logical level is the one section a reader should not
   skim, so it is the one section with a rail. */
.sect.warn > h4{color:var(--warn);border-bottom-color:var(--warn)}
.sect.warn > .departure{
  margin:0;font-size:12px;line-height:1.55;color:var(--text-2);
  border-left:3px solid var(--warn);background:var(--warn-bg);
  padding:9px 11px;border-radius:0 7px 7px 0
}
/* The highest-value paragraph on most physical cards: what bites, why, and
   what to do instead. The fix carries its own rail so it cannot be missed. */
.gotcha{border:1px solid var(--border);border-radius:9px;padding:10px 11px;margin-bottom:9px;background:var(--surface-2)}
.gotcha .g{font-size:12.5px;font-weight:650;color:var(--warn);line-height:1.4}
.gotcha .why{margin:6px 0 0;font-size:12px;line-height:1.5;color:var(--text-2)}
.gotcha .fix{margin:7px 0 0;font-size:12px;line-height:1.5;color:var(--text);border-left:2px solid var(--ok);padding-left:8px}
.gotcha .fix b{color:var(--ok);font-weight:650}

/* Long architecture names should be readable rather than permanently
   ellipsised when the viewport has room to give the component list a little
   more width. The established 288px sidebar remains below this breakpoint. */
@media (min-width:1400px){
  .app{grid-template-columns:336px minmax(0,1fr)}
}

@media (max-width:1180px){
  .app{grid-template-columns:1fr}
  .side{position:static;max-height:none;border-right:0;border-bottom:1px solid var(--border)}
  .row{grid-template-columns:minmax(0,120px) minmax(0,1fr) minmax(0,170px)}
}
@media (max-width:900px){
  .ctxbar{position:static}
  .side{top:0}
  .canvas.with-data-sources .row{grid-template-columns:1fr;width:100%;margin-left:0}
  .canvas.with-data-sources .cell.data,
  .canvas.with-data-sources .cell.left,
  .canvas.with-data-sources .cell.center,
  .canvas.with-data-sources .cell.right{grid-column:1}
  .canvas.with-data-sources .cell.left{transform:none}
  .row.parallel-row .cell.center{padding-inline:54px}
  .canvas.with-data-sources .data-source-column{
    display:grid;grid-template-columns:repeat(2,minmax(0,1fr));width:100%
  }
}
@media (max-width:700px){
  /* `inset:0` rather than `100vw`, which counts the scrollbar and would push
     the modal a scrollbar's width past the viewport it is covering. */
  .export-modal{inset:0;transform:none;width:auto;height:auto;border:0;border-radius:0}
  .ex-opts{gap:10px}
  .ex-dir{margin-left:0;width:100%}
  .ex-foot{flex-wrap:wrap}
  .hdr{position:static;padding:10px 14px;gap:10px}
  .hdr .sub{display:none}
  .ctxbar{padding:12px 14px}
  .seg{display:flex;flex-wrap:wrap;width:100%}
  .seg button{flex:1 1 100%;justify-content:flex-start}
  .app{grid-template-columns:1fr}
  .stage-area{order:1;padding:18px 14px 40px}
  .side{order:2;border-bottom:0;border-top:1px solid var(--border)}
  .canvas{padding-left:0}
  .row{grid-template-columns:1fr;gap:10px;margin-bottom:26px;position:relative}
  .row.stage-group-clearance{margin-bottom:26px}
  .row .cell{justify-content:center!important}
  .row .cell.left{transform:none}
  .row .cell.left > .node{width:100%;min-width:0;max-width:none}
  .row .cell:empty{display:none}
  .row,.row .cell,.data-source-column{pointer-events:auto}
  .row .cell.wired-stack{row-gap:11px}
  .row .cell.center > .node{flex:1 1 100%}
  .row.parallel-row .cell.center,
  .row.parallel-row:has(.cell.left .node) .cell.center{padding:0;max-width:none}
  .node{max-width:none;width:100%}
  .canvas.with-data-sources .data-source-column{display:flex;width:100%;gap:9px}
  .data-source-node{width:100%;max-width:none;padding:17px 12px 12px}
  .data-source-node .source-serves{display:none}
  .wires{display:none}
  .mobile-dependency-intro,.mobile-transition,.mobile-recovery,
  .mobile-stage-marker,.mobile-selection,.mobile-dep-chips{display:flex}
  .mobile-dependency-intro{
    flex-direction:column;gap:8px;margin-bottom:18px;padding:12px 13px;
    border:1px solid var(--border);border-radius:10px;background:var(--surface)
  }
  .mobile-dependency-intro strong{font-size:12px}
  .mobile-dependency-intro p{margin:0;color:var(--text-2);font-size:11px}
  .mobile-kind-list{display:flex;flex-wrap:wrap;gap:5px}
  .mobile-kind{
    display:inline-flex;align-items:center;gap:5px;padding:2px 6px;border:1px solid var(--border);
    border-radius:20px;background:var(--surface-2);color:var(--text-2);font-size:9.5px
  }
  .mobile-rel-key{width:18px;height:7px;overflow:visible;flex:none}
  .mobile-transition{
    position:relative;flex-direction:column;gap:4px;margin:-14px 8px 18px;padding:8px 10px 8px 17px;
    border-left:2px solid var(--wire);border-radius:0 8px 8px 0;background:var(--surface-2)
  }
  .mobile-transition::before{
    content:"";position:absolute;left:-5px;bottom:-5px;width:7px;height:7px;
    border-right:2px solid var(--wire);border-bottom:2px solid var(--wire);transform:rotate(45deg)
  }
  .mobile-transition-line{display:flex;align-items:flex-start;gap:7px;font-size:10.5px;color:var(--text-2)}
  .mobile-transition-line b{color:var(--text);font-weight:650}
  .mobile-recovery{
    flex-direction:column;gap:7px;margin:-14px 4px 20px 24px;padding:10px 11px;
    border:1px solid var(--wire-loop);border-left-width:3px;border-radius:8px;background:var(--warn-bg)
  }
  .mobile-recovery-title{font-size:10px;font-weight:750;text-transform:uppercase;letter-spacing:.045em;color:var(--wire-loop)}
  .mobile-recovery-path{font-size:10.5px;color:var(--text-2);line-height:1.45}
  .mobile-recovery-path b{color:var(--text)}
  .mobile-stage-marker{
    flex-direction:column;gap:2px;margin:2px 0 18px;padding:8px 10px;
    border:1px dashed var(--wire-gate);border-radius:9px;color:var(--wire-gate);background:var(--surface)
  }
  .mobile-stage-marker b{font-size:10px;text-transform:uppercase;letter-spacing:.045em}
  .mobile-stage-marker span{font-size:10px;color:var(--text-2)}
  .mobile-dep-chips{flex-wrap:wrap;gap:4px;margin-top:7px}
  .mobile-dep-chip{
    display:inline-flex;gap:3px;align-items:center;border:1px solid var(--dep-color,var(--border));
    border-radius:6px;background:var(--surface);color:var(--dep-color,var(--text-2));padding:2px 5px;
    font-size:9px;font-weight:650;line-height:1.35;text-transform:none
  }
  .mobile-selection{
    flex:1 1 100%;width:100%;flex-direction:column;gap:9px;margin:2px 0 8px;padding:11px 12px;
    border:2px solid var(--accent);border-radius:9px;background:var(--surface);box-shadow:var(--shadow)
  }
  .mobile-selection-head{display:flex;align-items:flex-start;gap:8px}
  .mobile-selection-head strong{font-size:11.5px;line-height:1.35}
  .mobile-selection-head button{margin-left:auto;border:0;background:none;color:var(--text-3);padding:0 2px}
  .mobile-selection-group{display:flex;flex-direction:column;gap:5px}
  .mobile-selection-label{font-size:9px;font-weight:750;text-transform:uppercase;letter-spacing:.045em;color:var(--text-3)}
  .mobile-selection-row{display:flex;align-items:flex-start;gap:6px;font-size:10px;color:var(--text-2)}
  .mobile-selection-row b{color:var(--text);font-weight:650}
  .mobile-dep-ref{
    border:1px solid var(--border);border-radius:5px;background:var(--surface-2);color:var(--text-2);
    padding:2px 5px;font-size:9.5px;text-align:left
  }
  .mobile-details-btn{
    align-self:flex-start;border:1px solid var(--accent);border-radius:6px;background:var(--accent-soft);
    color:var(--accent);padding:4px 7px;font-size:10px;font-weight:650
  }
  .drawer{width:100vw}
  .step{grid-template-columns:1fr;gap:8px}
  .step .grid{grid-template-columns:1fr}
  .build,.about{padding:20px 14px 60px}
  .about-hero{padding:20px}
  .about-hero h2{font-size:21px}
  .about-grid,.about-routes,.about-routes-two{grid-template-columns:1fr}
}
@media (prefers-reduced-motion:reduce){
  *{animation-duration:.001ms!important;transition-duration:.001ms!important}
}
