:root {
  /* ══ APP DESIGN TOKENS - single source of truth. Edit here to re-theme the whole app. ══
     INK (Rishabh 2026-09-14): forest ink on a quiet grey canvas, white surfaces, hairline borders at low-alpha ink.
     Token NAMES are the old ones - the tracker, the notes editor and the dashboard keep reading them. ══ */
  --font-display: 'Clash Display', 'Inter', system-ui, sans-serif;   /* title + headings */
  --font-body: 'Inter', system-ui, -apple-system, sans-serif;         /* everything else */
  /* ink ramp */
  --c-ink-900: #0b1a14; --c-ink-800: #14211b; --c-ink-700: #2a3830; --c-ink-600: #44534b;
  --c-ink-500: #5c6b63; --c-ink-450: #7d8981; --c-ink-400: #9aa39c;
  /* lines & fills */
  --c-line-200: rgba(11,26,20,.14); --c-line-150: rgba(11,26,20,.10); --c-line-100: rgba(11,26,20,.08);
  --c-fill-100: #f1f1f4; --c-fill-150: #ececf0; --c-fill-200: #e9e9ee; --c-fill-300: #f7f7f9;
  --c-fill-current: rgba(11,26,20,.055); --c-ring-current: rgba(11,26,20,.045);   /* the outline's current row (the team member's .outline-mark surface, read 2026-09-15) */
  /* surface */
  --c-bg: #f4f4f6;
  /* roadmap card coding (the team member's build): tint + 3px left bar per status */
  --c-blue-050: #eff5fd; --c-bar-now: #3d7fd6; --c-green-050: #eff7f2; --c-bar-done: #3f9d6b; --c-fill-075: #f4f5f7; --c-bar-later: #98a2b3;
  /* brand & semantic */
  --c-brand: #b42318; --c-brand-050: #fdecea; --c-brand-grad: linear-gradient(150deg, #d84056, #b21d32);
  --c-amber: #a06a12; --c-green: #0b7a53; --c-red: #b42318; --c-red-200: #f3c2bd; --c-red-050: #fdecea;

  /* extended palette (semantics, neutrals, white) */
  --c-white: #ffffff; --c-ink-300: #b3bab5; --c-line-250: rgba(11,26,20,.24); --c-line-175: rgba(11,26,20,.11); --c-line-120: rgba(11,26,20,.09); --c-line-050: rgba(11,26,20,.06); --c-fill-050: #fafafb; --c-cream: #fbfbfc; --c-surface-done: #f9fbfa; --c-green-700: #0b7a53; --c-green-200: #c2e3d4; --c-green-050: #e3f3ec; --c-red-500: #c73a2e; --c-red-300: #e0a49d; --c-red-075: #fdecea; --c-amber-700: #a06a12; --c-amber-050: #faf1de; --c-code: #9d2456;
}
@font-face { font-family: 'Clash Display'; font-weight: 500; font-style: normal; font-display: swap; src: url(fonts/ClashDisplay-500.woff2) format('woff2'); }
@font-face { font-family: 'Clash Display'; font-weight: 600; font-style: normal; font-display: swap; src: url(fonts/ClashDisplay-600.woff2) format('woff2'); }

    * { margin: 0; padding: 0; box-sizing: border-box; }

    body {
      font-family: var(--font-body);
      background: var(--c-bg);
      color: var(--c-ink-800);
      min-height: 100vh;
      padding: 0;
      -webkit-font-smoothing: antialiased;
    }
    /* The page's vertical scrollbar: an 8px rounded thumb on a clear track (Rishabh 2026-09-14: "hamara vertical
       scroller slim karo"). scrollbar-width stays initial so Chrome honours these (see the strip slider note). */
    /* ONE slim scrollbar for every scroller in the app - the page, the outline panel, a box editor with Fit off, a wide table, the roadmap panel (Rishabh 2026-09-15: "consistency nahi hai"). The strips keep their own 3px hover-only rule (more specific). */
    *::-webkit-scrollbar { width: 8px; height: 8px; }
    *::-webkit-scrollbar-button { display: none; }
    *::-webkit-scrollbar-corner { background: transparent; }
    *::-webkit-scrollbar-track { background: transparent; }
    *::-webkit-scrollbar-thumb { background: rgba(11,26,20,.16); border-radius: 999px; border: 2px solid transparent; background-clip: padding-box; }
    *::-webkit-scrollbar-thumb:hover { background: rgba(11,26,20,.3); background-clip: padding-box; }

    /* ── App bar ──
       ONE white row: the crimson book mark + the title on the left, the Dashboard button and ONE grid menu
       on the right. Everything that used to be a row of buttons (Share, the three exports, Hidden, Admin,
       Sign out) lives under the menu - #headerActions is the SAME node, moved, so every id still resolves. */
    .header {
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 1rem;
      height: 44px;
      padding: 4px 28px 4px 35px;   /* even by visible glyphs: the mark starts 35px in (over the first tab text), the 22px grid glyph ends 35px in (36px box + 7px inset); Rishabh 2026-09-14 */
      background: transparent;      /* the canvas shows through - no panel, no border (Rishabh 2026-09-14: "things must be subtle") */
      margin-bottom: 4px;
      position: relative;
    }
    .hdr-lockup { display: flex; align-items: center; gap: 10px; min-width: 0; }
    .hdr-mark { width: 28px; height: 28px; border-radius: 9px; background: var(--c-brand-grad); position: relative; flex: none; box-shadow: 0 1px 2px rgba(11,26,20,.10); }
    .hdr-mark::after { content: ''; position: absolute; inset: 0; background: var(--c-white); -webkit-mask: url(img/ib-mark.png) center / 20px 20px no-repeat; mask: url(img/ib-mark.png) center / 20px 20px no-repeat; }
    .hdr-right { display: flex; align-items: center; gap: 10px; flex: none; }
    /* The mark + title are the second way back to the dashboard while a document is open (dashboard/index.js showBack
       toggles the class; Rishabh 2026-09-14: "clicking on icon should also take back to dashboard"). */
    .hdr-lockup.is-home-link { cursor: pointer; border-radius: 10px; transition: opacity .12s; }
    .hdr-lockup.is-home-link:hover { opacity: .78; }
    .hdr-lockup.is-home-link:focus-visible { outline: 2px solid var(--c-ink-900); outline-offset: 3px; }
    .hdr-menu { position: relative; }
    .hdr-gridbtn { width: 36px; height: 36px; border-radius: 10px; display: grid; place-items: center; color: var(--c-ink-900); border: 0; background: transparent; cursor: pointer; transition: background .12s; }
    .hdr-gridbtn svg { width: 22px; height: 22px; display: block; }
    .hdr-gridbtn:hover { background: var(--c-fill-100); }
    .hdr-gridbtn[aria-expanded="true"] { background: var(--c-fill-150); }
    /* The panel - the team member's shape, his computed values: 268px, 6px padding, 14px radius, hairline border, a soft
       far shadow; an account card over a 3-column grid of 84px tiles; Sign out as a row under a hairline. */
    .hdr-pop { position: absolute; top: 46px; right: 0; z-index: 700; width: 268px; padding: 6px; display: flex; flex-direction: column; gap: 2px; background: var(--c-white); border: 1px solid var(--c-line-050); border-radius: 14px; box-shadow: 0 1px 2px rgba(11,26,20,.05), 0 24px 48px -20px rgba(11,26,20,.3); }
    .hdr-pop[hidden] { display: none; }
    .hdr-acct { display: flex; flex-direction: column; align-items: center; text-align: center; padding: 18px 14px 15px; margin: 0 0 6px; background: var(--c-fill-100); border-radius: 11px; }
    .hdr-acct-av { width: 46px; height: 46px; border-radius: 50%; display: grid; place-items: center; margin: 0 0 10px; background: var(--c-brand-grad); color: var(--c-white); font-family: var(--font-display); font-size: 18px; font-weight: 500; text-transform: uppercase; box-shadow: inset 0 .5px 0 rgba(255,255,255,.3); }
    .hdr-acct .cloud-who { display: block; order: 2; font-size: 13.5px; font-weight: 500; color: var(--c-ink-900); overflow-wrap: anywhere; }
    /* renderAdminButton (cloud-store) inserts #adminBtn before #who, so it lands in the card: a small chip under the name */
    .hdr-acct #adminBtn { order: 3; margin-top: 8px; padding: 5px 10px; border: 0; border-radius: 8px; background: var(--c-white); box-shadow: 0 0 0 1px var(--c-line-050); font-size: 12px; font-weight: 500; color: var(--c-ink-800); }
    .hdr-acct #adminBtn:hover { color: var(--c-ink-900); box-shadow: 0 0 0 1px var(--c-line-200); }
    .hdr-actions { display: grid; grid-template-columns: repeat(3, 1fr); gap: 2px; }
    .hdr-actions .btn { display: flex; flex-direction: column; align-items: center; justify-content: flex-start; gap: 7px; width: 100%; height: 84px; padding: 11px 4px 10px; border: 0; background: transparent; box-shadow: none; border-radius: 12px; font-size: 11px; font-weight: 500; line-height: 1.25; color: var(--c-ink-700); text-align: center; }
    .hdr-actions .btn:hover { background: var(--c-fill-100); color: var(--c-ink-900); border: 0; box-shadow: none; }
    .hdr-actions .btn::before { content: ''; display: block; width: 38px; height: 38px; border-radius: 50%; background: var(--c-fill-100) center / 16px 16px no-repeat; flex: none; }
    .hdr-actions .btn:hover::before { background-color: var(--c-white); }
    .hdr-actions #evLibBackBtn::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%232a3830' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M19 12H5'/%3E%3Cpath d='M12 19l-7-7 7-7'/%3E%3C/svg%3E"); }
    .hdr-actions #shareBtnTop::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%232a3830' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 12v7a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2v-7'/%3E%3Cpath d='M16 6l-4-4-4 4'/%3E%3Cpath d='M12 2v13'/%3E%3C/svg%3E"); }
    .hdr-actions #exportCsvBtnTop::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%232a3830' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3.5 4.5h17v15h-17z'/%3E%3Cpath d='M3.5 10h17'/%3E%3Cpath d='M9.5 4.5v15'/%3E%3C/svg%3E"); }
    .hdr-actions #exportMdBtnTop::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%232a3830' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14 2.5H6.5a2 2 0 0 0-2 2v15a2 2 0 0 0 2 2h11a2 2 0 0 0 2-2V8z'/%3E%3Cpath d='M14 2.5V8h5.5'/%3E%3Cpath d='M8 13h8'/%3E%3Cpath d='M8 17h8'/%3E%3C/svg%3E"); }
    .hdr-actions #exportLinksBtnTop::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%232a3830' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71'/%3E%3Cpath d='M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71'/%3E%3C/svg%3E"); }
    .hdr-actions #hiddenSharedBtnTop::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%232a3830' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94'/%3E%3Cpath d='M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19'/%3E%3Cpath d='M14.12 14.12a3 3 0 1 1-4.24-4.24'/%3E%3Cpath d='M1 1l22 22'/%3E%3C/svg%3E"); }
    .hdr-pop .hdr-signout { display: flex; align-items: center; gap: 10px; width: 100%; margin: 6px 0 0; padding: 10px 10px 4px; border: 0; border-top: 1px solid var(--c-line-050); border-radius: 0 0 8px 8px; background: transparent; box-shadow: none; font-size: 12.5px; font-weight: 500; color: var(--c-ink-800); text-align: left; }
    .hdr-pop .hdr-signout::before { content: ''; width: 16px; height: 16px; background: currentColor; -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4'/%3E%3Cpath d='M16 17l5-5-5-5'/%3E%3Cpath d='M21 12H9'/%3E%3C/svg%3E") center / 16px 16px no-repeat; mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='1.9' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4'/%3E%3Cpath d='M16 17l5-5-5-5'/%3E%3Cpath d='M21 12H9'/%3E%3C/svg%3E") center / 16px 16px no-repeat; }
    .hdr-pop .hdr-signout:hover { color: var(--c-red); background: transparent; border: 0; border-top: 1px solid var(--c-line-050); box-shadow: none; }

    .header h1 {
      font-family: var(--font-display);
      font-size: 15px;
      font-weight: 500;
      color: var(--c-ink-900);
      letter-spacing: -0.01em;
      line-height: 1.15;
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }

    .header h1 span { color: var(--c-ink-800); }

    /* #17: the ONE book-level read-only marker, beside the book title. A restriction shows a
       lock at its OWN level exactly once - the subject/chapter padlocks stay silent inside a
       read-only book precisely so this pill can speak for the whole book. Rendered + removed by
       cloud-store/books-store.js `_applyBookTitleToHeader` from St.activeBookReadOnly.
       Two classes + one element out-specifies `.header h1 span` above (one class + two
       elements), so the mode-badge ink rule cannot repaint this pill. Shape + amber borrowed
       verbatim from `.tl-pill.active` so it reads as the same kind of status chip. */
    .header h1 .hdr-ro {
      display: inline-block;
      vertical-align: middle;
      margin-left: 0.5rem;
      padding: 2px 8px;
      border-radius: 20px;
      background: var(--c-amber-050);
      color: var(--c-amber-700);
      font-size: 10px;
      font-weight: 600;
      letter-spacing: 0.06em;
      text-transform: uppercase;
      white-space: nowrap;
    }


    /* ── Layout ── */
    .layout {
      display: flex;
      flex-direction: column;
      gap: 0.6rem;
      padding: 0 22px 24px;
    }

    /* ── Tabs (horizontal) ── */
    .sidebar { width: 100%; }

    /* Strip anatomy (both strips): 28px tabs + 1px hairline + 3px slider band = 32px. The hairline is painted INSIDE the
       scroll area (a background line 3px up) so the active underline, at the tab's own bottom, sits exactly on it; a
       border below the scrollbar gutter can never be reached - the gutter clips (Rishabh 2026-09-15). */
    .tabs {
      display: flex;
      flex-direction: row;
      align-items: flex-start;
      gap: 0;
      height: 32px;
      background: linear-gradient(var(--c-line-050), var(--c-line-050)) left 0 bottom 3px / 100% 1px no-repeat;
      flex-wrap: nowrap;
      overflow-x: auto;
      overflow-y: hidden;
    }
    /* ── The strip slider (subjects + chapters) ──
       A 3px hairline band, reserved at all times so revealing the thumb never reflows the row; the thumb paints on
       hover only. scrollbar-width must stay at its initial value - a non-initial value makes Chrome ignore every
       ::-webkit-scrollbar rule and draw its own fixed-size bar. */
    .tabs, .subtabs { scrollbar-width: auto; scrollbar-color: auto; }
    .tabs::-webkit-scrollbar, .subtabs::-webkit-scrollbar { height: 3px; }
    .tabs::-webkit-scrollbar-track, .subtabs::-webkit-scrollbar-track { background: transparent; }
    .tabs::-webkit-scrollbar-thumb, .subtabs::-webkit-scrollbar-thumb { background: transparent; border-radius: 999px; }
    .tabs:hover::-webkit-scrollbar-thumb, .subtabs:hover::-webkit-scrollbar-thumb { background: rgba(11,26,20,.14); }   /* only the strip under the cursor (Rishabh 2026-09-14: "jis row pe cursor us row ka scroller") */
    .tabs::-webkit-scrollbar-thumb:hover, .subtabs::-webkit-scrollbar-thumb:hover { background: rgba(11,26,20,.26); }
    .tabs::-webkit-scrollbar-button, .subtabs::-webkit-scrollbar-button { display: none; }

    .tab {
      position: relative;
      display: inline-flex;
      align-items: center;
      gap: 0.4rem;
      padding: 0 13px;
      height: 28px;
      border: none;
      background: none;
      color: var(--c-ink-600);
      cursor: pointer;
      font-family: var(--font-display);
      font-size: 12.5px;
      font-weight: 400;
      transition: color 0.15s;
      border-radius: 0;
      text-align: center;
      margin-bottom: -1px;
      white-space: nowrap;
      flex: none;
    }

    .tab:hover { color: var(--c-ink-900); background: transparent; }
    /* 1px divider between subjects (his .tab::after: 1 x 10px at the right edge, 9px up), none after the last */
    .tab::after { content: ''; position: absolute; right: 0; bottom: 9px; width: 1px; height: 10px; background: var(--c-line-120); }
    .tab:last-of-type::after { background: transparent; }
    /* the active subject: a 2px ink underline inset 9px from each edge (his .tab.active::before), at the tab's bottom = on the hairline */
    .tab.active::before { content: ''; position: absolute; left: 9px; right: 9px; bottom: 0; height: 2px; background: var(--c-ink-900); border-radius: 2px 2px 0 0; }
    /* Drag-to-reorder feedback: the dragged tab dims; the drop target shows a
       left edge marker + tint. */
    .tab.is-dragging { opacity: 0.4; }
    .tab.drag-over { background: var(--c-line-150); box-shadow: inset 3px 0 0 var(--c-ink-700); }
    .tab.active { color: var(--c-ink-900); font-weight: 500; background: transparent; }
    /* ✕ to delete a tab — hidden until hover, red on hover (mirrors .del-sub) */
    .tab .del-tab {
      background: none;
      border: none;
      color: inherit;
      cursor: pointer;
      font-size: 0.72rem;
      padding: 0;
      line-height: 1;
      opacity: 0;
      transition: opacity 0.12s;
    }
    .tab:hover .del-tab { opacity: 0.6; }
    .tab .del-tab:hover { opacity: 1; color: var(--c-red); }
    /* "+ Add Tab" — same muted affordance as "+ Add Epic" */
    /* "+ Add Domain" / "+ Add Subject" as TEXT, the same control as Add Table / Add Notes (Rishabh 2026-09-14: "it should + add subject / domain whichever relevant") */
    .add-tab { position: relative; display: inline-flex; align-items: center; padding: 0 10px; height: 28px; border: none; border-radius: 7px; background: none; color: var(--c-ink-700); cursor: pointer; font-family: var(--font-display); font-size: 12px; font-weight: 400; transition: color 0.15s, background 0.15s; white-space: nowrap; flex: none; }
    .add-tab:hover { color: var(--c-ink-900); background: var(--c-fill-100); }

    .main-content { flex: 1; min-width: 0; }

    /* ── Sub-tabs (Epics within a section) ──
       Same underline pattern as the main tabs, but smaller text, lighter
       weight, thinner underline — reads as a sub-heading underneath. */
    .subtabs {
      display: flex;
      flex-wrap: nowrap;
      align-items: flex-start;
      gap: 2px;
      height: 32px;
      margin-bottom: 0.7rem;
      background: linear-gradient(var(--c-line-050), var(--c-line-050)) left 0 bottom 3px / 100% 1px no-repeat;   /* the same hairline the subject strip has, same anatomy */
      overflow-x: auto;
      overflow-y: hidden;
    }

    .subtab {
      position: relative;
      padding: 0 11px;
      height: 28px;
      border: none;
      background: none;
      color: var(--c-ink-500);
      cursor: pointer;
      font-family: var(--font-display);
      font-size: 11.8px;
      font-weight: 500;
      transition: color 0.15s;
      border-radius: 0;
      text-align: center;
      display: inline-flex;
      align-items: center;
      gap: 6px;
      white-space: nowrap;
      flex: none;
    }

    .subtab:hover { color: var(--c-ink-900); background: transparent; }
    /* the active chapter: ink text + a 2px underline inset 9px (his .subtab.active::after) - text, not a pill
       (Rishabh 2026-09-14: "chapter selection pata nahi kyun button jaise hai") */
    .subtab.active { color: var(--c-ink-900); font-weight: 500; background: transparent; }
    .subtab.active::after { content: ''; position: absolute; left: 9px; right: 9px; bottom: 0; height: 2px; background: var(--c-ink-900); border-radius: 2px 2px 0 0; }
    /* 1px divider between chapters, the subjects' one (::before here - ::after is the active underline); none after the last */
    .subtab::before { content: ''; position: absolute; right: 0; bottom: 9px; width: 1px; height: 10px; background: var(--c-line-120); }
    .subtab:last-of-type::before { background: transparent; }
    .subtab[draggable="true"] { cursor: grab; }
    .subtab[draggable="true"]:active { cursor: grabbing; }
    .subtab.drag-over { background: var(--c-fill-200); box-shadow: inset 2px 0 0 var(--c-ink-900); }
    .subtab-name[contenteditable="true"] {
      outline: 2px solid var(--c-ink-700);
      border-radius: 3px;
      padding: 0 4px;
      background: var(--c-white);
      color: var(--c-ink-800);
      cursor: text;
    }

    .subtab .del-sub {
      background: none;
      border: none;
      color: inherit;
      cursor: pointer;
      font-size: 0.72rem;
      padding: 0;
      line-height: 1;
      opacity: 0;
      transition: opacity 0.12s;
    }

    .subtab:hover .del-sub { opacity: 0.6; }
    .subtab .del-sub:hover { opacity: 1; color: var(--c-red); }

    .add-subtab {
      position: relative;
      display: inline-flex;
      align-items: center;
      padding: 0 10px;
      height: 28px;
      border: none;
      border-radius: 7px;
      background: none;
      color: var(--c-ink-700);
      cursor: pointer;
      font-family: var(--font-display);
      font-size: 12px;
      font-weight: 400;
      transition: color 0.15s, background 0.15s;
      white-space: nowrap;
      flex: none;
    }
    .add-subtab:hover { color: var(--c-ink-900); background: var(--c-fill-100); }
    /* The add actions of BOTH strips sit STICKY at the right edge of their scrolling strip, so they are visible without
       scrolling (Rishabh 2026-09-14: "+ for adding domain always visible, scroll nahi karna padta"). The wrapper comes from
       data.js / subtabs.js (his .strip-actions); the canvas-coloured fade hides the tabs sliding under it. */
    .strip-actions { position: sticky; right: 0; z-index: 3; flex: none; align-self: flex-start; height: 29px; display: flex; align-items: center; gap: 2px; padding: 0 0 1px 12px; background: linear-gradient(var(--c-line-050), var(--c-line-050)) left 0 top 28px / 100% 1px no-repeat, linear-gradient(90deg, rgba(244,244,246,0) 0, var(--c-bg) 12px); }   /* 12px of air after the last tab (Rishabh 2026-09-15: "inke left mein bahut gap hai" at 34) - the "+ Add" text lands 22px after the tab's edge, about one tab-to-tab label distance; sits right after the last tab; sticky right:0 pins it to the visible edge only once the strip overflows (Rishabh 2026-09-15). Fixed 29px (28 tabs + the hairline row) with the hairline at top 28px - the strip's own row whether or not a scrollbar gutter exists */   /* solid canvas under the buttons after a 12px fade - the chapters sliding under it stay hidden (Rishabh 2026-09-14: "chapters wala add button overlap"); it stretches to the hairline row (padding-bottom 1px) and paints the same hairline on its own bottom row, so the line runs on under the controls */

    /* ── Notes-type Epic pill ──
       Same ink treatment as every other sub-tab; the ▤ mark (below) is what
       distinguishes a notes epic, not colour. (Timeline pills carry this class
       too, so they pick up the same neutral treatment.) */
    .subtab.notes-epic { color: var(--c-ink-500); }
    .subtab.notes-epic:hover { color: var(--c-ink-900); background: transparent; }
    .subtab.notes-epic.active { color: var(--c-ink-900); background: transparent; font-weight: 500; }
    .subtab.notes-epic .subtab-name::before { content: '▤ '; font-size: 0.85em; }


    /* ── Notes editor area ──
       A notes-Epic hosts one or more independent boxes. Each box is its own
       contenteditable region saving to its own .md file. The .notes-boxes
       grid arranges them based on [data-layout]. */
    .notes-toolbar {
      display: flex;
      gap: 0.5rem;
      align-items: center;
      margin-bottom: 0.6rem;
      flex-wrap: wrap;
    }
    :is(.notes-toolbar, .nr-head) .btn-small {
      padding: 6px 11px;
      border: 1px solid var(--c-line-200);
      background: var(--c-white);
      color: var(--c-ink-800);
      border-radius: 10px;
      font-size: 12.5px;
      font-family: inherit;
      font-weight: 500;
      cursor: pointer;
      box-shadow: 0 1px 2px rgba(11,26,20,.04);
      transition: border-color 0.15s, background 0.15s;
    }
    :is(.notes-toolbar, .nr-head) .btn-small:hover { border-color: var(--c-ink-900); color: var(--c-ink-900); background: var(--c-white); }
    :is(.notes-toolbar, .nr-head) .btn-add {
      background: var(--c-ink-900);
      color: var(--c-white);
      border-color: var(--c-ink-900);
    }
    :is(.notes-toolbar, .nr-head) .btn-add:hover { background: #000; border-color: #000; color: var(--c-white); }
    :is(.notes-toolbar, .nr-head) .toolbar-label {
      font-size: 11px;
      letter-spacing: 0.06em;
      text-transform: uppercase;
      color: var(--c-ink-400);
      font-weight: 500;
      margin-left: 0.2rem;
    }
    :is(.notes-toolbar, .nr-head) .layout-group {
      display: inline-flex;
      gap: 2px;
      background: var(--c-fill-100);
      border-radius: 8px;
      padding: 3px;
    }
    :is(.notes-toolbar, .nr-head) .layout-btn {
      padding: 5px 11px;
      border: none;
      background: transparent;
      color: var(--c-ink-500);
      font-size: 12.5px;
      font-weight: 500;
      font-family: inherit;
      cursor: pointer;
      border-radius: 8px;
      transition: background 0.15s, color 0.15s;
    }
    :is(.notes-toolbar, .nr-head) .layout-btn:first-child { border-radius: 8px; }
    :is(.notes-toolbar, .nr-head) .layout-btn:last-child { border-radius: 8px; }
    :is(.notes-toolbar, .nr-head) .layout-btn.active {
      background: var(--c-ink-900);
      color: var(--c-white);
      font-weight: 500;
    }
    :is(.notes-toolbar, .nr-head) .layout-btn:not(.active):hover { color: var(--c-ink-700); background: var(--c-fill-100); }
    .notes-toolbar .toolbar-spacer { flex: 1; }
    .notes-toolbar .toolbar-meta {
      font-size: 0.72rem;
      color: var(--c-ink-400);
      font-style: italic;
    }

    .notes-boxes {
      display: grid;
      gap: 1rem;
      /* Don't stretch boxes to fill their grid cell — each box hugs its
         editor's own height so per-box resize takes effect visibly. In a row
         of boxes, that means boxes can have different heights. */
      align-items: start;
    }
    /* minmax(0, 1fr) — NOT bare 1fr — so a wide table/diagram inside a box can't
       blow its column past an equal share and shove the other columns off-screen.
       Bare 1fr = minmax(auto, 1fr); the `auto` floor is the box's content min-
       width, which a wide table inflates. minmax(0, …) pins the floor to 0 and
       the box scrolls its own overflow (editor + .md-table-scroll are overflow:auto). */
    .notes-boxes[data-layout="stack"]  { grid-template-columns: minmax(0, 1fr); }
    .notes-boxes[data-layout="2col"]   { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .notes-boxes[data-layout="3col"]   { grid-template-columns: repeat(3, minmax(0, 1fr)); }
    .notes-boxes[data-layout="2x2"]    { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    /* Flow: flexbox wrap so boxes pack into rows AND the last (partial) row
       stretches to fill the width — grid 1fr columns would leave a gap there.
       ~30% basis → about 3 per row on desktop; min-width drops to fewer on
       narrow screens. e.g. 5 boxes → row of 3, then 2 (each ~half width). */
    .notes-boxes[data-layout="flow"] {
      display: flex;
      flex-wrap: wrap;
    }
    .notes-boxes[data-layout="flow"] .notes-box {
      flex: 1 1 30%;
      min-width: 300px;
    }
    /* A box marked "full width" (⬌) spans the WHOLE row — via grid-column in the
       column layouts, via flex-basis in Flow — so you can mix a full-width box with
       a multi-column row (e.g. one wide box on top, two columns beneath it). */
    .notes-box--full { grid-column: 1 / -1; }
    .notes-boxes[data-layout="flow"] .notes-box--full { flex-basis: 100%; }

    .notes-box {
      background: var(--c-white);
      border: 1px solid var(--c-line-100);
      border-radius: 13px;
      box-shadow: 0 1px 2px rgba(11,26,20,.04);
      position: relative;
      display: flex;
      flex-direction: column;
      transition: border-color 0.15s;
      /* Let a grid/flex item shrink below its content's intrinsic width so a wide
         table scrolls inside the box instead of widening its column. (Flow layout
         re-raises this to 300px below — that override wins by specificity.) */
      min-width: 0;
    }
    .notes-box:focus-within {
      border-color: var(--c-line-200);
      box-shadow: 0 1px 2px rgba(11,26,20,.04), 0 16px 32px -18px rgba(11,26,20,.2);
    }
    /* MU-1 L7: a box someone else is typing in right now. The ring says "not yours for
       the moment", the label says whose. The refusal itself is contenteditable=false,
       set by renderNotesBoxLocks - this block is only the look. */
    .notes-box.is-locked-by-other {
      border-color: var(--c-amber-700);
      box-shadow: 0 0 0 3px var(--c-amber-050);
    }
    .notes-box.is-locked-by-other .notes-editor { cursor: default; color: var(--c-ink-500); }
    /* The box's own actions go with the box: delete, rename, upload, table, diagram,
       video, restore and the drag handle all write to it. Fullscreen stays - it reads.
       Same shape as the read-only rule below (:not(.box-fs)), so the two read alike.
       The refusal does not depend on this: every one of those paths writes through
       saveNotesContent / deleteNotesContent, which refuse a held box on their own. */
    .notes-box.is-locked-by-other .notes-box-actions .box-action:not(.box-fs),
    .notes-box.is-locked-by-other .notes-box-actions .drag-handle,
    .notes-box.is-locked-by-other .notes-box-actions .box-sep { display: none; }
    .box-lock-label {
      position: absolute;
      top: 8px;
      right: 10px;
      z-index: 3;
      font-family: var(--font-body);
      font-size: 0.72rem;
      line-height: 1;
      padding: 0.3rem 0.5rem;
      border-radius: 999px;
      color: var(--c-amber-700);
      background: var(--c-amber-050);
      border: 1px solid var(--c-line-150);
      pointer-events: none;
    }
    /* The box toolbar: in flow at the box's top-right but taking no room (negative bottom margin = its own height, so the
       editor starts where it always did), STICKY so it rides along while a long box scrolls, and shown only while the
       box has focus - click inside to type and it appears, click anywhere else and it goes (Rishabh 2026-09-15). */
    .notes-box-actions {
      position: sticky;
      top: 8px;
      align-self: flex-end;
      height: 22px;
      margin: 0.5rem 0.6rem calc(-0.5rem - 22px) 0;
      display: flex;
      gap: 4px;
      opacity: 0;
      pointer-events: none;
      transition: opacity 0.15s;
      z-index: 2;
    }
    .notes-box:focus-within .notes-box-actions { opacity: 1; pointer-events: auto; }
    .notes-box-actions .box-sep { width: 1px; height: 14px; align-self: center; margin: 0 2px; background: var(--c-line-150); }   /* between the button groups */
    /* While exporting to PNG, fully hide the per-box action buttons so they
       never bleed into the captured image (even if a box is focused). */
    #notesBoxes.tt-exporting .notes-box-actions { display: none !important; }
    .notes-box-actions .box-action {
      background: rgba(255,255,255,0.9);
      border: 1px solid var(--c-line-100);
      color: var(--c-ink-400);
      width: 22px;
      height: 22px;
      border-radius: 4px;
      cursor: pointer;
      font-size: 0.7rem;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      padding: 0;
      line-height: 1;
      user-select: none;
    }
    .notes-box-actions .box-action:hover { color: var(--c-red); border-color: var(--c-red-200); background: var(--c-red-050); }
    /* Align L/C/R are text-formatting, not destructive — blue hover (like the
       drag handle), not the red the other actions share. Tiny font for letters. */
    .notes-box-actions .box-align { font-size: 0.6rem; font-weight: 700; }
    .notes-box-actions .box-align:hover { color: var(--c-ink-700); border-color: var(--c-line-200); background: var(--c-fill-100); }
    /* Bold/Italic/Underline selection buttons — same blue-hover family as L/C/R.
       The glyph itself shows the style (B bold, I italic, U underline). */
    .notes-box-actions .box-fmt { font-size: 0.7rem; }
    .notes-box-actions .box-fmt:hover { color: var(--c-ink-700); border-color: var(--c-line-200); background: var(--c-fill-100); }
    /* Text-color button: an "A" underlined in red to signal color; opens a swatch popover. */
    .notes-box-actions .box-color { font-size: 0.7rem; }
    .notes-box-actions .box-color .ncp-a { font-weight: 700; border-bottom: 2px solid var(--c-red); line-height: 1; }
    .notes-box-actions .box-color:hover { color: var(--c-ink-700); border-color: var(--c-line-200); background: var(--c-fill-100); }
    /* Full-width toggle (⬌): highlights ink when the box is spanning the row. */
    .notes-box-actions .box-fw.active { color: var(--c-ink-700); border-color: var(--c-line-200); background: var(--c-fill-200); }
    /* Fixed-height toggle (⇕): highlights ink when the box is excluded from Fit. */
    .notes-box-actions .box-nofit.active { color: var(--c-ink-700); border-color: var(--c-line-200); background: var(--c-fill-200); }
    /* Swatch popover (appended to <body>, fixed-positioned under the color button).
       z-index sits above the fullscreen notes box (9000) but below the restore modal (10000). */
    .notes-color-pop { position: fixed; z-index: 9600; display: none; padding: 6px; max-width: 168px;
      background: var(--c-white); border: 1px solid var(--c-line-200); border-radius: 8px; box-shadow: 0 6px 20px rgba(0,0,0,.16); }
    .notes-color-pop.open { display: flex; flex-wrap: wrap; gap: 5px; align-items: center; }
    .notes-color-pop .ncp-sw { width: 18px; height: 18px; padding: 0; border-radius: 50%;
      border: 1px solid rgba(0,0,0,.18); cursor: pointer; }
    .notes-color-pop .ncp-sw:hover { transform: scale(1.18); }
    .notes-color-pop .ncp-clear { flex: 0 0 100%; margin-top: 2px; padding: 3px 6px; font-size: .72rem;
      cursor: pointer; color: var(--c-ink-600); background: var(--c-fill-300); border: 1px solid var(--c-line-200); border-radius: 5px; }
    .notes-color-pop .ncp-clear:hover { background: var(--c-fill-150); }
    /* Drag handle is the same chrome as the X but with grab cursor + blue hover */
    .notes-box-actions .drag-handle {
      cursor: grab;
      font-size: 0.85rem;
      font-weight: bold;
    }
    .notes-box-actions .drag-handle:active { cursor: grabbing; }
    .notes-box-actions .drag-handle:hover { color: var(--c-ink-700); border-color: var(--c-line-200); background: var(--c-fill-100); }
    /* Drag visual: source dims, target gets a dashed ink outline */
    .notes-box.is-dragging { opacity: 0.4; }
    .notes-box.drag-over {
      outline: 2px dashed var(--c-ink-700);
      outline-offset: -1px;
      background: var(--c-fill-200);
    }

    .notes-editor {
      width: 100%;
      padding: 1.25rem 1.5rem;
      outline: none;
      font-family: 'Instrument Sans', 'Inter', system-ui, sans-serif;
      font-size: 0.88rem;
      line-height: 1.7;
      color: var(--c-ink-800);
      white-space: pre-wrap;
      word-wrap: break-word;
      /* Browser-native resize: drag the bottom-right corner to grow OR shrink
         the editor vertically. `flex: 1` is intentionally OMITTED — it would
         override any explicit/inline height set by the resize handle. The small
         min-height is the real floor; the per-layout rules below set the default
         (starting) height, which the resize handle can freely drag below. */
      resize: vertical;
      overflow: auto;
      min-height: 120px;
    }
    /* Per-layout DEFAULT height (not a hard floor): single box gets a tall area;
       multi-box layouts give each box a shorter height so all fit. Using `height`
       (not `min-height`) means the resize handle can shrink a box below this —
       e.g. to fit a small diagram without a wall of white space underneath. */
    .notes-boxes[data-layout="stack"] .notes-editor { height: 68vh; }
    .notes-boxes[data-layout="2col"]  .notes-editor { height: 68vh; }
    .notes-boxes[data-layout="3col"]  .notes-editor { height: 68vh; }
    .notes-boxes[data-layout="2x2"]   .notes-editor { height: 36vh; }
    .notes-boxes[data-layout="flow"]  .notes-editor { height: 40vh; }
    /* Multiple stacked boxes shouldn't each be 68vh; give them a shorter default */
    .notes-boxes[data-layout="stack"] .notes-box:nth-child(n+2) .notes-editor { height: 40vh; }
    /* Fit mode (the ↕ Fit toggle): each box fits the SCREEN - it grows with its text up to the viewport (minus the
       16px landing gap above and below and the box's own border), then scrolls inside; the scrollbar paints only while
       the pointer is over the box (Rishabh 2026-09-15: "Fit ON: box screen par poora nahi aayega, right mein cursor
       laane par us box ka scroller aaye"). `!important` beats both the per-layout height above and any persisted
       inline height. Fit OFF stays what it was: a fixed 68vh box with its bar always on. */
    .notes-boxes[data-fit="screen"] .notes-box:not(.notes-box--nofit) .notes-editor, .notes-boxes[data-fit="content"] .notes-box:not(.notes-box--nofit) .notes-editor {
      height: auto !important;
      min-height: 80px;
      overflow: visible;
      resize: none;
    }
    /* The BOX is the scroller, not the editor: Chrome paints an element's own cursor over its custom scrollbar, and
       the editor's is the text I-beam (Rishabh 2026-09-15). The box is not editable, so its bar gets the arrow; the
       sticky toolbar is a child of the box and sticks inside this scroll. */
    .notes-boxes[data-fit="screen"] .notes-box:not(.notes-box--nofit) { max-height: calc(100vh - 34px); overflow-y: auto; overflow-x: hidden; }   /* "screen" only - "content" (fit to height) lets the box grow and the page scroll */
    .notes-boxes[data-fit="screen"] .notes-box:not(.notes-box--nofit)::-webkit-scrollbar-thumb { background: transparent; }
    .notes-boxes[data-fit="screen"] .notes-box:not(.notes-box--nofit):hover::-webkit-scrollbar-thumb { background: rgba(11,26,20,.16); background-clip: padding-box; }
    .notes-boxes[data-fit="screen"] .notes-box:not(.notes-box--nofit):hover::-webkit-scrollbar-thumb:hover { background: rgba(11,26,20,.3); background-clip: padding-box; }
    /* Per-box opt-OUT of Fit (⇕): the box keeps its own resizable height (inline or
       per-layout default) and scrolls, so e.g. a big diagram box doesn't blow the
       page height while the surrounding text boxes still auto-fit. align-self:start
       stops the Fit row-stretch from inflating it to a taller sibling's height. */
    .notes-boxes[data-fit="screen"] .notes-box--nofit, .notes-boxes[data-fit="content"] .notes-box--nofit { align-self: start; }
    .notes-boxes[data-fit="screen"] .notes-box--nofit .notes-editor, .notes-boxes[data-fit="content"] .notes-box--nofit .notes-editor { overflow: auto; resize: vertical; }
    /* In Fit mode, stretch every box in a row up to the tallest one so a multi-
       column layout (2col / 3col / 2×2 / flow) stays visually aligned instead of
       having a ragged bottom edge. The shorter box gets trailing whitespace. The
       global `align-items:start` it overrides is only needed in resize mode, which
       Fit disables — so this is safe to scope to Fit. */
    .notes-boxes[data-fit="screen"], .notes-boxes[data-fit="content"] { align-items: stretch; }

    .notes-editor:empty::before {
      content: 'Start typing notes here…';
      color: var(--c-ink-300);
    }
    /* Dragging an image file from File Explorer over the editor — highlight
       so the user knows where the image will land. */
    .notes-editor.drag-active {
      background: var(--c-fill-100);
      outline: 2px dashed var(--c-ink-700);
      outline-offset: -2px;
    }

    /* Markdown heading lines — display-only styling. The leading # markers stay
       in the text (dimmed via .md-hash) so the saved markdown is byte-for-byte
       unchanged; this only changes how the line LOOKS in the box. */
    .notes-editor .md-head { font-family: var(--font-body); font-weight: 600; color: var(--c-ink-900); line-height: 1.3; }   /* box headings in Inter, like the body (Rishabh 2026-09-14 "try using inter"; Clash 600 at 23px read heavy) */
    .notes-editor .md-h1 { font-size: 1.45rem; margin: 0.5rem 0 0.2rem; }
    .notes-editor .md-h2 { font-size: 1.2rem;  margin: 0.45rem 0 0.15rem; }
    .notes-editor .md-h3 { font-size: 1.05rem; margin: 0.4rem 0 0.1rem; }
    .notes-editor .md-h4,
    .notes-editor .md-h5,
    .notes-editor .md-h6 { font-size: 0.95rem; margin: 0.35rem 0 0.1rem; }
    .notes-editor .md-hash { color: var(--c-ink-300); font-weight: 400; }

    /* Mermaid diagram block — rendered SVG sits inside; on focus the block
       expands back to its ```mermaid``` source for editing (see expand
       function in notes.js). contenteditable="false" makes it an atomic
       character — cursor sits before/after, Backspace deletes the whole block. */
    .notes-editor .mermaid-block {
      position: relative;
      margin: 0.75rem 0;
      padding: 0.85rem 1rem;
      background: var(--c-fill-300);
      border: 1px solid var(--c-line-100);
      border-radius: 8px;
      text-align: center;
      cursor: default;
      overflow-x: auto;
      transition: border-color 0.15s, box-shadow 0.15s;
    }
    /* "⋮ source" button on a rendered mermaid block — top-right, fades in
       on hover. Clicking it flips the whole block into raw mermaid-source
       editing (same UX as .md-table-edit-src). */
    .notes-editor .mermaid-edit-src {
      position: absolute;
      top: 0.3rem;
      right: 0.4rem;
      background: transparent;
      border: 1px solid transparent;
      border-radius: 4px;
      font-size: 0.7rem;
      color: var(--c-ink-400);
      cursor: pointer;
      padding: 0.1rem 0.4rem;
      opacity: 0;
      transition: opacity 0.15s, background 0.15s, color 0.15s, border-color 0.15s;
      z-index: 1;
    }
    .notes-editor .mermaid-block:hover .mermaid-edit-src {
      opacity: 1;
    }
    .notes-editor .mermaid-edit-src:hover {
      background: var(--c-fill-100);
      border-color: var(--c-line-200);
      color: var(--c-ink-700);
    }
    .notes-editor .mermaid-block:hover {
      border-color: var(--c-line-200);
      box-shadow: 0 1px 4px rgba(43, 39, 35, 0.08);
    }
    .notes-editor .mermaid-block svg {
      max-width: 100%;
      height: auto;
    }

    /* Excalidraw block — atomic contenteditable=false card holding a static
       SVG preview of a hand-drawn scene. Mirrors .mermaid-block visually.
       Two corner buttons: ✎ edit (opens the modal canvas) and ⋮ source
       (flips to raw JSON). See js/excalidraw.js. */
    .notes-editor .excalidraw-block {
      position: relative;
      margin: 0.75rem 0;
      padding: 0.85rem 1rem;
      background: var(--c-white);
      border: 1px solid var(--c-line-100);
      border-radius: 8px;
      text-align: center;
      cursor: default;
      overflow-x: auto;
      transition: border-color 0.15s, box-shadow 0.15s;
    }
    .notes-editor .excalidraw-block:hover {
      border-color: var(--c-line-200);
      box-shadow: 0 1px 4px rgba(43, 39, 35, 0.08);
    }
    .notes-editor .excalidraw-block svg,
    .notes-editor .excalidraw-block img {
      /* Cap the displayed preview so it doesn't balloon to the full box width.
         min(680px, 100%) → at most 680px on a wide box, shrinks to fit on a
         narrow one; height:auto scales proportionally. Never upscales a small
         diagram. Open ✎ edit for the full-size interactive canvas. */
      max-width: min(680px, 100%);
      height: auto;
    }
    .notes-editor .excalidraw-edit-btn,
    .notes-editor .excalidraw-dl-btn,
    .notes-editor .excalidraw-edit-src,
    .notes-editor .excalidraw-del-btn {
      position: absolute;
      top: 0.3rem;
      background: transparent;
      border: 1px solid transparent;
      border-radius: 4px;
      font-size: 0.7rem;
      color: var(--c-ink-400);
      cursor: pointer;
      padding: 0.1rem 0.4rem;
      opacity: 0;
      transition: opacity 0.15s, background 0.15s, color 0.15s, border-color 0.15s;
      z-index: 1;
    }
    .notes-editor .excalidraw-edit-src { right: 0.4rem; }
    .notes-editor .excalidraw-dl-btn  { right: 4.4rem; }
    .notes-editor .excalidraw-edit-btn { right: 8.4rem; }
    .notes-editor .excalidraw-del-btn { right: 12.4rem; }
    .notes-editor .excalidraw-block:hover .excalidraw-edit-btn,
    .notes-editor .excalidraw-block:hover .excalidraw-dl-btn,
    .notes-editor .excalidraw-block:hover .excalidraw-edit-src,
    .notes-editor .excalidraw-block:hover .excalidraw-del-btn,
    .notes-editor .excalidraw-edit-btn:focus,
    .notes-editor .excalidraw-dl-btn:focus,
    .notes-editor .excalidraw-edit-src:focus,
    .notes-editor .excalidraw-del-btn:focus {
      opacity: 1;
    }
    .notes-editor .excalidraw-edit-btn:hover,
    .notes-editor .excalidraw-dl-btn:hover,
    .notes-editor .excalidraw-edit-src:hover {
      background: var(--c-fill-100);
      border-color: var(--c-line-200);
      color: var(--c-ink-700);
    }
    .notes-editor .excalidraw-del-btn:hover {
      background: var(--c-red-050);
      border-color: var(--c-red-200);
      color: var(--c-red);
    }
    .notes-editor .excalidraw-loading,
    .notes-editor .excalidraw-empty {
      color: var(--c-ink-400);
      font-style: italic;
      font-size: 0.85rem;
      padding: 1.25rem 1rem;
    }
    /* ADD-ON: Diagram|Video view toggle + embedded lesson player. */
    .notes-editor .excalidraw-video-toggle {
      position: absolute;
      top: -1.9rem;            /* sits ABOVE the card's top border, outside the box */
      right: 0.4rem;
      z-index: 4;
      display: inline-flex;
      gap: 2px;
      padding: 2px;
      background: var(--c-fill-100);
      border: 1px solid var(--c-line-200);
      border-radius: 7px;
      opacity: 0;
      transition: opacity 0.15s;
    }
    /* Reveal on hover / focus — exactly like the edit/png/source/delete icons. */
    .notes-editor .excalidraw-block:hover .excalidraw-video-toggle,
    .notes-editor .excalidraw-video-toggle:focus-within { opacity: 1; }
    /* Video-enabled blocks: let the toggle sit OUTSIDE (above) the border, and
       reserve a little space above so it never collides with the text above. The
       diagram SVG is max-width-capped (never overflows), so dropping the scroll
       clip here is safe. Scoped to .has-video-toggle — every other diagram is
       completely untouched. */
    .notes-editor .excalidraw-block.has-video-toggle {
      overflow: visible;
      margin-top: 2.5rem;
    }
    .notes-editor .excalidraw-video-toggle .exv-seg {
      border: 0;
      background: transparent;
      cursor: pointer;
      font-size: 0.72rem;
      font-weight: 700;
      color: var(--c-ink-900);
      border-radius: 5px;
      padding: 0.18rem 0.55rem;
      line-height: 1.2;
    }
    .notes-editor .excalidraw-video-toggle .exv-seg.exv-on {
      background: var(--c-ink-700);
      color: var(--c-white);
    }
    .notes-editor .excalidraw-video-wrap {
      position: relative;
      width: 100%;
      max-width: 900px;
      margin: 0.4rem auto 0;
      aspect-ratio: 16 / 10;
      border-radius: 10px;
      overflow: hidden;
      background: var(--c-fill-150);
      border: 1px solid var(--c-line-100);
    }
    .notes-editor .excalidraw-video-iframe {
      position: absolute;
      inset: 0;
      width: 100%;
      height: 100%;
      border: 0;
    }
    .notes-editor .excalidraw-error {
      color: var(--c-red);
      font-size: 0.78rem;
      padding: 0.5rem 0.75rem;
      margin-top: 0.5rem;
      background: var(--c-red-050);
      border-radius: 4px;
      text-align: left;
    }
    .notes-editor .excalidraw-fallback {
      background: var(--c-fill-150);
      color: var(--c-ink-600);
      padding: 0.75rem;
      border-radius: 4px;
      font-family: 'Menlo', 'Consolas', monospace;
      font-size: 0.72rem;
      text-align: left;
      white-space: pre-wrap;
      word-break: break-word;
      margin: 0;
      max-height: 180px;
      overflow: auto;
    }
    .notes-editor .mermaid-loading {
      color: var(--c-ink-400);
      font-style: italic;
      font-size: 0.85rem;
      padding: 1rem;
    }
    .notes-editor .mermaid-error {
      color: var(--c-red);
      font-family: 'Menlo', 'Consolas', monospace;
      font-size: 0.78rem;
      padding: 0.5rem 0.75rem;
      margin-top: 0.5rem;
      background: var(--c-red-050);
      border-radius: 4px;
      text-align: left;
      white-space: pre-wrap;
      word-break: break-word;
    }
    .notes-editor .mermaid-fallback {
      background: var(--c-fill-150);
      color: var(--c-ink-600);
      padding: 0.75rem;
      border-radius: 4px;
      font-family: 'Menlo', 'Consolas', monospace;
      font-size: 0.8rem;
      text-align: left;
      white-space: pre-wrap;
      word-break: break-word;
      margin: 0;
    }

    /* Markdown table block — atomic contenteditable=false wrapper, but
       individual cells are contenteditable so they edit inline. The "⋮ source"
       button in the top-right swaps the whole block back to raw `|col|col|`
       lines for restructuring (add/remove rows, change alignment). */
    .notes-editor .md-table-block {
      position: relative;
      margin: 0.75rem 0;
      padding: 0.5rem;
      background: var(--c-white);
      border: 1px solid var(--c-line-100);
      border-radius: 6px;
      cursor: default;
      transition: border-color 0.15s, box-shadow 0.15s;
    }
    /* The TABLE scrolls horizontally inside this wrapper — NOT the whole block —
       so the absolute ⋮source button and the +/−Row/Col controls stay pinned to
       the block's top-right instead of scrolling away (mid-table) on a wide table. */
    .notes-editor .md-table-scroll { overflow-x: auto; }
    .notes-editor .md-table-block:hover {
      border-color: var(--c-line-200);
      box-shadow: 0 1px 4px rgba(43, 39, 35, 0.08);
    }
    /* Top-right control cluster (❄ freeze + ⋮ source) — a flex row so the two
       buttons auto-space and never overlap regardless of label width. */
    .notes-editor .md-table-tools {
      position: absolute;
      top: 0.3rem;
      right: 0.4rem;
      display: flex;
      gap: 4px;
      z-index: 3;
    }
    .notes-editor .md-table-edit-src {
      background: transparent;
      border: 1px solid transparent;
      border-radius: 4px;
      font-size: 0.7rem;
      color: var(--c-ink-400);
      cursor: pointer;
      padding: 0.1rem 0.4rem;
      opacity: 0;
      transition: opacity 0.15s, background 0.15s, color 0.15s, border-color 0.15s;
    }
    .notes-editor .md-table-block:hover .md-table-edit-src,
    .notes-editor .md-table-edit-src:focus {
      opacity: 1;
    }
    .notes-editor .md-table-edit-src:hover {
      background: var(--c-fill-100);
      border-color: var(--c-line-200);
      color: var(--c-ink-700);
    }
    /* ❄ Freeze-header toggle — same hover-reveal as ⋮ source. Stays visible
       (opacity 1) when active so a frozen table is recognisable. Not hidden in
       read-only (it's a display-only view control). */
    .notes-editor .md-table-freeze {
      background: transparent;
      border: 1px solid transparent;
      border-radius: 4px;
      font-size: 0.72rem;
      line-height: 1;
      color: var(--c-ink-400);
      cursor: pointer;
      padding: 0.1rem 0.4rem;
      opacity: 0;
      transition: opacity 0.15s, background 0.15s, color 0.15s, border-color 0.15s;
    }
    .notes-editor .md-table-block:hover .md-table-freeze,
    .notes-editor .md-table-freeze:focus,
    .notes-editor .md-table-freeze.active { opacity: 1; }
    .notes-editor .md-table-freeze:hover { background: var(--c-fill-100); border-color: var(--c-line-200); color: var(--c-ink-700); }
    .notes-editor .md-table-freeze.active { color: var(--c-ink-700); border-color: var(--c-line-200); background: var(--c-fill-100); }
    /* Frozen table: cap the height and scroll the rows inside the window with
       the header row pinned (the thead already has an opaque var(--c-fill-150) background,
       so rows don't bleed through). Excel-style freeze panes. */
    .notes-editor .md-table-block.md-table-frozen .md-table-scroll {
      max-height: 65vh;
      overflow-y: auto;
    }
    .notes-editor .md-table-block.md-table-frozen .md-table thead th {
      position: sticky;
      top: 0;
      z-index: 2;
    }
    /* Clear-all-sort/filter pill — sits at the block top-left, rendered ONLY when
       a sort/filter is active. Flow-positioned (above the .md-table-ctrls row in
       edit mode, above the table in read-only) so it never overlaps. Deliberately
       NOT hidden in read-only, since sort/filter work there. */
    .notes-editor .md-table-clear-view {
      display: inline-flex;
      align-items: center;
      gap: 4px;
      font-family: inherit;
      font-size: 0.68rem;
      padding: 0.12rem 0.5rem;
      margin-bottom: 0.4rem;
      border: 1px solid var(--c-line-200);
      background: var(--c-fill-100);
      color: var(--c-ink-700);
      border-radius: 4px;
      cursor: pointer;
    }
    .notes-editor .md-table-clear-view:hover { background: var(--c-line-150); border-color: var(--c-line-250); }
    .notes-editor .md-table {
      border-collapse: collapse;
      font-size: 0.85rem;
      width: 100%;
    }
    .notes-editor .md-table th,
    .notes-editor .md-table td {
      border: 1px solid var(--c-line-100);
      padding: 0.45rem 0.65rem;
      text-align: left;
      vertical-align: top;
      color: var(--c-ink-600);
    }
    /* Header cells anchor the drag-to-resize handle; fixed layout makes the
       <col> widths authoritative once the user has resized. */
    .notes-editor .md-table th { position: relative; }
    .notes-editor .md-table.md-table-fixed { table-layout: fixed; }
    /* Anti-congestion safety net: a table that was never sized (no colgroup, so
       auto-layout at width:100%) would slice into unreadable slivers once it has
       many columns. A per-cell min-width makes the table overflow and scroll
       (.md-table-scroll) instead. Fixed-layout (Fitted/resized) tables use their
       explicit <col> widths and ignore this. Few/medium columns still fill 100%. */
    .notes-editor .md-table:not(.md-table-fixed) th,
    .notes-editor .md-table:not(.md-table-fixed) td { min-width: 110px; }
    /* Resize handle reuses the .col-resize base (position/cursor/hover/
       readonly-hide); nudged to straddle the column border for easy grabbing. */
    .notes-editor .md-table .md-col-resize { right: -2px; width: 8px; }
    .notes-editor .md-table thead th {
      background: var(--c-fill-150);
      font-weight: 600;
      color: var(--c-ink-800);
    }
    .notes-editor .md-table tbody tr:nth-child(even) {
      background: var(--c-white);
    }
    /* ── Notes-table sort / filter (display-only view controls) ── */
    .notes-editor .md-table thead th:has(.tv-th-ctrls) { padding-right: 2.1rem; }
    .tv-th-ctrls {
      position: absolute;
      top: 50%;
      right: 11px;                 /* clear of the resize handle on the border */
      transform: translateY(-50%);
      display: inline-flex;
      gap: 1px;
      align-items: center;
      background: var(--c-fill-150);          /* match header bg so it occludes text behind */
    }
    .tv-sort, .tv-filter {
      cursor: pointer;
      color: var(--c-ink-400);
      font-size: 0.68rem;
      line-height: 1;
      padding: 2px;
      border-radius: 3px;
      user-select: none;
    }
    .tv-sort:hover, .tv-filter:hover { color: var(--c-ink-700); background: var(--c-line-100); }
    .tv-sort.tv-on, .tv-filter.tv-on { color: var(--c-ink-700); }
    .notes-editor .md-table tr.tv-row-hidden { display: none; }
    /* Filter dropdown (floating; appended to <body>). */
    .tv-filter-pop {
      position: absolute;
      z-index: 1000;
      width: 240px;
      background: var(--c-white);
      border: 1px solid var(--c-line-200);
      border-radius: 8px;
      box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
      padding: 8px;
      font-size: 0.8rem;
      color: var(--c-ink-600);
    }
    .tv-filter-search {
      width: 100%;
      box-sizing: border-box;
      padding: 5px 8px;
      border: 1px solid var(--c-line-200);
      border-radius: 6px;
      font-size: 0.8rem;
      margin-bottom: 6px;
    }
    .tv-filter-mode { display: flex; gap: 4px; margin-bottom: 6px; }
    .tv-filter-mode button {
      flex: 1;
      padding: 3px 6px;
      border: 1px solid var(--c-line-200);
      border-radius: 6px;
      background: var(--c-white);
      color: var(--c-ink-500);
      cursor: pointer;
      font-size: 0.72rem;
    }
    .tv-filter-mode button:hover { background: var(--c-fill-150); }
    .tv-filter-mode button.active { background: var(--c-fill-200); border-color: var(--c-ink-700); color: var(--c-ink-700); font-weight: 600; }
    .tv-filter-tools { display: flex; justify-content: space-between; margin-bottom: 4px; }
    .tv-filter-tools button {
      background: none; border: none; color: var(--c-ink-700); cursor: pointer; font-size: 0.74rem; padding: 2px 4px;
    }
    .tv-filter-tools button:hover { text-decoration: underline; }
    .tv-filter-list {
      max-height: 220px; overflow-y: auto;
      border-top: 1px solid var(--c-line-100); border-bottom: 1px solid var(--c-line-100); padding: 4px 0;
    }
    .tv-filter-item { display: flex; align-items: center; gap: 6px; padding: 3px 4px; cursor: pointer; border-radius: 4px; }
    .tv-filter-item:hover { background: var(--c-fill-150); }
    .tv-filter-item input { flex-shrink: 0; margin: 0; }
    .tv-filter-item span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
    .tv-filter-item .tv-empty { color: var(--c-ink-400); font-style: italic; }
    .tv-filter-foot { display: flex; justify-content: flex-end; gap: 6px; margin-top: 8px; }
    .tv-btn { padding: 4px 12px; border: 1px solid var(--c-line-200); border-radius: 6px; background: var(--c-white); cursor: pointer; font-size: 0.78rem; }
    .tv-btn:hover { background: var(--c-fill-150); }
    .tv-btn-primary { background: var(--c-ink-700); border-color: var(--c-ink-700); color: var(--c-white); }
    .tv-btn-primary:hover { background: var(--c-ink-900); }
    /* Inline markdown rendered in notes (free text AND table cells): **bold**
       and `code`. Scoped to .notes-editor so it never touches the outline
       panel's <code> chips. The markers themselves are hidden (the text is
       wrapped in <strong>/<code>); getEditorContent/cellToMarkdown put the
       ** / ` back on save, so the stored markdown is unchanged. */
    .notes-editor strong, .notes-editor b { font-weight: 700; }
    .notes-editor em, .notes-editor i { font-style: italic; }
    .notes-editor u { text-decoration: underline; }
    .notes-editor code {
      font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
      font-size: 0.85em;
      background: var(--c-fill-150);
      border: 1px solid var(--c-line-100);
      border-radius: 3px;
      padding: 0.05em 0.32em;
      color: var(--c-code);
      white-space: pre-wrap;
    }
    /* Fullscreen a single notes box (⛶ action) — fills the viewport so a wide
       table has the whole screen width. Pure CSS toggle (.tt-box-fs); the editor
       inside keeps its listeners. Esc or the button exits. */
    .notes-box.tt-box-fs {
      position: fixed;
      inset: 0;
      z-index: 9000;
      margin: 0;
      width: 100vw;
      height: 100vh;
      max-width: none;
      background: var(--c-white);
      padding: 0.5rem 1rem 1rem;
      overflow: auto;
      border: none;
      border-radius: 0;
      box-shadow: none;
    }
    .notes-box.tt-box-fs .notes-editor {
      height: calc(100vh - 3rem) !important;
      max-height: none;
    }
    /* Lock the page behind the fullscreen box so only the box scrolls. */
    body.tt-box-fs-active { overflow: hidden; }
    /* In fullscreen, show ONLY the ⛶ toggle (which exits) and hide every other
       box action — so the ✕ (delete box) can't be mistaken for "close fullscreen".
       Keep the actions bar always visible (not hover-only) so the exit is obvious. */
    .notes-box.tt-box-fs .notes-box-actions { opacity: 1; }
    .notes-box.tt-box-fs .notes-box-actions .box-action:not(.box-fs) { display: none !important; }
    /* +/− Row/Col controls on a table block — revealed on hover, like ⋮ source. */
    .notes-editor .md-table-ctrls {
      display: flex;
      gap: 4px;
      margin-bottom: 0.4rem;
      opacity: 0;
      transition: opacity 0.15s;
    }
    .notes-editor .md-table-block:hover .md-table-ctrls,
    .notes-editor .md-table-block:focus-within .md-table-ctrls { opacity: 1; }
    .notes-editor .md-tbl-btn {
      font-family: inherit;
      font-size: 0.68rem;
      padding: 0.12rem 0.45rem;
      border: 1px solid var(--c-line-100);
      background: var(--c-white);
      color: var(--c-ink-500);
      border-radius: 4px;
      cursor: pointer;
      transition: all 0.12s;
    }
    .notes-editor .md-tbl-btn:hover { border-color: var(--c-ink-700); color: var(--c-ink-700); background: var(--c-fill-100); }
    .notes-editor .md-tbl-btn.md-tbl-del:hover { border-color: var(--c-red-300); color: var(--c-red); background: var(--c-red-050); }
    /* Per-cell editing affordances — subtle blue ring when focused, white
       background to make typed text stand out from the row stripe. */
    .notes-editor .md-table th:focus,
    .notes-editor .md-table td:focus {
      outline: 2px solid var(--c-line-200);
      outline-offset: -2px;
      background: var(--c-white);
    }
    /* Inline images pasted into a box are wrapped in a resizable .img-wrap.
       Wrapper handles the native browser resize (corner drag); the img inside
       fills the wrapper at 100%/100% via object-fit. The wrapper itself is
       contenteditable=false so it behaves as a single atomic character —
       cursor sits before/after, Backspace deletes the whole image. */
    .notes-editor .img-wrap {
      display: inline-block;
      resize: both;
      overflow: hidden;
      max-width: 100%;
      vertical-align: middle;
      border: 1px solid var(--c-line-100);
      border-radius: 6px;
      margin: 0.15rem 0;
      line-height: 0;
      cursor: default;
    }
    .notes-editor .img-wrap:hover {
      border-color: var(--c-line-200);
      box-shadow: 0 1px 4px rgba(43,39,35,0.15);
    }
    .notes-editor .img-wrap img {
      width: 100%;
      height: 100%;
      display: block;
      object-fit: contain;
      pointer-events: none; /* clicks bubble to wrapper, not the img */
    }
    /* Fallback for bare <img> not yet wrapped (shouldn't appear after migration) */
    .notes-editor img:not(.img-wrap img) {
      max-width: 100%;
      vertical-align: middle;
      border-radius: 6px;
    }

    /* ── Parent Task sub-sub-tabs (vertical sidebar) ──
       Sits to the left of the toolbar+table as a thin vertical bar. */
    .content-row {
      display: flex;
      gap: 13px;
      align-items: flex-start;
    }
    .content-col { flex: 1; min-width: 0; }

    .parent-task-tabs {
      display: flex;
      flex-direction: column;
      gap: 1px;
      min-width: 160px;
      max-width: 220px;
      flex-shrink: 0;
      padding-top: 0.15rem;
      /* Stick to the top of the viewport on scroll so the sidebar stays
         visible while paging through a long table or note. */
      position: sticky;
      top: 1rem;
      max-height: calc(100vh - 2rem);
      overflow-y: auto;
    }
    .parent-task-tabs:empty { display: none; }
    .parent-task-tab {
      padding: 0.35rem 0.7rem;
      border: none;
      background: none;
      color: var(--c-ink-500);
      cursor: pointer;
      font-size: 0.78rem;
      font-weight: 500;
      font-family: inherit;
      transition: all 0.15s;
      text-align: left;
      display: flex;
      align-items: center;
      justify-content: space-between;
      gap: 6px;
      border-left: 2px solid transparent;
      border-radius: 0 4px 4px 0;
    }
    .parent-task-tab:hover { color: var(--c-ink-700); background: var(--c-fill-100); }
    .parent-task-tab.active {
      color: var(--c-ink-900);
      font-weight: 500;
      background: var(--c-fill-100);
      border-left: 2px solid var(--c-ink-700);
    }
    .parent-task-tab .del-sub {
      background: none;
      border: none;
      color: inherit;
      cursor: pointer;
      font-size: 0.7rem;
      padding: 0;
      line-height: 1;
      opacity: 0;
      transition: opacity 0.12s;
      flex-shrink: 0;
    }
    .parent-task-tab:hover .del-sub { opacity: 0.6; }
    .parent-task-tab .del-sub:hover { opacity: 1; color: var(--c-red); }
    .pt-name {
      flex: 1;
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
    }
    .pt-name[contenteditable="true"] {
      outline: 1px solid var(--c-ink-700);
      border-radius: 3px;
      padding: 0 4px;
      background: var(--c-white);
      color: var(--c-ink-800);
      cursor: text;
      white-space: normal;
    }
    .add-pt-tab {
      padding: 0.35rem 0.7rem;
      border: none;
      background: none;
      color: var(--c-ink-400);
      cursor: pointer;
      font-size: 0.75rem;
      font-family: inherit;
      transition: color 0.15s;
      text-align: left;
      margin-top: 0.25rem;
    }
    .add-pt-tab:hover { color: var(--c-ink-700); }

    /* ── Notes outline (notes-epic mode reuses the .parent-task-tabs slot) ── */
    /* His outline: a wider panel with a hairline on its right (Rishabh 2026-09-14: "outline ki vertical line separating from
       main content missing"), a head well, sentence-case rows in the display face, 10px radii. */
    .parent-task-tabs:has(.outline-all) { min-width: 160px; max-width: 220px; gap: 0; padding: 0 0 8px; border-right: 1px solid var(--c-line-150); }   /* a line you can see (Rishabh 2026-09-14: "no separator") */
    .parent-task-tabs:has(.outline-all) .parent-task-tab { border-left: 0; border-radius: 10px; }
    .parent-task-tab.outline-all {
      color: var(--c-ink-900);
      font-family: var(--font-display);
      font-size: 12.5px;
      font-weight: 500;
      letter-spacing: -0.01em;
      text-transform: none;
      height: 48px;
      padding: 13px 14px 11px;
      margin: 0 0 6px;
      background: var(--c-bg);
      border-radius: 10px;
      justify-content: space-between;
    }
    .parent-task-tab.outline-all:hover { background: var(--c-bg); color: var(--c-ink-900); }
    .outline-all-label { flex: 1; overflow: hidden; text-overflow: ellipsis; }
    /* Expanded outline: fill the column height so the empty space BELOW the last
       heading is still inside #parentTaskTabs - right-click there -> Paste box works.
       Without this the panel shrinks to its few items and that empty area falls
       OUTSIDE the container (native menu shows instead). Only matches the expanded
       outline (it has .outline-all); table mode + the collapsed rail don't. */
    .parent-task-tabs:has(.outline-all) { min-height: calc(100vh - 2rem); }
    .outline-collapse-chev { width: 24px; height: 24px; display: grid; place-items: center; border-radius: 999px; font-size: 13px; color: var(--c-ink-400); transition: color 0.15s, background 0.15s; flex-shrink: 0; }
    .parent-task-tab.outline-all:hover .outline-collapse-chev { color: var(--c-ink-700); background: var(--c-fill-100); }
    /* Collapsed outline (the team member's, his computed values): a 40px rail - a 30px toggle, then one 24px numbered pip per
       box; the pip of the box in view is filled ink. */
    .parent-task-tabs.outline-collapsed { min-width: 0; max-width: none; width: 40px; padding: 8px 0 10px; gap: 8px; display: flex; flex-direction: column; align-items: center; border-right: 1px solid var(--c-line-150); height: auto; max-height: calc(100vh - 2rem); overflow: hidden; }
    /* the rail toggle is the expanded head's chevron, reversed (« / »): same 24px round well (Rishabh 2026-09-14: "reverse arrow, consistency") */
    .outline-rail-toggle { width: 24px; height: 24px; border: 0; border-radius: 999px; background: transparent; color: var(--c-ink-400); font-size: 13px; line-height: 1; display: grid; place-items: center; cursor: pointer; transition: color .12s, background .12s; }
    .outline-rail-toggle:hover { color: var(--c-ink-700); background: var(--c-fill-100); }
    .outline-rail-list { display: flex; flex-direction: column; align-items: center; gap: 5px; padding: 7px 0 2px; }
    /* pips = the same control pattern as every seg / layout button: 8px radius, fill well, ink when active - no bespoke shadows (Rishabh 2026-09-14: "same pattern jo har jagah hai") */
    .outline-pip { width: 24px; height: 24px; padding: 0; border: 0; border-radius: 8px; background: transparent; color: var(--c-ink-500); font-family: var(--font-display); font-size: 10.5px; font-weight: 500; display: grid; place-items: center; cursor: pointer; transition: background .12s, color .12s; }
    .outline-pip:hover { color: var(--c-ink-900); background: var(--c-fill-200); }
    .outline-pip.is-current { color: var(--c-ink-900); font-weight: 600; background: var(--c-fill-current); box-shadow: inset 0 0 0 .5px var(--c-ring-current); }   /* the same surface as the expanded current row (Rishabh 2026-09-15: "collapse mein highlight missing hai") */
    /* The current row (scroll-spy / outline click): the team member's surface - a quiet fill + a half-pixel ring, one filled
       row per panel (Rishabh 2026-09-15: "selected wale outline pe highlighting nahi hai", his reference screenshot). */
    .parent-task-tabs .outline-part-header.is-current, .parent-task-tabs .parent-task-tab.outline-item.is-current { color: var(--c-ink-900); font-weight: 500; background: var(--c-fill-current); box-shadow: inset 0 0 0 .5px var(--c-ring-current); }
    .parent-task-tabs .outline-part-header.is-current-part .outline-part-label { color: var(--c-ink-900); }
    /* a hairline between boxes (Rishabh 2026-09-14: "outline mein koi row separator hi nahi") */
    .parent-task-tabs:has(.outline-all) .outline-part-header + .outline-part-header,
    .parent-task-tabs:has(.outline-all) .parent-task-tab.outline-item + .outline-part-header { border-top: 1px dashed var(--c-line-100); border-radius: 0 0 10px 10px; margin-top: 4px; padding-top: 7px; }   /* prod's subtle dashed hairline (Rishabh 2026-09-14: "pehle wala theek tha, subtle") */
    .parent-task-tab.outline-item {
      font-family: var(--font-display);
      font-size: 12.5px;
      color: var(--c-ink-500);
      padding: 5px 11px;
      margin: 0 8px;
      /* Base .parent-task-tab is space-between (table-mode pills have a right-side
         ✕); outline rows have a left chevron + label, so pull them left. */
      justify-content: flex-start;
      gap: 4px;
    }
    .parent-task-tab.outline-l2 { font-size: 12px; color: var(--c-ink-500); }
    .parent-task-tab.outline-l3 { font-size: 11.5px; color: var(--c-ink-400); }
    .outline-item-label, .outline-part-label { min-width: 0; overflow-wrap: anywhere; }
    /* Collapsible-heading chevron (▸ → ▾ on expand). A leaf gets the same-width
       invisible spacer so same-level rows stay left-aligned - but only on a level where
       some row actually has a chevron; a level with none emits no slot at all
       (notes-outline.js levelHasToggle). */
    .outline-chevron {
      flex-shrink: 0;
      display: inline-flex;
      align-items: center;
      justify-content: center;
      width: 0.85rem;
      font-size: 0.6rem;
      color: var(--c-ink-400);
      cursor: pointer;
      user-select: none;
      transition: transform 0.15s ease, color 0.15s;
    }
    .outline-chevron:hover { color: var(--c-ink-700); }
    .outline-chevron.open { transform: rotate(90deg); }
    .outline-chevron-spacer { visibility: hidden; cursor: default; }
    /* Part header — shown when the doc has 2+ `---` -separated parts.
       Sits above the headings of that part, slightly indented, with a top
       border separating it from the previous part's headings. */
    .outline-part-header {
      padding: 6px 9px;
      margin: 1px 8px 0;
      font-family: var(--font-display);
      font-size: 12.5px;
      font-weight: 500;
      color: var(--c-ink-900);
      letter-spacing: -0.01em;
      cursor: pointer;
      border-radius: 10px;
      transition: color 0.15s, background 0.15s;
      display: flex;
      align-items: center;
      gap: 6px;
    }
    /* No static ▾ before a part header any more: it looked like a collapse control and collapsed nothing (Rishabh
       2026-09-14: "outline heading collapse and expand mein problem hai"). A heading that CAN collapse carries the real
       .outline-chevron the outline renders (.has-toggle); one that cannot shows no marker at all. */
    .outline-part-header:hover { color: var(--c-ink-900); background: var(--c-fill-100); }
    /* Drag-to-reorder (sidebar): dim the box being dragged, show a drop bar on
       the target. Scoped to .outline-part-header so it can't touch table pills. */
    .outline-part-header[draggable="true"] { cursor: grab; }
    .outline-part-header.outline-dragging { opacity: 0.4; }
    .outline-part-header.drag-over { background: var(--c-fill-200); box-shadow: inset 0 2px 0 var(--c-ink-700); }
    .outline-empty {
      padding: 0.5rem 0.7rem;
      font-size: 0.72rem;
      color: var(--c-ink-300);
      font-style: italic;
      line-height: 1.5;
    }
    .outline-empty code {
      background: var(--c-fill-150);
      color: var(--c-ink-500);
      padding: 0 4px;
      border-radius: 3px;
      font-size: 0.9em;
    }

    /* ── Category tabs (4th-level nav, only for sections that opt in) ──
       Renders above the toolbar. Empty (hidden) for sections without
       categories — so the rest of the app is visually identical. */
    .category-tabs {
      display: flex;
      gap: 4px;
      margin-bottom: 0.6rem;
      border-bottom: 1px solid var(--c-line-100);
    }
    .category-tabs:empty { display: none; }
    .category-tab {
      padding: 0.4rem 0.9rem;
      background: none;
      color: var(--c-ink-500);
      cursor: pointer;
      font-size: 0.8rem;
      font-weight: 500;
      transition: all 0.15s;
      border-bottom: 2px solid transparent;
      margin-bottom: -1px;
    }
    .category-tab:hover { color: var(--c-ink-700); }
    .category-tab.active {
      color: var(--c-ink-700);
      font-weight: 600;
      border-bottom: 2px solid var(--c-ink-700);
    }

    /* ── Toolbar ── */
    .toolbar {
      display: flex;
      gap: 0.6rem;
      margin-bottom: 0.6rem;
      justify-content: flex-end;
      align-items: center;
    }

    /* Heading label for the currently-selected Parent Task — sits at the
       left of the toolbar row. Hidden when on "All" or on a Categorized
       section (Personal — that area is already busy with Category tabs). */
    .active-pt-label {
      margin-right: auto;
      font-size: 1.05rem;
      font-weight: 600;
      color: var(--c-ink-700);
      letter-spacing: 0.01em;
    }
    .active-pt-label:empty { display: none; }

    .btn {
      padding: 7px 13px;
      border-radius: 10px;
      border: 1px solid var(--c-line-200);
      background: var(--c-white);
      color: var(--c-ink-800);
      cursor: pointer;
      font-size: 13px;
      font-weight: 500;
      font-family: inherit;
      line-height: 1.2;
      white-space: nowrap;
      box-shadow: 0 1px 2px rgba(11,26,20,.04);
      transition: border-color 0.15s, background 0.15s, color 0.15s;
    }

    .btn:hover { border-color: var(--c-ink-900); color: var(--c-ink-900); }
    .btn-primary { background: var(--c-ink-900); border-color: var(--c-ink-900); color: var(--c-white); }
    .btn-primary:hover { background: #000; border-color: #000; color: var(--c-white); }
    .btn-danger { color: var(--c-red); border-color: var(--c-red-300); }
    .btn-danger:hover { background: var(--c-red-050); border-color: var(--c-red); }

    /* ── Restore-to-an-earlier-time modal (js/restore.js) ──
       z-index sits above the fullscreen notes box (9000) and the Excalidraw
       modal backdrop (10000) so it's always reachable from either. */
    .tt-restore-backdrop {
      position: fixed; inset: 0; z-index: 10050;
      background: rgba(17, 24, 39, 0.45);
      display: flex; align-items: flex-start; justify-content: center;
      padding: 6vh 1rem; font-family: 'Instrument Sans', 'Inter', system-ui, sans-serif;
    }
    .tt-restore-card {
      background: var(--c-white); border-radius: 14px; width: 100%; max-width: 640px;
      max-height: 84vh; display: flex; flex-direction: column;
      box-shadow: 0 12px 44px rgba(0,0,0,0.22); overflow: hidden;
    }
    .tt-restore-head {
      display: flex; align-items: center; justify-content: space-between;
      padding: 0.9rem 1.1rem; border-bottom: 1px solid var(--c-line-100); font-size: 1.02rem;
    }
    .tt-restore-x {
      border: none; background: none; cursor: pointer; font-size: 1rem;
      color: var(--c-ink-500); padding: 0.2rem 0.4rem; border-radius: 6px;
    }
    .tt-restore-x:hover { background: var(--c-fill-150); color: var(--c-ink-800); }
    .tt-restore-body { padding: 0.9rem 1.1rem; overflow: auto; }
    .tt-restore-note {
      background: var(--c-fill-300); border: 1px solid var(--c-line-120); border-radius: 10px;
      padding: 0.7rem 0.85rem; font-size: 0.85rem; color: var(--c-ink-600); line-height: 1.5;
    }
    .tt-restore-can { margin-top: 0.35rem; font-size: 0.82rem; }
    .tt-restore-can .ok { color: var(--c-green-700); font-weight: 600; }
    .tt-restore-can .no { color: var(--c-amber-700); font-weight: 600; }
    .tt-restore-pickrow {
      display: flex; align-items: center; flex-wrap: wrap; gap: 0.5rem; margin-top: 0.9rem;
    }
    .tt-restore-lbl { font-size: 0.82rem; color: var(--c-ink-500); min-width: 84px; }
    .tt-restore-presets { display: flex; flex-wrap: wrap; gap: 0.4rem; }
    .tt-restore-preset { padding: 0.3rem 0.6rem; font-size: 0.76rem; }
    .tt-restore-when { padding: 0.35rem 0.5rem; border: 1px solid var(--c-line-200); border-radius: 6px; font: inherit; font-size: 0.8rem; }
    .tt-restore-msg { margin-top: 0.75rem; font-size: 0.84rem; color: var(--c-ink-500); min-height: 1.1em; }
    .tt-restore-msg.err { color: var(--c-red); }
    .tt-restore-preview { margin-top: 0.6rem; }
    .tt-restore-summary { font-size: 0.84rem; font-weight: 600; color: var(--c-ink-800); margin-bottom: 0.4rem; }
    .tt-restore-content {
      margin: 0; max-height: 34vh; overflow: auto; white-space: pre-wrap; word-break: break-word;
      background: var(--c-ink-900); color: var(--c-line-100); border-radius: 8px; padding: 0.7rem 0.8rem;
      font: 12px/1.5 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    }
    .tt-restore-content:empty { display: none; }
    .tt-restore-foot {
      display: flex; justify-content: flex-end; gap: 0.5rem;
      padding: 0.8rem 1.1rem; border-top: 1px solid var(--c-line-100);
    }

    /* ── Table ── */
    .table-wrapper {
      background: var(--c-white);
      border: 1px solid var(--c-line-100);
      border-radius: 10px;
      overflow: hidden;
      box-shadow: 0 1px 3px rgba(0,0,0,0.04);
      display: flex;
      flex-direction: column;
      max-height: calc(100vh - 11rem);
    }

    .table-scroll { overflow: auto; flex: 1 1 auto; min-height: 0; }

    table {
      width: 100%;
      border-collapse: collapse;
      table-layout: fixed;
    }

    /* Column widths */
    col.c-num    { width: 44px; }
    col.c-theme  { width: 130px; }
    col.c-epic   { width: 180px; }
    col.c-parent { width: 170px; }
    col.c-task   { width: 220px; }
    col.c-sub    { width: 210px; }
    col.c-owner  { width: 90px; }
    col.c-status { width: 100px; }
    col.c-notes  { width: 180px; }
    col.c-act    { width: 44px; }

    thead th {
      background: var(--c-fill-300);
      padding: 10px 14px;
      text-align: left;
      font-size: 0.75rem;
      font-weight: 600;
      letter-spacing: 0.02em;
      color: var(--c-ink-500);
      border-bottom: 2px solid var(--c-line-100);
      white-space: nowrap;
      position: sticky;
      top: 0;
      z-index: 2;
    }

    /* Column resize handle — sits on the right edge of each header. Drag to
       widen/narrow. Width persists per-column-name in localStorage. */
    .col-resize {
      position: absolute;
      right: 0;
      top: 0;
      bottom: 0;
      width: 6px;
      cursor: col-resize;
      user-select: none;
      z-index: 3;
    }
    .col-resize:hover { background: var(--c-ink-700); opacity: 0.35; }
    body.col-resizing { cursor: col-resize !important; user-select: none; }
    body.col-resizing * { cursor: col-resize !important; }

    thead th.center { text-align: center; }

    tbody tr { border-bottom: 1px solid var(--c-fill-100); transition: background 0.12s; }
    tbody tr:last-child { border-bottom: none; }
    tbody tr:nth-child(even) { background: var(--c-fill-300); }
    tbody tr:hover { background: var(--c-fill-100); }
    tbody tr.selected { background: var(--c-fill-200); }

    /* Group separator: when Theme cell has content, add top border */
    tbody tr.group-start { border-top: 2px solid var(--c-line-150); }
    tbody tr.group-start:first-child { border-top: none; }

    td {
      padding: 8px 14px;
      font-size: 0.82rem;
      color: var(--c-ink-800);
      vertical-align: top;
      line-height: 1.5;
      overflow: hidden;
    }

    td.center { text-align: center; }

    td.col-num {
      text-align: center;
      color: var(--c-ink-400);
      font-size: 0.75rem;
      font-weight: 500;
      font-variant-numeric: tabular-nums;
      position: relative;
    }

    /* Insert-row "+" — overlays the left edge of the row number cell,
       visible on row hover. Mirrors the column header insert button. */
    .ins-row-btn {
      position: absolute;
      left: 2px;
      top: 50%;
      transform: translateY(-50%);
      background: none;
      border: none;
      color: var(--c-ink-700);
      cursor: pointer;
      font-size: 0.95rem;
      font-weight: 700;
      line-height: 1;
      padding: 2px 4px;
      opacity: 0;
      transition: opacity 0.15s;
    }
    tr:hover .ins-row-btn { opacity: 0.45; }
    .ins-row-btn:hover { opacity: 1; }

    /* Theme & Epic cells — subtle color to show hierarchy */
    td.col-theme {
      font-weight: 600;
      color: var(--c-ink-700);
      font-size: 0.8rem;
    }

    td.col-epic {
      font-weight: 500;
      color: var(--c-ink-600);
    }

    td.col-parent {
      font-weight: 500;
      color: var(--c-ink-600);
    }

    td.col-task { color: var(--c-ink-800); }
    td.col-sub  { color: var(--c-ink-500); font-size: 0.8rem; }
    td.col-owner {
      font-weight: 500;
      color: var(--c-ink-600);
      font-size: 0.78rem;
    }

    td.col-status { font-size: 0.78rem; }
    td.col-notes  { color: var(--c-ink-500); font-size: 0.78rem; }

    /* Editable cells */
    .cell {
      min-height: 22px;
      padding: 2px 4px;
      border-radius: 3px;
      cursor: text;
      transition: box-shadow 0.15s;
      word-break: break-word;
      outline: none;
      /* Preserve line breaks the user types (Shift+Enter) — and preserve
         multiple spaces — while still wrapping at the cell boundary. */
      white-space: pre-wrap;
    }

    .cell:hover { box-shadow: inset 0 0 0 1px var(--c-line-200); }
    .cell:focus { box-shadow: inset 0 0 0 2px var(--c-ink-700); background: var(--c-white); }

    /* Formula cells — derived, read-only. Subtle italic + lighter color
       distinguishes them from editable cells. */
    .cell.formula-cell {
      color: var(--c-ink-500);
      font-style: italic;
      cursor: default;
    }
    .cell.formula-cell:hover { box-shadow: none; }

    /* A table pasted into a cell is stored as Markdown and rendered as a compact
       grid (see cellHtml/mdTableToHtml in table.js). Click the cell to edit the
       raw Markdown (ui.js focusin swaps the grid for the source text). */
    .cell-md-table {
      border-collapse: collapse;
      margin: 2px 0;
      font-size: 0.78rem;
      line-height: 1.35;
      white-space: normal;            /* override the cell's pre-wrap inside the grid */
    }
    .cell-md-table th,
    .cell-md-table td {
      border: 1px solid var(--c-line-200);
      padding: 2px 6px;
      text-align: left;
      vertical-align: top;
    }
    .cell-md-table th {
      background: var(--c-fill-150);
      font-weight: 600;
      color: var(--c-ink-600);
    }

    /* ── Read-only view (admin/manager browsing another user's tracker) ──
       Hide the editing affordances so the tracker is genuinely view-only.
       Content stays selectable for reading/copying; edits + mutating clicks
       are also blocked in JS (cloud-store.js read-only guards). */
    body.tt-readonly .toolbar button,
    body.tt-readonly .ins-row-btn,
    body.tt-readonly .del-btn,
    body.tt-readonly .ins-col-btn,
    body.tt-readonly .del-col-btn,
    body.tt-readonly .col-resize,
    body.tt-readonly .add-tab,
    body.tt-readonly .del-tab,
    body.tt-readonly .add-subtab,
    body.tt-readonly .add-pt-tab,
    body.tt-readonly .del-sub,
    body.tt-readonly .btn-add,
    body.tt-readonly .md-table-ctrls { display: none !important; }
    /* Read-only: hide the MUTATING box actions but KEEP the view-only fullscreen
       ⛶ so a wide table can still be blown up to read it. */
    body.tt-readonly .notes-box-actions .box-action:not(.box-fs) { display: none !important; }
    body.tt-readonly .cell,
    body.tt-readonly .notes-editor,
    body.tt-readonly .pt-name { cursor: default; }

    /* Tracker-LEVEL read-only (the parent banner already says "read-only"): the
       per-chapter 🔒 tab badges and the "View only" pill just repeat that banner,
       so hide them — one indicator at the parent level. In EDIT mode the banner
       says "editing" and this class is off, so they reappear to mark which
       chapters are still shared view-only. */
    body.tt-view-ro .subtab-ico,
    body.tt-view-ro .tts-viewonly-badge { display: none !important; }
    /* A fully view-only (shared) section carries ONE 🔒 on its tab, left of the
       name — but only in the read-only view, where it is the single parent-level
       lock. In edit/own view it is hidden (the per-chapter badges take over). */
    .tab-lock { display: none; margin-right: .3rem; }
    body.tt-view-ro .tab-lock { display: inline; }

    /* URL pills — http(s) URLs auto-wrap into a compact <a class="url-pill">
       showing just the domain (e.g. "webshare.io") so long URLs don't bloat
       the cell. Tooltip on hover reveals the full URL; right-click → "Copy
       link address". Plain click positions cursor (the global click handler
       in ui.js cancels link nav); Ctrl/Cmd+click opens in a new tab.
       On focus, the focusin handler in ui.js expands pills back to the full
       URL so the user can read/edit it. */
    .cell a.url-pill,
    .notes-editor a.url-pill {
      color: var(--c-ink-700);
      font-weight: 500;
      text-decoration: underline;
      text-decoration-color: rgba(43, 39, 35, 0.4);
      text-underline-offset: 2px;
      cursor: pointer;
      padding: 0 2px;
      border-radius: 3px;
      transition: background 0.12s, text-decoration-color 0.12s;
      /* Don't break the pill text — domain names are short enough to stay on one line */
      white-space: nowrap;
    }
    .cell a.url-pill::before,
    .notes-editor a.url-pill::before {
      content: '🔗 ';
      font-size: 0.85em;
      opacity: 0.7;
    }
    .cell a.url-pill:hover,
    .notes-editor a.url-pill:hover {
      background: rgba(43, 39, 35, 0.08);
      text-decoration-color: var(--c-ink-700);
    }

    /* Header wrapper: insert-before button + header text + delete-column button */
    .th-wrap { display: flex; align-items: center; gap: 4px; }
    .th-wrap .cell { flex: 1; }
    .ins-col-btn {
      background: none;
      border: none;
      color: var(--c-ink-700);
      cursor: pointer;
      font-size: 1rem;
      font-weight: 700;
      line-height: 1;
      padding: 0 3px;
      opacity: 0;
      transition: opacity 0.15s;
    }
    thead th:hover .ins-col-btn { opacity: 0.45; }
    .ins-col-btn:hover { opacity: 1 !important; }
    .del-col-btn {
      background: none;
      border: none;
      color: var(--c-red);
      cursor: pointer;
      font-size: 0.85rem;
      padding: 0 4px;
      opacity: 0;
      transition: opacity 0.15s;
    }
    thead th:hover .del-col-btn { opacity: 1; }

    /* ── Epic data-grid sort / filter (display-only view controls) ──
       The notes-table .tv-th-ctrls is absolute; the grid header is a flexbox, so
       these sit inline between the title and the ✕ delete button. The glyph
       styles (.tv-sort / .tv-filter / .tv-on) are reused from the notes block.
       Deliberately NOT hidden in read-only — sort/filter work there too. */
    .grid-th-ctrls { display: inline-flex; align-items: center; gap: 1px; flex-shrink: 0; }
    /* Let a long header title shrink (and clip) so the controls always stay
       visible; un-clip while it's being edited so the caret/typing behaves. */
    .th-wrap .cell { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
    .th-wrap .cell:focus { overflow: visible; text-overflow: clip; }
    /* Clear-all sort/filter pill in the table toolbar — shown only when a view is
       active. A <span> (not a .toolbar button) so it survives read-only and the
       read-only click guard. */
    .grid-clear-view {
      display: inline-flex;
      align-items: center;
      gap: 4px;
      font-size: 0.72rem;
      padding: 0.2rem 0.55rem;
      border: 1px solid var(--c-line-200);
      background: var(--c-fill-100);
      color: var(--c-ink-700);
      border-radius: 5px;
      cursor: pointer;
      user-select: none;
    }
    .grid-clear-view:hover { background: var(--c-line-150); border-color: var(--c-line-250); }
    .grid-clear-view[hidden] { display: none; }
    .grid-clear-inline {
      background: none; border: none; color: var(--c-ink-700); cursor: pointer;
      text-decoration: underline; font: inherit; padding: 0;
    }

    /* Delete button */
    .del-btn {
      background: none;
      border: none;
      cursor: pointer;
      color: var(--c-line-200);
      font-size: 0.85rem;
      padding: 2px;
      border-radius: 3px;
      transition: all 0.12s;
      opacity: 0;
    }

    tr:hover .del-btn { opacity: 1; }
    .del-btn:hover { color: var(--c-red); background: var(--c-red-050); }

    /* Empty state */
    .empty { text-align: center; padding: 2.5rem; color: var(--c-ink-400); font-size: 0.85rem; }

    /* Toast */
    .toast {
      position: fixed;
      bottom: 1.5rem;
      right: 1.5rem;
      background: var(--c-white);
      border: 1px solid var(--c-green-200);
      color: var(--c-green-700);
      padding: 0.6rem 1.1rem;
      border-radius: 8px;
      font-size: 0.8rem;
      font-weight: 500;
      box-shadow: 0 4px 12px rgba(0,0,0,0.08);
      transform: translateY(80px);
      opacity: 0;
      transition: all 0.25s ease;
      z-index: 100;
    }

    .toast.show { transform: translateY(0); opacity: 1; }

    /* Busy pill: a small bottom-right spinner shown while a copy/paste (or other
       slow op) is in flight - a big subject can take a moment and without this it
       looks like nothing happened. Shares the toast's bottom-right corner; it sits
       above the toast (z-index) so the fading pill cross-fades with the incoming
       success toast when the op finishes. */
    .tt-busy {
      position: fixed;
      bottom: 1.5rem;
      right: 1.5rem;
      display: flex;
      align-items: center;
      gap: 9px;
      background: var(--c-white);
      border: 1px solid var(--c-line-200, #e3ddd2);
      color: var(--c-ink-700, #3b3630);
      padding: 0.55rem 0.9rem;
      border-radius: 8px;
      font-size: 0.8rem;
      font-weight: 500;
      box-shadow: 0 4px 12px rgba(0,0,0,0.10);
      transform: translateY(80px);
      opacity: 0;
      transition: all 0.2s ease;
      z-index: 101;
    }
    .tt-busy.show { transform: translateY(0); opacity: 1; }
    .tt-busy-spin {
      width: 14px; height: 14px; flex: none;
      border: 2px solid var(--c-line-300, #cbc3b5);
      border-top-color: var(--c-ink-600, #4b453d);
      border-radius: 50%;
      display: inline-block;
      animation: ttspin .8s linear infinite;
    }
    @keyframes ttspin { to { transform: rotate(360deg); } }

    /* Undo toast: the shared .toast is text-only, so the roadmap renders its own
       toast with an Undo action after a destructive station delete (notes-roadmap.js). */
    .nr-undo-toast {
      position: fixed;
      bottom: 1.5rem;
      left: 50%;
      display: flex;
      align-items: center;
      gap: 12px;
      background: var(--c-white);
      border: 1px solid var(--c-line-200);
      color: var(--tl-ink, #2b2723);
      padding: 0.55rem 0.7rem 0.55rem 1rem;
      border-radius: 8px;
      font-size: 0.8rem;
      font-weight: 500;
      box-shadow: 0 6px 20px rgba(0,0,0,0.14);
      transform: translate(-50%, 80px);
      opacity: 0;
      pointer-events: none;
      transition: transform 0.22s ease, opacity 0.22s ease;
      z-index: 101;
    }
    .nr-undo-toast.show { transform: translate(-50%, 0); opacity: 1; pointer-events: auto; }
    .nr-undo-btn {
      font: inherit;
      font-weight: 700;
      color: var(--tl-accent, #2b2723);
      background: var(--c-fill-050, #f3f1ee);
      border: 1px solid var(--c-line-200);
      border-radius: 6px;
      padding: 4px 12px;
      cursor: pointer;
      transition: background .12s, border-color .12s;
    }
    .nr-undo-btn:hover { background: var(--c-fill-200, #e7e3dd); border-color: var(--tl-accent, #2b2723); }

    /* ── Excalidraw editor modal ──────────────────────────────────────────
       Full-screen overlay hosting the interactive Excalidraw canvas. Mounted
       at document.body (outside .notes-editor) so the global focus/click
       routers can't reach into it. z-index must sit ABOVE the fullscreen notes
       box (.tt-box-fs = 9000) — both are body-level position:fixed overlays, so
       a lower value would render the editor BEHIND a fullscreened box (clicking
       "edit" then appeared to do nothing). 10000 keeps it on top of everything. */
    .excalidraw-modal-backdrop {
      position: fixed;
      inset: 0;
      background: rgba(26, 26, 46, 0.45);
      z-index: 10000;
      display: flex;
      align-items: center;
      justify-content: center;
      padding: 2.5rem;
    }
    .excalidraw-modal {
      background: var(--c-white);
      border-radius: 10px;
      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
      width: 92vw;
      height: 86vh;
      display: flex;
      flex-direction: column;
      overflow: hidden;
    }
    .excalidraw-modal-header {
      display: flex;
      align-items: center;
      justify-content: space-between;
      padding: 0.75rem 1rem;
      border-bottom: 1px solid var(--c-line-100);
      flex: 0 0 auto;
    }
    .excalidraw-modal-title {
      font-size: 0.9rem;
      font-weight: 600;
      color: var(--c-ink-800);
    }
    .excalidraw-modal-actions {
      display: flex;
      gap: 0.5rem;
    }
    /* The canvas host must have explicit size — Excalidraw measures its parent
       and collapses to 0px without it. flex:1 fills the modal below the header. */
    .excalidraw-canvas-host {
      flex: 1 1 auto;
      min-height: 0;
      position: relative;
      display: flex;
      align-items: center;
      justify-content: center;
      color: var(--c-ink-400);
      font-size: 0.85rem;
    }
    /* Excalidraw mounts its own .excalidraw container — fill the host. */
    .excalidraw-canvas-host .excalidraw {
      width: 100%;
      height: 100%;
    }

    @media (max-width: 768px) {
      body { padding: 0.75rem 1rem 1rem; }
      .header h1 { font-size: 1.2rem; }
      .table-wrapper { max-height: calc(100vh - 8rem); }
    }

    /* ── Print / "↓ PDF" notes export ──────────────────────────────────────
       exportNotesPdf() adds body.tt-printing then calls window.print(). Scoped
       to that class so a normal Ctrl+P is unaffected. Shows ONLY the notes boxes,
       expanded to full content; the browser renders text + images + diagrams
       (incl. SVG foreignObject) natively — which is why this captures diagrams
       that the html2canvas PNG export can't. */
    @media print {
      body.tt-printing { padding: 0 !important; background: var(--c-white) !important; }
      body.tt-printing .header,
      body.tt-printing .sidebar,
      body.tt-printing .subtabs,
      body.tt-printing .category-tabs,
      body.tt-printing #parentTaskTabs,
      body.tt-printing #notesToolbar,
      body.tt-printing #tableView,
      body.tt-printing #adminBanner,
      body.tt-printing .toast,
      body.tt-printing .notes-box-actions { display: none !important; }
      body.tt-printing .content-row { display: block !important; }
      body.tt-printing #notesBoxes { display: block !important; gap: 0 !important; }
      body.tt-printing .notes-box {
        border: none !important; box-shadow: none !important; margin: 0 0 0.75rem !important;
      }
      body.tt-printing .notes-editor {
        height: auto !important; min-height: 0 !important; overflow: visible !important;
        padding: 0 !important;
      }
      /* Tables in print: browsers drop cell backgrounds (so the grey header
         fill vanishes and the header looks like a plain row). Borders DO print,
         so give the header a solid bottom separator and darken the faint cell
         borders; also force the header fill where the engine honors it. */
      body.tt-printing .notes-editor .md-table { border-collapse: collapse !important; }
      body.tt-printing .notes-editor .md-table th,
      body.tt-printing .notes-editor .md-table td {
        border: 1px solid var(--c-ink-400) !important;
      }
      body.tt-printing .notes-editor .md-table thead th {
        border-bottom: 2px solid var(--c-ink-600) !important;
        background: var(--c-fill-150) !important;
        font-weight: 700 !important;
        -webkit-print-color-adjust: exact !important;
        print-color-adjust: exact !important;
      }
      body.tt-printing .notes-editor .md-col-resize { display: none !important; }
    }

/* == Roadmap (section "Roadmap" sub-tab + per-chapter roadmap band) ======== */
    /* The always-visible section "Roadmap" sub-tab reuses the notes-view container
       but hides the notes chrome (toolbar + boxes) so only the roadmap band shows.
       tt-roadmap-tab is set by showRoadmapView / renderNotesRoadmap (state-derived). */
    body.tt-roadmap-tab #notesToolbar,
    body.tt-roadmap-tab #notesBoxes { display: none !important; }
    /* Empty state for an aggregate roadmap that has no cards yet. */
    .nr-empty { padding: 28px 18px; color: var(--c-ink-500); font-size: 13.5px; text-align: center; }

    .notes-roadmap { --tl-accent: var(--c-ink-700); --tl-now: var(--c-amber); --tl-next: var(--c-ink-450); --tl-later: var(--c-ink-450); --tl-done: var(--c-green); --tl-blocked: var(--c-red-500); --tl-line: var(--c-line-100); --tl-line-strong: var(--c-line-200); --tl-now-tint: var(--c-cream); --tl-ink: var(--c-ink-800); --tl-ink-muted: var(--c-ink-500); --tl-ink-faint: var(--c-ink-400); --tl-ink-300: var(--c-ink-300); --tl-card-line: var(--c-line-050); }
    /* His roadmap panel: a white 14px card with a soft far shadow; the head row holds the controls right-aligned. */
    .nr-head { display: flex; align-items: center; gap: 12px; margin: 0 0 10px; min-height: 28px; }
    .nr-tools { display: flex; align-items: center; gap: 8px; margin-left: auto; flex-wrap: wrap; }
    .tl-caption { max-width: 760px; margin: 4px 0 14px; color: var(--tl-ink-muted); font-size: 13.5px; line-height: 1.5; }
    .tl-caption b { color: var(--tl-ink); font-weight: 600; }
    .tl-empty { margin: 4px 0 16px; padding: 14px 16px; border: 1px dashed var(--tl-line-strong); border-radius: 6px; color: var(--tl-ink-muted); font-size: 14px; background: var(--c-fill-300); }
    .tl-empty b { color: var(--tl-accent); }

    .tl-scroll { overflow-x: auto; padding: 0 0 14px; background: var(--c-white); border: 1px solid var(--c-line-050); border-radius: 14px; box-shadow: inset 0 1px 0 rgba(255,255,255,.85), 0 1px 2px rgba(11,26,20,.05), 0 18px 40px -30px rgba(11,26,20,.28); }   /* the white panel is the timeline alone */
    .tl-timeline { position: relative; min-width: 940px; --tl-fcols: 0.25; }
    .tl-lane-head { width: 170px; flex: none; padding-right: 14px; box-sizing: border-box; }

    .tl-axis-row { display: flex; align-items: stretch; margin: 0; border-bottom: 1px solid rgba(11,26,20,.07); }
    .tl-axis-corner { display: flex; align-items: center; justify-content: center; gap: 4px; padding: 0 12px; font-family: var(--font-display); font-size: 10.5px; font-weight: 500; letter-spacing: 0; text-transform: none; color: var(--c-ink-500); border-right: 1px solid var(--c-line-050); background: var(--c-fill-050); }
    .tl-axis-track { position: relative; flex: 1; display: flex; }
    .tl-zhead { flex: 1; position: relative; display: flex; flex-direction: column; justify-content: center; gap: 3px; padding: 8px 12px; min-height: 48px; min-width: 0; border-left: 1px solid var(--c-line-050); }
    .tl-zhead .h { font-family: var(--font-display); font-size: 11px; font-weight: 500; display: flex; align-items: center; gap: 6px; min-height: 22px; color: var(--c-ink-800); }
    .tl-zhead .sub { font-family: var(--font-display); font-size: 10px; font-weight: 400; letter-spacing: 0; text-transform: none; color: var(--c-ink-450); margin-top: 6px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
    .tl-zhead .chip { width: 9px; height: 9px; border-radius: 2px; flex: none; background: var(--tl-later); }
    .tl-zhead.past .chip { background: var(--tl-done); }
    .tl-zhead.now .chip { background: var(--tl-now); }
    .tl-zhead.future .chip { background: var(--tl-next); }

    .tl-lane-row { display: flex; align-items: stretch; min-height: 68px; border-top: 1px solid rgba(11,26,20,.07); border-bottom: 1px solid var(--c-line-050); }
    .tl-lane-row:first-child { border-top: 0; }
    .tl-lane-head { display: flex; flex-direction: column; justify-content: center; padding: 10px 12px; border-right: 1px solid var(--c-line-050); position: sticky; left: 0; z-index: 5; background: var(--c-white); }
    .tl-lane-head .n { font-family: var(--font-display); font-size: 13px; font-weight: 500; letter-spacing: -.012em; color: var(--c-ink-900); cursor: text; }
    .tl-lane-head .n:hover { color: var(--tl-accent); }
    .tl-lane-head .s { font-size: 11.5px; color: var(--tl-ink-faint); margin-top: 2px; }
    .tl-lane-del { position: absolute; top: 4px; right: 12px; color: var(--tl-ink-300); font-size: 12px; cursor: pointer; opacity: 0; transition: opacity .12s; }
    .tl-lane-head:hover .tl-lane-del { opacity: 1; }
    .tl-lane-del:hover { color: var(--tl-blocked); }

    .tl-track { position: relative; flex: 1; display: flex; padding: 10px 0; transition: background .12s; border-radius: 8px; }
    .tl-lane-row:hover .tl-track { background: var(--c-fill-050); }
    .tl-lane-row:hover .tl-lane-head { background: var(--c-fill-050); }
    .tl-track::before { content: ""; position: absolute; top: 50%; left: 0; width: calc(var(--tl-fcols) * 100%); height: 2px; background: var(--tl-line-strong); transform: translateY(-50%); }
    .tl-track::after { content: ""; position: absolute; top: 50%; left: calc(var(--tl-fcols) * 100%); right: 0; height: 0; border-top: 2px dashed var(--tl-line-strong); transform: translateY(-50%); }
    .tl-zone { flex: 1; display: flex; flex-direction: column; justify-content: center; gap: 6px; padding: 0 10px; min-height: 62px; position: relative; z-index: 2; min-width: 0; }
    .tl-zone.tl-drop { background: rgba(43,39,35,.08); outline: 2px dashed var(--tl-accent); outline-offset: -3px; border-radius: 6px; }
    /* Inline add: faint + button that appears on cell hover; click -> input in place. */
    /* Absolutely positioned so an always-rendered add button never adds row height
       (it is opacity:0 until hover); cells stay as tall as their card, not card + button. */
    /* pointer-events:none until revealed so the invisible (opacity:0) button never
       steals a click meant for a card; a card sits ABOVE it (z-index below), so where
       the button overlaps a card the click always lands on the card - the "+" is only
       hittable in the empty part of a cell / a spare row. */
    .tl-cell-add { position: absolute; bottom: 4px; left: 50%; transform: translateX(-50%); width: 22px; height: 22px; line-height: 1; padding: 0; border: 1px dashed var(--tl-line-strong); border-radius: 5px; background: var(--c-white); color: var(--tl-ink-faint); font-size: 15px; cursor: pointer; opacity: 0; pointer-events: none; transition: opacity .12s, color .12s, border-color .12s; z-index: 5; }   /* above .tl-card (z 4): a cell whose card fills the row must still offer "add another" (Rishabh 2026-09-14) */
    .tl-zone:hover .tl-cell-add { opacity: 1; pointer-events: auto; }
    .tl-cell-add:hover { color: var(--tl-accent); border-color: var(--tl-accent); }
    /* Card above the add button so an overlap resolves to the card (see above). */
    .notes-roadmap .tl-card { z-index: 4; }
    /* R2/R3 grid mode (chapter-scope roadmap only): rows align same-row cards
       across timeframe columns; each (row,col) is a drop cell for drag-to-move/
       align. Scoped under .notes-roadmap so the standalone timeline is untouched. */
    .notes-roadmap .tl-track.tl-grid { display: grid; padding: 10px 0; column-gap: 0; row-gap: 6px; align-items: stretch; }
    .notes-roadmap .tl-track.tl-grid::before, .notes-roadmap .tl-track.tl-grid::after { content: none; }
    /* Top-align the card in its grid cell (not centered): a row band is as tall as
       its tallest card across all columns, so centering would drop shorter same-row
       cards to different heights and break horizontal alignment across timeframes.
       flex-start pins every card in a row to the band top so the row reads across. */
    .notes-roadmap .tl-cell { position: relative; display: flex; flex-direction: column; justify-content: flex-start; gap: 6px; padding: 8px; min-height: 68px; border-left: 1px solid var(--c-line-050); min-width: 0; z-index: 2; border-radius: 6px; transition: background .12s; }
    .notes-roadmap .tl-cell--collapsed { padding: 0; }
    .notes-roadmap .tl-cell.tl-drop { background: rgba(43,39,35,.08); outline: 2px dashed var(--tl-accent); outline-offset: -3px; }
    .notes-roadmap .tl-cell:hover .tl-cell-add { opacity: 1; pointer-events: auto; }
    /* R4: freeze the timeframe header WITHOUT bounding the board. The board keeps its
       full height and the PAGE scrolls (all lanes reachable); the axis row floats to
       the top of the viewport via a transform on window scroll (_nrFloatHeader) since
       pure CSS sticky can't pin to the window from inside the horizontal .tl-scroll.
       The lane heads stay sticky-left. Scoped so the standalone timeline is untouched. */
    .notes-roadmap .tl-scroll { padding-top: 0; }
    .notes-roadmap .tl-axis-row { position: relative; z-index: 6; background: var(--c-fill-050); padding-top: 16px; will-change: transform; }
    /* Fit OFF (.nr-compact): the box is capped (max-height via _nrFitScroll) and scrolls
       internally, with a plain sticky header. Fit ON (.nr-fit) keeps the default above
       (full board, page scroll) and the header floats via _nrFloatHeader. */
    .notes-roadmap .tl-scroll.nr-compact { overflow-y: auto; }
    .notes-roadmap .tl-scroll.nr-compact .tl-axis-row { position: sticky; top: 0; }
    .tl-inline-input { width: 100%; font: inherit; font-size: 12.6px; padding: 7px 9px; border: 1px solid var(--tl-accent); border-radius: 6px; box-shadow: 0 0 0 3px var(--c-fill-200); outline: none; }
    .tl-card.editing { cursor: default; }
    .tl-card-edit { display: flex; flex-direction: column; gap: 4px; width: 100%; min-width: 0; }
    .tl-card-input { width: 100%; box-sizing: border-box; font: inherit; font-size: 12.6px; font-weight: 600; padding: 3px 6px; border: 1px solid var(--tl-accent); border-radius: 4px; outline: none; }
    .tl-card-owner-input { width: 100%; box-sizing: border-box; font: inherit; font-size: 11px; color: var(--tl-ink-muted); padding: 3px 6px; border: 1px solid var(--tl-line-strong); border-radius: 4px; outline: none; }
    .tl-card-owner-input:focus { border-color: var(--tl-accent); }
    .tl-lane-input { width: 100%; font: inherit; font-size: 14px; font-weight: 700; color: var(--tl-ink); padding: 4px 6px; border: 1px solid var(--tl-accent); border-radius: 5px; box-shadow: 0 0 0 3px var(--c-fill-200); outline: none; }
    .tl-lane-head .s { cursor: text; }
    .tl-lane-head .s:hover { color: var(--tl-accent); }
    .tl-sub-add { color: var(--tl-ink-300); }
    .tl-lane-head .s:hover .tl-sub-add { color: var(--tl-accent); }
    .tl-lane-subinput { width: 100%; font: inherit; font-size: 11.5px; color: var(--tl-ink-muted); padding: 2px 5px; margin-top: 2px; border: 1px solid var(--tl-accent); border-radius: 4px; box-shadow: 0 0 0 3px var(--c-fill-200); outline: none; }

    .tl-card { position: relative; text-align: left; width: 100%; cursor: pointer; background: var(--c-fill-075); border: 0; border-radius: 8px; padding: 8px 10px 8px 12px; display: flex; flex-direction: column; justify-content: center; gap: 3px; min-height: 52px; overflow: hidden; transition: transform .12s, box-shadow .12s; }
    .tl-card::before { content: ''; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: var(--c-bar-later); }   /* the status bar - colour per status below */
    .tl-card:hover { transform: translateY(-1px); box-shadow: 0 2px 5px rgba(11,26,20,.06), 0 6px 16px -8px rgba(11,26,20,.2); }
    .tl-card.sel { border-color: var(--tl-accent); box-shadow: 0 0 0 3px var(--c-fill-200); }
    .tl-card .node { position: absolute; left: -7px; top: 50%; width: 12px; height: 12px; border-radius: 50%; transform: translateY(-50%); background: var(--tl-later); border: 2px solid var(--c-white); }
    .tl-card .node.active { background: var(--tl-now); } .tl-card .node.planned { background: var(--tl-next); }
    .tl-card .node.blocked { background: var(--tl-blocked); } .tl-card .node.done { background: var(--tl-done); }
    .tl-card.s-active { background: var(--c-blue-050); } .tl-card.s-active::before { background: var(--c-bar-now); }
    .tl-card.s-planned { background: var(--c-fill-075); } .tl-card.s-planned::before { background: var(--c-bar-later); }
    .tl-card.s-blocked { background: var(--c-red-050); } .tl-card.s-blocked::before { background: var(--c-red); }
    .tl-card.s-done { background: var(--c-green-050); } .tl-card.s-done::before { background: var(--c-bar-done); }
    .tl-card.s-done .t { color: var(--tl-ink-muted); }
    .tl-card .t { font-size: 11.5px; font-weight: 400; line-height: 1.35; letter-spacing: -.01em; color: var(--c-ink-900); }
    .tl-card .meta { display: flex; align-items: center; gap: 6px; font-size: 11px; color: var(--tl-ink-muted); font-variant-numeric: tabular-nums; }
    .tl-card-date { color: var(--tl-ink-faint); }

    @media (prefers-reduced-motion: no-preference) {
      .tl-card .node.active { animation: tlPulse 2s ease-in-out infinite; }
      @keyframes tlPulse { 0%,100% { box-shadow: 0 0 0 0 rgba(178,106,0,.5); } 50% { box-shadow: 0 0 0 5px rgba(178,106,0,0); } }
    }

    .tl-today-line { position: absolute; top: var(--tl-head-h, 22px); bottom: 0; width: 0; border-left: 1px dashed var(--c-ink-500); z-index: 4; pointer-events: none; }
    .tl-today-line::before { content: ''; position: absolute; top: 0; left: -4px; width: 8px; height: 8px; border-radius: 50%; background: var(--c-ink-700); box-shadow: 0 0 0 3px var(--c-fill-200); }
    /* Flag sits just LEFT of the line (right-aligned to it) so it never covers
       the current-period column label to its right. */
    .tl-today-flag { position: absolute; top: calc(-1 * var(--tl-head-h, 22px)); left: 0; transform: translateX(calc(-100% - 5px)); white-space: nowrap; font-size: 10px; font-weight: 700; letter-spacing: .12em; color: var(--c-white); background: var(--tl-now); padding: 3px 9px; border-radius: 5px; box-shadow: 0 2px 5px -1px rgba(217,119,6,.45); }
    .tl-now-band { position: absolute; top: var(--tl-head-h, 22px); bottom: 0; background: rgba(11,26,20,.027); z-index: 0; pointer-events: none; }   /* his faint "now" column wash */

    /* Drill panel */
    .tl-drill { margin-top: 16px; background: var(--c-white); border: 1px solid var(--tl-line); border-radius: 6px; padding: 18px 20px; min-height: 84px; }
    .tl-drill-empty { color: var(--tl-ink-faint); font-size: 14px; }
    .tl-dhead { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-bottom: 12px; }
    .tl-dtitle { font-size: 18px; font-weight: 700; letter-spacing: -.01em; color: var(--tl-ink); }
    .tl-dcrumb { font-size: 12px; color: var(--tl-ink-faint); }
    .tl-downer { font-size: 13px; color: var(--tl-ink-muted); }
    .tl-dactions { margin-left: auto; display: flex; gap: 8px; }
    .tl-danger:hover { border-color: var(--tl-blocked) !important; color: var(--tl-blocked) !important; background: var(--c-red-075) !important; }
    .tl-pill { font-size: 10px; letter-spacing: .06em; text-transform: uppercase; padding: 2px 8px; border-radius: 20px; font-weight: 600; }
    .tl-pill.active { background: var(--c-amber-050); color: var(--tl-now); }
    .tl-pill.planned { background: var(--c-fill-200); color: var(--tl-next); }
    .tl-pill.blocked { background: var(--c-red-075); color: var(--tl-blocked); }
    .tl-pill.done { background: var(--c-green-050); color: var(--tl-done); }
    .tl-tasks { list-style: none; margin: 0; padding: 0; }
    .tl-tasks li { padding: 8px 0; border-top: 1px solid var(--tl-line); font-size: 14px; color: var(--tl-ink); }
    .tl-tasks li:first-child { border-top: 0; }

    /* Editable detail panel (saves as you type/select) */
    .tl-dedit { display: flex; flex-direction: column; gap: 13px; }
    .tl-dedit-top { display: flex; gap: 10px; align-items: center; }
    .tl-dtitle-input { flex: 1; min-width: 0; font: inherit; font-size: 17px; font-weight: 700; color: var(--tl-ink); padding: 6px 8px; border: 1px solid transparent; border-radius: 6px; outline: none; }
    .tl-dtitle-input:hover { border-color: var(--tl-line); }
    .tl-dtitle-input:focus { border-color: var(--tl-accent); box-shadow: 0 0 0 3px var(--c-fill-200); }
    .tl-dgrid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; }
    .tl-dlab { display: flex; flex-direction: column; gap: 4px; font-size: 11px; font-weight: 600; letter-spacing: .04em; text-transform: uppercase; color: var(--tl-ink-faint); }
    .tl-dlab em { font-weight: 400; text-transform: none; letter-spacing: 0; }
    .tl-dlab select, .tl-dlab input, .tl-dtasks textarea { font: inherit; font-size: 13.5px; font-weight: 400; text-transform: none; letter-spacing: 0; color: var(--tl-ink); padding: 7px 9px; border: 1px solid var(--tl-line-strong); border-radius: 6px; background: var(--c-white); }
    .tl-dlab select:focus, .tl-dlab input:focus, .tl-dtasks textarea:focus { outline: 2px solid var(--tl-accent); outline-offset: -1px; border-color: var(--tl-accent); }
    .tl-dtasks textarea { resize: vertical; }
    @media (max-width: 720px) { .tl-dgrid { grid-template-columns: 1fr 1fr; } }

    /* Prompt modal (new Initiative / new Area). Appended to <body>, OUTSIDE
       .notes-roadmap, so it can't inherit the --tl-* palette scoped there —
       redeclare the vars it uses here or the border shorthands become invalid. */
    .tl-modal-overlay { --tl-line-strong: var(--c-line-200); --tl-line: var(--c-line-100); position: fixed; inset: 0; background: rgba(26,28,43,.42); z-index: 9700; display: flex; align-items: flex-start; justify-content: center; padding: 8vh 16px; }
    .tl-modal { background: var(--c-white); border-radius: 10px; box-shadow: 0 20px 60px rgba(26,28,43,.28); width: 460px; max-width: 100%; padding: 22px 24px; display: flex; flex-direction: column; gap: 14px; }
    .tl-modal-head { font-size: 17px; font-weight: 700; color: var(--c-ink-800); }
    .tl-field { display: flex; flex-direction: column; gap: 5px; font-size: 12.5px; font-weight: 600; color: var(--c-ink-500); flex: 1; }
    .tl-field em { font-weight: 400; color: var(--c-ink-400); font-style: normal; }
    .tl-field input, .tl-field select, .tl-field textarea { font: inherit; font-weight: 400; font-size: 14px; color: var(--c-ink-800); padding: 8px 10px; border: 1px solid var(--tl-line-strong); border-radius: 6px; background: var(--c-white); }
    .tl-field input:focus, .tl-field select:focus, .tl-field textarea:focus { outline: 2px solid var(--c-ink-700); outline-offset: -1px; border-color: var(--c-ink-700); }
    .tl-field textarea { resize: vertical; }
    .tl-field-row { display: flex; gap: 12px; }
    .tl-modal-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 4px; }
    .tl-modal-actions .btn-small { padding: 8px 16px; border: 1px solid var(--tl-line-strong); border-radius: 6px; background: var(--c-white); font-weight: 600; cursor: pointer; color: var(--c-ink-500); }
    .tl-modal-actions .btn-small:hover { border-color: var(--c-ink-700); color: var(--c-ink-700); }
    /* cm-ok is THE primary button of a modal action row - every dialog that has one wears it
       (showConfirmModal, showPromptModal, and the roadmap's naming dialog). It used to borrow
       .btn-add purely for the look, and that borrowing is what let the read-only sweep above
       swallow a confirm button that adds nothing. .btn-add now marks exactly one thing - a
       control that ADDS something - which is the only thing that sweep means to hide. */
    .tl-modal-actions .cm-ok { background: var(--c-ink-700); color: var(--c-white); border-color: var(--c-ink-700); }
    .tl-modal-actions .cm-ok:hover { background: var(--c-ink-900); color: var(--c-white); }
    /* Confirm-modal (showConfirmModal): a message line + a red primary for a
       destructive confirm (delete). Reuses the .tl-modal shell above. */
    .tl-modal-msg { font-size: 13.5px; line-height: 1.55; color: var(--c-ink-600); }
    .tl-modal-actions .btn-danger-modal { background: var(--c-red, #c0392b); color: var(--c-white, #fff); border-color: var(--c-red, #c0392b); }
    .tl-modal-actions .btn-danger-modal:hover { filter: brightness(0.92); }

/* == Quiet Precision look (ported from design panel A) ==================== */
    /* Header row: clean uppercase labels, no arrow line, now-column accented */
    .tl-axis-row { border-bottom: 1px solid var(--tl-line-strong); margin-bottom: 0; }
    .tl-zhead .chip { display: none; }
    .tl-zhead.past .h { color: var(--c-ink-450); }
    .tl-zhead.now .h { color: var(--tl-accent); }

    /* Cards: hairline only (drop the heavy status stripe); status is a chip */
    .tl-card { border-color: var(--tl-card-line); padding: 8px 10px 9px; gap: 5px; }
    .tl-card.sel { border-color: var(--tl-accent); box-shadow: 0 0 0 3px rgba(43,39,35,.12); }
    .tl-card-t { font-size: 11.5px; font-weight: 400; line-height: 1.35; color: var(--c-ink-900); letter-spacing: -.01em; }
    .tl-card-meta { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 10px; color: var(--c-ink-500); }
    .tl-who { display: inline-flex; align-items: center; gap: 5px; font-size: 10.5px; color: var(--c-ink-500); min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
    .tl-who-none { color: var(--c-ink-400); font-style: italic; }
    .tl-ava { flex: none; width: 14px; height: 14px; border-radius: 50%; background: rgba(31,31,31,.08); color: var(--c-ink-600); font-size: 8.5px; font-weight: 700; display: inline-flex; align-items: center; justify-content: center; }
    .tl-card-date { font-family: ui-monospace, "Cascadia Mono", Consolas, monospace; font-size: 10.5px; color: var(--tl-ink-faint); font-variant-numeric: tabular-nums; flex: none; }
    .tl-status { font-size: 9.5px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; display: inline-flex; align-items: center; gap: 5px; }
    .tl-status::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
    .tl-card.s-active .tl-status { color: var(--tl-now); }
    .tl-card.s-planned .tl-status { color: var(--tl-next); }
    .tl-card.s-blocked .tl-status { color: var(--tl-blocked); }
    .tl-card.s-done .tl-status { color: var(--tl-done); }
    .tl-card.s-done .tl-card-t { color: var(--tl-ink-muted); }

    /* Playhead + now band in ink accent */
    .tl-today-flag { background: var(--tl-accent); box-shadow: 0 2px 5px -1px rgba(43,39,35,.5); }

/* Remove the mid-lane rail + floating dot; status shows as a slim left edge */
    .tl-track::before, .tl-track::after { content: none; }
    .tl-card .node { display: none; }

/* Column separators (full-height verticals between time columns) */
    .tl-coldiv { position: absolute; top: 0; bottom: 0; width: 0; border-left: 1px solid rgba(11,26,20,.07); z-index: 1; pointer-events: none; }
    /* Date field inside the on-card editor */
    .tl-card-date-input { width: 100%; box-sizing: border-box; font: inherit; font-size: 10.5px; color: var(--tl-ink-muted); padding: 3px 6px; border: 1px solid var(--tl-line-strong); border-radius: 4px; outline: none; font-variant-numeric: tabular-nums; }
    .tl-card-date-input:focus { border-color: var(--tl-accent); }

/* Editable horizon (column) headers — Horizons grain only (data-hid present) */
    .tl-zhead[data-hid] { position: relative; }
    .tl-zhead[data-hid] .h { display: flex; align-items: center; gap: 3px; }
    .tl-hz-name { cursor: text; border-radius: 5px; padding: 1px 4px; margin: -1px -4px; }
    .tl-hz-name:hover { background: rgba(11,26,20,.06); }
    .tl-hz-sub { cursor: text; border-radius: 5px; padding: 0 3px; margin: 0 -3px; }
    .tl-hz-sub:hover { background: rgba(11,26,20,.05); }
    .tl-hz-del { margin-left: auto; cursor: pointer; color: var(--c-ink-300); font-size: 12px; line-height: 1; padding: 0 2px; opacity: 0; transition: opacity .12s, color .12s; }
    .tl-zhead[data-hid]:hover .tl-hz-del { opacity: 1; }
    .tl-hz-del:hover { color: var(--tl-blocked); }
    .tl-hz-input { width: 100%; box-sizing: border-box; font: inherit; font-size: 11px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--c-ink-600); border: 1px solid var(--tl-accent); border-radius: 4px; padding: 1px 4px; outline: none; background: var(--c-white); }
    .tl-hz-subinput { width: 100%; box-sizing: border-box; font: inherit; font-size: 10px; color: var(--tl-ink-faint); border: 1px solid var(--tl-line-strong); border-radius: 4px; padding: 1px 4px; outline: none; margin-top: 2px; }
    .tl-hz-subinput:focus { border-color: var(--tl-accent); }

/* Column-width resize handle — sits on a header's right edge; drag to widen /
   narrow the column against its neighbour (Horizons grain) */
    .tl-col-resize { position: absolute; top: 0; right: -4px; width: 9px; height: 100%; cursor: col-resize; z-index: 6; }
    .tl-col-resize::after { content: ""; position: absolute; top: 18%; bottom: 18%; left: 4px; width: 2px; border-radius: 2px; background: transparent; transition: background .12s; }
    .tl-zhead[data-hid]:hover .tl-col-resize::after { background: var(--tl-line-strong); }
    .tl-col-resize:hover::after, .tl-col-resize.is-live::after { background: var(--tl-accent); }
    /* Timeframe reorder: drag grip + left/right nudge arrows (hover-revealed, like the lane row controls) */
    .tl-hz-grip { cursor: grab; letter-spacing: -2px; color: var(--c-ink-300); font-size: 12px; line-height: 1; margin-right: 1px; opacity: 0; transition: opacity .12s, color .12s; }
    .tl-hz-grip:active { cursor: grabbing; }
    .tl-hz-grip:hover { color: var(--tl-accent); }
    .tl-zhead[data-hid]:hover .tl-hz-grip { opacity: 1; }
    .tl-hz-tools { margin-left: auto; display: inline-flex; align-items: center; gap: 1px; }
    .tl-hz-tools .tl-hz-del { margin-left: 0; }
    .tl-hz-mv { cursor: pointer; color: var(--c-ink-300); font-size: 13px; line-height: 1; padding: 0 1px; opacity: 0; transition: opacity .12s, color .12s; }
    .tl-zhead[data-hid]:hover .tl-hz-mv { opacity: 1; }
    .tl-hz-mv:hover { color: var(--tl-accent); }
    .tl-zhead.nr-hz-drop { box-shadow: inset 3px 0 0 var(--tl-accent); }
    .tl-zhead.tl-hz-unalloc .tl-hz-name { color: var(--tl-ink-faint); font-style: italic; }
    /* Shrink + wrap: header labels wrap (or ellipsis for the subtitle) instead of
       overflowing when columns get narrow, so the header never crosses its column. */
    .notes-roadmap .tl-zhead .h { min-width: 0; flex-wrap: wrap; }
    .notes-roadmap .tl-hz-name, .notes-roadmap .nr-today-pill { overflow-wrap: anywhere; min-width: 0; }
    body.tl-colresizing, body.tl-colresizing * { cursor: col-resize !important; user-select: none !important; }

/* The header separator line resolves into an arrowhead at its right end —
   the axis itself points toward the future (all grains). */
    .tl-axis-row { position: relative; }
    .tl-axis-arrow { position: absolute; right: 6px; bottom: 8px; width: 0; height: 0; border-top: 4px solid transparent; border-bottom: 4px solid transparent; border-left: 8px solid rgba(11,26,20,.07); opacity: .35; pointer-events: none; }

/* Layer-column filter toggle (opens the shared filter dropdown) */
    .tl-layer-filter { margin-left: 6px; cursor: pointer; color: var(--c-ink-300); font-size: 11px; line-height: 1; padding: 1px 4px; border-radius: 4px; transition: color .12s, background .12s; }
    .tl-layer-filter:hover { color: var(--tl-accent); background: rgba(43, 39, 35, .08); }
    .tl-layer-filter.tl-on { color: var(--tl-accent); background: rgba(43, 39, 35, .12); }

/* Collapse a column to a thin strip (kept, not deleted) — Horizons grain */
    .tl-col-collapse { margin-right: 4px; cursor: pointer; color: var(--c-ink-300); font-size: 13px; line-height: 1; padding: 0 1px; transition: color .12s; }
    .tl-col-collapse:hover { color: var(--tl-accent); }
    .tl-zhead.tl-collapsed { background: transparent; }
    .tl-zone--collapsed { background: transparent; padding: 0; min-width: 0; }
    .tl-collapsed-strip { position: absolute; top: 0; bottom: 0; display: flex; flex-direction: column; align-items: center; justify-content: flex-start; border: 0; background: rgba(11,26,20,.035); cursor: pointer; color: var(--c-ink-450); z-index: 3; padding: 10px 0 12px; overflow: hidden; transition: background .12s, color .12s; }
    .tl-collapsed-strip:hover { background: var(--c-fill-150); color: var(--tl-accent); }
    /* The label group is nudged by JS (_nrPositionCollapsedLabels) to stay centred
       in the visible slice of the strip as the page scrolls. */
    .tl-col-sticky { display: flex; flex-direction: column; align-items: center; gap: 8px; will-change: transform; }
    .tl-col-vlabel { writing-mode: vertical-rl; text-orientation: upright; font-size: 10px; font-weight: 700; letter-spacing: .5px; line-height: 1.05; text-transform: uppercase; white-space: nowrap; }
    .tl-col-chev { font-size: 13px; font-weight: 700; }

/* == Roadmap embedded in a notes epic (boxes = stations) ================== */
    /* Reuses the .tl-* board (tokens scoped above); this styles only its own
       header row + control buttons. Sits full-width above the notes boxes. */
    .notes-roadmap { margin: 0 0 1rem; }
    .notes-roadmap .nr-head { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin: 0 2px 8px; }
    .notes-roadmap .nr-tools { margin-left: auto; display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
    /* In-progress sub-tasks listed on the station card (below the title). */
    .notes-roadmap .nr-card-tasks { list-style: none; margin: 5px 0 0; padding: 0; display: flex; flex-direction: column; gap: 2px; min-width: 0; }
    .notes-roadmap .nr-card-tasks li { position: relative; padding-left: 12px; font-size: 11px; line-height: 1.3; color: var(--tl-ink-muted); overflow-wrap: anywhere; }
    /* Keep card contents inside the card: shrink to the cell and break long
       unbreakable tokens (URLs, slugs) instead of overflowing into the next column. */
    .notes-roadmap .tl-card { min-width: 0; }
    .notes-roadmap .tl-card-t { overflow-wrap: anywhere; }
    .notes-roadmap .nr-card-tasks li::before { content: '‣'; position: absolute; left: 2px; color: var(--tl-ink-faint); }
    .notes-roadmap .nr-card-tasks li.nr-task-gap { padding-left: 0; height: .35em; }
    .notes-roadmap .nr-card-tasks li.nr-task-gap::before { content: none; }
    /* Lane (category) dropdown in the inline card editor */
    .notes-roadmap .tl-card-lane-input { width: 100%; box-sizing: border-box; font: inherit; font-size: 11px; color: var(--tl-ink-muted); padding: 3px 6px; border: 1px solid var(--tl-line-strong); border-radius: 4px; outline: none; background: var(--c-white); }
    .notes-roadmap .tl-card-lane-input:focus { border-color: var(--tl-accent); }
    /* Done checkbox in the inline card editor */
    .notes-roadmap .nr-done-lab { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; color: var(--tl-ink-muted); cursor: pointer; }
    .notes-roadmap .nr-done-lab input { margin: 0; cursor: pointer; }
    /* Milestone rows in the card editor: Start / Blocked / End, each with its date. */
    .notes-roadmap .nr-ms { display: flex; flex-direction: column; gap: 4px; }
    /* Wrap so a date input never crops in a narrow column: when the label + a full
       date field (value + calendar picker) don't fit on one line, the input drops to
       its own line at full width. Wide cards keep label + field inline. */
    .notes-roadmap .nr-ms-row { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
    .notes-roadmap .nr-ms-lab, .notes-roadmap .nr-ms-check { flex: 0 0 62px; display: inline-flex; align-items: center; gap: 5px; font-size: 11px; color: var(--tl-ink-muted); cursor: default; }
    .notes-roadmap .nr-ms-check { cursor: pointer; }
    .notes-roadmap .nr-ms-check input { margin: 0; cursor: pointer; }
    .notes-roadmap .nr-ms-row .tl-card-date-input { flex: 1 1 128px; min-width: 0; }
    .notes-roadmap .nr-ms-row .tl-card-date-input:disabled { opacity: 0.45; cursor: not-allowed; }
    /* Editing card pops out to a usable width so the date rows never overflow a
       narrow grid column; sits above neighbouring cards while open. */
    /* Editing card stays INSIDE its column (shrink + wrap model): no fixed min-width
       and no overflow, so it never spills into the next timeframe and its textarea
       resize grip stays clickable. Widen the column (drag its edge) if it feels cramped. */
    .notes-roadmap .tl-card.editing { border-color: var(--tl-accent); box-shadow: 0 2px 8px -2px rgba(26,28,43,.14); }
    /* +column / Remove buttons inside the inline card editor */
    .notes-roadmap .nr-card-editbtns { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 1px; }
    .notes-roadmap .nr-mini { max-width: 100%; }
    .notes-roadmap .nr-mini { font: inherit; font-size: 10.5px; padding: 3px 7px; border: 1px solid var(--tl-line-strong); border-radius: 4px; background: var(--c-white); color: var(--tl-ink-muted); cursor: pointer; }
    .notes-roadmap .nr-mini:hover { border-color: var(--tl-accent); color: var(--tl-accent); }
    .notes-roadmap .nr-mini-danger:hover { border-color: var(--tl-blocked); color: var(--tl-blocked); }
    /* ── Stage-duration bar (shown inside an opened station's editor, below the buttons):
       a compact real-calendar mini-gantt of the entry's lifecycle. Scoped under
       .notes-roadmap; narrow editor -> it scrolls horizontally rather than breaking. */
    .notes-roadmap .nr-life { margin-top: 8px; padding-top: 8px; border-top: 1px dashed var(--tl-line-strong); font-size: 10px; overflow-x: auto; }
    .notes-roadmap .nr-life-empty { color: var(--tl-ink-muted); font-size: 10.5px; line-height: 1.4; padding: 2px 0; }
    .notes-roadmap .nr-life-caps { position: relative; height: 13px; min-width: 220px; }
    .notes-roadmap .nr-life-caps span { position: absolute; transform: translateX(-50%); white-space: nowrap; font-weight: 700; color: var(--tl-ink-muted); font-size: 9px; }
    .notes-roadmap .nr-life-track { position: relative; height: 16px; border-radius: 5px; background: var(--c-fill-100); border: 1px solid var(--tl-line); min-width: 220px; }
    .notes-roadmap .nr-life-seg { position: absolute; top: 2px; bottom: 2px; border-radius: 3px; }
    .notes-roadmap .nr-life-seg.wait { background: var(--c-amber-050); border: 1px solid var(--tl-now); }
    .notes-roadmap .nr-life-seg.work { background: var(--tl-accent); }
    .notes-roadmap .nr-life-ov { position: absolute; top: 2px; bottom: 2px; background: var(--tl-blocked); opacity: .8; border-radius: 3px; }
    .notes-roadmap .nr-life-mark { position: absolute; top: -3px; height: calc(100% + 6px); width: 0; transform: translateX(-1px); }
    .notes-roadmap .nr-life-mark.plan { border-left: 1.5px dashed var(--tl-ink-faint); }
    .notes-roadmap .nr-life-mark.target { border-left: 1.5px dashed var(--tl-blocked); }
    .notes-roadmap .nr-life-slips { position: relative; height: 12px; margin-top: 3px; min-width: 220px; }
    .notes-roadmap .nr-life-slips span { position: absolute; transform: translateX(-50%); white-space: nowrap; font-size: 9px; font-weight: 700; }
    .notes-roadmap .nr-life-slips .late { color: var(--tl-blocked); }
    .notes-roadmap .nr-life-slips .ok { color: var(--tl-done); }
    .notes-roadmap .nr-life-slips .neu { color: var(--tl-ink-muted); }
    .notes-roadmap .nr-life-axis { position: relative; height: 26px; margin-top: 2px; min-width: 220px; }
    .notes-roadmap .nr-life-axis span { position: absolute; transform: translateX(-50%); text-align: center; white-space: nowrap; }
    .notes-roadmap .nr-life-axis span i { display: block; font-style: normal; font-size: 8px; letter-spacing: .03em; text-transform: uppercase; color: var(--tl-ink-faint); }
    .notes-roadmap .nr-life-axis span b { display: block; font-size: 9.5px; color: var(--tl-ink); font-weight: 600; }
    .notes-roadmap .nr-life-axis span:first-child { transform: translateX(0); text-align: left; }
    .notes-roadmap .nr-life-axis span:last-child { transform: translateX(-100%); text-align: right; }
    .notes-roadmap .nr-life-note { display: flex; align-items: center; gap: 6px; margin-top: 6px; color: var(--tl-ink-muted); font-size: 9.5px; line-height: 1.4; }
    .notes-roadmap .nr-life-note b { color: var(--tl-now); font-weight: 700; }
    .notes-roadmap .nr-life-dot { flex: none; width: 7px; height: 7px; border-radius: 50%; background: var(--tl-now); }
    .notes-roadmap .nr-life-dot.muted { background: var(--tl-ink-faint); }
    /* Drop-onto-a-card target (reorder within / across columns). */
    .notes-roadmap .tl-card.nr-drop-target { outline: 2px dashed var(--tl-accent); outline-offset: -2px; }
    /* Row (initiative) controls — move up/down + delete, on hover of the row head */
    .notes-roadmap .nr-lane-ctrls { position: absolute; top: 4px; right: 10px; display: flex; gap: 8px; opacity: 0; transition: opacity .12s; z-index: 6; }
    .notes-roadmap .tl-lane-head:hover .nr-lane-ctrls { opacity: 1; }
    .notes-roadmap .nr-lane-ctrls span { cursor: pointer; color: var(--c-ink-300); font-size: 12px; line-height: 1; }
    .notes-roadmap .nr-lane-ctrls span:hover { color: var(--tl-accent); }
    .notes-roadmap .nr-lane-ctrls .nr-lane-x:hover { color: var(--tl-blocked); }
    .notes-roadmap .nr-lane-grip { cursor: grab; letter-spacing: -2px; }
    .notes-roadmap .nr-lane-grip:active { cursor: grabbing; }
    /* Row being dragged over as a reorder target */
    .notes-roadmap .tl-lane-head.nr-lane-drop { outline: 2px dashed var(--tl-accent); outline-offset: -3px; border-radius: 6px; }
    .notes-roadmap .btn-small.nr-filter-on { border-color: var(--tl-accent); color: var(--tl-accent); background: rgba(43, 39, 35, .08); }
    /* Aggregated (subject / all) scope: cards are a read-only view, not editable. */
    .notes-roadmap .tl-card.nr-card-ro { cursor: pointer; }
    /* Multi-select (aggregated): hover checkbox on each card, selected outline, + a top bar. */
    .notes-roadmap .nr-card-check { position: absolute; top: 5px; right: 5px; width: 15px; height: 15px; box-sizing: border-box; border: 1.5px solid var(--tl-line-strong); border-radius: 4px; background: var(--c-white); cursor: pointer; opacity: 0; transition: opacity .12s, background .12s, border-color .12s; z-index: 4; }
    .notes-roadmap .tl-card:hover .nr-card-check { opacity: 1; }
    .notes-roadmap .nr-card-check:hover { border-color: var(--tl-accent); }
    .notes-roadmap .nr-card-check.on { opacity: 1; background: var(--tl-accent); border-color: var(--tl-accent); }
    .notes-roadmap .nr-card-check.on::after { content: '✓'; position: absolute; inset: 0; color: var(--c-white); font-size: 11px; line-height: 13px; text-align: center; }
    .notes-roadmap .tl-card.nr-card-sel { border-color: var(--tl-accent); box-shadow: 0 0 0 2px var(--c-fill-200); }
    .notes-roadmap .nr-selbar { display: flex; align-items: center; gap: 10px; margin: 0 2px 8px; padding: 6px 12px; background: var(--c-fill-200); border: 1px solid var(--tl-accent); border-radius: 8px; font-size: 0.8rem; font-weight: 600; color: var(--tl-ink); }
    .notes-roadmap .nr-selbar-clear { font: inherit; font-size: 0.72rem; padding: 3px 9px; border: 1px solid var(--tl-line-strong); border-radius: 5px; background: var(--c-white); color: var(--tl-ink-muted); cursor: pointer; }
    .notes-roadmap .nr-selbar-clear:hover { border-color: var(--tl-accent); color: var(--tl-accent); }
    /* Shown briefly on first roadmap open while the shared timeframe columns load. */
    .notes-roadmap .nr-loading { padding: 24px 12px; font-size: 0.8rem; color: var(--tl-ink-muted); }
    /* Add-Initiative / add-Area affordance rows in the aggregated (group-by-Area) board. */
    .notes-roadmap .nr-add-row { min-height: 30px; }
    .notes-roadmap .nr-add-row .tl-track { border: 0; }
    /* Center the "+" horizontally in its head (like the station "+" in its cell). */
    .notes-roadmap .nr-add-row .tl-lane-head { align-items: center; padding-right: 0; }
    /* Add Initiative / Add Area use the SAME affordance as the station "+" (.tl-cell-add):
       a small dashed square, hidden until its row is hovered, turning accent on hover. */
    .notes-roadmap .nr-add-lane { width: 22px; height: 22px; line-height: 1; padding: 0; margin: 3px 0; display: inline-flex; align-items: center; justify-content: center; border: 1px dashed var(--tl-line-strong); border-radius: 5px; background: var(--c-white); color: var(--tl-ink-faint); font-size: 15px; font-weight: 400; cursor: pointer; opacity: 0; pointer-events: none; transition: opacity .12s, color .12s, border-color .12s; }
    .notes-roadmap .nr-add-row:hover .nr-add-lane, .notes-roadmap .tl-lane-row.nr-grp-cont:hover .nr-add-lane { opacity: 1; pointer-events: auto; }
    .notes-roadmap .nr-add-lane:hover { color: var(--tl-accent); border-color: var(--tl-accent); }
    .notes-roadmap .tl-timeline.nr-agg .tl-lane-head .n { cursor: text; }
    /* Group-by-Subject: a SEPARATE Subject column before the Chapter column.
       Width is set inline (matches the geometry offset). Subject label shows once
       per group (a visual span); later rows in the group leave it blank. */
    .notes-roadmap .nr-subj-col { flex: none; box-sizing: border-box; padding: 6px 10px; display: flex; align-items: flex-start; gap: 4px; border-right: 1px solid var(--tl-line); font-size: 12px; font-weight: 700; color: var(--tl-ink); position: relative; overflow: visible; }
    /* The subject label is absolutely positioned and centred across ALL its chapters
       by JS (sets `top` to the group centre, once). It then scrolls naturally with
       the board — smooth. Self-clips horizontally. */
    .notes-roadmap .nr-subj-col .n { position: absolute; top: 0; left: 10px; right: 10px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; will-change: transform; }
    .notes-roadmap .nr-subj-head { align-items: center; justify-content: center; padding: 0 12px; font-family: var(--font-display); font-size: 10.5px; letter-spacing: 0; text-transform: none; color: var(--c-ink-500); font-weight: 500; }   /* the Domain head = the Topic head's pattern, centred in the head row (his build) */
    /* Chapter corner in aggregated views: lay out «  + label in a ROW, bottom-aligned,
       matching the Subject corner and the timeframe headers (the base .tl-lane-head is
       a column, which stacked the « above the label). */
    .notes-roadmap .tl-axis-corner.nr-chap-head { flex-direction: row; align-items: center; justify-content: center; gap: 4px; padding: 0 12px; }   /* centred like his build; the lane-head's 10px top padding does not apply to the head row */
    /* Collapse control (« ) on a label-column header. */
    .notes-roadmap .nr-col-collapse { cursor: pointer; color: var(--c-ink-300); font-size: 12px; line-height: 1; padding: 0 3px; transition: color .12s; }
    .notes-roadmap .nr-col-collapse:hover { color: var(--tl-accent); }
    /* A collapsed label column (Subject / Chapter) → a thin strip, like a collapsed
       timeframe column: the vertical name + » live in the corner; per-row cells are
       thin empty strips. Click anywhere to expand. */
    .notes-roadmap .nr-col-collapsed { flex: none; box-sizing: border-box; position: relative; cursor: pointer; background: var(--c-fill-200); color: var(--tl-ink-muted); border-right: 1px solid var(--tl-line); overflow: visible; }
    /* In the header row the collapsed cell has no flow content (its label is
       absolute), so stretch it to the header height — otherwise it shrinks to a
       tiny box at the top. z-index lifts the floated vertical label above the
       per-row lane cells (which come later in the DOM and would otherwise paint
       over it, hiding the Subject / Chapter title). */
    .notes-roadmap .tl-axis-row .nr-col-collapsed { align-self: stretch; z-index: 6; }
    .notes-roadmap .nr-col-collapsed:hover { background: var(--c-fill-150); color: var(--tl-accent); }
    /* The collapsed column's label is centred in the column (matching a collapsed
       timeframe strip) by JS, then scrolls naturally. */
    .notes-roadmap .nr-col-collapsed .nr-col-sticky { position: absolute; top: 0; left: 0; right: 0; display: flex; flex-direction: column; align-items: center; gap: 8px; will-change: transform; }
    .notes-roadmap .nr-col-collapsed .tl-col-chev { font-size: 13px; font-weight: 700; }
    .notes-roadmap .nr-col-vlabel { writing-mode: vertical-rl; text-orientation: upright; font-size: 10px; font-weight: 700; letter-spacing: .5px; line-height: 1.05; text-transform: uppercase; white-space: nowrap; }
    /* Nested (group-by-Subject): same-subject chapters are contiguous. Chapters
       DIFFER → a divider sits on the CHAPTER + track columns. Subject is the SAME
       → its column stays continuous (one merged cell, label shown once). A NEW
       subject starts a fresh block: gap + a strong border across all columns. */
    .notes-roadmap .tl-lane-row.nr-grp-start,
    .notes-roadmap .tl-lane-row.nr-grp-cont { border: 0; margin-top: 0; }
    .notes-roadmap .tl-lane-row.nr-grp-start { margin-top: 16px; }
    .notes-roadmap .tl-lanes .tl-lane-row.nr-grp-start:first-child { margin-top: 0; }
    .notes-roadmap .tl-lane-row.nr-grp-cont .tl-lane-head,
    .notes-roadmap .tl-lane-row.nr-grp-cont .tl-track { border-top: 1px solid var(--tl-line-strong); }
    .notes-roadmap .tl-lane-row.nr-grp-start .nr-subj-col,
    .notes-roadmap .tl-lane-row.nr-grp-start .tl-lane-head,
    .notes-roadmap .tl-lane-row.nr-grp-start .tl-track { border-top: 2px solid var(--tl-line-strong); }

    /* Raw-data table — read-only flat view of the schedule entries the board is built from. */
    .notes-roadmap .nr-data { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--c-line-200); }
    .notes-roadmap .nr-data-head { font-size: 0.82rem; font-weight: 700; color: var(--c-ink-700); margin-bottom: 9px; display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
    .notes-roadmap .nr-data-sub { font-size: 0.72rem; font-weight: 400; color: var(--c-ink-300); }
    .notes-roadmap .nr-data-scroll { overflow-x: auto; border: 1px solid var(--c-line-200); border-radius: 8px; }
    .notes-roadmap .nr-data-table { border-collapse: collapse; width: 100%; font-size: 0.78rem; background: var(--c-white); }
    .notes-roadmap .nr-data-table th { text-align: left; font-weight: 600; color: var(--c-ink-500); background: var(--c-fill-100); padding: 7px 12px; border-bottom: 1px solid var(--c-line-200); white-space: nowrap; }
    .notes-roadmap .nr-data-table td { padding: 7px 12px; border-bottom: 1px solid var(--c-line-100); color: var(--c-ink-700); vertical-align: top; }
    .notes-roadmap .nr-data-table tbody tr:last-child td { border-bottom: none; }
    .notes-roadmap .nr-data-table tbody tr:hover { background: var(--c-fill-100); }
    .notes-roadmap .nr-dt-date { white-space: nowrap; font-variant-numeric: tabular-nums; color: var(--c-ink-500); }
    .notes-roadmap .nr-dt-empty { color: var(--c-ink-300); }
    .notes-roadmap .nr-dt-tasks { margin: 0; padding-left: 15px; }
    .notes-roadmap .nr-dt-tasks li { margin: 1px 0; }
    .notes-roadmap .nr-dt-status { display: inline-block; padding: 1px 9px; border-radius: 10px; font-size: 0.7rem; font-weight: 600; border: 1px solid currentColor; white-space: nowrap; }
    .notes-roadmap .nr-dt-status--done { color: var(--tl-done); }
    .notes-roadmap .nr-dt-status--active { color: var(--tl-now); }
    .notes-roadmap .nr-dt-status--blocked { color: var(--tl-blocked); }
    .notes-roadmap .nr-dt-status--planned { color: var(--tl-next); }
    .notes-roadmap .nr-dt-status--backlog { color: var(--c-ink-300); }
    /* Single-lane board: no top border joint needed, a touch more room per card. */
    .notes-roadmap .tl-timeline { min-width: 820px; }
    /* The current-period column header IS the today marker (black pill, mirrors the
       standalone flag). The floating "TODAY →" flag is dropped so there's only one. */
    .notes-roadmap .nr-today-pill { display: inline-flex; align-items: center; gap: 5px; font-family: var(--font-display); font-size: 10px; font-weight: 500; letter-spacing: 0; text-transform: none; color: var(--c-white); background: var(--c-ink-900); padding: 2px 9px 2px 8px; border-radius: 999px; box-shadow: none; }
    .notes-roadmap .nr-today-pill::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: var(--c-bar-now); flex: none; }   /* the Now dot = the Now cards' blue (Rishabh 2026-09-14: bright, like his, in the cards' colour) */
    /* Sub-tasks textarea in the inline card editor (the standalone card editor has
       title/owner/date; the notes roadmap adds the "currently working on" list). */
    .notes-roadmap .tl-card-tasks-input { width: 100%; box-sizing: border-box; font: inherit; font-size: 11px; color: var(--tl-ink-muted); padding: 4px 6px; border: 1px solid var(--tl-line-strong); border-radius: 4px; outline: none; resize: vertical; min-height: 3.4em; }
    .notes-roadmap .tl-card-tasks-input:focus { border-color: var(--tl-accent); }

    /* look&feel: tabular figures */
    #taskTable { font-variant-numeric: tabular-nums; }
