/* =====================================================================
   Design tokens (F4 — single design language for the playground chrome).
   Every spacing, radius, font-size, color and shadow used by the UI flows
   from these custom properties so the toolbar, panels, dialogs, cards and
   buttons share one consistent visual rhythm. Diagram-specific theme
   presets only override the *color* tokens (--accent, --bg, …) — the scale
   tokens (spacing / radius / type) stay fixed across every theme.
   ===================================================================== */
:root {
  /* --- palette (light base; theme presets + .dark override these) --- */
  --bg: #ffffff;
  --panel: #f7f8fa;
  --border: #e2e6ec;
  --text: #1a1d23;
  --dim: #6b7280;
  --accent: #3b82f6;
  --error: #dc2626;
  --ok: #059669;
  --warn: #b45309;          /* amber for "rendered, lines skipped" */
  --warn-mark: #d97706;     /* amber dot / squiggle / toast accent */
  --on-accent: #ffffff;     /* text/icon on a solid --accent fill */
  --star: #f5a623;          /* GitHub star glyph */
  --scrim: #0a0c10;         /* modal backdrop base (mixed w/ transparency) */
  --dots: #e8eaf0;

  /* --- spacing scale (consistent padding/gap rhythm) --- */
  --sp-1: 2px;
  --sp-2: 4px;
  --sp-3: 6px;
  --sp-4: 8px;
  --sp-5: 10px;
  --sp-6: 12px;
  --sp-7: 14px;
  --sp-8: 16px;
  --sp-10: 20px;
  --sp-12: 24px;

  /* --- border-radius scale --- */
  --r-xs: 4px;
  --r-sm: 6px;
  --r-md: 8px;
  --r-lg: 10px;
  --r-xl: 12px;
  --r-2xl: 16px;
  --r-pill: 999px;
  --r-circle: 50%;

  /* --- type scale --- */
  --fs-2xs: 10px;   /* uppercase eyebrows / section labels */
  --fs-xs: 11px;    /* fine print, kbd, sub-labels */
  --fs-sm: 12px;    /* secondary text, template buttons */
  --fs-base: 13px;  /* body text + standard button labels */
  --fs-md: 14px;    /* control glyphs, close buttons */
  --fs-lg: 15px;    /* brand, command-palette input */
  --fs-h3: 16px;
  --fs-h2: 18px;
  --fs-h1: 21px;

  /* --- elevation (shadows) --- */
  --shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.08);
  --shadow-md: 0 8px 28px rgba(0, 0, 0, 0.18);
  --shadow-pop: 0 10px 30px rgba(0, 0, 0, 0.28);   /* menus / popovers / toast */
  --shadow-lg: 0 18px 50px rgba(0, 0, 0, 0.28);
  --shadow-xl: 0 24px 64px rgba(0, 0, 0, 0.32);

  /* --- monospace stack for editor / code chips --- */
  --mono: 'JetBrains Mono', ui-monospace, 'SF Mono', Menlo, Consolas, monospace;

  /* Canvas + node polish tokens (U19). */
  --canvas: #fbfcfe;
  --node-shadow: drop-shadow(0 1px 1px rgba(15, 23, 42, 0.06)) drop-shadow(0 3px 8px rgba(15, 23, 42, 0.08));
  --node-shadow-hover: drop-shadow(0 2px 3px rgba(15, 23, 42, 0.10)) drop-shadow(0 8px 18px rgba(15, 23, 42, 0.14));
}
:root.dark {
  --bg: #0f1115;
  --panel: #171a21;
  --border: #2d3340;
  --text: #e5e9f0;
  --dim: #9ca3af;
  --accent: #60a5fa;
  --warn: #fbbf24;
  --warn-mark: #f59e0b;
  --dots: #1f2530;
  /* Heavier shadows read on the deep dark canvas. */
  --shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.32);
  --shadow-md: 0 8px 28px rgba(0, 0, 0, 0.42);
  --shadow-pop: 0 10px 30px rgba(0, 0, 0, 0.5);
  --shadow-lg: 0 18px 50px rgba(0, 0, 0, 0.5);
  --shadow-xl: 0 24px 64px rgba(0, 0, 0, 0.55);
  /* A deeper, calmer dark canvas + glow-style node shadows. */
  --canvas: #0c0e13;
  --node-shadow: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.45)) drop-shadow(0 4px 12px rgba(0, 0, 0, 0.42));
  --node-shadow-hover: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.55)) drop-shadow(0 10px 22px rgba(0, 0, 0, 0.5));
}

* { box-sizing: border-box; }
html, body { height: 100%; margin: 0; }
body {
  display: flex;
  flex-direction: column;
  font-family: var(--app-font, Inter, 'Helvetica Neue', Arial, sans-serif);
  background: var(--bg);
  color: var(--text);
}

/* ---------------- boot / loading overlay ---------------- */
/* Covers the app until the WASM engine initializes; app.js fades it out. */
.boot {
  position: fixed;
  inset: 0;
  z-index: 500;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg);
  transition: opacity 0.3s ease;
}
.boot.hide { opacity: 0; pointer-events: none; }
.boot-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  color: var(--dim);
  font-size: var(--fs-base);
}
.boot-logo { font-size: 40px; color: var(--accent); animation: boot-pulse 1.4s ease-in-out infinite; }
.boot-spinner {
  width: 26px;
  height: 26px;
  border: 2.5px solid var(--border);
  border-top-color: var(--accent);
  border-radius: var(--r-circle);
  animation: boot-spin 0.8s linear infinite;
}
@keyframes boot-spin { to { transform: rotate(360deg); } }
@keyframes boot-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.45; } }
@media (prefers-reduced-motion: reduce) {
  .boot-logo, .boot-spinner { animation: none; }
}

header {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 8px 14px;
  border-bottom: 1px solid var(--border);
  flex: none;
  flex-wrap: wrap;
}
.brand { display: flex; align-items: center; gap: 8px; font-size: var(--fs-lg); flex: none; }
.logo { color: var(--accent); }
.brand-pitch {
  font-size: var(--fs-sm);
  color: var(--dim);
  padding-left: 8px;
  margin-left: 2px;
  border-left: 1px solid var(--border);
  white-space: nowrap;
}
.tag { color: var(--dim); font-size: var(--fs-sm); }
#perf { font-variant-numeric: tabular-nums; }

/* "Star on GitHub" call-to-action: subtle until hover. */
.star-link {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font: inherit;
  font-size: var(--fs-base);
  padding: 5px 11px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--panel);
  color: var(--text);
  text-decoration: none;
  white-space: nowrap;
  transition: border-color 0.12s, background 0.12s, transform 0.06s;
}
.star-link:hover { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 7%, var(--panel)); }
.star-link:active { transform: translateY(1px); }
.star-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.star-ic { color: var(--star); font-size: var(--fs-md); line-height: 1; }
@media (max-width: 980px) {
  .brand-pitch { display: none; }
  .star-link .star-text { display: none; }
}

