      :root {
        --bg-color: #121212;
        --font-family: "Outfit", sans-serif;
        --cyan-bright: #22d3ee;
        --cyan-glow: rgba(34, 211, 238, 0.6);
        --yellow-bright: #facc15;
        --yellow-glow: rgba(250, 204, 21, 0.6);
      }

      * {
        box-sizing: border-box;
        margin: 0;
        padding: 0;
      }

      body {
        background-color: var(--bg-color);
        font-family: var(--font-family);
        color: #f8fafc;
        height: 100vh;
        display: flex;
        align-items: center;
        justify-content: center;
        overflow: hidden;
      }

      /* Outer layout container */
      .viewport-container {
        position: relative;
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 80px;
      }

      /* ─── ROOT NODE CONTAINER ─── */
      .node-wrapper {
        position: relative;
        width: 280px;
        height: 280px;
        display: flex;
        align-items: center;
        justify-content: center;
        cursor: default;
        z-index: 10;
        pointer-events: none; /* Passes mouse events to elements below */
      }

      /* Layer 1: Yellow Dashed Circle (backmost) - Enlarged & Brighter */
      .yellow-dashed-circle {
        position: absolute;
        top: 50%;
        left: 50%;
        width: 280px;
        height: 280px;
        pointer-events: none;
        z-index: 1;
        filter: drop-shadow(0 0 15px var(--yellow-glow));
        /* Base centring so the ring stays aligned even when the spin animation
           is frozen (e.g. body.deep-zoom sets animation: none). The slow-spin
           keyframes re-apply this same translate while animating. */
        transform: translate(-50%, -50%);
        animation: slow-spin 140s linear infinite;
      }

      .yellow-dashed-circle circle {
        stroke: var(--yellow-bright);
        transition: stroke 0.3s ease;
      }

      /* Layer 2: Glass Circle (middle-back) - Permanently Showing */
      .glass-circle {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: 220px;
        height: 220px;
        border-radius: 50%;
        z-index: 2;
        pointer-events: auto; /* Receives mouse events */

        /* Frosted diagonal reflection split - light bending through glass body (reduced frost by 25%) */
        background: linear-gradient(
          135deg,
          rgba(255, 255, 255, 0.10) 0%,
          rgba(255, 255, 255, 0.04) 50%,
          rgba(255, 255, 255, 0.01) 51%,
          rgba(255, 255, 255, 0.06) 100%
        );

        /* Backdrop filter with contrast tuning (reduced blur by 25%) */
        backdrop-filter: blur(21px) saturate(210%) brightness(1.15) contrast(1.15);
        -webkit-backdrop-filter: blur(21px) saturate(210%) brightness(1.15) contrast(1.15);

        /* Border brighter at top-left, fading around to near-invisible at bottom-right */
        border: 1px solid transparent;
        background-clip: padding-box;
        outline: 1px solid rgba(255, 255, 255, 0.14);

        box-shadow:
          /* Top rim — sharp bright arc (light striking glass edge) */
          inset 0 2.5px 3px rgba(255, 255, 255, 0.5),
          /* Left rim — softer secondary catch light */
          inset 3px 0 8px rgba(255, 255, 255, 0.15),
          /* Bottom rim — deep shadow, opposite the light source */
          inset 0 -4px 12px rgba(0, 0, 0, 0.35),
          /* Right rim — slight cool shadow */
          inset -3px 0 8px rgba(0, 0, 40, 0.15),
          /* Frosted inner glow (reduced opacity by 25%) */
          inset 0 0 20px rgba(255, 255, 255, 0.07),
          /* Outer ambient scatter — glass glowing faintly */
          0 0 55px rgba(160, 185, 255, 0.15),
          /* Outer drop shadow */
          0 20px 52px -10px rgba(0, 0, 0, 0.70);

        /* Was `all`: with one of these on every node, `all` makes the engine
           diff every animatable property on each style recalc — and the physics
           tick rewrites inline styles on the wrapper every frame. Only these
           three actually change on hover. */
        transition:
          background 0.3s cubic-bezier(0.16, 1, 0.3, 1),
          box-shadow 0.3s cubic-bezier(0.16, 1, 0.3, 1),
          transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);
      }

      /* Subtle zoom on hover (reduced frosting/opacity by 25%) */
      .node-wrapper:hover .glass-circle {
        background: linear-gradient(
          135deg,
          rgba(255, 255, 255, 0.13) 0%,
          rgba(255, 255, 255, 0.06) 50%,
          rgba(255, 255, 255, 0.02) 51%,
          rgba(255, 255, 255, 0.09) 100%
        );
        box-shadow:
          inset 0 2.5px 3px rgba(255, 255, 255, 0.60),
          inset 3px 0 8px rgba(255, 255, 255, 0.20),
          inset 0 -4px 12px rgba(0, 0, 0, 0.35),
          inset -3px 0 8px rgba(0, 0, 40, 0.15),
          inset 0 0 22px rgba(255, 255, 255, 0.11),
          0 0 70px rgba(0, 0, 0, 0.80),
          0 0 22px rgba(0, 0, 0, 0.60),
          0 20px 52px -5px rgba(0, 0, 0, 0.80);
        transform: translate(-50%, -50%) scale(1.02);
      }


      body.deep-zoom .yellow-dashed-circle,
      body.deep-zoom .group-zone__ring {
        animation: none !important;
      }

      /* Control Icons floating directly on Glass Circle */
      .control-icon {
        position: absolute;
        background: none;
        border: none;
        outline: none;
        color: rgba(34, 211, 238, 0.85);
        font-family: var(--font-family);
        font-size: 22px;
        font-weight: 600;
        display: flex;
        align-items: center;
        justify-content: center;
        cursor: pointer;
        z-index: 10;
        transform: translate(-50%, -50%);
        pointer-events: auto; /* Receives mouse events */
        transition:
          transform 0.2s cubic-bezier(0.16, 1, 0.3, 1),
          color 0.2s ease,
          filter 0.2s ease;
      }

      /* Six controls distributed evenly at 45° intervals around the node, radius 88.75px
         (halfway between the purple 67.5px and glass 110px circles). Spaced away
         from the 0° and 180° horizontal axes so they do not overlap when node text is long.

         Top semi-circle:
         - 225° (top-left): delete button
         - 270° (top): add-child button
         - 315° (top-right): expand pill (rotated -27° from default -18° to yield -45°/315°)

         Bottom semi-circle:
         - 135° (bottom-left): steering button
         - 90° (bottom): blur-toggle button
         - 45° (bottom-right): isolate button */

      /* 45 deg (bottom right) */
      .btn-isolate {
        left: 202.8px;
        top: 202.8px;
      }

      /* 135 deg (bottom left) */
      .btn-steering {
        left: 77.2px;
        top: 202.8px;
      }

      /* 225 deg (top left) */
      .btn-delete {
        left: 77.2px;
        top: 77.2px;
      }

      /* 270 deg (top) — add a custom child node */
      .btn-add-child {
        left: 140px;
        top: 51.25px;
      }

      /* 90 deg (bottom) — blur/unblur the background image. Contextual: only
         nodes that actually have an image show it (see visibility rule below),
         so it doesn't crowd the evenly-spaced core controls on plain nodes. */
      .btn-blur-toggle {
        left: 140px;
        top: 228.75px;
      }
      /* Hide the eye entirely unless the node carries a background image */
      .node-wrapper:not([data-image-url]) .btn-blur-toggle {
        display: none;
      }
      /* Icon reflects current state: open eye = visible, closed eye = blurred */
      .btn-blur-toggle .eye-closed {
        display: none;
      }
      .node-wrapper[data-blurred="true"] .btn-blur-toggle .eye-open {
        display: none;
      }
      .node-wrapper[data-blurred="true"] .btn-blur-toggle .eye-closed {
        display: block;
      }

      /* -45 deg (Top Right) - Rotated from -18 deg by -27 deg */
      .btn-expand-pill {
        position: absolute;
        left: 0;
        top: 0;
        width: 280px;
        height: 280px;
        background: none;
        border: none;
        outline: none;
        z-index: 10;
        pointer-events: none; /* Passes mouse events to elements below */
        transform: rotate(-27deg);
      }

      .glass-pill-bg {
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
        height: 100%;
        /* Reduced frosting/opacity by 25% */
        background: linear-gradient(
          135deg,
          rgba(255, 255, 255, 0.09) 0%,
          rgba(255, 255, 255, 0.03) 50%,
          rgba(255, 255, 255, 0.01) 51%,
          rgba(255, 255, 255, 0.04) 100%
        );
        backdrop-filter: blur(15px) saturate(180%) brightness(1.2) contrast(1.1);
        -webkit-backdrop-filter: blur(15px) saturate(180%) brightness(1.2) contrast(1.1);
        clip-path: url(#pill-clip);
        cursor: pointer;
        pointer-events: auto; /* Captures mouse events only within clip-path */
        transition: background 0.3s cubic-bezier(0.16, 1, 0.3, 1);
        box-shadow: inset 0 2px 3px rgba(255, 255, 255, 0.35); /* highlight on the pill edge */
      }

      .glass-pill-bg:hover {
        /* Reduced frosting/opacity by 25% */
        background: linear-gradient(
          135deg,
          rgba(255, 255, 255, 0.15) 0%,
          rgba(255, 255, 255, 0.07) 50%,
          rgba(255, 255, 255, 0.03) 51%,
          rgba(255, 255, 255, 0.10) 100%
        );
      }

      .btn-expand-pill .pill-outline {
        transition: stroke 0.3s ease;
      }

      .glass-pill-bg:hover ~ svg .pill-outline {
        stroke: rgba(255, 255, 255, 0.45);
      }

      .btn-expand-pill .arrow-container {
        transform-origin: 0px 0px;
        transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1);
      }

      .btn-expand-pill .arrow-path {
        transition:
          stroke 0.3s ease,
          filter 0.3s ease;
      }

      .glass-pill-bg:hover ~ svg .arrow-path {
        stroke: #ffffff;
        filter: drop-shadow(0 0 8px var(--cyan-glow));
      }

      .control-icon:hover {
        color: #ffffff;
        filter: drop-shadow(0 0 8px var(--cyan-glow));
        transform: translate(-50%, -50%) scale(1.3);
      }

      .control-icon:active {
        transform: translate(-50%, -50%) scale(0.92);
      }

      /* Red hover for delete button */
      .btn-delete:hover {
        color: #ff4b72;
        filter: drop-shadow(0 0 8px rgba(255, 75, 114, 0.9));
      }

      /* Green hover for add-child button */
      .btn-add-child:hover {
        color: #4ade80;
        filter: drop-shadow(0 0 8px rgba(74, 222, 128, 0.9));
      }

      /* Layer 3: Dark Purple Gradient Node Base (middle-front) with Noise Texture */
      .purple-node-base {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: 135px;
        height: 135px;
        /* Top-left to bottom-left gradient overlaid with fractal noise texture */
        background-image:
          url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='3' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)' opacity='0.12'/%3E%3C/svg%3E"),
          linear-gradient(170deg, #9333ea, #06041f);
        border: 1px solid rgba(104, 36, 167, 0.25);
        border-radius: 50%;
        z-index: 3;
        display: flex;
        align-items: center;
        justify-content: center;
        box-shadow:
          0 12px 36px -8px rgba(0, 0, 0, 0.7),
          inset 0 2px 8px rgba(0, 0, 0, 0.5);
        transition:
          background 0.35s cubic-bezier(0.16, 1, 0.3, 1),
          box-shadow 0.35s cubic-bezier(0.16, 1, 0.3, 1),
          transform 0.35s cubic-bezier(0.16, 1, 0.3, 1),
          border-color 0.35s cubic-bezier(0.16, 1, 0.3, 1);
        overflow: hidden; /* Added to clip background images to the circle */
      }

      .node-wrapper:hover .purple-node-base {
        transform: translate(-50%, -50%) scale(1.03);
        border-color: rgba(168, 85, 247, 0.4);
        box-shadow:
          0 12px 36px -4px rgba(0, 0, 0, 0.8),
          inset 0 2px 8px rgba(0, 0, 0, 0.4),
          0 0 15px rgba(168, 85, 247, 0.25);
      }

      /* Layer 4: Glass Text Input (frontmost) - Refractive Glass & Pill-Shaped & Auto-Width */
      .glass-input-field {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        min-width: 100px;
        max-width: 600px;
        height: 46px;
        pointer-events: auto; /* Receives mouse events */
        /* Multi-layer gradient simulating light bending through glass (reduced frost by 25%) */
        background:
          linear-gradient(
            148deg,
            rgba(255, 255, 255, 0.31) 0%,
            rgba(255, 255, 255, 0.09) 18%,
            rgba(200, 220, 255, 0.03) 40%,
            rgba(255, 255, 255, 0.0) 60%,
            rgba(180, 210, 255, 0.04) 100%
          ),
          linear-gradient(
            180deg,
            rgba(255, 255, 255, 0.05) 0%,
            rgba(140, 160, 255, 0.02) 100%
          );
        border-top: 1px solid rgba(255, 255, 255, 0.65);
        border-left: 1px solid rgba(210, 230, 255, 0.45);
        border-right: 1px solid rgba(180, 200, 255, 0.25);
        border-bottom: 1px solid rgba(255, 255, 255, 0.12);
        border-radius: 9999px;
        backdrop-filter: blur(30px) saturate(280%) brightness(1.3) contrast(1.05);
        -webkit-backdrop-filter: blur(30px) saturate(280%) brightness(1.3) contrast(1.05);
        color: #ffffff;
        font-family: var(--font-family);
        font-size: 30px;
        font-weight: 600;
        text-align: center;
        padding: 0 20px;
        line-height: 46px;
        outline: none;
        z-index: 20;
        box-shadow:
          inset 0 2px 1.5px rgba(255, 255, 255, 0.65),
          inset 0 -2px 5px rgba(0, 0, 0, 0.3),
          inset 2px 0 4px rgba(255, 255, 255, 0.08),
          inset -2px 0 4px rgba(100, 120, 200, 0.06),
          0 0 0 1px rgba(255, 255, 255, 0.08),
          0 14px 36px -4px rgba(0, 0, 0, 0.55),
          0 0 28px rgba(160, 190, 255, 0.12);
        transition:
          background 0.25s ease,
          border-color 0.25s ease,
          box-shadow 0.25s ease,
          color 0.2s ease;
      }

      .glass-input-field::placeholder {
        color: rgba(255, 255, 255, 0.32);
      }

      .glass-input-field:hover {
        background:
          linear-gradient(
            148deg,
            rgba(255, 255, 255, 0.52) 0%,
            rgba(255, 255, 255, 0.18) 18%,
            rgba(200, 220, 255, 0.07) 40%,
            rgba(255, 255, 255, 0.0) 60%,
            rgba(180, 210, 255, 0.1) 100%
          ),
          linear-gradient(
            180deg,
            rgba(255, 255, 255, 0.1) 0%,
            rgba(140, 160, 255, 0.05) 100%
          );
        border-top-color: rgba(255, 255, 255, 0.75);
        box-shadow:
          inset 0 2px 1.5px rgba(255, 255, 255, 0.75),
          inset 0 -2px 5px rgba(0, 0, 0, 0.3),
          inset 2px 0 6px rgba(255, 255, 255, 0.1),
          inset -2px 0 6px rgba(100, 120, 200, 0.08),
          0 0 0 1px rgba(255, 255, 255, 0.12),
          0 18px 44px -4px rgba(0, 0, 0, 0.65),
          0 0 36px rgba(160, 190, 255, 0.18);
      }

      .glass-input-field:focus {
        background:
          linear-gradient(
            148deg,
            rgba(255, 255, 255, 0.3) 0%,
            rgba(180, 210, 255, 0.08) 25%,
            rgba(10, 8, 40, 0.55) 55%,
            rgba(10, 8, 40, 0.65) 100%
          );
        backdrop-filter: blur(40px) saturate(280%) brightness(1.15) contrast(1.05);
        -webkit-backdrop-filter: blur(40px) saturate(280%) brightness(1.15) contrast(1.05);
        border-top-color: rgba(34, 211, 238, 0.7);
        border-left-color: rgba(34, 211, 238, 0.5);
        border-right-color: rgba(34, 211, 238, 0.3);
        border-bottom-color: rgba(34, 211, 238, 0.15);
        box-shadow:
          inset 0 2px 3px rgba(0, 0, 0, 0.5),
          inset 0 -1px 2px rgba(34, 211, 238, 0.1),
          0 0 30px rgba(34, 211, 238, 0.4),
          0 0 60px rgba(34, 211, 238, 0.15);
      }

      /* ─── NODE VARIANT (no dashed ring, glass retracts by default) ─── */

      /* Collapsed: glass circle shrinks to just peek out from behind the purple */
      .node-wrapper.node .glass-circle {
        transform: translate(-50%, -50%) scale(0.7);
        transition:
          transform 0.45s cubic-bezier(0.16, 1, 0.3, 1),
          box-shadow 0.45s cubic-bezier(0.16, 1, 0.3, 1),
          background 0.45s ease;
      }

      /* Controls invisible when collapsed */
      .node-wrapper.node .control-icon,
      .node-wrapper.node .btn-expand-pill {
        opacity: 0;
        pointer-events: none;
        transition: opacity 0.15s ease 0s;
      }

      /* Expanded: glass circle at full size */
      .node-wrapper.node.is-expanded .glass-circle {
        transform: translate(-50%, -50%) scale(1);
      }

      /* Controls fade in after glass has started expanding */
      .node-wrapper.node.is-expanded .control-icon,
      .node-wrapper.node.is-expanded .btn-expand-pill {
        opacity: 1;
        pointer-events: auto;
        transition: opacity 0.2s ease 0.2s;
      }

      .btn-expand-pill--loading .glass-pill-bg {
        animation: pill-pulse 1s ease-in-out infinite;
      }
      @keyframes pill-pulse {
        0%, 100% { opacity: 0.4; }
        50%       { opacity: 0.9; }
      }

      /* Purple base stays clickable and acts as the expand trigger */
      .node-wrapper.node .purple-node-base {
        cursor: pointer;
      }

      /* Dynamically created child nodes are fixed-positioned */
      .node-wrapper.dynamic {
        position: absolute;
        transform: translate(-50%, -50%);
      }

      /* ─── GHOST NODES ─── */
      .ghost-node {
        position: absolute;
        transform: translate(-50%, -50%) scale(0.82);
        width: 135px;
        height: 135px;
        border-radius: 50%;
        background: linear-gradient(170deg, #110822 0%, #06041f 100%);
        border: 2px dashed rgba(147, 51, 234, 0.5);
        display: flex;
        align-items: center;
        justify-content: center;
        color: rgba(255, 255, 255, 0.22);
        font-family: var(--font-family);
        font-size: 18px;
        font-weight: 600;
        letter-spacing: 0.02em;
        opacity: 0;
        cursor: pointer;
        z-index: 60;
        pointer-events: none;
        user-select: none;
        transition:
          opacity 0.4s ease,
          transform 0.45s cubic-bezier(0.16, 1, 0.3, 1),
          background 0.4s ease,
          color 0.4s ease,
          border-color 0.4s ease,
          border-style 0s ease 0.2s;
      }

      .ghost-node.visible {
        opacity: 1;
        transform: translate(-50%, -50%) scale(1);
        pointer-events: auto;
      }

      .ghost-node.solid {
        background: linear-gradient(170deg, #9333ea 0%, #06041f 100%);
        border: 1px solid rgba(104, 36, 167, 0.25);
        color: rgba(255, 255, 255, 0.88);
      }

      /* Glass ring that appears around committed ghost nodes */
      .ghost-glass-ring {
        position: absolute;
        transform: translate(-50%, -50%);
        width: 155px;
        height: 155px;
        border-radius: 50%;
        background: rgba(255, 255, 255, 0.04);
        backdrop-filter: blur(38px) saturate(290%) brightness(1.25) contrast(1.08);
        -webkit-backdrop-filter: blur(38px) saturate(290%) brightness(1.25) contrast(1.08);
        border: 1px solid transparent;
        outline: 1px solid rgba(255, 255, 255, 0.14);
        box-shadow:
          inset 0 2.5px 3px rgba(255, 255, 255, 0.45),
          inset 3px 0 8px rgba(255, 255, 255, 0.1),
          inset 0 -4px 12px rgba(0, 0, 0, 0.3),
          0 0 55px rgba(160, 185, 255, 0.13),
          0 20px 52px -10px rgba(0, 0, 0, 0.65);
        opacity: 0;
        transition: opacity 0.4s ease 0.15s;
        z-index: 59;
        pointer-events: none;
      }

      .ghost-glass-ring.visible {
        opacity: 1;
      }

      /* ─── BRIDGE (PURPLE) EDGE CONNECTORS ─── */
      /* Dimmed by default so they don't clutter the map; restored to full
         opacity while the edge itself — or either node it links — is hovered
         or selected (.is-active toggled from refreshExtraEdgeHighlight()). */
      .extra-edge-line {
        opacity: 0.3;
        transition: opacity 0.2s ease;
      }
      .extra-edge-line.is-active {
        opacity: 1;
      }

      /* ─── LINEAGE EDGE GLOW ─── */
      /* While a node is selected, the tree edges along its path back to the root
         light up in the selection cyan — the canvas echo of the breadcrumb bar.
         The stroke here beats the inline #475569 the physics loop writes because
         presentation attributes rank below author CSS. */
      .edge--lineage line:not(.edge-hitline) {
        stroke: rgba(34, 211, 238, 0.9);
        transition:
          stroke 0.25s ease,
          filter 0.25s ease;
      }
      .edge--lineage {
        filter: drop-shadow(0 0 3px rgba(34, 211, 238, 0.65));
      }
      /* Bridge tethers on a lineage path: the dimmed purple line lifts to full
         opacity so the cyan path back to the root reads through it. */
      .edge--lineage .extra-edge-line {
        opacity: 1;
      }

      /* ─── TUNNEL BUTTONS ─── */
      .tunnel-btn {
        position: absolute;
        transform: translate(-50%, -50%) rotate(var(--angle, 0deg));
        height: 28px;
        border-radius: 9999px;
        /* Glass — no glare, just refraction */
        background: linear-gradient(
          148deg,
          rgba(255, 255, 255, 0.14) 0%,
          rgba(255, 255, 255, 0.04) 100%
        );
        backdrop-filter: blur(24px) saturate(240%) brightness(1.2);
        -webkit-backdrop-filter: blur(24px) saturate(240%) brightness(1.2);
        border-top: 1px solid rgba(255, 255, 255, 0.5);
        border-left: 1px solid rgba(255, 255, 255, 0.28);
        border-right: 1px solid rgba(255, 255, 255, 0.14);
        border-bottom: 1px solid rgba(255, 255, 255, 0.06);
        box-shadow:
          inset 0 1.5px 1px rgba(255, 255, 255, 0.45),
          inset 0 -1px 3px rgba(0, 0, 0, 0.2),
          0 4px 14px rgba(0, 0, 0, 0.35);
        display: flex;
        align-items: center;
        padding: 0 8px;
        cursor: pointer;
        z-index: 65;
        color: rgba(255, 255, 255, 0.85);
        font-family: var(--font-family);
        font-size: 11px;
        font-weight: 500;
        white-space: nowrap;
        outline: none;
        pointer-events: auto;
        opacity: 0;
        transition: opacity 0.22s ease, background 0.2s ease, box-shadow 0.2s ease;
      }

      .tunnel-btn.branch-visible {
        opacity: 1;
      }

      .tunnel-btn:hover {
        background: linear-gradient(
          148deg,
          rgba(255, 255, 255, 0.22) 0%,
          rgba(255, 255, 255, 0.07) 100%
        );
        box-shadow:
          inset 0 1.5px 1px rgba(255, 255, 255, 0.6),
          inset 0 -1px 3px rgba(0, 0, 0, 0.2),
          0 6px 18px rgba(0, 0, 0, 0.45);
      }

      .tunnel-arrow { flex-shrink: 0; }

      /* Grid trick: expands exactly to label content width, no fixed max */
      .tunnel-label-wrap {
        display: inline-grid;
        grid-template-columns: 0fr;
        transition: grid-template-columns 0.35s cubic-bezier(0.16, 1, 0.3, 1);
      }

      .tunnel-btn:hover .tunnel-label-wrap {
        grid-template-columns: 1fr;
      }

      .tunnel-label-inner {
        overflow: hidden;
        padding-left: 0;
        transition: padding-left 0.35s cubic-bezier(0.16, 1, 0.3, 1);
      }

      .tunnel-btn:hover .tunnel-label-inner {
        padding-left: 5px;
      }

      /* Cyan pulse ring when a tunnel is used to travel to a node */
      @keyframes travel-pulse {
        0%   { box-shadow: 0 12px 36px -8px rgba(0,0,0,0.7), inset 0 2px 8px rgba(0,0,0,0.5); }
        35%  { box-shadow: 0 0 0 12px rgba(34,211,238,0.38), 0 12px 36px -8px rgba(0,0,0,0.7), inset 0 2px 8px rgba(0,0,0,0.5); }
        100% { box-shadow: 0 0 0 0px rgba(34,211,238,0),    0 12px 36px -8px rgba(0,0,0,0.7), inset 0 2px 8px rgba(0,0,0,0.5); }
      }

      .node-travel-target .purple-node-base {
        animation: travel-pulse 0.85s cubic-bezier(0.16, 1, 0.3, 1) forwards;
      }

      /* ── CONTEXT BAR ── */
      .context-bar-group {
        position: fixed;
        transform: translateX(-50%) scale(0.88);
        transform-origin: center top;
        display: flex;
        flex-direction: column;
        align-items: stretch;
        gap: 8px;
        opacity: 0;
        pointer-events: none;
        z-index: 300;
        transition: opacity 0.3s ease, transform 0.4s cubic-bezier(0.16, 1, 0.3, 1),
                    top 0.42s cubic-bezier(0.16, 1, 0.3, 1);
      }

      .context-bar-group.visible {
        opacity: 1;
        transform: translateX(-50%) scale(1);
        pointer-events: auto;
      }

      /* Hide context bar when any node is in expanded image peek mode */
      body:has(.node--peek-expanded) #context-bar-group {
        opacity: 0 !important;
        pointer-events: none !important;
      }

      /* ── CONTEXT BAR — morphs into AI card ── */
      .context-bar {
        display: flex;
        flex-direction: column-reverse; /* icon row anchors at bottom; AI content grows upward */
        align-items: stretch;
        background: rgba(255, 255, 255, 0.07);
        backdrop-filter: blur(80px) saturate(160%) brightness(1.12);
        -webkit-backdrop-filter: blur(80px) saturate(160%) brightness(1.12);
        border: 1px solid rgba(255, 255, 255, 0.18);
        border-radius: 9999px;
        overflow: hidden;
        box-shadow: 0 8px 32px rgba(0,0,0,0.45), inset 0 1px 0 rgba(255,255,255,0.22), inset 0 -1px 0 rgba(0,0,0,0.12);
        color: #22d3ee;
        width: 300px; /* Base width to hold all 7 icon buttons without squeezing */
        transition: width 0.38s cubic-bezier(0.16, 1, 0.3, 1),
                    border-radius 0.42s cubic-bezier(0.16, 1, 0.3, 1),
                    background 0.38s ease,
                    border-color 0.38s ease,
                    box-shadow 0.38s ease;
      }

      /* Normal pill row of icon buttons */
      .ctx-icon-row {
        display: flex;
        align-items: center;
        gap: 2px;
        height: 52px;
        padding: 0 16px;
        flex-shrink: 0;
        white-space: nowrap;
        transition: height 0.38s cubic-bezier(0.16, 1, 0.3, 1),
                    opacity 0.18s ease,
                    padding 0.38s cubic-bezier(0.16, 1, 0.3, 1);
      }

      /* AI content — collapsed by default via grid trick; width:0/min-width:100% prevents it from stretching the bar wider than the icon row */
      .ai-panel-inner {
        display: grid;
        grid-template-rows: 0fr;
        width: 0;
        min-width: 100%;
        opacity: 0;
        pointer-events: none;
        transition: grid-template-rows 0.42s cubic-bezier(0.16, 1, 0.3, 1),
                    opacity 0.28s ease;
      }

      .ai-panel-inner > div { overflow: hidden; }

      .ai-panel-content {
        display: flex;
        flex-direction: column;
        gap: 10px;
        padding: 14px;
      }

      /* ── OPEN STATES FOR THE CONTEXT BAR (MORPH TO CARD) ── */
      .context-bar-group.ai-open .context-bar,
      .context-bar-group.search-open .context-bar,
      .context-bar-group.context-input-open .context-bar {
        border-radius: 18px;
        background: rgba(34, 38, 50, 0.97);
        border-color: rgba(255, 255, 255, 0.1);
        box-shadow: 0 20px 56px rgba(0,0,0,0.6), inset 0 1px 0 rgba(255,255,255,0.07);
        width: 360px; /* Stretch wider when open to fit text inputs & mode selectors! */
      }

      .context-bar-group.ai-open .ctx-icon-row {
        height: 0;
        opacity: 0;
        padding-top: 0;
        padding-bottom: 0;
        pointer-events: none;
      }

      .context-bar-group.ai-open .ai-panel-inner {
        grid-template-rows: 1fr;
        opacity: 1;
        pointer-events: auto;
      }

      .context-bar-group.ai-open .chip-tray {
        opacity: 0;
        pointer-events: none;
        transition: opacity 0.18s ease;
      }

      /* ── SEARCH OPEN STATE ── */

      .context-bar-group.search-open .ctx-icon-row {
        height: 0;
        opacity: 0;
        padding-top: 0;
        padding-bottom: 0;
        pointer-events: none;
      }

      .context-bar-group.search-open .search-panel-inner {
        grid-template-rows: 1fr;
        opacity: 1;
        pointer-events: auto;
      }

      .context-bar-group.search-open .chip-tray {
        opacity: 0;
        pointer-events: none;
        transition: opacity 0.18s ease;
      }

      /* Search panel wrapper — same grid trick as AI panel */
      .search-panel-inner {
        display: grid;
        grid-template-rows: 0fr;
        width: 0;
        min-width: 100%;
        opacity: 0;
        pointer-events: none;
        transition: grid-template-rows 0.42s cubic-bezier(0.16, 1, 0.3, 1),
                    opacity 0.28s ease;
      }

      .search-panel-inner > div { overflow: hidden; }

      .search-panel-content {
        display: flex;
        flex-direction: column;
        gap: 6px;
        padding: 10px;
        max-height: 264px;
        overflow-y: auto;
        scrollbar-width: thin;
        scrollbar-color: rgba(255,255,255,0.15) transparent;
      }

      .search-panel-content::-webkit-scrollbar { width: 3px; }
      .search-panel-content::-webkit-scrollbar-track { background: transparent; }
      .search-panel-content::-webkit-scrollbar-thumb { background: rgba(255,255,255,0.15); border-radius: 2px; }

      .sr-result {
        background: rgba(48, 52, 66, 0.9);
        border-radius: 10px;
        padding: 10px 12px;
        display: flex;
        flex-direction: column;
        gap: 5px;
        flex-shrink: 0;
        cursor: pointer;
        transition: background 0.15s ease;
      }

      .sr-result:hover { background: rgba(60, 65, 82, 0.9); }

      .sr-loading {
        padding: 14px 12px;
        font-size: 13px;
        color: rgba(255,255,255,0.38);
        text-align: center;
      }

      .sr-meta {
        display: flex;
        align-items: center;
        gap: 8px;
      }

      .sr-favicon {
        width: 22px;
        height: 22px;
        border-radius: 50%;
        border: 1.5px solid rgba(255,255,255,0.22);
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: 10px;
        color: rgba(255,255,255,0.45);
        flex-shrink: 0;
      }

      .sr-site { display: flex; flex-direction: column; }
      .sr-site-name { font-size: 13px; font-weight: 600; color: rgba(255,255,255,0.88); line-height: 1.2; }
      .sr-url      { font-size: 11px; color: rgba(255,255,255,0.38); line-height: 1.2; }
      .sr-title    { font-size: 16px; font-weight: 700; color: rgba(255,255,255,0.92); line-height: 1.3; }
      .sr-desc     { font-size: 12px; color: rgba(255,255,255,0.48); line-height: 1.45; }

      /* AI textarea */
      .ai-prompt-field {
        width: 100%;
        box-sizing: border-box;
        height: 130px;
        background: rgba(16, 18, 28, 0.85);
        border: 1px solid rgba(255, 255, 255, 0.07);
        border-radius: 12px;
        padding: 12px 14px;
        font-family: var(--font-family, system-ui, sans-serif);
        font-size: 13px;
        color: rgba(255, 255, 255, 0.72);
        resize: none;
        outline: none;
        line-height: 1.5;
      }

      .ai-prompt-field::placeholder { color: rgba(255, 255, 255, 0.26); }

      .ai-actions {
        display: flex;
        align-items: center;
        gap: 6px;
        padding: 0 2px;
      }

      .ai-spacer { flex: 1; }

      .ai-act-btn {
        display: flex;
        align-items: center;
        justify-content: center;
        background: none;
        border: none;
        cursor: pointer;
        color: #22d3ee;
        width: 30px;
        height: 30px;
        border-radius: 50%;
        flex-shrink: 0;
        transition: background 0.15s ease;
      }

      .ai-act-btn:hover { background: rgba(34, 211, 238, 0.12); }

      .ai-act-btn--listening {
        color: #f87171;
        background: rgba(248, 113, 113, 0.15);
        animation: voice-listening-pulse 1.1s ease-in-out infinite;
      }
      @keyframes voice-listening-pulse {
        0%, 100% { opacity: 0.7; }
        50%      { opacity: 1; }
      }

      .ai-act-btn.ai-plus {
        font-size: 24px;
        font-weight: 300;
        line-height: 1;
      }

      .ai-chips-wrap {
        display: flex;
        flex-wrap: wrap;
        gap: 6px;
      }

      .ai-chip-btn {
        background: rgba(16, 18, 28, 0.85);
        border: 1px solid rgba(255, 255, 255, 0.08);
        border-radius: 9999px;
        padding: 5px 14px;
        font-family: var(--font-family, system-ui, sans-serif);
        font-size: 12px;
        color: rgba(255, 255, 255, 0.55);
        cursor: pointer;
        transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
      }

      .ai-chip-btn:hover {
        background: rgba(34, 211, 238, 0.1);
        border-color: rgba(34, 211, 238, 0.3);
        color: #22d3ee;
      }

      .ctx-btn {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 36px;
        height: 36px;
        border-radius: 50%;
        background: none;
        border: none;
        cursor: pointer;
        color: rgba(255, 255, 255, 0.65); /* Very light grey */
        transition: background 0.18s ease, color 0.18s ease;
        flex-shrink: 0;
      }

      .ctx-btn:hover {
        background: rgba(255,255,255,0.12);
        color: #22d3ee; /* Original cyan color */
      }

      .ctx-divider {
        width: 1px;
        height: 22px;
        background: rgba(255,255,255,0.18);
        margin: 0 4px;
        flex-shrink: 0;
      }

      /* ── CONTEXT INPUT PANEL ── */
      .context-input-panel-inner {
        display: grid;
        grid-template-rows: 0fr;
        width: 0;
        min-width: 100%;
        opacity: 0;
        pointer-events: none;
        transition: grid-template-rows 0.38s cubic-bezier(0.16, 1, 0.3, 1),
                    opacity 0.25s ease;
      }

      .context-input-panel-inner > div { overflow: hidden; }

      .context-input-content {
        display: flex;
        align-items: center;
        gap: 8px;
        height: 84px;
        padding: 8px 12px 8px 16px;
      }

      .context-text-input {
        flex: 1;
        background: none;
        border: none;
        outline: none;
        font-family: var(--font-family);
        font-size: 13px;
        font-weight: 400;
        color: rgba(255, 255, 255, 0.85);
        caret-color: rgba(255, 255, 255, 0.7);
        min-width: 0;
        height: 60px;
        resize: none;
        padding: 4px 0;
        line-height: 1.4;
      }

      .context-text-input::placeholder {
        color: rgba(255, 255, 255, 0.3);
      }

      .context-send-btn {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 32px;
        height: 32px;
        border-radius: 50%;
        background: none;
        border: none;
        cursor: pointer;
        color: #22d3ee;
        flex-shrink: 0;
        transition: background 0.15s ease;
      }

      .context-send-btn:hover {
        background: rgba(34, 211, 238, 0.15);
      }

      /* ── EXPANSION MODE TOGGLE (Factual ⟷ Creative) ── */
      .context-mode-row {
        display: flex;
        align-items: center;
        gap: 10px;
        padding: 11px 12px 3px 16px;
      }
      .context-mode-label {
        font-size: 10.5px;
        font-weight: 600;
        letter-spacing: 0.06em;
        text-transform: uppercase;
        color: rgba(255, 255, 255, 0.4);
      }
      .mode-toggle {
        display: inline-flex;
        gap: 2px;
        padding: 3px;
        background: rgba(255, 255, 255, 0.06);
        border: 1px solid rgba(255, 255, 255, 0.08);
        border-radius: 999px;
      }
      .mode-toggle-btn {
        border: none;
        background: none;
        cursor: pointer;
        padding: 5px 14px;
        border-radius: 999px;
        font-family: var(--font-family);
        font-size: 12px;
        font-weight: 600;
        color: rgba(255, 255, 255, 0.55);
        transition: color 0.18s ease, background 0.18s ease, box-shadow 0.18s ease;
      }
      .mode-toggle-btn:hover { color: rgba(255, 255, 255, 0.85); }
      .mode-toggle-btn--active {
        background: rgba(34, 211, 238, 0.16);
        color: var(--cyan-bright);
        box-shadow: inset 0 0 0 1px rgba(34, 211, 238, 0.32);
      }

      /* ── CONTEXT INPUT OPEN STATE ── */
      .context-bar-group.context-input-open .ctx-icon-row {
        height: 0;
        opacity: 0;
        padding-top: 0;
        padding-bottom: 0;
        pointer-events: none;
      }

      .context-bar-group.context-input-open .context-input-panel-inner {
        grid-template-rows: 1fr;
        opacity: 1;
        pointer-events: auto;
      }

      .context-bar-group.context-input-open .chip-tray {
        opacity: 0;
        pointer-events: none;
        transition: opacity 0.18s ease;
      }

      /* ── CHIP TRAY ── */
      .chip-tray {
        display: flex;
        flex-wrap: wrap;
        gap: 6px;
        width: 0;
        min-width: 100%;
      }

      .chip-tray:empty { display: none; }

      /* ── CONTEXT TOOLTIP ── */
      .context-tooltip {
        text-align: center;
        font-family: var(--font-family);
        font-size: 11px;
        font-weight: 500;
        letter-spacing: 0.08em;
        text-transform: uppercase;
        color: rgba(34, 211, 238, 0.75);
        text-shadow: 0 0 8px rgba(34, 211, 238, 0.35);
        opacity: 0;
        transform: translateY(-2px);
        transition: opacity 0.18s ease, transform 0.18s ease;
        pointer-events: none;
        margin-top: 4px;
        min-height: 16px;
      }

      .context-tooltip.visible {
        opacity: 1;
        transform: translateY(0);
      }

      .file-chip {
        display: inline-flex;
        align-items: center;
        gap: 5px;
        height: 28px;
        padding: 0 8px 0 8px;
        background: rgba(255, 255, 255, 0.06);
        backdrop-filter: blur(24px) saturate(160%);
        border: 1px solid rgba(255, 255, 255, 0.14);
        border-radius: 9999px;
        font-family: var(--font-family);
        font-size: 12px;
        font-weight: 400;
        color: rgba(255, 255, 255, 0.58);
        white-space: nowrap;
        cursor: default;
        box-shadow: 0 2px 8px rgba(0,0,0,0.25);
      }

      .chip-remove {
        display: flex;
        align-items: center;
        justify-content: center;
        width: 14px;
        height: 14px;
        border-radius: 50%;
        border: none;
        background: none;
        color: rgba(255, 255, 255, 0.35);
        cursor: pointer;
        padding: 0;
        margin-left: 2px;
        flex-shrink: 0;
        opacity: 0;
        transition: opacity 0.15s ease, color 0.15s ease;
      }

      .file-chip:hover .chip-remove {
        opacity: 1;
      }

      .chip-remove:hover {
        color: rgba(255, 255, 255, 0.9);
      }

      /* ── BREADCRUMB ── */
      .breadcrumb-bar {
        position: fixed;
        bottom: 40px;
        left: 50%;
        transform: translateX(-50%);
        display: flex;
        align-items: center;
        z-index: 250;
        pointer-events: auto;
        opacity: 0;
        transition: opacity 0.3s ease;
        /* Soft dark "cloud" behind the crumbs — sized by the flex content, so it
           grows and shrinks proportionately with the breadcrumb trail. The wide,
           colour-matched box-shadow gives it hazy, cloud-like edges. */
        padding: 14px 30px;
        border-radius: 999px;
        background: rgba(11, 14, 22, 0.55);
        backdrop-filter: blur(16px) saturate(140%);
        -webkit-backdrop-filter: blur(16px) saturate(140%);
        box-shadow:
          0 0 46px 26px rgba(11, 14, 22, 0.45),
          0 14px 40px -10px rgba(0, 0, 0, 0.5);
      }

      .breadcrumb-bar.visible { opacity: 1; }

      .bc-item {
        position: relative;
        display: flex;
        align-items: center;
        justify-content: center;
        flex-shrink: 0;
      }

      .bc-label {
        position: absolute;
        bottom: calc(100% + 8px);
        left: 50%;
        transform: translateX(-50%);
        font-family: var(--font-family);
        font-size: 11.5px;
        font-weight: 500;
        color: rgba(255, 255, 255, 0.65);
        white-space: normal;
        text-align: center;
        max-width: 160px;
        word-wrap: break-word;
        overflow-wrap: break-word;
        pointer-events: none;

        /* Clamp to 2 lines max with ellipsis */
        display: -webkit-box;
        -webkit-line-clamp: 2;
        -webkit-box-orient: vertical;
        overflow: hidden;
        text-overflow: ellipsis;
        line-height: 1.3;
        max-height: 2.6em;
      }

      .bc-circle {
        width: 22px;
        height: 22px;
        border-radius: 50%;
        border: 1.5px solid rgba(255, 255, 255, 0.32);
        background: transparent;
        cursor: pointer;
        box-sizing: border-box;
        transition: border-color 0.2s ease;
        flex-shrink: 0;
      }

      .bc-circle:hover { border-color: rgba(255, 255, 255, 0.65); }

      .bc-item.bc-active .bc-circle {
        border: 2px solid #22d3ee;
        box-shadow: 0 0 10px rgba(34, 211, 238, 0.35);
      }

      /* Root crumb — mirror the root node's yellow dashed circle */
      .bc-item--root .bc-circle {
        border: 2px dashed var(--yellow-bright);
        box-shadow: 0 0 10px var(--yellow-glow);
      }
      .bc-item--root .bc-circle:hover {
        border-color: var(--yellow-bright);
      }
      /* An active root keeps the yellow dash but adds a cyan halo */
      .bc-item.bc-active.bc-item--root .bc-circle {
        border: 2px dashed var(--yellow-bright);
        box-shadow: 0 0 12px rgba(34, 211, 238, 0.45), 0 0 8px var(--yellow-glow);
      }

      .bc-connector {
        width: 128px;
        height: 1.5px;
        background: rgba(255, 255, 255, 0.22);
        flex-shrink: 0;
      }

      /* Bridge node: common nodes merged, branches split and merge dynamically */
      .breadcrumb-bar--merged {
        display: flex;
        align-items: center;
        flex-direction: row !important;
        gap: 0;
        padding: 18px 36px; /* expanded padding for the split structure */
        border-radius: 28px;
      }

      .bc-section {
        display: flex;
        align-items: center;
      }

      .bc-split-rows-container {
        display: flex;
        flex-direction: column;
        gap: 36px; /* Sizable gap between parallel branches to prevent text collision */
        position: relative;
      }

      .bc-split-row {
        display: flex;
        align-items: center;
      }

      .bc-branch-fork {
        width: 32px;
        height: 80px;
        align-self: center;
        display: flex;
        align-items: center;
        justify-content: center;
        flex-shrink: 0;
      }

      .bc-branch-fork--left {
        margin-right: 4px;
        margin-left: 4px;
      }

      .bc-branch-fork--right {
        margin-left: 4px;
        margin-right: 4px;
      }

      /* ── STICKY NOTES ── */
      .sticky-note {
        position: fixed;
        width: 210px;
        height: 210px;
        border-radius: 2px;
        display: flex;
        flex-direction: column;
        box-shadow: 5px 7px 24px rgba(0,0,0,0.38), 2px 3px 8px rgba(0,0,0,0.22);
        z-index: 160;
        cursor: grab;
        user-select: none;
        transform-origin: center center;
      }

      .sticky-note:active { cursor: grabbing; }
      .sticky-note.is-dragging { cursor: grabbing; box-shadow: 8px 12px 32px rgba(0,0,0,0.5); }

      .sticky-note--teal   { background: linear-gradient(145deg, #22c4d2 0%, #0a9baa 100%); }
      .sticky-note--yellow { background: linear-gradient(145deg, #f0b800 0%, #d09600 100%); }
      .sticky-note--purple { background: linear-gradient(145deg, #c428d8 0%, #9e16b0 100%); }

      .sticky-note-drag-handle {
        height: 22px;
        flex-shrink: 0;
        cursor: grab;
      }

      .sticky-note.is-dragging .sticky-note-drag-handle { cursor: grabbing; }

      .note-btn {
        position: absolute;
        width: 22px;
        height: 22px;
        border-radius: 50%;
        background: rgba(0, 0, 0, 0.22);
        border: none;
        color: rgba(255, 255, 255, 0.8);
        cursor: pointer;
        display: flex;
        align-items: center;
        justify-content: center;
        transition: background 0.15s ease, opacity 0.15s ease;
        padding: 0;
      }

      .note-btn:hover { background: rgba(0, 0, 0, 0.42); color: #fff; }

      .note-delete-btn {
        top: 6px;
        right: 6px;
        opacity: 0;
      }

      .sticky-note:hover .note-delete-btn { opacity: 1; }

      .note-expand-btn {
        bottom: 8px;
        left: 50%;
        transform: translateX(-50%);
        opacity: 0.45;
      }

      .sticky-note:hover .note-expand-btn { opacity: 1; }

      .sticky-note textarea {
        flex: 1;
        background: none;
        border: none;
        outline: none;
        resize: none;
        font-family: var(--font-family);
        font-size: 13px;
        font-weight: 400;
        line-height: 1.5;
        color: rgba(255, 255, 255, 0.82);
        padding: 0 12px 12px 12px;
        cursor: text;
        user-select: text;
      }

      .sticky-note textarea::placeholder {
        color: rgba(255, 255, 255, 0.45);
      }

      /* ── SEARCH BAR ── */
      .search-bar-wrapper {
        position: fixed;
        top: 48px;
        left: 120px; /* room for the drawer toggle at 48px */
        z-index: 200;
        display: flex;
        align-items: center;
      }

      .search-bar {
        display: flex;
        align-items: center;
        height: 58px;
        background: #f5a800;
        border-radius: 9999px;
        padding: 0 18px 0 20px;
        box-shadow: 0 8px 32px rgba(0, 0, 0, 0.45), 0 2px 8px rgba(0, 0, 0, 0.3);
        overflow: hidden;
        /* Width animates between contracted (58px) and expanded (accounts for 120px left margin + 120px right margin) */
        width: calc(100vw - 240px);
        transition: width 0.55s cubic-bezier(0.16, 1, 0.3, 1),
                    border-radius 0.55s cubic-bezier(0.16, 1, 0.3, 1),
                    padding 0.55s cubic-bezier(0.16, 1, 0.3, 1);
      }

      .search-bar.contracted {
        width: 58px;
        padding: 0 0 0 0;
        justify-content: center;
      }

      .search-icon-left {
        display: none;
      }

      .search-input {
        flex: 1;
        border: none;
        background: transparent;
        outline: none;
        font-family: var(--font-family);
        font-size: 36px;
        font-weight: 600;
        letter-spacing: 0.08em;
        text-transform: uppercase;
        color: rgba(0, 0, 0, 0.75);
        caret-color: rgba(0, 0, 0, 0.8);
        min-width: 0;
        transition: opacity 0.25s ease;
        white-space: nowrap;
        overflow: hidden;
      }

      .search-input::placeholder {
        color: rgba(0, 0, 0, 0.32);
      }

      .search-bar.contracted .search-input {
        opacity: 0;
        pointer-events: none;
        width: 0;
        flex: 0;
      }

      .search-icon-right {
        display: flex;
        align-items: center;
        justify-content: center;
        flex-shrink: 0;
        background: none;
        border: none;
        cursor: pointer;
        margin-left: 8px;
        color: #1a1000;
        opacity: 0.55;
        transition: opacity 0.25s ease;
      }

      .search-icon-right:hover {
        opacity: 0.85;
      }

      .search-bar.contracted .search-icon-right {
        margin-left: 0;
      }

      /* Icon dims down after contraction settles */
      .search-bar.contracted.dimmed .search-icon-right {
        opacity: 0.28;
      }

      .search-bar.contracted.dimmed .search-icon-right:hover {
        opacity: 0.75;
      }

      /* Root node fade-in when query is submitted */
      #root-node { transition: opacity 0.5s ease; }

      /* Animations */
      @keyframes slow-spin {
        from { transform: translate(-50%, -50%) rotate(0deg); }
        to   { transform: translate(-50%, -50%) rotate(360deg); }
      }

      @keyframes fast-spin {
        from { transform: translate(-50%, -50%) rotate(0deg); }
        to   { transform: translate(-50%, -50%) rotate(360deg); }
      }

      /* ── AI loading ring (child nodes) ── */
      .loading-ring {
        position: absolute;
        top: 50%;
        left: 50%;
        width: 280px;
        height: 280px;
        pointer-events: none;
        z-index: 1;
        opacity: 0;
        filter: drop-shadow(0 0 12px var(--cyan-glow));
        transition: opacity 0.35s ease;
      }

      /* Child nodes: show ring and spin when loading */
      .node--loading .loading-ring {
        opacity: 1;
        animation: fast-spin 3s linear infinite;
      }

      /* Root nodes already have the yellow-dashed-circle — hide the extra ring */
      .node--loading:has(.yellow-dashed-circle) .loading-ring {
        opacity: 0;
        animation: none;
      }

      /* Root nodes: yellow circle → cyan + faster spin while loading */
      .node--loading .yellow-dashed-circle {
        animation: fast-spin 3s linear infinite;
        filter: drop-shadow(0 0 18px var(--cyan-glow));
      }
      .node--loading .yellow-dashed-circle circle {
        stroke: var(--cyan-bright);
      }

      @keyframes auto-bridge-pulse {
        0%   { box-shadow: 0 0 0 0px  rgba(34, 211, 238, 0.85); }
        60%  { box-shadow: 0 0 0 22px rgba(34, 211, 238, 0); }
        100% { box-shadow: 0 0 0 22px rgba(34, 211, 238, 0); }
      }
      .node--auto-bridge .glass-circle {
        animation: auto-bridge-pulse 1.1s ease-out 3;
      }

      .node--prefetched {
        filter: drop-shadow(0 0 10px rgba(34, 211, 238, 0.28));
        transition: filter 0.6s ease;
      }

      /* ─── AUTOSAVE TOAST ─── */
      .autosave-toast {
        position: fixed;
        top: 24px;
        left: 50%;
        transform: translateX(-50%) translateY(-12px);
        background: rgba(15, 23, 42, 0.92);
        backdrop-filter: blur(12px);
        -webkit-backdrop-filter: blur(12px);
        border: 1px solid rgba(255, 255, 255, 0.12);
        color: #e2e8f0;
        font-size: 13px;
        font-weight: 500;
        padding: 10px 18px;
        border-radius: 999px;
        z-index: 999;
        opacity: 0;
        pointer-events: none;
        transition: opacity 0.35s ease, transform 0.35s ease;
        white-space: nowrap;
      }
      .autosave-toast.visible {
        opacity: 1;
        transform: translateX(-50%) translateY(0);
      }

      /* ─── GHOST SELECTION HINT ─── */
      #ghost-hint {
        position: fixed;
        bottom: 32px;
        left: 50%;
        transform: translateX(-50%) translateY(12px);
        background: rgba(15, 23, 42, 0.92);
        backdrop-filter: blur(12px);
        -webkit-backdrop-filter: blur(12px);
        border: 1px solid rgba(255, 255, 255, 0.12);
        color: #cbd5e1;
        font-size: 13px;
        font-weight: 500;
        padding: 10px 18px;
        border-radius: 999px;
        z-index: 200;
        opacity: 0;
        pointer-events: none;
        transition: opacity 0.3s ease, transform 0.3s ease;
        white-space: nowrap;
      }
      #ghost-hint.visible {
        opacity: 1;
        transform: translateX(-50%) translateY(0);
      }
      #ghost-hint .ghost-hint-count {
        color: var(--cyan-bright);
        font-weight: 600;
      }

      /* ─── CANVAS (pan/zoom container) ─── */
      /* ─── DOT GRID LAYER ─── */
      /* Layers 1-2: near dot grid. Layer 3: far parallax grid — bigger, fainter
         dots that pan/zoom slower (see updateGridBackground). Lives on its own
         fixed layer so the radial mask below fades the dots toward the viewport
         edges: the mask is anchored to the viewport, so as the dots pan the fade
         stays centred and reads as a continuous edge falloff. */
      #grid-bg {
        position: fixed;
        inset: 0;
        z-index: 0;
        pointer-events: none;
        /* The inner layers are oversized so a translate never exposes an edge;
           this clips them back to the viewport. */
        overflow: hidden;
        -webkit-mask-image: radial-gradient(
          ellipse 75% 75% at 50% 50%,
          #000 30%,
          transparent 92%
        );
        mask-image: radial-gradient(
          ellipse 75% 75% at 50% 50%,
          #000 30%,
          transparent 92%
        );
      }

      /* Both dot layers: oversized by more than the largest tile (grid tops out
         near 95px, the far layer near 115px at max zoom) so translating by up to
         one tile in any direction still covers the viewport. */
      #grid-layer-near,
      #grid-layer-far {
        position: absolute;
        inset: -128px;
        pointer-events: none;
        will-change: transform;
      }

      /* Near layer — the two bright dot grids, offset half a tile from each other. */
      #grid-layer-near {
        background-image:
          radial-gradient(rgba(255, 255, 255, 0.2) 2px, transparent 2px),
          radial-gradient(rgba(255, 255, 255, 0.2) 2px, transparent 2px);
        background-size:
          64px 64px,
          64px 64px;
        background-position:
          0 0,
          32px 32px;
      }

      /* Far layer — dimmer, larger, and parallaxes more slowly. */
      #grid-layer-far {
        background-image: radial-gradient(
          rgba(255, 255, 255, 0.07) 3px,
          transparent 3px
        );
        background-size: 96px 96px;
        background-position: 0 0;
      }

      #canvas {
        position: fixed;
        inset: 0;
        overflow: visible;
      }

      #canvas-content {
        width: 100%;
        height: 100%;
        transform-origin: 0 0;
        /* Panning and zooming rewrite this element's transform every frame. Without
           a promotion hint the compositor has no separate layer to move, so each
           frame re-rasterises the painted subtree — ~14,000 elements' worth of
           box-shadows, SVG edges and node art — instead of translating a texture
           that is already on the GPU. Off-screen nodes are visibility:hidden, so
           the layer only ever covers what is actually painted. */
        will-change: transform;
      }

      /* ─── VIGNETTE ─── */
      #vignette {
        position: fixed;
        inset: 0;
        pointer-events: none;
        z-index: 90;
        background: radial-gradient(
          ellipse 75% 75% at 50% 50%,
          transparent 40%,
          rgba(0, 0, 0, 0.41) 80%,
          rgba(0, 0, 0, 0.62) 100%
        );
      }

      /* Stronger "zoomed-in" vignette lives on a stacked layer so it can be
         eased in via opacity (radial-gradient backgrounds don't transition,
         they snap). Fades in/out when body.zoom-vignette toggles past 80%. */
      #vignette::after {
        content: "";
        position: absolute;
        inset: 0;
        pointer-events: none;
        background: radial-gradient(
          ellipse 60% 60% at 50% 50%,
          transparent 21%,
          rgba(0, 0, 0, 0.59) 65%,
          rgba(0, 0, 0, 0.73) 100%
        );
        opacity: 0;
        transition: opacity 1.6s ease;
      }

      body.zoom-vignette #vignette::after {
        opacity: 1;
      }

      /* ─── NODE LOCKED STATE ─── */
      .node--locked .purple-node-base {
        border: 2px solid rgba(250, 204, 21, 0.6) !important;
        box-shadow:
          0 12px 36px -8px rgba(0, 0, 0, 0.7),
          inset 0 2px 8px rgba(0, 0, 0, 0.5),
          0 0 18px rgba(250, 204, 21, 0.35) !important;
      }

      .node--locked .btn-steering {
        color: rgba(250, 204, 21, 0.9) !important;
        filter: drop-shadow(0 0 6px rgba(250, 204, 21, 0.7));
      }

      /* ─── CONNECTION SOURCE STATE ─── */
      .connect-source .glass-circle {
        outline: 2px solid rgba(34, 211, 238, 0.7) !important;
        box-shadow:
          inset 0 2.5px 3px rgba(255, 255, 255, 0.45),
          0 0 0 4px rgba(34, 211, 238, 0.18),
          0 0 30px rgba(34, 211, 238, 0.4) !important;
      }

      /* ─── ISOLATION MODE ─── */
      .node-isolated-dim {
        opacity: 0.04 !important;
        pointer-events: none !important;
        transition: opacity 0.4s ease !important;
      }

      /* ─── DEPTH SCALING ─── */
      .node-wrapper.dynamic {
        transform-origin: center center;
      }

      /* ─── CURSOR STATES ─── */
      body.is-panning {
        cursor: grabbing !important;
      }

      body.connect-mode {
        cursor: crosshair !important;
      }

      /* ─── GHOST NODES (preview before commit) ─── */
      .node--ghost {
        opacity: 0.45;
        pointer-events: none; /* glass-pill-bg re-enables below */
      }
      .node--ghost .glass-pill-bg {
        pointer-events: none;
      }
      .node--ghost .control-icon,
      .node--ghost .btn-delete,
      .node--ghost .btn-isolate,
      .node--ghost .btn-steering {
        display: none;
      }
      /* Allow dragging ghost nodes to reposition them */
      .node--ghost {
        pointer-events: auto;
        cursor: grab;
      }

      /* Ghost node picked for selective commit */
      .node--ghost-selected {
        opacity: 0.9 !important;
      }
      .node--ghost-selected .glass-circle {
        box-shadow: 0 0 0 3px rgba(34, 211, 238, 0.9), 0 0 18px rgba(34, 211, 238, 0.45);
      }

      /* ─── RETRACTING NODES (pulled back by physics) ─── */
      .node--retracting {
        opacity: 0.25;
        pointer-events: none;
        transition: opacity 0.25s ease;
      }
      .node--retracting .glass-circle {
        transform: translate(-50%, -50%) scale(0.5);
        transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);
      }
      .node--retracting .purple-node-base {
        transform: translate(-50%, -50%) scale(0.5);
        transition: transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);
      }

      .sticky-note.node--retracting {
        opacity: 0.25;
        pointer-events: none;
      }

      /* ─── EDGE TUNNEL BUTTONS ─── */
      .edge-tunnel-btn {
        opacity: 0;
        pointer-events: none;
        transition: opacity 0.18s ease;
      }
      .edge-tunnel-btn .tunnel-pill {
        transition: width 0.22s cubic-bezier(0.34, 1.56, 0.64, 1),
                    x 0.22s cubic-bezier(0.34, 1.56, 0.64, 1);
      }
      /* Hover keeps the frosted-glass look — no colour shift, just a slightly
         brighter translucent pill and a lighter neutral edge/chevron */
      .edge-tunnel-btn:hover .tunnel-pill {
        fill: rgba(40, 52, 74, 0.92) !important;
        stroke: rgba(255, 255, 255, 0.32) !important;
      }
      .edge-tunnel-btn:hover path {
        stroke: #e2e8f0 !important;
      }
      .edge-tunnel-btn .tunnel-chevron {
        transition: transform 0.22s cubic-bezier(0.34, 1.56, 0.64, 1);
      }
      .edge-tunnel-btn .tunnel-label {
        font-family: 'Outfit', sans-serif;
        font-size: 11px;
        font-weight: 500;
        fill: #cbd5e1;
        transition: opacity 0.12s ease;
        pointer-events: none;
        user-select: none;
      }

      /* ─── VIEWPORT TOOLBAR (right side) ─── */
      .left-toolbar {
        position: fixed;
        top: 122px; /* aligned with old search-bar offset */
        right: 48px;
        display: flex;
        flex-direction: column;
        /* Right-align so a hovered button expands LEFTWARD (its right edge stays
           put) instead of stretching every button in the column. */
        align-items: flex-end;
        gap: 8px;
        z-index: 200;
      }

      /* Icon-only at rest; on hover the button grows left and reveals its label
         to the left of the icon (replaces native title tooltips). The icon sits
         in a fixed 46px slot pinned to the right so it never shifts. */
      .toolbar-btn {
        min-width: 46px;
        max-width: 46px;
        width: auto;
        height: 46px;
        padding: 0;
        border-radius: 12px;
        border: 1px solid rgba(255, 255, 255, 0.1);
        background: rgba(15, 18, 30, 0.72);
        backdrop-filter: blur(12px);
        -webkit-backdrop-filter: blur(12px);
        color: rgba(255, 255, 255, 0.4);
        cursor: pointer;
        display: flex;
        flex-direction: row;
        align-items: center;
        justify-content: flex-end;
        overflow: hidden;
        white-space: nowrap;
        transition:
          max-width 0.28s cubic-bezier(0.16, 1, 0.3, 1),
          background 0.2s ease,
          color 0.2s ease,
          border-color 0.2s ease;
      }

      .toolbar-btn__icon {
        flex: 0 0 46px;
        height: 46px;
        display: flex;
        align-items: center;
        justify-content: center;
      }

      .toolbar-btn__label {
        opacity: 0;
        padding: 0 2px 0 14px;
        font-family: var(--font-family);
        font-size: 13px;
        font-weight: 600;
        line-height: 1;
        color: inherit;
        transition: opacity 0.18s ease;
      }

      .toolbar-btn:hover {
        max-width: 340px;
        background: rgba(250, 204, 21, 0.08);
        color: var(--yellow-bright);
        border-color: rgba(250, 204, 21, 0.4);
      }

      .toolbar-btn:hover .toolbar-btn__label {
        opacity: 1;
      }

      .toolbar-btn.active {
        background: rgba(34, 211, 238, 0.12);
        color: #22d3ee;
        border-color: rgba(34, 211, 238, 0.4);
      }

      .toolbar-divider {
        width: 26px;
        height: 1px;
        align-self: center;
        margin: 2px 0;
        background: rgba(255, 255, 255, 0.12);
      }

      /* ─── MARQUEE SELECTION ─── */
      .marquee-rect {
        position: fixed;
        border: 1.5px dashed rgba(34, 211, 238, 0.7);
        background: rgba(34, 211, 238, 0.04);
        pointer-events: none;
        z-index: 9000;
        border-radius: 3px;
      }

      body.marquee-mode,
      body.marquee-mode .node-wrapper,
      body.marquee-mode #canvas,
      body.marquee-mode #canvas-content {
        cursor: crosshair !important;
      }

      .node--selected .glass-circle {
        box-shadow:
          0 0 0 2px rgba(34, 211, 238, 0.7),
          0 0 24px rgba(34, 211, 238, 0.25) !important;
      }

      /* Hover & Selection visual elevation overrides */
      .node-wrapper.node--selected,
      .node-wrapper.is-expanded,
      .sticky-note.is-dragging {
        z-index: 1000 !important;
      }
      .node-wrapper:hover,
      .sticky-note:hover {
        z-index: 500 !important;
      }

      /* Hover & Selection typographic weight overrides */
      .node-wrapper:hover .glass-input-field,
      .node-wrapper.is-expanded .glass-input-field,
      .node-wrapper.node--selected .glass-input-field,
      .sticky-note:hover textarea,
      .sticky-note.is-dragging textarea {
        font-weight: 700 !important;
      }

      /* On hover, lift the label to full brightness regardless of the
         depth-graded dim colour written inline by the physics update loop.
         !important is required to beat the inline style. */
      .node-wrapper:hover .glass-input-field {
        color: rgba(255, 255, 255, 1) !important;
      }

      /* The physics loop also fades the whole wrapper by lineage depth
         (node.style.opacity), which composites over the label — so white text
         on a deep node still reads grey. Restore full opacity while hovered so
         the text can actually reach full brightness. No transition here: the
         loop animates this opacity per-frame and a transition would lag it. */
      .node-wrapper:hover {
        opacity: 1 !important;
      }

      /* ─── GROUP ZONE ─── */
      .group-zone {
        position: absolute;
        border-radius: 50%;
        background: rgba(100, 120, 255, 0.04);
        cursor: grab;
        z-index: 0;
        transition: background 0.2s ease;
      }

      .group-zone:hover {
        background: rgba(100, 120, 255, 0.07);
      }

      .group-zone:hover .group-zone__ring circle {
        stroke: rgba(160, 180, 255, 0.65);
      }

      .group-zone:active {
        cursor: grabbing;
      }

      .group-zone__ring {
        position: absolute;
        inset: 0;
        width: 100%;
        height: 100%;
        pointer-events: none;
        animation: group-ring-spin 140s linear infinite;
        transform-origin: 50% 50%;
      }

      @keyframes group-ring-spin {
        to { transform: rotate(360deg); }
      }

      .group-zone__label {
        position: absolute;
        top: 14%;
        left: 50%;
        transform: translateX(-50%);
        /* Reduced by 0.4rem so groups sit below roots in the visual hierarchy. */
        font-size: calc(11px - 0.4rem);
        font-weight: 600;
        color: rgba(160, 180, 255, 0.55);
        letter-spacing: 0.08em;
        text-transform: uppercase;
        outline: none;
        cursor: text;
        min-width: 20px;
        text-align: center;
        white-space: nowrap;
        transition: color 0.3s ease, opacity 0.3s ease;
      }

      /* Faint pulse while the AI is (re)naming the group */
      .group-zone__label--naming {
        animation: group-naming-pulse 1.1s ease-in-out infinite;
      }
      @keyframes group-naming-pulse {
        0%, 100% { opacity: 0.4; }
        50%      { opacity: 0.85; }
      }

      /* ─── COLLAPSED GROUP (zoomed out) ─── */
      /* Members are hidden; the group reads as a single node with just its name. */
      .node--group-hidden {
        opacity: 0 !important;
        pointer-events: none !important;
        transition: opacity 0.25s ease;
        /* opacity:0 still paints and composites every backdrop-filter layer
           underneath it. content-visibility tells the browser to skip rendering
           the subtree outright, which is what "invisible" should have meant. */
        content-visibility: hidden;
      }

      /* ── Motion-gated glass (perf — worst on macOS) ─────────────────────────
         Toggled by setGraphMoving() in script.js while the graph is moving:
         physics running, or the user panning/zooming.

         backdrop-filter is the single most expensive thing on the canvas. The
         compositor snapshots what is behind the element and blurs it, per layer,
         per frame, and cannot cache that while anything underneath moves — so
         with two layers on every node and ~80 of them on screen it re-blurs the
         whole viewport many times over, every frame. On a Retina Mac each of
         those snapshots is 4x the pixels of a 1x display, which is why this bites
         hardest there.

         While moving, the glass falls back to a flat translucent fill of roughly
         the same value. The `background` transitions already on these elements
         make it a crossfade, and the full effect is back ~180ms after the graph
         settles — which is when there is actually something to look at. */
      body.graph-moving .glass-circle,
      body.graph-moving .glass-input-field,
      body.graph-moving .glass-pill-bg {
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
      }
      /* Stand-in fills so the shapes keep their weight without the blur behind
         them. Each is the light gradient the element already had, over a dark
         translucent base: a real blur doesn't just soften the backdrop, it
         averages fine detail (grid dots, thin edges) out of existence, and the
         base is what reproduces that. Without it the glass reads as a hole. */
      body.graph-moving .glass-circle {
        background:
          linear-gradient(
            135deg,
            rgba(160, 180, 235, 0.16) 0%,
            rgba(130, 150, 210, 0.08) 50%,
            rgba(120, 140, 200, 0.06) 51%,
            rgba(150, 170, 225, 0.11) 100%
          ),
          radial-gradient(
            circle,
            rgba(24, 28, 48, 0.55) 0%,
            rgba(20, 24, 42, 0.45) 70%,
            rgba(18, 22, 38, 0.38) 100%
          );
      }
      body.graph-moving .glass-input-field {
        background:
          linear-gradient(
            148deg,
            rgba(255, 255, 255, 0.16) 0%,
            rgba(255, 255, 255, 0.05) 40%,
            rgba(200, 220, 255, 0.03) 100%
          ),
          linear-gradient(
            180deg,
            rgba(46, 52, 84, 0.82) 0%,
            rgba(34, 39, 66, 0.78) 100%
          );
      }
      body.graph-moving .glass-pill-bg {
        background:
          linear-gradient(
            135deg,
            rgba(150, 165, 215, 0.15) 0%,
            rgba(120, 135, 185, 0.07) 50%,
            rgba(110, 125, 175, 0.05) 51%,
            rgba(140, 155, 205, 0.1) 100%
          ),
          linear-gradient(
            180deg,
            rgba(24, 28, 48, 0.5) 0%,
            rgba(20, 24, 42, 0.42) 100%
          );
      }

      /* ── Off-screen nodes (perf) ────────────────────────────────────────────
         Set by updateNodeCulling(). content-visibility:hidden makes the browser
         skip style, layout, paint AND compositing for the whole subtree — which
         is where the two backdrop-filter layers per node live. Positions are
         still driven by physics, so a culled node reappears correctly the moment
         it scrolls back into view. */
      .node--offscreen {
        /* visibility:hidden (not content-visibility, not display:none) is the
           sweet spot: it skips paint AND compositing for the subtree — so the two
           backdrop-filter layers per node cost nothing — while being far cheaper
           to toggle than anything that changes layout or containment. */
        visibility: hidden;
        pointer-events: none;
      }
      .group-zone--collapsed {
        background: radial-gradient(
          circle,
          rgba(100, 120, 255, 0.12) 0%,
          rgba(100, 120, 255, 0.05) 60%,
          transparent 100%
        );
      }
      .group-zone--collapsed .group-zone__ring circle {
        stroke: rgba(170, 188, 255, 0.7);
        stroke-dasharray: none;
      }
      .group-zone--collapsed .group-zone__label {
        top: 50%;
        color: rgba(214, 224, 255, 0.96);
        text-shadow: 0 2px 12px rgba(0, 0, 0, 0.6);
        transform-origin: center center;
      }
      .group-zone--collapsed .group-zone__delete,
      .group-zone--collapsed .group-zone__expand {
        opacity: 0 !important;
        pointer-events: none !important;
      }

      .group-zone__delete {
        position: absolute;
        top: 8px;
        right: 8px;
        background: rgba(255, 255, 255, 0.05);
        border: 1px solid rgba(255, 255, 255, 0.08);
        border-radius: 50%;
        color: rgba(255, 255, 255, 0.6);
        font-size: 20px;
        width: 24px;
        height: 24px;
        display: flex;
        align-items: center;
        justify-content: center;
        cursor: pointer;
        opacity: 0.65;
        transition: opacity 0.15s ease, color 0.15s ease, background 0.15s ease, border-color 0.15s ease;
        line-height: 1;
        padding: 0 0 3px 0; /* Center multiplication glyph vertically */
        box-sizing: border-box;
      }

      .group-zone:hover .group-zone__delete {
        opacity: 1;
      }

      .group-zone__delete:hover {
        color: #ffffff;
        background: rgba(239, 68, 68, 0.65);
        border-color: rgba(239, 68, 68, 0.8);
      }

      /* Group "unified node" expand button — grows concepts from the group edge */
      .group-zone__expand {
        position: absolute;
        bottom: 10px;
        left: 50%;
        transform: translateX(-50%);
        display: flex;
        align-items: center;
        justify-content: center;
        width: 34px;
        height: 34px;
        border-radius: 50%;
        border: 1px solid rgba(160, 180, 255, 0.4);
        background: rgba(20, 26, 46, 0.82);
        backdrop-filter: blur(10px);
        -webkit-backdrop-filter: blur(10px);
        color: rgba(180, 196, 255, 0.85);
        cursor: pointer;
        opacity: 0;
        transition: opacity 0.15s ease, background 0.15s ease, color 0.15s ease,
          transform 0.15s ease;
      }
      .group-zone:hover .group-zone__expand {
        opacity: 1;
      }
      .group-zone__expand:hover {
        background: rgba(100, 120, 255, 0.28);
        color: #cdd7ff;
        transform: translateX(-50%) scale(1.1);
      }
      .group-zone__expand--loading {
        opacity: 1 !important;
        animation: group-expand-pulse 1s ease-in-out infinite;
        pointer-events: none;
      }
      @keyframes group-expand-pulse {
        0%, 100% { opacity: 0.4; }
        50%      { opacity: 1; }
      }

      /* ─── OFF-SCREEN ROOT INDICATORS ─── */
      #root-indicator-layer {
        position: fixed;
        inset: 0;
        pointer-events: none;
        z-index: 210;
      }
      .root-indicator {
        position: absolute;
        transform: translate(-50%, -50%);
        display: flex;
        align-items: center;
        gap: 7px;
        max-width: 180px;
        padding: 6px 12px 6px 10px;
        border-radius: 999px;
        border: 1.5px dashed var(--yellow-bright);
        background: rgba(15, 18, 30, 0.82);
        backdrop-filter: blur(12px);
        -webkit-backdrop-filter: blur(12px);
        box-shadow: 0 0 16px var(--yellow-glow), 0 8px 24px -8px rgba(0, 0, 0, 0.6);
        color: #f1f5f9;
        font-family: var(--font-family);
        cursor: pointer;
        pointer-events: auto;
        transition: transform 0.12s ease, background 0.15s ease;
      }
      .root-indicator:hover {
        background: rgba(30, 35, 55, 0.92);
        transform: translate(-50%, -50%) scale(1.06);
      }
      .root-ind-arrow {
        display: inline-block;
        font-size: 13px;
        line-height: 1;
        color: var(--yellow-bright);
        filter: drop-shadow(0 0 4px var(--yellow-glow));
      }
      .root-ind-label {
        font-size: 12px;
        font-weight: 500;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
      }

      /* ─── NODE BACKGROUND IMAGES ─── */
      .node-bg-image {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        object-fit: cover;
        opacity: 0;
        transition: opacity 0.5s ease, filter 0.3s ease, transform 0.3s ease;
        z-index: 1;
        pointer-events: none;
      }

      .node-bg-overlay {
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        background: rgba(0, 0, 0, 0.45);
        opacity: 0;
        transition: opacity 0.5s ease, background-color 0.3s ease;
        z-index: 2;
        pointer-events: none;
      }

      .node-wrapper:hover .node-bg-overlay {
        background: rgba(0, 0, 0, 0.25);
      }

      /* ─── SENSITIVE-IMAGE CENSORING ─── */
      /* A single resolved flag, data-blurred (set in applyNodeBlur), drives the
         blur — it composes the manual eye-toggle override with the automatic
         censor rule. The image is scaled up so the blur fully covers the circle
         with no soft transparent ring at the clipped edge. */
      .node-wrapper[data-blurred="true"] .node-bg-image {
        filter: blur(12px) saturate(0.6) brightness(0.75);
        transform: scale(1.25);
      }
      .node-wrapper[data-blurred="true"] .node-bg-overlay {
        background: rgba(0, 0, 0, 0.5);
      }
      /* Warning badge — only for images blurred because they were auto-flagged
         sensitive, not for a plain manual blur. Rendered via ::after on the base
         so no extra DOM is needed. */
      .node-wrapper[data-blurred="true"][data-sensitive="true"]
        .purple-node-base::after {
        content: "⚠ Sensitive";
        position: absolute;
        bottom: 14%;
        left: 50%;
        transform: translateX(-50%);
        z-index: 4;
        font-size: 7px;
        font-weight: 600;
        letter-spacing: 0.02em;
        white-space: nowrap;
        color: rgba(255, 255, 255, 0.92);
        background: rgba(0, 0, 0, 0.55);
        padding: 2px 6px;
        border-radius: 9999px;
        pointer-events: none;
      }

      /* Smooth opacity transitions for peek */
      .node-wrapper .glass-input-field,
      .node-wrapper .node-bg-overlay,
      .node-wrapper .btn-expand-pill,
      .node-wrapper .control-icon {
        transition: opacity 0.45s ease;
      }

      /* Bare label shown during peek — no container, just text floating on image */
      .node-peek-label {
        position: absolute;
        bottom: 16%;
        left: 50%;
        transform: translateX(-50%);
        font-size: 7.5px;
        font-weight: 500;
        letter-spacing: 0.09em;
        text-transform: uppercase;
        color: rgba(255, 255, 255, 0.82);
        text-shadow: 0 1px 4px rgba(0, 0, 0, 0.6);
        white-space: nowrap;
        overflow: hidden;
        max-width: 78%;
        text-overflow: ellipsis;
        pointer-events: none;
        opacity: 0;
        transition: opacity 0.4s ease;
        z-index: 20;
      }

      /* ─── PEEK INFO CARD (fixed top-right) ─── */
      #node-peek-card {
        position: fixed;
        top: 118px;
        right: 110px; /* clears the viewport toolbar column (right:48px, 46px wide) */
        width: 300px;
        max-width: 34vw;
        padding: 16px 18px;
        border-radius: 16px;
        background: rgba(15, 18, 30, 0.72);
        backdrop-filter: blur(20px) saturate(160%);
        -webkit-backdrop-filter: blur(20px) saturate(160%);
        border: 1px solid rgba(255, 255, 255, 0.1);
        box-shadow:
          inset 0 1px 1px rgba(255, 255, 255, 0.08),
          0 20px 48px -12px rgba(0, 0, 0, 0.6);
        color: #e2e8f0;
        z-index: 240;
        pointer-events: none;
        opacity: 0;
        transform: translateX(12px);
        transition: opacity 0.3s ease, transform 0.3s cubic-bezier(0.16, 1, 0.3, 1);
      }
      #node-peek-card.visible {
        opacity: 1;
        transform: translateX(0);
      }
      .peek-card-crumb {
        font-size: 10.5px;
        font-weight: 500;
        letter-spacing: 0.04em;
        text-transform: uppercase;
        color: #64748b;
        margin-bottom: 6px;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
      }
      .peek-card-title {
        font-size: 17px;
        font-weight: 600;
        color: #f1f5f9;
        margin-bottom: 8px;
        line-height: 1.25;
      }
      .peek-card-body {
        font-size: 13px;
        line-height: 1.6;
        color: #cbd5e1;
      }

      /* ─── PEEK IMAGE EXPAND (rounded full-image panel) ─── */
      .node-wrapper.node--peek-expanded {
        z-index: 60;
      }
      .node--peek-expanded .glass-circle {
        opacity: 0;
      }
      .node-wrapper.node--peek-expanded .purple-node-base {
        /* Scale is computed in JS so the panel reaches ~20% of the viewport
           regardless of canvas zoom or the node's depth scale. !important beats
           the :hover scale(1.03) rule, which is always active during a peek. */
        transform: translate(-50%, -50%) scale(var(--peek-expand-scale, 2)) !important;
        border-radius: 22px;
        overflow: hidden;
        transition:
          transform 0.4s cubic-bezier(0.16, 1, 0.3, 1),
          border-radius 0.4s ease;
      }
      .node--peek-expanded .node-bg-image {
        object-fit: contain;
        border-radius: 22px;
        background: #0b0f1a;
      }
      .node--peek-expanded .node-peek-label {
        font-size: 6px;
        bottom: 8%;
      }

      /* Persistent error badge — doesn't auto-dismiss, click retries */
      .node-error-badge {
        position: absolute;
        top: 6%;
        right: 8%;
        width: 22px;
        height: 22px;
        border-radius: 50%;
        border: 1.5px solid rgba(248, 113, 113, 0.85);
        background: rgba(30, 15, 15, 0.9);
        color: #f87171;
        font-size: 13px;
        font-weight: 700;
        line-height: 1;
        display: flex;
        align-items: center;
        justify-content: center;
        cursor: pointer;
        z-index: 25;
        animation: node-error-pulse 1.6s ease-in-out infinite;
      }
      .node-error-badge:hover {
        background: rgba(248, 113, 113, 0.25);
        transform: scale(1.12);
      }
      @keyframes node-error-pulse {
        0%, 100% { box-shadow: 0 0 0 0 rgba(248, 113, 113, 0.35); }
        50%      { box-shadow: 0 0 0 5px rgba(248, 113, 113, 0); }
      }

      /* ── SOURCE BADGE — which engine produced this node's children ── */
      .node-source-badge {
        position: absolute;
        top: calc(100% + 6px);
        left: 50%;
        transform: translateX(-50%);
        display: inline-flex;
        align-items: center;
        gap: 5px;
        padding: 3px 9px;
        border-radius: 999px;
        font-family: var(--font-family);
        font-size: 11px;
        font-weight: 600;
        white-space: nowrap;
        background: rgba(18, 22, 30, 0.88);
        border: 1px solid rgba(255, 255, 255, 0.12);
        color: rgba(255, 255, 255, 0.75);
        backdrop-filter: blur(8px);
        -webkit-backdrop-filter: blur(8px);
        z-index: 20;
        cursor: default;
      }
      .node-source-badge .src-dot {
        width: 7px;
        height: 7px;
        border-radius: 50%;
        background: currentColor;
        box-shadow: 0 0 6px currentColor;
        flex-shrink: 0;
      }
      .node-source-badge--wiki   { color: #34d399; border-color: rgba(52, 211, 153, 0.4); }
      .node-source-badge--groq   { color: var(--cyan-bright); border-color: rgba(34, 211, 238, 0.4); }
      .node-source-badge--ollama { color: #fbbf24; border-color: rgba(251, 191, 36, 0.45); }

      /* ── INTENT-MISMATCH SPEECH BUBBLE ── */
      .intent-bubble {
        position: absolute;
        bottom: calc(100% + 14px);
        left: 50%;
        transform: translateX(-50%);
        width: 250px;
        padding: 12px 13px;
        background: rgba(28, 32, 42, 0.97);
        border: 1px solid rgba(255, 255, 255, 0.12);
        border-radius: 14px;
        box-shadow: 0 16px 40px rgba(0, 0, 0, 0.55);
        backdrop-filter: blur(12px);
        -webkit-backdrop-filter: blur(12px);
        z-index: 40;
        animation: intent-pop 0.22s cubic-bezier(0.16, 1, 0.3, 1);
      }
      .intent-bubble::after {
        content: "";
        position: absolute;
        top: 100%;
        left: 50%;
        transform: translateX(-50%);
        border: 7px solid transparent;
        border-top-color: rgba(28, 32, 42, 0.97);
      }
      .intent-bubble-text {
        font-family: var(--font-family);
        font-size: 12.5px;
        line-height: 1.45;
        color: rgba(255, 255, 255, 0.9);
        margin-bottom: 10px;
      }
      .intent-bubble-actions {
        display: flex;
        flex-wrap: wrap;
        gap: 6px;
      }
      .intent-btn {
        border: none;
        cursor: pointer;
        padding: 6px 11px;
        border-radius: 8px;
        font-family: var(--font-family);
        font-size: 11.5px;
        font-weight: 600;
        background: rgba(255, 255, 255, 0.08);
        color: rgba(255, 255, 255, 0.8);
        transition: background 0.15s ease, color 0.15s ease;
      }
      .intent-btn:hover { background: rgba(255, 255, 255, 0.15); }
      .intent-btn--primary { background: rgba(34, 211, 238, 0.9); color: #06232b; }
      .intent-btn--primary:hover { background: var(--cyan-bright); }
      .intent-btn--ghost { background: none; color: rgba(255, 255, 255, 0.45); }
      .intent-btn--ghost:hover { background: rgba(255, 255, 255, 0.06); color: rgba(255, 255, 255, 0.7); }
      @keyframes intent-pop {
        from { opacity: 0; transform: translateX(-50%) translateY(6px) scale(0.96); }
        to   { opacity: 1; transform: translateX(-50%) translateY(0) scale(1); }
      }

      /* ── Connect mode ── */
      #canvas.canvas--connecting {
        cursor: crosshair;
      }
      .node--connect-source .glass-circle {
        box-shadow: 0 0 0 3px rgba(124, 58, 237, 0.7), 0 0 24px rgba(124, 58, 237, 0.4);
      }

      /* ── Graph search dim / match (1.15) ── */
      .node--search-dim  { opacity: 0.1 !important; transition: opacity 0.2s; }
      .node--search-match { opacity: 1   !important; transition: opacity 0.2s; }
      .node--search-match .glass-circle {
        box-shadow: 0 0 0 2px rgba(34, 211, 238, 0.7), 0 0 20px rgba(34, 211, 238, 0.35);
      }

      /* ── Isolation mode (1.3) ── */
      .node--isolated-out {
        opacity: 0.07 !important;
        pointer-events: none;
        transition: opacity 0.3s;
      }

      #isolation-exit-btn {
        position: fixed;
        top: 18px;
        left: 50%;
        transform: translateX(-50%) translateY(-10px);
        opacity: 0;
        pointer-events: none;
        z-index: 200;
        background: rgba(30, 41, 59, 0.92);
        border: 1px solid rgba(255,255,255,0.15);
        color: #e2e8f0;
        font-family: var(--font-family);
        font-size: 13px;
        padding: 7px 20px;
        border-radius: 20px;
        cursor: pointer;
        backdrop-filter: blur(8px);
        transition: background 0.2s, opacity 0.3s ease, transform 0.3s ease;
      }
      #isolation-exit-btn.visible {
        opacity: 1;
        pointer-events: auto;
        transform: translateX(-50%) translateY(0);
      }
      #isolation-exit-btn:hover { background: rgba(51, 65, 85, 0.95); }

      /* ── Left toolbar extra buttons (1.12 / 1.13 / 1.14) ── */
      .left-toolbar {
        gap: 8px;
      }

      /* ── Modal overlay (synthesis + shortcuts) ── */
      .modal-overlay {
        display: none;
        position: fixed;
        inset: 0;
        z-index: 300;
        background: rgba(0,0,0,0.55);
        backdrop-filter: blur(4px);
        align-items: center;
        justify-content: center;
      }
      .modal-overlay.visible { display: flex; }

      .modal-box {
        background: rgba(15, 23, 42, 0.97);
        border: 1px solid rgba(255,255,255,0.12);
        border-radius: 16px;
        width: min(600px, 92vw);
        max-height: 80vh;
        display: flex;
        flex-direction: column;
        overflow: hidden;
        box-shadow: 0 24px 60px rgba(0,0,0,0.6);
      }

      .modal-header {
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 16px 20px;
        border-bottom: 1px solid rgba(255,255,255,0.08);
        font-size: 14px;
        font-weight: 600;
        color: #e2e8f0;
      }

      .modal-close {
        background: none;
        border: none;
        color: #94a3b8;
        font-size: 20px;
        cursor: pointer;
        line-height: 1;
        padding: 0 4px;
      }
      .modal-close:hover { color: #e2e8f0; }

      .modal-body {
        padding: 20px;
        overflow-y: auto;
        font-size: 13.5px;
        line-height: 1.7;
        color: #cbd5e1;
      }
      .modal-body h3 { font-size: 14px; color: #e2e8f0; margin: 16px 0 6px; }
      .modal-body h4 { font-size: 13px; color: #94a3b8; margin: 10px 0 4px; }
      .modal-body strong { color: #e2e8f0; }

      /* Summary footer — regenerate action pinned below the scrolling body */
      .modal-footer {
        display: flex;
        justify-content: flex-end;
        padding: 12px 20px;
        border-top: 1px solid rgba(255, 255, 255, 0.08);
      }
      .modal-regen-btn {
        display: inline-flex;
        align-items: center;
        gap: 7px;
        background: rgba(255, 255, 255, 0.06);
        border: 1px solid rgba(255, 255, 255, 0.14);
        border-radius: 9999px;
        color: #cbd5e1;
        font-family: var(--font-family);
        font-size: 12.5px;
        font-weight: 600;
        padding: 7px 14px;
        cursor: pointer;
        transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease;
      }
      .modal-regen-btn:hover {
        background: rgba(255, 255, 255, 0.1);
        color: #f8fafc;
        border-color: rgba(255, 255, 255, 0.24);
      }
      .modal-regen-btn:disabled {
        opacity: 0.5;
        cursor: default;
      }
      /* Spin the refresh icon while regenerating */
      .modal-regen-btn.is-loading svg {
        animation: regen-spin 0.9s linear infinite;
      }
      @keyframes regen-spin {
        to { transform: rotate(360deg); }
      }

      /* Toolbar summary button glows the root-node yellow once a summary exists */
      #btn-synthesis.has-summary { color: var(--yellow-bright); }

      /* Shortcuts grid */
      .shortcuts-grid { display: flex; flex-direction: column; gap: 6px; }
      .sc-row {
        display: flex;
        align-items: center;
        gap: 14px;
        padding: 4px 0;
        border-bottom: 1px solid rgba(255,255,255,0.05);
      }
      .sc-row:last-child { border-bottom: none; }
      kbd {
        background: rgba(255,255,255,0.08);
        border: 1px solid rgba(255,255,255,0.14);
        border-radius: 6px;
        padding: 3px 9px;
        font-family: monospace;
        font-size: 12px;
        color: #94a3b8;
        white-space: nowrap;
        min-width: 160px;
      }
      .sc-row span { color: #cbd5e1; font-size: 13px; }

      /* ── AI chip active state (1.8.3) ── */
      .ai-chip-btn--active {
        background: rgba(34, 211, 238, 0.18) !important;
        border-color: rgba(34, 211, 238, 0.5) !important;
        color: #22d3ee !important;
      }

      /* ── Context input panel: full textarea (1.11) ── */
      .context-text-input {
        width: 100%;
        resize: none;
        background: rgba(255,255,255,0.06);
        border: 1px solid rgba(255,255,255,0.12);
        border-radius: 10px;
        color: #e2e8f0;
        font-family: var(--font-family);
        font-size: 13px;
        padding: 10px 12px;
        outline: none;
        line-height: 1.5;
      }
      .context-text-input:focus { border-color: rgba(34,211,238,0.4); }
      .context-input-actions {
        display: flex;
        justify-content: flex-end;
        margin-top: 8px;
      }

      /* ── Duplicate/Search match node highlight (Sonar Ripple / Water echo) ── */
      @keyframes glass-match-pulse {
        0% { transform: translate(-50%, -50%) scale(1); }
        50% { transform: translate(-50%, -50%) scale(1.05); }
        100% { transform: translate(-50%, -50%) scale(1); }
      }

      @keyframes sonar-ripple-slow {
        0% {
          transform: translate(-50%, -50%) scale(0.01);
          opacity: 0.95;
          border-width: 3.5px;
          box-shadow: 0 0 10px rgba(34, 211, 238, 0.6), inset 0 0 5px rgba(34, 211, 238, 0.3);
        }
        50% {
          opacity: 0.7;
          border-width: 2px;
          box-shadow: 0 0 20px rgba(34, 211, 238, 0.3), inset 0 0 10px rgba(34, 211, 238, 0.15);
        }
        100% {
          transform: translate(-50%, -50%) scale(3.2);
          opacity: 0;
          border-width: 0.3px;
          border-color: rgba(34, 211, 238, 0);
          box-shadow: 0 0 40px rgba(34, 211, 238, 0), inset 0 0 20px rgba(34, 211, 238, 0);
        }
      }

      .node--search-match-pulse .glass-circle {
        animation: glass-match-pulse 1.4s ease-in-out;
      }

      .sonar-ripple-overlay {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: 0;
        height: 0;
        pointer-events: none;
        z-index: 1;
      }

      .sonar-ring {
        position: absolute;
        top: 50%;
        left: 50%;
        width: 220px;
        height: 220px;
        border-radius: 50%;
        border: solid rgba(34, 211, 238, 0.95);
        pointer-events: none;
        transform: translate(-50%, -50%) scale(0.01);
        opacity: 0;
        animation: sonar-ripple-slow 4.5s cubic-bezier(0.1, 0.5, 0.1, 1) forwards;
      }

      /* ─── BUBBLE-POP RETRACTION ─── */
      /* Wrapper transform carries depth scale inline, so the pop animates the
         inner layers (same pattern as .node--retracting) */
      .node--popping {
        pointer-events: none !important;
      }
      .node--popping .glass-circle,
      .node--popping .purple-node-base {
        animation: node-pop 0.28s cubic-bezier(0.45, 0, 0.75, 0.35) forwards;
      }
      .node--popping .glass-input-field,
      .node--popping .btn-expand-pill,
      .node--popping .control-icon,
      .node--popping .yellow-dashed-circle,
      .node--popping .loading-ring,
      .node--popping .node-peek-label {
        opacity: 0 !important;
        transition: opacity 0.12s ease;
      }
      @keyframes node-pop {
        0%   { transform: translate(-50%, -50%) scale(1);    opacity: 1; }
        38%  { transform: translate(-50%, -50%) scale(1.14); opacity: 0.9; }
        100% { transform: translate(-50%, -50%) scale(0);    opacity: 0; }
      }
      .sticky-note.node--popping {
        opacity: 0;
        transition: opacity 0.22s ease;
      }

      /* ─── NODE SPOTLIGHT ─── */
      /* Very faint radial glow behind a selected node; a childless selection
         casts the same glow behind its parent (applied via .node--spotlight) */
      .node-wrapper::before {
        content: "";
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: 640px;
        height: 640px;
        border-radius: 50%;
        background: radial-gradient(
          circle,
          rgba(190, 205, 255, 0.09) 0%,
          rgba(190, 205, 255, 0.045) 38%,
          transparent 68%
        );
        opacity: 0;
        transition: opacity 0.7s ease;
        pointer-events: none;
        z-index: 0;
      }
      .node--spotlight::before {
        opacity: 1;
      }

      /* ─── DRAWER TOGGLE (hamburger) ─── */
      #drawer-toggle {
        position: fixed;
        top: 48px;
        left: 48px;
        width: 58px;
        height: 58px;
        border-radius: 16px;
        border: 1px solid rgba(255, 255, 255, 0.1);
        background: rgba(25, 25, 25, 0.65);
        backdrop-filter: blur(12px);
        -webkit-backdrop-filter: blur(12px);
        color: rgba(255, 255, 255, 0.45);
        cursor: pointer;
        display: flex;
        align-items: center;
        justify-content: center;
        z-index: 460;
        transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease,
          left 0.32s cubic-bezier(0.16, 1, 0.3, 1);
      }
      #drawer-toggle:hover {
        background: rgba(255, 255, 255, 0.12);
        color: rgba(255, 255, 255, 0.85);
        border-color: rgba(255, 255, 255, 0.2);
      }
      #drawer-toggle.active {
        left: 350px; /* clears the floating drawer (14 + 320 + 16 gap) */
        background: rgba(255, 255, 255, 0.15);
        color: rgba(255, 255, 255, 0.85);
        border-color: rgba(255, 255, 255, 0.2);
      }

      /* ─── MAP DRAWER ─── */
      #drawer-scrim {
        position: fixed;
        inset: 0;
        background: rgba(0, 0, 0, 0.4);
        opacity: 0;
        pointer-events: none;
        transition: opacity 0.3s ease;
        z-index: 440;
      }
      #drawer-scrim.visible {
        opacity: 1;
        pointer-events: auto;
      }

      /* Floating rounded glass panel — same glassmorphism as the nodes and
         peek card (heavy blur + saturate, inset top highlight, ambient glow) so
         the drawer reads as part of the same surface family, not a flat sidebar. */
      #map-drawer {
        position: fixed;
        top: 14px;
        left: 14px;
        bottom: 14px;
        width: 320px;
        display: flex;
        flex-direction: column;
        overflow: hidden;
        background:
          url("data:image/svg+xml,%3Csvg viewBox='0 0 250 250' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='matrix' values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.035 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noise)'/%3E%3C/svg%3E"),
          linear-gradient(to right, rgba(18, 19, 23, 0.96), rgba(10, 11, 12, 0.98));
        backdrop-filter: blur(32px) saturate(180%) brightness(1.0);
        -webkit-backdrop-filter: blur(32px) saturate(180%) brightness(1.0);
        border: 1px solid rgba(255, 255, 255, 0.08);
        border-radius: 22px;
        box-shadow:
          inset 0 1px 1px rgba(255, 255, 255, 0.05),
          0 30px 70px -12px rgba(0, 0, 0, 0.8),
          0 0 60px rgba(0, 0, 0, 0.5);
        transform: translateX(calc(-100% - 22px));
        transition: transform 0.36s cubic-bezier(0.16, 1, 0.3, 1);
        z-index: 450;
        font-family: var(--font-family);
      }
      #map-drawer.open {
        transform: translateX(0);
      }
 
      .drawer-header {
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 22px 20px 14px;
      }
      .drawer-title {
        font-size: 15px;
        font-weight: 600;
        color: #e2e8f0;
        letter-spacing: 0.02em;
      }
      #drawer-new-map {
        display: flex;
        align-items: center;
        gap: 7px;
        padding: 8px 14px;
        border-radius: 12px;
        border: 1px solid rgba(255, 255, 255, 0.08);
        background: rgba(40, 44, 52, 0.45);
        backdrop-filter: blur(10px) saturate(110%);
        -webkit-backdrop-filter: blur(10px) saturate(110%);
        color: #e2e8f0;
        font-family: var(--font-family);
        font-size: 12.5px;
        font-weight: 600;
        cursor: pointer;
        box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.05), 0 2px 8px rgba(0, 0, 0, 0.2);
        transition: background 0.2s ease, border-color 0.2s ease, transform 0.15s ease;
      }
      #drawer-new-map:hover {
        background: rgba(60, 64, 72, 0.7);
        border-color: rgba(255, 255, 255, 0.18);
        color: #ffffff;
      }
      #drawer-new-map:active {
        transform: scale(0.97);
      }
 
      .drawer-search-wrap {
        display: flex;
        align-items: center;
        gap: 9px;
        margin: 0 20px 12px;
        padding: 9px 16px;
        border-radius: 9999px;
        border: none;
        background: #f5a800;
        color: rgba(0, 0, 0, 0.6);
        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
        transition: box-shadow 0.2s ease;
      }
      .drawer-search-wrap:focus-within {
        box-shadow: 0 4px 16px rgba(245, 168, 0, 0.35);
      }
      #drawer-search {
        flex: 1;
        background: none;
        border: none;
        outline: none;
        color: rgba(0, 0, 0, 0.85);
        font-family: var(--font-family);
        font-size: 13px;
        font-weight: 500;
      }
      #drawer-search::placeholder {
        color: rgba(0, 0, 0, 0.4);
      }
 
      #drawer-map-list {
        flex: 1;
        overflow-y: auto;
        padding: 2px 12px 12px;
        display: flex;
        flex-direction: column;
        gap: 4px;
      }
      #drawer-map-list::-webkit-scrollbar {
        width: 6px;
      }
      #drawer-map-list::-webkit-scrollbar-thumb {
        background: rgba(255, 255, 255, 0.12);
        border-radius: 3px;
      }
 
      .drawer-map-item {
        position: relative;
        padding: 11px 58px 11px 14px;
        border-radius: 14px;
        border: 1px solid rgba(255, 255, 255, 0.06);
        background: rgba(255, 255, 255, 0.02);
        cursor: pointer;
        transition: background 0.15s ease, border-color 0.15s ease,
          box-shadow 0.15s ease;
      }
      .drawer-map-item:hover {
        background: rgba(255, 255, 255, 0.07);
        border-color: rgba(255, 255, 255, 0.14);
      }
      .drawer-map-item--active {
        background: #000000 !important;
        border: 1.5px dashed var(--yellow-bright) !important;
        box-shadow: 0 0 15px rgba(250, 204, 21, 0.25);
      }
      .drawer-map-name {
        font-size: 13.5px;
        font-weight: 500;
        color: #e2e8f0;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
      }
      .drawer-map-item--active .drawer-map-name {
        color: var(--yellow-bright);
      }
      .drawer-map-meta {
        font-size: 11px;
        color: #64748b;
        margin-top: 3px;
      }
      .drawer-map-delete {
        position: absolute;
        top: 50%;
        right: 10px;
        transform: translateY(-50%);
        width: 22px;
        height: 22px;
        border-radius: 50%;
        border: none;
        background: none;
        color: rgba(255, 255, 255, 0.25);
        cursor: pointer;
        display: flex;
        align-items: center;
        justify-content: center;
        opacity: 0;
        transition: opacity 0.15s ease, color 0.15s ease, background 0.15s ease;
      }
      .drawer-map-item:hover .drawer-map-delete {
        opacity: 1;
      }
      .drawer-map-delete:hover {
        color: #f87171;
        background: rgba(248, 113, 113, 0.12);
      }
      /* Duplicate sits just left of delete; same reveal-on-hover treatment. */
      .drawer-map-duplicate {
        position: absolute;
        top: 50%;
        right: 34px;
        transform: translateY(-50%);
        width: 22px;
        height: 22px;
        border-radius: 50%;
        border: none;
        background: none;
        color: rgba(255, 255, 255, 0.25);
        cursor: pointer;
        display: flex;
        align-items: center;
        justify-content: center;
        opacity: 0;
        transition: opacity 0.15s ease, color 0.15s ease, background 0.15s ease;
      }
      .drawer-map-item:hover .drawer-map-duplicate {
        opacity: 1;
      }
      .drawer-map-duplicate:hover {
        color: #22d3ee;
        background: rgba(34, 211, 238, 0.12);
      }
      .drawer-empty {
        padding: 24px 14px;
        font-size: 12.5px;
        color: #64748b;
        text-align: center;
      }

      .drawer-settings {
        border-top: 1px solid rgba(255, 255, 255, 0.08);
        padding: 14px 20px 18px;
      }
      .drawer-settings-title {
        font-size: 11px;
        font-weight: 600;
        letter-spacing: 0.1em;
        text-transform: uppercase;
        color: #64748b;
        margin-bottom: 10px;
      }
      .drawer-setting {
        display: flex;
        align-items: center;
        justify-content: space-between;
        padding: 7px 0;
        font-size: 13px;
        color: #cbd5e1;
        cursor: pointer;
        user-select: none;
      }
      .drawer-setting input {
        display: none;
      }
      .drawer-switch {
        position: relative;
        width: 34px;
        height: 19px;
        border-radius: 10px;
        background: rgba(255, 255, 255, 0.12);
        transition: background 0.2s ease;
        flex-shrink: 0;
      }
      .drawer-switch::after {
        content: "";
        position: absolute;
        top: 2.5px;
        left: 3px;
        width: 14px;
        height: 14px;
        border-radius: 50%;
        background: #94a3b8;
        transition: left 0.2s ease, background 0.2s ease;
      }
      .drawer-setting input:checked + .drawer-switch {
        background: rgba(34, 211, 238, 0.35);
      }
      .drawer-setting input:checked + .drawer-switch::after {
        left: 17px;
        background: #22d3ee;
      }
      .drawer-save-note {
        margin-top: 12px;
        font-size: 11px;
        color: #475569;
        text-align: center;
      }

      /* ─── ZOOM LEVEL INDICATOR ─── */
      #zoom-indicator {
        position: fixed;
        bottom: 48px;
        left: 48px;
        z-index: 200;
        display: flex;
        align-items: center;
        justify-content: center;
        background: none;
        border: none;
        color: #64748b;
        font-family: var(--font-family);
        font-size: 13.5px;
        font-weight: 600;
        letter-spacing: 0.04em;
        pointer-events: none;
        user-select: none;
        box-shadow: none;
      }

      /* ─── COSMIC-WEB LAYOUT MODE ────────────────────────────────────────────
         Toggled by #btn-cosmic. Nodes are hue-rotated per cluster so each galaxy
         reads as a distinct colour; cross-cluster bridge edges ("filaments") are
         muted-by-default but pop to a bright, thin, high-contrast thread so the
         rare load-bearing links stand out instead of getting lost. --cluster-rot
         is written per node by applyClusterVisuals() in script.js. */
      body.cosmic-web .purple-node-base {
        filter: hue-rotate(var(--cluster-rot, 0deg)) saturate(1.12);
      }
      body.cosmic-web .node-wrapper:hover .purple-node-base {
        filter: hue-rotate(var(--cluster-rot, 0deg)) saturate(1.25) brightness(1.06);
      }
      /* Intra-cluster bridges recede; only genuine filaments should draw the eye. */
      body.cosmic-web .extra-edge-line {
        stroke: #5b6b8c;
        opacity: 0.16;
      }
      body.cosmic-web .filament .extra-edge-line {
        stroke: #67e8f9;
        opacity: 0.92;
        stroke-width: 1.5;
        stroke-dasharray: none;
        filter: drop-shadow(0 0 3px rgba(103, 232, 249, 0.5));
      }
      /* Active-state accent on the toolbar toggle. */
      .toolbar-btn#btn-cosmic.active {
        color: #67e8f9;
        background: rgba(103, 232, 249, 0.14);
      }

      /* ── AI SPARKLE BADGE ON NODES ── */
      .node-sparkle-badge {
        position: absolute;
        top: 36px;
        right: 36px;
        width: 22px;
        height: 22px;
        background: rgba(34, 211, 238, 0.15);
        border: 1px solid rgba(34, 211, 238, 0.45);
        color: #22d3ee;
        border-radius: 50%;
        display: flex;
        align-items: center;
        justify-content: center;
        box-shadow: 0 0 12px rgba(34, 211, 238, 0.45), inset 0 0 4px rgba(34, 211, 238, 0.2);
        pointer-events: none;
        z-index: 10;
        backdrop-filter: blur(4px);
        -webkit-backdrop-filter: blur(4px);
        animation: sparkle-float 3s ease-in-out infinite alternate;
      }
      
      .node-sparkle-badge svg {
        width: 13px;
        height: 13px;
      }

      @keyframes sparkle-float {
        0% {
          transform: translateY(0) scale(1);
          box-shadow: 0 0 10px rgba(34, 211, 238, 0.4);
        }
        100% {
          transform: translateY(-3px) scale(1.08);
          box-shadow: 0 0 16px rgba(34, 211, 238, 0.65);
        }
      }

      /* Active AI context bar button (Yellow) */
      .ctx-btn.ctx-btn--ai-active {
        color: var(--yellow-bright) !important;
        filter: drop-shadow(0 0 4px rgba(250, 204, 21, 0.5));
      }

      /* Shimmering Star Effect */
      @keyframes star-twinkle {
        0% {
          opacity: 0;
          transform: translate(-50%, -50%) scale(0.3);
        }
        50% {
          opacity: 0.95;
          transform: translate(-50%, -50%) scale(1.15);
        }
        100% {
          opacity: 0;
          transform: translate(-50%, -50%) scale(0.3);
        }
      }

      .shimmer-star {
        position: absolute;
        width: 5px;
        height: 5px;
        background-color: #ffffff;
        border-radius: 50%;
        box-shadow: 0 0 4px #ffffff, 0 0 8px rgba(255, 255, 255, 0.6);
        pointer-events: none;
        z-index: 1; /* sits on top of background dots but behind nodes */
        animation: star-twinkle 1.8s ease-in-out forwards;
      }
