/* ---------- tokens: "drafting table" ---------- */
/* ANCHOR: STYLE::TOKENS @ CONFIG.CSS #M ^P1 */
/* CONTRACT: Design vocabulary: CSS custom properties for both themes
   (porcelain/ink light, slate dark); every themed surface derives from these
   tokens; adding a theme value starts here
   REQUIRES: None
   MEDIUM: theme correctness derives from these variables */
:root{
  --paper:#EDF0EF;         /* cool porcelain sheet */
  --grid:#BCC6C3;          /* graphite dots */
  --ink:#20262B;           /* instrument ink */
  --ink-soft:#5A646B;
  --chrome:#FBFCFC;        /* panels */
  --edge-hair:#D5DBD9;
  --accent:#2F5FE3;        /* drafting cobalt: selection + focus only */
  --danger:#C4433B;
  --node-fill:#FFFFFF;
  --node-stroke:#2A3238;
  --dim:0.16;
  --r:10px;
  --shadow:0 10px 28px rgba(32,38,43,.14), 0 2px 6px rgba(32,38,43,.10);
  --font-ui:"Segoe UI Variable Text","Segoe UI","Avenir Next",system-ui,sans-serif;
  --font-mono:ui-monospace,"Cascadia Code","SF Mono",Menlo,Consolas,monospace;
}

/* dark theme: manual choice wins; otherwise follow the system
   (prefers-color-scheme; standard media query, training-knowledge flagged) */
html[data-theme="dark"]{
  --paper:#191D21; --grid:#31393E; --ink:#E6EAE8; --ink-soft:#98A3A9;
  --chrome:#22272C; --edge-hair:#343B41;
}
@media (prefers-color-scheme: dark){
  html:not([data-theme="light"]){
    --paper:#191D21; --grid:#31393E; --ink:#E6EAE8; --ink-soft:#98A3A9;
    --chrome:#22272C; --edge-hair:#343B41;
  }
}
html[data-label-size="l"]{--label-size:16px;--label-weight:600}
html[data-label-size="xl"]{--label-size:19px;--label-weight:600}
html[data-label-size="xxl"]{--label-size:24px;--label-weight:700}
/* END ANCHOR: STYLE::TOKENS @ CONFIG.CSS #M ^P1 */

/* ANCHOR: STYLE::COMPONENTS @ UI.CSS #M ^P1 */
/* CONTRACT: Component classes (kebab-case) bound by the UI anchors: cards,
   edges, chip, toolbar, popover, panel, search, legend; class names are the
   CSS layer of the Lexical Registry
   REQUIRES: STYLE::TOKENS
   MEDIUM: the CSS layer of the Lexical Registry */
*{box-sizing:border-box}
html,body{height:100%;margin:0;overflow:hidden}
body{font-family:var(--font-ui);color:var(--ink);background:var(--paper)}
button{font:inherit;color:inherit;cursor:pointer}
:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