.templates {
  display: flex;
  gap: 4px;
  flex: 1;
  overflow-x: auto;
  scrollbar-width: none;
}
.templates::-webkit-scrollbar { display: none; }
.templates button {
  font: inherit;
  font-size: var(--fs-sm);
  padding: 4px 9px;
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--dim);
  cursor: pointer;
  white-space: nowrap;
}
.templates button:hover { color: var(--text); background: var(--panel); }
.templates button.active { color: var(--accent); border-color: var(--border); background: var(--panel); }

/* ---------------- diagram-type quick switcher ("New") ---------------- */
/* A compact dropdown to start a fresh diagram of any type from a clean
   minimal starter (distinct from the richer examples gallery). Takes the
   header's flex space so the actions group stays right-aligned. */
.switcher { flex: 1; display: flex; align-items: center; }
.new-plus { font-size: var(--fs-md); line-height: 1; color: var(--accent); }
.new-list {
  min-width: 220px;
  max-height: min(70vh, 460px);
  overflow-y: auto;
  padding: 5px;
}
.new-list button[role="menuitem"] {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
}
.new-list .new-ic {
  width: 18px;
  text-align: center;
  color: var(--dim);
  font-size: var(--fs-base);
  flex: none;
}
.new-list button:hover .new-ic,
.new-list button:focus-visible .new-ic { color: var(--accent); }
.new-list .new-label { flex: 1; }
.new-list .new-sub {
  font-size: var(--fs-xs);
  color: var(--dim);
  white-space: nowrap;
}
.new-list .menu-sep { height: 1px; background: var(--border); margin: 5px 4px; }
.new-list .new-section {
  font-size: var(--fs-2xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--dim);
  padding: 6px 8px 3px;
}
.new-list button.new-featured .new-ic { color: var(--accent); }

.actions { display: flex; gap: 6px; flex: none; align-items: center; }
.actions button {
  font: inherit;
  font-size: var(--fs-base);
  padding: 5px 11px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--panel);
  color: var(--text);
  cursor: pointer;
  transition: border-color 0.12s, background 0.12s, transform 0.06s;
}
.actions button:hover { border-color: var(--accent); }
.actions button:active { transform: translateY(1px); }
.actions button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 1px;
}

/* Theme toggle: square icon button with a subtle hover lift. */
.icon-btn {
  width: 34px;
  height: 32px;
  padding: 0 !important;
  font-size: var(--fs-lg);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.icon-btn:hover { background: color-mix(in srgb, var(--accent) 10%, var(--panel)); }
.icon-btn[aria-pressed="true"] {
  border-color: var(--accent);
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, var(--panel));
}

/* ---------------- animated edges ---------------- */
/* When #preview has .animate-edges, marching-ants the dashed/dotted edge
   paths and add a subtle dash flow to solid/thick edges. Works directly on
   the engine's edge <path> elements (inside <g data-edge>), so it functions
   regardless of any engine-side <animate> support. Respects reduced-motion. */
#preview.animate-edges g[data-edge] > path[stroke-dasharray] {
  animation: layra-march 0.9s linear infinite;
}
/* Solid + thick edges have no dasharray; give them a flowing dash overlay. */
#preview.animate-edges g[data-edge] > path:not([stroke-dasharray]) {
  stroke-dasharray: 9 7;
  animation: layra-march 1.1s linear infinite;
}
@keyframes layra-march {
  to { stroke-dashoffset: -32; }
}
@media (prefers-reduced-motion: reduce) {
  #preview.animate-edges g[data-edge] > path { animation: none; }
}

/* Export dropdown */
.menu { position: relative; }
.menu-trigger { display: inline-flex; align-items: center; gap: 5px; }
.menu-trigger .caret { font-size: var(--fs-2xs); color: var(--dim); transition: transform 0.15s; }
.menu-trigger[aria-expanded="true"] { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, var(--panel)); }
.menu-trigger[aria-expanded="true"] .caret { transform: rotate(180deg); }
.menu-list {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  min-width: 190px;
  padding: 5px;
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--panel);
  box-shadow: var(--shadow-md);
  z-index: 50;
  display: flex;
  flex-direction: column;
  gap: 1px;
  animation: menu-in 0.12s ease-out;
}
.menu-list[hidden] { display: none; }
@keyframes menu-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}
.menu-list button {
  text-align: left;
  border: 0 !important;
  border-radius: var(--r-sm);
  background: transparent;
  padding: 7px 10px;
  font-size: var(--fs-base);
  width: 100%;
}
.menu-list button:hover,
.menu-list button:focus-visible {
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  color: var(--text);
  outline: none;
}
.menu-sep { height: 1px; background: var(--border); margin: 4px 2px; }

main { display: flex; flex: 1; min-height: 0; }

.pane { min-width: 0; position: relative; }
.editor-pane {
  display: flex;
  flex-direction: row;
  width: var(--editor-w, 44%);
  flex: none;
}
.editor-col {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-width: 0;
}

/* Editor top bar: section label + live diagram-type badge. */
.editor-bar {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 6px 12px;
  border-bottom: 1px solid var(--border);
  background: var(--panel);
}
.editor-bar-label {
  font-size: var(--fs-2xs);
  font-weight: 600;
  letter-spacing: 0.08em;
  color: var(--dim);
}
.type-badge {
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.02em;
  padding: 2px 9px;
  border-radius: var(--r-pill);
  border: 1px solid var(--border);
  background: var(--bg);
  color: var(--dim);
  font-variant: small-caps;
  transition: color 0.12s, border-color 0.12s, background 0.12s;
}
.type-badge[data-type]:not([data-type=""]) {
  color: var(--accent);
  border-color: color-mix(in srgb, var(--accent) 45%, var(--border));
  background: color-mix(in srgb, var(--accent) 9%, var(--bg));
}

/* Scroll host pairs a synced line-number gutter with the textarea. */
.editor-scroll {
  flex: 1;
  display: flex;
  min-height: 0;
  overflow: hidden;
  position: relative;
  background: var(--bg);
}
.gutter {
  flex: none;
  width: 44px;
  padding: 14px 8px 14px 0;
  text-align: right;
  font: 13.5px/1.55 var(--mono);
  color: var(--dim);
  background: var(--panel);
  border-right: 1px solid var(--border);
  user-select: none;
  overflow: hidden;
  white-space: pre;
  opacity: 0.7;
}
.gutter .gl.active { color: var(--accent); opacity: 1; font-weight: 600; }
.gutter .gl.has-issue { position: relative; }
.gutter .gl.has-issue::after {
  content: "";
  position: absolute;
  right: 1px;
  top: 50%;
  transform: translateY(-50%);
  width: 5px;
  height: 5px;
  border-radius: var(--r-circle);
  background: var(--error);
}
.gutter .gl.has-issue.warn-issue::after { background: var(--warn-mark); }

