:root{
    --toolbar-bg:#23201b; --toolbar-text:#fff;
    --paper:#f4efe6; --paper-2:#efe8db; --ink:#23201b; --ink-soft:#6b6357;
    --line:#d8cfbf; --line-2:#c8bda8;
    --accent:#e0613a; --accent-deep:#b8451f; --teal:#2f6f6a;
    --chrome:#fbf8f2; --chrome-edge:#e7ddcc;
    --node-bg:#ffffff; --node-ink:#23201b;
    /* The map cards' fill. Every theme's --node-bg is its "surface" colour
       and is reused by dialogs, panels and inputs; the cards read this
       derived variable instead, and the per-map "nodeBg" theme setting
       writes ONLY this one (applyThemeConfigVars) - so a translucent card
       colour, e.g. #ffffff80 over a look's texture, never bleeds into the
       Preferences card or the sign-in form. */
    --card-bg:var(--node-bg);
    --canvas-dot:#d8cfbf;
    --stage-glow:rgba(255,255,255,.5);
    --link:#b8451f;
    /* Universal hover tint: overlays the ink colour, so it darkens light
       surfaces and lightens dark surfaces - always a visible delta. */
    --hover:color-mix(in srgb, var(--ink) 12%, transparent);
    --hover-strong:color-mix(in srgb, var(--ink) 20%, transparent);
    --shadow:0 2px 4px rgba(40,30,15,.06),0 8px 24px rgba(40,30,15,.10);
    --shadow-lg:0 10px 40px rgba(40,30,15,.18);
    --r:14px;
    --sans:"Bricolage Grotesque",system-ui,sans-serif;
    --serif:"Fraunces",Georgia,serif;
  }
  /* ===== Themes ===== */
  :root[data-theme="dark"]{
    --toolbar-bg:#f3f3f3; --toolbar-text:#1e1e1e;
    --paper:#1e1e1e; --paper-2:#252526; --ink:#d4d4d4; --ink-soft:#9d9d9d;
    --line:#3c3c3c; --line-2:#4a4a4a;
    --accent:#3794ff; --accent-deep:#1f6fdc; --teal:#4ec9b0;
    --chrome:#252526; --chrome-edge:#3c3c3c;
    --node-bg:#2d2d2d; --node-ink:#d4d4d4;
    --canvas-dot:#3a3a3a;
    --stage-glow:rgba(255,255,255,.04);
    --link:#79b8ff;
    --shadow:0 2px 4px rgba(0,0,0,.30),0 8px 24px rgba(0,0,0,.45);
    --shadow-lg:0 12px 40px rgba(0,0,0,.55);
  }
  :root[data-theme="light-owl"]{   /* Light Owl - github.com/sdras/night-owl-vscode-theme */
    --toolbar-bg:#403f53; --toolbar-text:#fbfbfb;
    --paper:#fbfbfb; --paper-2:#f0f0f0; --ink:#403f53; --ink-soft:#90a7b2;
    --line:#ececec; --line-2:#d9d9d9;
    --accent:#2aa298; --accent-deep:#1f7d75; --teal:#0c969b;
    --chrome:#f0f0f0; --chrome-edge:#e0e0e0;
    --node-bg:#ffffff; --node-ink:#403f53;
    --canvas-dot:#d9d9d9;
    --stage-glow:rgba(255,255,255,.6);
    --link:#288ed7;
    --shadow:0 1px 3px rgba(64,63,83,.10),0 8px 24px rgba(64,63,83,.08);
    --shadow-lg:0 12px 40px rgba(64,63,83,.16);
  }
  :root[data-theme="night-owl"]{   /* Night Owl - github.com/sdras/night-owl-vscode-theme */
    --toolbar-bg:#d6deeb; --toolbar-text:#011627;
    --paper:#011627; --paper-2:#0b2942; --ink:#d6deeb; --ink-soft:#5f7e97;
    --line:#1d3b53; --line-2:#2c5574;
    --accent:#7e57c2; --accent-deep:#6440a5; --teal:#7fdbca;
    --chrome:#011627; --chrome-edge:#1d3b53;
    --node-bg:#0b2942; --node-ink:#d6deeb;
    --canvas-dot:#1d3b53;
    --stage-glow:rgba(126,87,194,.06);
    --link:#82aaff;
    --shadow:0 2px 4px rgba(0,0,0,.30),0 8px 24px rgba(0,0,0,.45);
    --shadow-lg:0 12px 40px rgba(0,0,0,.55);
  }
  :root[data-theme="dracula"]{
    --toolbar-bg:#f8f8f2; --toolbar-text:#282a36;
    --paper:#282a36; --paper-2:#21222c; --ink:#f8f8f2; --ink-soft:#a3a8c0;
    --line:#44475a; --line-2:#6272a4;
    --accent:#ff79c6; --accent-deep:#e857af; --teal:#8be9fd;
    --chrome:#21222c; --chrome-edge:#44475a;
    --node-bg:#44475a; --node-ink:#f8f8f2;
    --canvas-dot:#44475a;
    --stage-glow:rgba(189,147,249,.06);
    --link:#8be9fd;
    --shadow:0 2px 4px rgba(0,0,0,.30),0 8px 24px rgba(0,0,0,.45);
    --shadow-lg:0 12px 40px rgba(0,0,0,.55);
  }
  :root[data-theme="nord"]{
    --toolbar-bg:#eceff4; --toolbar-text:#2e3440;
    --paper:#2e3440; --paper-2:#3b4252; --ink:#eceff4; --ink-soft:#a9b1bf;
    --line:#434c5e; --line-2:#4c566a;
    --accent:#88c0d0; --accent-deep:#5e81ac; --teal:#a3be8c;
    --chrome:#3b4252; --chrome-edge:#434c5e;
    --node-bg:#434c5e; --node-ink:#eceff4;
    --canvas-dot:#434c5e;
    --stage-glow:rgba(143,188,187,.05);
    --link:#88c0d0;
    --shadow:0 2px 4px rgba(0,0,0,.25),0 8px 24px rgba(0,0,0,.40);
    --shadow-lg:0 12px 40px rgba(0,0,0,.55);
  }
  :root[data-theme="catppuccin-dark"]{   /* Catppuccin Mocha - https://github.com/catppuccin/catppuccin */
    --toolbar-bg:#f5e0dc; --toolbar-text:#1e1e2e;
    --paper:#1e1e2e; --paper-2:#181825; --ink:#cdd6f4; --ink-soft:#a6adc8;
    --line:#313244; --line-2:#45475a;
    --accent:#cba6f7; --accent-deep:#a674e0; --teal:#94e2d5;
    --chrome:#181825; --chrome-edge:#313244;
    --node-bg:#313244; --node-ink:#cdd6f4;
    --canvas-dot:#313244;
    --stage-glow:rgba(203,166,247,.05);
    --link:#89b4fa;
    --shadow:0 2px 4px rgba(0,0,0,.30),0 8px 24px rgba(0,0,0,.45);
    --shadow-lg:0 12px 40px rgba(0,0,0,.55);
  }
  :root[data-theme="catppuccin-light"]{   /* Catppuccin Latte - https://github.com/catppuccin/catppuccin */
    --toolbar-bg:#4c4f69; --toolbar-text:#eff1f5;
    --paper:#eff1f5; --paper-2:#e6e9ef; --ink:#4c4f69; --ink-soft:#6c6f85;
    --line:#ccd0da; --line-2:#bcc0cc;
    --accent:#8839ef; --accent-deep:#6c2bc7; --teal:#179299;
    --chrome:#e6e9ef; --chrome-edge:#ccd0da;
    --node-bg:#ffffff; --node-ink:#4c4f69;
    --canvas-dot:#ccd0da;
    --stage-glow:rgba(136,57,239,.04);
    --link:#1e66f5;
    --shadow:0 1px 3px rgba(76,79,105,.12),0 8px 24px rgba(76,79,105,.12);
    --shadow-lg:0 12px 40px rgba(76,79,105,.18);
  }
  :root[data-theme="rose-pine-moon"]{   /* Rosé Pine Moon - https://rosepinetheme.com */
    --toolbar-bg:#e0def4; --toolbar-text:#232136;
    --paper:#232136; --paper-2:#2a273f; --ink:#e0def4; --ink-soft:#908caa;
    --line:#393552; --line-2:#44415a;
    --accent:#c4a7e7; --accent-deep:#a57dd5; --teal:#9ccfd8;
    --chrome:#2a273f; --chrome-edge:#393552;
    --node-bg:#393552; --node-ink:#e0def4;
    --canvas-dot:#2a283e;
    --stage-glow:rgba(196,167,231,.05);
    --link:#c4a7e7;
    --shadow:0 2px 4px rgba(0,0,0,.30),0 8px 24px rgba(0,0,0,.45);
    --shadow-lg:0 12px 40px rgba(0,0,0,.55);
  }
  :root[data-theme="rose-pine-dawn"]{   /* Rosé Pine Dawn - https://rosepinetheme.com */
    --toolbar-bg:#575279; --toolbar-text:#faf4ed;
    --paper:#faf4ed; --paper-2:#f2e9e1; --ink:#575279; --ink-soft:#797593;
    --line:#f2e9e1; --line-2:#dfdad9;
    --accent:#907aa9; --accent-deep:#7a6494; --teal:#56949f;
    --chrome:#faf4ed; --chrome-edge:#f2e9e1;
    --node-bg:#fffaf3; --node-ink:#575279;
    --canvas-dot:#dfdad9;
    --stage-glow:rgba(144,122,169,.04);
    --link:#907aa9;
    --shadow:0 1px 3px rgba(87,82,121,.12),0 8px 24px rgba(87,82,121,.12);
    --shadow-lg:0 12px 40px rgba(87,82,121,.18);
  }
  :root[data-theme="github-dark"]{
    --toolbar-bg:#f0f6fc; --toolbar-text:#0d1117;
    --paper:#0d1117; --paper-2:#161b22; --ink:#e6edf3; --ink-soft:#8b949e;
    --line:#30363d; --line-2:#3d444d;
    --accent:#58a6ff; --accent-deep:#1f6feb; --teal:#3fb950;
    --chrome:#161b22; --chrome-edge:#30363d;
    --node-bg:#161b22; --node-ink:#e6edf3;
    --canvas-dot:#30363d;
    --stage-glow:rgba(88,166,255,.05);
    --link:#58a6ff;
    --shadow:0 2px 4px rgba(0,0,0,.30),0 8px 24px rgba(0,0,0,.45);
    --shadow-lg:0 12px 40px rgba(0,0,0,.55);
  }
  :root[data-theme="github-light"]{
    --toolbar-bg:#24292f; --toolbar-text:#ffffff;
    --paper:#ffffff; --paper-2:#f6f8fa; --ink:#1f2328; --ink-soft:#656d76;
    --line:#d0d7de; --line-2:#afb8c1;
    --accent:#0969da; --accent-deep:#0a5cc0; --teal:#1a7f37;
    --chrome:#f6f8fa; --chrome-edge:#d0d7de;
    --node-bg:#ffffff; --node-ink:#1f2328;
    --canvas-dot:#d8dee4;
    --stage-glow:rgba(9,105,218,.04);
    --link:#0969da;
    --shadow:0 1px 3px rgba(31,35,40,.12),0 8px 24px rgba(31,35,40,.12);
    --shadow-lg:0 12px 40px rgba(31,35,40,.18);
  }
  :root[data-theme="slate-steel"]{   /* Slate & Steel - enterprise cloud monitoring */
    --toolbar-bg:#f8fafc; --toolbar-text:#0f172a;
    --paper:#0f172a; --paper-2:#1e293b; --ink:#cbd5e1; --ink-soft:#64748b;
    --line:#334155; --line-2:#3e4c63;
    --accent:#38bdf8; --accent-deep:#0284c7; --teal:#2dd4bf;
    --chrome:#1e293b; --chrome-edge:#334155;
    --node-bg:#1e293b; --node-ink:#cbd5e1;
    --canvas-dot:#334155;
    --stage-glow:rgba(56,189,248,.05);
    --link:#38bdf8;
    --shadow:0 2px 4px rgba(0,0,0,.30),0 8px 24px rgba(0,0,0,.45);
    --shadow-lg:0 12px 40px rgba(0,0,0,.55);
  }
:root[data-theme="vscode-onedark"]{   /* VSCode One Dark Pro */
    --toolbar-bg:#abb2bf; --toolbar-text:#282c34;
    --paper:#282c34; --paper-2:#21252b; --ink:#abb2bf; --ink-soft:#5c6370;
    --line:#3e4451; --line-2:#4a5261;
    --accent:#98c379; --accent-deep:#50a14f; --teal:#61afef;
    --chrome:#21252b; --chrome-edge:#3e4451;
    --node-bg:#2c323d; --node-ink:#abb2bf;
    --canvas-dot:#3e4451;
    --stage-glow:rgba(152,195,121,.05);
    --link:#61afef;
    --shadow:0 2px 4px rgba(0,0,0,.30),0 8px 24px rgba(0,0,0,.45);
    --shadow-lg:0 12px 40px rgba(0,0,0,.55);
  }
:root[data-theme="monokai-pro"]{   /* VSCode Monokai Pro */
    --toolbar-bg:#fcfcfa; --toolbar-text:#2d2a2e;
    --paper:#2d2a2e; --paper-2:#19181a; --ink:#fcfcfa; --ink-soft:#727072;
    --line:#403e41; --line-2:#504d52;
    --accent:#a9dc76; --accent-deep:#6ca030; --teal:#ffd866;
    --chrome:#19181a; --chrome-edge:#403e41;
    --node-bg:#363337; --node-ink:#fcfcfa;
    --canvas-dot:#403e41;
    --stage-glow:rgba(169,220,118,.05);
    --link:#ff6188;
    --shadow:0 2px 4px rgba(0,0,0,.35),0 8px 24px rgba(0,0,0,.50);
    --shadow-lg:0 12px 40px rgba(0,0,0,.60);
  }
:root[data-theme="amazon-aws"]{   /* Amazon AWS Console */
    --toolbar-bg:#f9fafb; --toolbar-text:#111827;
    --paper:#161e2e; --paper-2:#1f2937; --ink:#d1d5db; --ink-soft:#6b7280;
    --line:#374151; --line-2:#455160;
    --accent:#ff9900; --accent-deep:#ec7211; --teal:#93c5fd;
    --chrome:#1f2937; --chrome-edge:#374151;
    --node-bg:#232f3e; --node-ink:#d1d5db;
    --canvas-dot:#374151;
    --stage-glow:rgba(255,153,0,.05);
    --link:#ff9900;
    --shadow:0 2px 4px rgba(0,0,0,.30),0 8px 24px rgba(0,0,0,.45);
    --shadow-lg:0 12px 40px rgba(0,0,0,.55);
  }
:root[data-theme="synthwave"]{   /* Synthwave '84 Sunset */
    --toolbar-bg:#e2d9f3; --toolbar-text:#1a102f;
    --paper:#1a102f; --paper-2:#281b45; --ink:#e2d9f3; --ink-soft:#9a84b4;
    --line:#483267; --line-2:#5a4080;
    --accent:#00f5d4; --accent-deep:#00c4ac; --teal:#ff71ce;
    --chrome:#281b45; --chrome-edge:#483267;
    --node-bg:#281b45; --node-ink:#e2d9f3;
    --canvas-dot:#483267;
    --stage-glow:rgba(255,113,206,.06);
    --link:#ff71ce;
    --shadow:0 2px 4px rgba(0,0,0,.40),0 8px 24px rgba(0,0,0,.55);
    --shadow-lg:0 12px 40px rgba(0,0,0,.65);
  }
:root[data-theme="matrix-green"]{   /* Matrix Green terminal */
    --toolbar-bg:#d7ffe0; --toolbar-text:#04140b;
    --paper:#030705; --paper-2:#07140b; --ink:#9ef7b2; --ink-soft:#347744;
    --line:#123a1f; --line-2:#1b4b2b;
    --accent:#39ff88; --accent-deep:#1fbf5f; --teal:#a9ffc0;
    --chrome:#07140b; --chrome-edge:#123a1f;
    --node-bg:#0b2414; --node-ink:#9ef7b2;
    --canvas-dot:#123a1f;
    --stage-glow:rgba(57,255,136,.06);
    --link:#39ff88;
    --shadow:0 2px 4px rgba(0,0,0,.40),0 8px 24px rgba(0,0,0,.55);
    --shadow-lg:0 12px 40px rgba(0,0,0,.65);
  }
:root[data-theme="solarized"]{   /* Solarized Classic */
    --toolbar-bg:#073642; --toolbar-text:#fdf6e3;
    --paper:#fdf6e3; --paper-2:#eee8d5; --ink:#657b83; --ink-soft:#93a1a1;
    --line:#eee8d5; --line-2:#d8d2be;
    --accent:#268bd2; --accent-deep:#206ea4; --teal:#2aa198;
    --chrome:#eee8d5; --chrome-edge:#d8d2be;
    --node-bg:#ffffff; --node-ink:#657b83;
    --canvas-dot:#d8d2be;
    --stage-glow:rgba(38,139,210,.05);
    --link:#268bd2;
    --shadow:0 1px 3px rgba(7,54,66,.12),0 8px 24px rgba(7,54,66,.10);
    --shadow-lg:0 12px 40px rgba(7,54,66,.18);
  }
:root[data-theme="scholar-parchment"]{   /* Scholar Parchment */
    --toolbar-bg:#053327; --toolbar-text:#faf8f3;
    --paper:#faf8f3; --paper-2:#f1ece1; --ink:#2c2c2a; --ink-soft:#5a5a56;
    --line:#e2ddd3; --line-2:#d4cdbe;
    --accent:#0a4d3c; --accent-deep:#063a2e; --teal:#c5a059;
    --chrome:#f1ece1; --chrome-edge:#e2ddd3;
    --node-bg:#ffffff; --node-ink:#2c2c2a;
    --canvas-dot:#e2ddd3;
    --stage-glow:rgba(197,160,89,.06);
    --link:#0a4d3c;
    --shadow:0 1px 3px rgba(44,44,42,.10),0 8px 24px rgba(44,44,42,.08);
    --shadow-lg:0 12px 40px rgba(44,44,42,.16);
  }
:root[data-theme="paper-ink"]{   /* Paper & Ink editorial */
    --toolbar-bg:#111111; --toolbar-text:#fcfbf7;
    --paper:#fcfbf7; --paper-2:#f1efe9; --ink:#343434; --ink-soft:#77736b;
    --line:#ddd9d0; --line-2:#cec9bd;
    --accent:#27364b; --accent-deep:#1b2636; --teal:#5c6b7a;
    --chrome:#f1efe9; --chrome-edge:#ddd9d0;
    --node-bg:#ffffff; --node-ink:#343434;
    --canvas-dot:#ddd9d0;
    --stage-glow:rgba(39,54,75,.05);
    --link:#27364b;
    --shadow:0 1px 3px rgba(52,52,52,.10),0 8px 24px rgba(52,52,52,.08);
    --shadow-lg:0 12px 40px rgba(52,52,52,.16);
  }
:root[data-theme="mint-graphite"]{   /* Mint Graphite */
    --toolbar-bg:#18251f; --toolbar-text:#f7fbf9;
    --paper:#f7fbf9; --paper-2:#e6f3ee; --ink:#34423c; --ink-soft:#71827a;
    --line:#d8e8e1; --line-2:#c6dbd1;
    --accent:#0f9f75; --accent-deep:#0b7e5c; --teal:#34d399;
    --chrome:#e6f3ee; --chrome-edge:#d8e8e1;
    --node-bg:#ffffff; --node-ink:#34423c;
    --canvas-dot:#d8e8e1;
    --stage-glow:rgba(15,159,117,.05);
    --link:#0f9f75;
    --shadow:0 1px 3px rgba(52,66,60,.10),0 8px 24px rgba(52,66,60,.08);
    --shadow-lg:0 12px 40px rgba(52,66,60,.16);
  }
:root[data-theme="carbon-amber"]{   /* Carbon & Amber CAD */
    --toolbar-bg:#ffd066; --toolbar-text:#121212;
    --paper:#121212; --paper-2:#1a1400; --ink:#d4af37; --ink-soft:#8c6a00;
    --line:#332600; --line-2:#4a3a00;
    --accent:#ffb000; --accent-deep:#c98f00; --teal:#ffd066;
    --chrome:#1a1400; --chrome-edge:#332600;
    --node-bg:#1f1800; --node-ink:#d4af37;
    --canvas-dot:#332600;
    --stage-glow:rgba(255,176,0,.06);
    --link:#ffb000;
    --shadow:0 2px 4px rgba(0,0,0,.40),0 8px 24px rgba(0,0,0,.55);
    --shadow-lg:0 12px 40px rgba(0,0,0,.65);
  }
:root[data-theme="cyber-quantum"]{   /* Cyber-Quantum */
    --toolbar-bg:#e2f8ff; --toolbar-text:#0a101d;
    --paper:#0a101d; --paper-2:#10192c; --ink:#e2f8ff; --ink-soft:#62879b;
    --line:#1b3b4d; --line-2:#28526b;
    --accent:#00f0ff; --accent-deep:#00b8c4; --teal:#ff0055;
    --chrome:#10192c; --chrome-edge:#1b3b4d;
    --node-bg:#10192c; --node-ink:#e2f8ff;
    --canvas-dot:#1b3b4d;
    --stage-glow:rgba(0,240,255,.07);
    --link:#00f0ff;
    --shadow:0 2px 4px rgba(0,0,0,.40),0 8px 24px rgba(0,0,0,.55);
    --shadow-lg:0 12px 40px rgba(0,0,0,.65);
  }
:root[data-theme="blueprint"]{   /* Architectural Blueprint */
    --toolbar-bg:#e0f2fe; --toolbar-text:#005596;
    --paper:#005596; --paper-2:#004478; --ink:#e0f2fe; --ink-soft:#7dd3fc;
    --line:#4080b0; --line-2:#5797c2;
    --accent:#ffffff; --accent-deep:#c9e3f5; --teal:#7dd3fc;
    --chrome:#004478; --chrome-edge:#4080b0;
    --node-bg:#004478; --node-ink:#e0f2fe;
    --canvas-dot:#4080b0;
    --stage-glow:rgba(255,255,255,.08);
    --link:#7dd3fc;
    --shadow:0 2px 4px rgba(0,0,0,.35),0 8px 24px rgba(0,0,0,.50);
    --shadow-lg:0 12px 40px rgba(0,0,0,.60);
  }
:root[data-theme="obsidian"]{   /* Obsidian Terminal */
    --toolbar-bg:#ffffff; --toolbar-text:#000000;
    --paper:#000000; --paper-2:#18181b; --ink:#a1a1aa; --ink-soft:#52525b;
    --line:#27272a; --line-2:#333338;
    --accent:#ffffff; --accent-deep:#d4d4d8; --teal:#e4e4e7;
    --chrome:#18181b; --chrome-edge:#27272a;
    --node-bg:#18181b; --node-ink:#a1a1aa;
    --canvas-dot:#27272a;
    --stage-glow:rgba(255,255,255,.05);
    --link:#ffffff;
    --shadow:0 2px 4px rgba(0,0,0,.50),0 8px 24px rgba(0,0,0,.65);
    --shadow-lg:0 12px 40px rgba(0,0,0,.75);
  }
:root[data-theme="swiss-crimson"]{   /* Swiss Crimson */
    --toolbar-bg:#000000; --toolbar-text:#f4f4f4;
    --paper:#f4f4f4; --paper-2:#e6e6e6; --ink:#111111; --ink-soft:#666666;
    --line:#d1d1d1; --line-2:#c0c0c0;
    --accent:#d90429; --accent-deep:#a60320; --teal:#2f2f2f;
    --chrome:#e6e6e6; --chrome-edge:#d1d1d1;
    --node-bg:#ffffff; --node-ink:#111111;
    --canvas-dot:#d1d1d1;
    --stage-glow:rgba(217,4,41,.05);
    --link:#d90429;
    --shadow:0 1px 3px rgba(17,17,17,.10),0 8px 24px rgba(17,17,17,.08);
    --shadow-lg:0 12px 40px rgba(17,17,17,.16);
  }
:root[data-theme="nordic-sage"]{   /* Nordic Pine & Sage */
    --toolbar-bg:#1b2621; --toolbar-text:#f3f5f3;
    --paper:#f3f5f3; --paper-2:#e4eae6; --ink:#2d3a34; --ink-soft:#687770;
    --line:#d5ddd8; --line-2:#c3cdc7;
    --accent:#3b604d; --accent-deep:#2c4a3a; --teal:#52b788;
    --chrome:#e4eae6; --chrome-edge:#d5ddd8;
    --node-bg:#ffffff; --node-ink:#2d3a34;
    --canvas-dot:#d5ddd8;
    --stage-glow:rgba(59,96,77,.05);
    --link:#3b604d;
    --shadow:0 1px 3px rgba(45,58,52,.10),0 8px 24px rgba(45,58,52,.08);
    --shadow-lg:0 12px 40px rgba(45,58,52,.16);
  }
:root[data-theme="deep-ocean"]{   /* Deep Ocean Phosphor */
    --toolbar-bg:#e6fffa; --toolbar-text:#06181d;
    --paper:#06181d; --paper-2:#0d282e; --ink:#a3e5d9; --ink-soft:#3b7a70;
    --line:#113836; --line-2:#1a4a45;
    --accent:#10b981; --accent-deep:#0b8e61; --teal:#5eead4;
    --chrome:#0d282e; --chrome-edge:#113836;
    --node-bg:#0d282e; --node-ink:#a3e5d9;
    --canvas-dot:#113836;
    --stage-glow:rgba(16,185,129,.06);
    --link:#10b981;
    --shadow:0 2px 4px rgba(0,0,0,.40),0 8px 24px rgba(0,0,0,.55);
    --shadow-lg:0 12px 40px rgba(0,0,0,.65);
  }
:root[data-theme="google-material"]{   /* Google Material You */
    --toolbar-bg:#e3e2e6; --toolbar-text:#1f1f1f;
    --paper:#1f1f1f; --paper-2:#2d2d2d; --ink:#e3e2e6; --ink-soft:#8e918f;
    --line:#444746; --line-2:#56595a;
    --accent:#a8c7fa; --accent-deep:#7fa8e8; --teal:#81d4fa;
    --chrome:#2d2d2d; --chrome-edge:#444746;
    --node-bg:#2d2d2d; --node-ink:#e3e2e6;
    --canvas-dot:#444746;
    --stage-glow:rgba(168,199,250,.05);
    --link:#a8c7fa;
    --shadow:0 2px 4px rgba(0,0,0,.35),0 8px 24px rgba(0,0,0,.50);
    --shadow-lg:0 12px 40px rgba(0,0,0,.60);
  }
:root[data-theme="github-modern"]{   /* GitHub Modern (dark dimmed) */
    --toolbar-bg:#cdd9e5; --toolbar-text:#22272e;
    --paper:#22272e; --paper-2:#2d333b; --ink:#adbac7; --ink-soft:#768390;
    --line:#444c56; --line-2:#545d68;
    --accent:#539bf5; --accent-deep:#316dca; --teal:#3fb950;
    --chrome:#2d333b; --chrome-edge:#444c56;
    --node-bg:#2d333b; --node-ink:#adbac7;
    --canvas-dot:#444c56;
    --stage-glow:rgba(83,155,245,.05);
    --link:#539bf5;
    --shadow:0 2px 4px rgba(0,0,0,.30),0 8px 24px rgba(0,0,0,.45);
    --shadow-lg:0 12px 40px rgba(0,0,0,.55);
  }
:root[data-theme="sakura-drift"]{   /* Eos Sakura Drift */
    --toolbar-bg:#2c1e23; --toolbar-text:#fff9fa;
    --paper:#fff9fa; --paper-2:#ffebf0; --ink:#4a3e43; --ink-soft:#9e8890;
    --line:#f7d6df; --line-2:#efc3ce;
    --accent:#ff758f; --accent-deep:#e35472; --teal:#8d86c9;
    --chrome:#ffebf0; --chrome-edge:#f7d6df;
    --node-bg:#ffffff; --node-ink:#4a3e43;
    --canvas-dot:#f7d6df;
    --stage-glow:rgba(255,117,143,.05);
    --link:#ff758f;
    --shadow:0 1px 3px rgba(74,62,67,.10),0 8px 24px rgba(74,62,67,.08);
    --shadow-lg:0 12px 40px rgba(74,62,67,.16);
  }
:root[data-theme="aurora-frost"]{   /* Nordic Aurora Frost */
    --toolbar-bg:#e0fbfc; --toolbar-text:#0b132b;
    --paper:#0b132b; --paper-2:#1c2541; --ink:#c0d6df; --ink-soft:#486581;
    --line:#1c2541; --line-2:#2a3a5e;
    --accent:#70e000; --accent-deep:#54a800; --teal:#64dfdf;
    --chrome:#1c2541; --chrome-edge:#1c2541;
    --node-bg:#1c2541; --node-ink:#c0d6df;
    --canvas-dot:#1c2541;
    --stage-glow:rgba(112,224,0,.06);
    --link:#70e000;
    --shadow:0 2px 4px rgba(0,0,0,.35),0 8px 24px rgba(0,0,0,.50);
    --shadow-lg:0 12px 40px rgba(0,0,0,.60);
  }
:root[data-theme="espresso"]{   /* Velvet Espresso & Caramel */
    --toolbar-bg:#faedcd; --toolbar-text:#1a1412;
    --paper:#1a1412; --paper-2:#281e19; --ink:#e3d5ca; --ink-soft:#8c7a6b;
    --line:#382b24; --line-2:#473731;
    --accent:#d4a373; --accent-deep:#b08350; --teal:#bc6c25;
    --chrome:#281e19; --chrome-edge:#382b24;
    --node-bg:#281e19; --node-ink:#e3d5ca;
    --canvas-dot:#382b24;
    --stage-glow:rgba(212,163,115,.06);
    --link:#d4a373;
    --shadow:0 2px 4px rgba(0,0,0,.40),0 8px 24px rgba(0,0,0,.55);
    --shadow-lg:0 12px 40px rgba(0,0,0,.65);
  }
:root[data-theme="arctic-glass"]{   /* Arctic Glass */
    --toolbar-bg:#102a43; --toolbar-text:#f4faff;
    --paper:#f4faff; --paper-2:#e9f5fb; --ink:#274154; --ink-soft:#6b8496;
    --line:#d6eaf4; --line-2:#c4deeb;
    --accent:#149bd7; --accent-deep:#0f7cac; --teal:#38bdf8;
    --chrome:#e9f5fb; --chrome-edge:#d6eaf4;
    --node-bg:#ffffff; --node-ink:#274154;
    --canvas-dot:#d6eaf4;
    --stage-glow:rgba(20,155,215,.05);
    --link:#149bd7;
    --shadow:0 1px 3px rgba(39,65,84,.10),0 8px 24px rgba(39,65,84,.08);
    --shadow-lg:0 12px 40px rgba(39,65,84,.16);
  }
:root[data-theme="copper-lab"]{   /* Copper Laboratory */
    --toolbar-bg:#fff8f2; --toolbar-text:#1b1715;
    --paper:#1b1715; --paper-2:#29201c; --ink:#e4d7ce; --ink-soft:#927c70;
    --line:#463128; --line-2:#573d32;
    --accent:#d97745; --accent-deep:#b45b30; --teal:#e89a70;
    --chrome:#29201c; --chrome-edge:#463128;
    --node-bg:#29201c; --node-ink:#e4d7ce;
    --canvas-dot:#463128;
    --stage-glow:rgba(217,119,69,.06);
    --link:#d97745;
    --shadow:0 2px 4px rgba(0,0,0,.40),0 8px 24px rgba(0,0,0,.55);
    --shadow-lg:0 12px 40px rgba(0,0,0,.65);
  }
:root[data-theme="forest-night"]{   /* Forest Night */
    --toolbar-bg:#f4fff8; --toolbar-text:#101b17;
    --paper:#101b17; --paper-2:#172720; --ink:#d5e5dc; --ink-soft:#71897d;
    --line:#294138; --line-2:#345448;
    --accent:#63c174; --accent-deep:#4a9e5d; --teal:#76d98a;
    --chrome:#172720; --chrome-edge:#294138;
    --node-bg:#172720; --node-ink:#d5e5dc;
    --canvas-dot:#294138;
    --stage-glow:rgba(99,193,116,.06);
    --link:#63c174;
    --shadow:0 2px 4px rgba(0,0,0,.35),0 8px 24px rgba(0,0,0,.50);
    --shadow-lg:0 12px 40px rgba(0,0,0,.60);
  }
:root[data-theme="cobalt"]{   /* Cobalt Studio */
    --toolbar-bg:#d7e3ff; --toolbar-text:#0b1530;
    --paper:#0b1530; --paper-2:#121f42; --ink:#d7e3ff; --ink-soft:#7082a8;
    --line:#263b6b; --line-2:#304a87;
    --accent:#4f8cff; --accent-deep:#3a6dd6; --teal:#78a9ff;
    --chrome:#121f42; --chrome-edge:#263b6b;
    --node-bg:#121f42; --node-ink:#d7e3ff;
    --canvas-dot:#263b6b;
    --stage-glow:rgba(79,140,255,.06);
    --link:#4f8cff;
    --shadow:0 2px 4px rgba(0,0,0,.35),0 8px 24px rgba(0,0,0,.50);
    --shadow-lg:0 12px 40px rgba(0,0,0,.60);
  }
:root[data-theme="lavender-mist"]{   /* Lavender Mist */
    --toolbar-bg:#211a32; --toolbar-text:#faf8ff;
    --paper:#faf8ff; --paper-2:#f0ebfa; --ink:#403a52; --ink-soft:#817a94;
    --line:#e4ddf2; --line-2:#d6cee8;
    --accent:#7956c8; --accent-deep:#6041a6; --teal:#b69cff;
    --chrome:#f0ebfa; --chrome-edge:#e4ddf2;
    --node-bg:#ffffff; --node-ink:#403a52;
    --canvas-dot:#e4ddf2;
    --stage-glow:rgba(121,86,200,.05);
    --link:#7956c8;
    --shadow:0 1px 3px rgba(64,58,82,.10),0 8px 24px rgba(64,58,82,.08);
    --shadow-lg:0 12px 40px rgba(64,58,82,.16);
  }
:root[data-theme="ruby-night"]{   /* Ruby Night */
    --toolbar-bg:#ffd4dc; --toolbar-text:#151314;
    --paper:#151314; --paper-2:#24191c; --ink:#e8dddf; --ink-soft:#8e7a7e;
    --line:#43242b; --line-2:#57313a;
    --accent:#f43f5e; --accent-deep:#c62b47; --teal:#ff7187;
    --chrome:#24191c; --chrome-edge:#43242b;
    --node-bg:#24191c; --node-ink:#e8dddf;
    --canvas-dot:#43242b;
    --stage-glow:rgba(244,63,94,.07);
    --link:#f43f5e;
    --shadow:0 2px 4px rgba(0,0,0,.40),0 8px 24px rgba(0,0,0,.55);
    --shadow-lg:0 12px 40px rgba(0,0,0,.65);
  }
:root[data-theme="sandstone"]{   /* Sandstone */
    --toolbar-bg:#2d2118; --toolbar-text:#fbf6ee;
    --paper:#fbf6ee; --paper-2:#f3e7d4; --ink:#51463a; --ink-soft:#8a7967;
    --line:#e8d8c2; --line-2:#dcc9ae;
    --accent:#b45309; --accent-deep:#924308; --teal:#e99a55;
    --chrome:#f3e7d4; --chrome-edge:#e8d8c2;
    --node-bg:#ffffff; --node-ink:#51463a;
    --canvas-dot:#e8d8c2;
    --stage-glow:rgba(180,83,9,.06);
    --link:#b45309;
    --shadow:0 1px 3px rgba(81,70,58,.10),0 8px 24px rgba(81,70,58,.08);
    --shadow-lg:0 12px 40px rgba(81,70,58,.16);
  }
:root[data-theme="electric-indigo"]{   /* Electric Indigo */
    --toolbar-bg:#e9e2ff; --toolbar-text:#0e0a22;
    --paper:#0e0a22; --paper-2:#191238; --ink:#dcd7ff; --ink-soft:#7770a5;
    --line:#33255b; --line-2:#42336f;
    --accent:#8b5cf6; --accent-deep:#6f3ed4; --teal:#a78bfa;
    --chrome:#191238; --chrome-edge:#33255b;
    --node-bg:#191238; --node-ink:#dcd7ff;
    --canvas-dot:#33255b;
    --stage-glow:rgba(139,92,246,.07);
    --link:#8b5cf6;
    --shadow:0 2px 4px rgba(0,0,0,.40),0 8px 24px rgba(0,0,0,.55);
    --shadow-lg:0 12px 40px rgba(0,0,0,.65);
  }
:root[data-theme="teal-paper"]{   /* Teal Paper */
    --toolbar-bg:#12322f; --toolbar-text:#f7fcfb;
    --paper:#f7fcfb; --paper-2:#e6f2f0; --ink:#304744; --ink-soft:#6f8581;
    --line:#d4e7e3; --line-2:#c2dcd6;
    --accent:#0f766e; --accent-deep:#0b5a54; --teal:#2dd4bf;
    --chrome:#e6f2f0; --chrome-edge:#d4e7e3;
    --node-bg:#ffffff; --node-ink:#304744;
    --canvas-dot:#d4e7e3;
    --stage-glow:rgba(15,118,110,.05);
    --link:#0f766e;
    --shadow:0 1px 3px rgba(48,71,68,.10),0 8px 24px rgba(48,71,68,.08);
    --shadow-lg:0 12px 40px rgba(48,71,68,.16);
  }
:root[data-theme="steel-orange"]{   /* Steel & Orange */
    --toolbar-bg:#d9dee3; --toolbar-text:#171a1d;
    --paper:#171a1d; --paper-2:#23282d; --ink:#d9dee3; --ink-soft:#7d8790;
    --line:#353b40; --line-2:#454c54;
    --accent:#f97316; --accent-deep:#d15c0b; --teal:#ff9a55;
    --chrome:#23282d; --chrome-edge:#353b40;
    --node-bg:#23282d; --node-ink:#d9dee3;
    --canvas-dot:#353b40;
    --stage-glow:rgba(249,115,22,.06);
    --link:#f97316;
    --shadow:0 2px 4px rgba(0,0,0,.40),0 8px 24px rgba(0,0,0,.55);
    --shadow-lg:0 12px 40px rgba(0,0,0,.65);
  }
:root[data-theme="cosmic-rose"]{   /* Cosmic Rose */
    --toolbar-bg:#ffd6ec; --toolbar-text:#100c1b;
    --paper:#100c1b; --paper-2:#20142a; --ink:#e4d9ea; --ink-soft:#86708f;
    --line:#38223f; --line-2:#482c52;
    --accent:#f472b6; --accent-deep:#d44e97; --teal:#f9a8d4;
    --chrome:#20142a; --chrome-edge:#38223f;
    --node-bg:#20142a; --node-ink:#e4d9ea;
    --canvas-dot:#38223f;
    --stage-glow:rgba(244,114,182,.07);
    --link:#f472b6;
    --shadow:0 2px 4px rgba(0,0,0,.40),0 8px 24px rgba(0,0,0,.55);
    --shadow-lg:0 12px 40px rgba(0,0,0,.65);
  }
:root[data-theme="plasma-crimson"]{   /* Plasma Crimson */
    --toolbar-bg:#ffe8ed; --toolbar-text:#12080c;
    --paper:#12080c; --paper-2:#1f0e14; --ink:#f5d0d8; --ink-soft:#a56b78;
    --line:#4a1a28; --line-2:#5f2233;
    --accent:#ff2d55; --accent-deep:#d10f36; --teal:#ff5c7a;
    --chrome:#1f0e14; --chrome-edge:#4a1a28;
    --node-bg:#1f0e14; --node-ink:#f5d0d8;
    --canvas-dot:#4a1a28;
    --stage-glow:rgba(255,45,85,.08);
    --link:#ff2d55;
    --shadow:0 2px 4px rgba(0,0,0,.45),0 8px 24px rgba(0,0,0,.60);
    --shadow-lg:0 12px 40px rgba(0,0,0,.70);
  }
:root[data-theme="neon-noir"]{   /* Neon Noir */
    --toolbar-bg:#ffffff; --toolbar-text:#0a0a0f;
    --paper:#0a0a0f; --paper-2:#12121c; --ink:#c8c8d4; --ink-soft:#5a5a70;
    --line:#1f1f2e; --line-2:#2a2a3e;
    --accent:#00ff9f; --accent-deep:#00cc7e; --teal:#a0ffd0;
    --chrome:#12121c; --chrome-edge:#1f1f2e;
    --node-bg:#12121c; --node-ink:#c8c8d4;
    --canvas-dot:#1f1f2e;
    --stage-glow:rgba(0,255,159,.07);
    --link:#00ff9f;
    --shadow:0 2px 4px rgba(0,0,0,.45),0 8px 24px rgba(0,0,0,.60);
    --shadow-lg:0 12px 40px rgba(0,0,0,.70);
  }
:root[data-theme="desert-oasis"]{   /* Desert Oasis */
    --toolbar-bg:#2c2116; --toolbar-text:#fdf6e9;
    --paper:#fdf6e9; --paper-2:#f5e8d0; --ink:#4a3c2a; --ink-soft:#8a7a62;
    --line:#e8d5b5; --line-2:#dcc59e;
    --accent:#d97706; --accent-deep:#b45f05; --teal:#f59e0b;
    --chrome:#f5e8d0; --chrome-edge:#e8d5b5;
    --node-bg:#ffffff; --node-ink:#4a3c2a;
    --canvas-dot:#e8d5b5;
    --stage-glow:rgba(217,119,6,.06);
    --link:#d97706;
    --shadow:0 1px 3px rgba(74,60,42,.10),0 8px 24px rgba(74,60,42,.08);
    --shadow-lg:0 12px 40px rgba(74,60,42,.16);
  }
:root[data-theme="ice-crystal"]{   /* Ice Crystal */
    --toolbar-bg:#0c1e36; --toolbar-text:#f0f9ff;
    --paper:#f0f9ff; --paper-2:#e0f2fe; --ink:#1e3a5f; --ink-soft:#5b7a9a;
    --line:#bae6fd; --line-2:#a4d9f5;
    --accent:#0ea5e9; --accent-deep:#0b84bc; --teal:#38bdf8;
    --chrome:#e0f2fe; --chrome-edge:#bae6fd;
    --node-bg:#ffffff; --node-ink:#1e3a5f;
    --canvas-dot:#bae6fd;
    --stage-glow:rgba(14,165,233,.05);
    --link:#0ea5e9;
    --shadow:0 1px 3px rgba(30,58,95,.10),0 8px 24px rgba(30,58,95,.08);
    --shadow-lg:0 12px 40px rgba(30,58,95,.16);
  }
:root[data-theme="ember-forge"]{   /* Ember Forge */
    --toolbar-bg:#fff5eb; --toolbar-text:#140e0a;
    --paper:#140e0a; --paper-2:#221610; --ink:#e8d5c4; --ink-soft:#9a7a62;
    --line:#3d2418; --line-2:#4e2d1e;
    --accent:#ef4444; --accent-deep:#c92828; --teal:#f87171;
    --chrome:#221610; --chrome-edge:#3d2418;
    --node-bg:#221610; --node-ink:#e8d5c4;
    --canvas-dot:#3d2418;
    --stage-glow:rgba(239,68,68,.08);
    --link:#ef4444;
    --shadow:0 2px 4px rgba(0,0,0,.45),0 8px 24px rgba(0,0,0,.60);
    --shadow-lg:0 12px 40px rgba(0,0,0,.70);
  }
:root[data-theme="violet-circuit"]{   /* Violet Circuit */
    --toolbar-bg:#f5f0ff; --toolbar-text:#0f0a1a;
    --paper:#0f0a1a; --paper-2:#1a1230; --ink:#d4c8f0; --ink-soft:#7a6a9a;
    --line:#2e1f4a; --line-2:#3b2960;
    --accent:#a855f7; --accent-deep:#8b33de; --teal:#c084fc;
    --chrome:#1a1230; --chrome-edge:#2e1f4a;
    --node-bg:#1a1230; --node-ink:#d4c8f0;
    --canvas-dot:#2e1f4a;
    --stage-glow:rgba(168,85,247,.08);
    --link:#a855f7;
    --shadow:0 2px 4px rgba(0,0,0,.45),0 8px 24px rgba(0,0,0,.60);
    --shadow-lg:0 12px 40px rgba(0,0,0,.70);
  }
:root[data-theme="moss-stone"]{   /* Moss & Stone */
    --toolbar-bg:#1a2416; --toolbar-text:#f4f6f0;
    --paper:#f4f6f0; --paper-2:#e8eedc; --ink:#2e3a2a; --ink-soft:#6a7a62;
    --line:#d4dcc8; --line-2:#c2ccb4;
    --accent:#4d7c0f; --accent-deep:#3a5e0b; --teal:#84cc16;
    --chrome:#e8eedc; --chrome-edge:#d4dcc8;
    --node-bg:#ffffff; --node-ink:#2e3a2a;
    --canvas-dot:#d4dcc8;
    --stage-glow:rgba(77,124,15,.06);
    --link:#4d7c0f;
    --shadow:0 1px 3px rgba(46,58,42,.10),0 8px 24px rgba(46,58,42,.08);
    --shadow-lg:0 12px 40px rgba(46,58,42,.16);
  }
:root[data-theme="twilight-amber"]{   /* Twilight Amber */
    --toolbar-bg:#fff8ec; --toolbar-text:#16120c;
    --paper:#16120c; --paper-2:#241e14; --ink:#e8dcc8; --ink-soft:#9a8a6a;
    --line:#3a3020; --line-2:#4a3d2a;
    --accent:#fbbf24; --accent-deep:#d19f12; --teal:#fcd34d;
    --chrome:#241e14; --chrome-edge:#3a3020;
    --node-bg:#241e14; --node-ink:#e8dcc8;
    --canvas-dot:#3a3020;
    --stage-glow:rgba(251,191,36,.07);
    --link:#fbbf24;
    --shadow:0 2px 4px rgba(0,0,0,.40),0 8px 24px rgba(0,0,0,.55);
    --shadow-lg:0 12px 40px rgba(0,0,0,.65);
  }
:root[data-theme="ocean-depth"]{   /* Ocean Depth */
    --toolbar-bg:#e8f4fa; --toolbar-text:#06141c;
    --paper:#06141c; --paper-2:#0c1e28; --ink:#b8d8e8; --ink-soft:#4a7a90;
    --line:#0e2a38; --line-2:#163e52;
    --accent:#22d3ee; --accent-deep:#18aec7; --teal:#67e8f9;
    --chrome:#0c1e28; --chrome-edge:#0e2a38;
    --node-bg:#0c1e28; --node-ink:#b8d8e8;
    --canvas-dot:#0e2a38;
    --stage-glow:rgba(34,211,238,.07);
    --link:#22d3ee;
    --shadow:0 2px 4px rgba(0,0,0,.40),0 8px 24px rgba(0,0,0,.55);
    --shadow-lg:0 12px 40px rgba(0,0,0,.65);
  }
:root[data-theme="charcoal-gold"]{   /* Charcoal Gold */
    --toolbar-bg:#f5f0e6; --toolbar-text:#121212;
    --paper:#121212; --paper-2:#1c1c18; --ink:#d4d0c8; --ink-soft:#8a8678;
    --line:#2e2e28; --line-2:#3c3c34;
    --accent:#eab308; --accent-deep:#c29304; --teal:#facc15;
    --chrome:#1c1c18; --chrome-edge:#2e2e28;
    --node-bg:#1c1c18; --node-ink:#d4d0c8;
    --canvas-dot:#2e2e28;
    --stage-glow:rgba(234,179,8,.07);
    --link:#eab308;
    --shadow:0 2px 4px rgba(0,0,0,.40),0 8px 24px rgba(0,0,0,.55);
    --shadow-lg:0 12px 40px rgba(0,0,0,.65);
  }
:root[data-theme="soft-clay"]{   /* Soft Clay */
    --toolbar-bg:#2a1e18; --toolbar-text:#fbf6f2;
    --paper:#fbf6f2; --paper-2:#f5e8e0; --ink:#4a3a32; --ink-soft:#8a7468;
    --line:#e8d8cc; --line-2:#dcc8b8;
    --accent:#c2410c; --accent-deep:#9c340a; --teal:#fb923c;
    --chrome:#f5e8e0; --chrome-edge:#e8d8cc;
    --node-bg:#ffffff; --node-ink:#4a3a32;
    --canvas-dot:#e8d8cc;
    --stage-glow:rgba(194,65,12,.06);
    --link:#c2410c;
    --shadow:0 1px 3px rgba(74,58,50,.10),0 8px 24px rgba(74,58,50,.08);
    --shadow-lg:0 12px 40px rgba(74,58,50,.16);
  }
:root[data-theme="azure-horizon"]{   /* Azure Horizon */
    --toolbar-bg:#e8f4ff; --toolbar-text:#0a1420;
    --paper:#0a1420; --paper-2:#121e30; --ink:#c0d8f0; --ink-soft:#5a7a9a;
    --line:#1a2e48; --line-2:#234063;
    --accent:#3b82f6; --accent-deep:#2e66d6; --teal:#60a5fa;
    --chrome:#121e30; --chrome-edge:#1a2e48;
    --node-bg:#121e30; --node-ink:#c0d8f0;
    --canvas-dot:#1a2e48;
    --stage-glow:rgba(59,130,246,.07);
    --link:#3b82f6;
    --shadow:0 2px 4px rgba(0,0,0,.40),0 8px 24px rgba(0,0,0,.55);
    --shadow-lg:0 12px 40px rgba(0,0,0,.65);
  }
:root[data-theme="jade-temple"]{   /* Jade Temple */
    --toolbar-bg:#e8fff4; --toolbar-text:#0a1612;
    --paper:#0a1612; --paper-2:#12241c; --ink:#c0e0d4; --ink-soft:#4a8a72;
    --line:#1a3a2e; --line-2:#234c3c;
    --accent:#10b981; --accent-deep:#0c9668; --teal:#34d399;
    --chrome:#12241c; --chrome-edge:#1a3a2e;
    --node-bg:#12241c; --node-ink:#c0e0d4;
    --canvas-dot:#1a3a2e;
    --stage-glow:rgba(16,185,129,.07);
    --link:#10b981;
    --shadow:0 2px 4px rgba(0,0,0,.40),0 8px 24px rgba(0,0,0,.55);
    --shadow-lg:0 12px 40px rgba(0,0,0,.65);
  }
:root[data-theme="magenta-pulse"]{   /* Magenta Pulse */
    --toolbar-bg:#fff0ff; --toolbar-text:#140a16;
    --paper:#140a16; --paper-2:#221022; --ink:#e8d0e8; --ink-soft:#9a6a9a;
    --line:#3a1a3a; --line-2:#4a234a;
    --accent:#ec4899; --accent-deep:#c82e7b; --teal:#f472b6;
    --chrome:#221022; --chrome-edge:#3a1a3a;
    --node-bg:#221022; --node-ink:#e8d0e8;
    --canvas-dot:#3a1a3a;
    --stage-glow:rgba(236,72,153,.08);
    --link:#ec4899;
    --shadow:0 2px 4px rgba(0,0,0,.45),0 8px 24px rgba(0,0,0,.60);
    --shadow-lg:0 12px 40px rgba(0,0,0,.70);
  }
:root[data-theme="graphite-terminal"]{   /* Graphite Terminal */
    --toolbar-bg:#e8e8e8; --toolbar-text:#1a1a1a;
    --paper:#1a1a1a; --paper-2:#242424; --ink:#b8b8b8; --ink-soft:#6a6a6a;
    --line:#333333; --line-2:#424242;
    --accent:#60a5fa; --accent-deep:#4585e0; --teal:#93c5fd;
    --chrome:#242424; --chrome-edge:#333333;
    --node-bg:#242424; --node-ink:#b8b8b8;
    --canvas-dot:#333333;
    --stage-glow:rgba(96,165,250,.06);
    --link:#60a5fa;
    --shadow:0 2px 4px rgba(0,0,0,.40),0 8px 24px rgba(0,0,0,.55);
    --shadow-lg:0 12px 40px rgba(0,0,0,.65);
  }
:root[data-theme="honeycomb"]{   /* Honeycomb */
    --toolbar-bg:#2a1e0a; --toolbar-text:#fffbeb;
    --paper:#fffbeb; --paper-2:#fef3c7; --ink:#4a3a1a; --ink-soft:#8a7a4a;
    --line:#f5e6b0; --line-2:#ebd98e;
    --accent:#f59e0b; --accent-deep:#cc8108; --teal:#fbbf24;
    --chrome:#fef3c7; --chrome-edge:#f5e6b0;
    --node-bg:#ffffff; --node-ink:#4a3a1a;
    --canvas-dot:#f5e6b0;
    --stage-glow:rgba(245,158,11,.07);
    --link:#f59e0b;
    --shadow:0 1px 3px rgba(74,58,26,.10),0 8px 24px rgba(74,58,26,.08);
    --shadow-lg:0 12px 40px rgba(74,58,26,.16);
  }
:root[data-theme="frosted-pine"]{   /* Frosted Pine */
    --toolbar-bg:#e8f8ec; --toolbar-text:#0c1610;
    --paper:#0c1610; --paper-2:#122018; --ink:#c0d8c8; --ink-soft:#5a8a6a;
    --line:#1a3a28; --line-2:#234c34;
    --accent:#34d399; --accent-deep:#27ac7d; --teal:#6ee7b7;
    --chrome:#122018; --chrome-edge:#1a3a28;
    --node-bg:#122018; --node-ink:#c0d8c8;
    --canvas-dot:#1a3a28;
    --stage-glow:rgba(52,211,153,.07);
    --link:#34d399;
    --shadow:0 2px 4px rgba(0,0,0,.40),0 8px 24px rgba(0,0,0,.55);
    --shadow-lg:0 12px 40px rgba(0,0,0,.65);
  }
:root[data-theme="quantum-violet"]{   /* Quantum Violet */
    --toolbar-bg:#f0ecff; --toolbar-text:#0e0a18;
    --paper:#0e0a18; --paper-2:#18122a; --ink:#d0c8e8; --ink-soft:#7a6a9a;
    --line:#2a1e48; --line-2:#38295e;
    --accent:#8b5cf6; --accent-deep:#6f3ee0; --teal:#a78bfa;
    --chrome:#18122a; --chrome-edge:#2a1e48;
    --node-bg:#18122a; --node-ink:#d0c8e8;
    --canvas-dot:#2a1e48;
    --stage-glow:rgba(139,92,246,.08);
    --link:#8b5cf6;
    --shadow:0 2px 4px rgba(0,0,0,.45),0 8px 24px rgba(0,0,0,.60);
    --shadow-lg:0 12px 40px rgba(0,0,0,.70);
  }
:root[data-theme="copper-rust"]{   /* Copper Rust */
    --toolbar-bg:#fff5ec; --toolbar-text:#16120e;
    --paper:#16120e; --paper-2:#241a12; --ink:#e0d0c0; --ink-soft:#9a7a62;
    --line:#3a2a1e; --line-2:#4a3728;
    --accent:#ea580c; --accent-deep:#c04309; --teal:#fb923c;
    --chrome:#241a12; --chrome-edge:#3a2a1e;
    --node-bg:#241a12; --node-ink:#e0d0c0;
    --canvas-dot:#3a2a1e;
    --stage-glow:rgba(234,88,12,.08);
    --link:#ea580c;
    --shadow:0 2px 4px rgba(0,0,0,.40),0 8px 24px rgba(0,0,0,.55);
    --shadow-lg:0 12px 40px rgba(0,0,0,.65);
  }
:root[data-theme="lunar-silver"]{   /* Lunar Silver */
    --toolbar-bg:#f0f4f8; --toolbar-text:#0e1014;
    --paper:#0e1014; --paper-2:#181c22; --ink:#c8d0d8; --ink-soft:#6a7888;
    --line:#2a3038; --line-2:#383f49;
    --accent:#94a3b8; --accent-deep:#74828f; --teal:#cbd5e1;
    --chrome:#181c22; --chrome-edge:#2a3038;
    --node-bg:#181c22; --node-ink:#c8d0d8;
    --canvas-dot:#2a3038;
    --stage-glow:rgba(148,163,184,.06);
    --link:#94a3b8;
    --shadow:0 2px 4px rgba(0,0,0,.35),0 8px 24px rgba(0,0,0,.50);
    --shadow-lg:0 12px 40px rgba(0,0,0,.60);
  }
*{box-sizing:border-box}
  html,body{margin:0;height:100%;overflow:hidden;font-family:var(--sans);color:var(--ink);background:var(--paper)}
  button{font-family:inherit;cursor:pointer}

  /* ===== App shell ===== */
  /* Three rows: a top header, the main content, and a status bar. Both bars
     span only the tracks to the right of the sidebar (they start beside it,
     not above/below it); .side spans all three rows and .stage is placed
     explicitly so nothing is left to auto-placement. */
  .app{display:grid;grid-template-columns:auto 1fr;grid-template-rows:auto auto minmax(0,1fr) auto;height:calc(100vh / var(--ui-zoom, 1));height:calc(100dvh / var(--ui-zoom, 1))}
  .topbar{grid-column:2 / -1;grid-row:1}
  .side{grid-column:1;grid-row:1 / 5}
  .stage{grid-column:2;grid-row:3}
  .statusbar{grid-column:2 / -1;grid-row:4}
  #tabStrip{grid-column:2/-1;grid-row:2;display:flex;align-items:flex-end;gap:6px;padding:4px 12px 0;overflow:hidden}
  #tabStrip.hidden{display:none}   /* collapsed row = auto 0, so the stage takes its place */
  #tabRow{display:flex;gap:4px;overflow-x:auto;scrollbar-width:none;flex:1;min-width:0;align-items:flex-end}
  #tabRow::-webkit-scrollbar{display:none}
  #tabRow .tab{display:flex;align-items:center;gap:6px;max-width:200px;min-width:0;padding:5px 8px 6px 10px;border:1px solid var(--line);border-bottom:none;border-radius:10px 10px 0 0;background:var(--paper-2);cursor:pointer;font-family:inherit;font-size:12px;color:var(--ink-soft);position:relative;top:1px;transition:background-color .2s ease,color .2s ease,border-color .2s ease}
  #tabRow .tab:hover{color:var(--ink)}
  #tabRow .tab.active{background:var(--paper);color:var(--ink);font-weight:600;border-color:var(--line-2)}
  #tabRow .tab-title{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  #tabRow .tab-close{width:16px;height:16px;flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;border-radius:4px;font-size:10px;line-height:1;color:var(--ink-soft)}
  #tabRow .tab-close:hover{background:var(--hover);color:var(--ink)}
  .tab-new{flex:0 0 auto;width:30px;height:26px;border:1px dashed var(--line-2);background:none;color:var(--ink-soft);border-radius:8px 8px 0 0;cursor:pointer;font-size:16px;line-height:1;font-family:inherit}
  .tab-new:hover{color:var(--accent);border-color:var(--accent)}
  /* Floating shells and single-column layouts have no top strip row -
     the tab strip stays hidden there unless tabbed workspace is enabled. */
body.ui-classic:not(.tabs-on) #tabStrip, body.ui-rail:not(.tabs-on) #tabStrip, body.ui-zen:not(.tabs-on) #tabStrip, body.ui-mirror:not(.tabs-on) #tabStrip, body.ui-deck:not(.tabs-on) #tabStrip, body.ui-dock:not(.tabs-on) #tabStrip, body.ui-split:not(.tabs-on) #tabStrip, body.ui-minimal:not(.tabs-on) #tabStrip, body.ui-outline:not(.tabs-on) #tabStrip{display:none}
body.ui-rail.tabs-on .app{grid-template-rows:auto minmax(0,1fr)}
body.ui-rail.tabs-on #tabStrip{display:flex;grid-column:3/-1;grid-row:1}
body.ui-rail.tabs-on .side{grid-row:1/3}
body.ui-rail.tabs-on .topbar{grid-row:1/3}
body.ui-rail.tabs-on .stage{grid-column:3;grid-row:2}
body.ui-rail.tabs-on.md-ready .app{grid-template-rows:auto minmax(0,1fr)}
body.ui-rail.tabs-on.md-ready #tabStrip{grid-column:3/-1;grid-row:1}
body.ui-rail.tabs-on.md-ready #mdPane{grid-column:3;grid-row:2}
body.ui-rail.tabs-on.md-ready .stage{grid-column:4;grid-row:2}
body.ui-classic.tabs-on .app{grid-template-rows:auto minmax(0,1fr)}
body.ui-classic.tabs-on #tabStrip{display:flex;grid-column:2;grid-row:1}
body.ui-classic.tabs-on .side{grid-row:1/3}
body.ui-classic.tabs-on .stage{grid-column:2;grid-row:2}
body.ui-classic.tabs-on.md-ready .app{grid-template-rows:auto minmax(0,1fr)}
body.ui-classic.tabs-on.md-ready #tabStrip{grid-column:2/-1;grid-row:1}
body.ui-classic.tabs-on.md-ready #mdPane{grid-column:2;grid-row:2}
body.ui-classic.tabs-on.md-ready .stage{grid-column:3;grid-row:2}
  body.focus-mode #tabStrip{display:none}   /* focus is canvas-only */
  body.shared-view #tabStrip{display:none}  /* shared banner view is single-map */
  #tabRow .tab.active .tab-close{color:var(--ink-soft)}
  /* Markdown mode: split pane (editor | live map) */
  body.md-ready .app{grid-template-columns:auto auto minmax(0,1fr)}   /* md pane takes the middle track once it exists */
  #mdPane{width:0;overflow:hidden;position:relative;display:flex;flex-direction:column;min-width:0;min-height:0;background:var(--paper);border-right:1px solid var(--line);transition:width .22s cubic-bezier(.4,0,.2,1);grid-column:2;grid-row:3}
  body.md-ready .stage{grid-column:3;grid-row:3}
  body.md-mode #mdPane{width:var(--md-w,40vw)}
  body:not(.md-mode) #mdPane{border-right-width:0}   /* a closed pane must be 0 wide, not 1px of border - see #outlinePane */
  body.md-resizing #mdPane{transition:none}                            /* no easing while dragging the divider */
  @media (prefers-reduced-motion: reduce){ #mdPane{transition:none} }
  #mdPane .md-head{display:flex;align-items:center;gap:8px;padding:8px 12px;border-bottom:1px solid var(--line);font-size:12px;font-weight:600;color:var(--ink-soft)}
  #mdPane .md-pos{margin-left:auto;font-size:11px;font-weight:400;color:var(--ink-soft);font-variant-numeric:tabular-nums}
  /* markdown editor formatting toolbar */
  #mdPane .md-toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:2px;padding:4px 8px;border-bottom:1px solid var(--line);background:var(--paper)}
  #mdPane .md-toolbar button{min-width:26px;height:26px;padding:0 6px;border:1px solid transparent;background:transparent;color:var(--ink-soft);cursor:pointer;border-radius:6px;font-size:12px;font-weight:600;line-height:1;display:inline-flex;align-items:center;justify-content:center}
  #mdPane .md-toolbar button:hover{background:var(--paper-2,rgba(127,127,127,.12));color:var(--ink);border-color:var(--line)}
  #mdPane .md-toolbar button s{text-decoration:line-through}
  #mdPane .md-toolbar .md-sep{width:1px;height:16px;background:var(--line);margin:0 4px}
  #mdPane.md-preview .md-toolbar{display:none}
  #mdPane .md-close{border:none;background:transparent;cursor:pointer;font-size:15px;line-height:1;color:var(--ink-soft);padding:2px 7px;border-radius:6px}
  #mdPane .md-close:hover{background:var(--paper-2,rgba(0,0,0,.05))}
  #mdPane .md-body{display:flex;flex:1;min-height:0;overflow:hidden}
  #mdPane .md-gutter{flex:0 0 auto;box-sizing:border-box;padding:12px 6px 12px 8px;text-align:right;overflow:hidden;user-select:none;background:var(--paper);border-right:1px solid var(--line);color:var(--ink-soft);font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:13px;line-height:20px}
  #mdPane .md-gutter .gl{height:20px;display:flex;align-items:center;justify-content:flex-end;gap:1px}
  #mdPane .md-gutter .gl.active{color:var(--accent);font-weight:700}
  #mdPane .md-gutter .gl-fold{flex:0 0 12px;width:12px;height:16px;display:inline-flex;align-items:center;justify-content:center;font-size:9px;line-height:1;border-radius:3px;cursor:pointer;color:var(--ink-soft);opacity:.7}
  #mdPane .md-gutter .gl-fold:empty{cursor:default}
  #mdPane .md-gutter .gl-fold:not(:empty):hover{background:color-mix(in srgb, var(--ink-soft) 20%, transparent);opacity:1}
  #mdPane .md-gutter .gl-num{min-width:1.6em}
  #mdPane .md-code{position:relative;flex:1;min-width:0;overflow:hidden}
  #mdPane .md-hl,#mdEditor{position:absolute;inset:0;margin:0;box-sizing:border-box;padding:12px 14px;border:0;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:13px;line-height:20px;white-space:pre;tab-size:2}
  #mdPane .md-hl{overflow:hidden;pointer-events:none;color:var(--ink)}
  /* Scroll-sync targets a plain inner wrapper via transform, not the outer .md-hl/.md-gutter
     (which must stay put so their own overflow:hidden keeps clipping the visible window). */
  #mdPane .md-hl-inner,#mdPane .md-gutter-inner{will-change:transform}
  #mdPane .md-hl .hl-line{min-height:20px}
  /* active-line highlight: a real background on the actual row div - it's always exactly
     where the caret is, in or out of view, with no separate pixel math to keep in sync
     while clicking or scrolling (that used to drift; this can't). */
  #mdPane .md-hl .hl-line.active{background:var(--paper-2,rgba(127,127,127,.10))}
  #mdPane .md-fold-chip{display:inline-block;margin-left:6px;padding:0 7px;border-radius:8px;background:color-mix(in srgb, var(--ink-soft) 16%, transparent);color:var(--ink-soft);font-size:11px;font-style:normal}
  #mdPane .md-hl{z-index:1}
  #mdEditor{z-index:2}
  /* rendered preview */
  #mdPane .md-prev-btn{margin-left:2px;border:1px solid var(--line);background:transparent;color:var(--ink-soft);cursor:pointer;font-size:11px;font-weight:600;padding:2px 9px;border-radius:6px}
  #mdPane .md-prev-btn.on{background:var(--accent);color:#fff;border-color:var(--accent)}
  #mdPane .md-wrap-btn{margin-left:2px;border:1px solid var(--line);background:transparent;color:var(--ink-soft);cursor:pointer;font-size:11px;font-weight:600;padding:2px 9px;border-radius:6px}
  #mdPane .md-wrap-btn.on{background:var(--accent);color:#fff;border-color:var(--accent)}
  #mdPane.md-preview .md-wrap-btn{display:none}
  /* Word wrap: the textarea and highlight overlay share this rule so switching both to
     pre-wrap at once keeps them pixel-aligned (identical font/width/padding/text, so the
     browser wraps them the same way). The gutter's rows are normally a fixed 20px each
     (one line = one row); once wrapped, a line can span several visual rows, so
     mdSyncGutterRowHeights() overrides each .gl row's height in JS to match its
     corresponding .hl-line's actual (now possibly taller) rendered height. */
  #mdPane.md-wrap .md-hl,#mdPane.md-wrap #mdEditor{white-space:pre-wrap;overflow-wrap:anywhere}
  #mdPane .md-pdf-btn{display:none;border:1px solid var(--line);background:transparent;color:var(--ink-soft);cursor:pointer;font-size:11px;font-weight:600;padding:2px 9px;border-radius:6px}
  #mdPane .md-pdf-btn:hover{background:var(--paper-2,rgba(127,127,127,.12));color:var(--ink)}
  #mdPane.md-preview .md-pos{display:none}
  #mdPane.md-preview .md-pdf-btn{display:inline-flex;margin-left:auto}
  #mdPane .md-prev{position:absolute;inset:0;display:none;overflow:auto;padding:16px 22px;background:var(--paper);color:var(--ink);z-index:4;line-height:1.6;text-align:left}
  #mdPane.md-preview .md-prev{display:block}
  #mdPane.md-preview .md-hl,#mdPane.md-preview #mdEditor,#mdPane.md-preview .md-gutter{display:none}
  #mdPane .md-prev h1,#mdPane .md-prev h2,#mdPane .md-prev h3{margin:.6em 0 .3em;line-height:1.25}
  #mdPane .md-prev h1{font-size:1.6em;border-bottom:1px solid var(--line);padding-bottom:.2em}
  #mdPane .md-prev h2{font-size:1.3em;border-bottom:1px solid var(--line);padding-bottom:.2em}
  #mdPane .md-prev h3{font-size:1.1em}
  #mdPane .md-prev p,#mdPane .md-prev ul,#mdPane .md-prev ol,#mdPane .md-prev blockquote{margin:.5em 0}
  #mdPane .md-prev pre.mp-code{background:var(--paper-2,rgba(127,127,127,.10));padding:10px 12px;border-radius:8px;overflow:auto;font-size:12.5px}
  #mdPane .md-prev code{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
  #mdPane .md-prev table{border-collapse:collapse;font-size:.95em}
  #mdPane .md-prev th,#mdPane .md-prev td{border:1px solid var(--line);padding:5px 9px}
  #mdPane .md-prev th{background:var(--paper-2,rgba(127,127,127,.12));font-weight:700;text-align:left}
  #mdPane .md-prev blockquote{border-left:3px solid var(--line);margin-left:0;padding:.2em 0 .2em 12px;color:var(--ink-soft)}
  #mdPane .md-prev img{max-width:100%}
  #mdPane .md-prev hr{border:0;border-top:1px solid var(--line);margin:1em 0}
  #mdPane .md-prev a{color:#3b82f6}
  #mdPane .md-prev math{font-size:1.04em}
  #mdPane .md-prev math[display="block"]{display:block;margin:.6em auto;text-align:center}
  /* horizontal-rule divider node */
  .node.hr-node{min-width:54px;box-shadow:none}
  .node.hr-node .node-hr{display:block;width:54px;height:0;border-top:2px solid var(--ink-soft,#98a2b3);opacity:.6}
  #mdEditor{overflow:auto;resize:none;outline:none;background:transparent;color:transparent;caret-color:var(--ink)}
  #mdEditor::selection{background:color-mix(in srgb, var(--accent) 28%, transparent)}
  /* markdown syntax colors - driven by theme variables, so they follow the theme */
  #mdPane .hl-head{color:var(--accent);font-weight:700}
  #mdPane .hl-comment{color:var(--ink-soft);opacity:.6;font-style:italic}
  #mdPane .hl-code,#mdPane .hl-fence,#mdPane .hl-code-inline{color:var(--accent-deep,var(--accent))}
  #mdPane .hl-strong{color:var(--ink);font-weight:700}
  #mdPane .hl-em{color:var(--ink);font-style:italic}
  #mdPane .hl-link,#mdPane .hl-img{color:#3b82f6}
  #mdPane .hl-bullet,#mdPane .hl-task{color:var(--accent);font-weight:700}
  #mdPane .hl-quote{color:var(--ink-soft);font-style:italic}
  #mdPane .hl-punc{color:var(--ink-soft)}
  #mdPane .hl-hmark{color:var(--ink-soft);font-weight:700}
  #mdPane .hl-strike{color:var(--ink-soft);text-decoration:line-through}
  #mdPane .hl-hr{color:var(--ink-soft)}
  #mdPane .hl-tag{color:#22a06b}
  #mdPane .hl-url{color:#3b82f6;text-decoration:underline}
  #mdPane .md-resize{position:absolute;top:0;right:0;width:7px;height:100%;cursor:col-resize;z-index:6}
  .tb#mdToggle.on{background:var(--accent);color:#fff}

  /* ===== Sidebar ===== */
  .side{width:268px;min-height:0;position:relative;background:var(--chrome);border-right:1px solid var(--chrome-edge);display:flex;flex-direction:column;transition:width .22s cubic-bezier(.4,0,.2,1),background-color .3s ease,border-color .3s ease}
  /* width is !important on every collapsed rule: the expand path writes an
     inline width, and whichever code collapses the sidebar next must win over
     it or the column stays open and blank. */
  .side.collapsed{width:36px !important;border:none}                 /* icon rail instead of fully gone */
  .side.resizing{transition:none}
  .side.collapsed .brand{display:none !important}  /* never bleed into the slim rail */
  .side.collapsed .side-tabs,
  .side.collapsed .side-pane,
  .side.collapsed .side-foot,
  .side.collapsed .new-map-row,   /* classic's wide "New mind map" row; left out, it overflowed a 0px sidebar into the tab strip */
  .side.collapsed .side-resize{display:none !important}
  /* Collapsed state = slim rail with the reopen button, so the sidebar can
     never get "lost". The same ☰ button sits in the brand header, beside
     the MindSpark title. */
  .side-rail{display:none;width:36px;flex:1 0 auto;justify-content:center;align-items:center}
  .side.collapsed .side-rail{display:flex}
  .side-rail .tb{background:none;border:none}
  /* Drag handle on the sidebar's right edge (desktop only) */
  .side-resize{position:absolute;top:0;right:-4px;width:8px;height:100%;cursor:col-resize;z-index:10;opacity:0;transition:opacity .15s}
  .side-resize:hover,.side-resize:active{opacity:.55;background:var(--accent)}
  .side-tabs{display:flex;gap:2px;padding:0 10px 10px}
  .side-tab{flex:1;padding:7px 6px;border:none;background:none;border-radius:9px;font-family:inherit;font-size:12.5px;font-weight:600;color:var(--ink-soft);cursor:pointer;display:flex;align-items:center;justify-content:center;gap:6px;white-space:nowrap}
  .side-tab:hover{background:var(--hover);color:var(--ink)}
  .side-tab.active{background:var(--paper-2);color:var(--ink)}
  .side-pane{flex:1;min-height:0;display:flex;flex-direction:column}
  /* Tab switching is class-based (never inline styles) so the collapsed-rail
     rules below always win: `.side-pane:not(.active)` is hidden, the active
     pane is shown, and `.side.collapsed` (declared later + !important) hides
     everything inside the slim rail. */
  .side-pane.active{display:flex}
  .side-pane:not(.active){display:none}
  /* Template list inside the sidebar Templates tab */
  .tpl-side-hdr{font-size:10.5px;text-transform:uppercase;letter-spacing:.1em;color:var(--accent);font-weight:700;padding:12px 8px 4px}
  .tpl-side-item{display:flex;align-items:center;gap:10px;width:100%;text-align:left;padding:8px 10px;border:none;background:none;border-radius:10px;cursor:pointer;font-family:inherit;color:var(--ink);margin:1px 0}
  .tpl-side-item:hover{background:var(--hover)}
  .tpl-side-ic{width:30px;height:30px;flex-shrink:0;display:flex;align-items:center;justify-content:center;color:#fff;border-radius:8px;font-size:14px}
  .tpl-side-meta{display:flex;flex-direction:column;line-height:1.3;min-width:0}
  .tpl-side-meta b{font-weight:600;font-size:13px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .tpl-side-meta i{font-style:normal;color:var(--ink-soft);font-size:11.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  @media (prefers-reduced-motion: reduce){ .side, #viewport{transition:none !important} }
  .brand{display:flex;align-items:center;gap:10px;padding:18px 18px 14px}
  .brand .mark{flex:0 0 auto; filter:drop-shadow(0 1px 3px rgba(40,30,15,.2))}
  .brand h1{font-family:var(--serif);font-weight:900;font-size:22px;margin:0;letter-spacing:-.5px}
  .brand h1 span{color:var(--accent)}
  .brand #newMap,
  .brand #toggleSide{width:32px;height:32px;flex:0 0 auto;font-size:16px}
  .brand #newMap{margin-left:auto}
  .brand #newMap:hover,
  .brand #toggleSide:hover{background:var(--hover)}
  .side-scroll{flex:1;min-height:0;overflow-y:auto;padding:6px 10px 12px}
  .side-label{font-size:11px;text-transform:uppercase;letter-spacing:.12em;color:var(--ink-soft);padding:10px 8px 6px;font-weight:700}
  .map-item{display:flex;align-items:center;gap:8px;padding:9px 10px;border-radius:10px;margin:2px 0;cursor:pointer;position:relative}
  .map-item:hover{background:var(--hover)}
  .map-item.active{background:var(--chrome);box-shadow:var(--shadow)}
  .map-item .dot{width:8px;height:8px;border-radius:50%;flex:0 0 auto}
  .map-item .nm{flex:1;font-size:14px;font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .map-item .row-menu{opacity:0;border:none;background:none;color:var(--ink-soft);padding:2px 5px;border-radius:6px;font-size:17px;line-height:1;flex:0 0 auto;cursor:pointer;transition:opacity .12s}
  .map-item:hover .row-menu, .map-item.active .row-menu{opacity:.65}
  .map-item .row-menu:hover{opacity:1;background:var(--line);color:var(--ink)}
  @media (pointer:coarse){ .map-item .row-menu{opacity:.6} }   /* always tappable on touch */
  .row-pop{position:fixed;background:var(--paper,#fff);border:1px solid var(--chrome-edge,#d0d7de);border-radius:10px;box-shadow:var(--shadow,0 8px 28px rgba(0,0,0,.16));padding:5px;min-width:152px;z-index:400;display:flex;flex-direction:column;gap:2px}
  .row-pop button{display:flex;align-items:center;gap:9px;width:100%;text-align:left;border:none;background:none;color:var(--ink);font-size:13.5px;padding:8px 10px;border-radius:7px;cursor:pointer;font-family:inherit}
  .row-pop button:hover{background:var(--hover)}
  .row-pop button.danger{color:var(--accent-deep,#b8451f)}
  .row-pop button.danger:hover{background:rgba(184,69,31,.10)}
  .row-pop .rp-ic{width:16px;text-align:center;opacity:.85;font-size:14px}
  .side-foot{padding:12px 16px;padding-bottom:calc(12px + env(safe-area-inset-bottom, 0px));border-top:1px solid var(--chrome-edge);font-size:11.5px;color:var(--ink-soft);line-height:1.5}
  .side-foot b{color:var(--ink)}
  .qotd-sep{height:1px;background:var(--chrome-edge);margin:12px -16px 0;opacity:.9}
  .side-foot:has(#qotd[hidden]) .qotd-sep{display:none}
  .qotd{position:relative;margin-top:12px;padding:8px 10px 8px 10px;border-left:2px solid var(--accent);background:color-mix(in srgb, var(--accent) 7%, transparent);border-radius:0 8px 8px 0}
  .qotd[hidden]{display:none}
  .qotd-text{font-size:12px;line-height:1.45;color:var(--ink);font-style:italic;white-space:pre-wrap;word-break:break-word}
  .qotd-text::before{content:'“'} .qotd-text::after{content:'”'}
  .qotd-author{margin-top:4px;font-size:10.5px;color:var(--ink-soft);text-align:right;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
  .qotd-author::before{content:'- '}
  .qotd-refresh{position:absolute;top:4px;right:4px;width:20px;height:20px;display:grid;place-items:center;border:none;background:transparent;color:var(--ink-soft);border-radius:6px;cursor:pointer;font-size:12px;line-height:1;opacity:0;transition:opacity .15s, background-color .15s}
  .qotd:hover .qotd-refresh{opacity:1}
  .qotd-refresh:hover{background:var(--hover);color:var(--ink)}
  .side.collapsed .qotd{display:none}

  /* ===== Canvas region ===== */
  .stage{position:relative;overflow:hidden;background:
    radial-gradient(circle at 1px 1px,var(--canvas-dot) 1px,transparent 0);
    background-size:26px 26px;background-color:var(--paper)}
  .stage:before{content:"";position:absolute;inset:0;pointer-events:none;
    background:radial-gradient(ellipse at 50% 0%,var(--stage-glow),transparent 60%)}
  #viewport{position:absolute;inset:0;transform-origin:0 0}
  #edges{position:absolute;left:0;top:0;overflow:visible;pointer-events:none}

  /* ===== Top header - full-width bar, mirrors the status bar's strip look ===== */
  .topbar{display:flex;align-items:center;gap:8px;padding:5px 10px;background:var(--chrome);border-bottom:1px solid var(--chrome-edge);z-index:30;flex-wrap:wrap;row-gap:4px;min-width:0}
  .tb-group{display:flex;align-items:center;gap:2px;padding:0;background:none;border:none;border-radius:0;box-shadow:none}
  .tb{border:none;background:none;color:var(--ink);width:36px;height:34px;border-radius:8px;display:grid;place-items:center;font-size:16px;white-space:nowrap}
  .tb:hover{background:var(--hover)}
  .tb:disabled{opacity:.32;cursor:default}
  .tb.wide{width:auto;padding:0 12px;font-size:13.5px;font-weight:600;gap:7px}
  .tb.primary{background:var(--accent);color:#fff}
  .tb.primary:hover{background:var(--accent-deep)}
  .title-edit{font-family:var(--serif);font-weight:600;font-size:19px;border:none;background:transparent;color:var(--ink);padding:6px 12px;min-width:120px;max-width:340px;border-radius:9px;outline:none}
  .title-edit:hover,.title-edit:focus{background:var(--chrome)}
  /* Hairline separator between topbar clusters (outside any .tb-group) */
  .tb-sep{width:1px;height:26px;background:var(--chrome-edge);flex:0 0 auto}
  .spacer{flex:1}
  .search-wrap{display:flex;align-items:center;background:none;border:none;border-radius:0;box-shadow:none;overflow:hidden;width:0;transition:width .22s,background-color .3s ease,border-color .3s ease,color .3s ease}
  .search-wrap.open{width:230px;background:var(--paper-2);border-radius:9px}
  .search-wrap.open.replace-mode{width:420px}
  .search-wrap input{border:none;background:none;outline:none;font-family:inherit;font-size:12px;color:var(--ink);padding:9px 12px;width:100%;min-width:0}
  .search-wrap #replace,.search-wrap .search-act{display:none}
  .search-wrap.replace-mode #replace{display:block;border-left:1px solid var(--chrome-edge)}
  .search-wrap.replace-mode .search-act{display:inline-flex}
  .search-count{font-size:11px;color:var(--ink-soft);white-space:nowrap;padding:0 8px;flex-shrink:0}
  .search-toggle{border:none;background:none;cursor:pointer;color:var(--ink-soft);font-size:14px;padding:8px 10px;flex-shrink:0;border-radius:0}
  .search-toggle:hover{background:var(--hover);color:var(--ink)}
  .search-act{border:none;background:none;cursor:pointer;color:var(--accent);font-size:12px;font-weight:600;padding:8px 11px;flex-shrink:0;font-family:inherit;align-items:center}
  .search-act:hover{background:var(--hover)}
  .node.match{outline:2.5px solid var(--accent);outline-offset:2px}
  .node.match-current{outline:3px solid var(--accent);outline-offset:2px;box-shadow:0 0 0 6px color-mix(in srgb, var(--accent) 22%, transparent)}
  .node.dim{opacity:.32;transition:opacity .15s}
  .save-pill{font-size:12px;color:var(--ink-soft);background:var(--chrome);border:1px solid var(--chrome-edge);border-radius:20px;padding:6px 13px;box-shadow:var(--shadow);font-weight:500;display:flex;align-items:center;gap:6px}
  .save-pill .ring{width:8px;height:8px;border-radius:50%;background:var(--teal)}
  .save-pill.saving .ring{background:var(--accent);animation:pulse 1s infinite}
  @keyframes pulse{50%{opacity:.3}}

  /* ===== Bottom controls - one "overview" card =====
     Minimap and zoom controls live inside the status bar as a single chip.
     Hovering it expands the breadcrumb (see .breadcrumb.shown). Collapses to
     a stub via the chevron (state persisted in JS). */
  .overview{flex:0 0 auto;display:flex;align-items:center;gap:7px;padding:2px 6px;border-radius:8px}
  .overview:hover{background:var(--hover)}
  .overview .minimap{position:static;border-radius:6px;box-shadow:none}
  .zoom-row{display:flex;align-items:center;gap:3px}
  .zoom-row button{border:none;background:none;width:28px;height:26px;border-radius:7px;font-size:15px;color:var(--ink);flex:0 0 auto;display:grid;place-items:center}
  .zoom-row button:hover{background:var(--hover)}
  #zoomSlider{flex:1;min-width:0;width:70px;accent-color:var(--accent);height:16px;margin:0;cursor:pointer}
  .zoom-val{font-size:11px;text-align:center;color:var(--ink-soft);font-weight:600;padding:3px 4px;border-radius:5px;cursor:pointer;min-width:38px;outline:none;flex:0 0 auto}
  .zoom-val:hover{background:var(--hover);color:var(--ink)}
  .zoom-val[contenteditable="true"]{background:#fff;box-shadow:0 0 0 2px var(--accent);color:var(--ink)}
  .overview-toggle{border:none;background:none;color:var(--ink-soft);font-size:11px;width:22px;height:22px;flex:0 0 auto;border-radius:6px;cursor:pointer;display:grid;place-items:center;transition:transform .18s}
  .overview-toggle:hover{background:var(--hover);color:var(--ink)}
  .overview.collapsed{padding:2px}
  .overview.collapsed .minimap,
  .overview.collapsed .zoom-row{display:none}
  .overview.collapsed .overview-toggle{transform:rotate(-90deg)}

  /* ===== Status bar - bottom strip under the canvas ===== */
  .statusbar{display:flex;align-items:center;gap:14px;padding:5px 14px;background:var(--chrome);border-top:1px solid var(--chrome-edge);min-height:34px;font-family:var(--sans)}
  .statusbar .hint{
    display:flex;align-items:center;gap:6px;position:static;margin:0;
    background:none;border:none;box-shadow:none;border-radius:0;padding:0;
    font-size:12px;color:var(--ink-soft);max-width:70%;line-height:1.5;flex:1;min-width:0;
  }
  .statusbar .hint b{color:var(--ink);font-weight:600}
  /* The hint's text lives in its own span so it can shrink and ellipsize as a
     single unit - the bar shrinks when the overview collapses (the chip is
     content-sized), so without this the text would re-wrap into a ragged
     multi-line mess every time the overview is toggled. */
  .statusbar .hint .hint-text{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
  .statusbar .hint .close{border:none;background:none;color:var(--ink-soft);font-size:14px;line-height:1;padding:2px 5px;border-radius:5px;cursor:pointer;flex:0 0 auto}
  .statusbar .hint .close:hover{background:var(--hover);color:var(--ink)}
  .statusbar .save-pill,
  .statusbar .token-total{font-size:11.5px;padding:4px 11px;box-shadow:none}
  .statusbar .user-pill{height:28px;font-size:12px}
  .statusbar .user-pill img{width:20px;height:20px}
  .sb-right{margin-left:auto;display:flex;align-items:center;gap:10px;flex:0 0 auto}
  .hint b{color:var(--ink);font-weight:600}
  .hint kbd{font-family:var(--sans);background:var(--paper-2);border:1px solid var(--line);border-radius:5px;padding:1px 6px;font-size:11px;font-weight:600;color:var(--ink)}
  .hint .close{float:right;margin-left:8px;cursor:pointer;color:var(--ink-soft);border:none;background:none;font-size:14px}

  /* ===== Nodes ===== */
  .node{position:absolute;background:var(--card-bg);border:1.5px solid var(--line);border-radius:12px;padding:9px 15px;font-size:15px;font-weight:500;line-height:1.35;box-shadow:var(--shadow);width:max-content;max-width:240px;min-width:34px;user-select:none;transition:background-color .3s ease,color .3s ease,box-shadow .15s,border-color .15s,transform .06s;white-space:pre-wrap;overflow-wrap:anywhere;word-break:break-word;display:flex;align-items:center;justify-content:center;text-align:center;box-sizing:border-box}
  .node:hover{box-shadow:var(--shadow-lg)}
  .node.root{font-family:var(--serif);font-weight:600;font-size:19px;padding:12px 22px;border-width:0}
  .node.sel{outline:2.5px solid var(--accent);outline-offset:2px}
  .node.editing{cursor:text;user-select:text;outline:none !important;box-shadow:none}
  .node.editing .node-text{outline:none}
  .node.dim{opacity:.28}
  .node.match{outline:2.5px solid var(--teal);outline-offset:2px}
  .node .badge{display:none}  /* legacy, no longer rendered */
  /* Zebra striping - XMind-style alternating tint by tree depth. Only affects
     uncoloured nodes: the root and user-picked card colours carry inline
     background styles that win over these classes. Subtle color-mix so the
     stripes follow every theme, and they ride the theme-switch transition. */
  :root{
    --zebra-1:color-mix(in srgb, var(--card-bg) 93%, var(--accent));
    --zebra-2:color-mix(in srgb, var(--card-bg) 93%, var(--teal));
  }
  .node[data-depth="1"],.node[data-depth="3"],.node[data-depth="5"],
  .node[data-depth="7"]{background:var(--zebra-1)}
  .node[data-depth="2"],.node[data-depth="4"],.node[data-depth="6"],
  .node[data-depth="8"]{background:var(--zebra-2)}
  /* Hover-only "created/last edited" watermark - sits just above the node (not inside it,
     which used to collide with the node's own vertically-centered text on shorter nodes)
     so it never overlaps the actual content. */
  .node .node-watermark{
    position:absolute; left:0; right:0; bottom:100%; margin-bottom:3px;
    pointer-events:none; overflow:hidden;
    font-family:var(--sans); font-size:9px; font-weight:600; letter-spacing:.02em;
    color:var(--ink-soft); opacity:0;
    transition:opacity .18s ease;
    white-space:nowrap; text-overflow:ellipsis;
    text-align:center;
  }
  .node:hover .node-watermark{opacity:.85}
  .node.editing .node-watermark{opacity:0 !important}   /* never fight with the caret while typing */
  /* Formula nodes ("=SUM(children)" etc): a small fx badge marks the node as a live
     calculation, and the result shows in a tabular-numeral style so a column of computed
     values lines up like a spreadsheet. The title tooltip (native, on hover) reveals the
     actual formula text. */
  .node.formula-node{position:relative}
  .node.formula-node::before{
    content:'\0192x'; position:absolute; top:-7px; left:-7px;
    width:16px; height:16px; border-radius:50%;
    background:var(--accent); color:#fff;
    font-size:9px; font-weight:700; font-style:normal;
    display:flex; align-items:center; justify-content:center;
    box-shadow:0 1px 3px rgba(0,0,0,.25);
    pointer-events:none;
  }
  .node.formula-node .node-text{font-variant-numeric:tabular-nums}
  .node.formula-error{border-color:#e5484d}
  .node.formula-error::before{background:#e5484d}
  .node.formula-error .node-text{color:#e5484d}
  /* Frontmatter node (a skill.md's YAML name/description block, etc.): a small badge marks
     it as metadata rather than regular outline content - the table itself is the normal
     block-node table rendering, this is purely a visual "what is this" hint. */
  .node.frontmatter-node{position:relative}
  .node.frontmatter-node::before{
    content:'YAML'; position:absolute; top:-9px; left:8px;
    padding:1px 5px; border-radius:4px;
    background:var(--teal); color:#fff;
    font-size:8px; font-weight:700; font-style:normal; letter-spacing:.03em;
    box-shadow:0 1px 3px rgba(0,0,0,.25);
    pointer-events:none;
  }
  /* Formula function autocomplete popup (Excel-style "=SU" -> suggests SUM) */
  .formula-ac{
    position:fixed; z-index:1200; min-width:220px; max-width:320px; max-height:220px;
    overflow-y:auto; background:var(--chrome); border:1px solid var(--line);
    border-radius:8px; box-shadow:var(--shadow-lg); padding:4px; font-family:var(--sans);
  }
  .formula-ac-row{
    display:flex; flex-direction:column; gap:1px; padding:5px 8px; border-radius:5px;
    cursor:pointer; line-height:1.3;
  }
  .formula-ac-row.active,.formula-ac-row:hover{background:var(--accent); }
  .formula-ac-row.active .formula-ac-sig,.formula-ac-row:hover .formula-ac-sig,
  .formula-ac-row.active .formula-ac-desc,.formula-ac-row:hover .formula-ac-desc{color:#fff}
  .formula-ac-sig{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12.5px;font-weight:700;color:var(--ink)}
  .formula-ac-desc{font-size:11px;color:var(--ink-soft)}

  /* ===== Quick-action handles on nodes (appear on hover) ===== */
  .node .handle{
    position:absolute; width:22px; height:22px; border-radius:50%;
    display:flex; align-items:center; justify-content:center;
    font-size:15px; font-weight:600; line-height:1; cursor:pointer;
    user-select:none; box-shadow:0 2px 5px rgba(0,0,0,.22);
    border:2px solid var(--card-bg, #fff); opacity:0; transition:opacity .12s, transform .1s;
    z-index:8;
  }
  .node:hover .handle{opacity:1}
  .node .handle:hover{transform:scale(1.15)}
  .node.editing .handle{display:none}

  /* Collapse / expand - at the outer edge, always visible (subtle) */
  .node .h-collapse{
    background:var(--card-bg, #fff); color:var(--ink); border:1.5px solid var(--line-2);
    width:18px; height:18px; font-size:13px; opacity:.8;
    right:-10px; top:50%; margin-top:-9px;
  }
  .node:hover .h-collapse{opacity:1}
  .node .h-collapse.collapsed{background:var(--accent);color:#fff;border-color:var(--accent);opacity:1}
  .node.left .h-collapse{left:-10px;right:auto}

  /* Add child - outer edge (right for right-side / root, left for left-side) */
  .node .h-child{background:var(--accent);color:#fff;right:-32px;top:50%;margin-top:-11px}
  .node.left .h-child{left:-32px;right:auto}

  /* Add sibling - below the node, centered */
  .node .h-sibling{background:var(--teal);color:#fff;bottom:-30px;left:50%;margin-left:-11px}

  /* Resize grip - bottom-right corner, visible only on selected nodes */
  .node .resize-grip{
    position:absolute; right:-2px; bottom:-2px; width:14px; height:14px;
    cursor:nwse-resize; opacity:0; pointer-events:none; transition:opacity .12s;
    background:
      linear-gradient(135deg, transparent 40%, var(--accent) 40%, var(--accent) 55%, transparent 55%,
                              transparent 65%, var(--accent) 65%, var(--accent) 80%, transparent 80%);
    border-bottom-right-radius:12px;
  }
  .node.sel .resize-grip{opacity:.9; pointer-events:auto}
  .node .resize-grip:hover{opacity:1}
  .node.editing .resize-grip{display:none}

  /* Drop-target highlight while drag-and-drop reparenting. The three modes
     need to be clearly distinguishable at a glance during a fast drag, not
     just technically different - before/after (sibling insertion) previously
     had only a bare 3px line hugging the node's own edge, much weaker than
     the child-nest treatment below it. Strengthened to a thicker line that
     extends past the node's own width (box-shadow spread, not just blur) so
     it reads as a real insertion marker, plus a background tint so there's
     more than one signal to notice mid-drag. */
  .node.drop-before{
    box-shadow:0 -5px 0 3px var(--accent), var(--shadow);
    background:color-mix(in srgb, var(--accent) 12%, var(--card-bg)) !important;
  }
  .node.drop-after{
    box-shadow:0 5px 0 3px var(--accent), var(--shadow);
    background:color-mix(in srgb, var(--accent) 12%, var(--card-bg)) !important;
  }
  /* File-drop target - deliberately distinct from .drop-target above.
     That one means "nest as child" during node dragging; this one means
     "attach the image you are holding". Using the same visual would
     promise the wrong action. */
  .node.file-drop{
    outline:3px dashed var(--teal, #2f6f6a); outline-offset:5px;
    box-shadow:0 0 0 6px color-mix(in srgb, var(--teal, #2f6f6a) 22%, transparent);
  }
  .node.drop-target{
    outline:3px dashed var(--accent); outline-offset:5px;
    background:linear-gradient(0deg,
      color-mix(in srgb, var(--accent) 22%, var(--card-bg)),
      color-mix(in srgb, var(--accent) 22%, var(--card-bg))) !important;
    box-shadow:0 0 0 6px color-mix(in srgb, var(--accent) 20%, transparent);
  }

  /* Notes indicator - small page-icon at the top-right of nodes with a note */
  .node .notes-mark{
    position:absolute; top:-9px; right:-9px;
    width:22px; height:22px; border-radius:4px;
    background:var(--sticky, #fff7b0); border:1.5px solid var(--sticky-edge, #f2e27a);
    display:flex; align-items:center; justify-content:center;
    font-size:11px; cursor:pointer; z-index:6;
    box-shadow:0 1px 3px rgba(0,0,0,.18); transform:rotate(-6deg);
  }
  .node .notes-mark:hover{transform:rotate(0deg) scale(1.12)}
  .node.left .notes-mark{right:auto; left:-9px}

  /* List rendering inside a node */
  .node-text-list .list-marker{display:inline-block; min-width:1.6em; opacity:.7; user-select:none}

  /* Alignment-picker glyphs */
  .align-icon{display:inline-block; font-family:monospace; font-size:13px; line-height:1}
  .align-icon.align-left{text-align:left}
  .align-icon.align-center{text-align:center}
  .align-icon.align-right{text-align:right}

  /* ===== Notes editor - styled as a sticky note ===== */
  :root{ --sticky:#fff7b0; --sticky-edge:#f2e27a; --sticky-ink:#4a431f; }
  :root[data-theme="dark"], :root[data-theme="night-owl"], :root[data-theme="dracula"], :root[data-theme="catppuccin-dark"],
  :root[data-theme="rose-pine-moon"], :root[data-theme="nord"], :root[data-theme="github-dark"],
  :root[data-theme="slate-steel"], :root[data-theme="vscode-onedark"], :root[data-theme="monokai-pro"], :root[data-theme="amazon-aws"],
  :root[data-theme="synthwave"], :root[data-theme="matrix-green"],
  :root[data-theme="carbon-amber"], :root[data-theme="cyber-quantum"], :root[data-theme="blueprint"], :root[data-theme="obsidian"],
  :root[data-theme="deep-ocean"], :root[data-theme="google-material"], :root[data-theme="github-modern"], :root[data-theme="aurora-frost"],
  :root[data-theme="espresso"], :root[data-theme="copper-lab"], :root[data-theme="forest-night"], :root[data-theme="cobalt"],
  :root[data-theme="ruby-night"], :root[data-theme="electric-indigo"], :root[data-theme="steel-orange"], :root[data-theme="cosmic-rose"],
  :root[data-theme="plasma-crimson"], :root[data-theme="neon-noir"], :root[data-theme="ember-forge"], :root[data-theme="violet-circuit"],
  :root[data-theme="twilight-amber"], :root[data-theme="ocean-depth"], :root[data-theme="charcoal-gold"], :root[data-theme="azure-horizon"],
  :root[data-theme="jade-temple"], :root[data-theme="magenta-pulse"], :root[data-theme="graphite-terminal"], :root[data-theme="frosted-pine"],
  :root[data-theme="quantum-violet"], :root[data-theme="copper-rust"], :root[data-theme="lunar-silver"]{
    --sticky:#3a3520; --sticky-edge:#5c5430; --sticky-ink:#f3ecc4;
  }
  .notes-popup{
    position:fixed; z-index:1100;
    background:var(--sticky);
    color:var(--sticky-ink);
    border-radius:4px 4px 6px 6px;
    box-shadow:0 14px 34px rgba(0,0,0,.34), 0 2px 5px rgba(0,0,0,.16);
    width:340px; max-width:92vw;
    border:1px solid var(--sticky-edge);
    border-top:none;
    font-family:var(--sans);
    overflow:hidden;
    transform:rotate(-1deg);          /* slight sticky-note tilt */
    transform-origin:top center;
  }
  .notes-popup::before{
    content:''; display:block; height:8px;
    background:linear-gradient(180deg, color-mix(in srgb, var(--sticky-edge) 80%, #000 6%), var(--sticky-edge));
  }
  .notes-popup .np-toolbar{
    display:flex; align-items:center; gap:1px;
    padding:7px 9px;
    border-bottom:1px solid color-mix(in srgb, var(--sticky-edge) 70%, transparent);
    background:color-mix(in srgb, var(--sticky-edge) 30%, var(--sticky));
  }
  .notes-popup .np-toolbar button{
    border:none; background:transparent; cursor:pointer;
    width:32px; height:30px; border-radius:6px;
    font-family:inherit; font-size:13px; color:var(--sticky-ink);
    display:inline-flex; align-items:center; justify-content:center;
  }
  .notes-popup .np-toolbar button:hover{background:color-mix(in srgb, var(--sticky-ink) 12%, transparent)}
  .notes-popup .np-toolbar button b,
  .notes-popup .np-toolbar button i,
  .notes-popup .np-toolbar button s{font-family:var(--serif); font-size:14px}
  .notes-popup .np-toolbar button i{font-style:italic}
  .notes-popup .np-div{width:1px; height:20px; background:color-mix(in srgb, var(--sticky-edge) 80%, transparent); margin:0 4px}
  .notes-popup .np-editor{
    padding:14px 16px; min-height:170px; max-height:50vh; overflow-y:auto;
    font-family:var(--sans); font-size:14px; line-height:1.6;
    color:var(--sticky-ink); outline:none; background:transparent;
  }
  .notes-popup .np-editor:empty:before{
    content:attr(data-placeholder); color:color-mix(in srgb, var(--sticky-ink) 50%, transparent); pointer-events:none;
  }
  .notes-popup .np-editor h1{font-size:20px; margin:.4em 0 .3em; font-family:var(--serif); font-weight:700}
  .notes-popup .np-editor h2{font-size:16px; margin:.4em 0 .3em; font-family:var(--serif); font-weight:600}
  .notes-popup .np-editor p{margin:.3em 0}
  .notes-popup .np-editor ul,
  .notes-popup .np-editor ol{margin:.3em 0; padding-left:1.6em}
  .notes-popup .np-editor a{color:var(--link); text-decoration:underline}
  /* A formula rendered in place inside the editor (see npMathSpan). It is not
     editable itself; clicking it swaps its $ source back in. */
  .notes-popup .np-math{
    display:inline-block; padding:0 3px; border-radius:4px; cursor:pointer;
    font-size:1.05em; line-height:1.3; vertical-align:baseline;
  }
  .notes-popup .np-math[data-display="1"]{display:block; text-align:center; margin:.2em 0}
  .notes-popup .np-math:hover{background:color-mix(in srgb, var(--sticky-ink) 10%, transparent); outline:1px dashed color-mix(in srgb, var(--sticky-ink) 40%, transparent)}
  .notes-popup .np-actions{
    display:flex; gap:8px; padding:10px 12px;
    border-top:1px solid color-mix(in srgb, var(--sticky-edge) 70%, transparent);
    background:color-mix(in srgb, var(--sticky-edge) 22%, var(--sticky));
    align-items:center;
  }
  .notes-popup button{
    padding:7px 14px; border-radius:7px; border:1px solid var(--sticky-edge);
    background:color-mix(in srgb, var(--sticky-edge) 25%, var(--sticky)); cursor:pointer;
    font-family:inherit; font-size:13px; font-weight:500; color:var(--sticky-ink);
  }
  .notes-popup .np-actions > button:hover{background:color-mix(in srgb, var(--sticky-ink) 12%, transparent)}
  .notes-popup button.primary{background:var(--accent); color:#fff; border-color:var(--accent)}
  .notes-popup button.primary:hover{background:var(--accent-deep)}
  .notes-popup .np-clear{margin-right:auto; color:var(--ink-soft); border-color:transparent; background:transparent}
  .notes-popup .np-clear:hover{color:var(--accent-deep); background:var(--hover)}

  /* ===== Map style variants (applied to viewport[data-style]) ===== */
  #viewport[data-style="modern"]{--edge-color:var(--line-2);--edge-width:2.2}
  #viewport[data-style="classic"] .node{border-radius:4px; border-width:1.5px}
  #viewport[data-style="classic"]{--edge-color:var(--line-2);--edge-width:1.6}
  #viewport[data-style="classic"] .node.root{border-radius:6px}
  #viewport[data-style="bubble"]  .node{border-radius:999px; padding:11px 22px; border-width:0; box-shadow:var(--shadow-lg)}
  #viewport[data-style="bubble"] {--edge-color:var(--accent);--edge-width:3}
  #viewport[data-style="bubble"]  .node.root{padding:14px 26px}
  #viewport[data-style="sketch"]  .node{border-radius:3px; border-width:2px; border-color:var(--ink); box-shadow:none}
  #viewport[data-style="sketch"]  .node.root{border-width:0}
  #viewport[data-style="sketch"] {--edge-color:var(--ink-soft);--edge-width:1.6}
  #viewport[data-style="dashed"]   {--edge-color:var(--line-2);--edge-width:2.2}
  #viewport[data-style="dashed"]   .node{border-radius:14px}
  #viewport[data-style="minimal"]  {--edge-color:var(--line-2);--edge-width:1.1}
  #viewport[data-style="minimal"]  .node{border-radius:6px; border-width:1px; box-shadow:none}
  #viewport[data-style="minimal"]  .node.root{border-radius:8px}
  #viewport[data-style="zigzag"]   {--edge-color:var(--line-2);--edge-width:2}
  #viewport[data-style="zigzag"]   .node{border-radius:2px; border-width:2px; box-shadow:none}
  #viewport[data-style="zigzag"]   .node.root{border-radius:2px}
  #viewport[data-style="neon"]     {--edge-color:var(--accent);--edge-width:2.4}
  #viewport[data-style="neon"]     .node{border-radius:10px; border-width:1px; border-color:color-mix(in srgb, var(--accent) 55%, transparent); box-shadow:0 0 0 1px color-mix(in srgb, var(--accent) 18%, transparent), 0 0 16px color-mix(in srgb, var(--accent) 38%, transparent)}
  #viewport[data-style="neon"]     .node.root{box-shadow:0 0 0 1px color-mix(in srgb, var(--accent) 32%, transparent), 0 0 26px color-mix(in srgb, var(--accent) 55%, transparent)}
  #viewport[data-style="neon"]     #edges path{filter:drop-shadow(0 0 3px color-mix(in srgb, var(--accent) 65%, transparent))}
  #viewport[data-style="circuit"]  {--edge-color:var(--accent);--edge-width:1.4}
  #viewport[data-style="circuit"]  .node{border-radius:4px; border-width:1.5px; border-color:color-mix(in srgb, var(--accent) 45%, transparent); box-shadow:inset 0 0 0 1px color-mix(in srgb, var(--accent) 10%, transparent), 0 1px 3px color-mix(in srgb, var(--accent) 12%, transparent)}
  #viewport[data-style="circuit"]  .node.root{border-width:1.5px; box-shadow:inset 0 0 0 1px color-mix(in srgb, var(--accent) 14%, transparent), 0 0 10px color-mix(in srgb, var(--accent) 18%, transparent)}
  #viewport[data-style="circuit"]  #edges path{stroke-dasharray:3 3}
  #viewport[data-style="blueprint"]{--edge-color:var(--ink-soft);--edge-width:1.2}
  #viewport[data-style="blueprint"] .node{border-radius:11px; border-width:1.5px; border-style:dashed; border-color:var(--ink); background:color-mix(in srgb, var(--paper) 82%, transparent); box-shadow:none}
  #viewport[data-style="blueprint"] .node.root{border-radius:13px; border-style:dashed}
  #viewport[data-style="blueprint"] #edges path{stroke-dasharray:6 4}
  #viewport[data-style="clay"]     {--edge-color:var(--line-2);--edge-width:1.6}
  #viewport[data-style="clay"]     .node{border-radius:16px; border-width:1px; border-color:color-mix(in srgb, var(--line) 40%, transparent); background:var(--card-bg); box-shadow:inset 2px 2px 4px color-mix(in srgb, #fff 70%, transparent), inset -2px -2px 6px color-mix(in srgb, var(--ink) 12%, transparent), 0 8px 20px color-mix(in srgb, var(--ink) 14%, transparent)}
  #viewport[data-style="clay"]     .node.root{border-radius:18px; box-shadow:inset 3px 3px 6px color-mix(in srgb, #fff 75%, transparent), inset -3px -3px 8px color-mix(in srgb, var(--ink) 14%, transparent), 0 12px 28px color-mix(in srgb, var(--ink) 16%, transparent)}
  #viewport[data-style="clay"]     #edges path{opacity:.95}
  #viewport[data-style="ink"]      {--edge-color:var(--ink);--edge-width:2.6}
  #viewport[data-style="ink"]      .node{border-radius:8px; border-width:3px; border-color:var(--ink); box-shadow:4px 4px 0 var(--ink)}
  #viewport[data-style="ink"]      .node.root{border-radius:10px; border-width:3px; box-shadow:4px 4px 0 var(--ink)}
  #viewport[data-style="ink"]      #edges path{stroke-linecap:square}
  #viewport[data-style="paper"]    {--edge-color:var(--line-2);--edge-width:1.5}
  #viewport[data-style="paper"]    .node{border-radius:6px; border-width:1px; border-color:var(--line); background-color:var(--card-bg); background-image:repeating-linear-gradient(180deg, transparent 0 22px, color-mix(in srgb, var(--line) 22%, transparent) 23px); background-size:100% 23px; box-shadow:0 2px 6px color-mix(in srgb, var(--ink) 10%, transparent), 0 1px 2px color-mix(in srgb, var(--ink) 8%, transparent)}
  #viewport[data-style="paper"]    .node::after{content:""; position:absolute; top:0; right:0; width:14px; height:14px; background:linear-gradient(135deg, transparent 50%, color-mix(in srgb, var(--line) 55%, transparent) 50%, color-mix(in srgb, var(--paper) 92%, transparent) 56%); border-radius:0 6px 0 4px; box-shadow:-1px 1px 2px color-mix(in srgb, var(--ink) 10%, transparent); pointer-events:none}
  #viewport[data-style="paper"]    .node.root{border-radius:8px}
  #viewport[data-style="paper"]    .node.root::after{width:16px; height:16px; border-radius:0 8px 0 5px}
  #viewport[data-style="paper"]    #edges path{stroke-linecap:round}

  /* Cascades the pencil font to every part of the app that already
     references --sans/--serif (sidebar, modals, buttons, topbar, and
     nodes/edges too, since those never had their own font override) -
     not a per-component override, the same two variables everything
     already uses. This is now the ONLY thing "Back to School" controls
     via color/font variables - no palette override, see below. */
  :root[data-look="handwritten"]{ --sans:"Caveat",cursive; --serif:"Caveat",cursive; }

  /* ===== "Back to School" look and feel - font + chrome texture only =====
     Deliberately does NOT touch .node/.nodebar border-radius or #viewport's
     --edge-color/--edge-width: card shape and branch style are Map Style's
     job exclusively (Modern/Classic/Bubble/Sketch), independent of which
     Look and Feel is active - picking "Back to School" must never lock out
     or override a Map Style choice. Canvas texture uses var(--paper)/
     var(--line) as already defined by whichever Colour Theme is active, not
     a hardcoded palette - Back to School no longer sets colors at all, so
     the ruled paper automatically follows Light/Dark/Nord/etc.
     font-size on .node: NOT a shape override (no border-radius/transform
     here), just legibility compensation - handwriting fonts need more size
     than a geometric sans for equivalent readability. */
  :root[data-look="handwritten"] .node{ font-size:1.2em; }
  :root[data-look="handwritten"] .stage{
    background-image:repeating-linear-gradient(var(--paper) 0px, var(--paper) 27px, var(--line) 28px);
    background-size:100% 28px; background-color:var(--paper);
  }
  :root[data-look="handwritten"] .nodebar{
    font-weight:700; font-size:1.15em;
    border-radius:16px 9px 16px 9px;
    border:2px solid var(--ink); box-shadow:none;
  }
  /* Sidebar - thicker ink-colored edge instead of the default hairline */
  :root[data-look="handwritten"] .side{border-right:2px solid var(--ink)}
  /* Modal cards (citation form, due-date form, etc.) - same sketchy-border
     language as the toolbar, for visual consistency across the app */
  :root[data-look="handwritten"] .vf-card{
    border-radius:20px 8px 20px 8px; border:2px solid var(--ink); box-shadow:var(--shadow-lg);
  }
  :root[data-look="handwritten"] .vf-card h2{font-weight:700}
  /* Remaining containers audited and covered in this pass - context menus,
     pickers, the donation card, export/template popups, search box, minimap.
     Grouped since they share the same underlying structure (chrome/node-bg
     background, chrome-edge border, rounded corners) - same sketchy-border
     language as the rest of the app, not restyled individually from scratch. */
  :root[data-look="handwritten"] .row-pop,
  :root[data-look="handwritten"] .picker,
  :root[data-look="handwritten"] .donate-card,
  :root[data-look="handwritten"] .export-pop{
    border-radius:16px 6px 16px 6px; border:2px solid var(--ink);
  }
  :root[data-look="handwritten"] .donate-card{ border-radius:20px 8px 20px 8px; }
  :root[data-look="handwritten"] .search-wrap{ border-radius:14px 6px 14px 6px; border:2px solid var(--ink); }
  :root[data-look="handwritten"] .minimap{ border-radius:12px 4px 12px 4px; border:2px solid var(--ink); }
  :root[data-look="handwritten"] .toast{ border-radius:14px 5px 14px 5px; border:2px solid var(--ink); font-weight:500; }

  /* ===== "At Coffee Shop" look and feel - same principles, lighter touch =====
     Font-only color/font override, same as Back to School - no palette
     override here either. Differentiated from Back to School through
     restraint, not a new color: a lighter 1.5px border (vs 2px) and a
     quieter diagonal-hatch canvas texture instead of overt ruled-paper
     lines.
     Nunito (not a handwriting font, deliberately) needs no font-size
     compensation on .node - unlike Caveat/Patrick Hand, it's designed to
     read well at normal body-text size, so there's no bump here at all.
     That also means this look carries much less risk of the
     overflow/overlap class of bug a size bump can cause elsewhere (nodes
     growing taller than manually-set sizes, edges drawn against stale
     measurements) - not eliminated everywhere, but not something this
     specific look needs to fight. Nunito genuinely has a bold weight
     (unlike Patrick Hand's single weight), so emphasis below uses
     font-weight:700 directly instead of a size-based workaround. */
  :root[data-look="coffee-shop"]{ --sans:"Nunito",sans-serif; --serif:"Nunito",sans-serif; }
  :root[data-look="coffee-shop"] .stage{
    background-image:repeating-linear-gradient(135deg, var(--paper) 0px, var(--paper) 22px, var(--line) 23px);
    background-size:32px 32px; background-color:var(--paper);
  }
  :root[data-look="coffee-shop"] .nodebar{
    font-weight:700;
    border-radius:14px 8px 14px 8px;
    border:1.5px solid var(--ink); box-shadow:none;
  }
  :root[data-look="coffee-shop"] .side{border-right:1.5px solid var(--ink)}
  :root[data-look="coffee-shop"] .vf-card{
    border-radius:18px 7px 18px 7px; border:1.5px solid var(--ink); box-shadow:var(--shadow-lg);
  }
  :root[data-look="coffee-shop"] .vf-card h2{font-weight:700}
  :root[data-look="coffee-shop"] .row-pop,
  :root[data-look="coffee-shop"] .picker,
  :root[data-look="coffee-shop"] .donate-card,
  :root[data-look="coffee-shop"] .export-pop{
    border-radius:14px 5px 14px 5px; border:1.5px solid var(--ink);
  }
  :root[data-look="coffee-shop"] .donate-card{ border-radius:18px 7px 18px 7px; }
  :root[data-look="coffee-shop"] .search-wrap{ border-radius:12px 5px 12px 5px; border:1.5px solid var(--ink); }
  :root[data-look="coffee-shop"] .minimap{ border-radius:10px 4px 10px 4px; border:1.5px solid var(--ink); }
  :root[data-look="coffee-shop"] .toast{ border-radius:12px 4px 12px 4px; border:1.5px solid var(--ink); }

  /* ===== "In the Lab" look and feel - technical, squared-off =====
      Font-only override plus a quiet blueprint grid on the canvas, same
      principles as the other looks: no palette change, no card-shape or
      edge-style interference (those belong to Map Style). Everything is
      squared and precise to match a monospace: 3px corners instead of
      organic rounded ones, 1.5px ink borders, a lab-notebook grid texture
      (both axes) instead of dots or ruled lines. JetBrains Mono is a
      designed text face, so no font-size compensation on .node. */
   :root[data-look="lab"]{ --sans:"JetBrains Mono",monospace; --serif:"JetBrains Mono",monospace; }
   :root[data-look="lab"] .stage{
     background-image:linear-gradient(color-mix(in srgb, var(--line) 55%, transparent) 1px, transparent 1px),
       linear-gradient(90deg, color-mix(in srgb, var(--line) 55%, transparent) 1px, transparent 1px);
     background-size:26px 26px; background-color:var(--paper);
   }
   :root[data-look="lab"] .nodebar{
     border-radius:3px;
     border:1.5px solid var(--ink); box-shadow:none;
   }
   :root[data-look="lab"] .side{border-right:1.5px solid var(--ink)}
   :root[data-look="lab"] .new-map{border:1.5px dashed var(--ink-soft)}
   :root[data-look="lab"] .vf-card{
     border-radius:3px; border:1.5px solid var(--ink); box-shadow:var(--shadow-lg);
   }
   :root[data-look="lab"] .vf-card h2{font-weight:700}
   :root[data-look="lab"] .row-pop,
   :root[data-look="lab"] .picker,
   :root[data-look="lab"] .donate-card,
   :root[data-look="lab"] .export-pop,
   :root[data-look="lab"] .tpl-pop{
     border-radius:3px; border:1.5px solid var(--ink);
   }
   :root[data-look="lab"] .donate-card{ border-radius:4px; }
   :root[data-look="lab"] .search-wrap{ border-radius:3px; border:1.5px solid var(--ink); }
   :root[data-look="lab"] .minimap{ border-radius:3px; border:1.5px solid var(--ink); }
:root[data-look="lab"] .toast{ border-radius:3px; border:1.5px solid var(--ink); }

  /* ===== "The Scientist" - Schrödinger's graph paper =====
      Quantum lab: crisp measurement grid + interference fringes +
      probability clouds + lattice dots. Glowing accent instrumentation
      rather than flat ink: tighter monospace tracking, luminous borders,
      specimen-label breadcrumb. Distinct from "In the Lab" (flat grid,
      ink borders) - here the grid is accent-laced, clouds drift, and
      chrome glows. No palette or Map Style interference - all
      var(--paper)/--line/--accent. */
   :root[data-look="scientist"]{ --sans:"Space Mono",monospace; --serif:"Space Mono",monospace; }
    :root[data-look="scientist"] .stage{
      background-image:
        /* crisp 28px measurement grid */
        linear-gradient(color-mix(in srgb, var(--line) 52%, transparent) 1px, transparent 1px),
        linear-gradient(90deg, color-mix(in srgb, var(--line) 52%, transparent) 1px, transparent 1px),
        /* interference fringes - faint diagonal wave */
        repeating-linear-gradient(-14deg, transparent 0 34px, color-mix(in srgb, var(--accent) 7%, transparent) 35px, transparent 36px),
        /* pinpoint lattice - sub-pixel dots at intersections */
        radial-gradient(circle at 50% 50%, color-mix(in srgb, var(--accent) 18%, transparent) 1.2px, transparent 1.7px);
      background-size:28px 28px, 28px 28px, auto, 52px 52px;
      background-color:var(--paper);
    }
   :root[data-look="scientist"] .nodebar{
     border-radius:3px;
     border:1.5px solid var(--accent);
     box-shadow:0 0 0 1px color-mix(in srgb, var(--accent) 14%, transparent), 0 0 12px color-mix(in srgb, var(--accent) 18%, transparent);
     letter-spacing:0.01em;
   }
   :root[data-look="scientist"] .side{border-right:1.5px solid var(--accent); box-shadow:inset -1px 0 0 color-mix(in srgb, var(--accent) 10%, transparent)}
   :root[data-look="scientist"] .new-map{border:1.5px dashed var(--accent); background:color-mix(in srgb, var(--accent) 6%, transparent)}
   :root[data-look="scientist"] .vf-card{
     border-radius:3px; border:1.5px solid var(--accent); box-shadow:0 0 0 1px color-mix(in srgb, var(--accent) 10%, transparent), var(--shadow-lg);
   }
   :root[data-look="scientist"] .vf-card h2{font-weight:800; letter-spacing:0.04em; text-transform:uppercase; font-size:13px; color:var(--accent)}
   :root[data-look="scientist"] .row-pop,
   :root[data-look="scientist"] .picker,
   :root[data-look="scientist"] .donate-card,
   :root[data-look="scientist"] .export-pop,
   :root[data-look="scientist"] .tpl-pop{
     border-radius:3px; border:1.5px solid var(--accent);
     box-shadow:0 0 0 1px color-mix(in srgb, var(--accent) 10%, transparent), var(--shadow);
   }
   :root[data-look="scientist"] .donate-card{ border-radius:4px; }
   :root[data-look="scientist"] .search-wrap{ border-radius:3px; border:1.5px solid var(--accent); box-shadow:0 0 0 1px color-mix(in srgb, var(--accent) 8%, transparent) }
   :root[data-look="scientist"] .minimap{ border-radius:3px; border:1.5px solid var(--accent); box-shadow:0 0 8px color-mix(in srgb, var(--accent) 20%, transparent) }
   :root[data-look="scientist"] .toast{ border-radius:3px; border:1.5px solid var(--accent); box-shadow:0 0 10px color-mix(in srgb, var(--accent) 16%, transparent) }
   /* specimen-label breadcrumb - monospace, upper + tracked, accent pill */
   :root[data-look="scientist"] .breadcrumb{
     background:var(--paper); border:1.5px solid var(--accent);
     box-shadow:0 0 0 1px color-mix(in srgb, var(--accent) 12%, transparent), 0 4px 16px color-mix(in srgb, var(--accent) 14%, transparent);
     border-radius:6px; padding:3px 6px; gap:2px;
      font-family:"Space Mono",monospace; font-size:11.5px; letter-spacing:0.06em; text-transform:uppercase;
   }
   :root[data-look="scientist"] .breadcrumb .bc-crumb{ border-radius:4px; padding:3px 8px; font-weight:700; letter-spacing:0.05em; }
   :root[data-look="scientist"] .breadcrumb .bc-crumb:hover{ background:color-mix(in srgb, var(--accent) 10%, transparent); color:var(--accent) }
   :root[data-look="scientist"] .breadcrumb .bc-sep{ color:var(--accent); opacity:1; font-weight:900; font-size:10px; }

  /* ===== "The Architect" - blueprint system drafting table =====
      Software-architecture blueprint: dual grid (major 32px + minor 8px),
      faint 45° construction haze, snapshot component ghosts, and title-block
      corners. Heavy ink structure with accent spine - not the lab's flat
      grid. Space Grotesk for confident, structural sans (distinct from
      office Bricolage / studio Fraunces). Title-block breadcrumb like a
      drawing sheet label. No palette override - follows active Colour Theme. */
   :root[data-look="architect"]{ --sans:"Space Grotesk",sans-serif; --serif:"Space Grotesk",sans-serif; }
   :root[data-look="architect"] .stage{
     background-image:
       /* major 32px blueprint grid */
       linear-gradient(color-mix(in srgb, var(--line) 48%, transparent) 1px, transparent 1px),
       linear-gradient(90deg, color-mix(in srgb, var(--line) 48%, transparent) 1px, transparent 1px),
       /* minor 8px subdivision - lighter */
       linear-gradient(color-mix(in srgb, var(--line) 20%, transparent) 1px, transparent 1px),
       linear-gradient(90deg, color-mix(in srgb, var(--line) 20%, transparent) 1px, transparent 1px),
       /* 45° construction haze - very faint */
       repeating-linear-gradient(45deg, transparent 0 48px, color-mix(in srgb, var(--line) 9%, transparent) 49px, transparent 50px),
       /* blueprint title-block corners - L-shaped faint ink markers */
       linear-gradient(90deg, color-mix(in srgb, var(--ink) 14%, transparent) 2px, transparent 2px),
       linear-gradient(color-mix(in srgb, var(--ink) 14%, transparent) 2px, transparent 2px),
       /* ghost system blocks - faint accent rectangles hinting at components */
       linear-gradient(color-mix(in srgb, var(--accent) 4.5%, transparent) 1px, transparent 1px),
       linear-gradient(90deg, color-mix(in srgb, var(--accent) 4.5%, transparent) 1px, transparent 1px);
     background-size:32px 32px, 32px 32px, 8px 8px, 8px 8px, 64px 64px, 100% 100%, 100% 100%, 220px 140px, 220px 140px;
     background-position:0 0, 0 0, 0 0, 0 0, 0 0, 0 0, 0 0, 18% 42%, 72% 68%;
     background-repeat:repeat, repeat, repeat, repeat, repeat, no-repeat, no-repeat, no-repeat, no-repeat;
     background-color:var(--paper);
   }
   :root[data-look="architect"] .nodebar{
      border-radius:6px;
      border:1.5px solid var(--ink); border-left:4px solid var(--accent);
      box-shadow:inset 0 1px 0 color-mix(in srgb, var(--paper) 60%, transparent), 0 1px 0 color-mix(in srgb, var(--ink) 8%, transparent);
    }
   :root[data-look="architect"] .nodebar::before{
     content:""; position:absolute; top:6px; right:6px; width:6px; height:6px;
     border-top:1.5px solid var(--accent); border-right:1.5px solid var(--accent); opacity:.55; border-radius:1px;
   }
   :root[data-look="architect"] .side{border-right:2px solid var(--ink); box-shadow:inset -2px 0 0 color-mix(in srgb, var(--accent) 18%, transparent)}
   :root[data-look="architect"] .side .side-tabs{ border-bottom:1px solid var(--line) }
   :root[data-look="architect"] .new-map{border:1.5px dashed var(--ink); border-left:3px solid var(--accent); background:color-mix(in srgb, var(--paper-2) 60%, transparent)}
   :root[data-look="architect"] .vf-card{
     border-radius:6px; border:2px solid var(--ink); border-left:4px solid var(--accent); box-shadow:var(--shadow-lg);
   }
   :root[data-look="architect"] .vf-card h2{font-weight:800; letter-spacing:0.06em; text-transform:uppercase; font-size:12.5px; color:var(--ink)}
   :root[data-look="architect"] .row-pop,
   :root[data-look="architect"] .picker,
   :root[data-look="architect"] .donate-card,
   :root[data-look="architect"] .export-pop,
   :root[data-look="architect"] .tpl-pop{
     border-radius:6px; border:1.5px solid var(--ink);
   }
   :root[data-look="architect"] .donate-card{ border-radius:8px; border-width:2px; }
   :root[data-look="architect"] .search-wrap{ border-radius:6px; border:1.5px solid var(--ink); border-left:3px solid var(--accent); }
   :root[data-look="architect"] .minimap{ border-radius:6px; border:2px solid var(--ink); box-shadow:inset 0 0 0 2px color-mix(in srgb, var(--accent) 14%, transparent) }
   :root[data-look="architect"] .toast{ border-radius:6px; border:1.5px solid var(--ink); border-left:3px solid var(--accent); }
   /* title-block breadcrumb - architectural drawing label */
   :root[data-look="architect"] .breadcrumb{
     background:var(--paper); border:2px solid var(--ink); border-left:4px solid var(--accent);
     box-shadow:var(--shadow); border-radius:4px; padding:2px 5px; gap:1px;
      font-family:"Space Grotesk",sans-serif; font-size:11px; letter-spacing:0.1em; text-transform:uppercase; font-weight:800;
   }
   :root[data-look="architect"] .breadcrumb .bc-crumb{ border-radius:3px; padding:3px 8px; font-weight:800; letter-spacing:0.08em; background:color-mix(in srgb, var(--paper-2) 70%, transparent); }
   :root[data-look="architect"] .breadcrumb .bc-crumb.current{ background:var(--accent); color:#fff; }
   :root[data-look="architect"] .breadcrumb .bc-sep{ color:var(--ink); opacity:.45; font-weight:900; font-size:10px; letter-spacing:0; }
    :root[data-look="architect"] .breadcrumb .bc-crumb:hover{ background:color-mix(in srgb, var(--accent) 12%, transparent); }

  /* ===== "An Alien" - close encounter =====
      Abducted: night void, starfield, crop-circle grid and a saucer's beam.
      Space Mono is stark and modular like an alien console. No palette override. */
   :root[data-look="alien"]{ --sans:"Space Mono",monospace; --serif:"Space Mono",monospace;
    --look-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='400' viewBox='0 0 400 400'%3E%3Cg fill='none' stroke='%23000' stroke-width='1.1' stroke-linecap='round' stroke-linejoin='round'%3E%3Cg transform='translate(62 62)'%3E%3Cellipse cx='0' cy='0' rx='22' ry='14'/%3E%3Cpath d='M -18 -2 C -12 -14 12 -14 18 -2'/%3E%3Cellipse cx='0' cy='-4' rx='10' ry='12' fill='%23000' fill-opacity='0.04'/%3E%3Cellipse cx='-4' cy='-2' r='2.2' fill='%23000'/%3E%3Cellipse cx='4' cy='-2' r='2.2' fill='%23000'/%3E%3Cpath d='M -22 6 L -28 10 L -18 12 Z'/%3E%3Cpath d='M 22 6 L 28 10 L 18 12 Z'/%3E%3C/g%3E%3Cg transform='translate(168 58)'%3E%3Cellipse cx='0' cy='0' rx='28' ry='16'/%3E%3Cpath d='M -20 -4 C -14 -12 14 -12 20 -4'/%3E%3Cellipse cx='-8' cy='-1' rx='1.5' ry='1.2' fill='%23000'/%3E%3Cellipse cx='8' cy='-1' rx='1.5' ry='1.2' fill='%23000'/%3E%3Cpath d='M -6 6 L -8 12 M 0 7 L 0 13 M 6 6 L 8 12'/%3E%3C/g%3E%3Cg transform='translate(268 62)'%3E%3Cellipse cx='0' cy='-6' rx='14' ry='18'/%3E%3Cellipse cx='-5' cy='-4' r='3.2' fill='%23000'/%3E%3Cellipse cx='5' cy='-4' r='3.2' fill='%23000'/%3E%3Cpath d='M -4 6 Q 0 9 4 6' stroke='%23000'/%3E%3Cpath d='M 0 -22 Q 4 -26 2 -30'/%3E%3Ccircle cx='2' cy='-30' r='2' fill='none'/%3E%3Cpath d='M -8 12 L -10 28 L -6 28 Z'/%3E%3Cpath d='M 8 12 L 10 28 L 6 28 Z'/%3E%3C/g%3E%3Cg transform='translate(348 62)'%3E%3Cellipse cx='0' cy='0' rx='32' ry='18'/%3E%3Cellipse cx='0' cy='-8' rx='16' ry='12'/%3E%3Ccircle cx='-6' cy='-8' r='1.2' fill='%23000'/%3E%3Ccircle cx='6' cy='-8' r='1.2' fill='%23000'/%3E%3Cpath d='M -10 4 L -12 8 M -4 5 L -4 9 M 4 5 L 4 9 M 10 4 L 12 8'/%3E%3C/g%3E%3Cg transform='translate(78 148)'%3E%3Ccircle cx='0' cy='0' r='26' stroke-dasharray='2 3'/%3E%3Cpath d='M -18 -6 Q -12 -10 -8 -6 Q -4 -2 -8 2 Q -12 6 -18 2 Q -16 -2 -18 -6'/%3E%3Cpath d='M 6 -8 Q 12 -6 14 -2 Q 10 2 6 -2'/%3E%3Cpath d='M -6 8 Q 0 12 6 8'/%3E%3C/g%3E%3Cg transform='translate(200 158)'%3E%3Cellipse cx='0' cy='0' rx='34' ry='20'/%3E%3Cpath d='M -24 -6 C -18 -14 18 -14 24 -6'/%3E%3Cellipse cx='-8' cy='-2' r='2' fill='%23000'/%3E%3Cellipse cx='8' cy='-2' r='2' fill='%23000'/%3E%3Cpath d='M -10 8 L -12 16 M -2 10 L -2 18 M 2 10 L 2 18 M 10 8 L 12 16'/%3E%3C/g%3E%3Cg transform='translate(338 148)'%3E%3Ccircle cx='0' cy='-12' r='16' fill='%23000' fill-opacity='0.05'/%3E%3Cpath d='M -12 -8 L -14 -14 L -10 -16 L -6 -12 Z'/%3E%3Cpath d='M 0 -18 L 0 -24'/%3E%3Ccircle cx='0' cy='-26' r='2' fill='none'/%3E%3Cpath d='M -18 6 L -24 14 L -18 16 Z'/%3E%3Cpath d='M 18 6 L 24 14 L 18 16 Z'/%3E%3Crect x='-4' y='8' width='8' height='6' rx='1' fill='none'/%3E%3Cpath d='M -8 14 L -10 22 L -6 22 Z'/%3E%3Cpath d='M 8 14 L 10 22 L 6 22 Z'/%3E%3C/g%3E%3Cg transform='translate(48 268)'%3E%3Ccircle cx='0' cy='-14' r='12'/%3E%3Cpath d='M -8 -10 Q -12 -14 -8 -18 Q -4 -16 0 -18 Q 4 -16 8 -18 Q 12 -14 8 -10'/%3E%3Ccircle cx='-4' cy='-6' r='1.8' fill='%23000'/%3E%3Ccircle cx='4' cy='-6' r='1.8' fill='%23000'/%3E%3Cpath d='M -5 2 Q 0 6 5 2 L 0 8 Z'/%3E%3Cpath d='M -14 4 L -18 18 L -12 16 M 14 4 L 18 18 L 12 16'/%3E%3Cpath d='M 0 12 L -2 28 L 2 28 Z'/%3E%3C/g%3E%3Cg transform='translate(128 288)'%3E%3Cellipse cx='0' cy='0' rx='20' ry='12'/%3E%3Cpath d='M -14 -4 C -10 -8 10 -8 14 -4'/%3E%3Ccircle cx='-4' cy='-1' r='1.2' fill='%23000'/%3E%3Ccircle cx='4' cy='-1' r='1.2' fill='%23000'/%3E%3Cpath d='M -6 6 L -8 12 M 6 6 L 8 12'/%3E%3C/g%3E%3Cg transform='translate(218 292)'%3E%3Cellipse cx='0' cy='-6' rx='12' ry='15'/%3E%3Cellipse cx='-4.5' cy='-4' r='3.5' ry='5' fill='%23000'/%3E%3Cellipse cx='4.5' cy='-4' r='3.5' ry='5' fill='%23000'/%3E%3Cpath d='M -4 6 Q 0 10 4 6'/%3E%3Cpath d='M -8 10 L -10 22 L -6 22 Z'/%3E%3Cpath d='M 8 10 L 10 22 L 6 22 Z'/%3E%3Ctext x='14' y='2' font-size='6' fill='%23000' opacity='0.7'%3E✌%3C/text%3E%3C/g%3E%3Cg transform='translate(348 298)'%3E%3Ccircle cx='0' cy='0' r='28'/%3E%3Cpath d='M -18 -8 Q -12 -12 -8 -8 Q -4 -4 -8 0 Q -12 4 -18 0 Q -16 -4 -18 -8'/%3E%3Cpath d='M 8 -10 Q 14 -8 16 -4 Q 12 0 8 -4'/%3E%3Ccircle cx='-8' cy='-2' r='1.5' fill='%23000'/%3E%3Ccircle cx='8' cy='-4' r='1.2' fill='%23000'/%3E%3Cellipse cx='0' cy='18' rx='36' ry='10' fill='none' stroke-dasharray='1 2'/%3E%3C/g%3E%3Ccircle cx='28' cy='28' r='1.1' fill='%23000' fill-opacity='0.9'/%3E%3Ccircle cx='88' cy='18' r='0.9' fill='%23000'/%3E%3Ccircle cx='188' cy='38' r='0.8' fill='%23000'/%3E%3Ccircle cx='320' cy='28' r='1' fill='%23000'/%3E%3C/g%3E%3C/svg%3E");
    --look-mask-size:400px 400px;
    --look-mask-ink:6.5%;
  }
   /* The starfield tints from --ink, not a fixed white: white stars vanish on a
     light theme. Taking the ink means light specks on a dark paper and dark
     ones on a light paper, which is what a starfield needs to read either way.
     The stars inside the SVG data URI below are still fixed - an SVG in a data
     URI cannot read var(), and changing that needs the mask treatment, which is
     a bigger job than this. */
:root[data-look="alien"] .stage{
     background-image:
      url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='400' height='400' viewBox='0 0 400 400'%3E%3Cg opacity='0.08' fill='none' stroke='%231a1a1a' stroke-width='1.1' stroke-linecap='round' stroke-linejoin='round'%3E%3Cg transform='translate(62 62)'%3E%3Cellipse cx='0' cy='0' rx='22' ry='14'/%3E%3Cpath d='M -18 -2 C -12 -14 12 -14 18 -2'/%3E%3Cellipse cx='0' cy='-4' rx='10' ry='12' fill='none' fill-opacity='0.04'/%3E%3Cellipse cx='-4' cy='-2' r='2.2' fill='none'/%3E%3Cellipse cx='4' cy='-2' r='2.2' fill='none'/%3E%3Cpath d='M -22 6 L -28 10 L -18 12 Z'/%3E%3Cpath d='M 22 6 L 28 10 L 18 12 Z'/%3E%3C/g%3E%3Cg transform='translate(168 58)'%3E%3Cellipse cx='0' cy='0' rx='28' ry='16'/%3E%3Cpath d='M -20 -4 C -14 -12 14 -12 20 -4'/%3E%3Cellipse cx='-8' cy='-1' rx='1.5' ry='1.2' fill='none'/%3E%3Cellipse cx='8' cy='-1' rx='1.5' ry='1.2' fill='none'/%3E%3Cpath d='M -6 6 L -8 12 M 0 7 L 0 13 M 6 6 L 8 12'/%3E%3C/g%3E%3Cg transform='translate(268 62)'%3E%3Cellipse cx='0' cy='-6' rx='14' ry='18'/%3E%3Cellipse cx='-5' cy='-4' r='3.2' fill='none'/%3E%3Cellipse cx='5' cy='-4' r='3.2' fill='none'/%3E%3Cpath d='M -4 6 Q 0 9 4 6' stroke='%231a1a1a'/%3E%3Cpath d='M 0 -22 Q 4 -26 2 -30'/%3E%3Ccircle cx='2' cy='-30' r='2' fill='none'/%3E%3Cpath d='M -8 12 L -10 28 L -6 28 Z'/%3E%3Cpath d='M 8 12 L 10 28 L 6 28 Z'/%3E%3C/g%3E%3Cg transform='translate(348 62)'%3E%3Cellipse cx='0' cy='0' rx='32' ry='18'/%3E%3Cellipse cx='0' cy='-8' rx='16' ry='12'/%3E%3Ccircle cx='-6' cy='-8' r='1.2' fill='none'/%3E%3Ccircle cx='6' cy='-8' r='1.2' fill='none'/%3E%3Cpath d='M -10 4 L -12 8 M -4 5 L -4 9 M 4 5 L 4 9 M 10 4 L 12 8'/%3E%3C/g%3E%3Cg transform='translate(78 148)'%3E%3Ccircle cx='0' cy='0' r='26' stroke-dasharray='2 3'/%3E%3Cpath d='M -18 -6 Q -12 -10 -8 -6 Q -4 -2 -8 2 Q -12 6 -18 2 Q -16 -2 -18 -6'/%3E%3Cpath d='M 6 -8 Q 12 -6 14 -2 Q 10 2 6 -2'/%3E%3Cpath d='M -6 8 Q 0 12 6 8'/%3E%3C/g%3E%3Cg transform='translate(200 158)'%3E%3Cellipse cx='0' cy='0' rx='34' ry='20'/%3E%3Cpath d='M -24 -6 C -18 -14 18 -14 24 -6'/%3E%3Cellipse cx='-8' cy='-2' r='2' fill='none'/%3E%3Cellipse cx='8' cy='-2' r='2' fill='none'/%3E%3Cpath d='M -10 8 L -12 16 M -2 10 L -2 18 M 2 10 L 2 18 M 10 8 L 12 16'/%3E%3C/g%3E%3Cg transform='translate(338 148)'%3E%3Ccircle cx='0' cy='-12' r='16' fill='none' fill-opacity='0.05'/%3E%3Cpath d='M -12 -8 L -14 -14 L -10 -16 L -6 -12 Z'/%3E%3Cpath d='M 0 -18 L 0 -24'/%3E%3Ccircle cx='0' cy='-26' r='2' fill='none'/%3E%3Cpath d='M -18 6 L -24 14 L -18 16 Z'/%3E%3Cpath d='M 18 6 L 24 14 L 18 16 Z'/%3E%3Crect x='-4' y='8' width='8' height='6' rx='1' fill='none'/%3E%3Cpath d='M -8 14 L -10 22 L -6 22 Z'/%3E%3Cpath d='M 8 14 L 10 22 L 6 22 Z'/%3E%3C/g%3E%3Cg transform='translate(48 268)'%3E%3Ccircle cx='0' cy='-14' r='12'/%3E%3Cpath d='M -8 -10 Q -12 -14 -8 -18 Q -4 -16 0 -18 Q 4 -16 8 -18 Q 12 -14 8 -10'/%3E%3Ccircle cx='-4' cy='-6' r='1.8' fill='none'/%3E%3Ccircle cx='4' cy='-6' r='1.8' fill='none'/%3E%3Cpath d='M -5 2 Q 0 6 5 2 L 0 8 Z'/%3E%3Cpath d='M -14 4 L -18 18 L -12 16 M 14 4 L 18 18 L 12 16'/%3E%3Cpath d='M 0 12 L -2 28 L 2 28 Z'/%3E%3C/g%3E%3Cg transform='translate(128 288)'%3E%3Cellipse cx='0' cy='0' rx='20' ry='12'/%3E%3Cpath d='M -14 -4 C -10 -8 10 -8 14 -4'/%3E%3Ccircle cx='-4' cy='-1' r='1.2' fill='none'/%3E%3Ccircle cx='4' cy='-1' r='1.2' fill='none'/%3E%3Cpath d='M -6 6 L -8 12 M 6 6 L 8 12'/%3E%3C/g%3E%3Cg transform='translate(218 292)'%3E%3Cellipse cx='0' cy='-6' rx='12' ry='15'/%3E%3Cellipse cx='-4.5' cy='-4' r='3.5' ry='5' fill='none'/%3E%3Cellipse cx='4.5' cy='-4' r='3.5' ry='5' fill='none'/%3E%3Cpath d='M -4 6 Q 0 10 4 6'/%3E%3Cpath d='M -8 10 L -10 22 L -6 22 Z'/%3E%3Cpath d='M 8 10 L 10 22 L 6 22 Z'/%3E%3Ctext x='14' y='2' font-size='6' fill='%231a1a1a' opacity='0.7'%3E✌%3C/text%3E%3C/g%3E%3Cg transform='translate(348 298)'%3E%3Ccircle cx='0' cy='0' r='28'/%3E%3Cpath d='M -18 -8 Q -12 -12 -8 -8 Q -4 -4 -8 0 Q -12 4 -18 0 Q -16 -4 -18 -8'/%3E%3Cpath d='M 8 -10 Q 14 -8 16 -4 Q 12 0 8 -4'/%3E%3Ccircle cx='-8' cy='-2' r='1.5' fill='none'/%3E%3Ccircle cx='8' cy='-4' r='1.2' fill='none'/%3E%3Cellipse cx='0' cy='18' rx='36' ry='10' fill='none' stroke-dasharray='1 2'/%3E%3C/g%3E%3Ccircle cx='28' cy='28' r='1.1' fill='none' fill-opacity='0.9'/%3E%3Ccircle cx='88' cy='18' r='0.9' fill='none'/%3E%3Ccircle cx='188' cy='38' r='0.8' fill='none'/%3E%3Ccircle cx='320' cy='28' r='1' fill='none'/%3E%3C/g%3E%3C/svg%3E"),
      radial-gradient(ellipse 200px 70px at 50% 7%,
      color-mix(in srgb,
      var(--accent) 6%, transparent) 0, transparent 70%),
      radial-gradient(circle at 18% 22%,
      color-mix(in srgb,
      var(--ink) 88%, transparent) 1.4px, transparent 2px),
      radial-gradient(circle at 73% 18%,
      color-mix(in srgb,
      var(--ink) 74%, transparent) 1.2px, transparent 1.8px),
      radial-gradient(circle at 42% 38%,
      color-mix(in srgb,
      var(--ink) 62%, transparent) 1px, transparent 1.6px),
      radial-gradient(circle at 85% 52%,
      color-mix(in srgb,
      var(--ink) 78%, transparent) 1.2px, transparent 1.8px),
      radial-gradient(circle at 28% 68%,
      color-mix(in srgb,
      var(--ink) 58%, transparent) 1px, transparent 1.5px),
      linear-gradient(color-mix(in srgb,
      var(--line) 16%, transparent) 1px, transparent 1px),
      linear-gradient(90deg,
      color-mix(in srgb,
      var(--line) 16%, transparent) 1px, transparent 1px);
     background-size:0px 200px, 10px 10px, 0px 160px, 220px 220px, 280px 280px, 230px 230px, 0px 0px, 0px 0px;
     background-color:var(--paper);
   }
   :root[data-look="alien"] .node{
     border-radius:12px;
     border:1.5px solid color-mix(in srgb, var(--accent) 55%, var(--ink));
     box-shadow:0 0 0 1px color-mix(in srgb, var(--accent) 18%, transparent), 0 0 18px color-mix(in srgb, var(--accent) 28%, transparent);
   }
   :root[data-look="alien"] .node.root{
     border-radius:14px;
     border-width:2px;
     box-shadow:0 0 0 1px color-mix(in srgb, var(--accent) 28%, transparent), 0 0 26px color-mix(in srgb, var(--accent) 42%, transparent);
   }
   :root[data-look="alien"] .nodebar{
     border-radius:10px;
     border:1.5px solid var(--accent);
     box-shadow:0 0 12px color-mix(in srgb, var(--accent) 22%, transparent);
   }
   :root[data-look="alien"] .side{border-right:1.5px solid var(--accent); box-shadow:inset -1px 0 0 color-mix(in srgb, var(--accent) 14%, transparent)}
   :root[data-look="alien"] .vf-card{ border-radius:10px; border:1.5px solid var(--accent); box-shadow:0 0 0 1px color-mix(in srgb, var(--accent) 12%, transparent), var(--shadow-lg); }
   :root[data-look="alien"] .row-pop,
   :root[data-look="alien"] .picker,
   :root[data-look="alien"] .donate-card,
   :root[data-look="alien"] .export-pop{ border-radius:10px; border:1.5px solid var(--accent); }
   :root[data-look="alien"] .search-wrap{ border-radius:8px; border:1.5px solid var(--accent); }
   :root[data-look="alien"] .minimap{ border-radius:8px; border:1.5px solid var(--accent); box-shadow:0 0 14px color-mix(in srgb, var(--accent) 24%, transparent); }
   :root[data-look="alien"] .toast{ border-radius:8px; border:1.5px solid var(--accent); }
   :root[data-look="alien"] .breadcrumb{
     background:var(--paper); border:1.5px solid var(--accent);
     box-shadow:0 0 12px color-mix(in srgb, var(--accent) 18%, transparent);
     font-family:"Space Mono",monospace; letter-spacing:0.06em; text-transform:uppercase; font-size:11.5px;
   }

  /* ===== "A Psycho" - midnight slasher =====
      Grindhouse: high contrast, VHS tracking lines, blood spatter and a glitch.
      Oswald is condensed and tense like a thriller poster. No palette override. */
   :root[data-look="psycho"]{ --sans:"Oswald",system-ui,sans-serif; --serif:"Oswald",system-ui,sans-serif;
    --look-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='480' height='480' viewBox='0 0 480 480'%3E%3Cg fill='none' stroke='%23000' stroke-width='1.1' stroke-linecap='round' stroke-linejoin='round'%3E%3Cg transform='translate(88 96) rotate(-10)'%3E%3Cpath d='M -14 -8 Q -18 -18 0 -20 Q 18 -18 14 -8 Q 10 8 0 12 Q -10 8 -14 -8'/%3E%3Ccircle cx='-5' cy='-2' r='2.8' fill='%23000' stroke='none'/%3E%3Ccircle cx='5' cy='-2' r='2.8' fill='%23000' stroke='none'/%3E%3Cpath d='M -6 6 Q 0 9 6 6' fill='none' stroke='%23000' stroke-width='1'/%3E%3Cpath d='M -16 -12 L -18 -18 M -10 -14 L -12 -20 M 10 -14 L 12 -20 M 16 -12 L 18 -18'/%3E%3C/g%3E%3Cg transform='translate(318 64) rotate(14)'%3E%3Cpath d='M -22 0 Q 0 -14 22 0 Q 0 14 -22 0'/%3E%3Cpath d='M -10 0 A 10 10 0 0 0 10 0 A 7 7 0 0 1 -7 3 A 4 4 0 0 0 7 -1' stroke='%23000' stroke-width='0.9'/%3E%3Ccircle cx='0' cy='0' r='1.6' fill='%23000' stroke='none'/%3E%3C/g%3E%3Cg transform='translate(428 178) rotate(-16)'%3E%3Cpath d='M -9 -7 C -11 -11 -7 -15 0 -15 C 7 -15 11 -11 9 -7 L 7 4 L 5 8 L -5 8 L -7 4 Z'/%3E%3Ccircle cx='-3.5' cy='-2' r='1.9' fill='%23000' stroke='none'/%3E%3Ccircle cx='3.5' cy='-2' r='1.9' fill='%23000' stroke='none'/%3E%3Cpath d='M -1 2 L 0 4 L 1 2' fill='none'/%3E%3Cpath d='M -5 6 H -3 M -1 6 H 1 M 3 6 H 5'/%3E%3C/g%3E%3Cg transform='translate(196 214) rotate(8)'%3E%3Cpath d='M -7 -10 L -7 -4 L -10 -2 L -10 9 L 10 9 L 10 -2 L 7 -4 L 7 -10 Z'/%3E%3Crect x='-4.5' y='-13' width='9' height='3.2' rx='0.6'/%3E%3Ctext x='0' y='4' font-family='monospace' font-size='7' text-anchor='middle' fill='%23000' stroke='none' opacity='0.9'%3E×%3C/text%3E%3C/g%3E%3Cg transform='translate(72 322) rotate(-12)'%3E%3Cpath d='M -12 -28 C -14 -32 -8 -38 0 -38 C 8 -38 14 -32 12 -28 L 8 28 L -8 28 Z'/%3E%3Cline x1='-10' y1='-18' x2='10' y2='-16'/%3E%3Cline x1='-11' y1='-8' x2='11' y2='-6'/%3E%3Cline x1='-10' y1='2' x2='10' y2='4'/%3E%3Cline x1='-8' y1='12' x2='8' y2='14'/%3E%3Ccircle cx='0' cy='-32' r='7'/%3E%3Ccircle cx='-2.2' cy='-33' r='1' fill='%23000' stroke='none'/%3E%3Ccircle cx='2.2' cy='-33' r='1' fill='%23000' stroke='none'/%3E%3C/g%3E%3Cg transform='translate(356 348) rotate(18)'%3E%3Cpath d='M -11 -6 C -15 -10 -12 -16 0 -14 C 12 -16 15 -10 11 -6 C 15 -2 12 6 0 8 C -12 6 -15 -2 -11 -6' fill='none'/%3E%3Cpath d='M 0 -14 L 0 8' stroke='%23000' stroke-width='0.7'/%3E%3Cpath d='M -6 -8 C -8 -4 -6 0 -4 2'/%3E%3Cpath d='M 6 -8 C 8 -4 6 0 4 2'/%3E%3C/g%3E%3Cg transform='translate(250 30) rotate(20)'%3E%3Cpath d='M 0 -4 L 1.2 -1.2 L 4 0 L 1.2 1.2 L 0 4 L -1.2 1.2 L -4 0 L -1.2 -1.2 Z' fill='%23000' stroke='none' opacity='0.8'/%3E%3C/g%3E%3Cg transform='translate(30 210) rotate(-15)'%3E%3Cpath d='M -3 0 Q 0 -3 3 0 Q 0 3 -3 0' stroke='%23000' stroke-width='0.7'/%3E%3C/g%3E%3Cg transform='translate(460 60) rotate(25)'%3E%3Cpath d='M -3 -3 L 3 3 M 3 -3 L -3 3' stroke='%23000' stroke-width='0.7'/%3E%3C/g%3E%3Cg transform='translate(150 160) rotate(-8)'%3E%3Cpath d='M 0 -5 Q 2 0 0 5' stroke='%23000' stroke-width='0.7'/%3E%3C/g%3E%3Cg transform='translate(390 260) rotate(12)'%3E%3Cpath d='M -4 0 H 4 M 0 -4 V 4' stroke='%23000' stroke-width='0.7'/%3E%3C/g%3E%3Cg transform='translate(250 380) rotate(-20)'%3E%3Ccircle cx='0' cy='0' r='2.5' stroke='%23000' stroke-width='0.7'/%3E%3C/g%3E%3Cg transform='translate(30 460) rotate(10)'%3E%3Cpath d='M -3 -2 Q 0 2 3 -2' stroke='%23000' stroke-width='0.7'/%3E%3C/g%3E%3Ctext x='150' y='448' font-family='monospace' font-size='11' fill='%23000' stroke='none' opacity='0.8' transform='rotate(-14 150 448)'%3EPSY%3C/text%3E%3Cpath d='M 452 440 Q 458 448 452 456 Q 446 448 452 440' stroke='%23000' stroke-width='0.8' opacity='0.8' fill='none'/%3E%3C/g%3E%3C/svg%3E");
    --look-mask-size:480px 480px;
    --look-mask-ink:7.5%;
  }
:root[data-look="psycho"] .stage{
      background-image:
      url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='480' height='480' viewBox='0 0 480 480'%3E%3Cg opacity='0.09' fill='none' stroke='%231a1a1a' stroke-width='1.1' stroke-linecap='round' stroke-linejoin='round'%3E%3Cg transform='translate(88 96) rotate(-10)'%3E%3Cpath d='M -14 -8 Q -18 -18 0 -20 Q 18 -18 14 -8 Q 10 8 0 12 Q -10 8 -14 -8'/%3E%3Ccircle cx='-5' cy='-2' r='2.8' fill='none' stroke='none'/%3E%3Ccircle cx='5' cy='-2' r='2.8' fill='none' stroke='none'/%3E%3Cpath d='M -6 6 Q 0 9 6 6' fill='none' stroke='%231a1a1a' stroke-width='1'/%3E%3Cpath d='M -16 -12 L -18 -18 M -10 -14 L -12 -20 M 10 -14 L 12 -20 M 16 -12 L 18 -18'/%3E%3C/g%3E%3Cg transform='translate(318 64) rotate(14)'%3E%3Cpath d='M -22 0 Q 0 -14 22 0 Q 0 14 -22 0'/%3E%3Cpath d='M -10 0 A 10 10 0 0 0 10 0 A 7 7 0 0 1 -7 3 A 4 4 0 0 0 7 -1' stroke='%231a1a1a' stroke-width='0.9'/%3E%3Ccircle cx='0' cy='0' r='1.6' fill='none' stroke='none'/%3E%3C/g%3E%3Cg transform='translate(428 178) rotate(-16)'%3E%3Cpath d='M -9 -7 C -11 -11 -7 -15 0 -15 C 7 -15 11 -11 9 -7 L 7 4 L 5 8 L -5 8 L -7 4 Z'/%3E%3Ccircle cx='-3.5' cy='-2' r='1.9' fill='none' stroke='none'/%3E%3Ccircle cx='3.5' cy='-2' r='1.9' fill='none' stroke='none'/%3E%3Cpath d='M -1 2 L 0 4 L 1 2' fill='none'/%3E%3Cpath d='M -5 6 H -3 M -1 6 H 1 M 3 6 H 5'/%3E%3C/g%3E%3Cg transform='translate(196 214) rotate(8)'%3E%3Cpath d='M -7 -10 L -7 -4 L -10 -2 L -10 9 L 10 9 L 10 -2 L 7 -4 L 7 -10 Z'/%3E%3Crect x='-4.5' y='-13' width='9' height='3.2' rx='0.6'/%3E%3Ctext x='0' y='4' font-family='monospace' font-size='7' text-anchor='middle' fill='%231a1a1a' stroke='none' opacity='0.9'%3E%C3%97%3C/text%3E%3C/g%3E%3Cg transform='translate(72 322) rotate(-12)'%3E%3Cpath d='M -12 -28 C -14 -32 -8 -38 0 -38 C 8 -38 14 -32 12 -28 L 8 28 L -8 28 Z'/%3E%3Cline x1='-10' y1='-18' x2='10' y2='-16'/%3E%3Cline x1='-11' y1='-8' x2='11' y2='-6'/%3E%3Cline x1='-10' y1='2' x2='10' y2='4'/%3E%3Cline x1='-8' y1='12' x2='8' y2='14'/%3E%3Ccircle cx='0' cy='-32' r='7'/%3E%3Ccircle cx='-2.2' cy='-33' r='1' fill='none' stroke='none'/%3E%3Ccircle cx='2.2' cy='-33' r='1' fill='none' stroke='none'/%3E%3C/g%3E%3Cg transform='translate(356 348) rotate(18)'%3E%3Cpath d='M -11 -6 C -15 -10 -12 -16 0 -14 C 12 -16 15 -10 11 -6 C 15 -2 12 6 0 8 C -12 6 -15 -2 -11 -6' fill='none'/%3E%3Cpath d='M 0 -14 L 0 8' stroke='%231a1a1a' stroke-width='0.7'/%3E%3Cpath d='M -6 -8 C -8 -4 -6 0 -4 2'/%3E%3Cpath d='M 6 -8 C 8 -4 6 0 4 2'/%3E%3C/g%3E%3Cg transform='translate(250 30) rotate(20)'%3E%3Cpath d='M 0 -4 L 1.2 -1.2 L 4 0 L 1.2 1.2 L 0 4 L -1.2 1.2 L -4 0 L -1.2 -1.2 Z' fill='%231a1a1a' stroke='none' opacity='0.8'/%3E%3C/g%3E%3Cg transform='translate(30 210) rotate(-15)'%3E%3Cpath d='M -3 0 Q 0 -3 3 0 Q 0 3 -3 0' stroke='%231a1a1a' stroke-width='0.7'/%3E%3C/g%3E%3Cg transform='translate(460 60) rotate(25)'%3E%3Cpath d='M -3 -3 L 3 3 M 3 -3 L -3 3' stroke='%231a1a1a' stroke-width='0.7'/%3E%3C/g%3E%3Cg transform='translate(150 160) rotate(-8)'%3E%3Cpath d='M 0 -5 Q 2 0 0 5' stroke='%231a1a1a' stroke-width='0.7'/%3E%3C/g%3E%3Cg transform='translate(390 260) rotate(12)'%3E%3Cpath d='M -4 0 H 4 M 0 -4 V 4' stroke='%231a1a1a' stroke-width='0.7'/%3E%3C/g%3E%3Cg transform='translate(250 380) rotate(-20)'%3E%3Ccircle cx='0' cy='0' r='2.5' stroke='%231a1a1a' stroke-width='0.7'/%3E%3C/g%3E%3Cg transform='translate(30 460) rotate(10)'%3E%3Cpath d='M -3 -2 Q 0 2 3 -2' stroke='%231a1a1a' stroke-width='0.7'/%3E%3C/g%3E%3Ctext x='150' y='448' font-family='monospace' font-size='11' fill='%231a1a1a' stroke='none' opacity='0.8' transform='rotate(-14 150 448)'%3EPSY%3C/text%3E%3Cpath d='M 452 440 Q 458 448 452 456 Q 446 448 452 440' stroke='%231a1a1a' stroke-width='0.8' opacity='0.8' fill='none'/%3E%3C/g%3E%3C/svg%3E"),
      repeating-linear-gradient(0deg,
      transparent 0 2px,
      color-mix(in srgb,
      var(--accent) 5%, transparent) 3px, transparent 4px),
      linear-gradient(90deg,
      transparent 0 1px,
      color-mix(in srgb,
      var(--line) 10%, transparent) 1px);
      background-size:60% 50%, 40px 20px;
      background-color:var(--paper);
    }
    :root[data-look="psycho"] .node{
     border-radius:4px;
     border:2px solid var(--ink);
     box-shadow:4px 4px 0 var(--ink);
     transform:rotate(-0.4deg);
   }
   :root[data-look="psycho"] .node:nth-child(even){
     transform:rotate(0.4deg);
   }
   :root[data-look="psycho"] .node.root{
     border-radius:6px;
     border-width:3px;
     box-shadow:5px 5px 0 var(--ink);
     transform:rotate(0deg);
     font-weight:700; letter-spacing:0.02em; text-transform:uppercase;
   }
   :root[data-look="psycho"] .nodebar{
     border-radius:4px;
     border:2px solid var(--ink);
     box-shadow:4px 4px 0 var(--ink);
     transform:rotate(0.3deg);
   }
   :root[data-look="psycho"] .side{border-right:2px solid var(--ink); box-shadow:4px 0 0 var(--ink);}
   :root[data-look="psycho"] .vf-card{ border-radius:4px; border:2px solid var(--ink); box-shadow:4px 4px 0 var(--ink); transform:translate(-50%,-50%) rotate(-0.2deg); }
   :root[data-look="psycho"] .row-pop,
   :root[data-look="psycho"] .picker,
   :root[data-look="psycho"] .donate-card,
   :root[data-look="psycho"] .export-pop{ border-radius:4px; border:2px solid var(--ink); box-shadow:3px 3px 0 var(--ink); }
   :root[data-look="psycho"] .search-wrap{ border-radius:4px; border:2px solid var(--ink); box-shadow:2px 2px 0 var(--ink); }
   :root[data-look="psycho"] .minimap{ border-radius:4px; border:2px solid var(--ink); box-shadow:3px 3px 0 var(--ink); }
   :root[data-look="psycho"] .toast{ border-radius:4px; border:2px solid var(--ink); box-shadow:3px 3px 0 var(--ink); font-weight:700; letter-spacing:0.03em; text-transform:uppercase; }
   :root[data-look="psycho"] .breadcrumb{
     background:var(--paper); border:2px solid var(--ink); box-shadow:3px 3px 0 var(--ink);
     font-family:"Oswald",system-ui,sans-serif; letter-spacing:0.08em; text-transform:uppercase;
   }

/* Forest - birch grove: staggered vertical trunk lines on the canvas,
     rounded asymmetric corners, teal-green chrome. Fredoka is rounded and
     friendly, like a nature walk sign. */
  :root[data-look="forest"]{ --sans:"Fredoka",system-ui,sans-serif; --serif:"Fredoka",system-ui,sans-serif; }
  :root[data-look="forest"] .stage{
    background-image:
      radial-gradient(ellipse 7px 10px at 18% 22%, color-mix(in srgb, var(--teal) 10%, transparent) 98%, transparent 100%),
      radial-gradient(ellipse 5px 7px at 68% 18%, color-mix(in srgb, var(--teal) 7%, transparent) 98%, transparent 100%),
      radial-gradient(ellipse 9px 6px at 42% 38%, color-mix(in srgb, var(--teal) 8%, transparent) 98%, transparent 100%),
      radial-gradient(ellipse 6px 8px at 82% 52%, color-mix(in srgb, var(--teal) 6%, transparent) 98%, transparent 100%),
      radial-gradient(ellipse 8px 5px at 12% 68%, color-mix(in srgb, var(--teal) 7%, transparent) 98%, transparent 100%),
      radial-gradient(ellipse 5px 9px at 55% 78%, color-mix(in srgb, var(--teal) 6%, transparent) 98%, transparent 100%),
      radial-gradient(ellipse 6px 6px at 30% 88%, color-mix(in srgb, var(--teal) 5%, transparent) 98%, transparent 100%);
    background-size:220px 220px, 240px 240px, 200px 200px, 260px 260px, 210px 210px, 230px 230px, 190px 190px;
    background-color:var(--paper);
  }
  :root[data-look="forest"] .nodebar{
    border-radius:22px 10px 22px 10px;
    border:2px solid var(--teal); box-shadow:var(--shadow);
  }
  :root[data-look="forest"] .side{border-right:2px solid var(--teal)}
  :root[data-look="forest"] .new-map{border:2px dashed var(--teal)}
  :root[data-look="forest"] .vf-card{
    border-radius:22px 10px 22px 10px; border:2px solid var(--teal); box-shadow:var(--shadow);
  }
  :root[data-look="forest"] .vf-card h2{font-weight:600}
  :root[data-look="forest"] .row-pop,
  :root[data-look="forest"] .picker,
  :root[data-look="forest"] .donate-card,
  :root[data-look="forest"] .export-pop,
  :root[data-look="forest"] .tpl-pop{
    border-radius:18px 8px 18px 8px; border:2px solid var(--teal);
  }
  :root[data-look="forest"] .donate-card{ border-radius:24px 10px 24px 10px; }
  :root[data-look="forest"] .search-wrap{ border-radius:18px 8px 18px 8px; border:2px solid var(--teal); }
  :root[data-look="forest"] .minimap{ border-radius:18px 8px 18px 8px; border:2px solid var(--teal); }
  :root[data-look="forest"] .toast{ border-radius:16px 8px 16px 8px; border:2px solid var(--teal); }

  /* Beach - ocean ripples: horizontal wave bands on the canvas, pebble-pill
     cards. Oswald is tall and condensed, like seaside signage. */
  :root[data-look="beach"]{ --sans:"Oswald",system-ui,sans-serif; --serif:"Oswald",system-ui,sans-serif; }
  :root[data-look="beach"] .stage{
    background-image:repeating-linear-gradient(45deg, transparent 0 16px, color-mix(in srgb, var(--teal) 7%, transparent) 17px, transparent 18px);
    background-size:60px 60px; background-color:var(--paper);
  }
  :root[data-look="beach"] .nodebar{
    border-radius:999px;
    border:1px solid var(--teal); box-shadow:var(--shadow);
  }
  :root[data-look="beach"] .side{border-right:1px solid var(--teal)}
  :root[data-look="beach"] .new-map{border:1.5px dashed var(--teal)}
  :root[data-look="beach"] .vf-card{
    border-radius:999px; border:1px solid var(--teal); box-shadow:var(--shadow);
  }
  :root[data-look="beach"] .vf-card h2{font-weight:600}
  :root[data-look="beach"] .row-pop,
  :root[data-look="beach"] .picker,
  :root[data-look="beach"] .donate-card,
  :root[data-look="beach"] .export-pop,
  :root[data-look="beach"] .tpl-pop{
    border-radius:18px; border:1px solid var(--teal);
  }
  :root[data-look="beach"] .donate-card{ border-radius:24px; }
  :root[data-look="beach"] .search-wrap{ border-radius:999px; border:1px solid var(--teal); }
  :root[data-look="beach"] .minimap{ border-radius:999px; border:1px solid var(--teal); }
  :root[data-look="beach"] .toast{ border-radius:999px; border:1px solid var(--teal); }

  /* Studio - artist's sketchbook: diagonal crosshatch on the canvas, dashed
     pencil-outline chrome. Fraunces is a warm, wonky editorial serif. */
  :root[data-look="studio"]{ --sans:"Fraunces",serif; --serif:"Fraunces",serif; }
  :root[data-look="studio"] .stage{
    background-image:
      repeating-linear-gradient(45deg, color-mix(in srgb, var(--ink) 12%, transparent) 0 1px, transparent 1px 22px),
      repeating-linear-gradient(-45deg, color-mix(in srgb, var(--ink) 12%, transparent) 0 1px, transparent 1px 22px);
    background-size:31px 31px; background-color:var(--paper);
  }
  :root[data-look="studio"] .nodebar{
    border-radius:6px;
    border:1.5px dashed var(--ink); box-shadow:none;
  }
  :root[data-look="studio"] .side{border-right:1.5px dashed var(--ink)}
  :root[data-look="studio"] .new-map{border:1.5px dashed var(--ink-soft)}
  :root[data-look="studio"] .vf-card{
    border-radius:6px; border:1.5px dashed var(--ink); box-shadow:none;
  }
  :root[data-look="studio"] .vf-card h2{font-style:italic}
  :root[data-look="studio"] .row-pop,
  :root[data-look="studio"] .picker,
  :root[data-look="studio"] .donate-card,
  :root[data-look="studio"] .export-pop,
  :root[data-look="studio"] .tpl-pop{
    border-radius:6px; border:1.5px dashed var(--ink);
  }
  :root[data-look="studio"] .donate-card{ border-radius:8px; }
  :root[data-look="studio"] .search-wrap{ border-radius:6px; border:1.5px dashed var(--ink); }
  :root[data-look="studio"] .minimap{ border-radius:6px; border:1.5px dashed var(--ink); }
  :root[data-look="studio"] .toast{ border-radius:6px; border:1.5px dashed var(--ink); }

  /* Mountain - topographic contour rings on the canvas, peaked angular
     cards. Roboto Condensed is compact and alpine. */
  :root[data-look="mountain"]{ --sans:"Roboto Condensed",system-ui,sans-serif; --serif:"Roboto Condensed",system-ui,sans-serif; }
  :root[data-look="mountain"] .stage{
    background-image:
      linear-gradient(180deg, transparent 60%, color-mix(in srgb, var(--ink-soft) 12%, transparent) 61%, transparent 62%),
      repeating-linear-gradient(90deg, transparent 0 80px, color-mix(in srgb, var(--ink-soft) 8%, transparent) 81px, transparent 82px);
    background-size:100% 120px, 100% 100%; background-color:var(--paper);
  }
  :root[data-look="mountain"] .nodebar{
    border-radius:12px 12px 0 0;
    border:2px solid var(--ink-soft); box-shadow:var(--shadow-lg);
  }
  :root[data-look="mountain"] .side{border-right:2px solid var(--ink-soft)}
  :root[data-look="mountain"] .new-map{border:2px dashed var(--ink-soft)}
  :root[data-look="mountain"] .vf-card{
    border-radius:12px 12px 0 0; border:2px solid var(--ink-soft); box-shadow:var(--shadow-lg);
  }
  :root[data-look="mountain"] .vf-card h2{font-weight:700; text-transform:uppercase; letter-spacing:.04em}
  :root[data-look="mountain"] .row-pop,
  :root[data-look="mountain"] .picker,
  :root[data-look="mountain"] .donate-card,
  :root[data-look="mountain"] .export-pop,
  :root[data-look="mountain"] .tpl-pop{
    border-radius:10px 10px 0 0; border:2px solid var(--ink-soft);
  }
  :root[data-look="mountain"] .donate-card{ border-radius:14px 14px 0 0; }
  :root[data-look="mountain"] .search-wrap{ border-radius:10px 10px 0 0; border:2px solid var(--ink-soft); }
  :root[data-look="mountain"] .minimap{ border-radius:10px 10px 0 0; border:2px solid var(--ink-soft); }
  :root[data-look="mountain"] .toast{ border-radius:10px 10px 0 0; border:2px solid var(--ink-soft); }

  /* ---- in the Desert: wind-sculpted dunes - two soft parabolic ellipses
     at the horizon plus fine sand speck. Nunito is warm and dusty. Curved
     dunes distinguish from mountain sharp stratified bands. ---- */
  :root[data-look="desert"]{ --sans:"Nunito",system-ui,sans-serif; --serif:"Nunito",system-ui,sans-serif; }
  :root[data-look="desert"] .stage{
    background-image:
      url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1000 200'%3E%3Cg opacity='0.15' fill='none' stroke='%231a1a1a' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M118 162 Q117 122 122 68'/%3E%3Cpath d='M122 68 Q92 58 76 42'/%3E%3Cpath d='M122 68 Q102 48 86 30'/%3E%3Cpath d='M122 68 Q122 40 118 22'/%3E%3Cpath d='M122 68 Q142 48 160 36'/%3E%3Cpath d='M122 68 Q152 60 170 52'/%3E%3Ccircle cx='118' cy='72' r='3.2' fill='%231a1a1a' stroke='none'/%3E%3Ccircle cx='127' cy='74' r='2.6' fill='%231a1a1a' stroke='none'/%3E%3Cpath d='M348 158 Q346 118 352 64'/%3E%3Cpath d='M352 64 Q322 54 306 38'/%3E%3Cpath d='M352 64 Q332 44 316 28'/%3E%3Cpath d='M352 64 Q352 36 348 18'/%3E%3Cpath d='M352 64 Q372 44 390 34'/%3E%3Cpath d='M352 64 Q382 56 400 48'/%3E%3Ccircle cx='348' cy='68' r='3.2' fill='%231a1a1a' stroke='none'/%3E%3Ccircle cx='357' cy='70' r='2.6' fill='%231a1a1a' stroke='none'/%3E%3Cpath d='M618 160 Q616 120 622 66'/%3E%3Cpath d='M622 66 Q592 56 576 40'/%3E%3Cpath d='M622 66 Q602 46 586 30'/%3E%3Cpath d='M622 66 Q622 38 618 20'/%3E%3Cpath d='M622 66 Q642 46 660 36'/%3E%3Cpath d='M622 66 Q652 58 670 50'/%3E%3Ccircle cx='618' cy='70' r='3.2' fill='%231a1a1a' stroke='none'/%3E%3Ccircle cx='627' cy='72' r='2.6' fill='%231a1a1a' stroke='none'/%3E%3Cpath d='M848 162 Q846 122 852 70'/%3E%3Cpath d='M852 70 Q822 60 806 44'/%3E%3Cpath d='M852 70 Q832 50 816 34'/%3E%3Cpath d='M852 70 Q852 42 848 24'/%3E%3Cpath d='M852 70 Q872 50 890 40'/%3E%3Cpath d='M852 70 Q882 62 900 54'/%3E%3Ccircle cx='848' cy='74' r='3.2' fill='%231a1a1a' stroke='none'/%3E%3Ccircle cx='857' cy='76' r='2.6' fill='%231a1a1a' stroke='none'/%3E%3C/g%3E%3C/svg%3E"),
      radial-gradient(ellipse 520px 140px at 22% 108%, color-mix(in srgb, var(--line) 14%, transparent) 98%, transparent 100%),
      radial-gradient(ellipse 460px 120px at 78% 115%, color-mix(in srgb, var(--line) 11%, transparent) 98%, transparent 100%),
      radial-gradient(ellipse 620px 100px at 50% 102%, color-mix(in srgb, var(--accent) 6%, transparent) 98%, transparent 100%),
      radial-gradient(circle at 12px 12px, color-mix(in srgb, var(--ink) 9%, transparent) 1px, transparent 1.6px),
      radial-gradient(circle at 34px 28px, color-mix(in srgb, var(--ink) 7%, transparent) 0.9px, transparent 1.4px);
    background-size:100% 180px, 100% 100%, 100% 100%, 100% 100%, 46px 46px, 52px 52px;
    background-position:left bottom, 0 0, 0 0, 0 0, 0 0, 0 0;
    background-repeat:no-repeat, no-repeat, no-repeat, no-repeat, repeat, repeat;
    background-color:var(--paper);
  }
  :root[data-look="desert"] .nodebar{
    border-radius:12px;
    border:1.5px solid var(--ink-soft); box-shadow:var(--shadow);
  }
  :root[data-look="desert"] .side{border-right:1.5px solid var(--ink-soft)}
  :root[data-look="desert"] .new-map{border:1.5px dashed var(--ink-soft)}
  :root[data-look="desert"] .vf-card{
    border-radius:12px; border:1.5px solid var(--ink-soft); box-shadow:var(--shadow-lg);
  }
  :root[data-look="desert"] .vf-card h2{font-weight:700}
  :root[data-look="desert"] .row-pop,
  :root[data-look="desert"] .picker,
  :root[data-look="desert"] .donate-card,
  :root[data-look="desert"] .export-pop,
  :root[data-look="desert"] .tpl-pop{
    border-radius:12px; border:1.5px solid var(--ink-soft);
  }
  :root[data-look="desert"] .donate-card{ border-radius:14px; }
  :root[data-look="desert"] .search-wrap{ border-radius:12px; border:1.5px solid var(--ink-soft); }
  :root[data-look="desert"] .minimap{
    border-radius:12px;
    border:2px solid var(--ink-soft);
    border-bottom:3px solid var(--accent);
    box-shadow:0 4px 12px color-mix(in srgb, var(--ink-soft) 16%, transparent), inset 0 1px 0 color-mix(in srgb, #fff 55%, transparent);
    overflow:hidden;
    position:relative;
    background:var(--paper);
    transform:scaleY(-1);
  }
  :root[data-look="desert"] .minimap svg,
  :root[data-look="desert"] .minimap canvas{
    transform:scaleY(-1);
  }
  :root[data-look="desert"] .minimap::after{
    content:"";
    position:absolute; left:8px; right:8px; bottom:5px; height:2px;
    background:color-mix(in srgb, var(--accent) 20%, transparent);
    border-radius:999px; opacity:.6; pointer-events:none; z-index:2;
  }
  :root[data-look="desert"] .toast{ border-radius:12px; border:1.5px solid var(--ink-soft); }
  :root[data-look="desert"] .breadcrumb{
    background:var(--paper);
    border:1.5px solid var(--ink-soft);
    border-bottom:3px solid var(--accent);
    box-shadow:var(--shadow);
    border-radius:12px 12px 16px 16px;
    padding:4px 8px; gap:4px;
    font-family:"Nunito",system-ui,sans-serif; font-size:11px; letter-spacing:0.04em; text-transform:uppercase; font-weight:700;
  }
  :root[data-look="desert"] .breadcrumb .bc-crumb{
    border-radius:999px; padding:3px 10px; border:1.5px solid var(--ink-soft);
    background:color-mix(in srgb, var(--paper) 92%, var(--accent) 8%);
    font-weight:800;
  }
  :root[data-look="desert"] .breadcrumb .bc-crumb.current{
    background:var(--accent); color:var(--paper); border-color:var(--accent);
    box-shadow:0 0 0 2px color-mix(in srgb, var(--accent) 16%, transparent);
  }
  :root[data-look="desert"] .breadcrumb .bc-crumb:hover{
    background:color-mix(in srgb, var(--accent) 12%, var(--paper));
  }
  :root[data-look="desert"] .breadcrumb .bc-sep{
    position:relative; width:14px; text-align:center; color:transparent; opacity:1;
  }
  :root[data-look="desert"] .breadcrumb .bc-sep::after{
    content:"🌴";
    position:absolute; left:50%; top:50%; transform:translate(-50%,-50%);
    font-size:8px; opacity:.75;
  }

/* Groot - Baby Groot faces peeking from the bottom corners, vine speckle
     on the canvas. Rounded, organic chrome with a warm bark-green accent. */
  /* Moss and bark are TONES, not colours: mixing the theme's own teal and ink
     keeps them recognisable on Matrix Green, Dracula and Synthwave, where a
     fixed green and brown looked pasted on. A Look is colour-independent by
     contract - colour comes from whichever Colour Theme is active. */
  :root[data-look="groot"]{
    --sans:"Fredoka",system-ui,sans-serif; --serif:"Fredoka",system-ui,sans-serif;
    --groot-moss: color-mix(in srgb, var(--teal) 74%, var(--ink));
    --groot-bark: color-mix(in srgb, var(--ink) 62%, var(--teal));
  }
  :root[data-look="groot"] .stage{
    background-image:
      var(--groot-face, none),
      radial-gradient(circle at 20px 20px, color-mix(in srgb, var(--teal) 6%, transparent) 1px, transparent 1.6px),
      radial-gradient(circle at 40px 36px, color-mix(in srgb, var(--teal) 5%, transparent) 0.9px, transparent 1.4px);
    background-size:180px 180px, 58px 58px, 64px 64px;
    background-position:left -12px bottom -8px, 0 0, 0 0;
    background-repeat:no-repeat, repeat, repeat;
    background-color:var(--paper);
  }
  /* The face is not in this file. It is a 200x200 grid of tone indices, gzipped
     and base64'd in app.js (GROOT_FACE), rebuilt into an SVG data URI on first
     use and handed here as --groot-face. See the note there for why.

     Short version: the artwork is a dithered 5,261-pixel image, which needs
     ~3,600 separate path elements however tightly they are packed, and no path
     syntax fits that in under ~18 KB. Inlined it cost ~25 KB here and another
     ~25 KB in the export painter. As a compressed grid it is 4 KB, stored once.
     Same artwork to the pixel. */  :root[data-look="groot"] .nodebar{
    border-radius:14px;
    border:2px solid color-mix(in srgb, var(--groot-moss) 85%, var(--paper));
    background:color-mix(in srgb, var(--ink) 92%, var(--groot-moss) 8%);
    background-image:repeating-linear-gradient(90deg, transparent 0 8px, color-mix(in srgb, var(--paper) 8%, transparent) 8px 9px);
    box-shadow:0 6px 16px color-mix(in srgb, #000 22%, transparent), inset 0 1px 0 color-mix(in srgb, var(--paper) 14%, transparent);
    color:var(--paper);
  }
  :root[data-look="groot"] .nodebar button{
    border-color:color-mix(in srgb, var(--groot-moss) 28%, transparent);
    color:var(--paper);
  }
  :root[data-look="groot"] .nodebar button.on{
    background:color-mix(in srgb, var(--paper) 92%, var(--groot-moss) 8%);
    color:var(--ink); border-color:color-mix(in srgb, var(--paper) 85%, transparent);
  }
  :root[data-look="groot"] .nodebar button:hover{
    background:color-mix(in srgb, var(--paper) 14%, transparent);
  }
  :root[data-look="groot"] .nodebar .sep{
    background:color-mix(in srgb, var(--paper) 70%, transparent); opacity:.22;
  }
  :root[data-look="groot"] .side{border-right:2px solid var(--teal)}
  :root[data-look="groot"] .new-map{border:2px dashed var(--teal)}
  :root[data-look="groot"] .vf-card{
    border-radius:16px; border:2px solid var(--teal); box-shadow:var(--shadow-lg);
  }
  :root[data-look="groot"] .vf-card h2{font-weight:700}
  :root[data-look="groot"] .row-pop,
  :root[data-look="groot"] .picker,
  :root[data-look="groot"] .donate-card,
  :root[data-look="groot"] .export-pop,
  :root[data-look="groot"] .tpl-pop{
    border-radius:16px; border:2px solid var(--teal);
  }
  :root[data-look="groot"] .donate-card{ border-radius:18px; }
  :root[data-look="groot"] .search-wrap{ border-radius:16px; border:2px solid var(--teal); }
  :root[data-look="groot"] .minimap{
    border-radius:14px;
    border:2px solid var(--groot-moss);
    background:var(--paper);
    background-image:
      repeating-linear-gradient(90deg, transparent 0 2px, color-mix(in srgb, var(--groot-moss) 6%, transparent) 2px 3px);
    box-shadow:0 6px 16px color-mix(in srgb, var(--groot-moss) 20%, transparent), inset 0 1px 0 color-mix(in srgb, #fff 65%, transparent);
    overflow:hidden;
    position:relative;
    transform:scaleY(-1);
  }
  :root[data-look="groot"] .minimap svg,
  :root[data-look="groot"] .minimap canvas{
    transform:scaleY(-1);
  }
  :root[data-look="groot"] .minimap::after{
    content:"";
    position:absolute; left:8px; right:8px; bottom:5px; height:2px;
    background:color-mix(in srgb, var(--groot-moss) 22%, transparent);
    border-radius:999px; opacity:.7; pointer-events:none; z-index:2;
  }
  :root[data-look="groot"] .toast{ border-radius:16px; border:2px solid var(--teal); }
  :root[data-look="groot"] .breadcrumb{
    background:var(--paper);
    background-image:
      repeating-linear-gradient(90deg, transparent 0 10px, color-mix(in srgb, var(--groot-moss) 5%, transparent) 10px 11px);
    border:2px solid var(--groot-moss);
    border-left:4px solid var(--groot-bark);
    box-shadow:0 4px 14px color-mix(in srgb, var(--groot-moss) 18%, transparent), inset 0 1px 0 color-mix(in srgb, #fff 70%, transparent);
    border-radius:18px 10px 18px 10px;
    padding:6px 12px; gap:6px;
    font-family:"Fredoka",system-ui,sans-serif; font-size:11px; letter-spacing:0.06em; text-transform:uppercase; font-weight:800;
  }
  :root[data-look="groot"] .breadcrumb .bc-crumb{
    border-radius:12px 6px 12px 6px;
    padding:4px 12px; border:1.5px solid var(--groot-moss);
    background:color-mix(in srgb, var(--paper) 96%, var(--groot-moss) 4%);
    font-weight:800;
    box-shadow:inset 0 1px 0 color-mix(in srgb, #fff 60%, transparent);
  }
  :root[data-look="groot"] .breadcrumb .bc-crumb.current{
    background:var(--groot-moss); color:var(--paper); border-color:var(--groot-moss);
    box-shadow:0 2px 8px color-mix(in srgb, var(--groot-moss) 24%, transparent), 0 0 0 2px color-mix(in srgb, var(--groot-moss) 14%, transparent);
  }
  :root[data-look="groot"] .breadcrumb .bc-crumb:hover{
    background:color-mix(in srgb, var(--groot-moss) 12%, var(--paper));
    transform:translateY(-1px);
  }
  :root[data-look="groot"] .breadcrumb .bc-sep{
    position:relative; width:18px; height:14px; color:transparent; opacity:1;
  }
  :root[data-look="groot"] .breadcrumb .bc-sep::after{
    content:"";
    position:absolute; left:50%; top:50%; transform:translate(-50%,-50%);
    width:16px; height:10px;
    background:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 10'%3E%3Cpath d='M1 5 H15' stroke='%231a1a1a' stroke-width='1.2' stroke-linecap='round' opacity='0.7'/%3E%3Cpath d='M5 3 Q3 1 2 2 Q4 4 5 3' fill='%231a1a1a' opacity='0.55'/%3E%3Cpath d='M11 7 Q13 9 15 8 Q13 6 11 7' fill='%231a1a1a' opacity='0.55'/%3E%3C/svg%3E") center/contain no-repeat;
    opacity:1;
  }


  /* Scanlines and pixel grid tint from --ink rather than a fixed black. Black
     lines are invisible on a dark theme, and on one a CRT should glow light
     anyway - taking the theme's ink gets both for free. */


/* ===== "On a Sailboat" look - nautical: wave motion lines on the canvas,
     compass rose watermark, rope-knot breadcrumb crumbs. Quicksand is
     clean and rounded like sea-smoothed glass. */
  :root[data-look="sailboat"]{ --sans:"Quicksand",sans-serif; --serif:"Quicksand",sans-serif; }
  :root[data-look="sailboat"] .stage{
    background:
      radial-gradient(circle at 85% 15%, color-mix(in srgb, var(--teal) 4%, transparent) 0, transparent 40%);
    background-size:100% 100%;
    background-color:var(--paper);
  }
  /* Motion is a single compositor-only transform. background-position CANNOT be
     composited, so animating it repainted this whole full-viewport layer every
     frame: measured at 220 paints, 110 style recalcs and 859ms of main thread
     over 5s on a 6x-throttled CPU, against 0/0/0 for a static look. A keyframed
     translate3d runs on the compositor thread instead and touches neither.

     The layer is oversized only where it actually travels: one tile to the LEFT
     (the drift is rightward, so that is the edge that would be exposed) and a
     few px top and bottom for the bob. Insetting a full tile on all four sides
     also works but makes the compositing layer ~1680x1200 instead of ~1480x816
     at this viewport, and that is GPU memory a low-end device does not have to
     spare. contain:paint stops any invalidation escaping into the stage. */
/* A look can paint a texture as a MASK here instead of a background image, so
   its colour comes from --ink and follows the theme. The artwork itself lives
   in --look-mask on the look's own :root rule, ONCE: writing the data URI into
   both the prefixed and unprefixed property doubled it, which pushed alien past
   the per-look CSS size guard on its own. --look-mask-ink defaults to 0%, so
   this pseudo-element paints nothing for the looks that do not use it. */
.stage::before{
  content:""; position:absolute; inset:0; pointer-events:none; z-index:0;
  background-color:color-mix(in srgb, var(--ink) var(--look-mask-ink, 0%), transparent);
  -webkit-mask-image:var(--look-mask, none); mask-image:var(--look-mask, none);
  -webkit-mask-repeat:repeat;               mask-repeat:repeat;
  -webkit-mask-size:var(--look-mask-size, auto); mask-size:var(--look-mask-size, auto);
}
  .wave-layer{
    position:absolute; inset:-8px 0 -8px -200px; pointer-events:none; z-index:0;   /* scenery: under #viewport (see _syncLookFx) */
    will-change:transform; contain:paint;
    background:
      url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'%3E%3Cg opacity='0.06' fill='none' stroke='%231a1a1a' stroke-width='1.5' stroke-linecap='round'%3E%3Cpath d='M0 40 Q25 30 50 40 Q75 50 100 40 Q125 30 150 40 Q175 50 200 40'/%3E%3Cpath d='M0 80 Q25 70 50 80 Q75 90 100 80 Q125 70 150 80 Q175 90 200 80'/%3E%3Cpath d='M0 120 Q25 110 50 120 Q75 130 100 120 Q125 110 150 120 Q175 130 200 120'/%3E%3Cpath d='M0 160 Q25 150 50 160 Q75 170 100 160 Q125 150 150 160 Q175 170 200 160'/%3E%3C/g%3E%3C/svg%3E");
    background-size:200px 200px;
    display:none;
  }
  /* dx is linear 0 -> one tile; dy samples a 3px sine at the same 8s period,
     matching what the old rAF loop computed frame by frame. */
  @keyframes sailboat-swell{
    0%    { transform:translate3d(0,0,0); }
    12.5% { transform:translate3d(25px,2.1px,0); }
    25%   { transform:translate3d(50px,3px,0); }
    37.5% { transform:translate3d(75px,2.1px,0); }
    50%   { transform:translate3d(100px,0,0); }
    62.5% { transform:translate3d(125px,-2.1px,0); }
    75%   { transform:translate3d(150px,-3px,0); }
    87.5% { transform:translate3d(175px,-2.1px,0); }
    100%  { transform:translate3d(200px,0,0); }
  }
  :root[data-look="sailboat"] .wave-layer{
    display:block;
    animation:sailboat-swell 8s linear infinite;
  }
  :root[data-look="sailboat"] .node{
    border-radius:16px;
    border:1.5px solid var(--teal);
    box-shadow:0 2px 8px color-mix(in srgb, var(--teal) 12%, transparent);
  }
  :root[data-look="sailboat"] .node.root{
    border-radius:20px;
    border-width:2px;
    box-shadow:0 2px 12px color-mix(in srgb, var(--teal) 18%, transparent);
  }
  :root[data-look="sailboat"] .nodebar{
    border-radius:16px;
    border:1.5px solid var(--teal); box-shadow:var(--shadow);
  }
  :root[data-look="sailboat"] .side{border-right:1.5px solid var(--teal)}
  :root[data-look="sailboat"] .new-map{border:1.5px dashed var(--teal)}
  :root[data-look="sailboat"] .vf-card{
    border-radius:16px; border:1.5px solid var(--teal); box-shadow:var(--shadow-lg);
  }
  :root[data-look="sailboat"] .vf-card h2{font-weight:700}
  :root[data-look="sailboat"] .row-pop,
  :root[data-look="sailboat"] .picker,
  :root[data-look="sailboat"] .donate-card,
  :root[data-look="sailboat"] .export-pop,
  :root[data-look="sailboat"] .tpl-pop{
    border-radius:14px; border:1.5px solid var(--teal);
  }
  :root[data-look="sailboat"] .donate-card{ border-radius:18px; }
  :root[data-look="sailboat"] .search-wrap{ border-radius:999px; border:1.5px solid var(--teal); }
  :root[data-look="sailboat"] .minimap{
    border-radius:999px; border:1.5px solid var(--teal);
    box-shadow:0 0 12px color-mix(in srgb, var(--teal) 15%, transparent);
  }
  :root[data-look="sailboat"] .toast{ border-radius:999px; border:1.5px solid var(--teal); }
  :root[data-look="sailboat"] .breadcrumb{
    background:var(--paper); border:1.5px solid var(--teal);
    font-family:"Quicksand",sans-serif; font-size:11px; font-weight:600;
  }
  :root[data-look="sailboat"] .breadcrumb .bc-crumb{
    border-radius:999px; padding:3px 10px; font-weight:700;
  }
  :root[data-look="sailboat"] .breadcrumb .bc-crumb.current{
    background:var(--teal); color:#fff;
    box-shadow:0 0 8px color-mix(in srgb, var(--teal) 25%, transparent);
  }
  :root[data-look="sailboat"] .breadcrumb .bc-crumb:hover{
    background:color-mix(in srgb, var(--teal) 12%, var(--paper));
  }
  :root[data-look="sailboat"] .breadcrumb .bc-sep{
    color:var(--teal); opacity:.5; font-weight:900;
  }

  /* A sonar ping, because the static rings above are a DIAGRAM of sonar rather
     than sonar: the whole idea is a pulse. One ring expands from the centre and
     fades, every 5s, so the canvas is still for most of that.

     scale() and opacity only, so it runs on the compositor like the sailboat
     swell and costs no main thread. The ::after is the same ring at half phase,
     which reads as a repeating sweep rather than a lonely blip, and costs one
     more composited layer rather than any script.

     It starts at scale .12 rather than 0 so the 1.5px border never renders
     sub-pixel, which flickers at the start of each cycle. */


/* Sketchpad - expressive, bold pen strokes on a clean canvas. Thick borders,
     very asymmetric radii for a hand-drawn feel, and slightly larger node text
     to give the writing more presence. */
  :root[data-look="sketchpad"]{ --sans:system-ui,sans-serif; --serif:system-ui,sans-serif; }
  :root[data-look="sketchpad"] .node{ font-size:1.15em; }
  :root[data-look="sketchpad"] .nodebar{
    border-radius:14px 4px 14px 4px;
    border:2px solid var(--ink); box-shadow:none;
  }
  :root[data-look="sketchpad"] .side{border-right:2px solid var(--ink)}
  :root[data-look="sketchpad"] .vf-card{
    border-radius:16px 5px 16px 5px; border:2px solid var(--ink); box-shadow:var(--shadow-lg);
  }
  :root[data-look="sketchpad"] .vf-card h2{font-weight:700}
  :root[data-look="sketchpad"] .row-pop,
  :root[data-look="sketchpad"] .picker,
  :root[data-look="sketchpad"] .donate-card,
  :root[data-look="sketchpad"] .export-pop{
    border-radius:14px 4px 14px 4px; border:2px solid var(--ink);
  }
  :root[data-look="sketchpad"] .donate-card{ border-radius:18px 6px 18px 6px; }
  :root[data-look="sketchpad"] .search-wrap{ border-radius:12px 4px 12px 4px; border:2px solid var(--ink); }
  :root[data-look="sketchpad"] .minimap{ border-radius:10px 4px 10px 4px; border:2px solid var(--ink); }
  :root[data-look="sketchpad"] .toast{ border-radius:12px 5px 12px 5px; border:2px solid var(--ink); }

  /* ===== Theme panel - multi-section layout ===== */
  /* ===== Theme picker panel ===== */
  .theme-panel{
    background:var(--chrome); border:1px solid var(--chrome-edge); border-radius:14px;
    box-shadow:var(--shadow-lg); padding:8px; z-index:1000;
    min-width:340px; font-family:var(--sans);
  }
  .theme-panel-large{
    min-width:580px; max-width:700px; display:flex; flex-direction:column;
    gap:0; padding:0; overflow-x:hidden; overflow-y:auto;
  }
  .theme-panel-large .tp-section{padding:7px 12px; border-top:1px solid var(--chrome-edge)}
  .theme-panel-large .tp-section:first-child{border-top:none}
  .theme-panel-large .tp-section-special{
    background:color-mix(in srgb, var(--accent) 6%, transparent);
    border-top:1px solid color-mix(in srgb, var(--accent) 30%, transparent);
    border-bottom:1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  }
  .theme-panel-large .tp-section-special .tp-label{color:var(--accent)}
  .theme-panel-large .tp-label{
    font-size:11px; text-transform:uppercase; letter-spacing:.11em;
    color:var(--ink-soft); font-weight:700; margin-bottom:5px;
  }
  /* Cog beside a section label - opens that section's JSON settings. */
  .theme-panel-large .tp-label{ display:flex; align-items:center; gap:6px; }
  .theme-panel-large .tp-cog{
    background:none; border:none; cursor:pointer; padding:0 2px; line-height:1;
    font-size:12px; color:var(--ink-soft); opacity:.7;
  }
  .theme-panel-large .tp-cog:hover{ opacity:1; color:var(--accent); }
  /* Explanatory line and inline error inside a .var-form card. */
  .var-form .vf-hint{
    font-size:12px; line-height:1.5; color:var(--ink-soft); margin:-2px 0 12px;
  }
  .var-form .vf-err{
    font-size:12.5px; color:#c0392b; margin:8px 0 0;
    background:color-mix(in srgb, #c0392b 10%, transparent);
    border:1px solid color-mix(in srgb, #c0392b 35%, transparent);
    border-radius:8px; padding:7px 10px;
  }
  .var-form .vf-json{
    font-family:ui-monospace, SFMono-Regular, Menlo, monospace; font-size:12.5px;
    line-height:1.5; white-space:pre; overflow:auto;
  }
  /* ===== Inline colour swatches (attachColorSwatches in app.js) =====
     .cs-wrap is the textarea's own box: the mirror measures, the layer draws.
     The mirror carries the text a second time and must stay invisible but
     laid out, so visibility rather than display. */
  .cs-wrap{position:relative}
  /* Block, not inline-block: the inline baseline gap made the wrap (and so
     the layer) a few px taller than the textarea, and a square for the first
     line scrolled out of view showed in that gap under the box. */
  .cs-wrap > textarea{display:block}
  .cs-mirror{
    position:absolute; left:0; top:0; margin:0; overflow:hidden;
    visibility:hidden; pointer-events:none;
    border-style:solid; border-color:transparent;
  }
  .cs-layer{position:absolute; inset:0; overflow:hidden; pointer-events:none}
  .cs-swatch{
    position:absolute; width:11px; height:11px; padding:0; overflow:hidden;
    pointer-events:auto; cursor:pointer; border-radius:3px;
    border:1px solid color-mix(in srgb, var(--ink) 35%, transparent);
    /* Chequerboard under the fill, so a translucent colour reads as translucent. */
    background:
      linear-gradient(45deg, rgba(128,128,128,.45) 25%, transparent 25%,
                             transparent 75%, rgba(128,128,128,.45) 75%) 0 0/6px 6px,
      #fff;
  }
  .cs-swatch:hover{border-color:var(--accent); box-shadow:0 0 0 2px color-mix(in srgb, var(--accent) 30%, transparent)}
  .cs-fill{display:block; width:100%; height:100%}

  /* The picker itself. Above .var-form (z-index 6000), since it opens over one. */
  .cs-pop{
    position:fixed; z-index:6100; width:196px; padding:10px;
    background:var(--chrome); color:var(--ink);
    border:1px solid var(--chrome-edge); border-radius:12px;
    box-shadow:var(--shadow-lg); font-family:var(--sans);
    user-select:none; touch-action:none;
  }
  .cs-sv{position:relative; height:118px; border-radius:8px; overflow:hidden; cursor:crosshair}
  .cs-sv span{position:absolute; inset:0}
  .cs-sv span:first-child{background:linear-gradient(to right, #fff, rgba(255,255,255,0))}
  .cs-sv span:nth-child(2){background:linear-gradient(to top, #000, rgba(0,0,0,0))}
  .cs-bar{position:relative; height:12px; margin-top:10px; border-radius:6px; cursor:pointer}
  .cs-hue{background:linear-gradient(to right,#f00,#ff0,#0f0,#0ff,#00f,#f0f,#f00)}
  .cs-alpha{
    background:
      linear-gradient(45deg, rgba(128,128,128,.45) 25%, transparent 25%,
                             transparent 75%, rgba(128,128,128,.45) 75%) 0 0/8px 8px,
      #fff;
  }
  .cs-agrad{position:absolute; inset:0; border-radius:6px}
  .cs-dot{
    position:absolute; top:50%; width:12px; height:12px; margin:-6px 0 0 -6px;
    border-radius:50%; border:2px solid #fff; box-sizing:border-box;
    box-shadow:0 0 0 1px rgba(0,0,0,.4); pointer-events:none;
  }
  .cs-text{
    width:100%; box-sizing:border-box; margin-top:10px; padding:5px 7px;
    font-family:ui-monospace, SFMono-Regular, Menlo, monospace; font-size:12px;
    color:var(--ink); background:var(--paper);
    border:1px solid var(--line); border-radius:6px; outline:none;
  }
  .cs-text:focus{border-color:var(--accent)}

  /* While a picker is open the dialog stops hiding the map. Choosing a colour
     for the map through a card that covers it is the wrong way round, so the
     backdrop goes clear, and the card itself steps aside for the length of a
     drag (never for a click: see peek() in app.js). The picker is a child of
     body, not of the card, so it stays put and stays legible throughout. */
  .var-form .vf-backdrop{transition:background .18s ease, backdrop-filter .18s ease}
  .var-form.cs-peek .vf-backdrop{background:transparent; backdrop-filter:none}
  .var-form .vf-card{transition:opacity .16s ease}
  .var-form.cs-peek-drag .vf-card{opacity:.12}
  /* Import tile in the Layout row - a dashed square marking it as an action
     rather than one more layout to choose. */
  .theme-panel-large .theme-opt.layout-import .li-tile{
    width:70px; height:40px; flex-shrink:0; display:flex; align-items:center; justify-content:center;
    border:1.5px dashed var(--line-2); border-radius:10px;
    font-size:18px; line-height:1; color:var(--ink-soft);
  }
  .theme-panel-large .theme-opt.layout-import:hover .li-tile{
    border-color:var(--accent); color:var(--accent);
  }
  /* Saved-layout chips inside the import dialog. */
  .var-form .li-list{ display:flex; flex-wrap:wrap; gap:6px; margin-top:6px; }
  .var-form .li-chip{
    display:inline-flex; align-items:center; gap:6px; font-size:12.5px;
    background:var(--paper-2); border:1px solid var(--line); border-radius:999px; padding:4px 6px 4px 11px;
  }
  .var-form .li-chip button{
    background:none; border:none; cursor:pointer; color:var(--ink-soft); font-size:14px; line-height:1; padding:0 2px;
  }
  .var-form .li-chip button:hover{ color:#c0392b; }
  .theme-panel-large .tp-grid{
    display:grid; gap:3px;
    grid-template-columns:repeat(4,minmax(160px,1fr));
  }
  /* One-line scrolling row (Layout). Keeps the panel from gaining a whole
     extra line for a fifth option. Overrides the grid above rather than
     replacing it, so every other section is untouched. */
  .theme-panel-large .tp-grid.tp-scroll-row{
    display:flex; overflow-x:auto; overflow-y:hidden;
    scroll-behavior:smooth; scrollbar-width:none;   /* Firefox */
    position:relative;
  }
  .theme-panel-large .tp-grid.tp-scroll-row::-webkit-scrollbar{ display:none; }
  .theme-panel-large .tp-grid.tp-scroll-row > .theme-opt{
    flex:0 0 160px; width:160px; min-width:0;
  }
   /* Colour theme: 3 rows (4 columns) visible, horizontally scrollable like
      the single-row sections. A grid fills down before across, so it gets
      explicit rows and auto-flowing columns; overflow lands in new columns
      past the visible four rather than wrapping to a 4th row. The column min
      (166px) matches what the "I am" cards measure on a full-width panel:
      (700px panel - 24px padding - 12px gaps) / 4 columns. The fifth column
      (custom + Add theme tiles) is what forces every column to its minimum -
      with it the fr share never expands, so the minimum IS the card width. */
  .theme-panel-large .tp-grid.tp-scroll-row.tp-scroll-3row{
    display:grid; gap:4px; overflow-x:auto; overflow-y:hidden;
    grid-template-columns:none; grid-template-rows:repeat(3,auto);
    grid-auto-flow:column; grid-auto-columns:minmax(166px,1fr);
    scroll-behavior:smooth; scrollbar-width:none; position:relative;
  }
  .theme-panel-large .tp-grid.tp-scroll-row.tp-scroll-3row::-webkit-scrollbar{ display:none; }
  .theme-panel-large .tp-grid.tp-scroll-row.tp-scroll-3row > .theme-opt{
    flex:none; width:auto;
  }
  /* Edge fades: the only cue that more options exist off-screen. Applied with
     a mask so they tint whatever is behind them, and only on the side that
     actually has more to show - a permanent fade would imply content that
     is not there. */
  .theme-panel-large .tp-grid.tp-scroll-row.has-more-right{
    -webkit-mask-image:linear-gradient(to right, #000 calc(100% - 34px), transparent 100%);
    mask-image:linear-gradient(to right, #000 calc(100% - 34px), transparent 100%);
  }
  .theme-panel-large .tp-grid.tp-scroll-row.has-more-left{
    -webkit-mask-image:linear-gradient(to left, #000 calc(100% - 34px), transparent 100%);
    mask-image:linear-gradient(to left, #000 calc(100% - 34px), transparent 100%);
  }
  .theme-panel-large .tp-grid.tp-scroll-row.has-more-left.has-more-right{
    -webkit-mask-image:linear-gradient(to right, transparent 0, #000 34px, #000 calc(100% - 34px), transparent 100%);
    mask-image:linear-gradient(to right, transparent 0, #000 34px, #000 calc(100% - 34px), transparent 100%);
  }
  /* A focused option must never be hidden behind a fade. */
  .theme-panel-large .tp-grid.tp-scroll-row > .theme-opt:focus-visible{ outline-offset:-2px; }
  /* Two-row horizontal scrolling grid (Colour theme): only two rows are ever
     shown and extra columns scroll sideways - same fades and behaviour as the
     one-line rows, just with a taller window. Items keep stretching to fill
     the column track (the one-line row's fixed 160px flex width doesn't
     apply to grid items). */
  .theme-panel-large .tp-grid.tp-scroll-row.tp-scroll-2rows{
    display:grid;
    grid-template-rows:repeat(2,auto);
    grid-auto-flow:column;
    grid-auto-columns:minmax(160px,1fr);
  }
  .theme-panel-large .tp-grid.tp-scroll-row.tp-scroll-2rows > .theme-opt{
    width:auto; flex:none;
  }
  .style-thumb{
    width:70px; height:40px; border-radius:6px; border:1px solid var(--line);
    background:var(--paper); display:inline-flex; align-items:center; justify-content:center;
    flex-shrink:0; overflow:hidden;
  }
  .theme-opt{
    display:flex; align-items:center; gap:8px;
    padding:6px 8px; border:1.5px solid transparent; border-radius:9px;
    background:transparent; cursor:pointer; text-align:left;
    font-family:inherit; font-size:13px; font-weight:500; color:var(--ink);
  }
  .theme-opt:hover{background:var(--hover)}
  .theme-opt.active{border-color:var(--accent); background:var(--paper-2)}
  .theme-thumb{
    width:70px; height:40px; border-radius:6px;
    position:relative; border:1px solid var(--line); flex-shrink:0; overflow:hidden;
    display:flex; align-items:center; justify-content:center; gap:6px;
  }
  .theme-thumb .t1{position:static; width:14px; height:14px; border-radius:3px; flex-shrink:0}
  .theme-thumb .t2{position:static; width:11px; height:11px; border-radius:50%; flex-shrink:0}
  .theme-thumb.look-thumb{
    display:flex; align-items:center; justify-content:center;
    background:var(--paper); color:var(--ink); font-size:17px; font-weight:600;
  }
  .theme-name{flex:1; white-space:normal; line-height:1.25}

  .theme-opt.add-theme-opt{
    border:1.5px dashed var(--line-2);
    flex-direction:column; justify-content:center; text-align:center; gap:2px;
  }
  .theme-opt.add-theme-opt .theme-name{flex:0 0 auto; font-weight:600}
  .theme-opt.add-theme-opt .add-theme-icon{
    width:26px; height:26px; border-radius:50%;
    border:1.5px dashed var(--line-2);
    display:flex; align-items:center; justify-content:center;
    font-size:16px; line-height:1; font-weight:600; color:var(--ink-soft);
  }
  .theme-opt.add-theme-opt:hover .add-theme-icon,
  .theme-opt.add-theme-opt.active .add-theme-icon{border-color:var(--accent); color:var(--accent)}
  .theme-opt.custom-theme-opt .theme-name{
    white-space:normal; overflow-wrap:break-word; min-width:0;
  }
  /* Add-a-theme dialog: the one-click library picker. */
  .lib-grid{
    display:grid; grid-template-columns:repeat(3,minmax(0,1fr));
    gap:4px; max-height:216px; overflow-y:auto; margin-top:6px; padding:2px;
    scrollbar-width:thin;
  }
  .lib-card{
    display:flex; align-items:center; gap:6px; padding:5px 6px;
    border:1.5px solid transparent; border-radius:8px;
    background:transparent; cursor:pointer; text-align:left;
    font-family:inherit; font-size:12px; font-weight:500; color:var(--ink);
    transition: background-color 0.2s ease, border-color 0.2s ease;
  }
  .lib-card:hover{background:var(--hover); border-color:var(--line-2)}
  .lib-card .lib-name{flex:1; min-width:0; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; line-height:1.2}


  /* ===== Context toolbar on selected node ===== */
  .nodebar{position:absolute;z-index:25;display:flex;align-items:center;gap:2px;background:var(--toolbar-bg);color:var(--toolbar-text);border-radius:10px;padding:4px;box-shadow:var(--shadow-lg)}
  .nodebar .nb-group{display:flex;gap:1px}
  .nodebar .nb-div{width:1px;height:22px;background:color-mix(in srgb, var(--toolbar-text) 22%, transparent);margin:0 4px}
  .nodebar button{border:none;background:none;color:var(--toolbar-text);min-width:30px;height:30px;padding:0;border-radius:7px;font-size:14px;display:inline-flex;align-items:center;justify-content:center;cursor:pointer;font-family:inherit}
  .nodebar button:hover{background:color-mix(in srgb, var(--toolbar-text) 16%, transparent)}
  .nodebar button.on{background:var(--accent);color:#fff}
  .nodebar button.size-btn{padding:0 8px;gap:3px;font-size:12.5px;font-weight:500;font-variant-numeric:tabular-nums}
  .nodebar button.color-btn{padding:0 6px;gap:2px}
  .nodebar button .caret{font-size:9px;opacity:.7}
  .nodebar button .A-mark{font-family:var(--serif);font-weight:700;font-size:13px;line-height:1;display:inline-block;padding-bottom:1px}
  .nodebar button b,.nodebar button s,.nodebar button u,.nodebar button i{font-family:var(--serif);font-size:14px}
  .nodebar button i{font-style:italic}
  .node-text math{ font-size:1.04em; }
  .node-text math[display="block"]{ display:block; margin:3px auto; }
  .node-text{min-width:0;max-width:100%;overflow-wrap:anywhere;word-break:break-word}
  .node-text code{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:.9em;background:var(--paper-2,rgba(127,127,127,.14));padding:.1em .35em;border-radius:4px}
  /* Block nodes: a fenced code block or a table imported as its own node */
  .node-block{max-width:100%;overflow:auto;text-align:left}
  .node-block pre{margin:0;white-space:pre;overflow-x:auto;background:var(--paper-2,rgba(0,0,0,.05));padding:6px 9px;border-radius:6px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11.5px;line-height:1.5}
  .node-block pre code{font-family:inherit}
  .node-block table{border-collapse:collapse;font-size:11.5px}
  .node-block th,.node-block td{border:1px solid var(--line,#d9dee6);padding:2px 7px;text-align:left;white-space:nowrap}
  .node-block th{background:var(--paper-2,rgba(0,0,0,.05));font-weight:600}
  .node.block-node{max-width:none}                 /* grow to fit code/table; no scrollbar unless resized smaller */
  .block-node .node-text{cursor:default}
  .node .img-alt{display:block;font-size:12px;font-style:italic;color:var(--ink-soft,#667);white-space:normal;max-width:220px;line-height:1.4}
  .node.img-missing{border-style:dashed}
  .node.editing-block .node-block{cursor:text;user-select:text}
  .node.editing-block{border-color:var(--accent,#e0613a)}
  .node-text .node-link{color:var(--link,var(--accent));text-decoration:underline;text-underline-offset:2px;cursor:pointer;word-break:break-all}
  .node-text .node-link:hover{color:var(--accent-deep)}
  .node.editing .node-text .node-link{cursor:text;color:inherit;text-decoration:underline}
  .node-text .node-link-fav{width:14px;height:14px;border-radius:3px;object-fit:cover;vertical-align:-2px;margin-right:5px;display:inline-block;background:var(--line-2,#e2e8f0)}
  .node-text .node-link-label{word-break:break-all}
  .node.editing .node-text .node-link-fav{display:none}
  .swatches{display:flex;gap:3px;align-items:center;padding:0 2px}
  .sw{width:18px;height:18px;border-radius:50%;border:2px solid transparent;cursor:pointer}
  .sw:hover{transform:scale(1.18)}

  /* ===== Picker popovers (font size / text color / highlight) ===== */
  .picker{background:var(--node-bg, #fff);color:var(--ink);border-radius:10px;box-shadow:0 10px 32px rgba(0,0,0,.30),0 1px 3px rgba(0,0,0,.10);padding:6px;display:flex;gap:3px;align-items:center;z-index:1000;border:1px solid var(--chrome-edge)}
  .picker.size{flex-direction:column;max-height:240px;overflow-y:auto;padding:4px}
  .picker.size button{min-width:54px;justify-content:flex-start;padding:6px 12px}
  .picker button{border:none;background:none;cursor:pointer;padding:6px 10px;font-family:inherit;font-size:13px;border-radius:6px;color:var(--ink);display:inline-flex;align-items:center;justify-content:center}
  .picker button:hover{background:var(--hover)}
  .picker button.on{background:var(--paper-2);font-weight:600;color:var(--ink)}
  .picker .p-sw{width:22px;height:22px;padding:0;border-radius:50%;border:2px solid var(--node-bg, #fff);box-shadow:0 0 0 1px var(--line-2)}
  .picker .p-sw.on{box-shadow:0 0 0 2px var(--accent)}
  .picker .p-default{color:var(--ink-soft);font-size:12px;padding:6px 8px;border-right:1px solid var(--line);margin-right:2px;border-radius:0}

  /* ===== Empty state ===== */
  .empty{position:absolute;inset:0;display:grid;place-items:center;text-align:center;color:var(--ink-soft);z-index:5}
  .empty .e-card{background:var(--chrome);border:1px solid var(--chrome-edge);border-radius:20px;padding:40px 44px;box-shadow:var(--shadow-lg);max-width:380px}
  .empty h2{font-family:var(--serif);font-size:26px;color:var(--ink);margin:0 0 8px}
  .empty p{margin:0 0 20px;line-height:1.6}

  .toast{position:absolute;bottom:64px;left:50%;transform:translateX(-50%) translateY(20px);background:var(--toolbar-bg);color:var(--toolbar-text);padding:11px 20px;border-radius:11px;font-size:13.5px;font-weight:500;box-shadow:var(--shadow-lg);opacity:0;pointer-events:none;transition:opacity .25s,transform .25s,background-color .3s ease,border-color .3s ease,color .3s ease;z-index:50}
  .toast.show{opacity:1;transform:translateX(-50%) translateY(0)}
  /* ===== Login overlay (cloud / static-deploy mode only) ===== */
  .login-overlay{
    position:fixed; inset:0; z-index:5000;
    display:flex; align-items:center; justify-content:center;
    background:var(--paper);
    font-family:var(--sans);
    padding:20px; box-sizing:border-box;
  }
  .login-card{
    background:var(--node-bg, #fff); color:var(--ink);
    border-radius:16px; box-shadow:0 22px 70px rgba(0,0,0,.25), 0 1px 3px rgba(0,0,0,.06);
    padding:32px 36px; width:520px; max-width:92vw;
    border:1px solid var(--chrome-edge);
    /* Never taller than the window: the card scrolls inside itself instead of
       pushing the sign-in button off-screen where it cannot be reached. The
       collapsed <details> below keep it short enough that this rarely engages.

       Sized against the overlay (100% of a padded, inset:0 flex parent), NOT
       against 100vh. The app scales its whole UI at small viewports - at 0.8x a
       600px window is 750 CSS px of usable space, so a vh-based cap clips the
       card several hundred pixels short of the room it actually has. */
    max-height:100%;
    overflow-y:auto; overscroll-behavior:contain;
  }
  .login-brand{display:flex; align-items:center; gap:10px; margin-bottom:18px}
  .login-brand .mark{flex:0 0 auto; filter:drop-shadow(0 2px 6px rgba(224,97,58,.3))}
  .login-brand h1{
    font-family:var(--serif); font-weight:900; font-size:26px; margin:0;
    color:var(--ink); letter-spacing:-.5px;
  }
  .login-brand h1 span{color:var(--accent)}
  .login-card h2{
    font-family:var(--serif); font-weight:700; font-size:22px;
    margin:0 0 10px; color:var(--ink);
  }
  .login-card > p{
    color:var(--ink-soft); line-height:1.55; margin:0 0 14px; font-size:14px;
  }
  .login-card code{
    background:var(--paper-2); padding:1px 6px; border-radius:4px;
    font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace; font-size:12.5px;
  }
  .login-steps{
    counter-reset:step; list-style:none; padding:0; margin:18px 0;
  }
  .login-steps > li{
    position:relative; padding-left:40px; margin-bottom:18px;
    counter-increment:step;
  }
  .login-steps > li:before{
    content:counter(step);
    position:absolute; left:0; top:-2px;
    width:28px; height:28px; border-radius:50%;
    background:var(--accent); color:#fff;
    display:flex; align-items:center; justify-content:center;
    font-weight:700; font-size:14px;
  }
  .login-step-link{
    color:var(--accent); font-weight:600; text-decoration:none; font-size:15px;
  }
  .login-step-link:hover{text-decoration:underline}
  .login-step-hint{font-size:13px; color:var(--ink-soft); margin-top:6px; line-height:1.5}
  .login-steps label{display:block; font-size:14px; color:var(--ink); margin-bottom:6px; font-weight:500}
  .token-input{display:flex; gap:8px}
  .token-input input{
    flex:1; padding:10px 12px;
    font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace; font-size:13px;
    border:1.5px solid var(--line); border-radius:8px;
    background:var(--paper); color:var(--ink); outline:none;
  }
  .token-input input:focus{border-color:var(--accent); background:var(--node-bg, #fff)}
  .token-input button{
    padding:10px 20px; background:var(--accent); color:#fff;
    border:none; border-radius:8px; font-family:inherit; font-weight:600;
    cursor:pointer; font-size:14px;
  }
  .token-input button:hover{background:var(--accent-deep)}
  .token-input button:disabled{opacity:.65; cursor:wait}
  .login-error{
    color:#c5392a; font-size:13px; margin-top:8px; min-height:16px; line-height:1.4;
  }
  /* Each host offers two sign-in methods. The one that needs no setup leads;
     the other collapses, so the card stays short enough to fit on a laptop
     window. showLoginOverlay() opens the token method automatically whenever
     OAuth isn't usable, so nobody lands on a card with nothing actionable. */
  .login-token{margin-top:14px; border-top:1px solid var(--chrome-edge); padding-top:12px}
  .login-token > summary{
    cursor:pointer; list-style:none; color:var(--accent); font-size:13.5px; font-weight:600; padding:2px 0;
  }
  .login-token > summary::-webkit-details-marker{display:none}
  .login-token > summary::before{content:'▸ '; display:inline-block; transition:transform .15s}
  .login-token[open] > summary::before{content:'▾ '}
  .login-token > summary:hover{text-decoration:underline}
  .login-token .login-steps{margin-top:12px}
  .pane-label{display:block; font-size:14px; color:var(--ink); margin:16px 0 6px; font-weight:500}
  /* The repository target is a setting, not the sign-in action, so it folds
     away and the card opens on the button. The summary always shows the
     current value, and showLoginOverlay() opens the section whenever that
     value is not the default, so a custom target is never out of sight. */
  .login-repo{margin-top:14px}
  .login-repo > summary{
    cursor:pointer; list-style:none; color:var(--ink-soft); font-size:13px; padding:2px 0;
  }
  .login-repo > summary::-webkit-details-marker{display:none}
  .login-repo > summary::before{content:'\25B8 '; display:inline-block}
  .login-repo[open] > summary::before{content:'\25BE '}
  .login-repo > summary:hover{color:var(--ink)}
  .login-repo > summary .repo-current{color:var(--ink); font-size:12.5px}
  .login-repo > .repo-input{margin-top:8px}

  /* "No account yet?" line under each pane's sign-in controls. A link is all
     MindSpark can offer - neither host exposes an API to create an account, so
     the alternative to this line is a visitor with nowhere to go. Muted until
     it has a target: the Gitea one stays href-less until an instance is typed. */
  .login-signup{margin:10px 0 0; font-size:12.5px; color:var(--ink-soft); line-height:1.55}
  /* Link on its own line, explanation beneath - the same shape as the numbered
     steps' .login-step-link + .login-step-hint. Inline, the arrow ran straight
     into the next sentence and read as one run-on; worse in the Gitea pane,
     where the parked link is muted and stops looking like a link at all. */
  .login-signup a{display:block; margin-bottom:1px; color:var(--accent); font-weight:600; text-decoration:none}
  .login-signup a:hover{text-decoration:underline}
  .login-signup a[aria-disabled="true"]{color:var(--ink-soft); font-weight:500; cursor:default}

  /* Forge picker - GitHub vs Gitea/Forgejo. A segmented control rather than a
     <select> so both options are visible: users arriving from the "does this
     work with my Forgejo?" thread need to see the answer without opening a menu. */
  .forge-tabs{display:flex; gap:4px; margin:16px 0 4px; padding:4px; border-radius:10px; background:var(--paper-2)}
  .forge-tab{
    flex:1; padding:8px 10px; border:none; border-radius:7px; cursor:pointer;
    background:transparent; color:var(--ink-soft); font-family:inherit; font-size:13.5px; font-weight:600;
  }
  .forge-tab:hover{color:var(--ink)}
  .forge-tab.is-on{background:var(--paper); color:var(--ink); box-shadow:0 1px 3px rgba(0,0,0,.10)}
  .instance-input{
    width:100%; box-sizing:border-box; padding:10px 12px; margin-bottom:2px;
    font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace; font-size:13px;
    border:1.5px solid var(--line); border-radius:8px;
    background:var(--paper); color:var(--ink); outline:none;
  }
  .instance-input:focus{border-color:var(--accent); background:var(--node-bg, #fff)}

  /* Classic-token fallback tucked inside step 2 - present but not the default path. */
  .login-fallback{margin-top:8px}
  .login-fallback summary{cursor:pointer; color:var(--ink-soft); font-size:12.5px}
  .login-fallback summary:hover{color:var(--ink)}
  .login-fallback p{margin:8px 0 0; font-size:12.5px; color:var(--ink-soft); line-height:1.55}
  .login-fallback a{color:var(--accent)}
  .login-extra{margin-top:18px; padding-top:16px; border-top:1px solid var(--chrome-edge)}
  .login-extra summary{cursor:pointer; color:var(--ink-soft); font-size:13px; font-weight:500}
  .login-extra summary:hover{color:var(--ink)}
  .login-extra p{margin:10px 0 0; font-size:13px; color:var(--ink-soft); line-height:1.6}
  .login-extra a{color:var(--accent)}

  /* User pill - shown in topbar after GitHub sign-in */
  .user-pill{
    display:flex; align-items:center; gap:8px;
    padding:3px 4px 3px 4px;
    background:var(--chrome); border:1px solid var(--chrome-edge);
    border-radius:22px; font-size:13px; font-weight:500;
    color:var(--ink); height:32px;
  }
  .user-pill img{width:24px; height:24px; border-radius:50%; background:var(--paper-2)}
  /* Shown instead of the avatar when the image can't load. A self-hosted Gitea
     or Forgejo serves avatars from its own origin, which img-src cannot know in
     advance, so for those users this is the normal state - not an error state. */
  .user-pill .user-initial{
    width:24px; height:24px; border-radius:50%; padding:0;
    display:flex; align-items:center; justify-content:center;
    background:var(--accent); color:#fff; font-size:12px; font-weight:700; flex:0 0 auto;
  }
  .statusbar .user-pill .user-initial{width:20px; height:20px; font-size:11px}
  .user-pill span{padding:0 4px}
  .user-pill button{
    background:transparent; border:none; color:var(--ink-soft);
    cursor:pointer; font-family:inherit; padding:2px 8px;
    border-radius:6px; font-size:14px; height:26px;
  }
  .user-pill button:hover{background:var(--hover); color:var(--ink)}

  /* ===== Donate button + modal ===== */
  .tb.donate-btn{color:#e0613a; font-size:17px}
  .tb.donate-btn:hover{background:rgba(224,97,58,.12); color:#e0613a}

  .donate-modal{position:fixed; inset:0; z-index:6000; font-family:var(--sans); animation:fadeIn .15s ease}
  @keyframes fadeIn{from{opacity:0}to{opacity:1}}
  .donate-backdrop{position:absolute; inset:0; background:rgba(20,15,8,.45); backdrop-filter:blur(2px)}
  .donate-card{
    position:absolute; left:50%; top:50%; transform:translate(-50%,-50%);
    background:var(--node-bg, #fff); color:var(--ink);
    border-radius:18px; box-shadow:0 30px 80px rgba(0,0,0,.35);
    padding:30px 32px; width:440px; max-width:92vw; max-height:90vh; overflow-y:auto;
    border:1px solid var(--chrome-edge);
  }
  .donate-close{
    position:absolute; top:12px; right:14px; width:32px; height:32px;
    border:none; background:transparent; color:var(--ink-soft);
    font-size:22px; line-height:1; cursor:pointer; border-radius:8px;
  }
  .donate-close:hover{background:var(--hover); color:var(--ink)}
  .donate-head{text-align:center; margin-bottom:22px}
  .donate-icon{
    width:54px; height:54px; border-radius:50%;
    background:radial-gradient(circle at 30% 25%, #ff8a5b, #e0613a);
    color:#fff; font-size:26px; display:flex; align-items:center; justify-content:center;
    margin:0 auto 14px; box-shadow:0 6px 18px rgba(224,97,58,.4);
  }
  .donate-head h2{font-family:var(--serif); font-weight:700; font-size:22px; margin:0 0 6px}
  .donate-head p{color:var(--ink-soft); font-size:14px; line-height:1.55; margin:0}
  .donate-label{font-size:11px; text-transform:uppercase; letter-spacing:.1em; color:var(--ink-soft); font-weight:700; margin-bottom:8px}
  .donate-amounts{margin-bottom:18px}
  .donate-amount-row{display:flex; gap:8px; flex-wrap:wrap}
  .donate-amt{
    flex:1; min-width:60px; padding:11px 6px;
    background:var(--paper-2); border:1.5px solid var(--line); border-radius:9px;
    font-family:inherit; font-weight:600; font-size:14px; color:var(--ink); cursor:pointer;
    transition:.15s;
  }
  .donate-amt:hover{border-color:var(--accent); color:var(--accent)}
  .donate-amt.on{background:var(--accent); color:#fff; border-color:var(--accent)}
  .donate-custom{
    flex:1.4; min-width:90px; display:flex; align-items:center; gap:4px;
    background:var(--paper-2); border:1.5px solid var(--line); border-radius:9px;
    padding:0 10px; color:var(--ink-soft);
  }
  .donate-custom input{
    flex:1; width:0; border:none; background:transparent; outline:none;
    font-family:inherit; font-weight:600; font-size:14px; padding:10px 0; color:var(--ink);
  }
  .donate-providers{display:flex; flex-direction:column; gap:6px; margin-bottom:18px}
  .donate-provider{
    display:flex; align-items:center; gap:12px; padding:13px 14px;
    background:var(--paper-2); border:1px solid var(--line); border-radius:10px;
    font-family:inherit; font-size:14px; font-weight:500; color:var(--ink);
    cursor:pointer; transition:.15s; text-align:left;
  }
  .donate-provider:hover{background:var(--node-bg, #fff); border-color:var(--p-color); transform:translateX(2px)}
  .donate-provider .dp-icon{
    width:32px; height:32px; border-radius:8px;
    background:var(--p-color); color:#000; opacity:.95;
    display:flex; align-items:center; justify-content:center; font-weight:700; font-size:15px;
    flex-shrink:0;
  }
  .donate-provider .dp-label{flex:1}
  .donate-provider .dp-arrow{color:var(--ink-soft); font-size:16px}
  .donate-empty{
    background:var(--paper-2); border-radius:10px; padding:18px;
    font-size:13px; color:var(--ink-soft); line-height:1.6;
  }
  .donate-empty .small{font-size:12px}
  .donate-foot{
    text-align:center; padding-top:14px;
    border-top:1px solid var(--chrome-edge); font-size:12.5px;
  }
  .donate-foot a{color:var(--ink-soft); text-decoration:none; margin:0 6px}
  .donate-foot a:hover{color:var(--accent)}

  /* ===== MOBILE / TOUCH ===== */
  @media (max-width: 720px){
    /* Single-column grid: stage takes the whole screen; sidebar overlays it */
    .app{grid-template-columns:1fr}
    body.md-ready .app{grid-template-columns:1fr}                     /* single column; md pane overlays */
    #mdPane{position:fixed;top:0;left:0;bottom:0;width:min(94vw,560px);z-index:200;box-shadow:var(--shadow-lg);transform:translateX(-100%);transition:transform .25s cubic-bezier(.4,0,.2,1)}
    body.md-mode #mdPane{width:min(94vw,560px);transform:translateX(0)}
    #mdPane .md-resize{display:none}
    .side{
      position:fixed; top:0; left:0; bottom:0; width:min(280px, 86vw);
      z-index:200; box-shadow:var(--shadow-lg);
      transform:translateX(0);
      transition:transform .25s cubic-bezier(.4,0,.2,1);
    }
    .side.collapsed{
      width:min(280px, 86vw) !important;     /* keep width so transform works */
      transform:translateX(-100%);
      border:none; box-shadow:none;
    }
    /* Off-canvas overlay shows the sidebar contents again - but only the
       ACTIVE pane, and with !important to beat the collapsed-rail rules.
       (The brand stays hidden: the overlay is dismissed by tapping the dimmed
       stage, which closes the sidebar.) */
    .side.collapsed .side-tabs{display:flex !important}
    .side.collapsed .side-pane.active{display:flex !important}
    .side.collapsed .side-foot{display:block !important}
    .side.collapsed .side-rail,
    .side-resize{display:none !important}       /* no icon rail / resize on touch */
    /* Status bar: single-line, hint text shrinks to fit */
    .statusbar{padding:4px 10px; gap:8px; grid-column:1; grid-row:4}
    .statusbar .hint{max-width:58%}
    .statusbar .save-pill{display:none}
    .statusbar .token-total{padding:4px 9px; font-size:11px}
    /* Dim the canvas while the mobile sidebar is open */
    .app:has(.side:not(.collapsed)) .stage::after{
      content:""; position:absolute; inset:0; background:rgba(20,15,8,.35);
      z-index:150; backdrop-filter:blur(1px);
    }
    .stage{width:100%}

    /* Topbar: keep buttons readable on tiny screens */
    .topbar{padding:7px 8px; gap:4px; grid-column:1; grid-row:1}
    .side{grid-column:1; grid-row:2}
    .stage{grid-column:1; grid-row:3}
    #tabStrip, #tabsBtn{display:none}               /* no tabs on touch screens */
    .title-edit{min-width:60px; max-width:130px; font-size:16px; padding:4px 8px}
    .tb{width:38px; height:38px; font-size:18px}    /* bigger tap targets */
    .tb.wide{padding:0 10px}
    .save-pill{display:none}                        /* hide on phones to save room */
    .user-pill span{display:none}                   /* avatar only */
    .search-wrap.open{width:140px}
    .search-wrap.open.replace-mode{width:min(86vw,330px)}
    .donate-btn{display:flex}

    .hint{display:none}

    /* Format toolbar wraps and scrolls on narrow screens */
    .nodebar{max-width:calc(100vw - 16px); flex-wrap:wrap}
    .nodebar button{width:34px; height:34px; min-width:34px}

    /* Overview chip tighter on phones; minimap hidden */
    .overview{gap:4px; padding:2px 4px}
    .overview .minimap{display:none}
    .zoom-row button{width:32px; height:32px}

    /* Cards fit phone width */
    .login-card{padding:24px 22px}
    .login-brand h1{font-size:22px}
    .notes-popup{width:96vw}
    .donate-card{padding:24px 22px; border-radius:14px}
    .donate-head h2{font-size:20px}

    /* Theme panel becomes a bottom sheet */
    .theme-panel-large{
      min-width:0; width:100vw; max-width:100vw;
      position:fixed !important; left:0 !important; right:0 !important;
      bottom:0; top:auto !important;
      border-radius:16px 16px 0 0; max-height:80vh; overflow-y:auto;
    }
    .theme-panel-large .tp-grid{grid-template-columns:repeat(2, 1fr)}
  }

  /* Disable browser tap-highlight on interactive UI */
  .tb, .node, .handle, .sw, .donate-provider, .donate-amt, .theme-opt, .map-item,
  .nodebar button, .picker button, .login-card button {
    -webkit-tap-highlight-color:transparent;
    touch-action:manipulation;
  }
  /* Stage shouldn't double-tap-zoom on iOS */
  #stage{touch-action:none}

  /* ===== QR sub-view inside the donate modal ===== */
  .donate-back{
    position:absolute; top:14px; left:14px;
    border:none; background:transparent; cursor:pointer;
    color:var(--ink-soft); font-family:inherit; font-size:13px; padding:4px 8px;
    border-radius:6px;
  }
  .donate-back:hover{background:var(--hover); color:var(--ink)}
  .qr-view{text-align:center; padding-top:8px}
  .qr-view h2{font-family:var(--serif); font-weight:700; font-size:20px; margin:0 0 6px; color:var(--ink)}
  .qr-sub{color:var(--ink-soft); font-size:13.5px; line-height:1.5; margin:0 0 18px}
  .qr-frame{
    width:240px; max-width:90%; aspect-ratio:1/1; margin:0 auto;
    background:#fff; border-radius:12px; padding:14px;
    box-shadow:0 4px 20px rgba(0,0,0,.12); border:1px solid var(--chrome-edge);
  }
  .qr-image{width:100%; height:100%; object-fit:contain; display:block}
  .qr-note{
    margin-top:14px; font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
    font-size:13px; color:var(--ink); background:var(--paper-2);
    padding:7px 12px; border-radius:7px; display:inline-block;
  }
  .qr-deeplink{
    display:inline-block; margin-top:14px; font-size:13.5px;
    color:var(--accent); text-decoration:none; font-weight:500;
  }
  .qr-deeplink:hover{text-decoration:underline}
  .qr-foot{margin:18px 0 0; font-size:13px; color:var(--ink-soft)}

  /* ===== Export popover ===== */
  .export-pop{
    background:var(--chrome); border:1px solid var(--chrome-edge); border-radius:14px;
    box-shadow:var(--shadow-lg); padding:6px; z-index:1000;
    min-width:280px; max-width:300px; font-family:var(--sans);
    display:flex; flex-direction:column; gap:1px;
    max-height:calc(100vh - 72px); overflow-y:auto;
  }
  .export-pop button{
    display:flex; align-items:center; gap:12px;
    padding:9px 10px; background:transparent; border:none;
    border-radius:9px; cursor:pointer; text-align:left;
    color:var(--ink); font-family:inherit; font-size:13.5px;
  }
  .export-pop button:hover{background:var(--hover)}
  .export-pop .ex-ic{
    width:30px; height:30px; flex-shrink:0;
    display:flex; align-items:center; justify-content:center;
    background:var(--paper-2); border-radius:7px;
    font-size:15px; font-family:ui-monospace,monospace;
  }
  .export-pop button span:not(.ex-ic){display:flex; flex-direction:column; line-height:1.3}
  .export-pop button b{font-weight:600; font-size:13px}
  .export-pop button i{font-style:normal; color:var(--ink-soft); font-size:11.5px; margin-top:1px}
  .export-pop .ex-div{height:1px; background:var(--chrome-edge); margin:4px 6px}

  /* ===== Templates popover (classic floating) ===== */
  .tpl-pop{
    background:var(--chrome); border:1px solid var(--chrome-edge); border-radius:14px;
    box-shadow:var(--shadow-lg); padding:8px; z-index:1000;
    width:340px; font-family:var(--sans);
    display:flex; flex-direction:column; gap:1px;
    overflow-y:auto;
  }
  .tpl-pop .tpl-head{
    font-size:11px; text-transform:uppercase; letter-spacing:.11em;
    color:var(--ink-soft); font-weight:700; padding:6px 10px 8px;
  }
  .tpl-pop .tpl-divider{height:1px; background:var(--chrome-edge); margin:5px 6px}
  .tpl-pop .tpl-chev{margin-left:auto; color:var(--ink-soft); font-size:18px; font-weight:400; padding-left:6px}
  .tpl-cat:hover .tpl-chev{color:var(--ink)}
  .tpl-pop .tpl-back{
    display:flex; align-items:center; gap:4px;
    background:transparent; border:none; cursor:pointer;
    color:var(--ink-soft); font-family:inherit; font-size:12.5px; font-weight:600;
    padding:6px 8px; border-radius:8px; text-align:left;
  }
  .tpl-pop .tpl-back:hover{background:var(--hover); color:var(--ink)}
  .tpl-item{
    display:flex; align-items:center; gap:11px;
    padding:9px 10px; background:transparent; border:none;
    border-radius:9px; cursor:pointer; text-align:left;
    color:var(--ink); font-family:inherit;
  }
  .tpl-item:hover{background:var(--hover)}
  .tpl-ic{
    width:30px; height:30px; flex-shrink:0;
    display:flex; align-items:center; justify-content:center;
    color:#fff; border-radius:7px; font-weight:700;
    font-size:14px; font-family:var(--serif);
  }
  .tpl-item span:not(.tpl-ic){display:flex; flex-direction:column; line-height:1.3; min-width:0}
  .tpl-item b{font-weight:600; font-size:13px; color:var(--ink); white-space:nowrap; overflow:hidden; text-overflow:ellipsis}
  .tpl-item i{font-style:normal; color:var(--ink-soft); font-size:11.5px; margin-top:2px}
  .tpl-pop .tpl-del{
    margin-left:auto; color:var(--ink-soft); font-size:12px; padding:2px 6px;
    border-radius:5px; opacity:0;
  }
  .tpl-pop .tpl-item:hover .tpl-del{opacity:.7}
  .tpl-pop .tpl-del:hover{opacity:1; background:var(--hover); color:#c0392b}

  /* ===== Sidebar GitHub / bug links ===== */
  .side-links{
    display:flex; flex-direction:column; gap:8px; margin-top:10px; padding-top:10px;
    border-top:1px solid var(--chrome-edge);
  }
  .side-links a{
    display:flex; align-items:center; gap:7px;
    color:var(--ink-soft); text-decoration:none;
    font-size:12px; font-weight:500; white-space:nowrap;
  }
  .side-links a:hover{color:var(--accent)}
  /* Uniform 16px icon gutter so emoji and the GitHub SVG line up in a column. */
  .side-links a svg,
  .side-links a .li-ic{
    flex-shrink:0; width:16px; height:16px;
    display:inline-flex; align-items:center; justify-content:center;
    opacity:.85; font-size:13px; line-height:1;
  }
  .gh-stars{margin-left:auto;font-size:11px;font-weight:600;color:var(--ink-soft);background:var(--paper-2);border:1px solid var(--line);border-radius:20px;padding:1px 7px;line-height:1.6;white-space:nowrap}
  .gh-stars[hidden]{display:none}

  /* Inline lists inside a node (created via the selection-aware UL/OL button).
     Override the centered text-align since bulleted lines look better aligned left. */
  .node-text ul, .node-text ol{
    margin:4px 0; padding-left:22px;
    text-align:left; display:inline-block; vertical-align:top;
  }
  .node-text li{margin:2px 0}
  .node-text ul{list-style-type:disc}
  .node-text ol{list-style-type:decimal}

  /* ===== Focus mode - hide all chrome, full-bleed canvas ===== */
  body.focus-mode .topbar,
  body.focus-mode .side,
  body.focus-mode .hint,
  body.focus-mode .save-pill,
  body.focus-mode .user-pill,
  body.focus-mode .empty .btn-row,
  body.focus-mode .statusbar,
  body.focus-mode .search-wrap{display:none !important}
  body.focus-mode .app{grid-template-columns:1fr}
  body.focus-mode .stage{grid-column:1;grid-row:3;width:calc(100vw / var(--ui-zoom, 1)); height:calc(100vh / var(--ui-zoom, 1)); height:calc(100dvh / var(--ui-zoom, 1))}
  .focus-exit{
    position:fixed; top:16px; right:18px; z-index:5500;
    padding:8px 14px;
    background:var(--chrome); color:var(--ink);
    border:1px solid var(--chrome-edge);
    border-radius:22px;
    font-family:var(--sans); font-size:13px; font-weight:500;
    cursor:pointer; box-shadow:var(--shadow);
    opacity:.7; transition:opacity .2s;
  }
  .focus-exit:hover{opacity:1; background:var(--hover)}

  /* ===== Token-count badge (bottom-right of node) ===== */
  .node .token-badge{
    position:absolute; bottom:-9px; left:-6px;
    padding:1px 7px; border-radius:9px;
    background:var(--toolbar-bg); color:var(--toolbar-text);
    font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
    font-size:10px; font-weight:600; line-height:1.4;
    opacity:.85; pointer-events:auto; z-index:5;
    border:1.5px solid var(--card-bg, #fff);
    white-space:nowrap;
  }
  .node .token-badge:hover{opacity:1}
  .node.sel .token-badge{opacity:1}

  /* ===== Variable / placeholder form (Export as prompt) ===== */
  .var-form{position:fixed; inset:0; z-index:6000; font-family:var(--sans); animation:fadeIn .15s ease}
  .vf-backdrop{position:absolute; inset:0; background:rgba(20,15,8,.45); backdrop-filter:blur(2px)}
  .vf-card{
    position:absolute; left:50%; top:50%; transform:translate(-50%,-50%);
    background:var(--node-bg, #fff); color:var(--ink);
    border-radius:16px; box-shadow:0 30px 80px rgba(0,0,0,.35);
    padding:28px 30px; width:520px; max-width:92vw; max-height:88vh; overflow-y:auto;
    border:1px solid var(--chrome-edge);
  }
  .vf-close{
    position:absolute; top:12px; right:14px; width:32px; height:32px;
    border:none; background:transparent; color:var(--ink-soft);
    font-size:22px; line-height:1; cursor:pointer; border-radius:8px;
  }
  .vf-close:hover{background:var(--hover); color:var(--ink)}
  .vf-card h2{font-family:var(--serif); font-weight:700; font-size:22px; margin:0 0 6px}
  .vf-sub{color:var(--ink-soft); font-size:13.5px; margin:0 0 18px; line-height:1.55}
  .vf-fields{display:flex; flex-direction:column; gap:14px}
  .vf-row{display:flex; flex-direction:column; gap:6px}
  .vf-name{font-size:12px; color:var(--ink-soft); font-weight:500}
  .vf-name code{
    background:var(--paper-2); color:var(--ink);
    padding:2px 8px; border-radius:5px;
    font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace; font-size:13px;
  }
  .vf-input{
    width:100%; box-sizing:border-box;
    padding:9px 12px; font-family:var(--sans); font-size:14px;
    line-height:1.45; color:var(--ink);
    background:var(--paper); border:1.5px solid var(--line); border-radius:8px;
    resize:vertical; outline:none; min-height:38px;
  }
  .vf-input:focus{border-color:var(--accent); background:var(--node-bg, #fff)}
  /* Preferences card (showPreferences): one section per PREFS group, each a
     label / value / action row. Chips list the user's own layouts and
     templates with a delete each; the meter is storage used against the
     ~5 MB the browser allows this origin. */
  /* Each section is a <details>: the summary holds the heading and a one-line
     digest so a folded section still tells you what is inside. Which start
     open is decided by prefsSectionOpen() in app.js. */
  .pf-section{margin:10px 0 0; padding-top:8px; border-top:1px solid var(--chrome-edge)}
  .pf-section:first-child{margin-top:0; padding-top:0; border-top:none}
  .pf-section > summary{display:flex; align-items:baseline; gap:10px; cursor:pointer; list-style:none; padding:4px 0; border-radius:6px}
  .pf-section > summary::-webkit-details-marker{display:none}
  .pf-section > summary::before{content:'\25B8'; color:var(--ink-soft); font-size:11px; flex:0 0 10px}
  .pf-section[open] > summary::before{content:'\25BE'}
  .pf-section > summary:hover{background:var(--hover)}
  .pf-section > summary:focus-visible{outline:2px solid var(--accent); outline-offset:2px}
  .pf-section h3{margin:0; font-size:12px; font-weight:600; letter-spacing:.06em; text-transform:uppercase; color:var(--ink-soft); flex:0 0 auto}
  .pf-digest{font-size:12px; color:var(--ink-soft); min-width:0; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; flex:1}
  .pf-section[open] .pf-digest{display:none}
  .pf-rows{padding-top:4px}
  .pf-actions{flex-wrap:wrap}   /* four buttons; on a phone they take two rows rather than the card scrolling sideways */
  .pf-acts{display:inline-flex; gap:6px; flex-wrap:wrap}
  .pf-addprov{margin-top:6px}
  .pf-addprov-form{display:flex; flex-direction:column; gap:6px; margin-top:6px; padding:10px; border:1px dashed var(--line); border-radius:8px}
  .pf-addprov-form[hidden]{display:none}   /* display:flex above would otherwise beat the hidden attribute */
  .pf-in{font-family:inherit; font-size:13px; padding:6px 8px; border-radius:6px; border:1px solid var(--line); background:var(--node-bg,#fff); color:var(--ink); width:100%; box-sizing:border-box}
  .pf-row{display:flex; align-items:center; gap:10px; padding:5px 0; font-size:13px; min-height:28px}
  .pf-label{flex:0 0 150px; color:var(--ink-soft)}
  .pf-value{flex:1; min-width:0; color:var(--ink); overflow-wrap:anywhere; display:flex; flex-wrap:wrap; gap:4px; align-items:center}
  .pf-act{padding:4px 10px; border-radius:6px; border:1px solid var(--line); background:var(--node-bg,#fff); color:var(--ink);
    font-family:inherit; font-size:12px; cursor:pointer; white-space:nowrap}
  .pf-act:hover{background:var(--hover)}
  .pf-chip{display:inline-flex; align-items:center; gap:4px; padding:2px 4px 2px 8px; border-radius:999px; border:1px solid var(--line); font-size:12px}
  .pf-chip-x{border:none; background:transparent; color:var(--ink-soft); cursor:pointer; font-size:14px; line-height:1; padding:0 4px; border-radius:999px}
  .pf-chip-x:hover{background:var(--hover); color:var(--ink)}
  .pf-meter{height:6px; border-radius:999px; background:var(--hover); overflow:hidden; margin:2px 0 6px}
  .pf-meter-bar{height:100%; background:var(--accent); border-radius:999px}
  .pf-meter-bar.warn{background:#c62828}
  .pf-note{font-size:12px; color:var(--ink-soft); margin-top:4px}
  .pf-select{font-family:inherit; font-size:13px; padding:4px 8px; border-radius:6px; border:1px solid var(--line);
    background:var(--node-bg,#fff); color:var(--ink); max-width:100%}
  .pf-check{display:inline-flex; align-items:center; gap:2px; font-size:13px; cursor:pointer}
  .pf-check input{accent-color:var(--accent)}
  .pf-scale{display:inline-flex; align-items:center; gap:10px; flex-wrap:wrap}
  .pf-scale input[type=range]{width:140px; accent-color:var(--accent)}
  .pf-scale-pct{min-width:64px; font-variant-numeric:tabular-nums}
  @media (max-width:520px){ .pf-row{flex-wrap:wrap} .pf-label{flex-basis:100%} }
  .vf-actions{display:flex; gap:8px; margin-top:18px; align-items:center}
  .vf-actions button{
    padding:9px 16px; border-radius:8px; border:1px solid var(--line);
    background:var(--node-bg, #fff); cursor:pointer;
    font-family:inherit; font-size:13px; font-weight:500; color:var(--ink);
  }
  .vf-actions button:hover{background:var(--hover)}
  .vf-actions .vf-go{background:var(--accent); color:#fff; border-color:var(--accent)}
  .vf-actions .vf-go:hover{background:var(--accent-deep)}
  .vf-skip{margin-right:auto; color:var(--ink-soft); border-color:transparent !important; background:transparent !important}
  .vf-skip:hover{color:var(--ink); background:var(--hover) !important}
  .vf-clear{margin-right:auto; color:var(--ink-soft); border-color:transparent !important; background:transparent !important}
  .vf-clear:hover{color:var(--ink); background:var(--hover) !important}

  /* ===== Keyboard help overlay (press ?) ===== */
  .kb-help{position:fixed; inset:0; z-index:6000; font-family:var(--sans); animation:fadeIn .15s ease}
  .kb-backdrop{position:absolute; inset:0; background:rgba(20,15,8,.45); backdrop-filter:blur(2px)}
  .kb-card{
    position:absolute; left:50%; top:50%; transform:translate(-50%,-50%);
    background:var(--node-bg, #fff); color:var(--ink);
    border-radius:16px; box-shadow:0 30px 80px rgba(0,0,0,.35);
    padding:28px 32px; width:640px; max-width:92vw; max-height:88vh; overflow-y:auto;
    border:1px solid var(--chrome-edge);
  }
  .kb-close{
    position:absolute; top:12px; right:14px; width:32px; height:32px;
    border:none; background:transparent; color:var(--ink-soft);
    font-size:22px; line-height:1; cursor:pointer; border-radius:8px;
  }
  .kb-close:hover{background:var(--hover); color:var(--ink)}
  .kb-card h2{font-family:var(--serif); font-weight:700; font-size:22px; margin:0 0 16px}
  .kb-grid{display:grid; grid-template-columns:1fr 1fr; gap:18px 32px}
  .kb-card h3{
    font-size:11px; text-transform:uppercase; letter-spacing:.1em;
    color:var(--ink-soft); font-weight:700; margin:0 0 6px;
  }
  .kb-card table{border-collapse:collapse; width:100%; font-size:13.5px}
  .kb-card td{padding:5px 0; vertical-align:middle}
  .kb-card td:first-child{width:120px; padding-right:12px}
  .kb-card kbd{
    display:inline-block; padding:2px 7px;
    background:var(--paper-2); border:1px solid var(--chrome-edge);
    border-radius:5px; font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
    font-size:12px; line-height:1.4; color:var(--ink);
    box-shadow:0 1px 0 var(--chrome-edge);
  }
  .kb-foot{margin-top:18px; padding-top:14px; border-top:1px solid var(--chrome-edge);
    color:var(--ink-soft); font-size:12.5px; text-align:center}
  @media (max-width:720px){
    .kb-card{padding:22px 20px}
    .kb-grid{grid-template-columns:1fr}
  }

  /* ===== Whole-map token total (topbar) ===== */
  .token-total{
    font-size:12px; color:var(--ink-soft);
    background:var(--chrome); border:1px solid var(--chrome-edge);
    border-radius:20px; padding:6px 13px;
    box-shadow:var(--shadow); font-weight:500; white-space:nowrap;
    font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  }
  @media (max-width:720px){ .token-total{display:none !important} }

  /* ===== Multi-select ===== */
  .node.multi-sel{
    outline:2.5px dashed var(--accent); outline-offset:3px;
  }
  .node.multi-sel::after{
    content:'✓'; position:absolute; top:-9px; right:-9px;
    width:18px; height:18px; border-radius:50%;
    background:var(--accent); color:#fff;
    font-size:11px; font-weight:700; line-height:18px; text-align:center;
    box-shadow:0 1px 4px rgba(0,0,0,.3); z-index:6;
  }
  .bulk-bar{
    position:fixed; bottom:22px; left:50%; transform:translateX(-50%);
    z-index:600; display:flex; align-items:center; gap:4px;
    background:var(--toolbar-bg); color:var(--toolbar-text);
    border-radius:14px; padding:6px 8px; box-shadow:0 12px 36px rgba(0,0,0,.4);
    font-family:var(--sans); animation:fadeIn .15s ease;
  }
  .bulk-bar .bulk-count{font-size:13px; font-weight:600; padding:0 10px; white-space:nowrap}
  .bulk-bar .bulk-sep{width:1px; height:22px; background:currentColor; opacity:.2; margin:0 3px}
  .bulk-bar button{
    border:none; background:transparent; color:var(--toolbar-text);
    cursor:pointer; font-family:inherit; font-size:13px; font-weight:500;
    padding:7px 11px; border-radius:9px; white-space:nowrap;
  }
  .bulk-bar button:hover{background:color-mix(in srgb, var(--toolbar-text) 16%, transparent)}
  .bulk-bar .bulk-danger:hover{background:color-mix(in srgb, #e0473a 65%, transparent); color:#fff}
  .bulk-bar .bulk-cancel{font-size:14px; opacity:.75}

  /* ===== Cross-link mode ===== */
  .node.link-source{
    outline:2.5px solid var(--accent); outline-offset:3px;
    animation:linkpulse 1.1s ease-in-out infinite;
  }
  @keyframes linkpulse{50%{outline-color:color-mix(in srgb,var(--accent) 40%,transparent)}}

  /* ===== Print - take the map to a meeting ===== */
  @media print{
    /* The app is a fixed-viewport SPA (html,body{height:100%;overflow:hidden}) so the
       canvas never page-scrolls on screen - but that same constraint silently clips ANY
       print output to a single page's worth of content, however much there actually is.
       Print has no "viewport" in that sense, so drop the constraint entirely here. */
    html, body{ height:auto !important; overflow:visible !important; }
    .topbar, .side, .overview, .hint, .save-pill, .token-total, .statusbar,
    .nodebar, .search-wrap, .user-pill, .bulk-bar, .focus-exit,
    .picker, .tpl-pop, .export-pop, .theme-panel, #outlinePane, #deckBar, #tabStrip{ display:none !important; }
    .app{ grid-template-columns:1fr !important; }
    .stage{ width:100% !important; height:auto !important; overflow:visible !important; }
    body, .app, .stage{ background:#fff !important; }
    .node{ box-shadow:none !important; -webkit-print-color-adjust:exact; print-color-adjust:exact; }
    .node .token-badge, .node .notes-mark{ display:none !important; }
    @page{ margin:1cm; }
  }

  /* ===== Task state ===== */
  .node.has-image{flex-direction:column; align-items:stretch; padding-top:8px}
  /* Image nodes size themselves to the picture. Two changes from the
     original rule, both deliberate:
       - object-fit was `cover`, which CROPS the image to fill the box; an
         attached picture should be shown in full, so `contain` + auto
         dimensions let it keep its own aspect ratio.
       - .node caps at 240px, which squeezed every picture regardless of its
         real size. Images are down-scaled to 360px wide on attach
         (readImageFile), so 400px here lets one display at natural size
         including the node's 15px horizontal padding, while still bounding
         how large a card can get. */
  .node .node-image{
    max-width:100%; max-height:280px; width:auto; height:auto;
    border-radius:8px; object-fit:contain;
    margin-bottom:6px; cursor:zoom-in; display:block;
  }
  .node.has-image{ max-width:400px; }
  /* Marker badge - sits beside the task checkbox and uses the same
     flex-shrink:0 / vertical-align treatment so the two line up when a node
     has both. font-size is nudged up because emoji render smaller than
     surrounding text at the same size. */
  .node .node-marker{
    flex-shrink:0; margin-right:6px; font-size:17px; line-height:1;
    cursor:pointer; user-select:none; vertical-align:middle;
  }
  .node .node-marker:hover{ transform:scale(1.15); }
  .picker.marker-picker{
    display:grid; grid-template-columns:repeat(4, 1fr); gap:2px; padding:6px;
  }
  .picker.marker-picker button{
    font-size:19px; line-height:1; padding:6px; border-radius:8px;
    background:none; border:1.5px solid transparent; cursor:pointer;
  }
  .picker.marker-picker button:hover{ background:var(--hover); }
  .picker.marker-picker button.on{ border-color:var(--accent); background:var(--paper-2); }
  .picker.marker-picker button.mk-none{ grid-column:1 / -1; font-size:13px; color:var(--ink-soft); }
  .picker.marker-picker button.mk-custom{ grid-column:1 / -1; font-size:13px; color:var(--ink-soft); border:1.5px dashed var(--line-2); }
  .picker.marker-picker .mk-custom-row{ grid-column:1 / -1; display:flex; align-items:center; gap:6px; }
  .picker.marker-picker .mk-custom-row input{
    flex:1; min-width:0; font-size:16px; padding:5px 8px; border-radius:8px;
    border:1.5px solid var(--line-2); background:var(--paper-1); color:var(--ink); font-family:inherit;
  }
  .picker.marker-picker .mk-custom-row input:focus{ outline:none; border-color:var(--accent); }
  .picker.marker-picker .mk-custom-row button.mk-apply{ font-size:13px; padding:5px 10px; }
  .picker.marker-picker .mk-custom-row button.mk-apply:disabled{ opacity:.45; cursor:default; }
  .node .task-check{
    flex-shrink:0; width:18px; height:18px; margin-right:7px;
    border:2px solid var(--line-2); border-radius:5px;
    display:inline-flex; align-items:center; justify-content:center;
    font-size:12px; font-weight:700; cursor:pointer; vertical-align:middle;
    background:var(--card-bg);
  }
  .node .task-check.task-doing{border-color:#c98a1a; color:#c98a1a}
  .node .task-check.task-done{background:#4a9d5b; border-color:#4a9d5b; color:#fff}
  .node.task-done .node-text{text-decoration:line-through; opacity:.62}
  .node .task-progress{
    position:absolute; top:-9px; left:-6px;
    padding:1px 7px; border-radius:9px;
    background:var(--toolbar-bg); color:var(--toolbar-text);
    font-size:10px; font-weight:700; line-height:1.4;
    border:1.5px solid var(--card-bg); white-space:nowrap; z-index:5; opacity:.9;
    font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  }
  .node .task-progress.complete{background:#4a9d5b; color:#fff}

  /* ===== Reference / citation nodes ===== */
  .node.ref-node{
    border-left:4px solid var(--accent);
    font-style:italic;
  }
  .node .ref-mark{
    position:absolute; top:-9px; left:-9px;
    width:22px; height:22px; border-radius:50%;
    background:var(--card-bg); border:1.5px solid var(--accent);
    display:flex; align-items:center; justify-content:center;
    font-size:11px; cursor:pointer; z-index:6;
    box-shadow:0 1px 3px rgba(0,0,0,.18);
  }
  .node .ref-mark:hover{transform:scale(1.1)}

  /* ===== Global search results panel ===== */
  .global-results{
    position:fixed; z-index:1200; display:none;
    width:380px; max-width:92vw; max-height:70vh; overflow-y:auto;
    background:var(--chrome); border:1px solid var(--chrome-edge);
    border-radius:14px; box-shadow:var(--shadow-lg);
    font-family:var(--sans); padding:6px;
  }
  .global-results .gs-status{padding:14px; color:var(--ink-soft); font-size:13px; text-align:center}
  .global-results .gs-head{
    padding:8px 10px 6px; font-size:11px; text-transform:uppercase;
    letter-spacing:.08em; color:var(--ink-soft); font-weight:700;
  }
  .global-results .gs-group{margin-bottom:4px}
  .global-results .gs-map{
    padding:6px 10px 3px; font-size:12px; font-weight:700; color:var(--accent);
  }
  .global-results .gs-cur{color:var(--ink-soft); font-weight:400; text-transform:none}
  .global-results .gs-item{
    display:block; width:100%; text-align:left;
    padding:7px 10px; border:none; background:transparent; cursor:pointer;
    font-family:inherit; font-size:13px; color:var(--ink); border-radius:7px;
    line-height:1.4;
  }
  .global-results .gs-item:hover{background:var(--hover)}
  .global-results .gs-item mark{background:color-mix(in srgb, var(--accent) 40%, transparent); color:inherit; border-radius:2px; padding:0 1px}
  .global-results .gs-more{padding:3px 10px 8px; font-size:11.5px; color:var(--ink-soft)}
  /* 'all maps' toggle active state */
  .search-toggle.on{color:var(--accent); background:var(--hover)}

  /* ===== Sidebar duplicate button ===== */

  /* ===== Breadcrumb (floating pill, anchored under the topbar's left edge) =====
     Hidden by default; expands (fades in) while the mouse is over the overview
     in the status bar - the .shown class is toggled from JS. */
  .breadcrumb{
    position:fixed; top:56px; left:14px; transform:none;
    display:flex; align-items:center; gap:1px; z-index:90;
    background:var(--chrome); border:1px solid var(--chrome-edge);
    border-radius:10px; box-shadow:var(--shadow); padding:3px 6px;
    max-width:min(70vw, 720px); overflow:hidden; font-family:var(--sans);
    opacity:0; pointer-events:none; transform:translateY(-4px);
    transition:opacity .16s ease, transform .16s ease;
  }
  .breadcrumb.shown{opacity:1; pointer-events:auto; transform:translateY(0)}
  .breadcrumb .bc-crumb{
    border:none; background:transparent; cursor:pointer;
    font-family:inherit; font-size:12px; color:var(--ink-soft);
    padding:3px 7px; border-radius:6px; white-space:nowrap;
    max-width:170px; overflow:hidden; text-overflow:ellipsis;
  }
  .breadcrumb .bc-crumb:hover{background:var(--hover); color:var(--ink)}
  .breadcrumb .bc-crumb.current{color:var(--ink); font-weight:600}
  .breadcrumb .bc-sep{color:var(--ink-soft); font-size:12px; opacity:.6; flex:none}

  /* ===== Minimap (inside the overview card, bottom-right) ===== */
  .minimap{
    position:relative; z-index:29;
    width:104px; height:50px;
    background:color-mix(in srgb, var(--chrome) 92%, transparent);
    border:1px solid var(--chrome-edge); border-radius:10px;
    box-shadow:var(--shadow); overflow:hidden; cursor:crosshair;
  }
  .minimap svg{display:block;width:100%;height:100%}
  .minimap #mmView{ stroke:var(--accent); stroke-width:1.5; fill:color-mix(in srgb, var(--accent) 12%, transparent); }
  .minimap .mm-sel{ stroke:var(--accent); stroke-width:1.5; }
  @media (max-width:760px){ .minimap{display:none} .breadcrumb{max-width:88vw} }

  /* ===== Read-only shared view ===== */
  .shared-banner{
    position:fixed; top:0; left:0; right:0; z-index:300;
    display:flex; align-items:center; gap:12px;
    padding:9px 16px; font-family:var(--sans); font-size:13px;
    background:var(--accent); color:#fff;
    box-shadow:0 2px 12px rgba(0,0,0,.18);
  }
  .shared-banner .sb-eye{font-size:15px}
  .shared-banner .sb-text{opacity:.96}
  .shared-banner .sb-text b{font-weight:700}
  .shared-banner .sb-copy{
    margin-left:auto; border:1px solid rgba(255,255,255,.6); background:rgba(255,255,255,.16);
    color:#fff; font-family:inherit; font-size:12.5px; font-weight:600;
    padding:5px 12px; border-radius:8px; cursor:pointer;
  }
  .shared-banner .sb-copy:hover{background:rgba(255,255,255,.28)}
  .shared-banner .sb-brand{
    color:#fff; opacity:.85; text-decoration:none; font-weight:700; letter-spacing:.01em;
  }
  .shared-banner .sb-brand:hover{opacity:1; text-decoration:underline}

  /* In shared view: hide all editing chrome, keep viewing aids (zoom, minimap) */
  body.shared-view .side,
  body.shared-view #newMap,
  body.shared-view #menuExport,
  body.shared-view #searchBtn,
  body.shared-view #varsBtn,
  body.shared-view #focusBtn,
  body.shared-view #collapseAll,
  body.shared-view #mdToggle,
  body.shared-view #undo,
  body.shared-view #redo,
  body.shared-view #layout,
  body.shared-view #donateBtn,
  body.shared-view .hint,
  body.shared-view .save-pill,
  body.shared-view .menu-toggle,
  body.shared-view #addChild,
  body.shared-view #toggleSide{ display:none !important; }
  /* Sidebar is hidden in shared view - collapse the grid to one column so the
     stage fills the full width (otherwise it auto-places into the 0-width track
     and the canvas clips to nothing). */
  body.shared-view .app{ grid-template-columns:1fr; padding-top:var(--shared-banner-h, 42px); }
  body.shared-view .topbar{ grid-column:1; grid-row:1; }
  body.shared-view .stage{ grid-column:1; grid-row:3; }
  body.shared-view .statusbar{ grid-column:1; grid-row:4; }
  body.shared-view .breadcrumb{ top:97px; left:14px; }
  body.shared-view #mapTitle{ pointer-events:none; max-width:none; }
  body.shared-view .node{ cursor:default; }
  /* Read-only: no node editing affordances (collapse toggle + notes stay). */
  body.shared-view .handle.h-child,
  body.shared-view .handle.h-sibling,
  body.shared-view .resize-grip{ display:none !important; }
  @media (max-width:760px){
    .shared-banner{ font-size:12px; gap:8px; padding:8px 10px; }
    .shared-banner .sb-text{ flex:1; min-width:0; }
  }

  /* ===== Display-size (UI scale) control in theme panel ===== */
  .theme-panel .tp-hint{ font-weight:400; text-transform:none; letter-spacing:0; color:var(--ink-soft); font-size:10.5px; margin-left:6px; }
  .theme-panel .tp-scale{ display:flex; gap:6px; }
  .theme-panel .scale-opt{
    flex:1; padding:5px 0; border:1px solid var(--chrome-edge); border-radius:8px;
    background:var(--node-bg); color:var(--ink); cursor:pointer;
    font-family:var(--sans); font-size:12.5px; font-weight:600;
  }
  .theme-panel .scale-opt:hover{ background:var(--hover); }
  .theme-panel .scale-opt.active{ background:var(--accent); color:#fff; border-color:var(--accent); }

  /* ===== Version history panel ===== */
  .hist-panel{ position:fixed; top:64px; right:18px; width:320px; max-height:70vh; z-index:60;
    background:var(--node-bg); border:1px solid var(--chrome-edge); border-radius:14px;
    box-shadow:0 18px 50px rgba(0,0,0,.28); display:flex; flex-direction:column; overflow:hidden; font-family:var(--sans); }
  .hist-head{ display:flex; align-items:center; justify-content:space-between; padding:12px 14px; border-bottom:1px solid var(--chrome-edge); }
  .hist-x{ border:none; background:none; font-size:20px; cursor:pointer; color:var(--ink-soft); line-height:1; }
  .hist-list{ overflow-y:auto; padding:6px; }
  .hist-status{ padding:18px 14px; color:var(--ink-soft); font-size:13px; }
  .hist-sub{ color:var(--ink-soft); font-size:12px; }
  .hist-row{ display:flex; align-items:center; justify-content:space-between; gap:8px; padding:9px 10px; border-radius:9px; }
  .hist-row:hover{ background:var(--hover); }
  .hist-row.active{ background:var(--hover); outline:2px solid var(--accent); }
  .hist-when b{ display:block; font-size:13px; }
  .hist-when i{ display:block; font-size:11px; color:var(--ink-soft); font-style:normal; }
  .hist-actions{ display:flex; gap:6px; }
  .hist-actions button{ border:1px solid var(--chrome-edge); background:var(--node-bg); color:var(--ink);
    border-radius:7px; padding:5px 9px; font-size:12px; cursor:pointer; }
  .hist-actions button:hover{ background:var(--accent); color:#fff; border-color:var(--accent); }
  .hist-actions button.disabled{ opacity:.4; pointer-events:none; }
  .hist-banner{ position:fixed; top:14px; left:50%; transform:translateX(-50%); z-index:61;
    background:#2d2d2d; color:#fff; border-radius:999px; padding:8px 10px 8px 16px; display:flex; align-items:center; gap:10px;
    font-family:var(--sans); font-size:13px; box-shadow:0 10px 30px rgba(0,0,0,.3); }
  .hist-banner button{ border:none; border-radius:999px; padding:6px 12px; font-size:12px; cursor:pointer; font-weight:600; }
  .hb-restore{ background:var(--accent); color:#fff; }
  .hb-cancel{ background:rgba(255,255,255,.15); color:#fff; }

  /* ===== Build-prompt panel ===== */
  .bp-panel{ position:fixed; top:64px; right:18px; width:420px; max-width:calc(100vw - 36px); max-height:80vh; z-index:60;
    resize:both; min-width:300px; min-height:220px;
    background:var(--node-bg); border:1px solid var(--chrome-edge); border-radius:14px;
    box-shadow:0 18px 50px rgba(0,0,0,.28); display:flex; flex-direction:column; overflow:hidden; font-family:var(--sans); }
  .bp-head{ display:flex; align-items:center; justify-content:space-between; padding:12px 14px; border-bottom:1px solid var(--chrome-edge);
    cursor:move; user-select:none; }
  body.bp-dragging{ user-select:none; }
  body.bp-dragging .bp-panel{ box-shadow:0 24px 60px rgba(0,0,0,.34); }
  .bp-head b{ font-size:14px; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
  .bp-x{ border:none; background:none; font-size:20px; cursor:pointer; color:var(--ink-soft); }
  /* flex-shrink:0 - opening "Run with API" must not resize this box. If it
     shrank, its content would overflow, a scrollbar would appear inside it and
     the text would re-wrap narrower. The run section is the one that scrolls. */
  .bp-text{ margin:12px 14px 0; min-height:160px; max-height:38vh; resize:vertical; flex-shrink:0; border:1px solid var(--chrome-edge);
    border-radius:9px; padding:10px; font-family:var(--mono,ui-monospace,monospace); font-size:12.5px; line-height:1.5;
    background:var(--bg); color:var(--ink); }
  .bp-meta{ padding:6px 14px; color:var(--ink-soft); font-size:11.5px; }
  .bp-row{ display:flex; gap:8px; padding:0 14px 12px; }
  .bp-row button, .bp-run button{ border:1px solid var(--chrome-edge); background:var(--node-bg); color:var(--ink);
    border-radius:8px; padding:8px 12px; font-size:13px; cursor:pointer; font-family:var(--sans); }
  .bp-row button.primary, .bp-run button.primary{ background:var(--accent); color:#fff; border-color:var(--accent); }
  .bp-run{ border-top:1px solid var(--chrome-edge); padding:12px 14px; overflow-y:auto; min-height:0; }
  .bp-run-row{ display:flex; gap:8px; margin-bottom:8px; }
  .bp-run select, .bp-run input{ flex:1; border:1px solid var(--chrome-edge); border-radius:8px; padding:7px 9px;
    background:var(--bg); color:var(--ink); font-family:var(--sans); font-size:12.5px; min-width:0; }
  .bp-warn{ color:var(--ink-soft); font-size:11px; margin:4px 0 10px; line-height:1.4; }
  .bp-result{ margin-top:10px; font-size:12.5px; }
  .bp-answer{ white-space:pre-wrap; background:var(--bg); border:1px solid var(--chrome-edge); border-radius:9px;
    padding:10px; max-height:30vh; overflow-y:auto; line-height:1.5; }
  .bp-answer-acts{ display:flex; gap:8px; margin-top:8px; }
  .vf-doi-lookup{ display:flex; gap:8px; margin:0 0 12px; }
  .vf-doi-in{ flex:1; border:1px solid var(--chrome-edge); border-radius:8px; padding:8px 10px; background:var(--bg); color:var(--ink); font-family:var(--sans); font-size:13px; }
  .vf-doi-go{ border:1px solid var(--accent); background:var(--accent); color:#fff; border-radius:8px; padding:8px 14px; cursor:pointer; font-weight:600; }
  .vf-doi-go:disabled{ opacity:.6; cursor:default; }

  /* ===== Presentation mode ===== */
  body.presenting .node{ opacity:.28; transition:opacity .25s; }
  body.presenting .node.pres-current{ opacity:1; outline:3px solid var(--accent); outline-offset:3px; box-shadow:0 10px 40px rgba(0,0,0,.3); }
  body.presenting .handle, body.presenting .resize-grip, body.presenting #nodebar{ display:none !important; }
  .pres-bar{ position:fixed; bottom:24px; left:50%; transform:translateX(-50%); z-index:62;
    background:#23201b; color:#fff; border-radius:999px; padding:8px 12px; display:flex; align-items:center; gap:12px;
    font-family:var(--sans); box-shadow:0 12px 40px rgba(0,0,0,.4); max-width:90vw; }
  .pres-bar button{ border:none; background:rgba(255,255,255,.12); color:#fff; width:34px; height:34px; border-radius:50%;
    font-size:14px; cursor:pointer; flex:none; }
  .pres-bar button:hover:not(:disabled){ background:var(--accent); }
  .pres-bar button:disabled{ opacity:.35; cursor:default; }
  .pres-exit{ background:rgba(255,80,60,.25) !important; }
  .pres-count{ font-size:12px; opacity:.8; flex:none; }
  .pres-title{ font-size:14px; font-weight:600; max-width:46vw; overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }

  /* Version diff panel */
  .diff-panel{ position:fixed; right:18px; top:64px; width:360px; max-height:70vh; overflow:auto;
    background:var(--paper); border:1px solid var(--line); border-radius:14px; box-shadow:var(--shadow-lg);
    z-index:120; padding:6px 0; font-size:13px; }
  .diff-head{ display:flex; align-items:center; justify-content:space-between; padding:8px 14px; border-bottom:1px solid var(--line); position:sticky; top:0; background:var(--paper); }
  .diff-head b{ color:var(--ink); }
  .diff-x{ border:0; background:transparent; font-size:18px; cursor:pointer; color:var(--ink-soft); line-height:1; }
  .diff-sec{ padding:6px 0; }
  .diff-h{ font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:.04em; padding:4px 14px; }
  .diff-h.add{ color:#1a7f37; } .diff-h.del{ color:#cf222e; } .diff-h.chg{ color:#9a6700; }
  .diff-row{ padding:4px 14px; border-left:3px solid transparent; color:var(--ink); word-break:break-word; }
  .diff-row.add{ border-left-color:#1a7f37; background:rgba(26,127,55,.06); }
  .diff-row.del{ border-left-color:#cf222e; background:rgba(207,34,46,.06); text-decoration:line-through; color:var(--ink-soft); }
  .diff-row.chg{ border-left-color:#9a6700; background:rgba(154,103,0,.06); }
  .diff-row .d-from{ color:var(--ink-soft); text-decoration:line-through; }
  .diff-row .d-arrow{ margin:0 6px; color:var(--ink-soft); }
  .diff-empty{ padding:16px 14px; color:var(--ink-soft); }

  /* OAuth ("Sign in with GitHub") button on the login overlay */
  .login-oauth{ margin:2px 0 4px; }
  .oauth-btn{ display:flex; align-items:center; justify-content:center; gap:9px; width:100%; padding:11px 14px;
    border-radius:11px; border:1px solid var(--chrome-edge); background:var(--ink); color:var(--paper);
    font-size:14px; font-weight:600; cursor:pointer; transition:opacity .15s; }
  .oauth-btn:hover{ opacity:.9; }
  .oauth-btn svg{ width:18px; height:18px; fill:currentColor; }
  .oauth-or{ display:flex; align-items:center; gap:10px; margin:15px 2px 2px; color:var(--ink-soft); font-size:12px; }
  .oauth-or::before, .oauth-or::after{ content:''; flex:1; height:1px; background:var(--line); }

/* Pinned maps: small badge before the title in the sidebar list. */
.map-item.pinned .nm::before{ content:'\1F4CC'; margin-right:6px; font-size:.85em; opacity:.9; }

/* Live collaboration: remote cursors + presence pill. */
#collabCursors{ position:fixed; inset:0; pointer-events:none; z-index:60; overflow:hidden; }
.collab-cursor{ position:absolute; top:0; left:0; will-change:transform; transition:transform .08s linear; }
.collab-cursor svg{ display:block; filter:drop-shadow(0 1px 1px rgba(0,0,0,.3)); }
.collab-cursor b{ position:absolute; left:15px; top:13px; font-size:11px; font-weight:600; color:#fff; padding:1px 6px; border-radius:8px; white-space:nowrap; }
#collabPill{ position:fixed; bottom:18px; left:18px; z-index:70; display:flex; align-items:center; gap:8px;
  background:var(--chrome); border:1px solid var(--chrome-edge); border-radius:999px; padding:5px 8px 5px 12px;
  box-shadow:var(--shadow); font-size:12px; font-weight:500; }
#collabPill .cp-dots{ display:flex; }
#collabPill .cp-dot{ width:13px; height:13px; border-radius:50%; border:2px solid var(--chrome); margin-left:-5px; }
#collabPill .cp-dot:first-child{ margin-left:0; }
#collabPill .cp-txt{ color:var(--ink-soft); }
#collabPill button{ border:none; background:transparent; cursor:pointer; font-size:12px; opacity:.7; padding:2px 5px; border-radius:6px; color:var(--ink-soft); }
#collabPill button:hover{ opacity:1; background:var(--hover, rgba(127,127,127,.18)); }
#collabPill .cp-save{ opacity:1; font-weight:600; color:var(--accent); padding:3px 9px; border:1px solid var(--chrome-edge); border-radius:999px; }
#collabPill .cp-save:hover{ background:var(--accent); color:#fff; border-color:var(--accent); }

/* Export menu: small uppercase section labels grouping the items. */
.ex-grp{ font-size:10px; font-weight:700; text-transform:uppercase; letter-spacing:.6px;
  color:var(--ink-soft); opacity:.65; padding:10px 14px 3px; user-select:none; }
.export-pop > .ex-grp:first-child{ padding-top:6px; }

/* Shared-with-me section in the sidebar. */
.map-group-label{ font-size:10px; font-weight:700; text-transform:uppercase; letter-spacing:.6px; color:var(--ink-soft); opacity:.6; padding:12px 12px 4px; user-select:none; }
.map-item .shared-badge{ font-size:11px; opacity:.7; flex:0 0 auto; margin-right:2px; }

/* Cloud-edit keeps the editing toolbar visible, so push it clear of the shared banner. */
/* Cloud-edit shows the sidebar AND toolbar, so shift the whole app below the fixed
   shared banner (measured into --shared-banner-h so it adapts when the banner wraps). */
body.cloud-edit .app{ padding-top:var(--shared-banner-h, 44px); }

/* ---- Manage-access modal (identity ACLs) ---- */
.access-modal{ position:fixed; inset:0; background:rgba(0,0,0,.45); display:grid; place-items:center; z-index:600; }
.access-modal .am-card{ width:min(440px,92vw); max-height:86vh; overflow:auto; background:var(--paper); color:var(--ink);
  border:1px solid var(--line); border-radius:14px; box-shadow:var(--shadow-lg); padding:16px 18px; }
.access-modal .am-head{ display:flex; align-items:center; justify-content:space-between; margin-bottom:6px; font-size:16px; font-weight:700; }
.access-modal .am-x{ background:none; border:none; color:var(--ink-soft); font-size:22px; line-height:1; cursor:pointer; }
.access-modal .am-x:hover{ color:var(--ink); }
.access-modal .am-sec{ margin-top:14px; }
.access-modal .am-lbl{ font-size:12px; text-transform:uppercase; letter-spacing:.04em; color:var(--ink-soft); margin-bottom:8px; }
.access-modal .am-link label{ display:block; padding:5px 0; font-size:14px; cursor:pointer; }
.access-modal .am-link input{ margin-right:8px; accent-color:var(--accent); }
.access-modal .am-auth{ display:flex; align-items:center; gap:8px; margin-top:10px; font-size:13.5px; cursor:pointer; }
.access-modal .am-auth input{ margin:0; accent-color:var(--accent); }
.access-modal .am-auth input:disabled{ opacity:.4; }
.access-modal .am-list{ display:flex; flex-direction:column; gap:6px; margin-bottom:10px; }
.access-modal .am-row{ display:flex; align-items:center; gap:10px; padding:7px 10px; background:var(--paper-2); border:1px solid var(--line); border-radius:8px; }
.access-modal .am-who{ flex:1; font-size:14px; }
.access-modal .am-role{ font-size:12px; color:var(--ink-soft); }
.access-modal .am-rm{ background:none; border:1px solid var(--line-2); color:var(--ink-soft); border-radius:6px; padding:3px 9px; font-size:12px; cursor:pointer; }
.access-modal .am-rm:hover{ border-color:var(--accent); color:var(--accent); }
.access-modal .am-empty{ font-size:13px; color:var(--ink-soft); padding:6px 2px; }
.access-modal .am-add{ display:flex; gap:8px; }
.access-modal .am-user{ flex:1; background:var(--paper-2); border:1px solid var(--line); color:var(--ink); border-radius:8px; padding:8px 10px; font-size:14px; }
.access-modal .am-user::placeholder{ color:var(--ink-soft); }
.access-modal .am-user:focus{ outline:none; border-color:var(--accent); }
.access-modal .am-newrole{ background:var(--paper-2); border:1px solid var(--line); color:var(--ink); border-radius:8px; padding:8px; }
.access-modal .am-addbtn{ background:var(--accent); border:none; color:#fff; border-radius:8px; padding:8px 14px; font-weight:600; cursor:pointer; }
.access-modal .am-addbtn:hover{ background:var(--accent-deep); }
.access-modal .am-vis{ display:flex; flex-direction:column; gap:5px; }
.access-modal .am-visrow{ display:flex; align-items:center; justify-content:space-between; padding:5px 10px; background:var(--paper-2); border:1px solid var(--line); border-radius:8px; font-size:13px; }
.access-modal .am-vtime{ color:var(--ink-soft); font-size:12px; }
.access-modal .am-foot{ margin-top:14px; font-size:12px; color:var(--ink-soft); }

/* Contextual note on the login overlay when access requires sign-in (e.g. a shared map) */
.login-share-note{ margin:0 0 14px; padding:10px 13px; border-radius:10px; font-size:13.5px; line-height:1.4;
  background:color-mix(in srgb, var(--accent) 14%, transparent); border:1px solid color-mix(in srgb, var(--accent) 40%, transparent); color:var(--ink); }

/* Shared-map indicator: a compact themed pill (replaces the full-width banner). */
.user-pill.shared-pill{ background:var(--accent); color:#fff; border-color:transparent; font-weight:600; padding:3px 12px; }
.user-pill.shared-pill img, .user-pill.shared-pill button{ display:none !important; }
.user-pill.shared-pill span{ display:inline-block !important; padding:0; }
/* Pill-mode has no banner, so reclaim the space the banner used to reserve. */
body.no-banner.cloud-edit .app{ padding-top:0; }
body.no-banner.shared-view .stage{ top:0; }

/* Themed scrollbars - desktop only (mobile keeps native overlay scrollbars) */
@media (min-width:721px){
  *::-webkit-scrollbar{width:12px;height:12px}
  *::-webkit-scrollbar-track{background:transparent}
  *::-webkit-scrollbar-thumb{background:var(--line-2,var(--line));border-radius:10px;border:3px solid transparent;background-clip:padding-box}
  *::-webkit-scrollbar-thumb:hover{background:var(--ink-soft)}
  *::-webkit-scrollbar-corner{background:transparent}
  html{scrollbar-color:var(--line-2,var(--line)) transparent;scrollbar-width:thin}
}

/* ===== PDF export (markdown preview -> browser print -> Save as PDF) =====
   #mdPrintRoot is populated on demand by mdDownloadPdf() and is otherwise empty/hidden.
   Forces light, ink-friendly colors regardless of the app's active theme. */
#mdPrintRoot{display:none}
@media print{
  body.md-printing > *:not(#mdPrintRoot){display:none !important}
  body.md-printing #mdPrintRoot{
    display:block !important;position:static !important;padding:0 32px;
    color:#1a1a1a;background:#fff;
    font:14px/1.6 -apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;
  }
  /* Browsers drop background colors/images when printing unless told otherwise - this is
     what was silently stripping the code-block shading (and would strip any other
     background color here too, e.g. a table header tint) even though it renders fine
     on screen in the live preview. Applies to every descendant, not just #mdPrintRoot
     itself, since print-color-adjust doesn't reliably cascade in all engines. */
  #mdPrintRoot, #mdPrintRoot *{ -webkit-print-color-adjust:exact; print-color-adjust:exact; }
  #mdPrintRoot h1{font-size:1.9em;margin:0 0 .4em;line-height:1.25;color:#111;border-bottom:1px solid #ccc;padding-bottom:.2em}
  #mdPrintRoot h1,#mdPrintRoot h2,#mdPrintRoot h3{page-break-after:avoid}
  #mdPrintRoot h2,#mdPrintRoot h3{margin:.9em 0 .3em;line-height:1.25;color:#111}
  #mdPrintRoot h2{font-size:1.35em;border-bottom:1px solid #ccc;padding-bottom:.2em}
  #mdPrintRoot h3{font-size:1.1em}
  #mdPrintRoot p,#mdPrintRoot ul,#mdPrintRoot ol,#mdPrintRoot blockquote{margin:.5em 0}
  #mdPrintRoot pre.mp-code{background:#f2f2f2;padding:10px 12px;border-radius:6px;overflow:auto;font-size:12px;page-break-inside:avoid}
  #mdPrintRoot code{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace}
  #mdPrintRoot table{border-collapse:collapse;font-size:.95em;page-break-inside:avoid;margin:.5em 0}
  #mdPrintRoot th,#mdPrintRoot td{border:1px solid #ccc;padding:5px 9px}
  #mdPrintRoot th{background:#eef0f3;font-weight:700;text-align:left}
  #mdPrintRoot blockquote{border-left:3px solid #ccc;margin-left:0;padding:.2em 0 .2em 12px;color:#555}
  #mdPrintRoot img{max-width:100%}
  #mdPrintRoot hr{border:0;border-top:1px solid #ccc;margin:1em 0}
  #mdPrintRoot a{color:#2a5db0;text-decoration:underline}
  #mdPrintRoot math{font-size:1.04em;color:#1a1a1a}
  #mdPrintRoot math[display="block"]{display:block;margin:.6em auto;text-align:center;page-break-inside:avoid}
}

/* ===== Floating-shell interface layouts (Classic / Side-toolbar) =====
   body.ui-classic and body.ui-rail both drop the status bar and float the
   chrome over the canvas: minimap card + vertical zoombar bottom-right, hint
   bottom-left, breadcrumb top-centre, collapsed sidebar vanishes (no rail).
   Classic keeps the upstream toolbar as one floating strip inside .stage;
   Side-toolbar docks the same toolbar as a vertical icon rail left of the
   canvas with the title, save pill and minimap floating over it. The same
   DOM elements are reparented by applyUiLayout() - nothing is hidden or
   cloned, only restyled and repositioned. */
body.ui-classic .app, body.ui-rail .app{grid-template-rows:minmax(0,1fr)}
body.ui-classic .side, body.ui-rail .side, body.ui-zen .side{grid-column:1;grid-row:1;width:268px}
body.ui-classic .side.collapsed, body.ui-rail .side.collapsed, body.ui-zen .side.collapsed{width:0 !important}
body.ui-classic .side-rail, body.ui-rail .side-rail, body.ui-zen .side-rail,
body.ui-classic .side-resize, body.ui-rail .side-resize, body.ui-zen .side-resize{display:none}
body.ui-classic .statusbar, body.ui-rail .statusbar, body.ui-zen .statusbar{display:none}
/* Floating bottom-right: the minimap as its own card (right:72) and the
   vertical zoom bar beside it (right:18) - the upstream zoombar. The zoom
   row is reparented out of the overview card by applyUiLayout(); the
   overview here is just the minimap chip. */
body.ui-classic .overview, body.ui-rail .overview, body.ui-zen .overview{
  position:absolute;bottom:18px;right:72px;z-index:29;
  flex-direction:column;align-items:stretch;gap:0;padding:0;
  background:none;border:none;box-shadow:none;
}
body.ui-classic .overview .minimap, body.ui-rail .overview .minimap, body.ui-zen .overview .minimap{width:168px;height:120px}
body.ui-classic .zoom-row, body.ui-rail .zoom-row, body.ui-zen .zoom-row{
  position:absolute;bottom:18px;right:18px;z-index:30;
  flex-direction:column;gap:2px;padding:4px;
  background:var(--chrome);border:1px solid var(--chrome-edge);border-radius:12px;
  box-shadow:var(--shadow);
}
body.ui-classic .zoom-row button, body.ui-rail .zoom-row button, body.ui-zen .zoom-row button{width:36px;height:34px;border-radius:8px;font-size:17px}
body.ui-classic #zoomSlider, body.ui-rail #zoomSlider, body.ui-zen #zoomSlider{display:none}   /* no slider here; the % label handles custom zoom */
body.ui-classic .zoom-row #zoomIn, body.ui-rail .zoom-row #zoomIn, body.ui-zen .zoom-row #zoomIn{order:1}  /* upstream order: ＋ 100% － ⊡ */
body.ui-classic .zoom-row #zoomVal, body.ui-rail .zoom-row #zoomVal, body.ui-zen .zoom-row #zoomVal{order:2}
body.ui-classic .zoom-row #zoomOut, body.ui-rail .zoom-row #zoomOut, body.ui-zen .zoom-row #zoomOut{order:3}
body.ui-classic .zoom-row #zoomFit, body.ui-rail .zoom-row #zoomFit, body.ui-zen .zoom-row #zoomFit{order:4}
body.ui-classic .overview-toggle, body.ui-rail .overview-toggle, body.ui-zen .overview-toggle{display:none}
/* Floating hint pill, bottom-left (upstream position). */
body.ui-classic .hint, body.ui-rail .hint, body.ui-zen .hint{
  position:absolute;bottom:18px;left:18px;z-index:20;
  background:var(--chrome);border:1px solid var(--chrome-edge);border-radius:11px;
  padding:9px 13px;box-shadow:var(--shadow);font-size:12px;color:var(--ink-soft);
  max-width:330px;line-height:1.55;
}
body.ui-classic .hint .hint-text, body.ui-rail .hint .hint-text, body.ui-zen .hint .hint-text{white-space:normal;overflow:visible}
/* Breadcrumb: top-centre. */
body.ui-classic .breadcrumb, body.ui-rail .breadcrumb, body.ui-zen .breadcrumb{top:60px;left:50%;transform:translateX(-50%) translateY(-4px)}
body.ui-classic .breadcrumb.shown, body.ui-rail .breadcrumb.shown, body.ui-zen .breadcrumb.shown{transform:translateX(-50%) translateY(0)}
body.ui-classic.focus-mode .overview, body.ui-rail.focus-mode .overview, body.ui-zen.focus-mode .overview{display:none !important}
body.ui-classic.shared-view .overview, body.ui-rail.shared-view .overview, body.ui-zen.shared-view .overview{display:none !important}

/* ---- Classic: the upstream floating toolbar ---- */
body.ui-classic .app{grid-template-columns:auto 1fr}
body.ui-classic .stage{grid-column:2;grid-row:1}
body.ui-classic .topbar{
  position:absolute;top:14px;left:14px;right:14px;z-index:30;pointer-events:none;
  background:none;border-bottom:none;padding:0;flex-wrap:nowrap;gap:8px;
}
body.ui-classic .topbar > *{pointer-events:auto}
body.ui-classic .tb-group{background:var(--chrome);border:1px solid var(--chrome-edge);border-radius:12px;padding:4px;box-shadow:var(--shadow)}
body.ui-classic .tb-sep{display:none}
body.ui-classic .search-wrap{background:var(--chrome);border:1px solid var(--chrome-edge);border-radius:12px;box-shadow:var(--shadow)}
body.ui-classic .search-wrap.open{background:var(--paper-2)}
/* Sidebar shell (as upstream): plain brand, new-map row with ▾ caret, no
   tabs - the caret toggles the Templates pane in and out. */
body.ui-classic .side-tabs{display:none}
body.ui-classic .new-map-row{display:flex;gap:0;margin:14px 14px 10px}
body.ui-classic .new-map-row #newMap{
  flex:1;height:auto;padding:11px;margin:0;
  border:1.5px dashed var(--line-2);background:none;color:var(--ink-soft);
  border-top-left-radius:11px;border-bottom-left-radius:11px;
  border-top-right-radius:0;border-bottom-right-radius:0;
  font-weight:600;font-size:14px;font-family:inherit;
}
body.ui-classic .new-map-row #newMap:hover{border-color:var(--accent);color:var(--accent);background:var(--node-bg)}
body.ui-classic .new-map-row .new-map-caret{
  width:36px;padding:0;background:var(--accent);color:#fff;border:none;
  border-left:1px solid color-mix(in srgb, #000 18%, var(--accent));
  border-top-right-radius:11px;border-bottom-right-radius:11px;
  cursor:pointer;font-size:13px;font-family:inherit;
}
body.ui-classic .new-map-row .new-map-caret:hover{background:var(--accent-deep)}
body.ui-classic.md-ready .app{grid-template-columns:auto auto minmax(0,1fr)}
body.ui-classic #mdPane{grid-column:2;grid-row:1}
body.ui-classic.md-ready .stage{grid-column:3;grid-row:1}
body.ui-classic.focus-mode .app{grid-template-columns:1fr}
body.ui-classic.focus-mode .stage{grid-column:1;grid-row:1;width:calc(100vw / var(--ui-zoom, 1));height:calc(100dvh / var(--ui-zoom, 1))}
body.ui-classic.shared-view .app{grid-template-columns:1fr;padding-top:var(--shared-banner-h, 42px)}
body.ui-classic.shared-view .stage{grid-column:1;grid-row:1}
body.ui-classic.shared-view .breadcrumb{top:97px;left:50%;transform:translateX(-50%) translateY(-4px)}
body.ui-classic.shared-view .breadcrumb.shown{transform:translateX(-50%) translateY(0)}

/* ---- Side-toolbar: the toolbar is a vertical icon rail left of the canvas.
   Title, save pill, minimap card, zoombar and hint float over the canvas. ---- */
body.ui-rail .app{grid-template-columns:auto 46px minmax(0,1fr)}
body.ui-rail .side{grid-column:1;grid-row:1}
body.ui-rail .topbar{
  grid-column:2;grid-row:1;position:relative;z-index:20;   /* a solid column above the canvas, whatever overlaps it */
  display:flex;flex-direction:column;align-items:center;gap:5px;
  padding:10px 5px;background:var(--chrome);border-right:1px solid var(--chrome-edge);
  border-bottom:none;overflow:visible;scrollbar-width:none;
}
body.ui-rail .topbar::-webkit-scrollbar{display:none}
body.ui-rail .topbar .tb-group{flex-direction:column;gap:2px}
body.ui-rail .topbar .tb{width:36px;height:34px;padding:0;font-size:16px}
body.ui-rail .topbar .tb.wide{width:36px;padding:0;font-size:16px}
body.ui-rail .topbar .tb-sep{display:none}
body.ui-rail .topbar .spacer,
body.ui-rail .topbar .title-edit{display:none}   /* the title is moved out to float on the canvas */
body.ui-rail .topbar > .user-pill,
body.ui-rail .topbar > .token-total{display:none}  /* too wide for the rail (left over from classic) */
/* Search floats right of the rail, over the canvas - toggled by the
   ⌕ button exactly like the modern toolbar's own inline field. */
body.ui-rail .topbar .search-wrap{
  position:absolute;top:64px;left:calc(100% + 8px);right:auto;z-index:20;
  width:0; overflow:hidden;
  background:none; border:none; box-shadow:none;
}
body.ui-rail .topbar .search-wrap.open{
  width:230px;
  background:var(--chrome);border:1px solid var(--chrome-edge);border-radius:12px;
  box-shadow:var(--shadow);
}
body.ui-rail .topbar .search-wrap.open.replace-mode{width:420px}
body.ui-rail .stage{grid-column:3;grid-row:1}
body.ui-rail .title-edit{
  position:absolute;top:14px;left:14px;z-index:30;max-width:42vw;
  background:transparent;border:1px solid transparent;
}
body.ui-rail .title-edit:hover, body.ui-rail .title-edit:focus{background:var(--chrome);border-color:var(--chrome-edge)}
/* Top-right group on the canvas: signed-in pill + save feedback (see the rail
   branch of applyUiLayout). The pills themselves are unstyled here; the group
   is what floats, so they never overlap each other whatever their width. */
body.ui-rail .rail-float{position:absolute;top:14px;right:14px;z-index:30;display:flex;align-items:center;gap:8px}
body.ui-rail .rail-float .save-pill{margin:0}
body.ui-rail.md-ready .app{grid-template-columns:auto 46px auto minmax(0,1fr)}
body.ui-rail #mdPane{grid-column:3;grid-row:1}
body.ui-rail.md-ready .stage{grid-column:4;grid-row:1}
body.ui-rail.focus-mode .app{grid-template-columns:1fr}
body.ui-rail.focus-mode .topbar{display:none}
body.ui-rail.focus-mode .stage{grid-column:1;grid-row:1;width:calc(100vw / var(--ui-zoom, 1));height:calc(100dvh / var(--ui-zoom, 1))}
body.ui-rail.shared-view .app{grid-template-columns:auto 46px minmax(0,1fr);padding-top:var(--shared-banner-h, 42px)}
body.ui-rail.shared-view .topbar{grid-column:2;grid-row:1}
body.ui-rail.shared-view .stage{grid-column:3;grid-row:1}
body.ui-rail.shared-view .breadcrumb{top:97px;left:50%;transform:translateX(-50%) translateY(-4px)}
body.ui-rail.shared-view .breadcrumb.shown{transform:translateX(-50%) translateY(0)}

/* ── Side-toolbar popovers: fly out to the right of the rail ───────────────
   In the rail layout the toolbar is a 46px vertical strip. A classic dropdown
   (below the button, right-aligned) gets clamped to the left viewport edge and
   looks detached - the pattern every modern app with a vertical rail uses is a
   horizontal flyout 8px to the right of the rail, top-aligned with the trigger
   (VS Code activity bar, Figma tools, Slack navigation, Discord server list).
   The JS `positionPopup(…, {side:'right'})` places the popover there; these
   rules just polish the feel so the flyout reads as attached to the rail. */
@keyframes railPopIn{
  from{opacity:0; transform:translateX(-6px) scale(.98);}
  to{opacity:1; transform:translateX(0) scale(1);}
}
body.ui-rail .theme-panel,
body.ui-rail .export-pop{
  transform-origin:left center;
  animation:railPopIn .14s cubic-bezier(.2,0,.2,1);
  /* A slightly stronger shadow so the flyout lifts clearly off the canvas and
     the rail when it sits 8px away - matching VS Code / Slack elevation. */
  box-shadow:0 12px 40px rgba(0,0,0,.22), 0 2px 8px rgba(0,0,0,.14);
}
@media (prefers-reduced-motion: reduce){
  body.ui-rail .theme-panel,
  body.ui-rail .export-pop{animation:none;}
}

/* ---- Zen / write: the shell vanishes; the canvas fills the window. The
   toolbar strip, breadcrumb and save pill are hidden and slide in only while
   the pointer hovers the top edge (body.zen-chrome). Minimap card, zoombar
   and hint stay floating at all times. ---- */
body.ui-zen .app{grid-template-columns:1fr;grid-template-rows:minmax(0,1fr)}
body.ui-zen .side{
  position:fixed;top:0;left:0;bottom:0;width:min(320px,86vw);z-index:400;
  background:var(--chrome);border-right:1px solid var(--chrome-edge);
  box-shadow:var(--shadow-lg);transform:translateX(-100%);
  transition:transform .25s cubic-bezier(.4,0,.2,1);
  display:flex;flex-direction:column;
}
body.ui-zen.side-open .side{transform:translateX(0)}
body.ui-zen .statusbar{display:none}
body.ui-zen .stage{grid-column:1;grid-row:1}
body.ui-zen .topbar{
  position:absolute;top:14px;left:50%;right:auto;z-index:30;pointer-events:none;
  display:flex;align-items:center;gap:6px;flex-wrap:nowrap;overflow:hidden;
  background:var(--chrome);border:1px solid var(--chrome-edge);border-radius:12px;
  padding:4px 8px;box-shadow:var(--shadow);max-width:92vw;width:max-content;
  opacity:0;transform:translateX(-50%) translateY(-12px);
  transition:opacity .18s ease, transform .18s ease;
}
body:not(.ui-zen) #zenPin{display:none}
body.ui-zen.zen-chrome .topbar{opacity:1;transform:translateX(-50%) translateY(0);pointer-events:auto}
/* Pinned: bar stays visible without hovering the top edge (state in localStorage).
   Declared BEFORE the focus-mode rules below so focus mode still hides it. */
body.ui-zen.zen-pinned .topbar{opacity:1;transform:translateX(-50%) translateY(0);pointer-events:auto}
body.ui-zen #zenPin.on{background:var(--accent);color:#fff}
body.ui-zen .tb-group{background:none;border:none;border-radius:0;padding:0;box-shadow:none}
body.ui-zen .tb-sep{width:1px;height:22px;background:var(--chrome-edge);flex:0 0 auto}
body.ui-zen .search-wrap{background:transparent;border:none;box-shadow:none;flex:0 0 auto}
body.ui-zen .search-wrap.open{background:var(--paper-2);border:1px solid var(--chrome-edge);border-radius:8px;padding:2px}
/* Opening search must widen the centered bar instead of squeezing the field:
   lift the 92vw cap and absorb the extra width from the map title first. */
body.ui-zen .topbar:has(.search-wrap.open){max-width:98vw}
body.ui-zen .topbar:has(.search-wrap.open) .title-edit{min-width:60px;max-width:160px}
/* While the find field is open the least-used actions step aside, so the
   token counter and pin stay on the first row instead of being clipped.
   Tabbed workspace (▭) is the primary reclaim per spec; Donate (♥) is also
   low-priority while searching and avoids the ~2px clip at 1024px / ~50px at
   960px that otherwise hides the pin. (Present used to be reclaimed here too;
   that button is gone from the bar.) */
body.ui-zen .topbar:has(.search-wrap.open) #tabsBtn,
body.ui-zen .topbar:has(.search-wrap.open) #donateBtn{display:none}
@media (max-width:1024px){
  /* 960px still clips the pin by ~20px even after the three above; reclaim
     one more low-priority control only on narrow windows so wide screens
     keep the full bar. */
  body.ui-zen .topbar:has(.search-wrap.open) #varsBtn{display:none}
}
body.ui-zen .save-pill{display:flex;position:absolute;top:22px;right:14px;z-index:30;margin:0}
body.ui-zen .token-total{background:none;border:none;box-shadow:none;border-radius:0;padding:6px 4px;margin-left:4px}
body.ui-zen .breadcrumb{display:none}
body.ui-zen.md-ready .topbar{max-width:min(92vw, calc(100% - 28px))}
body.ui-zen.md-ready .topbar:has(.search-wrap.open){max-width:min(98vw, calc(100% - 16px))}
body.ui-zen.md-ready .app{grid-template-columns:auto minmax(0,1fr)}
body.ui-zen #mdPane{grid-column:1;grid-row:1}
body.ui-zen.md-ready .stage{grid-column:2;grid-row:1}
body.ui-zen.tabs-on .app{grid-template-rows:auto minmax(0,1fr)}
body.ui-zen.tabs-on #tabStrip{grid-column:1;grid-row:1;display:flex}
body.ui-zen.tabs-on .stage{grid-column:1;grid-row:2}
body.ui-zen.tabs-on.md-ready .app{grid-template-columns:auto minmax(0,1fr);grid-template-rows:auto minmax(0,1fr)}
body.ui-zen.tabs-on.md-ready #tabStrip{grid-column:1/-1;grid-row:1}
body.ui-zen.tabs-on.md-ready #mdPane{grid-column:1;grid-row:2}
body.ui-zen.tabs-on.md-ready .stage{grid-column:2;grid-row:2}
body.ui-zen.focus-mode #mdPane{display:none}
@media (prefers-reduced-motion: reduce){ body.ui-zen .topbar{transition:none} }
body.ui-zen.focus-mode .topbar{opacity:0;transform:translateY(-12px);pointer-events:none}
body.ui-zen.focus-mode .stage{grid-column:1;grid-row:1;width:calc(100vw / var(--ui-zoom, 1));height:calc(100dvh / var(--ui-zoom, 1))}
body.ui-zen.shared-view .app{grid-template-columns:1fr;padding-top:var(--shared-banner-h, 42px)}
body.ui-zen.shared-view .topbar{display:none}
body.ui-zen.shared-view .stage{grid-column:1;grid-row:1}
body.ui-zen.shared-view .breadcrumb{top:97px;left:50%;transform:translateX(-50%) translateY(-4px)}
body.ui-zen.shared-view .breadcrumb.shown{transform:translateX(-50%) translateY(0)}

/* ---- Bottom-dock: the status bar becomes a full-width dock that owns the
   sidebar toggle, the Maps/Templates tabs, the hint and the overview chip;
   the sidebar turns into a slide-over panel instead of a permanent column. ---- */
body.ui-dock .app{grid-template-columns:1fr;grid-template-rows:auto auto minmax(0,1fr) auto}
body.ui-dock .topbar{grid-column:1;grid-row:1}
body.ui-dock #tabStrip{grid-column:1;grid-row:2}
body.ui-dock .stage{grid-column:1;grid-row:3}
body.ui-dock .statusbar{grid-column:1;grid-row:4;width:100%;gap:12px;padding:6px 12px}
body.ui-dock .side{
  position:fixed;top:0;left:0;bottom:0;width:min(320px,86vw);z-index:400;
  background:var(--chrome);border-right:1px solid var(--chrome-edge);
  box-shadow:var(--shadow-lg);transform:translateX(-100%);
  transition:transform .25s cubic-bezier(.4,0,.2,1);
}
body.ui-dock.side-open .side{transform:translateX(0)}
body.ui-dock .side-rail, body.ui-dock .side-resize{display:none}
body.ui-dock .side-tabs{display:flex;gap:2px;padding:2px;background:var(--paper-2);border-radius:10px}
body.ui-dock .hint{margin-left:auto}
body.ui-dock.md-ready .app{grid-template-columns:minmax(0,1fr) auto}
body.ui-dock.md-ready #mdPane{grid-column:2;grid-row:3; border-right:none; border-left:1px solid var(--line)}
body.ui-dock.md-ready .stage{grid-column:1;grid-row:3}
body.ui-dock.md-ready .topbar{grid-column:1/-1;grid-row:1}
body.ui-dock.md-ready #tabStrip{grid-column:1/-1;grid-row:2}
body.ui-dock.md-ready .statusbar{grid-column:1/-1;grid-row:4}
body.ui-dock.md-ready #mdPane .md-resize{left:0; right:auto}
body.ui-dock.md-mode #mdPane{width:var(--md-w,40vw)}
body.ui-dock.focus-mode .app{grid-template-columns:1fr}
body.ui-dock.focus-mode #mdPane{display:none}
body.ui-dock.focus-mode .stage{grid-column:1;grid-row:3;width:calc(100vw / var(--ui-zoom, 1));height:calc(100dvh / var(--ui-zoom, 1))}
body.ui-dock.shared-view .app{grid-template-columns:1fr}
body.ui-dock.shared-view #mdPane{display:none}
body.ui-dock.shared-view .stage{grid-column:1;grid-row:3}

/* ---- Split editor: the modern shell plus the markdown pane pinned open as a
   permanent third column (side | editor | canvas). ---- */
body.ui-split .app{grid-template-columns:auto auto minmax(0,1fr)}
body.ui-split .side{grid-column:1;grid-row:1/5}
body.ui-split .topbar{grid-column:2/-1;grid-row:1}
body.ui-split #mdPane{grid-column:2;grid-row:3;width:var(--md-w,40vw)}
body.ui-split .stage{grid-column:3;grid-row:3}
body.ui-split .statusbar{grid-column:2/-1;grid-row:4}
body.ui-split #mdToggle{display:none}
body.ui-split #mdPane .md-close{display:none}
 body.ui-split.focus-mode .app{grid-template-columns:1fr}
  body.ui-split.focus-mode #mdPane{display:none}
  body.ui-split.focus-mode .stage{grid-column:1;grid-row:3;width:calc(100vw / var(--ui-zoom, 1));height:calc(100dvh / var(--ui-zoom, 1))}
body.ui-split.tabs-on .app{grid-template-rows:auto auto minmax(0,1fr) auto}
body.ui-split.tabs-on #tabStrip{display:flex;grid-column:2/-1;grid-row:2}
body.ui-split.tabs-on #mdPane{grid-column:2;grid-row:3}
body.ui-split.tabs-on .stage{grid-column:3;grid-row:3}
body.ui-split.shared-view .app{grid-template-columns:1fr}
body.ui-split.shared-view #mdPane{display:none}
body.ui-split.shared-view .stage{grid-column:1;grid-row:3}

 /* ---- Minimal: the plain modern shell with the sidebar gone entirely - no
   column, no slide-over, nothing to toggle. ---- */
body.ui-minimal .app{grid-template-columns:1fr}
body.ui-minimal .topbar{grid-column:1;grid-row:1}
body.ui-minimal .stage{grid-column:1;grid-row:3}
body.ui-minimal .statusbar{grid-column:1;grid-row:4}
body.ui-minimal .side{
  position:fixed;top:0;left:0;bottom:0;width:min(320px,86vw);z-index:400;
  background:var(--chrome);border-right:1px solid var(--chrome-edge);
  box-shadow:var(--shadow-lg);transform:translateX(-100%);
  transition:transform .25s cubic-bezier(.4,0,.2,1);
}
body.ui-minimal.side-open .side{transform:translateX(0)}
body.ui-minimal .side-rail, body.ui-minimal .side-resize{display:none}
body.ui-minimal #toggleSide{display:none}
body.ui-minimal.md-ready .app{grid-template-columns:minmax(0,1fr) auto}
body.ui-minimal.md-ready #mdPane{grid-column:2;grid-row:3; border-right:none; border-left:1px solid var(--line)}
body.ui-minimal.md-ready .stage{grid-column:1;grid-row:3}
body.ui-minimal.md-ready .topbar{grid-column:1/-1;grid-row:1}
body.ui-minimal.md-ready #tabStrip{grid-column:1/-1;grid-row:2}
body.ui-minimal.md-ready .statusbar{grid-column:1/-1;grid-row:4}
body.ui-minimal.md-ready #mdPane .md-resize{left:0; right:auto}
body.ui-minimal.md-mode #mdPane{width:var(--md-w,40vw)}
body.ui-minimal.tabs-on .app{grid-template-rows:auto auto minmax(0,1fr) auto}
body.ui-minimal.tabs-on #tabStrip{display:flex;grid-column:1;grid-row:2}
body.ui-minimal.tabs-on .stage{grid-column:1;grid-row:3}
body.ui-minimal.tabs-on.md-ready #mdPane{grid-column:2;grid-row:3}
body.ui-minimal.tabs-on.md-ready .stage{grid-column:1;grid-row:3}
body.ui-minimal.focus-mode .app{grid-template-columns:1fr}
body.ui-minimal.focus-mode #mdPane{display:none}
body.ui-minimal.focus-mode .stage{grid-column:1;grid-row:3;width:calc(100vw / var(--ui-zoom, 1));height:calc(100dvh / var(--ui-zoom, 1))}
body.ui-minimal.shared-view .app{grid-template-columns:1fr}
body.ui-minimal.shared-view #mdPane{display:none}
body.ui-minimal.shared-view .stage{grid-column:1;grid-row:3}

  /* ---- Minimal launcher: a Raspberry-Pi-OS-style menu. The MindSpark logo
   sits beside the map title at the top-left and opens a context menu with
   Maps, Templates and Open source. Only the minimal layout shows the logo. ---- */
.minimal-menu-btn{display:none;align-items:center;justify-content:center;
  width:34px;height:34px;margin:6px 4px 6px 10px;padding:0;flex:0 0 auto;
  border:none;border-radius:9px;background:none;cursor:pointer}
.minimal-menu-btn:hover{background:var(--hover)}
.minimal-menu-btn:active{transform:scale(.94)}
.minimal-menu-btn svg{width:24px;height:24px}
body.ui-minimal .minimal-menu-btn{display:flex}
.minimal-menu{
  position:fixed;min-width:190px;z-index:500;padding:6px;
  background:var(--chrome);border:1px solid var(--chrome-edge);border-radius:12px;
  box-shadow:var(--shadow-lg);display:flex;flex-direction:column;gap:2px;
  animation:pop .12s ease-out;
}
.minimal-menu[hidden]{display:none}
.minimal-menu .mm-item{
  display:flex;align-items:center;gap:10px;padding:8px 10px;width:100%;
  border:none;background:none;border-radius:8px;font-family:inherit;font-size:13px;
  color:var(--ink);cursor:pointer;text-align:left}
.minimal-menu .mm-item:hover{background:var(--hover)}
.minimal-menu .mm-item.mm-has-sub:hover{background:var(--paper-2)}
.minimal-menu .mm-item.mm-has-sub:hover .mm-caret{color:var(--accent);opacity:1}
.minimal-menu .mm-item:active{transform:scale(.98)}
.minimal-menu .mm-item + .mm-item{border-top:1px solid transparent}
.minimal-menu .mm-item .mm-lbl{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.minimal-menu .mm-item .mm-caret{margin-left:auto;font-size:10px;opacity:.6;transform:translateY(-1px)}
.minimal-menu .mm-ic{width:18px;height:18px;flex:0 0 auto;display:flex;align-items:center;justify-content:center;color:var(--accent)}
.minimal-menu .mm-ic svg{width:16px;height:16px}
.minimal-menu .mm-ic .dot{width:9px;height:9px;border-radius:50%;flex:0 0 auto;display:block}
.minimal-menu .mm-ic svg + .dot{display:none}
@keyframes pop{from{opacity:0}to{opacity:1}}

/* Cascading sub-panels anchored beside their parent item. They live on <body>
   (never inside the animated menu) so their fixed positioning is relative to
   the viewport; they flip to the left/bottom edge when they would otherwise
   run off the screen. */
.minimal-sub{
  position:fixed;min-width:190px;max-width:280px;max-height:min(70vh,420px);overflow-y:auto;
  z-index:501;padding:6px;background:var(--chrome);border:1px solid var(--chrome-edge);
  border-radius:12px;box-shadow:var(--shadow-lg);display:flex;flex-direction:column;gap:2px;
  animation:pop .12s ease-out;
}
.minimal-sub[hidden]{display:none}
.minimal-sub .mm-item{display:flex;align-items:center;gap:10px;padding:8px 10px;width:100%;border:none;background:none;border-radius:8px;font-family:inherit;font-size:13px;color:var(--ink);cursor:pointer;text-align:left}
.minimal-sub .mm-item:hover{background:var(--hover)}
.minimal-sub .mm-item:active{transform:scale(.98)}
.minimal-sub .mm-item.active{background:var(--paper-2);color:var(--accent);font-weight:600}
.minimal-sub .mm-item .mm-lbl{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.minimal-sub .mm-item .mm-pin{margin-left:auto;font-size:11px;opacity:.7}
.minimal-sub .mm-ic{width:18px;height:18px;flex:0 0 auto;display:flex;align-items:center;justify-content:center;color:var(--accent)}
.minimal-sub .mm-ic svg{width:16px;height:16px}
.minimal-sub .mm-ic .dot{width:9px;height:9px;border-radius:50%;flex:0 0 auto;display:block}
.minimal-sub .mm-empty{padding:8px 10px;font-size:12px;color:var(--muted);text-align:center}
.minimal-sub .map-group-label{font-size:10px;text-transform:uppercase;letter-spacing:.6px;color:var(--muted);padding:8px 10px 4px;font-weight:700}

/* ---- Mirror classic: the same floating shell as classic, flipped to the
   left. applyUiLayout() keeps body.ui-classic applied too, so every classic
   rule already covers this layout - only the positions are mirrored. ---- */
body.ui-mirror .topbar{justify-content:flex-end}     /* actions left, title right */
body.ui-mirror .tb-group{flex-direction:row-reverse}
body.ui-mirror .overview{right:auto;left:72px}       /* minimap card bottom-left */
body.ui-mirror .zoom-row{right:auto;left:18px}       /* zoombar beside it, left edge */
body.ui-mirror .hint{left:auto;right:18px}           /* hint bottom-right */
body.ui-mirror.shared-view .breadcrumb{transform:translateX(-50%) translateY(-4px)}
body.ui-mirror.shared-view .breadcrumb.shown{transform:translateX(-50%) translateY(0)}

/* ---- Presentation: chrome vanishes, the canvas fills the window and the map
   is walked node by node (breadth-first). The current node gets an accent
   ring and the rest of the map dims; a slim bar top-centre shows the node
   title, the position in the walk and prev/next controls. ---- */
body.ui-deck .app{grid-template-columns:1fr;grid-template-rows:minmax(0,1fr)}
body.ui-deck .stage{grid-column:1;grid-row:1}
body.ui-deck .side, body.ui-deck .topbar, body.ui-deck .statusbar,
body.ui-deck .hint, body.ui-deck .overview, body.ui-deck .breadcrumb,
body.ui-deck .save-pill, body.ui-deck .search-wrap, body.ui-deck #mdPane,
body.ui-deck .focus-exit{display:none !important}
#deckBar{
  position:fixed;top:14px;left:50%;transform:translateX(-50%);z-index:500;
  display:flex;align-items:center;gap:12px;max-width:min(92vw, 640px);
  padding:6px 8px 6px 14px;background:var(--chrome);
  border:1px solid var(--chrome-edge);border-radius:12px;box-shadow:var(--shadow);
  font-size:13px;color:var(--ink);
}
#deckBar .deck-title{font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
#deckBar .deck-pos{font-variant-numeric:tabular-nums;color:var(--ink-soft);font-size:12px;flex:0 0 auto}
#deckBar .deck-nav{display:flex;gap:4px}
#deckBar button{width:30px;height:30px;border-radius:8px;border:none;background:none;color:var(--ink-soft);cursor:pointer;font-size:13px;line-height:1}
#deckBar button:hover{background:var(--hover);color:var(--ink)}
#deckBar #deckExit:hover{background:color-mix(in srgb, var(--accent) 14%, transparent);color:var(--accent)}
body.ui-deck .node{transition:opacity .3s ease}
body.ui-deck .node:not(.deck-current){opacity:.28}
body.ui-deck .node.deck-current{box-shadow:0 0 0 3px var(--accent)}

/* ---- Outline dock: the modern shell plus a live tree panel between the
   sidebar and the canvas (side | outline | canvas). Folded by default - the
   ▤ toolbar button opens it. Rows select + centre the node; the twist folds
   a branch locally without touching the map. ---- */
body.ui-outline .app{grid-template-columns:auto 0 minmax(0,1fr)}
body.ui-outline.outline-open .app{grid-template-columns:auto auto minmax(0,1fr)}
body.ui-outline .topbar, body.ui-outline .statusbar{grid-column:2/-1}
body.ui-outline .stage{grid-column:3;grid-row:3}
body.ui-outline #mdToggle{display:none}
body:not(.ui-outline) #outlineBtn{display:none}
#outlinePane{
  grid-column:2;grid-row:3;display:flex;flex-direction:column;min-width:0;min-height:0;
  width:0;overflow:hidden;background:var(--paper);border-right:1px solid var(--line);
  transition:width .22s cubic-bezier(.4,0,.2,1);
}
body.ui-outline.outline-open #outlinePane{width:min(280px,24vw)}
/* box-sizing:border-box cannot shrink a border, so the collapsed pane still
   measured 1px wide and painted a stray hairline down the canvas edge (in
   minimal that was the last column of the screen). Drop the border while it
   is closed so the pane is genuinely zero-width. */
body.ui-outline:not(.outline-open) #outlinePane{border-right-width:0}
#outlinePane .ol-head{display:flex;align-items:center;gap:8px;padding:8px 12px;border-bottom:1px solid var(--line);font-size:12px;font-weight:700;color:var(--ink-soft);letter-spacing:.04em}
#outlinePane .ol-close{margin-left:auto;border:none;background:none;cursor:pointer;color:var(--ink-soft);font-size:13px;line-height:1;padding:4px 6px;border-radius:6px}
#outlinePane .ol-close:hover{background:var(--hover);color:var(--ink)}
#outlinePane .ol-body{flex:1;min-height:0;overflow:auto;padding:8px 6px 14px}
#outlinePane .ol-tree, #outlinePane .ol-sub{list-style:none;margin:0;padding:0}
#outlinePane .ol-sub{padding-left:16px}
#outlinePane .ol-node.collapsed > .ol-sub{display:none}
#outlinePane .ol-row{display:flex;align-items:center;gap:4px;padding:4px 8px;border-radius:8px;cursor:pointer;font-size:13px;line-height:1.45;color:var(--ink)}
#outlinePane .ol-row:hover{background:var(--hover)}
#outlinePane .ol-node.sel > .ol-row{background:color-mix(in srgb, var(--accent) 14%, transparent);color:var(--accent)}
#outlinePane .ol-twist{flex:0 0 14px;width:14px;text-align:center;color:var(--ink-soft);font-size:10px;user-select:none;transition:transform .15s ease}
#outlinePane .ol-leaf{visibility:hidden}
#outlinePane .ol-node.collapsed > .ol-row .ol-twist{transform:rotate(-90deg)}
#outlinePane .ol-label{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
body.ui-outline.focus-mode .app{grid-template-columns:1fr}
body.ui-outline.focus-mode #outlinePane{display:none}
body.ui-outline.focus-mode .stage{grid-column:1;grid-row:3;width:calc(100vw / var(--ui-zoom, 1));height:calc(100dvh / var(--ui-zoom, 1))}
body.ui-outline.shared-view .app{grid-template-columns:auto minmax(0,1fr)}
body.ui-outline.shared-view #outlinePane{display:none}
body.ui-outline.shared-view .stage{grid-column:2;grid-row:3}

@media (max-width:720px){
  #deckBar{top:8px;left:8px;right:8px;transform:none;max-width:none}
  body.ui-outline .app{grid-template-columns:1fr}
  body.ui-outline .topbar, body.ui-outline .statusbar{grid-column:1}
  body.ui-outline .stage{grid-column:1;grid-row:3}
  body.ui-outline #outlinePane, body.ui-outline #outlineBtn{display:none}
  body.ui-classic .app{grid-template-columns:1fr}
  body.ui-classic .side{grid-column:1;grid-row:1;width:min(280px, 86vw)}
  body.ui-classic .stage{grid-column:1;grid-row:1}
  body.ui-classic .side.collapsed{width:min(280px, 86vw) !important}
  body.ui-classic .topbar{top:10px;left:10px;right:10px}
  /* Full-width strip on phones. The insets stretch the bar, so the desktop
     translateX(-50%) centering must go too - it shifted the strip half its
     own width off-screen (left edge unreachable). */
  body.ui-zen .topbar{top:10px;left:10px;right:10px;width:auto;max-width:none;transform:translateY(-12px)}
  body.ui-zen.zen-chrome .topbar,
  body.ui-zen.zen-pinned .topbar{transform:translateY(0)}
  body.ui-split .app{grid-template-columns:1fr}
  body.ui-split .topbar{grid-column:1;grid-row:1}
  body.ui-split .stage{grid-column:1;grid-row:3}
  body.ui-split .statusbar{grid-column:1;grid-row:4}
  body.ui-classic .hint, body.ui-rail .hint, body.ui-zen .hint{display:none}
  body.ui-classic .overview, body.ui-rail .overview, body.ui-zen .overview{display:none}   /* minimap is hidden on small screens; the zoombar stays */
  body.ui-classic .zoom-row, body.ui-rail .zoom-row, body.ui-zen .zoom-row{bottom:12px;right:12px}
  body.ui-mirror .zoom-row{bottom:12px;left:12px;right:auto}
  /* Rail keeps its slim column on phones; the sidebar is the off-canvas
     overlay and the canvas fills the remaining column. */
  body.ui-rail .app{grid-template-columns:40px minmax(0,1fr)}
  body.ui-rail .side{grid-column:1;grid-row:1;width:min(280px, 86vw)}
  body.ui-rail .topbar{grid-column:1;grid-row:1;padding:8px 2px}
  body.ui-rail .stage{grid-column:2;grid-row:1}
}

/* ===== Smooth theme switching =====
   When a Colour Theme (or a theme-config JSON) changes the custom
   properties, these surfaces interpolate their colors over 0.3s - the same
   easing as the theme cards - instead of snapping. Canvas textures
   (background-image) are not interpolatable, so they still swap instantly
   while the paper color underneath fades; node and edge strokes fade with
   the theme too. Interactive hover controls use the shorter 0.2s so hover
   feedback stays snappy. */
body, .app, .topbar, .statusbar, .stage, .nodebar, .brand, .save-pill,
.vf-card, .row-pop, .picker, .donate-card, .export-pop,
.search-wrap, .minimap, .toast, .theme-panel, .notes-popup{
  transition: background-color 0.3s ease, border-color 0.3s ease, color 0.3s ease;
}
#edges path{
  transition: stroke 0.3s ease;
}
.tb, .map-item, .scale-opt, .side-tab, .tpl-side-item, .title-edit,
.overview, .zoom-val, .zoom-row button,
input, textarea, select{
  transition: background-color 0.2s ease, border-color 0.2s ease, color 0.2s ease;
}
@media (prefers-reduced-motion: reduce){
  body, .app, .topbar, .statusbar, .stage, .nodebar, .brand, .save-pill,
  .vf-card, .row-pop, .picker, .donate-card, .export-pop,
  .minimap, .theme-panel, .notes-popup, #edges path,
  .tb, .map-item, .scale-opt, .side-tab, .tpl-side-item, .title-edit,
  .overview, .zoom-val, .zoom-row button,
  input, textarea, select{
    transition: none !important;
  }
}
@media (prefers-reduced-motion: reduce){
  .wave-layer{ display:none !important; }
}
.bp-panel:focus{ outline:none; }
.bp-task-wrap{ margin:10px 0 6px; padding:0 14px; }
.bp-task-label{ font-size:11px; opacity:.6; margin-bottom:2px; }
.bp-task-chips{ display:flex; gap:4px; flex-wrap:wrap; margin-bottom:4px; }
.bp-chip{ font-size:11px; padding:2px 6px; border-radius:3px; border:1px solid var(--chrome-edge); background:var(--node-bg); color:var(--ink); cursor:pointer; }
.bp-chip:hover{ background:var(--accent); color:#fff; }
.bp-chip-wrap{ display:inline-flex; align-items:stretch; }
.bp-chip-wrap .bp-chip{ border-top-right-radius:0; border-bottom-right-radius:0; }
.bp-chip-del{ font-size:11px; line-height:1; padding:0 5px; cursor:pointer; color:var(--ink-soft);
  border:1px solid var(--chrome-edge); border-left:none; border-radius:0 3px 3px 0; background:var(--node-bg); }
.bp-chip-del:hover{ background:var(--accent); border-color:var(--accent); color:#fff; }
.bp-save{ font-size:11px; padding:2px 6px; border-radius:3px; cursor:pointer; color:var(--ink-soft);
  border:1px dashed var(--chrome-edge); background:transparent; }
.bp-save:hover{ border-color:var(--accent); color:var(--accent); }
.bp-chip.active{ background:var(--accent); color:#fff; }
.bp-instruction{ width:100%; min-height:48px; font-family:inherit; font-size:12px; padding:4px 6px; border:1px solid var(--chrome-edge); border-radius:3px; background:var(--node-bg); color:var(--ink); resize:vertical; }
/* Expanded = the "Run with API" section is open. The panel may use more of the
   window than its 80vh default, but never more than fits below its own top
   anchor: 100vh minus the 64px top offset and an 18px bottom margin (the same
   gap it keeps on the right). A fixed height here once made it fill the whole
   screen and run 64px past the bottom edge, clipping the Send row. */
.bp-panel.bp-expanded{ max-height:calc(100vh - 82px); }