/* ---------- chrome ---------- */
.topbar{
  position:fixed;inset:0 0 auto 0;z-index:30;height:52px;
  display:flex;align-items:center;justify-content:space-between;
  padding:0 14px;background:var(--chrome);
  border-bottom:1px solid var(--edge-hair);
}
.brand{display:flex;align-items:center;gap:9px;font-weight:600;letter-spacing:.02em}
.btn-board{font-weight:500;max-width:220px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.btn-board .caret{color:var(--ink-soft);font-size:10px}
.brand svg{color:var(--ink)}
.topbar-actions{display:flex;align-items:center;gap:8px}
.save-status{font-family:var(--font-mono);font-size:11px;color:var(--ink-soft);margin-right:4px}

.btn{
  background:var(--chrome);border:1px solid var(--edge-hair);border-radius:8px;
  padding:6px 12px;font-size:13px;transition:background .12s,border-color .12s;
}
.btn:hover{border-color:var(--ink-soft)}
.btn[aria-pressed="true"]{background:var(--ink);color:var(--chrome);border-color:var(--ink)}
.btn-quiet{border-color:transparent;color:var(--ink-soft)}
.btn-quiet:hover{color:var(--danger);border-color:var(--danger)}
.btn-small{padding:3px 9px;font-size:12px;border-radius:6px}
.btn-round{width:32px;height:32px;padding:0;border-radius:50%;font-size:16px;line-height:1}

/* ---------- stage / canvas ---------- */
#stage{position:fixed;inset:52px 0 0 0}
#canvas{width:100%;height:100%;display:block;touch-action:none;cursor:default}
#canvas.space{cursor:grab}
#canvas.panning{cursor:grabbing}
.grid-dot{fill:var(--grid)}

.empty-hint{
  position:absolute;inset:0;display:grid;place-content:center;text-align:center;
  pointer-events:none;color:var(--ink-soft);
}
/* Author display values override the hidden attribute (MDN: hidden global
   attribute), so [hidden] must win explicitly or the hint never goes away. */
.empty-hint[hidden]{display:none}
.empty-hint p{margin:4px 0;font-size:15px}
.empty-hint .sub{font-size:12px;font-family:var(--font-mono);margin-top:10px}
.empty-hint strong{font-family:var(--font-mono)}

/* ---------- nodes (SVG) ---------- */
.node{cursor:move}
.node .card{
  /* rounded corners on arbitrary polygons: stroke matches fill, round joins */
  stroke-width:12;stroke-linejoin:round;
  filter:url(#cardShadow);
  transition:fill .12s,stroke .12s;
}
.node:hover .card{filter:url(#cardShadowHover)}
.node .ring{fill:none;stroke:var(--accent);stroke-width:2.5;stroke-linejoin:round;pointer-events:none}
.node.dimmed{opacity:var(--dim)} /* still clickable: selecting a dimmed node jumps focus to it */
.edge.dimmed{opacity:var(--dim);pointer-events:none}

.node-label{overflow:visible}
.node-label div{
  width:100%;height:100%;display:flex;align-items:center;justify-content:center;
  text-align:center;font-family:var(--font-mono);font-size:var(--label-size,13px);font-weight:var(--label-weight,500);line-height:1.3;
  color:var(--ink);padding:4px;word-break:break-word;overflow:hidden;
  border-radius:6px;
}
.node-label div:empty::before{content:attr(data-ph);color:var(--ink-soft);opacity:.7}
.node-label div[contenteditable="true"]{outline:2px solid var(--accent);background:#fff;overflow:auto;cursor:text}

.handle{fill:var(--chrome);stroke:var(--accent);stroke-width:2;opacity:0;pointer-events:none;cursor:crosshair;transition:opacity .12s}
.handle-hit{fill:transparent;opacity:0;pointer-events:none;cursor:crosshair} /* TOUCH::HARDEN */
.node:hover .handle-hit,.node.selected .handle-hit{pointer-events:all}
.node:hover .handle,.node.selected .handle{opacity:1;pointer-events:all}
.grip{fill:none;stroke:var(--ink-soft);stroke-width:2;stroke-linecap:round;opacity:0;transition:opacity .12s;pointer-events:none}
.grip-hit{fill:transparent;cursor:nwse-resize;pointer-events:none}
.node:hover .grip,.node.selected .grip{opacity:.9}
.node:hover .grip-hit,.node.selected .grip-hit{pointer-events:all}
.edge-arrow{stroke:none}
.edge-label{font-family:var(--font-mono);font-size:12px;fill:var(--ink);
  stroke:var(--paper);stroke-width:4;paint-order:stroke;pointer-events:none}

/* animated flow: dash march in the arrow's direction; the global
   reduced-motion rule freezes it into a static dashed line */
.edge.flow-fwd .edge-path,.edge.flow-rev .edge-path{stroke-dasharray:8 6}
.edge.flow-fwd .edge-path{animation:flowf .8s linear infinite}
.edge.flow-rev .edge-path{animation:flowr .8s linear infinite}
@keyframes flowf{to{stroke-dashoffset:-14}}
@keyframes flowr{to{stroke-dashoffset:14}}

.search{
  position:absolute;top:14px;left:50%;transform:translateX(-50%);z-index:35;width:300px;
  background:var(--chrome);border:1px solid var(--edge-hair);border-radius:var(--r);
  box-shadow:var(--shadow);padding:8px;
}
.search[hidden]{display:none}
.search input{
  width:100%;border:1px solid var(--edge-hair);border-radius:6px;padding:7px 9px;
  font-family:var(--font-mono);font-size:13px;background:var(--paper);color:var(--ink);
}
.search input:focus{border-color:var(--accent);outline:none}
.search ul{list-style:none;margin:6px 0 0;padding:0;max-height:240px;overflow:auto}
.search li button{
  display:block;width:100%;text-align:left;border:none;background:none;border-radius:6px;
  padding:7px 9px;font-size:13px;font-family:var(--font-mono);color:var(--ink);
}
.search li button:hover{background:var(--paper)}
.search .search-empty{padding:8px 9px;font-size:12px;color:var(--ink-soft)}

.notes-panel{
  position:absolute;right:14px;bottom:70px;width:264px;z-index:20;
  background:var(--chrome);border:1px solid var(--edge-hair);border-radius:var(--r);
  box-shadow:var(--shadow);padding:12px;display:flex;flex-direction:column;gap:8px;
}
.notes-panel[hidden]{display:none}
.notes-head{display:flex;align-items:center;justify-content:space-between}
.notes-head h2{font-size:12px;margin:0;font-family:var(--font-mono);font-weight:600;
  text-transform:uppercase;letter-spacing:.08em;color:var(--ink-soft);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:190px}
.notes-panel textarea{
  width:100%;min-height:140px;resize:vertical;border:1px solid var(--edge-hair);
  border-radius:6px;padding:8px;font-family:var(--font-mono);font-size:12px;
  line-height:1.5;background:var(--paper);color:var(--ink);
}
.notes-panel textarea:focus{border-color:var(--accent);outline:none}

.notes-dot{fill:var(--accent);pointer-events:none}

.marquee{position:absolute;z-index:15;border:1.5px solid var(--accent);
  background:rgba(47,95,227,.08);pointer-events:none;border-radius:3px}
.marquee[hidden]{display:none}

/* per-node filter chip */
.node-chip{overflow:visible}
.node-chip .chip{
  display:flex;gap:6px;align-items:center;justify-content:center;
  font-family:var(--font-mono);font-size:11px;
}
.chip-btn{
  display:flex;align-items:center;gap:6px;background:var(--chrome);
  border:1px solid var(--edge-hair);border-radius:999px;padding:3px 10px;box-shadow:var(--shadow);
  white-space:nowrap;
}
.chip-btn .dot{width:9px;height:9px;border-radius:50%;flex:none}
.chip-del{background:var(--chrome);border:1px solid var(--edge-hair);border-radius:999px;
  width:22px;height:22px;padding:0;color:var(--ink-soft);box-shadow:var(--shadow)}
.chip-del:hover{color:var(--danger);border-color:var(--danger)}
.chip-add:hover{color:var(--accent);border-color:var(--accent)}
.chip-color{display:flex;background:var(--chrome);border:1px solid var(--edge-hair);border-radius:999px;
  width:22px;height:22px;align-items:center;justify-content:center;box-shadow:var(--shadow);cursor:pointer}
.chip-color input{width:14px;height:14px;padding:0;border:none;background:none;cursor:pointer}

/* ---------- edges ---------- */
.edge-path{fill:none;stroke-width:2.5;stroke-linecap:round}
.edge-hit{fill:none;stroke:transparent;stroke-width:16;cursor:pointer}
.edge.emphasized .edge-path{stroke-width:4}
/* pointer-events:none is load-bearing: without it, elementFromPoint() on drop
   hits this preview line (its endpoint tracks the cursor) instead of the target node. */
.ghost{fill:none;stroke:var(--accent);stroke-width:2;stroke-dasharray:6 6;pointer-events:none}

/* ---------- legend ---------- */
.legend{
  position:absolute;top:14px;right:14px;width:248px;z-index:20;
  background:var(--chrome);border:1px solid var(--edge-hair);border-radius:var(--r);
  box-shadow:var(--shadow);padding:12px;
}
.legend[hidden]{display:none}
.legend-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:8px}
.legend h2{font-size:12px;margin:0;font-family:var(--font-mono);font-weight:600;
  text-transform:uppercase;letter-spacing:.08em;color:var(--ink-soft)}
.legend ul{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:6px}
.legend li{display:flex;align-items:center;gap:8px}
.swatch{
  width:20px;height:20px;border-radius:6px;border:1px solid rgba(0,0,0,.15);
  padding:0;flex:none;position:relative;
}
.swatch.hidden-cat::after{
  content:"";position:absolute;inset:8px -3px auto;height:2px;background:var(--ink);transform:rotate(-45deg);
}
.legend input[type="color"]{width:22px;height:22px;padding:0;border:none;background:none;flex:none;cursor:pointer}
.legend input[type="text"]{
  flex:1;min-width:0;border:1px solid transparent;border-radius:6px;padding:4px 6px;
  font-family:var(--font-mono);font-size:12px;background:transparent;color:var(--ink);
}
.legend input[type="text"]:hover{border-color:var(--edge-hair)}
.legend input[type="text"]:focus{border-color:var(--accent);outline:none;background:#fff}
.cat-del{border:none;background:none;color:var(--ink-soft);font-size:14px;padding:2px 4px}
.cat-del:hover{color:var(--danger)}
.legend-tip{font-size:11px;color:var(--ink-soft);margin:10px 0 0;line-height:1.45}

/* ---------- zoom bar ---------- */
.zoombar{
  position:absolute;left:14px;bottom:14px;z-index:20;display:flex;gap:6px;align-items:center;
  background:var(--chrome);border:1px solid var(--edge-hair);border-radius:999px;
  padding:5px;box-shadow:var(--shadow);
}
.zoombar .btn{border:none}
.zoombar-sep{width:1px;height:18px;background:var(--edge-hair)}

/* ---------- FAB + shape picker ---------- */
.fab-wrap{position:absolute;right:22px;bottom:22px;z-index:20;display:flex;flex-direction:column;align-items:center}
.fab{
  width:56px;height:56px;border-radius:50%;border:none;background:var(--ink);color:var(--chrome);
  font-size:28px;line-height:1;box-shadow:var(--shadow);transition:transform .15s;
}
.fab[aria-expanded="true"]{transform:rotate(45deg)}
.shape-picker{
  display:flex;flex-direction:column;gap:8px;margin-bottom:12px;
}
.shape-picker[hidden]{display:none}
.shape-picker button{
  width:48px;height:48px;border-radius:12px;border:1px solid var(--edge-hair);
  background:var(--chrome);box-shadow:var(--shadow);display:grid;place-items:center;
  transition:transform .12s,border-color .12s;
}
.shape-picker button:hover{transform:scale(1.08);border-color:var(--ink)}
.shape-picker svg{width:26px;height:26px}
.shape-picker polygon,.shape-picker rect{fill:none;stroke:var(--ink);stroke-width:2.5;stroke-linejoin:round}

/* ---------- popover (edge menu, node filter menu) ---------- */
.popover{
  position:absolute;z-index:40;background:var(--chrome);border:1px solid var(--edge-hair);
  border-radius:var(--r);box-shadow:var(--shadow);padding:6px;min-width:170px;
}
.popover[hidden]{display:none}
.popover .pop-title{font-family:var(--font-mono);font-size:10px;text-transform:uppercase;
  letter-spacing:.08em;color:var(--ink-soft);padding:4px 8px 6px}
.popover button.pop-item{
  display:flex;align-items:center;gap:8px;width:100%;text-align:left;
  border:none;background:none;border-radius:6px;padding:7px 8px;font-size:13px;
}
.popover button.pop-item:hover{background:var(--paper)}
.popover button.pop-item .dot{width:11px;height:11px;border-radius:50%;flex:none;border:1px solid rgba(0,0,0,.15)}
.popover button.pop-item.danger{color:var(--danger)}
.popover .pop-sep{height:1px;background:var(--edge-hair);margin:5px 4px}
.popover .pop-input{width:100%;border:1px solid var(--edge-hair);border-radius:6px;
  padding:6px 8px;font-family:var(--font-mono);font-size:12px;margin:2px 0 4px;
  background:var(--paper);color:var(--ink)}
.popover .pop-input:focus{border-color:var(--accent);outline:none}
.popover .pop-item.active{background:var(--paper);font-weight:600}

@media (max-width:640px){
  .legend{width:200px}
  .topbar-actions .save-status{display:none}
}
@media (prefers-reduced-motion:reduce){
  *{transition:none !important;animation:none !important}
}
/* END ANCHOR: STYLE::COMPONENTS @ UI.CSS #M ^P1 */

/* TRACE::VIEW (anchor: js/nodes.js) — one reach set, two surfaces in lockstep */
.node.trace-dim { opacity: 0.18; }
.edge.trace-dim { opacity: 0.12; }
.edge.trace-emph path { stroke-width: 3.5px; }
.node.trace-root rect, .node.trace-root path, .node.trace-root ellipse,
.node.trace-root polygon { stroke-width: 3px; }

/* SEARCH::DEEP (anchor: js/ui.js) — note-hit snippets in the find overlay */
.search-snippet { display: block; font-size: 11px; opacity: 0.65;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* WHATIF::RENDER (anchor: js/edges.js) — ghosted = present but excluded.
   Distinct from trace-dim (0.18/0.12) and from hidden (vanishes). */
.node.ghosted { opacity: 0.45; }
.node.ghosted polygon.card { stroke-dasharray: 6 5; }
.edge.ghosted { opacity: 0.45; }

/* Hover-reveal + enlarge (Supreme Admin directives, Entries 069 + 074):
   2.5x floor, compensated by zoom so a fit-to-screen layout still gets a
   full-size usable menu — the scale grows as the canvas shrinks (capped 9x) */
.node-chip .chip { transition: transform .12s ease; transform-origin: center top; }
/* Entry 083: origin TOP — the menu rests below the card and its bloom projects
   DOWNWARD, never covering the card (small cards were being swallowed) */
.node:hover .node-chip .chip {
  /* Entry 078: JS supplies a viewport-fitted scale; the calc is the fallback */
  transform: scale(var(--menu-scale, clamp(2.5, calc(2.5 / var(--zoom-k, 1)), 9)));
}

/* TOUCH::HARDEN (anchor: js/nodes.js) — coarse pointers get >=44px menu targets */
@media (pointer: coarse) {
  .chip-btn { padding: 12px 16px; font-size: 14px; }
  .node-chip .chip { gap: 10px; }
}

/* Trace legibility (Entry 071): explicit mode pill + unmistakable root */
#trace-pill { position: absolute; top: 12px; left: 50%; transform: translateX(-50%);
  background: var(--accent); color: #fff; font-family: var(--font-mono); font-size: 12px;
  padding: 6px 14px; border-radius: 999px; box-shadow: var(--shadow); cursor: pointer;
  z-index: 30; max-width: 80%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.node.trace-root polygon.card { stroke: var(--accent) !important; stroke-width: 5px !important;
  stroke-dasharray: none !important; }

/* FLOW::EDIT (anchor: js/edges.js) — panel metrics rows */
.panel-sub { margin: 14px 0 6px; font-size: 12px; opacity: .7; }
.metric-row { display: flex; gap: 8px; align-items: center; margin-bottom: 6px; }
.metric-row span { flex: 1; font-size: 13px; }
.metric-row input { width: 110px; }

/* FLOW::DISPLAY (anchor: js/edges.js) — money on the pixels */
.edge-label.has-flow { font-family: var(--font-mono); font-weight: 600; }
.net-badge { font-family: var(--font-mono); font-size: 12px; font-weight: 700;
  paint-order: stroke; stroke: var(--paper); stroke-width: 3px; }
.net-badge.pos { fill: #2E9E63; }
.net-badge.neg { fill: #C0392B; }
.net-badge.warn { fill: #C77700; }
.edge.flow-cycle path { stroke: #C77700 !important; stroke-dasharray: 3 4 !important; }

/* Badge bloom (Supreme Admin ruling, Entry 080 — option b): hover on desktop,
   selection on touch, enlarges the net badge like the card menu */
.net-badge { transition: transform .12s ease; transform-box: fill-box;
  transform-origin: right bottom; }
.node:hover .net-badge, .node.selected .net-badge {
  transform: scale(var(--menu-scale, 2.5));
}
/* Entry 095 (Supreme Admin directive): the SAME bloom on ALL annotation text —
   the aggregator mark joins badges and line labels */
.agg-mark { transition: transform .12s ease; transform-box: fill-box;
  transform-origin: right bottom; } /* Entry 096: blooms LEFTWARD, away from the badge */
.node:hover .agg-mark, .node.selected .agg-mark {
  transform: scale(var(--menu-scale, 2.5));
}

/* Line-badge bloom (Supreme Admin field report, Entry 084): flow text on
   connections enlarges like card badges — hover on desktop, select on touch */
.edge-label { transition: transform .12s ease; transform-box: fill-box;
  transform-origin: center center;
  paint-order: stroke; stroke: var(--paper); stroke-width: 3px; }
.edge:hover .edge-label, .edge.selected .edge-label {
  transform: scale(clamp(2.2, calc(2.2 / var(--zoom-k, 1)), 8));
}

/* AGG::TOGGLE (anchor: js/nodes.js) — aggregator mark */
.agg-mark { font-family: var(--font-mono); font-size: 11px; font-weight: 700;
  fill: var(--accent); paint-order: stroke; stroke: var(--paper); stroke-width: 3px; }

/* TIME::SCRUB (anchor: js/ui.js) — horizon control */
.horizon-wrap { display: inline-flex; align-items: center; gap: 6px; }
.horizon-wrap input[type="range"] { width: 90px; }
#horizon-label { font-family: var(--font-mono); font-size: 11px; min-width: 44px; }
/* A4.1r per-type strict toggle (Legend rows) */
.cat-strict { background: none; border: 1px solid var(--edge-hair); border-radius: 6px;
  cursor: pointer; font-size: 12px; padding: 2px 6px; opacity: .7; }
.cat-strict.on { opacity: 1; color: #C77700; border-color: #C77700; }
/* Aggregator badge accent */
.net-badge.agg { fill: var(--accent); }
.net-badge.agg.pos { fill: #2E9E63; }
.net-badge.agg.neg { fill: #C0392B; }

/* Entry 097: badges and marks are DISPLAY-ONLY — clicks pass through to
   whatever lives beneath (the top-right resize grip shares their corner) */
.net-badge, .agg-mark { pointer-events: none; }

/* A4.2 (Supreme Admin ruling, Entry 098) — shown-metrics stack: display-only,
   blooming as ONE ordered group, down-left away from badge and grip */
.metric-line { font-family: var(--font-mono); font-size: 10px; fill: var(--ink);
  opacity: .8; paint-order: stroke; stroke: var(--paper); stroke-width: 3px; }
.metric-stack { pointer-events: none; transition: transform .12s ease;
  transform-box: fill-box; transform-origin: right top; }
.node:hover .metric-stack, .node.selected .metric-stack {
  transform: scale(var(--menu-scale, 2.5));
}

/* LAYER::VIEW (anchor: js/palette.js) — Layer Mode (A5.1 rulings) */
body.layer-mode #canvas { background: #23252B; }
body.layer-mode #canvas .grid-dot, body.layer-mode .dots { opacity: .25; }
.layer-arc { fill: none; stroke-linejoin: round; stroke-linecap: round;
  pointer-events: none; } /* Entry 109: width/opacity are attribute-driven per arc */
.ghosted-layer { opacity: .35; }
.ghosted-layer .shape-poly { stroke-dasharray: 6 5; }
#layer-menu { position: fixed; top: 64px; right: 16px; width: 320px; z-index: 60;
  background: var(--paper); border: 1px solid var(--edge-hair); border-radius: 12px;
  box-shadow: 0 12px 32px rgba(0,0,0,.35); font-size: 13px; }
.layer-menu-head { display: flex; justify-content: space-between; align-items: center;
  padding: 8px 12px; border-bottom: 1px solid var(--edge-hair); font-weight: 700; }
#layer-menu .layer-list { list-style: none; margin: 0; padding: 6px; max-height: 46vh; overflow: auto; }
#layer-menu .layer-list li { display: flex; align-items: center; gap: 6px; padding: 4px 6px; }
#layer-menu .layer-list li input[type="text"] { flex: 1; min-width: 60px; }
#layer-menu .layer-empty { opacity: .7; font-style: italic; }
.layer-menu-foot { display: flex; gap: 6px; padding: 8px 12px; border-top: 1px solid var(--edge-hair); }
#layer-pill { position: fixed; top: 60px; left: 50%; transform: translateX(-50%); z-index: 59;
  background: var(--ink); color: var(--paper); border: none; border-radius: 999px;
  padding: 6px 14px; font-family: var(--font-mono); font-size: 12px; cursor: pointer;
  box-shadow: 0 4px 14px rgba(0,0,0,.3); }