/* ---------------- inline diagnostics (U21) ---------------- */
/* A non-interactive overlay laid over the textarea text area (right of the
   44px gutter). Each diagnostic gets a wavy underline drawn on the offending
   line; the marker itself is clickable to jump / show a quick-fix. The layer
   pointer-events:none, the markers re-enable pointer-events. */
.squiggles {
  position: absolute;
  top: 0;
  left: 44px;
  right: 0;
  bottom: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 2;
}
.squiggle {
  position: absolute;
  height: 21px;          /* one line-height (13.5px * 1.55 ≈ 21px) */
  pointer-events: none;  /* underline never blocks caret/selection */
  /* wavy red underline at the text baseline */
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='6' height='3'><path d='M0 2 Q1.5 0 3 2 T6 2' fill='none' stroke='%23dc2626' stroke-width='0.9'/></svg>");
  background-repeat: repeat-x;
  background-position: left bottom 2px;
}
.squiggle.warn {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='6' height='3'><path d='M0 2 Q1.5 0 3 2 T6 2' fill='none' stroke='%23d97706' stroke-width='0.9'/></svg>");
}
.squiggle-flag {
  /* a small clickable flag badge sitting at the end of the underlined line */
  position: absolute;
  right: -16px;
  top: 50%;
  transform: translateY(-50%);
  font: 700 9px/1 var(--mono);
  color: var(--on-accent);
  background: var(--error);
  border: none;
  border-radius: var(--r-circle);
  width: 14px;
  height: 14px;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0.9;
  cursor: pointer;
  pointer-events: auto;
}
.squiggle.warn .squiggle-flag { background: var(--warn-mark); }
.squiggle-flag:hover { opacity: 1; transform: translateY(-50%) scale(1.14); }

/* The quick-fix popover anchored under a clicked diagnostic. */
.quickfix {
  position: absolute;
  z-index: 30;
  min-width: 220px;
  max-width: 340px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  box-shadow: var(--shadow-pop);
  padding: 10px 12px;
  font-size: var(--fs-sm);
  color: var(--text);
}
.quickfix-msg { display: block; margin-bottom: 8px; line-height: 1.4; }
.quickfix-msg .qf-line { color: var(--dim); font-family: var(--mono); }
.quickfix-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.quickfix-btn {
  border: 1px solid var(--accent);
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  color: var(--accent);
  border-radius: var(--r-sm);
  padding: 5px 10px;
  font-size: var(--fs-sm);
  font-weight: 600;
  cursor: pointer;
}
.quickfix-btn:hover { background: color-mix(in srgb, var(--accent) 26%, transparent); }
.quickfix-btn.secondary {
  border-color: var(--border);
  background: transparent;
  color: var(--dim);
  font-weight: 500;
}
.quickfix-btn.secondary:hover { color: var(--text); border-color: var(--accent); }
.quickfix-fix-preview {
  display: block;
  margin: 4px 0 8px;
  padding: 5px 8px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--r-xs);
  font-family: var(--mono);
  font-size: var(--fs-xs);
  color: var(--ok);
  white-space: pre-wrap;
  word-break: break-word;
}

/* ---------------- shape/snippet palette ---------------- */
.palette {
  flex: none;
  display: flex;
  flex-direction: column;
  width: 146px;
  border-right: 1px solid var(--border);
  background: var(--panel);
  overflow-y: auto;
  scrollbar-width: thin;
  transition: width 0.18s ease;
}
.palette.collapsed { width: 34px; }
.palette.collapsed .palette-body { display: none; }
.palette-toggle {
  flex: none;
  align-self: flex-end;
  margin: 6px 6px 2px;
  width: 22px;
  height: 22px;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: var(--bg);
  color: var(--dim);
  cursor: pointer;
  font-size: var(--fs-sm);
  line-height: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}
.palette-toggle:hover { color: var(--accent); border-color: var(--accent); }
.palette.collapsed .palette-toggle { align-self: center; margin: 6px auto; }
.palette-body { padding: 4px 8px 12px; }
.palette-hint {
  font-size: var(--fs-2xs);
  line-height: 1.35;
  color: var(--dim);
  padding: 2px 4px 8px;
  opacity: 0.85;
}
.palette-group { margin-bottom: 12px; }
.palette-group-title {
  font-size: var(--fs-2xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--dim);
  padding: 4px 4px 6px;
}
.palette-item {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 6px 8px;
  margin-bottom: 3px;
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  background: var(--bg);
  color: var(--text);
  cursor: pointer;
  font: inherit;
  font-size: var(--fs-sm);
  text-align: left;
  transition: border-color 0.1s, background 0.1s, transform 0.06s;
}
.palette-item:hover {
  border-color: var(--pi, var(--accent));
  background: color-mix(in srgb, var(--pi, var(--accent)) 8%, var(--bg));
}
.palette-item:active { transform: translateY(1px); }
.palette-item:focus-visible { outline: 2px solid var(--pi, var(--accent)); outline-offset: 1px; }
.pi-glyph {
  flex: none;
  width: 18px;
  text-align: center;
  font-size: var(--fs-lg);
  color: var(--pi, var(--accent));
}
/* Per-shape glyph hues — match the engine's role colors so the palette is a
   legend, not grey monotony. */
