  :root {
    /* ── Brand palette ── */
    --paper: #FBF7F1;
    --paper-2: #F3EDE2;
    --ink: #1F1B16;
    --ink-soft: #534B40;
    --ink-faint: #9A9088;
    --amber: #C8651B;
    --amber-soft: #E8A974;
    --sage: #8FA68E;
    --sage-soft: #C6D4C4;
    --done: #C9C1B5;

    /* ── Shadows ── */
    --shadow-sm: 0 1px 2px rgba(31, 27, 22, 0.06), 0 1px 1px rgba(31, 27, 22, 0.04);
    --shadow-md: 0 6px 24px rgba(31, 27, 22, 0.08), 0 2px 6px rgba(31, 27, 22, 0.05);
    --shadow-lg: 0 24px 60px rgba(31, 27, 22, 0.14), 0 8px 20px rgba(31, 27, 22, 0.06);

    /* ── Radius ── */
    --radius: 14px;

    /* ── Safe-area insets ── */
    --safe-top: env(safe-area-inset-top, 0px);
    --safe-bottom: env(safe-area-inset-bottom, 0px);

    /* ── White surface ── */
    --white: #fff;
    --white-88: rgba(255, 255, 255, 0.88);
    --white-85: rgba(255, 255, 255, 0.85);
    --white-95: rgba(255, 255, 255, 0.95);

    /* ── Paper tints (translucent) ── */
    --paper-92: rgba(251, 247, 241, 0.92);
    --paper-96: rgba(251, 247, 241, 0.96);
    --paper-98: rgba(251, 247, 241, 0.98);
    --paper-70: rgba(251, 247, 241, 0.70);

    /* ── Canvas / background tints ── */
    --canvas-row2-bg: rgba(248, 246, 242, 0.95);
    --canvas-row3-bg: rgba(255, 250, 243, 0.95);
    --plan-banner-bg: rgba(255, 247, 235, 0.95);
    --new-card-hover-bg: rgba(255, 247, 235, 0.6);

    /* ── Ink alpha variants ── */
    --ink-02: rgba(31, 27, 22, 0.02);
    --ink-03: rgba(31, 27, 22, 0.03);
    --ink-04: rgba(31, 27, 22, 0.04);
    --ink-05: rgba(31, 27, 22, 0.05);
    --ink-06: rgba(31, 27, 22, 0.06);
    --ink-07: rgba(31, 27, 22, 0.07);
    --ink-08: rgba(31, 27, 22, 0.08);
    --ink-10: rgba(31, 27, 22, 0.10);
    --ink-12: rgba(31, 27, 22, 0.12);
    --ink-15: rgba(31, 27, 22, 0.15);
    --ink-18: rgba(31, 27, 22, 0.18);
    --ink-25: rgba(31, 27, 22, 0.25);
    --ink-35: rgba(31, 27, 22, 0.35);
    --ink-92: rgba(31, 27, 22, 0.92);

    /* ── Amber alpha variants ── */
    --amber-08: rgba(200, 101, 27, 0.08);
    --amber-10: rgba(200, 101, 27, 0.10);
    --amber-12: rgba(200, 101, 27, 0.12);
    --amber-15: rgba(200, 101, 27, 0.15);
    --amber-18: rgba(200, 101, 27, 0.18);
    --amber-22: rgba(200, 101, 27, 0.22);
    --amber-25: rgba(200, 101, 27, 0.25);
    --amber-30: rgba(200, 101, 27, 0.30);
    --amber-35: rgba(200, 101, 27, 0.35);
    --amber-40: rgba(200, 101, 27, 0.40);
    --amber-55: rgba(200, 101, 27, 0.55);
    --amber-65: rgba(200, 101, 27, 0.65);

    /* ── Sage alpha variants ── */
    --sage-07: rgba(143, 166, 142, 0.07);
    --sage-16: rgba(143, 166, 142, 0.16);
    --sage-18: rgba(143, 166, 142, 0.18);
    --sage-30: rgba(143, 166, 142, 0.30);
    --sage-35: rgba(143, 166, 142, 0.35);
    --sage-40: rgba(143, 166, 142, 0.40);
    --sage-45: rgba(143, 166, 142, 0.45);
    --sage-28: rgba(143, 166, 142, 0.28);
    --sage-50: rgba(143, 166, 142, 0.5);
    --sage-60: rgba(143, 166, 142, 0.6);
    --sage-70: rgba(143, 166, 142, 0.7);
    --sage-42: rgba(143, 166, 142, 0.42);

    /* ── Amber-soft tint (canvas gradient) ── */
    --amber-soft-08: rgba(232, 169, 116, 0.08);
    --amber-soft-10: rgba(232, 169, 116, 0.10);

    /* ── Bucket accent colors ── */
    /* Green – First */
    --bucket-first-color: #4A8E4F;
    --bucket-first-mid: #7FB582;
    --bucket-first-06: rgba(127, 181, 130, 0.06);
    --bucket-first-10: rgba(127, 181, 130, 0.10);
    --bucket-first-18: rgba(127, 181, 130, 0.18);
    --bucket-first-22: rgba(127, 181, 130, 0.22);

    /* Blue – Then */
    --bucket-then-color: #3D6F94;
    --bucket-then-mid: #5C8FB5;
    --bucket-then-06: rgba(92, 143, 181, 0.06);   /* unused but kept for symmetry */
    --bucket-then-10: rgba(92, 143, 181, 0.10);
    --bucket-then-18: rgba(92, 143, 181, 0.18);
    --bucket-then-22: rgba(92, 143, 181, 0.22);

    /* Purple – After */
    --bucket-after-color: #6F4FA1;
    --bucket-after-mid: #9B7BBF;
    --bucket-after-10: rgba(155, 123, 191, 0.10);
    --bucket-after-12: rgba(155, 123, 191, 0.12);
    --bucket-after-18: rgba(155, 123, 191, 0.18);
    --bucket-after-22: rgba(155, 123, 191, 0.22);

    /* Grey – Archive */
    --bucket-archive-color: #6B655E;
    --bucket-archive-mid: #9A9088;
    --bucket-archive-06: rgba(154, 144, 136, 0.06);
    --bucket-archive-16: rgba(154, 144, 136, 0.16);
    --bucket-archive-18: rgba(154, 144, 136, 0.18);

    /* ── Node type colors ── */
    /* Goal node */
    --node-goal-bg-from: #FFF6E8;
    --node-goal-bg-to: #FCEAD0;
    /* Milestone node */
    --node-milestone-bg-from: #F2F7F1;
    --node-milestone-bg-to: #E4EFE3;
    /* Task node */
    --node-task-bg: #FFFEFB;

    /* ── Danger / destructive ── */
    --danger: #B0432A;
    --danger-12: rgba(176, 67, 42, 0.12);
    --danger-20: rgba(176, 67, 42, 0.20);

    /* ── Gold (goal halo) ── */
    /* #FFD700 = rgb(255,215,0): zero blue channel, fully saturated at hue 51°.
       Blue=0 is the key — any other gold with B>0 mixes muddy on coloured backgrounds. */
    --gold: #FFD700;
    --gold-50: rgba(255, 215, 0, 0.50);
    --gold-60: rgba(255, 215, 0, 0.60);
    --gold-75: rgba(255, 215, 0, 0.75);

    /* ── Selection highlight: dependency edges (dark red, left) ── */
    --dep-edge: #B22B2B;
    --dep-edge-50: rgba(178, 43, 43, 0.50);
    /* ── Selection highlight: successor edges (lighter orange, right) ── */
    --suc-edge: #D97828;
    --suc-edge-50: rgba(217, 120, 40, 0.50);
    /* ── Value-path edge color (kept for any legacy references) ── */
    --path-edge: #D04A1A;
    --path-edge-50: rgba(208, 74, 26, 0.50);

    /* ── Root badge (red) ── */
    --root-color: #C03C32;
    --root-bg: rgba(192, 60, 50, 0.10);
    --root-border: rgba(192, 60, 50, 0.55);

    /* ── Status colors ── */
    --status-progress-color: #B0571B;
    --status-done-color: #4A8E4F;

    /* ── Successor-completed pattern ── */
    --succ-stripe-a: rgba(244, 248, 243, 0.6);

    /* ── Plan bar (over capacity) ── */
    --plan-over-from: rgba(200, 80, 60, 0.45);
    --plan-over-to: rgba(200, 80, 60, 0.28);
  }

  * { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
  html, body {
    margin: 0; padding: 0;
    /* Use a JS-driven height var as the primary source of truth. Some in-app
       browsers (Telegram, certain webviews) report unstable 100%/100vh on first
       paint, collapsing position:fixed children to zero height - which left only
       the fixed-pixel menubar visible. --app-height is set from
       window.innerHeight on load/resize and is reliable. 100% is the fallback. */
    height: 100%;
    height: var(--app-height, 100%);
    overscroll-behavior: none;
    -webkit-user-select: none; user-select: none;
    -webkit-touch-callout: none;
    background: var(--paper);
    color: var(--ink);
    font-family: "Inter Tight", -apple-system, BlinkMacSystemFont, sans-serif;
    font-size: 15px;
    overflow: hidden;
  }

  body {
    position: fixed; inset: 0;
    /* Explicit height (not just inset:0) so webviews that mis-handle fixed
       insets still give the body a real height. */
    width: 100%;
    height: var(--app-height, 100%);
    touch-action: none;
    background: var(--paper);
    color: var(--ink);
  }

  /* ============== CANVAS ============== */
  #canvas {
    position: absolute;
    top: calc(var(--safe-top) + 40px);
    left: 0; right: 0; bottom: 0;
    overflow: hidden;
    background:
      radial-gradient(circle at 30% 20%, var(--amber-soft-08), transparent 50%),
      radial-gradient(circle at 80% 80%, var(--sage-07), transparent 50%),
      var(--paper);
    cursor: grab;
  }
  #canvas.panning { cursor: grabbing; }

  #grid {
    position: absolute;
    inset: 0;
    background-image:
      radial-gradient(circle, var(--ink-18) 1px, transparent 1.2px);
    background-repeat: repeat;
    /* background-position and background-size set by applyTransform() */
    pointer-events: none;
  }

  #world {
    position: absolute;
    top: 0; left: 0;
    width: 0; height: 0;
    transform-origin: 0 0;
    will-change: transform;
  }

  /* ============== NODES ============== */
  .node {
    position: absolute;
    background: var(--white);
    border: 1px solid var(--ink-08);
    border-radius: var(--radius);
    padding: 10px 12px;
    box-shadow: var(--shadow-sm);
    display: grid;
    /* Title (top), filler (grows), chrome (bottom), meta (very bottom) */
    grid-template-rows: auto 1fr auto auto;
    gap: 4px;
    cursor: pointer;
    transition: box-shadow .25s cubic-bezier(.3,.7,.3,1), border-color .25s, opacity .25s, transform .12s;
    will-change: transform;
    overflow: hidden;
    /* Prevent iOS Safari from intercepting touch as a scroll gesture */
    touch-action: none;
    /* Enable container queries so badge/type can hide when card is narrow. */
    container-type: inline-size;
  }
  /* Narrow card: hide the ROOT badge + the type label so the title and core
     chrome (expand chevron + check) remain readable. Threshold is just above
     W_MIN so a 1-unit-wide card at any grain still shows everything. */
  @container (max-width: 135px) {
    .node-badge,
    .node-type { display: none !important; }
  }
  .node:active { transform: scale(0.985); }
  .node.dragging { box-shadow: var(--shadow-lg); z-index: 100; transition: none; }
  .node.resizing { box-shadow: var(--shadow-lg); z-index: 100; transition: none; }
  .node.connecting-source { border-color: var(--amber); box-shadow: 0 0 0 2px var(--amber-25); }

  /* Top chrome row: badge on the left, check on the right. Fixed-height, never overlaps title. */
  .node-chrome {
    display: flex;
    justify-content: space-between;
    align-items: center;
    min-height: 18px;
    gap: 8px;
  }
  .node-badge {
    display: none; /* hidden by default; toggled per-state */
    font-size: 8.5px;
    letter-spacing: 0.12em;
    font-weight: 600;
    font-family: "Inter Tight", sans-serif;
    text-transform: uppercase;
    padding: 2px 6px;
    border-radius: 4px;
    line-height: 1;
    white-space: nowrap;
  }
  .node.is-root .node-badge {
    display: inline-block;
    color: var(--root-color);
    background: var(--root-bg);
  }

  .node[data-type="goal"] {
    background: linear-gradient(180deg, var(--node-goal-bg-from), var(--node-goal-bg-to));
    border-color: var(--amber-22);
  }
  .node[data-type="milestone"] {
    background: linear-gradient(180deg, var(--node-milestone-bg-from), var(--node-milestone-bg-to));
    border-color: var(--sage-35);
  }
  .node[data-type="task"] {
    background: var(--node-task-bg);
  }

  .node.done {
    background: var(--paper-2) !important;
    opacity: 0.55;
  }
  .node.done .node-title { text-decoration: line-through; color: var(--ink-faint); }

  /* successor-completed: this task was implicitly skipped because its successor
     was marked done without doing this. Visually distinct from "done" so the
     user knows the work didn't actually happen. */
  .node.successor-completed {
    background:
      repeating-linear-gradient(
        135deg,
        var(--sage-18),
        var(--sage-18) 6px,
        var(--succ-stripe-a) 6px,
        var(--succ-stripe-a) 12px
      ) !important;
    opacity: 0.7;
    border-color: var(--sage-40) !important;
  }
  .node.successor-completed .node-title {
    color: var(--ink-soft);
    font-style: italic;
  }
  /* .node.successor-completed .node-check - style now handled by progressCheckSvg('skipped') */

  .node.locked {
    filter: saturate(0.3);
    opacity: 0.78;
  }
  .node.locked .node-title { color: var(--ink-soft); }
  .node.locked .node-type { color: var(--ink-faint); }

  /* Selected and best-next both get a glowing box-shadow. We use box-shadow
     rather than a ::before pseudo because .node has overflow:hidden, which
     would clip a ::before halo.  Best-next gets a subtle pulse; selected
     gets a stronger, faster pulse. */
  @keyframes glow-best {
    0%, 100% { box-shadow: 0 0 0 0 var(--amber-25), 0 0 18px 4px var(--amber-15), var(--shadow-sm); }
    50%      { box-shadow: 0 0 0 2px var(--amber-35), 0 0 26px 8px var(--amber-22), var(--shadow-sm); }
  }
  @keyframes glow-selected {
    0%, 100% { box-shadow: 0 0 0 2px var(--amber-35), 0 0 22px 6px var(--amber-25), var(--shadow-md); }
    50%      { box-shadow: 0 0 0 3px var(--amber-55), 0 0 34px 10px var(--amber-40), var(--shadow-md); }
  }
  .node.best-next {
    animation: glow-best 2.4s ease-in-out infinite;
  }
  .node.selected {
    border-color: var(--amber);
    animation: glow-selected 1.6s ease-in-out infinite;
  }
  /* Selected wins over best-next: if both, use the stronger glow. */
  .node.best-next.selected {
    animation: glow-selected 1.6s ease-in-out infinite;
  }
  /* Direct connections of the selected node: amber outline (no pulsing glow,
     so they read as "related" rather than "selected"). */
  .node.connected-highlight {
    border-color: var(--amber);
    box-shadow: 0 0 0 2px var(--amber-35), var(--shadow-md);
  }

  /* Selection highlighting: deps (left, dark red) and successors (right, lighter orange) */
  .node.dep-lit {
    border-color: var(--dep-edge);
    box-shadow: 0 0 0 2px var(--dep-edge-50), var(--shadow-md);
    transition: box-shadow .2s, border-color .2s;
  }
  .node.suc-lit {
    border-color: var(--suc-edge);
    box-shadow: 0 0 0 2px var(--suc-edge-50), var(--shadow-md);
    transition: box-shadow .2s, border-color .2s;
  }
  /* Keep .path-lit as alias for suc-lit (legacy fallback) */
  .node.path-lit {
    border-color: var(--suc-edge);
    box-shadow: 0 0 0 2px var(--suc-edge-50), var(--shadow-md);
    transition: box-shadow .2s, border-color .2s;
  }
  .node.path-goal {
    border-color: var(--gold);
    border-width: 2.5px;
    box-shadow:
      /* Gold layers front-to-back — high opacity so gold wins over any background */
      0 0 0 5px  rgba(255, 215, 0, 0.92),
      0 0 24px 8px rgba(255, 215, 0, 0.78),
      0 0 55px 18px rgba(255, 215, 0, 0.55),
      /* Cream-white backing (last = lowest layer): neutralises the coloured canvas
         so the gold composites over near-white rather than the purple bucket tint */
      0 0 44px 15px rgba(255, 252, 240, 0.96),
      var(--shadow-md);
    animation: goal-pulse 1.8s ease-in-out infinite;
  }
  @keyframes goal-pulse {
    0%, 100% {
      box-shadow:
        0 0 0 5px  rgba(255, 215, 0, 0.92),
        0 0 24px 8px rgba(255, 215, 0, 0.78),
        0 0 55px 18px rgba(255, 215, 0, 0.55),
        0 0 44px 15px rgba(255, 252, 240, 0.96),
        var(--shadow-md);
    }
    50% {
      box-shadow:
        0 0 0 7px  rgba(255, 215, 0, 0.96),
        0 0 36px 14px rgba(255, 215, 0, 0.88),
        0 0 80px 28px rgba(255, 215, 0, 0.65),
        0 0 60px 22px rgba(255, 252, 240, 0.96),
        var(--shadow-md);
    }
  }

  /* Everything unrelated to the selection fades back. */
  .node.connection-dimmed {
    opacity: 0.35;
    transition: opacity .2s;
  }

  .node-title {
    font-family: "Fraunces", Georgia, serif;
    font-weight: 500;
    font-size: 15px;
    line-height: 1.25;
    /* min-height: at least one full line so the title is always visible */
    min-height: 1.25em;
    color: var(--ink);
    word-break: break-word;
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 4;
    -webkit-box-orient: vertical;
    min-width: 0;
    /* Guarantees the … shows: the box never exceeds 4 lines, and line-clamp
       adds the ellipsis when text overflows that height. */
    text-overflow: ellipsis;
  }
  /* When the title is actually clipped, a subtle gradient fade on the last line
     reinforces that there's more text (in addition to the … from line-clamp). */
  .node.title-clipped .node-title { cursor: help; }
  .node-filler { min-height: 0; }
  .node[data-type="goal"] .node-title { font-size: 18px; font-weight: 600; }
  .node[data-type="milestone"] .node-title { font-size: 16px; font-weight: 500; }

  .node-meta {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 8px;
    font-size: 10.5px;
    color: var(--ink-faint);
    letter-spacing: 0.04em;
    text-transform: uppercase;
    font-family: "Inter Tight", sans-serif;
    font-weight: 500;
    min-height: 14px;
  }
  .node-score {
    color: var(--amber);
    font-weight: 600;
  }
  .node-effort {
    color: var(--ink-soft);
    font-weight: 600;
    margin-right: auto; /* push node-type to the far right */
  }

  /* Action row inside chrome: chevron + check, right-aligned */
  .node-actions {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: 6px;
    position: relative; /* keep above progress fill */
    z-index: 2;
  }

  /* Progress fill for parents: sage gradient from left, width = completion %.
     Pseudo-element so it doesn't fight node content. Sits behind everything else. */
  .node.has-children > * {
    position: relative;
    z-index: 1;
  }
  /* The handles and resize zones are absolutely positioned and must stay that way.
     .node.has-children > * above would override them to position:relative (which
     drops them into the grid flow, creating phantom bottom rows). Re-assert. */
  .node.has-children .connect-handle,
  .node.has-children .add-prereq-handle,
  .node.has-children .resize-handle,
  .node.has-children .resize-edge {
    position: absolute;
    z-index: 3;
  }
  .node.has-children::before {
    content: "";
    position: absolute;
    top: 0; left: 0; bottom: 0;
    width: var(--progress, 0%);
    background: linear-gradient(90deg, var(--sage-30), var(--sage-16));
    border-right: 1px solid var(--sage-45);
    transition: width 0.35s cubic-bezier(0.3, 0.7, 0.3, 1);
    z-index: 0;
    pointer-events: none;
  }
  .node.has-children[data-progress="100"]::before {
    border-right-color: transparent;
  }

  .node-expand {
    flex-shrink: 0;
    width: 20px; height: 20px;
    border-radius: 6px;
    border: 1px solid var(--ink-faint);
    background: transparent;
    color: var(--ink-soft);
    cursor: pointer;
    padding: 0;
    display: flex; align-items: center; justify-content: center;
    transition: all .2s;
  }
  .node-expand:hover {
    border-color: var(--ink);
    color: var(--ink);
    background: var(--ink-04);
  }
  .node-expand:active { transform: scale(0.92); }
  .node-expand svg { width: 12px; height: 12px; }
  /* When the project is at its deepest grain, drilling further isn't allowed.
     Hide the chevron entirely so it doesn't look interactive. */
  body.at-depth-cap .node-expand { display: none; }
  /* Solid chevron when node has children, outlined when leaf */
  .node.has-children .node-expand {
    background: var(--ink);
    border-color: var(--ink);
    color: var(--paper);
  }
  .node.has-children .node-expand:hover {
    background: var(--amber);
    border-color: var(--amber);
  }

  .node-check {
    flex-shrink: 0;
    width: 20px; height: 20px;
    cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    transition: transform .15s;
    background: none;
    border: none;
    padding: 0;
  }
  .node-check:active { transform: scale(0.85); }
  .node-check svg { width: 20px; height: 20px; display: block; }

  /* Resize handle */
  .resize-handle {
    position: absolute;
    bottom: 2px; right: 2px;
    width: 22px; height: 22px;
    cursor: nwse-resize;
    opacity: 0;
    transition: opacity .2s;
    display: flex; align-items: flex-end; justify-content: flex-end;
    padding: 2px;
    touch-action: none;
  }
  .resize-handle::after {
    content: "";
    width: 10px; height: 10px;
    border-right: 2.5px solid var(--ink-soft);
    border-bottom: 2.5px solid var(--ink-soft);
    border-bottom-right-radius: 3px;
  }
  .node:hover .resize-handle, .node.selected .resize-handle { opacity: 0.6; }

  @media (pointer: coarse) {
    .resize-handle {
      width: 44px; height: 44px;
      bottom: 0; right: 0;
      opacity: 0.55;
      padding: 4px;
      /* Make sure it sits above any other inner content */
      z-index: 4;
    }
    .resize-handle::after {
      width: 16px; height: 16px;
      border-right-width: 3px;
      border-bottom-width: 3px;
    }
    .node.selected .resize-handle { opacity: 0.9; }
  }

  /* Edge resize zones - only on devices with a fine pointer (mouse/trackpad).
     On touch, the corner handle is the only way to resize. */
  .resize-edge {
    position: absolute;
    display: none;
    z-index: 2;
  }
  @media (pointer: fine) {
    .resize-edge { display: block; }
  }
  .resize-edge-left {
    left: -4px; top: 8px; bottom: 8px;
    width: 8px;
    cursor: ew-resize;
  }
  .resize-edge-right {
    right: -4px; top: 8px; bottom: 8px;
    width: 8px;
    cursor: ew-resize;
  }
  .resize-edge-top {
    top: -4px; left: 8px; right: 8px;
    height: 8px;
    cursor: ns-resize;
  }
  .resize-edge-bottom {
    bottom: -4px; left: 8px; right: 8px;
    height: 8px;
    cursor: ns-resize;
  }
  /* Hide edge resize zones on ghost/goal/secondary overlays */
  .node.ghost-dep .resize-edge,
  .node.secondary-goal .resize-edge,
  .goal-node-overlay .resize-edge { display: none; }

  /* Connect handle (right edge dot - drag to create unlocks downstream) */
  /* Successor handle: right edge, drag to draw a dependency arrow */
  .connect-handle {
    position: absolute;
    top: 50%; right: -26px;
    width: 52px; height: 52px;
    background: var(--amber);
    border: 2.5px solid var(--paper);
    border-radius: 50%;
    transform: translateY(-50%);
    opacity: 0;
    transition: opacity .2s, transform .15s;
    cursor: crosshair;
    z-index: 3;
    touch-action: none;
    box-shadow: 0 2px 6px var(--amber-35);
  }
  .node:hover .connect-handle, .node.selected .connect-handle { opacity: 1; }
  .connect-handle:active { transform: translateY(-50%) scale(1.2); }
  @media (pointer: coarse) {
    .connect-handle     { width: 52px; height: 52px; right: -26px; }
    .add-prereq-handle  { width: 52px; height: 52px; left: -26px; font-size: 28px; }
  }

  /* Dependency handle (left edge — drag or tap to add a prereq) */
  .add-prereq-handle {
    position: absolute;
    top: 50%; left: -26px;
    width: 52px; height: 52px;
    background: var(--paper);
    border: 2px solid var(--ink-soft);
    border-radius: 50%;
    transform: translateY(-50%);
    opacity: 0;
    transition: opacity .2s, transform .15s, background .15s, border-color .15s;
    cursor: pointer;
    z-index: 3;
    display: flex; align-items: center; justify-content: center;
    color: var(--ink-soft);
    font-size: 28px;
    font-weight: 400;
    line-height: 1;
    touch-action: none;
    box-shadow: var(--shadow-sm);
  }
  .add-prereq-handle::before {
    content: "+";
    margin-top: -1px;
  }
  .node:hover .add-prereq-handle, .node.selected .add-prereq-handle { opacity: 1; }
  .add-prereq-handle:hover {
    background: var(--ink);
    border-color: var(--ink);
    color: var(--paper);
    transform: translateY(-50%) scale(1.1);
  }
  .add-prereq-handle:active { transform: translateY(-50%) scale(0.92); }

  /* Goal node overlay: the drilled-into parent, pinned at the right of the drill view */
  .goal-node-overlay {
    border-color: var(--amber-40) !important;
    background: linear-gradient(135deg, var(--node-goal-bg-from), var(--node-goal-bg-to)) !important;
    box-shadow: 0 4px 18px var(--amber-18), var(--shadow-md) !important;
    z-index: 5;
  }

  /* Secondary successors: when the drilled-into parent has other successors at
     the same level, they appear stacked below the primary goal as muted ghosts. */
  .node.secondary-goal {
    opacity: 0.5;
    cursor: pointer;
    z-index: 4 !important;
    box-shadow: 0 2px 12px var(--ink-06) !important;
  }
  .node.secondary-goal:hover {
    opacity: 0.85;
  }
  .node.secondary-goal::before { display: none; } /* no halo */
  .node.secondary-goal .node-title {
    font-size: 14px;
    font-weight: 500;
  }
  .node.secondary-goal .node-actions { display: none; }
  .node.ghost-dep {
    opacity: 0.55;
    filter: saturate(0.6);
    cursor: pointer;
    border-style: dashed !important;
    z-index: 2;
  }
  .node.ghost-dep:hover {
    opacity: 0.85;
    filter: saturate(1);
  }
  .ghost-badge {
    color: var(--ink-soft) !important;
    background: var(--ink-08) !important;
    display: inline-block !important;
  }
  .node.ghost-dep .node-expand,
  .node.ghost-dep .resize-handle,
  .node.ghost-dep .connect-handle,
  .node.ghost-dep .add-prereq-handle,
  .node.ghost-dep .node-check { display: none; }
  .goal-node-overlay::before {
    /* Soft glow halo behind the goal node */
    content: "";
    position: absolute;
    inset: -8px;
    border-radius: calc(var(--radius) + 8px);
    background: radial-gradient(circle at center, var(--amber-22), transparent 70%);
    z-index: -1;
    pointer-events: none;
  }
  .goal-node-overlay .node-title {
    font-family: "Fraunces", Georgia, serif;
    font-weight: 600;
    font-size: 17px;
    color: var(--ink);
    cursor: text;
  }
  .goal-badge {
    color: var(--amber) !important;
    background: var(--amber-12) !important;
    display: inline-block !important;
  }
  /* Hide the regular drilling/resize/outbound-connect affordances on the goal node.
     But SHOW the add-prereq handle (left "+") - tapping/dragging it creates a new
     dependency task that feeds into the goal. */
  .goal-node-overlay .node-expand,
  .goal-node-overlay .resize-handle,
  .goal-node-overlay .connect-handle { display: none; }
  /* The add-prereq handle stays visible on the goal so the user can create deps. */
  .goal-node-overlay .add-prereq-handle {
    /* Override the default opacity:0 hover-only behavior - make it always visible on the goal */
    opacity: 0.85 !important;
  }
  .node.is-root {
    border-color: var(--root-border);
  }

  /* ============== BUCKETS (First / Then / After kanban columns) ============== */
  #days-layer {
    position: absolute;
    top: 0; left: 0;
    pointer-events: none;
  }
  .bucket-col {
    position: absolute;
    top: -10000px; height: 20000px;
    pointer-events: auto;
    border-left: 1px solid var(--ink-06);
  }
  .bucket-col:last-child { border-right: 1px solid var(--ink-06); }
  .bucket-col[data-bucket-id="archive"] { background: var(--bucket-archive-06); }
  .bucket-col[data-bucket-id="first"] { background: var(--bucket-first-10); }
  .bucket-col[data-bucket-id="then"]  { background: var(--bucket-then-10); }
  .bucket-col[data-bucket-id="after"] { background: var(--bucket-after-10); right: -99999px; }

  /* Bucket & milestone labels live in screen space, pinned to the top of the viewport. */
  /* ============== MILESTONES (vertical dashed lines) ============== */
  #milestones-layer {
    position: absolute;
    top: 0; left: 0;
    pointer-events: none;
  }
  .milestone-line {
    position: absolute;
    top: -10000px; height: 20000px;
    width: 0;
    border-left: 1.5px dashed var(--amber-65);
    pointer-events: auto;
  }

  /* ============== EDGES ============== */
  #edges {
    position: absolute;
    top: 0; left: 0;
    width: 100%; height: 100%;
    pointer-events: none;
    overflow: visible;
  }
  .edge-hit {
    fill: none;
    stroke: transparent;
    stroke-width: 18;
    pointer-events: stroke;
    cursor: pointer;
  }
  .edge {
    fill: none;
    stroke: var(--ink-soft);
    stroke-width: 2;
    opacity: 0.7;
    transition: opacity .25s, stroke .25s, stroke-width .15s;
    pointer-events: none;
  }
  /* Prereq not done yet: dashed to show "waiting" */
  .edge.pending { stroke-dasharray: 6 4; opacity: 0.4; }
  /* Prereq done, successor not yet: solid, slightly brighter to show "unlocked" */
  .edge.unlocked { stroke: var(--amber); opacity: 0.55; }
  /* Both done */
  .edge.done { stroke: var(--sage); opacity: 0.5; }
  /* Terminal subtask → goal: dashed amber, shows the implicit feed-into-parent */
  .edge.goal-feed { stroke: var(--amber); stroke-dasharray: 5 4; opacity: 0.45; }
  .edge-group:hover .edge { stroke: var(--amber); opacity: 1; stroke-width: 3; }

  /* When a node is selected, its incident edges are emphasized and the rest
     fade back so the task's connections stand out.
     Dashed edges remain dashed — we only change stroke color and opacity. */
  .edge-group.edge-connected .edge {
    stroke: var(--amber);
    opacity: 1;
    stroke-width: 3.5;
  }
  /* Dependency edges (left of selected): dark red */
  .edge-group.edge-dep-lit .edge {
    stroke: var(--dep-edge);
    opacity: 1;
    stroke-width: 3.5;
  }
  /* Successor edges (right of selected): lighter orange */
  .edge-group.edge-suc-lit .edge {
    stroke: var(--suc-edge);
    opacity: 1;
    stroke-width: 3.5;
  }
  .edge-group.edge-dimmed .edge { opacity: 0.12; }

  /* ============== MENUBAR (Linear-style) ============== */
  .menubar {
    position: fixed;
    top: var(--safe-top); left: 0; right: 0;
    z-index: 50;
    pointer-events: none;
  }
  .menubar > * { pointer-events: auto; }

  /* Primary row */
  .menubar-row {
    height: 40px;
    display: flex;
    align-items: center;
    background: var(--paper-92);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    border-bottom: 1px solid var(--ink-08);
    padding: 0 8px;
    gap: 0;
  }

  /* Nav section: exit + back + out + breadcrumbs + grain */
  .mb-nav {
    display: flex;
    align-items: center;
    gap: 2px;
    flex: 1;
    min-width: 0;
    overflow: hidden;
  }

  /* Divider between sections */
  .mb-sep {
    width: 1px;
    height: 18px;
    background: var(--ink-12);
    flex-shrink: 0;
    margin: 0 6px;
  }

  /* Actions section */
  .mb-actions {
    display: flex;
    align-items: center;
    gap: 2px;
    flex-shrink: 0;
  }
  .mb-btn {
    width: 30px; height: 30px;
    border-radius: 6px;
    border: none;
    background: none;
    color: var(--ink-soft);
    display: flex; align-items: center; justify-content: center;
    cursor: pointer;
    transition: background .15s, color .15s;
  }
  .mb-btn:hover { background: var(--ink-07); color: var(--ink); }
  .mb-btn:active { background: var(--ink-12); }
  .mb-btn.active { background: var(--ink); color: var(--paper); }
  .mb-btn svg { width: 15px; height: 15px; }

  /* Touch devices: enlarge tap targets toward the 44px HIG minimum. The icons
     stay the same size; only the hit area grows. */
  @media (pointer: coarse) {
    .mb-btn, .mb-nav-btn { width: 38px; height: 38px; }
    .mb-btn svg, .mb-nav-btn svg { width: 17px; height: 17px; }
  }
  /* Very narrow screens: hide the wordmark so nav + actions fit without the
     breadcrumb getting crushed. The brand is decorative, not functional. */
  @media (max-width: 420px) {
    .brand { display: none; }
  }

  /* Nav items: back/out/exit look like mb-btn */
  .mb-nav-btn {
    width: 30px; height: 30px;
    border-radius: 6px;
    border: none;
    background: none;
    color: var(--ink-soft);
    display: flex; align-items: center; justify-content: center;
    cursor: pointer;
    transition: background .15s, color .15s;
    flex-shrink: 0;
  }
  .mb-nav-btn:hover { background: var(--ink-07); color: var(--ink); }
  .mb-nav-btn svg { width: 15px; height: 15px; }

  .brand {
    font-family: "Fraunces", serif;
    font-size: 15px;
    font-weight: 600;
    letter-spacing: -0.01em;
    color: var(--ink);
    display: flex;
    align-items: center;
    gap: 6px;
    flex-shrink: 0;
    padding: 0 6px;
  }
  .brand::before {
    content: "";
    width: 8px; height: 14px;
    background: var(--amber);
    border-radius: 2px;
    display: inline-block;
    transform: skewX(-8deg);
  }
  body.in-project .brand { display: none; }

  /* Breadcrumbs inside menubar */
  .breadcrumbs {
    display: flex;
    align-items: center;
    gap: 4px;
    flex: 1;
    min-width: 0;
    overflow: hidden;
    font-family: "Inter Tight", sans-serif;
  }
  .breadcrumb-item {
    flex-shrink: 1;
    min-width: 0;
    height: 26px;
    padding: 0 8px;
    border-radius: 6px;
    border: none;
    background: none;
    color: var(--ink-soft);
    font-size: 12px;
    font-weight: 500;
    cursor: pointer;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 140px;
    transition: color .15s, background .15s;
    display: flex;
    align-items: center;
  }
  .breadcrumb-item:hover { color: var(--ink); background: var(--ink-06); }
  .breadcrumb-item.current {
    color: var(--ink);
    font-weight: 600;
    cursor: default;
    background: var(--ink-06);
  }

  .grain-chip {
    flex-shrink: 0;
    padding: 2px 7px;
    border-radius: 4px;
    background: var(--bucket-after-12);
    color: var(--bucket-after-color);
    font-family: "Inter Tight", sans-serif;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    white-space: nowrap;
  }
  .grain-chip:empty { display: none; }
  .breadcrumb-sep {
    color: var(--ink-faint);
    font-size: 10px;
    flex-shrink: 0;
  }

  /* REMOVE OLD icon-btn style - replaced by mb-btn */
  .icon-btn {
    width: 30px; height: 30px;
    border-radius: 6px;
    border: none;
    background: none;
    color: var(--ink-soft);
    display: flex; align-items: center; justify-content: center;
    cursor: pointer;
    transition: background .15s, color .15s;
  }
  .icon-btn:hover { background: var(--ink-07); color: var(--ink); }
  .icon-btn:active { background: var(--ink-12); }
  .icon-btn.active { background: var(--ink); color: var(--paper); }
  .icon-btn svg { width: 15px; height: 15px; }

  /* Row 2: bucket headers - thinner, tracks canvas pan */
  .menubar-row-buckets {
    height: 32px;
    position: relative;
    overflow: hidden;
    background: var(--canvas-row2-bg);
    border-bottom: 1px solid var(--ink-06);
    /* Inherit blur from parent .menubar; don't re-apply (iOS rendering bug
       when nested backdrop-filters cover empty regions). */
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
  /* Row 3: milestone labels - same height when visible */
  .menubar-row-milestones {
    height: 32px;
    position: relative;
    overflow: hidden;
    background: var(--canvas-row3-bg);
    border-bottom: 1px solid var(--ink-05);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
  /* Hide the row entirely (no height) when no milestones exist OR when
     visually empty. JS sets a class for the latter case. */
  .menubar-row-milestones.is-hidden,
  body:not(.in-project) .menubar-row-milestones,
  body:not(.in-project) .menubar-row-buckets {
    display: none;
  }

  /* Bucket label in row 2 */
  .mb-bucket-label {
    position: absolute;
    top: 50%; transform: translate(-50%, -50%);
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 22px;
    padding: 0 10px;
    border-radius: 5px;
    font-family: "Inter Tight", sans-serif;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.10em;
    text-transform: uppercase;
    white-space: nowrap;
    cursor: pointer;
    user-select: none;
    pointer-events: auto;
    transition: opacity .15s, filter .15s;
  }
  /* Compressed: tighter padding, no text */
  .mb-bucket-label.compressed { padding: 0 7px; letter-spacing: 0; }
  .mb-bucket-label:hover { filter: brightness(0.9); }
  .mb-bucket-label.bl-archive { color: var(--bucket-archive-color); background: var(--bucket-archive-16); }
  .mb-bucket-label.bl-first  { color: var(--bucket-first-color); background: var(--bucket-first-18); }
  .mb-bucket-label.bl-then   { color: var(--bucket-then-color); background: var(--bucket-then-18); }
  .mb-bucket-label.bl-after  { color: var(--bucket-after-color); background: var(--bucket-after-18); }
  .mb-bucket-count {
    font-size: 10px;
    font-weight: 700;
    padding: 1px 5px;
    border-radius: 4px;
    line-height: 1.4;
    letter-spacing: 0;
    text-transform: none;
  }
  .bl-archive .mb-bucket-count { background: var(--bucket-archive-mid); color: var(--white); }
  .bl-first  .mb-bucket-count { background: var(--bucket-first-mid); color: var(--white); }
  .bl-then   .mb-bucket-count { background: var(--bucket-then-mid); color: var(--white); }
  .bl-after  .mb-bucket-count { background: var(--bucket-after-mid); color: var(--white); }

  /* Milestone label in row 3 */
  .mb-milestone-label {
    position: absolute;
    top: 50%; transform: translate(-50%, -50%);
    display: inline-flex;
    align-items: center;
    gap: 4px;
    height: 22px;
    padding: 0 8px;
    border-radius: 5px;
    font-family: "Inter Tight", sans-serif;
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.04em;
    color: var(--amber);
    background: var(--amber-08);
    white-space: nowrap;
    cursor: pointer;
    user-select: none;
    pointer-events: auto;
    transition: background .15s;
  }
  .mb-milestone-label:hover { background: var(--amber-15); }

  /* Canvas sits below all 3 rows: 40 + 32 + 32 = 104px
     But rows 2+3 only show when in-project. When not in project only row 1 (40px). */
  body.in-project #canvas { top: calc(var(--safe-top) + 104px) !important; }
  body:not(.in-project) #canvas { top: calc(var(--safe-top) + 40px) !important; }
  /* Plan banner clears row 1 only (it shows at depth 1+) */
  .plan-banner { top: calc(var(--safe-top) + 112px) !important; }


  /* ============== BOTTOM BAR ============== */
  .bottombar {
    position: fixed;
    bottom: calc(var(--safe-bottom) + 14px); left: 16px; right: 16px;
    z-index: 50;
    display: flex;
    gap: 10px;
    align-items: center;
    transition: transform .25s cubic-bezier(0.3, 0.7, 0.3, 1), opacity .2s;
  }
  /* Collapsed: slide down off-screen, but a small floating "+" stays via the
     separate .bottombar-fab. */
  .bottombar.collapsed {
    transform: translateY(120%);
    opacity: 0;
    pointer-events: none;
  }
  .bottombar-fab {
    position: fixed;
    bottom: calc(var(--safe-bottom) + 14px); right: 16px;
    z-index: 50;
    width: 52px; height: 52px;
    border-radius: 18px;
    border: none;
    background: var(--ink);
    color: var(--paper);
    cursor: pointer;
    box-shadow: var(--shadow-md);
    display: flex; align-items: center; justify-content: center;
    transition: transform .25s cubic-bezier(0.3, 0.7, 0.3, 1), opacity .2s;
  }
  .bottombar-fab svg { width: 22px; height: 22px; }
  .bottombar-fab:active { transform: scale(0.94); }
  /* The FAB only shows when the bottombar is collapsed */
  .bottombar-fab.hidden {
    transform: translateY(120%);
    opacity: 0;
    pointer-events: none;
  }
  .add-input {
    flex: 1;
    height: 52px;
    border-radius: 18px;
    border: 1px solid var(--ink-08);
    background: var(--white-88);
    backdrop-filter: blur(24px);
    -webkit-backdrop-filter: blur(24px);
    padding: 0 18px;
    font-family: "Inter Tight", sans-serif;
    font-size: 15px;
    color: var(--ink);
    box-shadow: var(--shadow-md);
    outline: none;
    transition: border-color .2s;
  }
  .add-input:focus { border-color: var(--amber); }
  .add-input::placeholder { color: var(--ink-faint); }

  .add-btn {
    width: 52px; height: 52px;
    border-radius: 18px;
    border: none;
    background: var(--ink);
    color: var(--paper);
    cursor: pointer;
    box-shadow: var(--shadow-md);
    display: flex; align-items: center; justify-content: center;
    transition: transform .12s;
  }
  .add-btn:active { transform: scale(0.92); }

  /* ============== INSPECTOR ============== */
  .inspector {
    position: fixed;
    bottom: 0; left: 0; right: 0;
    background: var(--paper-96);
    backdrop-filter: blur(30px);
    -webkit-backdrop-filter: blur(30px);
    border-top-left-radius: 24px;
    border-top-right-radius: 24px;
    border-top: 1px solid var(--ink-06);
    padding: 14px 20px calc(var(--safe-bottom) + 20px);
    transform: translateY(100%);
    transition: transform .4s cubic-bezier(.2,.9,.3,1);
    z-index: 60;
    box-shadow: 0 -10px 40px var(--ink-12);
    max-height: 80vh;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    touch-action: pan-y;
  }
  .inspector.open { transform: translateY(0); }
  .inspector-handle {
    width: 40px; height: 4px;
    background: var(--ink-faint);
    opacity: 0.4;
    border-radius: 2px;
    margin: 2px auto 14px;
  }
  .inspector h3 {
    font-family: "Fraunces", serif;
    font-weight: 500;
    font-size: 22px;
    line-height: 1.2;
    margin: 0 0 16px;
    color: var(--ink);
  }
  .insp-row {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 10px 0;
  }
  .insp-label {
    width: 80px;
    font-size: 12px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--ink-faint);
    font-weight: 500;
  }
  .insp-slider {
    flex: 1;
    -webkit-appearance: none;
    appearance: none;
    height: 4px;
    background: var(--paper-2);
    border-radius: 2px;
    outline: none;
  }
  .insp-slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 22px; height: 22px;
    background: var(--amber);
    border-radius: 50%;
    cursor: pointer;
    border: 2px solid var(--white);
    box-shadow: var(--shadow-sm);
  }
  .insp-value {
    width: 32px;
    text-align: right;
    font-variant-numeric: tabular-nums;
    font-weight: 500;
    color: var(--ink);
    font-size: 14px;
  }
  .insp-title-input {
    width: 100%;
    border: none;
    background: transparent;
    font-family: "Fraunces", serif;
    font-weight: 500;
    font-size: 22px;
    color: var(--ink);
    outline: none;
    border-bottom: 1px solid var(--ink-08);
    padding: 4px 0 8px;
    margin-bottom: 8px;
  }
  .insp-actions {
    display: flex; gap: 10px;
    margin-top: 14px;
  }
  .insp-btn {
    flex: 1;
    height: 44px;
    border-radius: 14px;
    border: 1px solid var(--ink-10);
    background: var(--white);
    font-family: inherit;
    font-size: 14px;
    font-weight: 500;
    color: var(--ink);
    cursor: pointer;
    transition: transform .12s, background .2s;
  }
  .insp-btn:active { transform: scale(0.97); }
  .insp-btn.danger { color: var(--danger); border-color: var(--danger-20); }
  .insp-btn.primary { background: var(--ink); color: var(--paper); border-color: var(--ink); }

  /* ============== FOCUS MODE ============== */
  /* Dim non-focus nodes directly - no overlay pseudo-element needed. */
  .node.dimmed {
    opacity: 0.15;
    pointer-events: none;
  }
  /* Focus-highlighted nodes look completely normal - they simply aren't dimmed.
     The contrast comes from everything else being faded out. */
  /* Rank badge on focus-highlighted nodes: show position (1, 2, 3) */
  body.focus-mode .focus-highlight .focus-rank {
    display: flex;
  }
  .focus-rank {
    display: none;
    position: absolute;
    top: -10px; left: -10px;
    width: 22px; height: 22px;
    border-radius: 50%;
    background: var(--amber);
    color: var(--white);
    font-family: "Inter Tight", sans-serif;
    font-size: 11px;
    font-weight: 700;
    align-items: center;
    justify-content: center;
    z-index: 11;
    box-shadow: 0 2px 6px var(--amber-40);
  }

  /* ============== EDGE MODAL ============== */
  .modal-backdrop {
    position: fixed;
    inset: 0;
    background: var(--ink-35);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    z-index: 100;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    opacity: 0;
    pointer-events: none;
    transition: opacity .25s;
  }
  .modal-backdrop.open { opacity: 1; pointer-events: auto; }
  .modal-sheet {
    background: var(--paper-98);
    backdrop-filter: blur(30px);
    -webkit-backdrop-filter: blur(30px);
    border-top-left-radius: 24px;
    border-top-right-radius: 24px;
    width: 100%;
    max-width: 480px;
    padding: 14px 22px calc(var(--safe-bottom) + 24px);
    box-shadow: 0 -10px 50px var(--ink-18);
    transform: translateY(40px);
    transition: transform .35s cubic-bezier(.2,.9,.3,1);
  }
  .modal-backdrop.open .modal-sheet { transform: translateY(0); }
  @media (min-width: 600px) {
    .modal-backdrop { align-items: center; }
    .modal-sheet { border-radius: 24px; margin: 0 20px; }
  }
  .modal-handle {
    width: 40px; height: 4px;
    background: var(--ink-faint);
    opacity: 0.4;
    border-radius: 2px;
    margin: 2px auto 16px;
  }
  .modal-title {
    font-family: "Fraunces", serif;
    font-size: 22px;
    font-weight: 500;
    color: var(--ink);
    margin-bottom: 14px;
  }
  .modal-edge-row {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
    margin-bottom: 12px;
  }
  .modal-node-pill {
    background: var(--white);
    border: 1px solid var(--ink-10);
    border-radius: 10px;
    padding: 8px 12px;
    font-size: 13px;
    font-weight: 500;
    color: var(--ink);
    max-width: 180px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    box-shadow: var(--shadow-sm);
  }
  .modal-arrow { flex-shrink: 0; }
  .modal-desc {
    font-size: 13px;
    color: var(--ink-soft);
    line-height: 1.5;
    margin: 6px 0 4px;
  }
  .cascade-options {
    display: flex;
    flex-direction: column;
    gap: 8px;
    margin-top: 12px;
  }
  .cascade-option {
    border: 1px solid var(--ink-08);
    border-radius: 10px;
    padding: 10px 12px;
    background: var(--bucket-first-06);
  }
  .cascade-option-skip {
    background: var(--bucket-archive-06);
  }
  .cascade-option-label {
    font-family: "Inter Tight", sans-serif;
    font-size: 13px;
    font-weight: 600;
    color: var(--ink);
    margin-bottom: 2px;
  }
  .cascade-option-desc {
    font-size: 12px;
    color: var(--ink-soft);
    line-height: 1.45;
  }
  .modal-actions {
    display: flex; gap: 10px;
    margin-top: 14px;
  }
  /* ============== PLAN MODE BANNER ============== */
  .plan-banner {
    position: fixed;
    top: calc(var(--safe-top) + 64px);
    left: 16px; right: 16px;
    z-index: 45;
    background: var(--plan-banner-bg);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    border: 1px solid var(--amber-30);
    border-radius: 14px;
    padding: 10px 14px;
    box-shadow: var(--shadow-md);
  }
  .plan-banner-row {
    display: flex;
    align-items: center;
    gap: 12px;
  }
  .plan-banner-label {
    flex-shrink: 0;
    font-family: "Inter Tight", sans-serif;
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: 0.14em;
    color: var(--amber);
    background: var(--amber-12);
    padding: 4px 8px;
    border-radius: 6px;
  }
  .plan-banner-bars {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
  }
  .plan-bar {
    position: relative;
    height: 22px;
    background: var(--ink-06);
    border-radius: 8px;
    overflow: hidden;
  }
  .plan-bar-fill {
    position: absolute;
    inset: 0;
    width: 0%;
    border-radius: 8px;
    transition: width .3s cubic-bezier(0.3, 0.7, 0.3, 1), background .3s;
  }
  .plan-bar-target .plan-bar-fill {
    background: linear-gradient(90deg, var(--ink-18), var(--ink-10));
  }
  .plan-bar-current .plan-bar-fill {
    background: linear-gradient(90deg, var(--sage-50), var(--sage-28));
  }
  .plan-bar-current.over .plan-bar-fill {
    background: linear-gradient(90deg, var(--plan-over-from), var(--plan-over-to));
  }
  .plan-bar-current.match .plan-bar-fill {
    background: linear-gradient(90deg, var(--sage-70), var(--sage-42));
  }
  .plan-bar-text {
    position: relative;
    z-index: 1;
    padding: 0 10px;
    line-height: 22px;
    font-family: "Inter Tight", sans-serif;
    font-size: 11px;
    font-weight: 500;
    color: var(--ink-soft);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .plan-bar-text span {
    font-weight: 600;
    color: var(--ink);
    font-variant-numeric: tabular-nums;
  }
  #plan-banner-commit {
    flex-shrink: 0;
  }

  /* ============== PROJECTS LIST ============== */
  .projects-list {
    position: fixed;
    inset: 0;
    background:
      radial-gradient(circle at 25% 15%, var(--amber-soft-10), transparent 55%),
      radial-gradient(circle at 80% 85%, var(--sage-07), transparent 55%),
      var(--paper);
    z-index: 100;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    /* body sets touch-action:none for the canvas; re-enable vertical panning
       here so the project grid scrolls on touch devices. */
    touch-action: pan-y;
  }
  .projects-list-inner {
    max-width: 920px;
    margin: 0 auto;
    padding: calc(var(--safe-top) + 56px) 20px calc(var(--safe-bottom) + 40px);
  }
  .projects-title {
    font-family: "Fraunces", Georgia, serif;
    font-weight: 400;
    font-size: 38px;
    letter-spacing: -0.02em;
    color: var(--ink);
    margin: 0 0 32px;
  }
  .projects-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 14px;
  }
  .project-card {
    position: relative;
    background: var(--white-85);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    border: 1px solid var(--ink-08);
    border-radius: 18px;
    padding: 18px 18px 16px;
    cursor: pointer;
    transition: transform .12s, box-shadow .2s, border-color .2s;
    box-shadow: var(--shadow-sm);
    overflow: hidden;
    min-height: 140px;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
  }
  .project-card:hover {
    border-color: var(--amber);
    box-shadow: var(--shadow-md);
  }
  .project-card:active { transform: scale(0.985); }
  .project-card-name {
    font-family: "Fraunces", Georgia, serif;
    font-weight: 500;
    font-size: 20px;
    line-height: 1.2;
    color: var(--ink);
    word-break: break-word;
    margin-bottom: 12px;
  }
  .project-card-meta {
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-family: "Inter Tight", sans-serif;
    font-size: 11px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ink-faint);
    font-weight: 500;
  }
  .project-card-grain {
    color: var(--amber);
    background: var(--amber-10);
    padding: 4px 10px;
    border-radius: 999px;
  }
  .project-card-progress {
    color: var(--sage);
  }
  /* Tiny progress fill at the bottom of the card */
  .project-card::after {
    content: "";
    position: absolute;
    bottom: 0; left: 0;
    width: var(--progress, 0%);
    height: 3px;
    background: linear-gradient(90deg, var(--sage-60), var(--sage-35));
    transition: width .35s cubic-bezier(0.3, 0.7, 0.3, 1);
  }
  .project-card-delete {
    position: absolute;
    top: 8px; right: 8px;
    width: 26px; height: 26px;
    border-radius: 50%;
    border: none;
    background: var(--ink-05);
    color: var(--ink-faint);
    cursor: pointer;
    opacity: 0;
    transition: opacity .2s, background .2s, color .2s;
    display: flex; align-items: center; justify-content: center;
    padding: 0;
  }
  .project-card:hover .project-card-delete { opacity: 1; }
  .project-card-delete:hover {
    background: var(--danger-12);
    color: var(--danger);
  }
  .project-card-delete svg { width: 13px; height: 13px; }

  /* Rename (pencil) button - sits left of the delete button */
  .project-card-rename {
    position: absolute;
    top: 8px; right: 40px;
    width: 26px; height: 26px;
    border-radius: 50%;
    border: none;
    background: var(--ink-05);
    color: var(--ink-faint);
    cursor: pointer;
    opacity: 0;
    transition: opacity .2s, background .2s, color .2s;
    display: flex; align-items: center; justify-content: center;
    padding: 0;
  }
  .project-card:hover .project-card-rename { opacity: 1; }
  .project-card-rename:hover {
    background: var(--amber-12);
    color: var(--amber);
  }
  .project-card-rename svg { width: 13px; height: 13px; }
  @media (pointer: coarse) {
    .project-card-delete, .project-card-rename { opacity: 0.6; }
  }
  /* Editing state for the inline name field */
  .project-card-name.editing {
    outline: none;
    background: var(--amber-08);
    border-radius: 6px;
    padding: 2px 6px;
    margin: -2px -6px;
    cursor: text;
    caret-color: var(--amber);
  }

  /* "New project" card variant */
  .project-card.new-card {
    background: transparent;
    border: 1.5px dashed var(--ink-18);
    box-shadow: none;
    align-items: center;
    justify-content: center;
    text-align: center;
  }
  .project-card.new-card:hover {
    border-color: var(--amber);
    border-style: solid;
    background: var(--new-card-hover-bg);
  }
  .new-card-plus {
    width: 44px; height: 44px;
    border-radius: 50%;
    background: var(--ink);
    color: var(--paper);
    display: flex; align-items: center; justify-content: center;
    margin-bottom: 14px;
  }
  .new-card-plus svg { width: 22px; height: 22px; }
  .new-card-label {
    font-family: "Inter Tight", sans-serif;
    font-size: 13px;
    font-weight: 500;
    color: var(--ink-soft);
  }

  /* ============== GRAIN PICKER ============== */
  .grain-options {
    display: flex;
    flex-direction: row;
    gap: 8px;
    margin-top: 10px;
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    padding: 4px 2px 8px;
    scrollbar-width: thin;
  }
  .grain-options::-webkit-scrollbar { height: 4px; }
  .grain-options::-webkit-scrollbar-thumb { background: var(--ink-15); border-radius: 2px; }
  .grain-option {
    flex: 0 0 auto;
    min-width: 110px;
    border: 1px solid var(--ink-10);
    background: var(--white);
    border-radius: 12px;
    padding: 12px 14px;
    cursor: pointer;
    text-align: left;
    transition: all .15s;
    font-family: inherit;
  }
  .grain-option:hover {
    border-color: var(--ink);
  }
  .grain-option.selected {
    background: var(--ink);
    color: var(--paper);
    border-color: var(--ink);
  }
  /* Sub-levels hint under the grain options */
  .grain-sublevel-hint {
    font-family: "Inter Tight", sans-serif;
    font-size: 12px;
    color: var(--ink-faint);
    margin-top: 8px;
    font-style: italic;
  }
  .grain-option-name {
    font-family: "Fraunces", Georgia, serif;
    font-weight: 500;
    font-size: 16px;
    text-transform: capitalize;
  }
  .grain-option-desc {
    font-family: "Inter Tight", sans-serif;
    font-size: 11px;
    color: var(--ink-faint);
    margin-top: 2px;
    letter-spacing: 0.04em;
  }
  .grain-option.selected .grain-option-desc {
    color: var(--paper-70);
  }

  /* Hide canvas affordances when in projects-list view */
  body.viewing-projects .menubar,
  body.viewing-projects .bottombar,
  body.viewing-projects .legend,
  body.viewing-projects #canvas,
  body.viewing-projects .plan-banner { display: none !important; }

  /* Show bucket/milestone bar rows in showcase view-only mode (override body:not(.in-project) rule) */
  body.showcase-view .menubar-row-buckets,
  body.showcase-view .menubar-row-milestones { display: flex !important; }
  /* Hide edit-only menubar buttons in showcase view via CSS (belt and suspenders with JS) */
  body.showcase-view #btn-add-milestone,
  body.showcase-view #btn-focus,
  body.showcase-view #btn-autolayout { display: none !important; }

  /* ============== MINIMAP POPOVER ==============
     The minimap appears as a small popover beneath a breadcrumb item on hover.
     Each hover shows only the level that breadcrumb represents. */
  .minimap-popover {
    position: fixed;
    z-index: 200;
    background: var(--paper);
    border: 1px solid var(--ink-08);
    border-radius: 12px;
    box-shadow: 0 8px 28px var(--ink-18);
    padding: 10px 12px;
    width: 320px;
    opacity: 0;
    transform: translateY(-4px);
    transition: opacity .15s, transform .15s;
    /* pointer-events enabled so the user can hover over the popover itself
       without it disappearing. */
  }
  .minimap-popover.open {
    opacity: 1;
    transform: translateY(0);
  }
  .minimap-popover-label {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    margin-bottom: 6px;
  }
  .minimap-popover-name {
    font-family: "Fraunces", Georgia, serif;
    font-size: 13px;
    font-weight: 500;
    color: var(--ink);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    flex: 1;
    margin-right: 8px;
  }
  .minimap-popover-grain {
    font-family: "Inter Tight", sans-serif;
    font-size: 10px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--ink-faint);
    flex-shrink: 0;
  }
  .minimap-canvas {
    width: 100%;
    height: 100px;
    display: block;
    border-radius: 6px;
    background: var(--ink-02);
  }
  .minimap-empty {
    font-family: "Inter Tight", sans-serif;
    font-size: 11px;
    color: var(--ink-faint);
    text-align: center;
    padding: 24px 0;
    font-style: italic;
  }

  /* ============== TASK DETAIL PANEL ============== */
  #detail-stack-container {
    position: fixed;
    inset: 0;
    pointer-events: none;
    z-index: 300;
  }
  .detail-sheet {
    position: absolute;
    top: 0; right: 0; bottom: 0;
    width: min(480px, 100vw);
    background: var(--paper);
    box-shadow: -8px 0 48px var(--ink-18);
    display: flex;
    flex-direction: column;
    pointer-events: auto;
    transform: translateX(100%);
    transition: transform .28s cubic-bezier(0.3, 0.7, 0.3, 1),
                box-shadow .28s,
                right .28s cubic-bezier(0.3, 0.7, 0.3, 1);
    overflow: hidden;
  }
  .detail-sheet.open {
    transform: translateX(0);
  }
  /* Each additional sheet stacks slightly to the left and darker shadow */
  .detail-sheet:not(:last-child) {
    right: 20px;
    box-shadow: -4px 0 24px var(--ink-12);
    filter: brightness(0.97);
  }
  .detail-header {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: calc(var(--safe-top) + 14px) 16px 14px;
    border-bottom: 1px solid var(--ink-07);
    flex-shrink: 0;
  }
  .detail-back-btn {
    width: 32px; height: 32px;
    border-radius: 10px;
    border: none;
    background: var(--ink-06);
    color: var(--ink-soft);
    cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    flex-shrink: 0;
  }
  .detail-back-btn:active { background: var(--ink-12); }
  .detail-back-btn svg { width: 18px; height: 18px; }
  .detail-title-input {
    flex: 1;
    font-family: "Fraunces", Georgia, serif;
    font-size: 18px;
    font-weight: 500;
    color: var(--ink);
    background: none;
    border: none;
    outline: none;
    min-width: 0;
  }
  /* Linear-style properties bar: horizontal row of compact chips */
  .detail-props {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px;
    padding: 12px 16px 14px;
    border-bottom: 1px solid var(--ink-07);
    flex-shrink: 0;
  }
  .detail-prop {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    height: 26px;
    padding: 0 10px;
    border-radius: 6px;
    border: none;
    background: var(--ink-04);
    font-family: "Inter Tight", sans-serif;
    font-size: 12px;
    font-weight: 500;
    color: var(--ink-soft);
    cursor: default;
    white-space: nowrap;
    transition: background .12s, color .12s;
  }
  /* Status pill is interactive */
  .detail-prop-status { cursor: pointer; padding-left: 6px; }
  .detail-prop-status:hover { background: var(--ink-08); color: var(--ink); }
  .detail-prop-status:active { transform: scale(0.97); }
  /* State-tinted backgrounds for the status pill */
  .detail-prop-status.ps-todo         { background: var(--ink-05); }
  .detail-prop-status.ps-progress-33,
  .detail-prop-status.ps-progress-66  { background: var(--amber-10); color: var(--status-progress-color); }
  .detail-prop-status.ps-done         { background: var(--bucket-first-18); color: var(--status-done-color); }
  .detail-prop-status.ps-skipped      { background: var(--bucket-archive-18); color: var(--ink-soft); }
  .detail-prop-icon {
    display: flex; align-items: center; justify-content: center;
    width: 18px; height: 18px;
    flex-shrink: 0;
  }
  .detail-prop-icon svg { width: 18px; height: 18px; display: block; }
  .detail-prop-icon-sm { width: 12px; height: 12px; flex-shrink: 0; opacity: 0.7; }
  .detail-prop-label { line-height: 1; }

  /* Bucket chip with colored dot */
  .detail-prop-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }
  .detail-prop-bucket.bucket-first  .detail-prop-dot { background: var(--bucket-first-mid); }
  .detail-prop-bucket.bucket-then   .detail-prop-dot { background: var(--bucket-then-mid); }
  .detail-prop-bucket.bucket-after  .detail-prop-dot { background: var(--bucket-after-mid); }
  .detail-prop-bucket.bucket-first  { color: var(--bucket-first-color); background: var(--bucket-first-10); }
  .detail-prop-bucket.bucket-then   { color: var(--bucket-then-color); background: var(--bucket-then-10); }
  .detail-prop-bucket.bucket-after  { color: var(--bucket-after-color); background: var(--bucket-after-10); }

  /* Tooltip on stars: shows formula explanation on hover (desktop) or tap (mobile). */
  .detail-prop-stars {
    position: relative;
    cursor: help;
    outline: none;
  }
  .detail-prop-tip {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    width: 260px;
    background: var(--ink);
    color: var(--paper);
    padding: 10px 12px;
    border-radius: 8px;
    font-family: "Inter Tight", sans-serif;
    font-size: 11px;
    font-weight: 400;
    line-height: 1.5;
    box-shadow: 0 8px 24px var(--ink-25);
    z-index: 400;
    pointer-events: none;
    opacity: 0;
    transform: translateY(-2px);
    transition: opacity .15s, transform .15s;
    white-space: normal;
    letter-spacing: 0;
  }
  .detail-prop-tip strong { color: var(--paper); font-weight: 600; }
  .detail-prop-stars:hover .detail-prop-tip,
  .detail-prop-stars:focus .detail-prop-tip,
  .detail-prop-stars.tip-open .detail-prop-tip,
  .detail-prop-effort:hover .detail-prop-tip,
  .detail-prop-effort:focus .detail-prop-tip,
  .detail-prop-effort.tip-open .detail-prop-tip {
    opacity: 1;
    transform: translateY(0);
  }
  .detail-prop-effort { position: relative; cursor: help; outline: none; }
  .detail-body {
    flex: 1;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    touch-action: pan-y;
    padding: 0 16px calc(var(--safe-bottom) + 16px);
  }

  /* Sections inside detail */
  .detail-section {
    padding: 14px 0;
    border-bottom: 1px solid var(--ink-06);
  }
  .detail-section:last-child { border-bottom: none; }
  .detail-section-label {
    font-family: "Inter Tight", sans-serif;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.10em;
    text-transform: uppercase;
    color: var(--ink-faint);
    margin-bottom: 8px;
  }

  /* Minimap inside detail */
  .detail-minimap { border-radius: 8px; overflow: hidden; width: 100%; }
  .detail-minimap svg { width: 100%; height: 120px; display: block; }

  /* Dep/successor chips */
  .detail-chips { display: flex; flex-wrap: wrap; gap: 6px; }
  .detail-chip {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 5px 10px;
    border-radius: 8px;
    border: 1px solid var(--ink-10);
    background: var(--white);
    font-family: "Inter Tight", sans-serif;
    font-size: 12px;
    color: var(--ink-soft);
    cursor: pointer;
    transition: border-color .15s, background .15s;
    max-width: 200px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .detail-chip:hover { border-color: var(--amber); color: var(--ink); }
  .detail-chip-dot { width: 7px; height: 7px; border-radius: 50%; flex-shrink: 0; }
  .detail-chip-dep .detail-chip-dot { background: var(--bucket-then-mid); }
  .detail-chip-succ .detail-chip-dot { background: var(--bucket-after-mid); }

  /* Description */
  .detail-desc-view {
    font-size: 14px;
    color: var(--ink-soft);
    line-height: 1.6;
    cursor: text;
    min-height: 40px;
    border-radius: 8px;
    padding: 8px;
    margin: -8px;
    transition: background .15s;
  }
  .detail-desc-view:hover { background: var(--ink-03); }
  .detail-desc-view.empty { color: var(--ink-faint); font-style: italic; }
  .detail-desc-view a { color: var(--amber); text-decoration: underline; }
  .detail-desc-view p { margin: 0 0 8px 0; }
  .detail-desc-view p:last-child { margin-bottom: 0; }
  .detail-desc-view strong { color: var(--ink); font-weight: 600; }
  .detail-desc-view em { font-style: italic; }
  .detail-desc-view code {
    background: var(--ink-07);
    padding: 1px 5px;
    border-radius: 4px;
    font-size: 13px;
    font-family: ui-monospace, "SF Mono", Menlo, Consolas, monospace;
    color: var(--ink);
  }
  .detail-desc-view h1, .detail-desc-view h2, .detail-desc-view h3 {
    color: var(--ink);
    margin: 12px 0 6px;
    font-family: "Fraunces", Georgia, serif;
    font-weight: 600;
    line-height: 1.3;
  }
  .detail-desc-view h1:first-child,
  .detail-desc-view h2:first-child,
  .detail-desc-view h3:first-child { margin-top: 0; }
  .detail-desc-view h1 { font-size: 18px; }
  .detail-desc-view h2 { font-size: 16px; }
  .detail-desc-view h3 { font-size: 14px; }
  .detail-desc-view ul {
    margin: 0 0 8px 0;
    padding-left: 20px;
  }
  .detail-desc-view li { margin: 2px 0; }
  .detail-desc-edit {
    width: 100%;
    min-height: 80px;
    border: 1.5px solid var(--amber);
    border-radius: 8px;
    padding: 8px;
    font-size: 14px;
    font-family: inherit;
    color: var(--ink);
    background: var(--white);
    resize: vertical;
    outline: none;
    line-height: 1.6;
    box-sizing: border-box;
  }

  /* Comments */
  .detail-comment {
    background: var(--ink-03);
    border-radius: 10px;
    padding: 10px 12px;
    margin-bottom: 8px;
  }
  .detail-comment-text {
    font-size: 13px;
    color: var(--ink);
    line-height: 1.5;
    margin-bottom: 4px;
    white-space: pre-wrap;
  }
  .detail-comment-meta {
    font-size: 11px;
    color: var(--ink-faint);
  }
  .detail-comment-input {
    width: 100%;
    border: 1px solid var(--ink-12);
    border-radius: 10px;
    padding: 8px 10px;
    font-size: 13px;
    font-family: inherit;
    color: var(--ink);
    background: var(--white);
    outline: none;
    resize: none;
    min-height: 36px;
    box-sizing: border-box;
    transition: border-color .15s;
  }
  .detail-comment-input:focus { border-color: var(--amber); }

  /* Icons on canvas nodes */
  .node-info-icons {
    position: absolute;
    bottom: 4px; right: 4px;
    display: flex;
    gap: 3px;
    align-items: center;
    z-index: 2;
  }
  .node-info-icon {
    display: flex;
    align-items: center;
    gap: 2px;
    padding: 2px 5px;
    border-radius: 5px;
    background: var(--ink-08);
    font-size: 9px;
    font-family: "Inter Tight", sans-serif;
    color: var(--ink-faint);
    line-height: 1;
  }
  .node-info-icon svg { width: 10px; height: 10px; }

  .toast {
    position: fixed;
    top: calc(var(--safe-top) + 72px);
    left: 50%;
    transform: translateX(-50%) translateY(-20px);
    background: var(--ink-92);
    color: var(--paper);
    padding: 10px 18px;
    border-radius: 14px;
    font-size: 13.5px;
    font-weight: 500;
    backdrop-filter: blur(20px);
    z-index: 200;
    opacity: 0;
    transition: opacity .3s, transform .3s;
    pointer-events: none;
    box-shadow: var(--shadow-md);
  }
  .toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }

  /* ============== CONNECT GHOST LINE ============== */
  #connect-ghost {
    position: absolute;
    top: 0; left: 0;
    width: 100%;
    height: 100%;
    pointer-events: none;
    z-index: 99;
    overflow: visible;
  }
  .ghost-line {
    fill: none;
    stroke: var(--amber);
    stroke-width: 2;
    stroke-dasharray: 6 4;
    opacity: 0.8;
  }
  /* Small "phantom card" that follows the pointer when dragging a connector,
     making it visually clear you're dragging a new connection target. */
  .ghost-target-box {
    fill: var(--white-95);
    stroke: var(--amber);
    stroke-width: 2;
    stroke-dasharray: 4 3;
    rx: 6;
  }

  /* ============== EMPTY HINT ============== */
  .hint {
    position: absolute;
    top: 50%; left: 50%;
    transform: translate(-50%, -50%);
    text-align: center;
    color: var(--ink-faint);
    font-family: "Fraunces", serif;
    pointer-events: none;
    z-index: 1;
  }
  .hint h2 { font-weight: 400; font-size: 28px; margin: 0 0 8px; color: var(--ink-soft); }
  .hint p { font-family: "Inter Tight", sans-serif; font-size: 14px; margin: 0; }

  /* Mini help legend */
  .legend {
    position: fixed;
    left: 16px;
    bottom: calc(var(--safe-bottom) + 80px);
    background: var(--white-85);
    backdrop-filter: blur(20px);
    border: 1px solid var(--ink-06);
    border-radius: 14px;
    padding: 10px 12px;
    font-size: 11px;
    color: var(--ink-soft);
    z-index: 40;
    box-shadow: var(--shadow-sm);
    line-height: 1.5;
    max-width: 200px;
    opacity: 0;
    transform: translateY(8px);
    transition: opacity .3s, transform .3s;
    pointer-events: none;
  }
  .legend.show { opacity: 1; transform: translateY(0); }
  .legend strong { color: var(--ink); font-weight: 600; }
  .legend-row { display: flex; align-items: center; gap: 6px; }
  .legend-box { display: inline-block; background: var(--amber); border-radius: 2px; }

  /* ─────────────────────────────────────────────────────
     COMMUNITY SHOWCASE
     ───────────────────────────────────────────────────── */

  /* Entry button — below projects grid */
  .showcase-btn {
    display: flex;
    align-items: center;
    gap: 14px;
    width: 100%;
    margin-top: 24px;
    padding: 15px 18px;
    background: transparent;
    border: 1.5px dashed var(--ink-15);
    border-radius: 16px;
    cursor: pointer;
    text-align: left;
    transition: border-color .2s, background .2s;
  }
  .showcase-btn:hover {
    border-color: var(--amber);
    border-style: solid;
    background: var(--amber-08);
  }
  .showcase-btn-icon {
    width: 38px; height: 38px;
    border-radius: 50%;
    background: var(--ink-06);
    display: flex; align-items: center; justify-content: center;
    font-size: 17px;
    flex-shrink: 0;
    color: var(--ink-soft);
  }
  .showcase-btn-text { flex: 1; }
  .showcase-btn-label {
    font-family: "Inter Tight", sans-serif;
    font-size: 14px;
    font-weight: 600;
    color: var(--ink);
    line-height: 1.3;
  }
  .showcase-btn-sub {
    font-family: "Inter Tight", sans-serif;
    font-size: 12px;
    color: var(--ink-faint);
    margin-top: 2px;
  }
  .showcase-btn-arrow { color: var(--ink-faint); flex-shrink: 0; }

  /* Full-screen overlay — slides in from the right */
  .showcase-overlay {
    position: fixed;
    inset: 0;
    background:
      radial-gradient(circle at 80% 10%, var(--amber-soft-08), transparent 50%),
      radial-gradient(circle at 15% 85%, var(--sage-07), transparent 55%),
      var(--paper);
    z-index: 110;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    touch-action: pan-y;
    opacity: 0;
    transform: translateX(28px);
    pointer-events: none;
    transition: opacity .22s, transform .28s cubic-bezier(.2,.9,.3,1);
  }
  .showcase-overlay.open {
    opacity: 1;
    transform: translateX(0);
    pointer-events: auto;
  }

  .showcase-inner {
    max-width: 680px;
    margin: 0 auto;
    padding: calc(var(--safe-top) + 52px) 20px calc(var(--safe-bottom) + 60px);
  }

  .showcase-back {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    background: none;
    border: none;
    color: var(--amber);
    font-family: "Inter Tight", sans-serif;
    font-size: 14px;
    font-weight: 500;
    cursor: pointer;
    padding: 0;
    margin-bottom: 20px;
    transition: opacity .15s;
  }
  .showcase-back:hover { opacity: 0.75; }

  .showcase-title {
    font-family: "Fraunces", Georgia, serif;
    font-weight: 400;
    font-size: 32px;
    letter-spacing: -0.02em;
    color: var(--ink);
    margin: 0 0 4px;
  }
  .showcase-subtitle {
    font-family: "Inter Tight", sans-serif;
    font-size: 13px;
    color: var(--ink-faint);
    margin: 0 0 28px;
  }

  /* Card list */
  .showcase-list { display: flex; flex-direction: column; gap: 18px; }

  .showcase-card {
    background: var(--white-85);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    border: 1px solid var(--ink-08);
    border-radius: 18px;
    overflow: hidden;
    box-shadow: var(--shadow-sm);
    transition: box-shadow .2s, border-color .2s;
  }
  .showcase-card:hover { box-shadow: var(--shadow-md); border-color: var(--ink-12); }

  /* Minimap */
  .showcase-minimap {
    width: 100%;
    height: 168px;
    background: var(--ink-03);
    border-bottom: 1px solid var(--ink-06);
    display: block;
    overflow: hidden;
  }
  .showcase-minimap svg { width: 100%; height: 100%; display: block; }

  /* Card body */
  .showcase-card-body { padding: 15px 18px 17px; }

  .showcase-tags { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 9px; }
  .showcase-tag {
    font-family: "Inter Tight", sans-serif;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    padding: 3px 9px;
    border-radius: 999px;
    background: var(--amber-10);
    color: var(--amber);
  }
  .showcase-tag.featured { background: var(--ink); color: var(--paper); }

  .showcase-card-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 10px;
    margin-bottom: 7px;
  }
  .showcase-card-name {
    font-family: "Fraunces", Georgia, serif;
    font-weight: 500;
    font-size: 19px;
    color: var(--ink);
    line-height: 1.2;
  }
  .showcase-stars {
    display: flex;
    align-items: center;
    gap: 1px;
    flex-shrink: 0;
    margin-top: 3px;
  }
  .showcase-star { color: var(--gold); font-size: 13px; line-height: 1; }
  .showcase-rating-text {
    font-family: "Inter Tight", sans-serif;
    font-size: 11px;
    color: var(--ink-faint);
    margin-left: 5px;
    white-space: nowrap;
  }

  .showcase-desc {
    font-family: "Inter Tight", sans-serif;
    font-size: 13px;
    color: var(--ink-soft);
    line-height: 1.55;
    margin-bottom: 13px;
  }

  .showcase-comments {
    display: flex;
    flex-direction: column;
    gap: 9px;
    border-top: 1px solid var(--ink-06);
    padding-top: 12px;
  }
  .showcase-comment { display: flex; gap: 10px; align-items: flex-start; }
  .showcase-comment-avatar {
    width: 26px; height: 26px;
    border-radius: 50%;
    background: var(--amber-12);
    color: var(--amber);
    font-family: "Inter Tight", sans-serif;
    font-size: 11px;
    font-weight: 700;
    display: flex; align-items: center; justify-content: center;
    flex-shrink: 0;
  }
  .showcase-comment-avatar.editor { background: var(--ink); color: var(--paper); font-size: 12px; }
  .showcase-comment-who {
    font-family: "Inter Tight", sans-serif;
    font-size: 11px;
    font-weight: 600;
    color: var(--ink);
    margin-bottom: 2px;
  }
  .showcase-comment-text {
    font-family: "Inter Tight", sans-serif;
    font-size: 12px;
    color: var(--ink-soft);
    line-height: 1.45;
  }

  /* ── View-only toolbar (row 2 inside .menubar when in showcase-view) ── */
  .viewonly-bar {
    height: 44px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 12px;
    background: var(--paper-92);
    border-bottom: 1px solid var(--ink-08);
    gap: 10px;
    flex-shrink: 0;
  }
  .viewonly-back-btn {
    display: flex;
    align-items: center;
    gap: 5px;
    background: none;
    border: none;
    padding: 6px 8px;
    border-radius: 8px;
    font-family: "Inter Tight", sans-serif;
    font-size: 13px;
    font-weight: 500;
    color: var(--ink-soft);
    cursor: pointer;
    white-space: nowrap;
    transition: background .15s, color .15s;
  }
  .viewonly-back-btn:hover { background: var(--ink-06); color: var(--ink); }
  .viewonly-label {
    font-family: "Inter Tight", sans-serif;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--amber);
    background: var(--amber-10);
    padding: 3px 10px;
    border-radius: 999px;
    white-space: nowrap;
  }
  .viewonly-clone-btn {
    display: flex;
    align-items: center;
    background: var(--ink);
    color: var(--paper);
    border: none;
    padding: 7px 14px;
    border-radius: 8px;
    font-family: "Inter Tight", sans-serif;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    white-space: nowrap;
    transition: opacity .15s;
  }
  .viewonly-clone-btn:hover { opacity: 0.85; }
  .viewonly-clone-btn:active { transform: scale(0.97); }

  /* Showcase-view: canvas below nav(40) + viewonly-bar(44) + buckets(32) + milestones(32) = 148px */
  body.showcase-view #canvas { top: calc(var(--safe-top) + 148px) !important; }

  /* ── Showcase card footer + launch button ── */
  .showcase-card-footer {
    display: flex;
    justify-content: flex-end;
    padding-top: 12px;
    margin-top: 10px;
    border-top: 1px solid var(--ink-06);
  }
  .showcase-launch-btn {
    background: var(--ink);
    color: var(--paper);
    border: none;
    padding: 8px 18px;
    border-radius: 8px;
    font-family: "Inter Tight", sans-serif;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    transition: opacity .15s;
  }
  .showcase-launch-btn:hover { opacity: 0.85; }
  .showcase-launch-btn:active { transform: scale(0.97); }

  /* ── Inspector view-only state ── */
  .inspector.view-only .insp-title-input {
    pointer-events: none;
    opacity: 0.7;
    background: transparent;
  }
  .inspector.view-only .insp-slider { pointer-events: none; opacity: 0.5; }
  .inspector.view-only #insp-complete,
  .inspector.view-only #insp-delete { display: none; }

  /* ── Detail sheet view-only state ── */
  .detail-title-input[readonly] {
    pointer-events: none;
    opacity: 0.8;
    background: transparent;
    border-color: transparent;
    cursor: default;
  }
  .detail-prop-status:not([data-cycle-progress]) {
    cursor: default;
    pointer-events: none;
  }

  /* ── Version badge ── */
  #version-badge {
    position: fixed;
    bottom: 10px;
    right: 12px;
    font-size: 11px;
    font-family: 'SF Mono', 'Menlo', 'Monaco', monospace;
    color: var(--ink-soft);
    opacity: 0.45;
    pointer-events: none;
    z-index: 120;
    letter-spacing: 0.04em;
    user-select: none;
  }

  /* ============================================================
     DARK MODE
     All color tokens redefined for body.dark; structural rules
     are untouched — only values change.
  ============================================================ */
  body.dark {
    /* ── Base palette ── */
    --paper: #1C1915;
    --paper-2: #231E19;
    --ink: #EDE6DC;
    --ink-soft: #998C7F;
    --ink-faint: #665D54;
    --done: #4A4338;
    --sage-soft: #4D5E4C;

    /* ── Shadows (deeper contrast on dark bg) ── */
    --shadow-sm: 0 1px 3px rgba(0,0,0,0.35), 0 1px 2px rgba(0,0,0,0.22);
    --shadow-md: 0 6px 24px rgba(0,0,0,0.50), 0 2px 8px rgba(0,0,0,0.30);
    --shadow-lg: 0 24px 60px rgba(0,0,0,0.65), 0 8px 24px rgba(0,0,0,0.38);

    /* ── White surface → dark warm surface ── */
    --white: #252018;
    --white-88: rgba(37, 32, 24, 0.88);
    --white-85: rgba(37, 32, 24, 0.85);
    --white-95: rgba(37, 32, 24, 0.95);

    /* ── Paper tints ── */
    --paper-92: rgba(28, 25, 21, 0.92);
    --paper-96: rgba(28, 25, 21, 0.96);
    --paper-98: rgba(28, 25, 21, 0.98);
    --paper-70: rgba(28, 25, 21, 0.70);

    /* ── Canvas / background tints ── */
    --canvas-row2-bg: rgba(24, 21, 17, 0.95);
    --canvas-row3-bg: rgba(24, 21, 17, 0.95);
    --plan-banner-bg: rgba(32, 26, 18, 0.95);
    --new-card-hover-bg: rgba(42, 34, 22, 0.6);

    /* ── Ink alpha variants: base switches to light ink (#EDE6DC = 237,230,220) ── */
    --ink-02: rgba(237,230,220,0.02);
    --ink-03: rgba(237,230,220,0.03);
    --ink-04: rgba(237,230,220,0.04);
    --ink-05: rgba(237,230,220,0.05);
    --ink-06: rgba(237,230,220,0.06);
    --ink-07: rgba(237,230,220,0.07);
    --ink-08: rgba(237,230,220,0.08);
    --ink-10: rgba(237,230,220,0.10);
    --ink-12: rgba(237,230,220,0.12);
    --ink-15: rgba(237,230,220,0.15);
    --ink-18: rgba(237,230,220,0.18);
    --ink-25: rgba(237,230,220,0.25);
    --ink-35: rgba(237,230,220,0.35);
    --ink-92: rgba(237,230,220,0.92);

    /* ── Node type backgrounds ── */
    --node-goal-bg-from: #2B2318;
    --node-goal-bg-to: #342A1B;
    --node-milestone-bg-from: #1E2520;
    --node-milestone-bg-to: #222E24;
    --node-task-bg: #252018;

    /* ── Danger ── */
    --danger: #D96040;
    --danger-12: rgba(217,96,64,0.12);
    --danger-20: rgba(217,96,64,0.20);

    /* ── Status colors ── */
    --status-progress-color: #D4783A;
    --status-done-color: #6AB56F;

    /* ── Root badge ── */
    --root-color: #E05A4E;
    --root-bg: rgba(224,90,78,0.12);
    --root-border: rgba(224,90,78,0.50);

    /* ── Successor-completed pattern ── */
    --succ-stripe-a: rgba(30,28,24,0.6);

    /* ── Plan bar over-capacity ── */
    --plan-over-from: rgba(220,90,70,0.50);
    --plan-over-to: rgba(220,90,70,0.32);
  }