.palette-item[data-snip="rect"]     { --pi: #3b82f6; }
.palette-item[data-snip="rounded"]  { --pi: #3b82f6; }
.palette-item[data-snip="stadium"]  { --pi: #10b981; }
.palette-item[data-snip="decision"] { --pi: #06b6d4; }
.palette-item[data-snip="database"] { --pi: #8b5cf6; }
.palette-item[data-snip="queue"]    { --pi: #f59e0b; }
.palette-item[data-snip="circle"]   { --pi: #ec4899; }
.palette-item[data-snip="subgraph"] { --pi: #64748b; }
.palette-item[data-snip="arrow"]    { --pi: #6b7280; }
.palette-item[data-snip="labeled"]  { --pi: #3b82f6; }
.palette-item[data-snip="dashed"]   { --pi: #8b5cf6; }
.palette-item[data-snip="thick"]    { --pi: #ef4444; }
.pi-label { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* Infra icon grid: clickable tiles, each showing the real inline SVG glyph. */
.palette-infra { display: flex; flex-direction: column; }
/* Sub-category header inside the Infra group (Compute, Storage, …): a colored
   dot + label so each category reads at a glance. `--cat` is set per header. */
.palette-cat-title {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: var(--fs-2xs);
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--cat, var(--dim));
  padding: 9px 2px 5px;
}
.palette-cat-title:first-child { padding-top: 2px; }
.palette-cat-dot {
  flex: none;
  width: 7px;
  height: 7px;
  border-radius: var(--r-xs);
  background: var(--cat, var(--dim));
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--cat, var(--dim)) 22%, transparent);
}
.palette-icon-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 5px;
}
.palette-icon {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  padding: 8px 4px 6px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  /* A whisper of the category color in the tile background. */
  background:
    linear-gradient(color-mix(in srgb, var(--cat, var(--accent)) 5%, var(--bg)),
                    color-mix(in srgb, var(--cat, var(--accent)) 5%, var(--bg)));
  color: var(--cat, var(--accent));
  cursor: pointer;
  font: inherit;
  transition: border-color 0.1s, background 0.1s, transform 0.06s, box-shadow 0.1s;
}
.palette-icon:hover {
  border-color: var(--cat, var(--accent));
  background: color-mix(in srgb, var(--cat, var(--accent)) 13%, var(--bg));
  box-shadow: 0 2px 8px color-mix(in srgb, var(--cat, var(--accent)) 22%, transparent);
}
.palette-icon:active { transform: translateY(1px); }
.palette-icon:focus-visible { outline: 2px solid var(--cat, var(--accent)); outline-offset: 1px; }
.pi-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  color: var(--cat, var(--accent));
}
.pi-icon svg { display: block; width: 22px; height: 22px; }
.pi-name {
  font-size: var(--fs-2xs);
  line-height: 1.1;
  color: var(--dim);
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}
.palette-icon:hover .pi-name { color: var(--text); }

/* Larger hover preview: a popover to the right of the tile with a big glyph. */
.pi-preview {
  position: absolute;
  left: calc(100% + 8px);
  top: 50%;
  transform: translateY(-50%) scale(0.9);
  transform-origin: left center;
  z-index: 30;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  width: 96px;
  padding: 12px 10px 10px;
  border: 1px solid color-mix(in srgb, var(--cat, var(--accent)) 45%, var(--border));
  border-radius: var(--r-xl);
  background: var(--panel);
  box-shadow: var(--shadow-pop);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.12s ease, transform 0.12s ease;
}
.palette-icon:hover .pi-preview,
.palette-icon:focus-visible .pi-preview {
  opacity: 1;
  transform: translateY(-50%) scale(1);
}
.pi-preview-glyph {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 56px;
  height: 56px;
  color: var(--cat, var(--accent));
  background: color-mix(in srgb, var(--cat, var(--accent)) 12%, var(--bg));
  border-radius: var(--r-xl);
}
.pi-preview-glyph svg { display: block; width: 44px; height: 44px; }
.pi-preview-label {
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text);
  text-align: center;
  line-height: 1.15;
}
/* The narrow collapsed palette has no room for the popover. */
.palette.collapsed .pi-preview { display: none; }

#splitter {
  flex: none;
  width: 5px;
  cursor: col-resize;
  background: var(--border);
  transition: background 0.15s;
}
#splitter:hover, #splitter.dragging { background: var(--accent); }
#splitter:focus-visible { background: var(--accent); outline: 2px solid var(--accent); outline-offset: -1px; }

.preview-pane { flex: 1; }

#editor {
  flex: 1;
  min-width: 0;
  width: 100%;
  border: 0;
  resize: none;
  outline: none;
  padding: 14px 16px;
  font: 13.5px/1.55 var(--mono);
  background: var(--bg);
  color: var(--text);
  tab-size: 2;
  white-space: pre;
  overflow: auto;
}

.status {
  flex: none;
  padding: 6px 16px;
  font-size: var(--fs-sm);
  font-family: var(--mono);
  border-top: 1px solid var(--border);
  background: var(--panel);
  max-height: 64px;
  overflow-y: auto;
}
.status.ok { color: var(--ok); }
.status.err { color: var(--error); }
.status.warn { color: var(--warn); }

/* Pannable, zoomable canvas with a dot grid like draw.io */
#viewport {
  position: absolute;
  inset: 0;
  overflow: hidden;
  cursor: grab;
  background-color: var(--canvas);
  background-image: radial-gradient(var(--dots) 1.2px, transparent 1.2px);
  background-size: 22px 22px;
}
#viewport.panning { cursor: grabbing; }
#viewport:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
/* Drop target highlight while dragging a palette item over the canvas. */
#viewport.drag-over {
  cursor: copy;
  box-shadow: inset 0 0 0 2px var(--accent),
    inset 0 0 0 9999px color-mix(in srgb, var(--accent) 7%, transparent);
}
/* The palette item being dragged lifts and dims to signal liftoff. */
.palette-item.dragging, .palette-icon.dragging {
  opacity: 0.4;
  border-color: var(--accent);
}
.palette-item, .palette-icon { -webkit-user-drag: element; }
/* While a palette drag is in flight, suppress text selection everywhere. */
body.dragging-palette { cursor: grabbing; user-select: none; -webkit-user-select: none; }

/* ---------------- palette drag ghost + drop indicator ---------------- */
/* A floating preview that follows the cursor during a palette drag. */
.drag-ghost {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 400;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 12px 7px 9px;
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--panel);
  color: var(--text);
  font-size: var(--fs-sm);
  font-weight: 600;
  box-shadow: var(--shadow-pop);
  pointer-events: none;
  opacity: 0;
  transform: translate(-9999px, -9999px);
  transition: opacity 0.12s ease, border-color 0.12s ease, box-shadow 0.12s ease;
  will-change: transform;
}
.drag-ghost.show { opacity: 0.96; }
.drag-ghost.over-canvas {
  border-color: var(--accent);
  box-shadow: 0 10px 28px color-mix(in srgb, var(--accent) 30%, var(--scrim));
}
.drag-ghost-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 24px;
  height: 24px;
  color: var(--accent);
}
.drag-ghost-icon svg { display: block; width: 22px; height: 22px; }
.drag-ghost-glyph { font-size: var(--fs-h2); color: var(--accent); }
.drag-ghost-label { white-space: nowrap; }

/* A dashed placeholder shown inside the viewport at the exact drop point. */
.drop-indicator {
  position: absolute;
  z-index: 6;
  width: 116px;
  height: 46px;
  margin-left: -58px;
  margin-top: -23px;
  border: 2px dashed var(--accent);
  border-radius: var(--r-lg);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  opacity: 0;
  transform: scale(0.92);
  transition: opacity 0.1s ease, transform 0.1s ease;
}
.drop-indicator.show { opacity: 1; transform: scale(1); }
.drop-indicator-label {
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--accent);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 104px;
}
#preview {
  position: absolute;
  transform-origin: 0 0;
  will-change: transform;
}
/* Smooth, programmatic zoom only — toggled per-interaction in app.js.
   Panning never carries this class, so dragging stays 1:1 with the cursor. */
#preview.zooming { transition: transform 0.2s cubic-bezier(0.22, 0.61, 0.36, 1); }
#preview svg {
  display: block;
  /* Nodes dragged beyond the original viewBox must stay visible —
     SVG clips to its viewport by default. */
  overflow: visible;
}

/* ---------------- node & edge visual polish (U19) ---------------- */
/* Subtle, draw.io/Excalidraw-grade depth: soft drop-shadows on every node,
   smoothly mitred edge joins, and a tasteful lift on hover. Applied purely in
   CSS over the engine's SVG so it works for every diagram type and theme. */
#preview svg [data-node] {
  filter: var(--node-shadow);
  transition: filter 0.14s ease;
}
/* Cluster/subgraph containers read as flat surfaces, not floating cards. */
#preview svg [data-node]:hover {
  filter: var(--node-shadow-hover);
}
/* Round every stroked path's joins/caps so arrows and connectors look smooth
   instead of hard-mitred. Cheap, universal, and reversible. */
#preview svg [data-edge] path {
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* Node shape outlines get rounded joins too (diamonds, hexagons, cylinders). */
#preview svg [data-node] path,
#preview svg [data-node] polygon,
#preview svg [data-node] rect {
  stroke-linejoin: round;
}

.zoom-controls {
  position: absolute;
  bottom: 14px;
  right: 14px;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 4px;
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--panel);
  box-shadow: var(--shadow-sm);
}
.zoom-controls button {
  font: inherit;
  font-size: var(--fs-md);
  width: 28px;
  height: 28px;
  border: 0;
  border-radius: var(--r-sm);
  background: transparent;
  color: var(--text);
  cursor: pointer;
}
.zoom-controls button:hover { background: var(--border); }
#zoom-fit { width: auto; padding: 0 9px; font-size: var(--fs-sm); }
#zoom-level {
  font-size: var(--fs-xs);
  color: var(--dim);
  min-width: 40px;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

@media (max-width: 760px) {
  header { gap: 8px; padding: 7px 10px; }
  .switcher { flex: 0 1 auto; }
  .new-current { display: none; }
  .actions { flex-wrap: wrap; gap: 5px; }
  .actions button { font-size: var(--fs-sm); padding: 5px 9px; }
  main { flex-direction: column; }
  /* Stack editor over preview; each gets a usable half of the viewport. */
  .editor-pane { width: 100% !important; height: 48%; min-height: 160px; border-right: none; border-bottom: 1px solid var(--border); }
  .preview-pane { flex: 1; min-height: 200px; }
  #splitter { display: none; }
  /* Collapse the palette to its toggle so the editor keeps full width; users
     can expand it on demand. */
  .palette { position: absolute; z-index: 8; height: auto; max-height: 100%; box-shadow: 2px 0 12px rgba(0,0,0,0.18); }
  .palette.collapsed { box-shadow: none; }
}
[data-node]:hover > * { filter: brightness(0.96); }

#viewport.pan-mode, #viewport.pan-mode [data-node] { cursor: grab; }
#viewport.pan-mode.panning { cursor: grabbing; }

[data-node] { cursor: move; }

/* ---------------- minimap (bottom-left of preview) ---------------- */
.minimap {
  position: absolute;
  left: 14px;
  bottom: 14px;
  width: 190px;
  height: 130px;
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: color-mix(in srgb, var(--panel) 85%, transparent);
  backdrop-filter: blur(6px);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
  cursor: pointer;
  z-index: 5;
}
.minimap[hidden] { display: none; }
#minimap-canvas {
  position: absolute;
  inset: 0;
}
#minimap-canvas svg {
  position: absolute;
  display: block;
  pointer-events: none;
}
#minimap-view {
  position: absolute;
  border: 1.5px solid var(--accent);
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  border-radius: var(--r-xs);
  pointer-events: none;
  box-shadow: 0 0 0 9999px color-mix(in srgb, var(--bg) 28%, transparent);
}
.minimap.dragging { cursor: grabbing; }
@media (max-width: 760px) { .minimap { display: none !important; } }
/* ---------------- empty state (preview onboarding) ---------------- */
.empty-state {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;
  text-align: center;
  padding: 24px;
  color: var(--dim);
  pointer-events: auto;
}
.empty-glyph {
  font-size: 52px;
  line-height: 1;
  color: var(--accent);
  opacity: 0.85;
  margin-bottom: 4px;
  animation: empty-float 3.5s ease-in-out infinite;
}
@keyframes empty-float {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-6px); }
}
.empty-state h2 {
  margin: 0;
  font-size: var(--fs-h1);
  font-weight: 700;
  color: var(--text);
  letter-spacing: -0.01em;
}
.empty-state p { margin: 0; font-size: var(--fs-base); max-width: 360px; }
.empty-cta {
  margin-top: 8px;
  font: inherit;
  font-size: var(--fs-base);
  font-weight: 600;
  padding: 9px 18px;
  border: 0;
  border-radius: var(--r-md);
  background: var(--accent);
  color: var(--on-accent);
  cursor: pointer;
  box-shadow: 0 4px 14px color-mix(in srgb, var(--accent) 35%, transparent);
  transition: transform 0.08s, box-shadow 0.15s, filter 0.12s;
}
.empty-cta:hover { filter: brightness(1.07); box-shadow: 0 6px 20px color-mix(in srgb, var(--accent) 45%, transparent); }
.empty-cta:active { transform: translateY(1px); }
.empty-hint { font-size: var(--fs-sm); opacity: 0.8; margin-top: 6px; }

/* ---------------- examples gallery (modal overlay) ---------------- */
.gallery {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 32px;
}
.gallery[hidden] { display: none; }
.gallery-backdrop {
  position: absolute;
  inset: 0;
  background: color-mix(in srgb, var(--scrim) 52%, transparent);
  backdrop-filter: blur(4px);
  animation: gallery-fade 0.18s ease-out;
}
@keyframes gallery-fade { from { opacity: 0; } to { opacity: 1; } }
.gallery-panel {
  position: relative;
  width: min(1040px, 100%);
  max-height: 88vh;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--r-2xl);
  box-shadow: var(--shadow-xl);
  overflow: hidden;
  animation: gallery-pop 0.2s cubic-bezier(0.22, 0.61, 0.36, 1);
}
@keyframes gallery-pop {
  from { opacity: 0; transform: translateY(10px) scale(0.985); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}
.gallery-head {
  flex: none;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 16px;
  padding: 20px 24px 16px;
  border-bottom: 1px solid var(--border);
}
.gallery-head h2 { margin: 0; font-size: var(--fs-h2); font-weight: 700; color: var(--text); letter-spacing: -0.01em; }
.gallery-sub { margin: 4px 0 0; font-size: var(--fs-base); color: var(--dim); }
.gallery-close {
  flex: none;
  width: 32px;
  height: 32px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--panel);
  color: var(--dim);
  cursor: pointer;
  font-size: var(--fs-md);
  line-height: 1;
}
.gallery-close:hover { color: var(--text); border-color: var(--accent); }
.gallery-grid {
  flex: 1;
  overflow-y: auto;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 14px;
  padding: 20px 24px;
  scrollbar-width: thin;
}
.gallery-card {
  display: flex;
  flex-direction: column;
  border: 1px solid var(--border);
  border-radius: var(--r-xl);
  background: var(--panel);
  cursor: pointer;
  overflow: hidden;
  padding: 0;
  text-align: left;
  font: inherit;
  transition: border-color 0.12s, transform 0.08s, box-shadow 0.15s;
}
.gallery-card:hover {
  border-color: var(--accent);
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
}
.gallery-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.gallery-card.featured {
  grid-column: span 2;
  border-color: color-mix(in srgb, var(--accent) 40%, var(--border));
}
.gallery-card.featured .gallery-meta {
  position: relative;
  background: linear-gradient(color-mix(in srgb, var(--accent) 7%, var(--panel)), var(--panel));
}
/* A small "Showcase" badge marks the rich architecture examples. */
.gallery-card.featured .gallery-card-title::after {
  content: "Showcase";
  display: inline-block;
  margin-left: 8px;
  padding: 1px 7px;
  font-size: var(--fs-2xs);
  font-weight: 700;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  vertical-align: middle;
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--accent) 35%, var(--border));
  border-radius: var(--r-pill);
}
.gallery-thumb {
  height: 132px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 12px;
  background:
    radial-gradient(var(--dots) 1px, transparent 1px) 0 0 / 16px 16px,
    var(--bg);
  border-bottom: 1px solid var(--border);
  overflow: hidden;
}
.gallery-card.featured .gallery-thumb { height: 168px; }
.gallery-thumb svg { max-width: 100%; max-height: 100%; display: block; }
.gallery-meta { padding: 10px 13px 12px; }
.gallery-card-title { display: block; font-size: var(--fs-base); font-weight: 600; color: var(--text); }
.gallery-card-desc { display: block; font-size: var(--fs-xs); color: var(--dim); margin-top: 2px; }
.gallery-foot {
  flex: none;
  display: flex;
  justify-content: center;
  padding: 14px 24px 18px;
  border-top: 1px solid var(--border);
}
.gallery-blank {
  font: inherit;
  font-size: var(--fs-base);
  padding: 8px 16px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--bg);
  color: var(--dim);
  cursor: pointer;
  transition: color 0.12s, border-color 0.12s;
}
.gallery-blank:hover { color: var(--text); border-color: var(--accent); }
@media (max-width: 760px) {
  .gallery { padding: 12px; }
  .gallery-card.featured { grid-column: span 1; }
  .gallery-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
}

/* ---------------- command palette (Cmd/Ctrl+K) ---------------- */
.cmdk {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 14vh 16px 16px;
}
.cmdk[hidden] { display: none; }
.cmdk-backdrop {
  position: absolute;
  inset: 0;
  background: color-mix(in srgb, var(--scrim) 48%, transparent);
  backdrop-filter: blur(3px);
  animation: gallery-fade 0.14s ease-out;
}
.cmdk-panel {
  position: relative;
  width: min(560px, 100%);
  max-height: 60vh;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--r-2xl);
  box-shadow: var(--shadow-xl);
  overflow: hidden;
  animation: cmdk-pop 0.15s cubic-bezier(0.22, 0.61, 0.36, 1);
}
@keyframes cmdk-pop {
  from { opacity: 0; transform: translateY(-8px) scale(0.985); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}
.cmdk-search {
  flex: none;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 13px 16px;
  border-bottom: 1px solid var(--border);
}
.cmdk-search-icon { color: var(--accent); font-size: var(--fs-lg); flex: none; }
#cmdk-input {
  flex: 1;
  min-width: 0;
  border: 0;
  outline: none;
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: var(--fs-lg);
}
#cmdk-input::placeholder { color: var(--dim); }
.cmdk-esc {
  flex: none;
  font: inherit;
  font-size: var(--fs-2xs);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--dim);
  padding: 2px 6px;
  border: 1px solid var(--border);
  border-radius: var(--r-xs);
  background: var(--panel);
}
.cmdk-list {
  flex: 1;
  overflow-y: auto;
  padding: 6px;
  scrollbar-width: thin;
}
.cmdk-item {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 9px 11px;
  border-radius: var(--r-md);
  cursor: pointer;
  color: var(--text);
}
.cmdk-item[hidden] { display: none; }
.cmdk-item.active { background: color-mix(in srgb, var(--accent) 14%, transparent); }
.cmdk-ic {
  flex: none;
  width: 22px;
  text-align: center;
  font-size: var(--fs-md);
  color: var(--accent);
}
.cmdk-text { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.cmdk-title { font-size: var(--fs-base); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.cmdk-desc { font-size: var(--fs-xs); color: var(--dim); margin-top: 1px; }
.cmdk-kbd {
  flex: none;
  font: inherit;
  font-size: var(--fs-xs);
  min-width: 20px;
  text-align: center;
  color: var(--dim);
  padding: 2px 6px;
  border: 1px solid var(--border);
  border-radius: var(--r-xs);
  background: var(--panel);
  font-variant-numeric: tabular-nums;
}
.cmdk-item.active .cmdk-kbd { border-color: color-mix(in srgb, var(--accent) 45%, var(--border)); color: var(--text); }
.cmdk-empty { padding: 24px; text-align: center; color: var(--dim); font-size: var(--fs-base); }
.cmdk-empty[hidden] { display: none; }

/* ---------------- toast (transient feedback, e.g. Share) ---------------- */
.toast {
  position: fixed;
  left: 50%;
  bottom: 28px;
  transform: translate(-50%, 16px);
  z-index: 300;
  max-width: min(560px, 92vw);
  padding: 10px 16px;
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--panel);
  color: var(--text);
  font-size: var(--fs-base);
  box-shadow: var(--shadow-md);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.18s ease, transform 0.18s ease;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.toast.show {
  opacity: 1;
  transform: translate(-50%, 0);
  pointer-events: auto;
}
/* Error toast: red accent + a monospace code line. Wider, wraps long lines. */
.toast.error {
  border-color: color-mix(in srgb, var(--error) 55%, var(--border));
  background: color-mix(in srgb, var(--error) 8%, var(--panel));
  white-space: normal;
  cursor: pointer;
  max-width: min(620px, 94vw);
}
.toast .toast-title {
  display: block;
  font-weight: 600;
  color: var(--error);
  margin-bottom: 3px;
}
.toast .toast-code {
  display: block;
  font-family: var(--mono);
  font-size: var(--fs-sm);
  color: var(--text);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  padding: 4px 8px;
  margin-top: 4px;
  white-space: pre-wrap;
  word-break: break-word;
}
.toast .toast-hint { display: block; font-size: var(--fs-xs); color: var(--dim); margin-top: 5px; }
/* Warning variant: amber accent (rendered but skipped lines, not a hard error). */
.toast.error.is-warn {
  border-color: color-mix(in srgb, var(--warn-mark) 55%, var(--border));
  background: color-mix(in srgb, var(--warn-mark) 8%, var(--panel));
}
.toast.error.is-warn .toast-title { color: var(--warn); }

/* ---------------- help dialog (? button / command palette) ---------------- */
.help {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 32px;
}
.help[hidden] { display: none; }
.help-backdrop {
  position: absolute;
  inset: 0;
  background: color-mix(in srgb, var(--bg) 55%, transparent);
  backdrop-filter: blur(3px);
}
.help-panel {
  position: relative;
  width: min(760px, 96vw);
  max-height: 88vh;
  overflow-y: auto;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--r-2xl);
  box-shadow: var(--shadow-xl);
  padding: 22px 24px 24px;
  animation: help-in 0.16s ease;
}
@keyframes help-in { from { opacity: 0; transform: translateY(8px); } }
.help-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.help-head h2 { margin: 0 0 3px; font-size: var(--fs-h2); }
.help-sub { margin: 0; font-size: var(--fs-sm); color: var(--dim); }
.help-close {
  flex: none;
  width: 30px;
  height: 30px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--panel);
  color: var(--dim);
  font-size: var(--fs-md);
  cursor: pointer;
}
.help-close:hover { color: var(--text); border-color: var(--accent); }
.help-close:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.help-body {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 26px;
  margin-top: 18px;
}
.help-col h3 {
  margin: 0 0 10px;
  font-size: var(--fs-xs);
  letter-spacing: 0.07em;
  text-transform: uppercase;
  color: var(--dim);
}
.help-keys { display: grid; grid-template-columns: auto 1fr; gap: 7px 14px; margin: 0; }
.help-keys dt { white-space: nowrap; }
.help-keys dd { margin: 0; font-size: var(--fs-base); color: var(--text); }
.help-keys kbd, .help-list kbd {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  padding: 2px 6px;
  border: 1px solid var(--border);
  border-bottom-width: 2px;
  border-radius: var(--r-xs);
  background: var(--panel);
  color: var(--text);
}
.help-code {
  margin: 0 0 12px;
  padding: 12px 14px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  font-family: var(--mono);
  font-size: var(--fs-sm);
  line-height: 1.55;
  color: var(--text);
  overflow-x: auto;
  white-space: pre;
}
.help-list { margin: 0; padding-left: 18px; font-size: var(--fs-sm); line-height: 1.7; color: var(--text); }
.help-list code {
  font-family: var(--mono);
  font-size: var(--fs-xs);
  padding: 1px 5px;
  background: var(--panel);
  border: 1px solid var(--border);
  border-radius: var(--r-xs);
}
.help-foot { margin: 12px 0 0; font-size: var(--fs-sm); color: var(--dim); }
@media (max-width: 680px) {
  .help-body { grid-template-columns: 1fr; gap: 20px; }
  .help-panel { padding: 18px; }
}

/* ---------------- theme editor (U20) ---------------- */
.theme-dialog {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.theme-dialog[hidden] { display: none; }
.theme-backdrop {
  position: absolute;
  inset: 0;
  background: color-mix(in srgb, var(--scrim) 52%, transparent);
  backdrop-filter: blur(4px);
  animation: gallery-fade 0.18s ease-out;
}
.theme-panel {
  position: relative;
  width: min(560px, 100%);
  max-height: 88vh;
  overflow-y: auto;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--r-2xl);
  box-shadow: var(--shadow-xl);
  padding: 22px 24px 24px;
  animation: gallery-pop 0.2s cubic-bezier(0.22, 0.61, 0.36, 1);
}
.theme-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.theme-head h2 { margin: 0 0 3px; font-size: var(--fs-h2); }
.theme-sub { margin: 0; font-size: var(--fs-sm); color: var(--dim); }
.theme-close {
  flex: none;
  width: 32px;
  height: 32px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--panel);
  color: var(--dim);
  cursor: pointer;
  font-size: var(--fs-md);
  line-height: 1;
}
.theme-close:hover { color: var(--text); border-color: var(--accent); }
.theme-close:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.theme-body { margin-top: 16px; display: flex; flex-direction: column; gap: 20px; }
.theme-body h3 {
  margin: 0 0 10px;
  font-size: var(--fs-xs);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--dim);
}
.theme-presets {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(96px, 1fr));
  gap: 10px;
}
.theme-preset {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 7px;
  padding: 10px 8px;
  border: 1.5px solid var(--border);
  border-radius: var(--r-xl);
  background: var(--panel);
  color: var(--text);
  font: inherit;
  font-size: var(--fs-sm);
  cursor: pointer;
  transition: border-color 0.12s, transform 0.08s, box-shadow 0.12s;
}
.theme-preset:hover { border-color: var(--accent); transform: translateY(-1px); }
.theme-preset:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.theme-preset.active {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 22%, transparent);
}
.theme-swatch {
  position: relative;
  width: 48px;
  height: 36px;
  border-radius: var(--r-md);
  border: 1px solid var(--border);
  overflow: hidden;
}
.theme-swatch-dot {
  position: absolute;
  right: 6px;
  bottom: 6px;
  width: 14px;
  height: 14px;
  border-radius: var(--r-circle);
  box-shadow: 0 0 0 2px rgba(255,255,255,0.55);
}
.theme-preset-name { font-weight: 600; }
.theme-custom { display: flex; flex-direction: column; gap: 12px; }
.theme-field {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  font-size: var(--fs-base);
}
.theme-field > span:first-child { color: var(--text); font-weight: 500; }
.theme-field select {
  font: inherit;
  font-size: var(--fs-base);
  padding: 6px 10px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--panel);
  color: var(--text);
  min-width: 180px;
  cursor: pointer;
}
.theme-field select:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.theme-color-wrap { display: flex; align-items: center; gap: 8px; }
.theme-color-wrap input[type="color"] {
  width: 36px;
  height: 30px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--panel);
  cursor: pointer;
}
.theme-hex {
  font: inherit;
  font-family: var(--mono);
  font-size: var(--fs-sm);
  width: 92px;
  padding: 6px 8px;
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  background: var(--panel);
  color: var(--text);
  text-transform: lowercase;
}
.theme-hex:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
@media (max-width: 520px) {
  .theme-field { flex-direction: column; align-items: stretch; }
  .theme-field select, .theme-color-wrap { width: 100%; }
}

/* ---------------- onboarding tour (U23) ---------------- */
/* A first-visit guided walk-through: a dimming veil with a bright spotlight
   cut-out over the current target, plus a floating coachmark with Next/Skip.
   The veil + spot + coach are positioned imperatively by app.js. */
.tour {
  position: fixed;
  inset: 0;
  z-index: 600;          /* above every dialog (help/theme/gallery/cmdk) */
  pointer-events: none;  /* only interactive parts opt back in */
}
.tour[hidden] { display: none; }

/* Full-screen scrim. Clicking it skips the tour. */
.tour-veil {
  position: absolute;
  inset: 0;
  background: color-mix(in srgb, var(--scrim) 30%, transparent);
  backdrop-filter: blur(1px);
  pointer-events: auto;
  cursor: pointer;
  animation: tour-fade 0.2s ease-out;
}
@keyframes tour-fade { from { opacity: 0; } }

/* The spotlight: a transparent box whose enormous box-shadow paints the dim
   over everything outside it, leaving the target crisp and highlighted. */
.tour-spot {
  position: absolute;
  border-radius: var(--r-xl);
  pointer-events: none;
  box-shadow:
    0 0 0 9999px color-mix(in srgb, var(--scrim) 56%, transparent),
    0 0 0 2px color-mix(in srgb, var(--accent) 70%, transparent),
    0 0 22px 4px color-mix(in srgb, var(--accent) 40%, transparent);
  transition: left 0.28s cubic-bezier(0.22, 1, 0.36, 1),
              top 0.28s cubic-bezier(0.22, 1, 0.36, 1),
              width 0.28s cubic-bezier(0.22, 1, 0.36, 1),
              height 0.28s cubic-bezier(0.22, 1, 0.36, 1);
}

/* The coachmark card. */
.tour-coach {
  position: absolute;
  pointer-events: auto;
  width: min(340px, calc(100vw - 32px));
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--r-2xl);
  box-shadow: var(--shadow-lg);
  padding: 16px 18px 14px;
  animation: tour-pop 0.2s cubic-bezier(0.22, 1, 0.36, 1);
  transition: left 0.28s cubic-bezier(0.22, 1, 0.36, 1),
              top 0.28s cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes tour-pop { from { opacity: 0; transform: scale(0.96); } }

/* Little arrow pointing from the coach toward the spotlight. */
.tour-coach-arrow {
  position: absolute;
  width: 12px;
  height: 12px;
  background: var(--bg);
  border: 1px solid var(--border);
  transform: rotate(45deg);
}
.tour-coach[data-placement="right"] .tour-coach-arrow { border-right: none; border-top: none; }
.tour-coach[data-placement="left"] .tour-coach-arrow { border-left: none; border-bottom: none; }
.tour-coach[data-placement="bottom"] .tour-coach-arrow { border-bottom: none; border-right: none; }
.tour-coach[data-placement="top"] .tour-coach-arrow { border-top: none; border-left: none; }

.tour-coach-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 6px;
}
.tour-step-count {
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  color: var(--accent);
  text-transform: uppercase;
}
.tour-skip {
  border: none;
  background: none;
  color: var(--dim);
  font-size: var(--fs-sm);
  cursor: pointer;
  padding: 2px 4px;
  border-radius: var(--r-sm);
}
.tour-skip:hover { color: var(--text); }
.tour-skip:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.tour-coach-title { margin: 0 0 6px; font-size: var(--fs-h3); font-weight: 700; color: var(--text); letter-spacing: -0.01em; }
.tour-coach-body { margin: 0 0 12px; font-size: var(--fs-base); line-height: 1.55; color: var(--dim); }

.tour-dots { display: flex; gap: 6px; margin-bottom: 12px; }
.tour-dot {
  width: 7px;
  height: 7px;
  border-radius: var(--r-circle);
  background: var(--border);
  transition: background 0.2s, transform 0.2s;
}
.tour-dot.active { background: var(--accent); transform: scale(1.25); }

.tour-coach-foot { display: flex; justify-content: flex-end; gap: 8px; }
.tour-btn {
  font: inherit;
  font-size: var(--fs-base);
  font-weight: 600;
  padding: 7px 14px;
  border-radius: var(--r-md);
  border: 1px solid var(--border);
  cursor: pointer;
}
.tour-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.tour-btn-ghost { background: var(--panel); color: var(--text); }
.tour-btn-ghost:hover:not(:disabled) { border-color: var(--accent); }
.tour-btn-ghost:disabled { opacity: 0.4; cursor: default; }
.tour-btn-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--on-accent);
}
.tour-btn-primary:hover { background: color-mix(in srgb, var(--accent) 85%, #000); }

/* Floating "replay the tour" compass button (bottom-left of the viewport). */
.tour-fab {
  position: fixed;
  left: 16px;
  bottom: 16px;
  z-index: 90;
  width: 40px;
  height: 40px;
  border-radius: var(--r-circle);
  border: 1px solid var(--border);
  background: var(--panel);
  color: var(--text);
  font-size: var(--fs-h2);
  line-height: 1;
  cursor: pointer;
  box-shadow: var(--shadow-sm);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: transform 0.15s, border-color 0.15s, background 0.15s;
}
.tour-fab[hidden] { display: none; }
.tour-fab:hover { transform: translateY(-2px) scale(1.05); border-color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, var(--panel)); }
.tour-fab:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* "Take the guided tour" button inside the Help dialog. */
.tour-replay-btn {
  margin-top: 16px;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font: inherit;
  font-size: var(--fs-base);
  font-weight: 600;
  padding: 8px 14px;
  border-radius: var(--r-md);
  border: 1px solid var(--accent);
  background: color-mix(in srgb, var(--accent) 10%, var(--bg));
  color: var(--accent);
  cursor: pointer;
}
.tour-replay-btn:hover { background: color-mix(in srgb, var(--accent) 18%, var(--bg)); }
.tour-replay-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }

@media (max-width: 760px) {
  .tour-fab { left: 12px; bottom: 12px; }
}
