/* ============================================================
   NOVA — the Nova design system stylesheet (spec:
   docs/superpowers/specs/2026-08-18-nova-app-restyle-design.md)
   Layers: fonts → primitives → semantic tokens → components → pages.
   Values come from design/tokens/tokens.json; renders in
   design/components/img/ are the visual contract.
   ============================================================ */

/* ---- 1 · Fonts (self-hosted; PP faces slot in when licensed,
        see static/fonts/README.md) ---- */
@font-face { font-family: "Inter"; src: url("/static/fonts/inter-400.woff2") format("woff2"); font-weight: 400; font-display: swap; }
@font-face { font-family: "Inter"; src: url("/static/fonts/inter-500.woff2") format("woff2"); font-weight: 500; font-display: swap; }
@font-face { font-family: "Roboto Mono"; src: url("/static/fonts/roboto-mono-400.woff2") format("woff2"); font-weight: 400; font-display: swap; }
@font-face { font-family: "Roboto Mono"; src: url("/static/fonts/roboto-mono-500.woff2") format("woff2"); font-weight: 500; font-display: swap; }
/* When PP webfont licenses land, add the pp/ @font-face blocks here. */

:root {
    color-scheme: dark;

    /* ---- 2 · Primitives ---- */
    --gray-100:#F5F5F5; --gray-200:#EBEBEB; --gray-300:#E0E0E0; --gray-400:#B8B8B8;
    --gray-500:#8F8F8F; --gray-600:#7A7A7A; --gray-700:#525252; --gray-800:#292929;
    --gray-900:#1F1F1F; --gray-1000:#141414;
    --white-0:#FFFFFF00; --white-4:#FFFFFF0A; --white-8:#FFFFFF14; --white-16:#FFFFFF29;
    --white-24:#FFFFFF3D; --white-36:#FFFFFF5C; --white-100:#FFFFFF;
    --black-0:#00000000; --black-4:#0000000A; --black-8:#00000014; --black-16:#00000029;
    --black-24:#0000003D; --black-36:#0000005C; --black-80:#000000CC; --black-100:#000000;
    --brand-200:#DDEF6C; --brand-300:#D1E935; --brand-400:#B2CA16;
    --lava-200:#EF6C6C; --lava-300:#E93535; --lava-400:#CA1616;
    --mint-200:#79E2A3; --mint-300:#47D780; --mint-400:#28B862;
    --amber-200:#FCC85F; --amber-300:#FBB323; --amber-400:#DC9404;
    /* Not in design/tokens/tokens.json — the frames use this blue for the info
       status (ACQUIRED marks, the licensee-interest bar) and the palette has no
       name for it. Sampled off the v9 exports; ramp direction matches the other
       status families (-400 saturated for dark, -200 light for light). Open item
       1 in design/context/design-questions.md — replace when the team adds one. */
    --info-200:#5FB3FC; --info-400:#0477DC;

    --spacing-0:0; --spacing-4:4px; --spacing-8:8px; --spacing-12:12px; --spacing-16:16px;
    --spacing-24:24px; --spacing-32:32px; --spacing-40:40px; --spacing-48:48px;
    --spacing-60:60px; --spacing-72:72px; --spacing-84:84px; --spacing-96:96px;
    --radius-0:0; --radius-2:2px; --radius-4:4px; --radius-8:8px; --radius-999:999px;
    --stroke-1:1px; --stroke-2:2px;

    --elevation-input: 0 4px 8px 0 rgba(0,0,0,0.04);
    --elevation-menu:  0 0 2px 0 rgba(0,0,0,0.24), 0 2px 4px 0 rgba(0,0,0,0.04),
                       0 4px 8px 2px rgba(0,0,0,0.04), 0 8px 16px 4px rgba(0,0,0,0.04),
                       0 16px 32px 8px rgba(0,0,0,0.04);
    --elevation-modal: 0 2px 2px 0 rgba(0,0,0,0.24), 0 2px 4px 0 rgba(0,0,0,0.08),
                       0 4px 8px 2px rgba(0,0,0,0.08), 0 8px 16px 4px rgba(0,0,0,0.08),
                       0 16px 32px 8px rgba(0,0,0,0.08);

    --font-heading: "PP Neue Montreal", "Inter", -apple-system, "Segoe UI", sans-serif;
    --font-body:    "PP Neue Montreal", "Inter", -apple-system, "Segoe UI", sans-serif;
    --font-code:    "PP Neue Montreal Mono", "Roboto Mono", ui-monospace, monospace;

    /* ---- Motion (carried over verbatim; Figma specifies none) ---- */
    --ease-in: cubic-bezier(0.4,0,1,1); --ease-out: cubic-bezier(0,0,0.2,1);
    --ease-in-out: cubic-bezier(0.4,0,0.2,1); --ease-emphasis: cubic-bezier(0.165,0.85,0.45,1);
    --duration-100:100ms; --duration-150:150ms; --duration-200:200ms;
    --duration-300:300ms; --duration-500:500ms;
    --modal-open:250ms; --modal-close:125ms;

    /* ---- 3 · Semantic tokens — DARK (default) ---- */
    --bg-subtle:var(--black-100);        --bg-subtle-hover:var(--gray-1000);   --bg-subtle-press:var(--gray-900);
    --bg-base:var(--gray-1000);          --bg-base-hover:var(--gray-900);      --bg-base-press:var(--gray-800);
    --bg-component:var(--gray-900);      --bg-component-hover:var(--gray-800); --bg-component-press:var(--gray-700);
    --bg-field:var(--gray-800);          --bg-field-hover:var(--gray-900);     --bg-field-press:var(--gray-1000);
    --bg-button:var(--brand-200);        --bg-button-hover:var(--brand-300);   --bg-button-press:var(--brand-400);
    --bg-button-danger:var(--lava-200);  --bg-button-danger-hover:var(--lava-300); --bg-button-danger-press:var(--lava-400);
    --bg-button-transparent:var(--white-0); --bg-button-transparent-hover:var(--white-4); --bg-button-transparent-press:var(--white-8);
    --bg-tag:var(--brand-200);           --bg-tag-hover:var(--brand-300);      --bg-tag-press:var(--brand-400);
    --bg-disable:var(--gray-900);        --bg-overlay:var(--black-80);

    --fg-subtle:var(--white-100);        --fg-subtle-hover:var(--gray-100);    --fg-subtle-press:var(--gray-200);
    --fg-base:var(--gray-300);           --fg-base-hover:var(--gray-400);      --fg-base-press:var(--gray-500);
    --fg-muted:var(--gray-600);          --fg-muted-hover:var(--gray-700);     --fg-muted-press:var(--gray-800);
    /* interactive = lime on dark surfaces — verified 18 Aug via Figma MCP
       get_variable_defs (dark resolves to brand-200; light resolves to gray,
       see the :root[data-theme="light"] override below) */
    --fg-interactive:var(--brand-200);   --fg-interactive-hover:var(--brand-300); --fg-interactive-press:var(--brand-400);
    /* Status foregrounds run their ramp in OPPOSITE directions per mode
       (design/tokens/tokens.json: "light uses the -200 step as default and -400 as
       press, dark the reverse"). Confirmed against both v9 exports: the stat meter
       fills sample #DC9404 (amber-400) in Dark/Results.png and #FCC85F (amber-200)
       in Light/Results.png; the LIVE / DEPLOYING strips sample #28B862 (mint-400)
       dark and #79E2A3 (mint-200) light. This block used to carry the -300 hover
       step in dark and the light column's -400 in light — both wrong. */
    --fg-danger:var(--lava-400);         --fg-success:var(--mint-400);         --fg-warning:var(--amber-400);
    --fg-info:var(--info-400);          --bg-selection:#123A5C;
    --fg-oncolor:var(--black-100);       --fg-oncolor-hover:var(--gray-1000);  --fg-oncolor-press:var(--gray-900);
    --fg-disable:var(--gray-700);

    --border-subtle:var(--white-8);      --border-subtle-hover:var(--white-16); --border-subtle-press:var(--white-24);
    --border-base:var(--white-16);       --border-base-hover:var(--white-24);   --border-base-press:var(--white-36);
    --border-active:var(--white-100);    --border-disable:var(--white-8);
}

:root[data-theme="light"] {
    color-scheme: light;
    --bg-subtle:var(--gray-100);         --bg-subtle-hover:var(--gray-200);    --bg-subtle-press:var(--gray-300);
    --bg-base:var(--white-100);          --bg-base-hover:var(--gray-100);      --bg-base-press:var(--gray-200);
    --bg-component:var(--gray-100);      --bg-component-hover:var(--gray-200); --bg-component-press:var(--gray-300);
    --bg-field:var(--white-100);         --bg-field-hover:var(--gray-100);     --bg-field-press:var(--gray-200);
    --bg-button-transparent:var(--black-0); --bg-button-transparent-hover:var(--black-4); --bg-button-transparent-press:var(--black-8);
    --bg-disable:var(--gray-200);

    --fg-subtle:var(--black-100);        --fg-subtle-hover:var(--gray-1000);   --fg-subtle-press:var(--gray-900);
    --fg-base:var(--gray-800);           --fg-base-hover:var(--gray-900);      --fg-base-press:var(--gray-1000);
    --fg-muted:var(--gray-500);          --fg-muted-hover:var(--gray-600);     --fg-muted-press:var(--gray-700);
    --fg-danger:var(--lava-200);         --fg-success:var(--mint-200);         --fg-warning:var(--amber-200);
    --fg-info:var(--info-200);          --bg-selection:#C7E4FE;
    --fg-disable:var(--gray-400);
    /* Verified 18 Aug via Figma MCP get_variable_defs: interactive text is gray on
       a white canvas in light mode (lime stays for fills/tags only); dark mode keeps
       the brand-200 lime set in :root above. */
    --fg-interactive:var(--gray-500);    --fg-interactive-hover:var(--gray-400); --fg-interactive-press:var(--gray-300);

    --border-subtle:var(--black-8);      --border-subtle-hover:var(--black-16); --border-subtle-press:var(--black-24);
    --border-base:var(--black-16);       --border-base-hover:var(--black-24);   --border-base-press:var(--black-36);
    --border-active:var(--black-100);    --border-disable:var(--black-8);
    /* NOTE: --bg-button/tag and --fg-oncolor are identical in both modes and are
       NOT overridden here. The sidebar (and the 8px gutter above the chat column)
       ride --bg-subtle: black in dark, gray-100 in light — the light v9 frames
       show a light sidebar, so nothing pins --black-100 any more. */
}

/* ---- Reset + base ---- */
*,*::before,*::after { box-sizing:border-box; margin:0; padding:0; }
html { -webkit-font-smoothing:antialiased; scrollbar-width:thin; scrollbar-color:var(--border-base) transparent; }
body { font-family:var(--font-body); font-size:14px; line-height:20px;
       background:var(--bg-base); color:var(--fg-base); min-height:100vh; }
/* Selected text follows the Claude app's: a muted blue band. It used to be a lime
   fill with black ink, which made every drag across the page the loudest thing on it
   and spent the brand accent on something that carries no meaning. Dark is the demo's
   primary mode, so the band is a low-saturation navy there and a pale tint in light;
   the ink is left alone, so selected text keeps its own colour. (Balaji, 19 Aug.) */
::selection { background:var(--bg-selection); }
/* Components below set `display`, which outranks the UA's [hidden] rule — pin it. */
[hidden] { display:none !important; }
@media (prefers-reduced-motion: reduce) {
  :root { --duration-100:0ms; --duration-150:0ms; --duration-200:0ms;
          --duration-300:0ms; --duration-500:0ms; --modal-open:0ms; --modal-close:0ms; }
}

/* ---- Type roles ---- */
.nv-h48{font:500 48px/56px var(--font-heading);color:var(--fg-subtle);}
.nv-h40{font:500 40px/48px var(--font-heading);color:var(--fg-subtle);}
.nv-h32{font:500 32px/40px var(--font-heading);color:var(--fg-subtle);}
.nv-h28{font:500 28px/36px var(--font-heading);color:var(--fg-subtle);}
.nv-h24{font:500 24px/32px var(--font-heading);color:var(--fg-subtle);}
.nv-h20{font:500 20px/28px var(--font-heading);color:var(--fg-subtle);}
.nv-body-16{font:400 16px/24px var(--font-body);} .nv-body-16-md{font:500 16px/24px var(--font-body);}
.nv-body-14{font:400 14px/20px var(--font-body);} .nv-body-14-md{font:500 14px/20px var(--font-body);}
.nv-body-12{font:400 12px/16px var(--font-body);} .nv-body-12-md{font:500 12px/16px var(--font-body);}
.nv-body-10{font:400 10px/16px var(--font-body);} .nv-body-10-md{font:500 10px/16px var(--font-body);}
.nv-code-16{font:400 16px/24px var(--font-code);} .nv-code-14{font:400 14px/20px var(--font-code);}
.nv-code-12{font:400 12px/16px var(--font-code);} .nv-code-12-md{font:500 12px/16px var(--font-code);}

/* ---- 4 · Components ---- */
/* Sidebar — BLACK in both modes (pinned, not via --bg-subtle).
   Geometry pixel-measured off design/context/incubation/v9/Dark/Default.png
   and 09-collapsed-sidebar-dark.png (both exported at the 1728×900 screen reference):
   expanded 256, collapsed rail 56, 16px gutter, brand row 40, New chat 36 @ radius-2,
   nav rows full-bleed with a square 2px lime strip, account row 60 under a dashed
   hairline. The sidebar rides --bg-subtle: black in dark, gray-100 in light —
   the light Figma frame shows a LIGHT sidebar (user-confirmed 19 Aug), so the
   earlier both-modes-black pin was wrong. All its inks/hovers are semantic. */
.nv-shell { display:flex; min-height:100vh; }
.nv-sidebar { width:256px; flex:0 0 256px; background:var(--bg-subtle);
  color:var(--fg-base); display:flex; flex-direction:column;
  padding:var(--spacing-16) var(--spacing-16) 0; gap:var(--spacing-16);
  overflow:hidden;
  transition:width var(--duration-300) var(--ease-emphasis),
             flex-basis var(--duration-300) var(--ease-emphasis); }
/* One DOM, two widths: the grid areas restack when the rail collapses. */
.nv-sidebar-top { display:grid; grid-template-columns:1fr auto;
  grid-template-areas:"brand search" "new new";
  align-items:center; row-gap:var(--spacing-16); }
.nv-sidebar-brand { grid-area:brand; display:flex; align-items:center; gap:var(--spacing-8);
  height:40px; color:var(--fg-subtle); }
.nusx-logo { height:18px; width:auto; display:block; }
.nv-sidebar-mark { display:none; height:18px; width:auto; }
/* Search glyph — right-aligned in the brand row when expanded, third in the rail
   stack when collapsed (design/components/img/sidebar-dark.png shows both).
   Non-functional affordance: no handler, no search feature in this demo. */
.nv-sidebar-search { grid-area:search; display:inline-flex; align-items:center; justify-content:center;
  width:24px; height:24px; padding:0; border:0; background:transparent; color:var(--fg-muted);
  cursor:pointer; border-radius:var(--radius-4);
  transition:background var(--duration-100) var(--ease-in-out), color var(--duration-100) var(--ease-in-out); }
.nv-sidebar-search:hover { background:var(--bg-subtle-hover); color:var(--fg-subtle); }
.nv-sidebar-search svg { width:16px; height:16px; }
.nv-newchat { grid-area:new; display:flex; align-items:center; justify-content:center;
  gap:var(--spacing-8); width:100%; height:36px; border:0; cursor:pointer;
  border-radius:var(--radius-2); background:var(--bg-button); color:var(--fg-oncolor);
  font:500 14px/20px var(--font-body);
  transition:background var(--duration-100) var(--ease-in-out); }
.nv-newchat:hover { background:var(--bg-button-hover); }
.nv-newchat:active { background:var(--bg-button-press); }
.nv-newchat svg { width:16px; height:16px; flex:none; }
/* The group is full-bleed and each row carries the 16px text inset, so the
   hover/selected band and the lime strip touch the sidebar's left border exactly
   as they do in every frame — without negative margins that would overflow the
   scroller. */
.nv-nav-group { display:flex; flex-direction:column; min-height:0; overflow-y:auto;
  margin-inline:calc(-1 * var(--spacing-16)); }
/* Sentence case, Inter 12, NOT the mono uppercase eyebrow — verified against the
   frame (cap height 9px, proportional advance widths). */
.nv-nav-label { font:400 12px/16px var(--font-body); color:var(--fg-muted);
  padding:var(--spacing-8) var(--spacing-16); }
.nv-nav-item { position:relative; display:block;
  padding:var(--spacing-8) var(--spacing-16);
  border-radius:0; text-decoration:none; color:inherit;
  transition:background var(--duration-100) var(--ease-in-out); }
.nv-nav-item:hover { background:var(--bg-subtle-hover); }
.nv-nav-item.is-selected { background:var(--bg-subtle-press); }
/* The selected strip is --fg-interactive, not raw brand: it samples #DDEF6C in
   Dark/Results.png and #8F8F8F (gray-500) at the same x 0→2 in Light/Results.png,
   which is exactly what --fg-interactive resolves to per mode. (Report/kicker
   strips are different — those stay lime in both modes, see .nv-report .nv-eyebrow.) */
.nv-nav-item.is-selected::before { content:""; position:absolute; left:0; top:0; bottom:0;
  width:var(--stroke-2); border-radius:0; background:var(--fg-interactive); }
/* Title/description sizes verified 19 Aug via Figma MCP get_variable_defs on the
   Navigation Item component's text nodes (2128:12639 / 2128:12640): title is
   body-12 (12px/16), description is body-10 (10px/16px) — an off-scale size not
   in tokens.json's 12/14/16 body ramp, but authoritative for this component.
   16(title) + 2(gap) + 16(desc) + 8+8 padding = 50px row pitch, matching the frame. */
.nv-nav-item-title { display:block; font:400 12px/16px var(--font-body); color:var(--fg-subtle); }
.nv-nav-item-desc { display:block; font:400 10px/16px var(--font-body); color:var(--fg-muted); margin-top:2px; }

/* ---- Recents hover-preview popover ----
   Geometry verified live via Figma MCP get_metadata on the Aug-14 sidebar-hover
   frame's node 2127:23837 ("Message" frame): 280px wide, 12px padding all round,
   tag then up to three label/value rows on a 40px pitch, dashed 1px hairlines
   between rows only (none before the first). Positioned by agent.js, viewport-fixed
   so the sidebar's own scroll/clip never stales or clips it. */
/* Surface is --bg-field, not --bg-component: the popover samples #292929 (gray-800)
   in Dark/Sidebar Hover.png and #FFFFFF in Light/Sidebar Hover.png — the bg-field
   pair, not bg-component's #1F1F1F / #F5F5F5. */
.nv-recent-preview { position:fixed; z-index:90; width:280px;
  background:var(--bg-field); border:var(--stroke-1) solid var(--border-subtle);
  border-radius:var(--radius-8); box-shadow:var(--elevation-menu);
  padding:var(--spacing-12); pointer-events:none;
  transition:opacity var(--duration-150) var(--ease-out); }
.nv-recent-preview[hidden] { display:none; }
.nv-recent-preview-tag.nv-tag--transparent { color:var(--fg-interactive); text-transform:uppercase; }
.nv-recent-preview-row { display:flex; align-items:flex-start; justify-content:space-between;
  gap:var(--spacing-12); padding:var(--spacing-8) 0; }
.nv-recent-preview-tag + .nv-recent-preview-row { margin-top:var(--spacing-8); }
/* --border-base: the dashes sample #4B4B4B on the dark popover and #D6D6D6 on the
   light one — both the 16 % step, not the 8 % of --border-subtle. */
.nv-recent-preview-row + .nv-recent-preview-row { border-top:var(--stroke-1) dashed var(--border-base); }
.nv-recent-preview-label { flex:0 0 auto; font:400 12px/16px var(--font-body); color:var(--fg-muted); }
/* min-width:0 + break-word: a long author list (incubation assets can carry six-plus
   inventors) must wrap inside the fixed 280px card, not overflow it — the frame's own
   "JAMES SMITH" example never had to wrap, so this is a scale-to-n extension, not a
   deviation. */
.nv-recent-preview-value { flex:1 1 auto; min-width:0; font:500 12px/16px var(--font-code);
  color:var(--fg-subtle); text-transform:uppercase; text-align:right; overflow-wrap:break-word; }
/* Account footer: dashed hairline, then a 60px row (16 padding around a 28 avatar).
   The row's own bottom padding is the sidebar's bottom gutter. */
/* Full-bleed like the nav rows; the account row alone holds the foot (the theme
   picker lives inside its menu — no standalone segment, matching the frames). */
.nv-account { margin-top:auto; margin-inline:calc(-1 * var(--spacing-16)); }
.nv-account-item { position:relative; width:100%; display:flex; align-items:center;
  gap:var(--spacing-12); padding:var(--spacing-16); border:0;
  /* dashes sample #292929 over black (dark) and #CECECE over gray-100 (light) —
     the 16 % step in both, i.e. --border-base. */
  border-top:var(--stroke-1) dashed var(--border-base);
  background:transparent; cursor:pointer; text-align:left;
  color:var(--fg-subtle); font:inherit;
  transition:background var(--duration-100) var(--ease-in-out); }
.nv-account-item:hover { background:var(--bg-subtle-hover); }
.nv-account-item[aria-expanded="true"] { background:var(--bg-subtle-press); }
.nv-avatar { width:28px; height:28px; border-radius:var(--radius-999); flex:0 0 28px;
  background:var(--brand-200); color:var(--black-100); display:grid; place-items:center;
  font:500 12px/16px var(--font-body); }
/* Two-line identity: name over email, both ellipsized (deployed-reference row). */
.nv-account-id { flex:1; min-width:0; display:flex; flex-direction:column; }
.nv-account-name { min-width:0; overflow:hidden; text-overflow:ellipsis;
  white-space:nowrap; color:var(--fg-subtle); font:500 14px/20px var(--font-body); }
.nv-account-mail { min-width:0; overflow:hidden; text-overflow:ellipsis;
  white-space:nowrap; color:var(--fg-muted); font:400 12px/16px var(--font-body); }
/* Overflow glyph — the row's affordance, not a second control (the whole row opens
   the menu, matching the Account Item component's full-row hover/press states). */
.nv-account-more { flex:0 0 auto; display:inline-flex; align-items:center; justify-content:center;
  width:24px; height:24px; color:var(--fg-muted); }
.nv-account-more svg { width:16px; height:16px; }

/* ---- User menu (popover above the account row) ---- */
.nv-account-menu { position:absolute; left:var(--spacing-8); right:var(--spacing-8);
  bottom:calc(100% + var(--spacing-8)); z-index:60;
  display:flex; flex-direction:column;
  /* Same surface as the recents popover (--bg-field, frame-verified there): on a
     light sidebar --bg-component is the sidebar's own #F5F5F5, so the menu had no
     surface of its own. No v9 frame covers this menu — see the light-set report. */
  background:var(--bg-field); border:var(--stroke-1) solid var(--border-subtle);
  border-radius:var(--radius-8); box-shadow:var(--elevation-menu);
  padding:var(--spacing-4); }
.nv-account { position:relative; }
.nv-account-menu-label { display:block; padding:var(--spacing-8) var(--spacing-12) var(--spacing-4);
  font:500 11px/16px var(--font-code); text-transform:uppercase; letter-spacing:.04em;
  color:var(--fg-muted); }
.nv-account-menu-rule { border-top:var(--stroke-1) solid var(--border-subtle);
  margin:var(--spacing-4) 0; }
/* Theme options are radios: the checked one is the selected state — lime text on a
   stepped neutral, same grammar as the nav's selected row. */
.nv-theme-option { width:100%; border:0; background:transparent; cursor:pointer; text-align:left; }
.nv-theme-option[aria-checked="true"],
.nv-theme-option[aria-checked="true"]:hover { background:var(--bg-button-transparent-press);
  color:var(--fg-interactive); }
.nv-account-menu-item { display:flex; align-items:center; gap:var(--spacing-8);
  padding:var(--spacing-8) var(--spacing-12); border-radius:var(--radius-4);
  color:var(--fg-base); font:400 14px/20px var(--font-body); text-decoration:none;
  transition:background var(--duration-100) var(--ease-in-out), color var(--duration-100) var(--ease-in-out); }
/* hover pairs with the menu's --bg-field surface (component-hover now equals it in dark) */
.nv-account-menu-item:hover { background:var(--bg-field-hover); color:var(--fg-subtle); }
.nv-account-menu-item svg { width:16px; height:16px; flex:0 0 16px; }

/* ---- Collapsed rail (56px) ----
   Rail stack centres at y 36 / 84 / 132 in 09-collapsed-sidebar-dark.png; the
   8px nudge on the search button is what separates the 16px and 24px gaps. */
/* State lives on <html> so base_nova.html can resolve it pre-paint, exactly like
   the theme — collapsing after first paint reads as a jump. */
:root.nv-sidebar-collapsed .nv-sidebar { width:56px; flex-basis:56px; padding-inline:0; }
:root.nv-sidebar-collapsed .nv-sidebar-top { grid-template-columns:1fr;
  grid-template-areas:"brand" "new" "search"; justify-items:center; }
:root.nv-sidebar-collapsed .nv-sidebar-search { margin-top:var(--spacing-8); }
:root.nv-sidebar-collapsed .nusx-logo,
:root.nv-sidebar-collapsed .nv-sidebar-brand-name,
:root.nv-sidebar-collapsed .nv-newchat-label,
:root.nv-sidebar-collapsed .nv-nav-group,
:root.nv-sidebar-collapsed .nv-account-id,
:root.nv-sidebar-collapsed .nv-account-more { display:none; }
:root.nv-sidebar-collapsed .nv-sidebar-mark { display:block; }
:root.nv-sidebar-collapsed .nv-newchat { width:24px; height:24px; padding:0;
  background:transparent; color:var(--fg-muted); border-radius:var(--radius-4); }
:root.nv-sidebar-collapsed .nv-newchat:hover { background:var(--bg-subtle-hover); color:var(--fg-subtle); }
:root.nv-sidebar-collapsed .nv-account { margin-inline:0; }
:root.nv-sidebar-collapsed .nv-account-item { justify-content:center; padding:var(--spacing-16) 0; }
:root.nv-sidebar-collapsed .nv-account-menu { left:var(--spacing-8); right:auto; width:220px; }
/* The rail clips its content while the width animates; the popover is the one
   thing that must escape it. */
:root.nv-sidebar-collapsed .nv-sidebar:has(.nv-account-menu:not([hidden])) { overflow:visible; }

/* ---- Panel toggle — top-left of the main region in every frame ---- */
.nv-panel-toggle { position:absolute; left:var(--spacing-16); top:24px; z-index:20;
  display:inline-flex; align-items:center; justify-content:center;
  width:24px; height:24px; padding:0; border:0; background:transparent;
  color:var(--fg-muted); cursor:pointer; border-radius:var(--radius-4);
  transition:background var(--duration-100) var(--ease-in-out), color var(--duration-100) var(--ease-in-out); }
.nv-panel-toggle:hover { background:var(--bg-base-hover); color:var(--fg-subtle); }
.nv-panel-toggle svg { width:16px; height:16px; }

/* Buttons */
.nv-btn { display:inline-flex; align-items:center; justify-content:center; gap:var(--spacing-8);
  height:36px; padding:0 var(--spacing-16); border:0; cursor:pointer;
  border-radius:var(--radius-4); background:var(--bg-button); color:var(--fg-oncolor);
  font:500 14px/20px var(--font-body);
  transition:background var(--duration-100) var(--ease-in-out), border-color var(--duration-100) var(--ease-in-out); }
.nv-btn:hover { background:var(--bg-button-hover); }
.nv-btn:active { background:var(--bg-button-press); }
.nv-btn:focus-visible { outline:var(--stroke-1) solid var(--border-active); outline-offset:1px; }
.nv-btn:disabled { background:var(--bg-disable); color:var(--fg-disable); cursor:default; }
.nv-btn--transparent { background:var(--bg-button-transparent); color:var(--fg-base);
  border:var(--stroke-1) solid var(--border-base); }
.nv-btn--transparent:hover { background:var(--bg-button-transparent-hover); border-color:var(--border-base-hover); }
.nv-btn--transparent:active { background:var(--bg-button-transparent-press); border-color:var(--border-base-press); }
.nv-btn--transparent:disabled { background:transparent; color:var(--fg-disable); border-color:var(--border-disable); }
.nv-btn--danger { background:var(--bg-button-danger); color:var(--black-100); }
.nv-btn--danger:hover { background:var(--bg-button-danger-hover); }
.nv-btn--danger:active { background:var(--bg-button-danger-press); }
.nv-btn--icon { width:36px; padding:0; }

/* Tag / Link / Eyebrow */
.nv-tag { display:inline-flex; align-items:center; gap:var(--spacing-4);
  padding:2px var(--spacing-8); border-radius:var(--radius-2);
  background:var(--bg-tag); color:var(--black-100); font:500 12px/16px var(--font-code); }
/* The hairline comes OUT of the block padding, not on top of it: both Tag variants
   are 20 tall in the component render (design/components/img/tag-dark.png — filled
   40→60, transparent border 40, interior 41→59, border 59) and in every report frame
   (Results.png MATCHES THIS IP and 94% RELEVANCE both 1652→1672). Left at 2px the
   bordered variant stood 22 and sat a row out of line with its filled sibling. */
.nv-tag--transparent { background:transparent; color:var(--fg-muted);
  padding-block:1px; border:var(--stroke-1) solid var(--border-subtle); }
.nv-link { display:inline-flex; align-items:center; gap:var(--spacing-4);
  color:var(--fg-interactive); font:500 12px/16px var(--font-code);
  text-transform:uppercase; letter-spacing:.04em; text-decoration:none; cursor:pointer; }
.nv-link:hover { color:var(--fg-interactive-hover); }
/* Untracked mono: the Eyebrow component render and every frame instance advance at
   0.6em flat — "EVALUATION" steps 1043.5 → 1108 (7.167/char) in Results.png and
   "LICENSING · EVALUATE" spans 144.5 over 20 glyphs in eyebrow-dark.png, where the
   .04em this used to carry renders 7.68. (The Link component IS tracked — its
   "VIEW ON GOOGLE PATENTS" steps 7.56 — so .nv-link keeps its .04em.) */
.nv-eyebrow { display:flex; gap:var(--spacing-8); font:500 12px/16px var(--font-code);
  text-transform:uppercase; color:var(--fg-muted); }
.nv-eyebrow b { font-weight:500; color:var(--fg-subtle); }

/* Main region */
/* position:relative anchors .nv-panel-toggle to the main region's top-left. */
.nv-main { position:relative; flex:1; min-width:0; background:var(--bg-base); }

/* ============================================================
   Task 4 — Chat components: composer, prompt option, messages,
   thinking steps, cards, modal. Values verified 18 Aug via Figma
   MCP get_variable_defs against each component's dark_id (light
   resolves automatically through the shared semantic tokens);
   design/components/img/*.png cross-checked for composition.
   Corrections vs. the task brief found this way (see task-4-report.md):
     - nv-composer/nv-input border is --border-base (not --border-subtle).
     - nv-composer/nv-prompt-option/nv-result-card/nv-info-card/nv-namecard
       use --radius-4, not --radius-8 (radius-8 is reserved for nv-modal —
       it's the only component whose node tree binds that variable).
     - nv-prompt-option category is Inter Medium 10px (bodyMedium-10), not
       PP Mono 12px — confirmed against prompt-option-dark.png (sans, not
       monospace, visibly smaller than the description line).
     - nv-info value is heading-28 (nv-h28), not h24.
     - nv-table-row-meta is Inter body-14 (not mono code-12) — confirmed
       against a 2x crop of sidebar-table-row-dark.png (proportional, not
       monospace glyphs).
   ============================================================ */

/* ---- Composer ----
   Geometry from the Figma "Input" component instance in the welcome frame
   (get_metadata 2127:23821, user reference crop 19 Aug): the unit is 802 wide —
   promptOptions band 104 tall flush on a 110-tall composer. Composer: radius-8,
   24px padding, 16px placeholder top-left, bare "+" bottom-left, 36px lime send
   bottom-right. */
.nv-composer { position:relative; display:flex; flex-direction:column; justify-content:space-between;
  gap:var(--spacing-16); min-height:110px; background:var(--bg-field);
  border:var(--stroke-1) solid var(--border-base); border-radius:var(--radius-8);
  padding:var(--spacing-24); box-shadow:var(--elevation-input);
  transition:border-color var(--duration-100) var(--ease-in-out); }
.nv-composer.is-active, .nv-composer:focus-within { border-color:var(--border-active); }
.nv-composer-input { caret-color:var(--fg-interactive); }
.nv-composer-input { flex:1; width:100%; border:0; outline:0; resize:none; background:transparent;
  color:var(--fg-subtle); font:400 16px/24px var(--font-body); }
.nv-composer-input::placeholder { color:var(--fg-muted); }
.nv-composer-input:disabled { color:var(--fg-disable); }
.nv-composer-row { display:flex; align-items:center; justify-content:space-between; gap:var(--spacing-8); }
.nv-composer-attach { display:inline-flex; align-items:center; justify-content:center;
  width:28px; height:28px; padding:0; border:0; background:transparent; color:var(--fg-subtle);
  cursor:pointer; border-radius:var(--radius-4); transition:background var(--duration-100) var(--ease-in-out); }
.nv-composer-attach svg { width:20px; height:20px; }
.nv-composer-attach:hover { background:var(--bg-button-transparent-hover); }
.nv-composer-attach:disabled { color:var(--fg-disable); cursor:default; background:transparent; }
.nv-composer-send.nv-btn { width:36px; height:36px; padding:0; border-radius:var(--radius-4); }
.nv-composer:has(.nv-composer-input:disabled) { opacity:.5; }

/* ---- Prompt options — a shared band, not individual cards ----
   The reference crop + Input component: two borderless options (387×96, 4px
   insets, 8px band side-padding) on a --bg-subtle band (darker than the canvas
   in dark, lighter in light), rounded on top only, sitting flush on the
   composer. The ⌘ shortcuts are bordered keycaps top-right. */
.nv-prompt-option { position:relative; display:flex; flex-direction:column; gap:var(--spacing-4);
  background:transparent; border:0; border-radius:var(--radius-4); padding:var(--spacing-16) var(--spacing-16) var(--spacing-16) var(--spacing-16);
  text-align:left; text-decoration:none; cursor:pointer;
  transition:background var(--duration-100) var(--ease-in-out); }
.nv-prompt-option:hover { background:var(--bg-component-hover); }
.nv-prompt-option:disabled, .nv-prompt-option[aria-disabled="true"] { cursor:default; opacity:.5; }
.nv-prompt-option-category { display:block; font:500 10px/16px var(--font-body); color:var(--fg-interactive); }
.nv-prompt-option-title { display:block; margin-top:var(--spacing-4); font:500 14px/20px var(--font-body); color:var(--fg-subtle); }
.nv-prompt-option-desc { display:block; margin-top:var(--spacing-4); font:400 14px/20px var(--font-body); color:var(--fg-muted); }
.nv-prompt-option-tag { position:absolute; top:var(--spacing-12); right:var(--spacing-12); }
/* Keycap treatment overrides the transparent-tag hairline with a keycap border. */
/* Keycap hairline is the 8 % step: the ⌘1 box (x 945→978, y 654→674) samples
   #313131 on the dark band and #E1E1E1 on the light one. */
.nv-prompt-option-tag.nv-tag--transparent { border:var(--stroke-1) solid var(--border-subtle);
  border-radius:var(--radius-4); color:var(--fg-muted); padding:2px var(--spacing-8); }

/* ---- Messages ---- */
/* Frame-measured (licensing/v9/Dark/Results.png, split view, first turn):
   the bubble is 480px wide at its cap, 56px tall for two 20px lines → 8px block
   padding, 16px inline; its corner arc spans 20px in both axes (fitted against the
   export at y=2.0/5.25/9.75 → x=11.0/6.25/2.75, all within 0.3px of a 20px circle),
   which is off the 0/2/4/8/999 radius ramp — hence the literal. Same 480/20 in the
   non-split frames (Thinking.png, Right.png), so it is a cap, not a percentage. */
.nv-message { align-self:flex-end; max-width:480px; background:var(--bg-component);
  border-radius:20px; padding:var(--spacing-8) var(--spacing-16);
  color:var(--fg-subtle); font:400 14px/20px var(--font-body); }
.nv-message-ref { display:flex; align-items:center; gap:var(--spacing-8); margin-top:var(--spacing-8);
  color:var(--fg-muted); font:400 12px/16px var(--font-code); }
/* The assistant's prose is --fg-subtle, not --fg-base: the answer paragraph samples
   pure #FFFFFF in Dark/Results.png and pure #000000 in Light/Results.png. */
.nv-ai-message { max-width:75%; color:var(--fg-subtle); font:400 14px/20px var(--font-body); }

/* ---- Thinking ---- */
.nv-thinking { display:flex; flex-direction:column; }
/* 5px block padding = a 30px row pitch, measured off the v9 frames (Thinking.png,
   lime check glyphs centred at y 174.25 / 204.25 / 234.25 → 30px apart). 30 is off
   the 4/8/12 spacing grid, so the literal is the frame's, not an invention. */
.nv-thinking-step { display:flex; align-items:center; gap:var(--spacing-8); padding:5px 0; }
.nv-thinking-step-icon { display:inline-flex; align-items:center; justify-content:center;
  width:16px; height:16px; flex:0 0 16px; font-size:12px; line-height:1; }
/* default/pending: neutral hollow ring, no glyph */
.nv-thinking-step-icon::before { content:""; width:8px; height:8px; border-radius:var(--radius-999);
  border:1.5px solid var(--border-base); }
.nv-thinking-step-label { font:400 14px/20px var(--font-body); color:var(--fg-base); }
/* complete: lime check glyph (markup-supplied text), muted label — per thinking-step-dark.png */
.nv-thinking-step.is-complete .nv-thinking-step-icon { color:var(--fg-interactive); }
.nv-thinking-step.is-complete .nv-thinking-step-icon::before { content:none; }
.nv-thinking-step.is-complete .nv-thinking-step-label { color:var(--fg-muted); }
/* active: NO band. The v9 frames (Thinking.png, row 4 "Assembling the shortlist")
   keep the canvas at --bg-base straight through the active row — sampled across
   x 256…1728 at y 264, every pixel outside the glyph/text is (20,20,20). The row
   is marked instead by the brand's particle sphere (a 16px dotted disc, dots
   sampled at ≈#4A4A4A, i.e. the neutral ramp — not lime) and by a label that fades
   left→right from --fg-base to --fg-muted (sampled 164→145 along the label). */
.nv-thinking-step.is-active .nv-thinking-step-label {
  background:linear-gradient(90deg, var(--fg-base) 0%, var(--fg-muted) 100%);
  -webkit-background-clip:text; background-clip:text; color:transparent; }
/* Light mode runs the same fade far paler. Darkest ink sampled in six slices along
   "Assembling the shortlist" in Light/Thinking.png: 214 → 206 → 199 → 191 → 184,
   i.e. gray-300 → gray-400 (= --fg-disable in light). The dark frame's own
   brightest-ink slices run 165 → 100, which is what the base rule above renders,
   so this override is light-only. No semantic pair resolves to gray-300 in light
   and to dark's start, hence the frame-cited primitive on the light end only. */
/* background-IMAGE, not the `background` shorthand — the shorthand would reset
   background-clip back to border-box and paint the label as a solid bar. */
:root[data-theme="light"] .nv-thinking-step.is-active .nv-thinking-step-label {
  background-image:linear-gradient(90deg, var(--gray-300) 0%, var(--fg-disable) 100%); }
.nv-thinking-step.is-active .nv-thinking-step-icon::before { border:0;
  flex:0 0 16px; width:16px; height:16px; background-color:transparent;
  background-image:radial-gradient(var(--fg-muted) 0.6px, transparent 0.7px);
  background-size:2px 2px; animation:nv-spin var(--duration-500) linear infinite; }
.nv-thinking-step.is-divider { height:var(--stroke-1); padding:0; margin:var(--spacing-4) 0;
  background:var(--border-subtle); }
.nv-thinking-step.is-divider .nv-thinking-step-icon,
.nv-thinking-step.is-divider .nv-thinking-step-label { display:none; }
@keyframes nv-spin { to { transform:rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .nv-thinking-step.is-active .nv-thinking-step-icon::before { animation:none; }
}

/* ---- Result card ---- */
/* Hairline is the 16 % step. Sampled on both v9 Shortlist frames at the card's
   left/right edges (x 296 / 951, y 236): #3A3A3A dark, #D6D6D6 light — --border-base,
   not the 8 % --border-subtle this used to carry (near-invisible on white). */
.nv-result-card { display:flex; align-items:flex-start; gap:var(--spacing-12);
  background:var(--bg-base); border:var(--stroke-1) solid var(--border-base);
  border-radius:var(--radius-4); padding:var(--spacing-16);
  transition:background var(--duration-100) var(--ease-in-out); }
.nv-result-card:hover { background:var(--bg-base-hover); }
.nv-result-card-number { flex:0 0 auto; font:400 12px/16px var(--font-code); color:var(--fg-muted); }
.nv-result-card-body { flex:1; min-width:0; display:flex; flex-direction:column; gap:var(--spacing-8); }
.nv-result-card-title { font:400 14px/20px var(--font-body); color:var(--fg-subtle); }
.nv-result-card-desc { display:flex; align-items:center; gap:var(--spacing-8); flex-wrap:wrap;
  font:400 12px/16px var(--font-code); color:var(--fg-muted); }
.nv-result-card-action { flex:0 0 auto; align-self:center; }

/* ---- Table row ---- */
.nv-table-row { display:grid; grid-template-columns:auto 1fr auto; grid-template-rows:auto auto;
  align-items:center; column-gap:var(--spacing-12); row-gap:var(--spacing-4);
  /* row divider sampled at y 476.5 in both v9 Results frames: #3A3A3A / #D6D6D6 = 16 %. */
  padding:var(--spacing-12) var(--spacing-16); border-bottom:var(--stroke-1) solid var(--border-base); }
.nv-table-row-index { grid-column:1; grid-row:1 / 3; align-self:start; padding-top:2px;
  font:400 12px/16px var(--font-code); color:var(--fg-muted); }
.nv-table-row-name { grid-column:2; grid-row:1; font:500 14px/20px var(--font-body); color:var(--fg-subtle); }
.nv-table-row-meta { grid-column:2; grid-row:2; display:flex; align-items:center; gap:var(--spacing-4);
  flex-wrap:wrap; font:400 14px/20px var(--font-body); color:var(--fg-muted); }
.nv-table-row-fit { font:500 14px/20px var(--font-body); color:var(--fg-subtle); }
.nv-table-row-actions { grid-column:3; grid-row:1 / 3; display:flex; align-items:center; gap:var(--spacing-8); }

/* ---- Info / Highlight / Progress ---- */
.nv-info { display:flex; flex-direction:column; gap:var(--spacing-4); }
.nv-info-headline { font:500 12px/16px var(--font-code); text-transform:uppercase;
  letter-spacing:.04em; color:var(--fg-muted); }
/* Highlight-text component: the rule is AMBER, not lime, and it binds to the
   --fg-warning pair — highlight-text-dark.png samples #DC9404 and the light render
   #FCC85F, the same amber-400/amber-200 the level meter uses. Text is body-14
   --fg-base (#E0E0E0, 20px pitch), and its box starts 16 from the element edge, of
   which the rule itself is 2. */
.nv-highlight { border-left:var(--stroke-2) solid var(--fg-warning);
  padding-left:calc(var(--spacing-16) - var(--stroke-2));
  font:400 14px/20px var(--font-body); color:var(--fg-base); }
/* The track is a solid --bg-component step, not an outlined --bg-base one, and both
   ends are square: the Progress bar component renders a 4px bar whose track samples
   #1F1F1F on the dark canvas and #F5F5F5 on the light one (= gray-900 / gray-100 =
   the --bg-component pair) with a lime fill that cuts off flat
   (design/components/img/progress-bar-{dark,light}.png). The inset hairline this
   used to carry was working around a --bg-base fill that had no contrast to give. */
.nv-progress { position:relative; height:4px; border-radius:var(--radius-0);
  background:var(--bg-component); overflow:hidden; }
/* display:block so the fill works from a <span> too — an inline box ignores height. */
.nv-progress-fill { display:block; height:100%; border-radius:inherit; background:var(--bg-button); }

/* ---- Modal ---- */
.nv-modal-overlay { position:fixed; inset:0; z-index:100; display:flex; align-items:center;
  justify-content:center; padding:var(--spacing-24); background:var(--bg-overlay);
  animation:nv-fade-in var(--modal-open) var(--ease-out); }
.nv-modal-overlay.is-closing { animation:nv-fade-out var(--modal-close) var(--ease-in); }
/* Frame-measured (licensing/v9/Dark/Results/Email/Outreach.png): the dialog is
   720 × 662 at x 504→1224, its chrome (header title ink at 521, footer strip at
   520, Gmail button's right edge at 1208) inset 16, while the document inside it
   sits at 24 — the letterhead rule runs 528→1200. So the dialog carries the 16 and
   the body adds the remaining 8; the footer rule is full-bleed (712: x 504→1224). */
.nv-modal { width:min(720px, 90vw); max-height:85vh; overflow-y:auto; display:flex;
  flex-direction:column; gap:var(--spacing-16); background:var(--bg-component);
  border-radius:var(--radius-8); box-shadow:var(--elevation-modal); padding:var(--spacing-16); }
.nv-modal-header { display:flex; align-items:center; justify-content:space-between; gap:var(--spacing-12); }
.nv-modal-header-title { display:flex; align-items:center; gap:var(--spacing-12);
  font:500 16px/24px var(--font-body); color:var(--fg-subtle); min-width:0; }
/* gap 16, not 8: in both dialog frames (modal-Email.png, modal-Note.png) the close
   glyph centres 12 in from the dialog's content edge and the copy glyph 39.5 further
   left — 24px buttons (16 icon + 4 padding) spaced 16 apart. */
.nv-modal-header-actions { display:flex; align-items:center; gap:var(--spacing-16); color:var(--fg-muted); }
.nv-modal-header-actions button { display:inline-flex; border:0; background:transparent;
  color:inherit; cursor:pointer; padding:var(--spacing-4); border-radius:var(--radius-4); }
.nv-modal-header-actions button:hover { background:var(--bg-button-transparent-hover); color:var(--fg-subtle); }
.nv-modal-body { display:flex; flex-direction:column; gap:var(--spacing-16);
  padding-inline:var(--spacing-8); }
/* Callout above a modal document — the note frame's "<rep> spoke to <contact> on
   <date>" row (modal-Note.png): 56 tall on a --border-subtle hairline, a 24px icon
   frame 16 in from the box edge, the text 8 after it, all at --fg-base. Figma draws
   its stroke inside the frame, so the padding gives the border's 1px back to keep
   the icon ink at 44 and the text at 72 inside a 24-inset box. */
.nv-modal-note { display:flex; align-items:center; gap:var(--spacing-8);
  border:var(--stroke-1) solid var(--border-subtle); border-radius:var(--radius-4);
  padding:calc(var(--spacing-16) - var(--stroke-1));
  color:var(--fg-base); font:400 14px/20px var(--font-body); }
.nv-modal-note > svg { width:24px; height:24px; flex:0 0 24px; }
.nv-modal-section { display:flex; flex-direction:column; gap:var(--spacing-8);
  padding-top:var(--spacing-16); border-top:var(--stroke-1) solid var(--border-subtle); }
.nv-modal-section:first-child { padding-top:0; border-top:0; }
.nv-modal-section-label { font:400 14px/20px var(--font-body); color:var(--fg-muted); }
/* Full-bleed rule: the frame's footer separator spans the whole dialog (x 504→1224),
   so the row reaches past the dialog's 16px inset and puts it back as padding. */
.nv-modal-footer { display:flex; align-items:center; justify-content:space-between; gap:var(--spacing-12);
  margin-inline:calc(-1 * var(--spacing-16)); padding:var(--spacing-16) var(--spacing-16) 0;
  /* rule at y 712 samples #434343 (dark) / #CECECE (light) = the 16 % step. */
  border-top:var(--stroke-1) solid var(--border-base); }
.nv-modal-footer-status { display:flex; align-items:center; gap:var(--spacing-8);
  font:500 12px/16px var(--font-code); text-transform:uppercase; letter-spacing:.04em; color:var(--fg-muted); }
/* The frame draws the status as a strip, not a dot — same 2px × 16px mark the
   report kicker uses, in mint (licensing/v9/Dark/Results/Email/Outreach.png:
   x 520→522, y 739→755, sampled #28B862). */
.nv-modal-footer-status::before { content:""; width:var(--stroke-2); height:16px;
  flex:0 0 var(--stroke-2); border-radius:var(--radius-0); background:var(--fg-success); }
@keyframes nv-fade-in { from { opacity:0; } to { opacity:1; } }
@keyframes nv-fade-out { from { opacity:1; } to { opacity:0; } }
@media (prefers-reduced-motion: reduce) {
  .nv-modal-overlay, .nv-modal-overlay.is-closing { animation:none; }
}

/* ---- Headers ---- */
.nv-chat-header, .nv-details-header { display:flex; align-items:center; justify-content:space-between;
  gap:var(--spacing-12); height:56px; padding:0 var(--spacing-16);
  border-bottom:var(--stroke-1) solid var(--border-subtle); background:var(--bg-base); }
.nv-chat-header-actions, .nv-details-header-actions { display:flex; align-items:center; gap:var(--spacing-8); }
.nv-chat-header button, .nv-details-header button { display:inline-flex; align-items:center; justify-content:center;
  width:28px; height:28px; border:0; background:transparent; color:var(--fg-muted); cursor:pointer;
  border-radius:var(--radius-4); transition:background var(--duration-100) var(--ease-in-out), color var(--duration-100) var(--ease-in-out); }
.nv-chat-header button:hover, .nv-details-header button:hover { background:var(--bg-button-transparent-hover); color:var(--fg-subtle); }

/* ---- Input ---- */
.nv-input { height:36px; width:100%; background:var(--bg-field); border:var(--stroke-1) solid var(--border-base);
  border-radius:var(--radius-4); padding:0 var(--spacing-12); color:var(--fg-base);
  font:400 14px/20px var(--font-body); box-shadow:var(--elevation-input);
  transition:border-color var(--duration-100) var(--ease-in-out); }
.nv-input::placeholder { color:var(--fg-muted); }
.nv-input:focus { outline:0; border-color:var(--border-active); }
.nv-input:disabled { color:var(--fg-disable); border-color:var(--border-disable); cursor:default; }

/* ---- Step ---- */
.nv-step { display:inline-flex; align-items:center; gap:var(--spacing-8); }
.nv-step-bar { width:48px; height:2px; border-radius:var(--radius-999); background:var(--border-base); }
.nv-step.is-active .nv-step-bar, .nv-step-bar.is-active { background:var(--fg-interactive); }

/* ---- Illustration ---- */
.nv-illustration { display:grid; place-items:center; flex:0 0 64px; width:64px; height:64px;
  border:var(--stroke-1) solid var(--border-subtle); border-radius:var(--radius-4);
  background:var(--bg-component); color:var(--fg-muted); }
.nv-illustration svg { width:24px; height:24px; }

/* ---- Info card ---- */
.nv-info-card { display:flex; align-items:center; gap:var(--spacing-12); background:var(--bg-base);
  border:var(--stroke-1) solid var(--border-subtle); border-radius:var(--radius-4);
  padding:var(--spacing-12) var(--spacing-16); }
.nv-info-card-body { flex:1; min-width:0; }
.nv-info-card-title { font:400 14px/20px var(--font-body); color:var(--fg-subtle); }
.nv-info-card-caption { margin-top:var(--spacing-4); font:400 12px/16px var(--font-code); color:var(--fg-muted); }
.nv-info-card-action { flex:0 0 auto; }

/* ---- Namecard ---- */
.nv-namecard { display:flex; flex-direction:column; gap:var(--spacing-16); background:var(--bg-component);
  border:var(--stroke-1) solid var(--border-subtle); border-radius:var(--radius-4); padding:var(--spacing-16); }
.nv-namecard-header { display:flex; align-items:flex-start; justify-content:space-between;
  gap:var(--spacing-12); flex-wrap:wrap; }
.nv-namecard-title { font:500 20px/28px var(--font-heading); color:var(--fg-subtle); }
.nv-namecard-meta { margin-top:var(--spacing-4); font:400 14px/20px var(--font-body); color:var(--fg-muted); }
.nv-namecard-tags { display:flex; gap:var(--spacing-8); flex-wrap:wrap; }
.nv-namecard-section { display:flex; flex-direction:column; gap:var(--spacing-12);
  padding-top:var(--spacing-16); border-top:var(--stroke-1) dashed var(--border-subtle); }
.nv-namecard-section-label { font:400 14px/20px var(--font-body); color:var(--fg-muted); }
.nv-namecard-row { display:flex; align-items:baseline; gap:var(--spacing-12); }
/* label is fixed-width (never shrinks below its own text) so a long value never
   crowds it out — value takes the remaining space and wraps/right-aligns instead
   (first real nv-namecard-row consumer is Task 6's "Quick facts" panel, where
   free-text values like Sector can run long in a 320px rail). */
.nv-namecard-row-label { flex:0 0 auto; font:400 14px/20px var(--font-body); color:var(--fg-base); }
.nv-namecard-row-value { flex:1 1 auto; min-width:0; text-align:right;
  font:400 12px/16px var(--font-code); color:var(--fg-muted); }
.nv-namecard-quote { padding-top:var(--spacing-16); border-top:var(--stroke-1) solid var(--border-subtle);
  font:400 16px/24px var(--font-body); color:var(--fg-subtle); }
.nv-namecard-caption { margin-top:var(--spacing-8); font:400 12px/16px var(--font-code); color:var(--fg-muted); }

/* nv-btn small modifier (Task 5 uses this for table-row actions) */
.nv-btn--sm { height:28px; padding:0 var(--spacing-12); font-size:12px; }

/* ============================================================
   Task 5 — PAGE LAYERS
     · nv-page-chat  — the Nova chat surface (root route)
     · nv-report     — document layout for artifact panes / modals
   Composition follows design/context/licensing/*.png (the Aug-14
   licensing walkthrough) — see task-5-report.md for the frame-by-frame
   mapping. Everything here composes Task-2/Task-4 components; no new
   colours, radii or spacing values are introduced.
   ============================================================ */

/* ---- Shell carry-overs (Task 2 left these unstyled; the chat page is the
        first surface to render them) ---- */
/* The X is lime in dark only — the light frame's wordmark is solid black
   (verified against licensing/01-welcome-light.png, user-confirmed 19 Aug). */
.nusx-x { fill:var(--brand-200); }
:root[data-theme="light"] .nusx-x { fill:currentColor; }
/* Brand name sits beside the wordmark at heading-20 in --fg-muted (measured: cap
   height 14px, #7A7A7A, baseline shared with the logo). */
.nv-sidebar-brand-name { color:var(--fg-muted); font:400 20px/28px var(--font-heading); }
.nv-newchat, .nv-nav-item, .nv-btn { text-decoration:none; }
button.nv-nav-item { width:100%; border:0; background:transparent; cursor:pointer;
  font:inherit; text-align:left; }
.nv-nav-empty { padding:var(--spacing-8) var(--spacing-16); color:var(--fg-muted);
  font:400 12px/16px var(--font-body); }
/* the legacy .recent-title truncated to one line; nv-nav-item-title
   didn't carry that over, so long recents (thesis titles) wrapped to 4 lines.
   min-width:0 keeps the flex-stretched anchor from growing past the sidebar
   to fit the text before the ellipsis gets a chance to apply. */
.nv-nav-item { min-width:0; }
.nv-nav-item-title { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
/* agent.js keeps the pending-step glyph in the markup (the component draws the
   complete state's lime check from that text); hide it until the step lands. */
.nv-thinking-step:not(.is-complete) .nv-thinking-step-icon { color:transparent; }
/* Collapsed working steps. Once the answer lands agent.js folds the finished list
   behind a single "Thought for Ns" row — the expanded post-response checklist ate
   the column (Anni + Balaji, 19 Aug 2026). Figma's Thinking Steps has no collapsed
   variant, so the interaction is claude.ai's: summary row with a leading chevron,
   list animating open and closed from it. The 0fr→1fr grid row is what lets the
   list animate to its own height without a hardcoded max-height. */
.nv-thinking-toggle { display:flex; align-items:center; gap:var(--spacing-8);
  align-self:flex-start; padding:5px 0; border:0; background:none; cursor:pointer;
  font:400 14px/20px var(--font-body); color:var(--fg-muted); }
.nv-thinking-toggle:hover { color:var(--fg-base); }
.nv-thinking-toggle svg { width:16px; height:16px; flex:0 0 16px;
  transition:transform var(--duration-200) var(--ease-in-out); }
.nv-thinking.is-collapsed .nv-thinking-toggle svg { transform:rotate(-90deg); }
.nv-thinking-anim { display:grid; grid-template-rows:1fr;
  transition:grid-template-rows var(--duration-200) var(--ease-in-out); }
.nv-thinking.is-collapsed .nv-thinking-anim { grid-template-rows:0fr; }
.nv-thinking-body { min-height:0; overflow:hidden; }
@media (prefers-reduced-motion: reduce) {
  .nv-thinking-anim { transition:none; }
}
/* agent.js reads this to time the modal's close animation. */
:root { --modal-close-duration:var(--modal-close); }

/* ---- 5.1 · Chat surface ------------------------------------------------ */
/* The chat surface sits 8px below the shell top on a black band, with an 8px
   top-left corner — measured off incubation/v9/Dark/Default.png
   (fill starts at y=8, corner resolves by y=15). --nv-split is the artifact
   pane's share of the right region; 50% is the Figma default (the divider in
   05-results-shortlist-dark.png lands at x=991 of a 256…1728 region). */
/* The 8px gutter above the rounded chat column is the SIDEBAR's surface, not raw
   black: sampled at y 0…7.5 it is (0,0,0) in every Dark v9 frame and (245,245,245)
   in every Light one — i.e. --bg-subtle, which is black in dark and gray-100 in
   light. Pinning --black-100 left a black band across the top in light mode. */
.nv-page-chat { --nv-split:50%; display:flex; height:100vh; overflow:hidden;
  padding-top:var(--spacing-8); background:var(--bg-subtle); }
.nv-chat-col { position:relative; flex:1 1 auto; min-width:360px; display:flex;
  flex-direction:column; background:var(--bg-base); border-top-left-radius:var(--radius-8); }
/* The 56px chrome row the frames reserve above the conversation — it holds the
   panel toggle and masks the scroller passing beneath it. */
.nv-chat-col::before { content:""; position:absolute; top:0; left:0; right:0; height:56px;
  background:var(--bg-base); border-top-left-radius:var(--radius-8);
  z-index:15; pointer-events:none; }
/* 16px gutters, not 24: in the split frames the composer sits at x 272→975 inside
   a 256…991.5 chat column (licensing/v9/Dark/Results/Shortlist.png), i.e. 16 —
   and the thread's own 24px inset on top of that lands its text at x 296, which is
   exactly where every frame puts it. */
.nv-chat-scroll { flex:1; min-height:0; overflow-y:auto;
  padding:56px var(--spacing-16) var(--spacing-16); }
/* The conversation reads on a 754px column: the 802 measure less a 24px inset each
   side — the same inset the hero carries. Measured on Right.png (result rows and
   group rules run x 615→1369 inside the 591→1393 column) and on the split frames
   (thread content 296→951.5). */
.nv-chat-thread { padding-inline:var(--spacing-24); }
/* Drag handle — zero-width flex item; the pane's own border-left is the hairline,
   this only widens the hit area and lights it up on hover/drag. */
.nv-split-handle { display:none; flex:0 0 0; position:relative; z-index:10;
  cursor:col-resize; }
.nv-page-chat.is-split .nv-split-handle { display:block; }
.nv-split-handle::before { content:""; position:absolute; top:0; bottom:0;
  left:-3px; width:7px;
  transition:background var(--duration-100) var(--ease-in-out); }
.nv-split-handle:hover::before, .nv-split-handle.is-dragging::before,
.nv-split-handle:focus-visible::before { background:var(--border-base); }
.nv-split-handle:focus-visible { outline:0; }
body.nv-resizing { cursor:col-resize; user-select:none; }
.nv-measure { width:100%; max-width:802px; margin-inline:auto; }
/* 802px = the Figma content-column width (Top group / Input instance, frame
   2127:23811) — a layout fact from the frame, not a spacing-scale value. */

/* landing / thread are exclusive — agent.js flips data-state on #agentShell */
.nv-page-chat[data-state="landing"] .nv-chat-thread { display:none; }
.nv-page-chat[data-state="result"] .nv-chat-landing,
.nv-page-chat[data-state="result"] .nv-starters { display:none; }

/* Hero geometry from the welcome frame's Top group (2127:23817): texts inset
   24px inside the 802 column; eyebrow→headline→sub gaps 16; sub is a narrow
   ~400px measure at body-14; the eyebrow reads in the base ink, not muted
   (visibly darker than the sub in both mode frames). */
.nv-chat-hero { display:flex; flex-direction:column; gap:var(--spacing-16);
  padding-inline:var(--spacing-24); }
.nv-chat-hero .nv-eyebrow { color:var(--fg-subtle); }
/* 4x export detail: the eyebrow's square brackets are lime, its text is the
   primary ink. */
.nv-eyebrow-bracket { color:var(--fg-interactive); }
.nv-chat-hero-sub { max-width:400px; color:var(--fg-muted); }
/* Fallback-face compensation: PP Neue Montreal is materially narrower than
   Inter at display sizes; a touch of negative tracking closes most of the
   visual gap until the licensed webfonts land (static/fonts/README.md). The
   spec letter-spacing for the PP faces themselves stays 0. */
.nv-h48, .nv-h40, .nv-h32 { letter-spacing:-0.02em; }

/* The band is tucked 8px behind the composer on each side — measured on
   licensing/v9/Dark/Default.png: the band's #1F1F1F runs x 599.5→1384.5 while
   the composer below it runs 591→1393. */
.nv-starters { display:grid; grid-template-columns:1fr 1fr; gap:var(--spacing-4);
  background:var(--bg-component); border-radius:var(--radius-8) var(--radius-8) 0 0;
  padding:var(--spacing-4) var(--spacing-8); margin:0 var(--spacing-8); }
/* Band = gray-900 (#1F1F1F sampled from the 4x Default export), i.e. bg-component. */

/* Composer dock — always docked below the scroller (claude.ai model) */
.nv-composer-dock { flex:none; background:var(--bg-base);
  padding:var(--spacing-8) var(--spacing-16) var(--spacing-12); }
.nv-composer-note { margin-top:var(--spacing-8); text-align:center;
  color:var(--fg-muted); font:400 12px/16px var(--font-body); }
.nv-composer-chips { display:flex; flex-wrap:wrap; gap:var(--spacing-8); }
.nv-chip { display:inline-flex; align-items:center; gap:var(--spacing-8); min-width:0;
  max-width:100%; padding:2px var(--spacing-8); border-radius:var(--radius-2);
  border:var(--stroke-1) solid var(--border-subtle); color:var(--fg-base);
  font:400 12px/16px var(--font-body); }
.nv-chip-pno { flex:0 0 auto; font:400 12px/16px var(--font-code); color:var(--fg-muted); }
.nv-chip-title { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.nv-chip-x { flex:0 0 auto; border:0; background:transparent; cursor:pointer;
  color:var(--fg-muted); font:400 12px/16px var(--font-body); }
.nv-chip-x:hover { color:var(--fg-subtle); }
/* Ghost overlay — a starter drops a solid stem into the textarea and mirrors the
   grey suggestion tail underneath. Font metrics MUST match .nv-composer-input. */
.nv-composer-ta { position:relative; flex:1; min-height:24px; }
.nv-composer-ghost { position:absolute; inset:0; overflow:hidden; pointer-events:none;
  white-space:pre-wrap; word-wrap:break-word; color:var(--fg-muted);
  font:400 16px/24px var(--font-body); }
.nv-composer-ghost-typed { color:transparent; }
.nv-composer-ta.has-ghost .nv-composer-input::placeholder { color:transparent; }
.nv-composer-input { height:24px; max-height:180px; overflow-y:auto; }

/* ---- 5.2 · Thread ------------------------------------------------------ */
.nv-turn { display:flex; flex-direction:column; gap:var(--spacing-16);
  margin-bottom:var(--spacing-32); }
.nv-turn-user { align-items:flex-end; }
.nv-turn-main { display:flex; flex-direction:column; gap:var(--spacing-16); min-width:0; }
.nv-thinking { gap:0; }
.nv-turn .nv-ai-message { max-width:100%; }

/* Result / artifact card — the card opens the pane, the action slot carries the
   flow's next step (licensing/04, 05). */
.nv-result-card-main { flex:1; min-width:0; display:flex; align-items:flex-start;
  gap:var(--spacing-12); padding:0; border:0; background:transparent; cursor:pointer;
  text-align:left; font:inherit; color:inherit; }
.nv-result-card.is-open { border-color:var(--border-base); }
.nv-result-card-icon { flex:0 0 16px; width:16px; height:16px; color:var(--fg-muted); }
.nv-result-card-icon svg { width:16px; height:16px; }
.nv-card-tag { text-transform:uppercase; }
/* File-type labels (PATENT / PHD THESIS / RESEARCH) are neon — walkthrough
   decision #5, user-confirmed against the v9 frames 19 Aug. Scoped to the
   kind chip so other transparent tags stay muted. */
.nv-card-tag.nv-tag--transparent { color:var(--fg-interactive); }
.nv-result-card.has-next .nv-card-open { display:none; }
.nv-card-open { flex:0 0 auto; align-self:center; }

/* Next steps — inline in a card's action slot, or standalone under an
   off-script answer. */
.nv-next { display:flex; align-items:center; flex-wrap:wrap; gap:var(--spacing-8); }
.nv-next-label { font:500 12px/16px var(--font-code); text-transform:uppercase;
  letter-spacing:.04em; color:var(--fg-muted); margin-right:var(--spacing-4); }
.nv-next-btn { display:inline-flex; align-items:center; gap:var(--spacing-8); height:28px;
  padding:0 var(--spacing-12); cursor:pointer; border-radius:var(--radius-4);
  background:var(--bg-button-transparent); border:var(--stroke-1) solid var(--border-base);
  color:var(--fg-base); font:500 12px/16px var(--font-body);
  transition:background var(--duration-100) var(--ease-in-out); }
.nv-next-btn:hover, .nv-next-btn.is-hover { background:var(--bg-button-transparent-hover); }
.nv-next-k { font:500 12px/16px var(--font-code); text-transform:uppercase;
  letter-spacing:.04em; color:var(--fg-interactive); }
.nv-result-card-action .nv-next-btn { height:auto; padding:0; border:0; background:transparent;
  color:var(--fg-interactive); font:500 12px/16px var(--font-code);
  text-transform:uppercase; letter-spacing:.04em; }
.nv-result-card-action .nv-next-btn:hover,
.nv-result-card-action .nv-next-btn.is-hover { color:var(--fg-interactive-hover); }
.nv-result-card-action .nv-next-k { display:none; }
.nv-result-card-action .nv-next-btn::after { content:"→"; }

/* Search results — the agentic search's selectable asset list (licensing/10). */
/* container hairline sampled at x 296 / 951 in both v9 Results frames: 16 % step. */
.nv-results { border:var(--stroke-1) solid var(--border-base);
  border-radius:var(--radius-4); overflow:hidden; }
.nv-results .nv-table-row:last-child,
.nv-results-group:last-child .nv-table-row:last-child { border-bottom:0; }
button.nv-table-row { width:100%; border-left:0; border-right:0; border-top:0;
  background:transparent; cursor:pointer; text-align:left; font:inherit; color:inherit;
  transition:background var(--duration-100) var(--ease-in-out); }
button.nv-table-row:hover, button.nv-table-row.is-hover { background:var(--bg-base-hover); }
.nv-table-row-action { grid-column:3; grid-row:1 / 3; align-self:center; }
/* Sits under the results card in the accent, chevron first — sampled #DDEF6C in
   licensing/v9/Dark/Resultschat.png (chevron x 620→630, label ink from 645,
   16px below the card's bottom border at y 665). */
.nv-results-wrap { display:flex; flex-direction:column; gap:var(--spacing-16); }
.nv-results-more { display:flex; align-items:center; gap:var(--spacing-8);
  align-self:flex-start; padding:0; border:0; background:none; cursor:pointer;
  color:var(--fg-interactive); font:400 14px/20px var(--font-body); }
.nv-results-more:hover { color:var(--fg-interactive-hover); }
.nv-results-more svg { width:16px; height:16px; flex:0 0 16px;
  transition:transform var(--duration-200) var(--ease-in-out); }
.nv-results-more.is-open svg { transform:rotate(180deg); }
@media (prefers-reduced-motion: reduce) {
  .nv-results-more svg { transition:none; }
}
.nv-link svg { width:12px; height:12px; flex:0 0 12px; }
/* Grouped results (incubation only — licensing's list is flat and keeps .nv-results'
   own card). The v9 incubation frames put each collection's header ON THE CANVAS and
   give the rows their own card: strip x 296→298 / y 370→386 (2 × 16), card top border
   y 402 (16 below the strip), next header's strip y 640 (16 below the card).
   design/context/incubation/v9/{Dark,Light}/Results.png + Resultschat.png. */
.nv-results-grouped { border:0; border-radius:0; overflow:visible;
  display:flex; flex-direction:column; gap:var(--spacing-16); }
.nv-results-group-head { position:relative; display:flex; align-items:center;
  gap:var(--spacing-8); padding-left:calc(var(--stroke-2) + var(--spacing-8)); }
/* The strip stays brand lime in BOTH modes — sampled #DDEF6C at x 296→298 in the light
   frame too, like the report kickers and unlike the sidebar's selected nav strip. */
.nv-results-group-head::before { content:""; position:absolute; left:0; top:0;
  width:var(--stroke-2); height:16px; background:var(--brand-200); }
.nv-results-group-inv, .nv-results-group-sep, .nv-results-group-label {
  font:400 12px/16px var(--font-code); text-transform:uppercase; }
.nv-results-group-inv { color:var(--fg-subtle); }
.nv-results-group-sep, .nv-results-group-label { color:var(--fg-muted); }
.nv-results-group-label { flex:1; min-width:0; overflow:hidden;
  text-overflow:ellipsis; white-space:nowrap; }
.nv-results-group-body { margin-top:var(--spacing-16);
  border:var(--stroke-1) solid var(--border-base); border-radius:var(--radius-4);
  overflow:hidden; transition:background var(--duration-100) var(--ease-in-out),
  border-color var(--duration-100) var(--ease-in-out); }
.nv-results-group-body .nv-table-row:last-child { border-bottom:0; }
.nv-results-group.is-clickable { cursor:pointer; }
/* Hover lands on the card, not the header: the header sits on the canvas in the frames,
   so a block-wide fill would paint a band no frame draws. Neutral ramp only. */
.nv-results-group.is-clickable:hover .nv-results-group-body,
.nv-results-group.is-hover .nv-results-group-body { background:var(--bg-base-hover);
  border-color:var(--border-base-hover); }
.nv-results-group.is-clickable:hover .nv-results-group-eval,
.nv-results-group.is-hover .nv-results-group-eval { color:var(--fg-interactive-hover); }

/* Toast */
.nv-toast { position:fixed; left:50%; bottom:var(--spacing-24); z-index:200;
  transform:translateX(-50%) translateY(var(--spacing-8)); opacity:0;
  padding:var(--spacing-8) var(--spacing-16); border-radius:var(--radius-4);
  background:var(--bg-component); border:var(--stroke-1) solid var(--border-subtle);
  box-shadow:var(--elevation-menu); color:var(--fg-subtle);
  font:400 14px/20px var(--font-body);
  transition:opacity var(--duration-200) var(--ease-out),
             transform var(--duration-200) var(--ease-out); }
.nv-toast.is-on { opacity:1; transform:translateX(-50%) translateY(0); }

/* ---- 5.3 · Artifact pane + modal --------------------------------------- */
.nv-report-pane { display:none; flex:0 0 var(--nv-split); min-width:360px;
  flex-direction:column; background:var(--bg-base);
  border-left:var(--stroke-1) solid var(--border-subtle); }
.nv-page-chat.is-split .nv-report-pane { display:flex; }
/* Maximised: the pane takes the whole right region and inherits the surface corner. */
.nv-page-chat.is-max .nv-chat-col,
.nv-page-chat.is-max .nv-split-handle { display:none; }
.nv-page-chat.is-max .nv-report-pane { flex:1 1 auto; border-left:0;
  border-top-left-radius:var(--radius-8); }
.nv-main:has(.nv-page-chat.is-max) .nv-panel-toggle { display:none; }
.nv-art-expand-in { display:none; }
.nv-page-chat.is-max .nv-art-expand-out { display:none; }
.nv-page-chat.is-max .nv-art-expand-in { display:inline; }
.nv-report-scroll { flex:1; min-height:0; overflow-y:auto; }
/* Pane inset = 40px. Measured on licensing/v9/Dark/Results.png: the stat meter
   and every rule run x 1032.5 → 1688 inside a pane whose edges are 991.5 / 1728.
   The 43rem measure still caps the line length when the pane is maximised. */
/* The 40px inset is OUTSIDE the 43rem measure: at the frames' split width the pane
   runs x 991.5→1728 and the content runs 1032.5→1688 (655.5), i.e. the report fills
   the pane minus 40 each side. With max-width:43rem on the box itself the content
   was capped at 608 and every element sat ~24px in from the frame. Widening the cap
   by the two insets keeps the 43rem *reading measure* on a maximised pane. */
.nv-report-pane .nv-report { padding-inline:var(--spacing-40);
  max-width:calc(43rem + var(--spacing-40) + var(--spacing-40)); }
/* Section rules are full-bleed in the pane — Results.png's separators run the whole
   pane width (x 992 → 1728 at #272727 = --border-subtle), not the 40px-inset measure. */
.nv-report-pane .nv-report-section { margin-inline:calc(-1 * var(--spacing-40));
  padding-inline:var(--spacing-40); }
/* No hairline under the pane's chrome row: scanning x 1000→1720 at y 58→72 in
   Light/Results.png and Dark/Results.png returns pure canvas — the frames draw the
   print/copy row straight on the pane. Scoped to the pane so the companies/people
   pages (no v9 frame) keep their header rule. */
.nv-report-pane .nv-details-header { flex:none; border-bottom:0; }
.nv-visually-hidden { position:absolute; width:1px; height:1px; overflow:hidden;
  clip:rect(0 0 0 0); clip-path:inset(50%); white-space:nowrap; }
.nv-art-load, .nv-art-error { padding:var(--spacing-24); color:var(--fg-muted);
  font:400 14px/20px var(--font-body); }

/* The backdrop and the dialog stay siblings — agent.js closes on a backdrop
   click, and nesting would let a click inside the dialog bubble out to it. */
.nv-modal-overlay { z-index:100; }
.nv-modal { position:fixed; left:50%; top:50%; z-index:101;
  transform:translate(-50%, -50%); }
.nv-modal-overlay.is-closing, .nv-modal.is-closing { animation:nv-fade-out var(--modal-close) var(--ease-in); }
.nv-modal[hidden], .nv-modal-overlay[hidden] { display:none; }
/* The dialog is tabindex="-1" and agent.js focuses it on open purely to scope the
   reading order — Chrome's default focus ring then draws a blue outline round the
   whole dialog, which no v9 email frame has and which reads loudly on the light
   #F5F5F5 surface. Controls inside keep their own focus styling. */
.nv-modal:focus { outline:0; }
/* Header and footer stay put; only the document scrolls (licensing/06). */
.nv-modal { overflow:hidden; }
.nv-modal .nv-modal-body { gap:0; min-height:0; overflow-y:auto; }
.nv-modal .nv-modal-header, .nv-modal .nv-modal-footer { flex:none; }
/* In the modal the dialog's own padding is the document's inset (the v9 email frame
   puts the letterhead rule at x 528→1200 inside a 504→1224 dialog = 24 each side),
   so the report must not add a second one. */
.nv-modal-body .nv-report { padding-top:0; padding-inline:0; max-width:none; }
/* Inline SVGs carry no intrinsic size — as flex items they would collapse to 0. */
.nv-modal-header-actions button svg, .nv-chat-header button svg,
.nv-details-header button svg, .nv-btn svg, .nv-next-btn svg { width:16px; height:16px;
  flex:0 0 16px; }
/* ---- Internal-note disclosure -----------------------------------------
   The chevron sits beside the recipient's name, not with the header's Copy/Close
   actions: it belongs to the name it qualifies ("this licensee has CRM history"),
   and it is absent entirely when there is no note. Pulled back 4 off the header
   row's 12 gap so it reads as part of the name, not as a third action. */
.nv-modal-note-toggle { display:inline-flex; align-items:center; justify-content:center;
  flex:0 0 auto; margin-left:calc(-1 * var(--spacing-4)); padding:var(--spacing-4);
  border:0; background:transparent; color:var(--fg-muted); cursor:pointer;
  border-radius:var(--radius-4);
  transition:background var(--duration-100) var(--ease-in-out), color var(--duration-100) var(--ease-in-out); }
.nv-modal-note-toggle[hidden] { display:none; }
.nv-modal-note-toggle:hover { background:var(--bg-button-transparent-hover); color:var(--fg-subtle); }
.nv-modal-note-toggle:focus-visible { outline:var(--stroke-1) solid var(--border-active); outline-offset:1px; }
.nv-modal-note-toggle[aria-expanded="true"] { color:var(--fg-subtle); }
.nv-modal-note-toggle svg { width:16px; height:16px; flex:0 0 16px;
  transition:transform var(--duration-200) var(--ease-in-out); }
/* Points down at the folded note and flips up once it is showing — the same
   chevron-rotation the collapsed thinking steps use. */
.nv-modal-note-toggle[aria-expanded="true"] svg { transform:rotate(180deg); }

/* The 0fr→1fr grid row lets the note animate to its own height without a hardcoded
   max-height (same mechanism as .nv-thinking-anim). The dialog is a 16-gap flex
   column, so a collapsed slot would still cost one gap: the slot eats its leading
   gap with a negative margin and gives it back as padding INSIDE the clipped row,
   which keeps header→letterhead at 16 collapsed and header→note at 16 open. */
.nv-modal-noteslot { display:grid; grid-template-rows:1fr;
  margin-top:calc(-1 * var(--spacing-16));
  transition:grid-template-rows var(--duration-200) var(--ease-in-out); }
.nv-modal-noteslot.is-collapsed { grid-template-rows:0fr; }
/* The 16 rides on the note's own margin, not the clipper's padding: padding sits on
   the border box and would survive the 0fr row, leaving 16px of dead space above the
   letterhead while collapsed. overflow:hidden makes the clipper a BFC, so the margin
   cannot collapse out of it either. */
.nv-modal-noteslot > div { min-height:0; overflow:hidden; }
.nv-modal-noteslot > div > * { margin-top:var(--spacing-16); }
.nv-modal-noteslot:empty { display:none; }
@media (prefers-reduced-motion: reduce) {
  .nv-modal-noteslot { transition:none; }
}
/* Recipient avatar (email-modal header) — Figma Avatar component's Content=Icon
   variant: 28px neutral circle, muted generic person glyph. Verified via Figma MCP
   get_variable_defs on 2128:12662: background/background-component-press (#525252)
   + foreground/foreground-muted (#7a7a7a) — closest existing tokens are
   --bg-component-press / --fg-muted. */
.nv-modal-avatar { display:inline-flex; align-items:center; justify-content:center;
  width:28px; height:28px; flex:0 0 28px; border-radius:var(--radius-999);
  background:var(--bg-component-press); color:var(--fg-muted); }
.nv-modal-avatar svg { width:16px; height:16px; }
/* CRM / non-email documents arm neither footer control — drop the rule with them. */
.nv-modal-footer:not(:has(button:not([hidden]))) { display:none; }
.nv-modal-footer-status[data-state="reconnect"]::before { background:var(--fg-warning); }
.nv-modal-footer-status[data-state="checking"]::before { background:var(--fg-muted); }
.nv-modal-footer-status { border:0; background:transparent; cursor:default; }
.nv-modal-footer-status[data-state="reconnect"] { cursor:pointer; color:var(--fg-subtle); }

/* ---- Internal-notes dialog (CRM card) ---------------------------------- */
/* Narrower than the email dialog: modal-Note.png measures 560 × 568 where
   modal-Email.png measures 720. agent.js arms the class per open, before the fetch,
   so the dialog never resizes under the loading line. */
.nv-modal--note { width:min(560px, 90vw); }
/* The note document runs on a 24 rhythm, and clears the dialog's chrome by 24 top
   (the callout starts 40 under a 28px header row = the modal's own 16 gap + 24) and
   by 8 at the foot, on top of the dialog's 16. */
.nv-modal-body .nv-report[data-kind="crm"] { gap:var(--spacing-24);
  padding:var(--spacing-24) 0 var(--spacing-8); }
.nv-crm-section { display:flex; flex-direction:column; gap:var(--spacing-12); }
/* Dashed --border-base, 24 either side — the same half-covered hairline the
   letterhead rule draws, one contrast step up. No rule above the first section: the
   callout is already boxed off. */
.nv-crm-section + .nv-crm-section { padding-top:var(--spacing-24);
  border-top:var(--stroke-1) dashed var(--border-base); }
/* Section labels set as body-12 muted — the frame runs "Relationship", "Engagement"
   and "Latest need" at the same weight and colour as the contact's role. They stay
   <h3> so the document keeps its outline (and the modal's Copy button keeps emitting
   them as headings); this restates past `.nv-report h3` (0,1,1), which would
   otherwise render them at heading-20. */
.nv-report[data-kind="crm"] .nv-crm-label { font:400 12px/16px var(--font-body);
  color:var(--fg-muted); text-align:left; }
/* Prose sets ragged and in --fg-subtle here (the frame samples #FFFFFF end to end),
   not the justified --fg-base of a full report pane: at a 512px measure justification
   opens visible rivers. */
.nv-report[data-kind="crm"] p { color:var(--fg-subtle); text-align:left; }
.nv-crm-contact { display:flex; align-items:center; gap:var(--spacing-12); }
.nv-crm-contact-name { font:500 14px/20px var(--font-body); color:var(--fg-subtle); }
.nv-crm-contact-role { margin-top:var(--spacing-4); font:400 12px/16px var(--font-body);
  color:var(--fg-muted); }

/* ---- 5.4 · nv-report — the document layout ----------------------------- */
/* Content sits directly on the pane background; sections are split by hairlines,
   never by cards. Reading measure 43rem, centred. */
.nv-report { display:flex; flex-direction:column; gap:var(--spacing-16);
  max-width:43rem; margin-inline:auto;
  padding:var(--spacing-24) var(--spacing-24) var(--spacing-48);
  color:var(--fg-base); font:400 14px/20px var(--font-body); }
/* h1 = heading-28. Cap height measured at 20.75px in all three v9 report frames
   (Results.png "Tactile sensing & electronic skin", Shortlist.png "Candidate
   investors", Outreach.png "Investor outreach pack" — ink tops all at y 127.5,
   0.72 × 28 = 20.2), i.e. one step above the 24 this used to carry. */
.nv-report h1 { font:500 28px/36px var(--font-heading); color:var(--fg-subtle); }
/* h2 and h3 are both heading-20 in the v9 report: "Market", "Matching company
   sectors" and the angle name "Tactile sensing / e-skin" all measure 18.25px of ink
   over ascender+descender in Results.png, i.e. 20px on the heading ramp. */
.nv-report h2 { font:500 20px/28px var(--font-heading); color:var(--fg-subtle); }
.nv-report h3 { font:500 20px/28px var(--font-heading); color:var(--fg-subtle); }
.nv-report p { font:400 14px/20px var(--font-body); color:var(--fg-base); }
/* Running text sets justified, for a tidy right edge on the report's single reading
   measure. Only prose: the eyebrow is a <p> but lays out as a flex row, so
   text-align never reaches it, and metadata rows, cites, labels and ledger cells are
   not <p> at all. The last line stays ragged (text-align-last defaults to auto).
   No `hyphens: auto` — at this measure the word gaps stay even without it, and the
   report is full of terms that read badly broken (anti-CD19-41 BB-003ζ). */
.nv-report p, .nv-report li, .nv-report footer { text-align:justify; }
.nv-report a { color:var(--fg-interactive); text-decoration:none; }
.nv-report a:hover { color:var(--fg-interactive-hover); text-decoration:underline; }
.nv-report strong { font-weight:500; color:var(--fg-subtle); }
.nv-report em { font-style:normal; color:var(--fg-muted); }
.nv-report ul, .nv-report ol { display:flex; flex-direction:column; gap:var(--spacing-4);
  padding-left:var(--spacing-16); }
.nv-report li { font:400 14px/20px var(--font-body); color:var(--fg-base); }
/* A pulled source quote is neither an action nor a caution, so its rule is neutral:
   lime codes meaning in this system and amber is spoken for by Highlight-text. Same
   16-from-the-edge measure as that component. */
.nv-report blockquote { display:flex; flex-direction:column; gap:var(--spacing-4);
  border-left:var(--stroke-2) solid var(--border-base);
  padding-left:calc(var(--spacing-16) - var(--stroke-2)); }
.nv-report cite { font:400 12px/16px var(--font-code); color:var(--fg-muted); font-style:normal; }
.nv-report details { display:flex; flex-direction:column; gap:var(--spacing-8); }
.nv-report summary { cursor:pointer; list-style:none; font:500 12px/16px var(--font-code);
  text-transform:uppercase; letter-spacing:.04em; color:var(--fg-muted); }
.nv-report summary::-webkit-details-marker { display:none; }
.nv-report summary:hover { color:var(--fg-subtle); }
.nv-report footer { padding-top:var(--spacing-16);
  border-top:var(--stroke-1) solid var(--border-subtle);
  color:var(--fg-muted); font:400 12px/16px var(--font-body); }
/* The evaluation report's provenance block is not ruled off and not stepped down:
   Results.png runs it at body-14 (20px pitch, ink 3309.5 / 3330.25 / 3350.25) in
   --fg-base (#E0E0E0), 24 under the last ledger card (3281 → 3305.5) — and the
   full-bleed scan finds only three rules on the page, none above it. */
.nv-report[data-kind="report"] footer { margin-top:var(--spacing-8);
  padding-top:0; border-top:0;
  color:var(--fg-base); font:400 14px/20px var(--font-body); }
.nv-report-head { display:flex; flex-direction:column; gap:var(--spacing-8); }
/* Report kicker — a lime strip, then the mono muted label. Measured off
   licensing/v9/Dark/Results.png (▎EVALUATION), Results/Shortlist.png (▎SHORTLIST)
   and Results/Outreach.png (▎OUTREACH): the strip is 2px × 16px at the content's
   left edge (x 1032.5→1034.5, y 88→104) with the label's box 4px after it.
   Scoped to .nv-report so the shared .nv-eyebrow keeps its plain form on the
   hero and on the companies/people pages. */
/* The eyebrow is a <p>, so `.nv-report p` (0,1,1) was out-specifying `.nv-eyebrow`
   (0,1,0) and rendering the kicker as 14px body ink; the frames show mono-12 at
   --fg-muted, so restate it here. */
.nv-report .nv-eyebrow { align-items:center; gap:var(--spacing-8);
  font:500 12px/16px var(--font-code); color:var(--fg-muted); }
.nv-report .nv-eyebrow::before { content:""; flex:0 0 var(--stroke-2);
  width:var(--stroke-2); height:16px; background:var(--brand-200); }
/* The strip-to-label gap is 8, not 4: in Results.png the strip ends at x 1034.5 and
   the E of EVALUATION inks at 1043.5, and the label's own mono left bearing is ~1px
   at 12px (its 10 glyphs span 1043.5→1113.75 = a 7.2px advance). */
/* The kicker sits further off the headline than the head's own 8px rhythm — ink gap
   104 → 127.5 in the frame against the 15 an 8px gap renders. */
.nv-report .nv-eyebrow + h1 { margin-top:var(--spacing-8); }
/* 40px above the first line of a section, measured off Results.png: the rules land
   at y 619.5 and 1041.5 and the next block's ink at 664.25 / 1088.75, i.e. ~40 once
   each face's ink offset is taken off. (Was 24.) */
/* …and 40 BELOW the previous section too: the frames' rules sit 39.5–42 under the
   preceding block (card bottom 1002 → rule 1041.5, commentary bottom 1439.5 → rule
   1479.5), i.e. 24 on top of .nv-report's own 16px gap. */
/* Section children run on a 16 rhythm, not 12 — the shortlist frame sets its tier
   row's box bottom at 352 and the ledger card's top edge at 368. */
.nv-report-section { display:flex; flex-direction:column; gap:var(--spacing-16);
  padding-top:var(--spacing-40); border-top:var(--stroke-1) solid var(--border-subtle); }
/* The evaluation report is the looser document of the two: h2 → tiles 1109.9 → 1134,
   tiles → commentary 1296 → 1319.6, lead-in rule → first block 1628.5 → 1652 and
   block → block 1992 → 2016 all measure 24 in Results.png, and its sections clear
   40 either side of their rule (card bottom 1002 → rule 1041.5). */
.nv-report[data-kind="report"] .nv-report-section { gap:var(--spacing-24); }
.nv-report[data-kind="report"] > .nv-report-section { margin-top:var(--spacing-24); }
/* A section's lead-in is ruled off from its blocks with the same 2-on/2-off dashed
   hairline the leads frames use — Results.png y 1627.5, sitting 24 under the
   standfirst and 24 above the first angle row, i.e. on the section's own rhythm. */
/* Painted, not `border-top: 1px dashed`: Chrome draws a 1px dashed border on a 3-on
   / 2-off period, where the frame's rule runs an exact 2 and 2 (Results.png y 1627.5
   alternates 8px of #272727 and 8px of canvas at 4×). */
.nv-report hr { height:var(--stroke-1); margin:0; border:0;
  background-image:repeating-linear-gradient(to right,
    var(--border-subtle) 0 2px, transparent 2px 4px); }
/* Body ink, not muted: the verdict line under the headline stat and the
   "Where the collection maps…" lead-in both sample #E0E0E0 dark / #292929 light
   (= --fg-base) in design/context/incubation/v9/*/Results.png. Only the per-angle
   traction line inside a .nv-report-block is muted (#7A7A7A / #8F8F8F). */
.nv-report-sub { color:var(--fg-base); }
.nv-report-block .nv-report-sub { color:var(--fg-muted); }
/* Reference lines — patent number, venue, legal status — are set in the BODY face in
   the frames, not the mono one: "US 11,474,601 B2 · Science Robotics 4(32), eaax2198
   — ACES · Active (expires ~2039)" measures 5.9px per character at 12px, which is
   Inter, not a monospace (7.2 at the same size). Same for the member rows' numbers.
   Mono stays for labels, kickers and code. */
.nv-report-meta { display:flex; flex-wrap:wrap; align-items:center; gap:var(--spacing-8);
  font:400 12px/16px var(--font-body); color:var(--fg-muted); }
.nv-report-tags { display:flex; flex-wrap:wrap; gap:var(--spacing-8); }
.nv-report-label { font:500 12px/16px var(--font-code); text-transform:uppercase;
  letter-spacing:.04em; color:var(--fg-muted); }
/* Stat readouts sit on the full content measure and share it equally — the v9
   frames' single stat runs its meter the whole width (x 1032.5 → 1688), so a
   flex row sized to content (what this used to be) left the meters stub-short.
   Two readouts sit on an 80px gutter with a dashed rule down its middle: in the
   licensing evaluate frame the columns measure 290.4 each (x 109→585 and 717→1193
   at a 1.639 scale) either side of a 132px gutter with the rule at its centre
   (650→652). The rule is drawn from the column rather than padded into it — padding
   would come out of that column's own 290 and leave the two unequal. */
.nv-report-stats { display:grid; grid-template-columns:repeat(auto-fit, minmax(180px, 1fr));
  column-gap:calc(2 * var(--spacing-40)); row-gap:var(--spacing-24); }
.nv-report-stats > .nv-info + .nv-info { position:relative; }
.nv-report-stats > .nv-info + .nv-info::before { content:""; position:absolute;
  left:calc(-1 * var(--spacing-40)); top:0; bottom:0; width:var(--stroke-1);
  background:repeating-linear-gradient(to bottom,
    var(--border-subtle) 0 2px, transparent 2px 4px); }
/* The stat's label is body-12 against the report's body-14 — sampled proportional,
   sentence case, --fg-muted, one step down from the prose it sits above. */
.nv-report-stats .nv-info-headline { font:400 12px/16px var(--font-body);
  text-transform:none; letter-spacing:normal; }
/* The readout breathes: under the body-12 label the value hangs on a 16px box gap
   (label box ends 266.6, the value box opens at 281.5 in the licensing frame) and
   the meter follows 8 under it (317.5 → 324.3). */
.nv-report-stats .nv-info > .nv-h28,
.nv-report-stats .nv-info > .nv-stat-row { margin-top:var(--spacing-12); }
.nv-report-stats .nv-meter { margin-top:var(--spacing-4); }
/* Score readouts carry their band on the same line, pushed to the column's right
   edge and set in the meter's own colour — "87%  …  STRONG" in the frame. */
.nv-stat-row { display:flex; align-items:baseline; justify-content:space-between;
  gap:var(--spacing-12); }
.nv-stat-row .nv-h28 { margin-top:0; }
.nv-stat-band { flex:0 0 auto; font:500 12px/16px var(--font-code);
  text-transform:uppercase; color:var(--fg-info); }
/* Whatever follows the headline clears 24, not the head's own 8 — the readout label
   inks at 182.75 under an H1 whose box ends at 157 in Results.png, and the
   shortlist frame's standfirst starts at 180.5 under the same 121→157 box. */
.nv-report-head > h1:not(:last-child) { margin-bottom:var(--spacing-16); }
/* Same 24 above the identity row, whether it follows the meter (254 → 278 in
   Results.png) or the standfirst (240.5 → 264 in Results/Shortlist.png). */
.nv-report-head > .nv-report-collection-head { margin-top:var(--spacing-16); }

/* Segmented level meter — the v9 report's stat readout. Measured on
   licensing/v9/Dark/Results.png ("Investor interest / High"): three equal
   segments across the content measure, 8px apart (1245.5→1253.5 and
   1466.75→1474.75), 2px tall (y 252→254), square ends. Filled segments sample
   #DC9404 (amber-400) in the dark frame and #FCC85F (amber-200) in the light one
   — i.e. --fg-warning once its per-mode ramp is corrected (see the token block).
   The empty segment samples #323232 dark / #DDDDDD light, both ≈13 % neutral;
   --border-base (16 %) reproduces them to within 8/255. */
.nv-meter { display:flex; gap:var(--spacing-8); }
.nv-meter-seg { flex:1 1 0; height:var(--stroke-2); border-radius:var(--radius-0);
  background:var(--border-base); }
.nv-meter-seg.is-on { background:var(--fg-warning); }
/* Continuous variant — the same 2px rule and the same empty-track neutral, but one
   unbroken fill in --fg-info instead of three amber blocks. The colour separates the
   two readouts rather than grading one: a 0-100 score reads as a proportion (blue,
   continuous) where a three-band qualitative call reads as steps (amber, segmented). */
.nv-meter--continuous { display:block; height:var(--stroke-2);
  background:var(--border-base); }
.nv-meter--continuous > .nv-meter-seg { display:block; height:100%;
  background:var(--fg-info); }
/* Ledger rows live in their own hairline card — every v9 report frame boxes them
   (Results/Shortlist.png: card x 1032.5→1688, top edge y 368.5 at --border-base,
   rows 68 tall with the index at the card's 16px inset and the last row's divider
   suppressed). This is the "left open" item both earlier passes flagged. */
.nv-report-rows { display:flex; flex-direction:column;
  border:var(--stroke-1) solid var(--border-base); border-radius:var(--radius-4);
  overflow:hidden; }
.nv-report-rows .nv-table-row:last-child { border-bottom:0; }
/* Restated inside .nv-report for the same reason .nv-eyebrow is: on a <p> the
   0,1,1 of `.nv-report p` out-specifies this 0,1,0 and the note came out as
   body-14 --fg-base. The frame's group note is 12px --fg-muted — "One appetite
   read across the whole collection…" spans 1033→1646.5 at 5.68px/char in #7A7A7A. */
.nv-report-note, .nv-report p.nv-report-note { color:var(--fg-muted);
  font:400 12px/16px var(--font-body); }
/* No separator between angle blocks — scanning x 1400 between the first block's card
   (bottom border y 1991) and the next LEAD ANGLE label finds only canvas. */
/* No padding of its own — the section's 24px rhythm already sets block-to-block
   (card bottom 1992 → the next angle row 2016). Inside, the angle row → name →
   traction line all run on 8 (1672 → 1679.9, 1707.9 → 1715.6). */
.nv-report-block { display:flex; flex-direction:column; gap:var(--spacing-8); }
/* …except the ledger card, which drops 24 under the traction line (1755.6 → 1780). */
.nv-report-block > .nv-report-rows, .nv-report-block > blockquote { margin-top:var(--spacing-16); }
.nv-report-row { display:flex; align-items:baseline; flex-wrap:wrap; gap:var(--spacing-8); }
.nv-report-row-name { font:500 14px/20px var(--font-body); color:var(--fg-subtle); }
/* Row actions in a report are quiet: the v9 outreach frame draws them 36 × 36-high
   at 14px with a --border-base hairline and a *muted* label — sampled #7A7A7A on
   both "Proposal" and "Email" (Results/Outreach.png, x 1516→1599 / y 395→431, text
   ink 1529→1586). The lime an <a class="nv-btn"> would otherwise inherit from
   .nv-report a is wrong here — these are controls, not links. */
.nv-report .nv-btn--transparent { color:var(--fg-muted); }
.nv-report .nv-btn--transparent:hover { color:var(--fg-base); text-decoration:none; }
.nv-report-tier { display:flex; align-items:center; gap:var(--spacing-8); }
/* Scoped, not on the shared .nv-tag base — that component also carries proper-noun
   values elsewhere (company/person names, filter chips) that must stay as authored.
   Confirmed against design/context/licensing/v9/Dark/Results/Outreach.png: the tier
   badge itself ("STRONG") is uppercase, but the tag's icon+"Public (NYSE: …)"
   ownership pill on each row is not — so this only touches the badge span. */
.nv-report-tier > .nv-tag { text-transform:uppercase; letter-spacing:.04em; }
/* muted, not base: "University-IP / deep-tech translational" samples #7A7A7A on the
   dark shortlist frame and #8F8F8F on the light one — the --fg-muted pair. */
.nv-report-tier-label { flex:1; min-width:0; font:400 14px/20px var(--font-body); color:var(--fg-muted); }
/* Dashed, not solid: the email frame's letterhead rule (y 244.5 → 245.5,
   x 528 → 1200) covers exactly half its run — 1344 of 2688 subpixels. */
.nv-report-letterhead { display:flex; align-items:center; justify-content:space-between;
  gap:var(--spacing-16); padding-bottom:var(--spacing-16);
  border-bottom:var(--stroke-1) dashed var(--border-subtle); }
/* 18, not 14: in the email frame the wordmark's ink stands level with the subject's
   cap height (0.72 x 24 ~ 17), so the two marks share one weight of ink down the
   document's left edge. */
.nv-report-letterhead .nusx-logo { height:18px; }
/* The affiliation line runs mono-10 — one step below the documented 12/14/16 mono
   ramp, but it is what the email frame carries, and it keeps the line subordinate to
   the wordmark opposite it. Scoped to the letterhead: .nv-report-label stays 12
   everywhere else it is used (Anni, 2026-08-20). */
.nv-report-letterhead .nv-report-label { font-size:10px; }
.nv-report-body { display:flex; flex-direction:column; gap:var(--spacing-16); }
/* The letter sets at body-14, one step below the 16 it used to carry: measured off
   the "Create email draft" frame, where the prose reads a step under the modal's own
   16px recipient name (Anni, 2026-08-20). */
.nv-report-body p { font:400 14px/20px var(--font-body); }
.nv-report-num { flex:0 0 auto; font:400 12px/16px var(--font-code); color:var(--fg-muted); }
/* Asset-collection card — one --bg-component card holding the family's assets as
   full-width rows, not chips. Measured on licensing/v9/Dark/Results.png: card
   x 1032.5→1688 / y 314→516 at #1F1F1F, 4px inset; rows 62px tall, 4px apart;
   the selected row is #292929 (--bg-component-hover) with a 2px lime strip on its
   left edge that does NOT displace the label (both rows' text ink lands at
   x ≈1049), so the strip overlays the row's 12px inset rather than adding to it. */
.nv-report-collection { display:flex; flex-direction:column; gap:var(--spacing-4);
  padding:var(--spacing-4); border-radius:var(--radius-4); background:var(--bg-component); }
.nv-report-member { position:relative; display:flex; flex-direction:column; gap:2px;
  cursor:pointer; padding:var(--spacing-12); border:0; border-radius:var(--radius-2);
  background:transparent; text-align:left; color:var(--fg-base);
  font:400 14px/20px var(--font-body);
  transition:background var(--duration-100) var(--ease-in-out); }
.nv-report-member:hover { background:var(--bg-base-hover); }
/* The selected row is --bg-field with a --fg-interactive strip: it samples
   #292929 + lime in Dark/Results.png and #FFFFFF + #8F8F8F at the same
   coordinates in Light/Results.png — the bg-field and fg-interactive pairs,
   not bg-component-hover (#EBEBEB in light, i.e. darker than the card) and not
   raw brand. */
.nv-report-member.is-active { background:var(--bg-field); color:var(--fg-subtle); }
.nv-report-member.is-active::before { content:""; position:absolute; left:0; top:0; bottom:0;
  width:var(--stroke-2); background:var(--fg-interactive); }
/* Body face, not mono — see the note on .nv-report-meta. */
.nv-report-member-pno { font:400 12px/16px var(--font-body); color:var(--fg-muted); }
.nv-dot { display:inline-block; flex:0 0 6px; width:6px; height:6px;
  border-radius:var(--radius-999); background:var(--fg-muted); }
.nv-dot--success { background:var(--fg-success); }
.nv-dot--warning { background:var(--fg-warning); }

/* ---- v9 incubation report shapes -------------------------------------------
   All measurements below are from design/context/incubation/v9/{Dark,Light}/
   (4× exports, divided by 4, sampled with PIL getpixel). The pane content measure
   runs x 1032.5 → 1688. */

/* Collection identity row: inventor + programme left, the COLLECTION tag pinned to
   the content's right edge (tag box x 1600→1688, y 278→298). Name --fg-subtle,
   programme --fg-muted, both body-14. */
.nv-report-collection-head { display:flex; align-items:center; gap:var(--spacing-4);
  font:400 14px/20px var(--font-body); color:var(--fg-muted); }
.nv-report-collection-name { flex:0 0 auto; color:var(--fg-subtle); }
.nv-report-collection-topic { min-width:0; overflow:hidden; text-overflow:ellipsis;
  white-space:nowrap; }
/* COLLECTION / MATCHES THIS IP / 94% RELEVANCE all read uppercase in the frames
   (the ownership pill on a licensing lead row still does not — see .nv-report-tier). */
.nv-report-collection-head > .nv-tag,
.nv-report-row > .nv-tag { text-transform:uppercase; }
.nv-report-collection-head > .nv-tag { margin-left:auto; flex:0 0 auto; }
/* The row hugs the block it labels: 16 to the card below it, against the section's
   own 24 (identity row box ends 60.8, card top edge 76.5 in the evaluate frame —
   the same 16 the shortlist frame puts between its tier row and its ledger card). */
.nv-report-section > .nv-report-collection-head {
  margin-bottom:calc(var(--spacing-16) - var(--spacing-24)); }
/* When the identifier is a link out to the source record it keeps the row's body-14
   and takes the interactive colour, so .nv-report-collection-name's --fg-subtle
   must not claim it. */
.nv-report-assetlink { flex:0 0 auto; }
/* The two leads frames rule this row off with a 2-on/2-off dashed hairline at
   --border-subtle, 24px below it (Results/Shortlist.png y 307.5, x from 1032.5). */
.nv-report-collection-head--ruled { padding-bottom:var(--spacing-24);
  border-bottom:var(--stroke-1) dashed var(--border-subtle); }

/* The frontmatter is a card in the v9 report, not flowing prose, and it is set a step
   DENSER than the document around it. Every box in incubation/v9/Dark/Results.png,
   read against the card's 724→1002 border: 16 padding, 12 between blocks, title
   16/24 --fg-base (ink 744→759), meta 12/16 --fg-muted glued straight under it (ink
   767→780), abstract 12/16 --fg-subtle on a 16 pitch (ink 795…873), "Key technology"
   12/16 --fg-muted, its line 12/16 --fg-subtle, the link mono-12 brand. Those add up
   to the frame's 278 exactly; at the document's 14/20 the card ran 60 tall. */
.nv-report-card { display:flex; flex-direction:column; gap:var(--spacing-12);
  padding:var(--spacing-16); border:var(--stroke-1) solid var(--border-base);
  border-radius:var(--radius-4); }
.nv-report-card h2 { font:400 14px/20px var(--font-body); color:var(--fg-base); }
/* The card runs one step down from the report: its prose measures 5.9px/char over
   104 characters (x 1050→1662.5) on a 16px pitch (ink tops 795 / 811.75 / 827.75),
   i.e. body-12, against the 14/20 the surrounding commentary keeps. */
.nv-report-card p { color:var(--fg-subtle); font:400 12px/16px var(--font-body); }
/* Its identity line is proportional, not the mono .nv-report-meta carries elsewhere:
   "US 11,474,601 B2 · Science Robotics 4(32), eaax2198 — ACES · Active (expires
   ~2039)" spans 1050.5→1538.75 = 5.95px/char, where mono-12 would fix every advance
   at 7.2 (as VIEW ON GOOGLE PATENTS below it does). It sits 4 under the title. */
.nv-report-card .nv-report-meta { display:block; font-family:var(--font-body); }
.nv-report-card h2 + .nv-report-meta { margin-top:calc(var(--spacing-4) - var(--spacing-12)); }
/* "Key technology" is sentence-case body-14 muted in the frame, not the mono eyebrow,
   and its value hangs the card's own 12 off it (label box ends 912.75, the value
   inks at 924.5) rather than .nv-info's default 4. */
.nv-report-card .nv-info { gap:var(--spacing-12); }
.nv-report-card .nv-info-headline { font:400 14px/20px var(--font-body);
  text-transform:none; letter-spacing:normal; }

/* Market figures: one bordered card split into equal columns by hairlines
   (x 1032.5→1688 / y 1134→1296, dividers at 1251 / 1469; label --fg-muted,
   value --fg-subtle, note --fg-base at body-14). The tile sizes to its content on
   an even 16 inset — the frame's 160 was a floor that left the short tiles with a
   ~60px well under the caption, reading as a broken column rather than a figure. */
.nv-report-stats--tiles { grid-template-columns:repeat(3, minmax(0, 1fr)); gap:0;
  border:var(--stroke-1) solid var(--border-base); border-radius:var(--radius-4);
  overflow:hidden; }
.nv-report-stats--tiles > .nv-info { padding:var(--spacing-16);
  border-left:var(--stroke-1) solid var(--border-base); }
.nv-report-stats--tiles > .nv-info:first-child { border-left:0; }
.nv-report-stats--tiles .nv-h28 { color:var(--fg-subtle); }
/* The hairline between tiles IS the border-left above. The base stats grid also
   draws a dashed rule 40 to the left of every cell after the first — the centre of
   its 80px column gutter. With gap:0 here there is no gutter, so that rule landed
   40 inside the PRECEDING tile, cutting each cell in two. Dropped for this variant
   only; the ungridded stats rows still want it. */
.nv-report-stats--tiles > .nv-info + .nv-info::before { content:none; }
/* p.nv-report-note so this out-specifies the document's 12/16 note rule: the tiles'
   caption is body-14 in the frame (tile 2's runs two lines on a 20 pitch, ink
   1244→1260 and 1266→1276). */
.nv-report-stats--tiles p.nv-report-note { font:400 14px/20px var(--font-body);
  color:var(--fg-base); }
/* 4 between a tile's value and its caption (frame: value box ends 1258, caption 1262)
   — tighter than the hero stat's 8, which the .nv-report-stats rule above sets. */
.nv-report-stats--tiles > .nv-info { gap:var(--spacing-4); }

/* Angle label — a bare lime mono label, no chip: sampled #DDEF6C on the dark frame
   and #8F8F8F on the light one at x 1033 (= the --fg-interactive pair). The filled
   lime tag is MATCHES THIS IP (x 1442→1566) and the relevance is a transparent tag
   on the right edge (x 1579→1687). The frames draw no progress bar. */
.nv-report-angle { flex:0 0 auto; font:500 12px/16px var(--font-code);
  text-transform:uppercase; color:var(--fg-interactive); }
.nv-report-row-end { margin-left:auto; }

/* Ledger row — index, title + "Led by …" line, then the status mark and the money
   figure STACKED on the right (walkthrough decision #10). Sampled on
   Results/Shortlist.png row 1: index box at 1048.5, title ink 1086.75 (14px,
   --fg-base), meta line 12px, right column right-aligned at 1622 and a 36px action
   slot held open to 1671 so every row's status lines up whether or not it carries
   a note button. */
/* The meta column keeps a floor: the two right-hand tracks are max-content (≈300px
   of buttons + money figure), so on a pane narrower than the frame's 736px a bare
   `minmax(0,1fr)` collapsed the "Led by …" line to ~117px and five ragged lines.
   150px holds the frame's own two-line wrap; below that the row scrolls rather
   than shreds. */
.nv-lead-row { grid-template-columns:auto minmax(150px, 1fr) minmax(0, auto) max-content; }
.nv-lead-row .nv-table-row-name { grid-column:2; grid-row:1; }
/* block, not the shared flex row: the frame's second line is one running sentence
   ("Led by Ultraleap · Cambridge, UK · Last deal: May '26"), and flex items break it
   into ragged chunks. */
.nv-lead-row .nv-table-row-meta { grid-column:2; grid-row:2; display:block; }
.nv-lead-row .nv-lead-status { grid-column:3; grid-row:1; justify-self:end;
  display:flex; align-items:center; gap:var(--spacing-8); }
.nv-lead-row .nv-lead-scale { grid-column:3; grid-row:2; justify-self:end;
  font:400 12px/20px var(--font-body); color:var(--fg-muted); text-align:right; }
.nv-lead-row .nv-table-row-actions { grid-column:4; grid-row:1 / 3;
  min-width:36px; justify-content:flex-end; }
.nv-lead-row .nv-table-row-note { grid-column:2 / 5; }
.nv-status-label { font:400 12px/20px var(--font-code); text-transform:uppercase;
  color:var(--fg-muted); }
/* The frames draw the status mark as a 2 × 16 strip (sampled #28B862 at x 1548→1550 /
   y 387→403 beside DEPLOYING, same shape beside LIVE). The team's call is a
   colour-coded dot instead — the strip read as another piece of right-aligned text
   rather than a state you can scan down the column (Anni + Balaji, 19 Aug 2026). The
   label stays: a bare colour carries no meaning for anyone who can't separate the
   hues. */
.nv-report .nv-dot { flex:0 0 6px; width:6px; height:6px;
  border-radius:var(--radius-999); }
/* ACQUIRED marks sample #0477DC dark and #5FB3FC light in Results.png. There is no
   blue primitive in design/tokens/tokens.json — these are frame-cited literals and
   should become a token once the design team adds one. */
.nv-report .nv-dot--info { background:var(--fg-info); }

/* The index column is a fixed 24 with the standard 12 gutter after it: the title
   box lands 36px past the row's inset in every frame (results card 632 → 668,
   shortlist card 1048.5 → 1085.5). */
.nv-report .nv-table-row-index, .nv-results .nv-table-row-index { min-width:24px; }
/* Row titles are --fg-base (#E0E0E0 / #292929), not --fg-subtle — sampled on both
   the grouped result rows and the shortlist's firm names. */
.nv-report .nv-table-row-name, .nv-results .nv-table-row-name { color:var(--fg-base); }
/* The secondary line is 12px on a 20px rhythm (cap height 8.75 on "Led by"). */
.nv-report .nv-table-row-meta { font-size:12px; line-height:20px; }
/* The first tier section sits straight under the collection row's dashed rule — no
   second, solid full-bleed rule above it. (.nv-report's own 16px gap already carries
   most of the 24 the frame shows between the rule at y 307.5 and TIER at y 332.) */
.nv-report-section--flush { border-top:0; padding-top:var(--spacing-8); margin-top:0; }
/* Bands that keep their 40px clearance but drop the rule — the licensing shortlist's
   tiers (the incubation list keeps its rules, which its own frame shows). */
.nv-report-section--unruled { border-top:0; }

/* The modal's document kicker is plain sentence-case sans, not the pane's mono
   uppercase + lime strip: sampled "Cover email" in Results/Outreachemail.png at
   x 528.75→595 / y 272→281.25, #7A7A7A (--fg-muted), 12px. (Both earlier passes
   left this open.) Scoped to the email artifact — the CRM card in the same modal has
   no frame, so it keeps the kicker treatment it already shipped with. */
.nv-report[data-kind="email"] .nv-eyebrow { font:400 12px/16px var(--font-body);
  text-transform:none; letter-spacing:normal; color:var(--fg-muted); }
.nv-report[data-kind="email"] .nv-eyebrow::before { display:none; }
/* The letter's subject sits one step below a report's heading-28: the email frame
   runs it at 24, cap-matched to the NUSX wordmark on the letterhead above it. */
.nv-report[data-kind="email"] h1 { font:500 24px/32px var(--font-heading); }

.nv-report-note-block { display:flex; flex-direction:column; gap:var(--spacing-8);
  padding:var(--spacing-12) var(--spacing-16); border-radius:var(--radius-4);
  border:var(--stroke-1) solid var(--border-subtle); background:var(--bg-base); }
.nv-report-note-block p { font:400 12px/16px var(--font-body); color:var(--fg-muted); }
.nv-modal-noteslot .nv-report-note-block { background:var(--bg-base); }
.nv-report-slide { display:flex; flex-direction:column; gap:var(--spacing-8);
  padding-top:var(--spacing-24); border-top:var(--stroke-1) solid var(--border-subtle); }
.nv-report-prose > * + * { margin-top:var(--spacing-12); }

/* Small parts the chat + report markup leans on */
.nv-message-q { white-space:pre-wrap; }
.nv-message-ref-pno { font-family:var(--font-code); flex:none; white-space:nowrap; }
.nv-message-ref-title { flex:1 1 auto; min-width:0; color:var(--fg-base); overflow:hidden;
  text-overflow:ellipsis; white-space:nowrap; }
.nv-table-row-pno { font:400 12px/16px var(--font-code); }
.nv-table-row-note { grid-column:2 / 4; margin-top:var(--spacing-4);
  color:var(--fg-muted); font:400 12px/16px var(--font-body); }
a.nv-table-row-name, a.nv-tag { text-decoration:none; }
a.nv-table-row-name:hover { color:var(--fg-subtle-hover); }
/* ---- Market-demand franchise card ----------------------------------------
   One bordered card per pharma, three groups separated by rules of deliberately
   DIFFERENT weight — measured on the v9 evaluate frame at 1.639× (card interior
   x 10 → 1091, i.e. the report's own 656 measure; padding 26px = 16 on all four
   sides; radius 4 from the corner run, which closes in 6px):

     · identity   name + product tags on one row, trial line under it
     - - - - - -  INSET dashed hairline, --border-base (dash peaks #3A3A3A at
                  y 138.5, running x 36 → 1066, i.e. inside the padding)
     · chart      "Oncology trials by indication" + the magnitude rows
     ───────────  FULL-BLEED solid hairline, --border-subtle (y 337.5, spanning
                  the card's whole interior; integrated ink 31 = 1.639 × (#272727
                  − canvas), half what a --border-base line would lay down)
     · quote      the pulled statement + its attribution

   The dashed rule is the stronger of the two on purpose: broken into 2px dashes it
   needs --border-base to read as a rule at all, where the solid full-bleed one
   already carries the weight of running edge to edge. 16px clears every rule on
   both sides, which is the card's gap. */
.nv-report-firm { display:flex; flex-direction:column; gap:var(--spacing-16);
  padding:var(--spacing-16); border:var(--stroke-1) solid var(--border-base);
  border-radius:var(--radius-4); }
.nv-report-firm > hr { background:repeating-linear-gradient(to right,
    var(--border-base) 0 2px, transparent 2px 4px); }
.nv-report-firm > hr.nv-report-firm-rule { margin-inline:calc(-1 * var(--spacing-16));
  background:var(--border-subtle); }

/* 4 between the firm and its trial line (name box ends 79, the 12/16 line's box
   opens at 85) — the head is one unit, against the card's 16 between units. */
.nv-report-firm-head { display:flex; flex-direction:column; gap:var(--spacing-4); }
/* Tags ride the name's own row, pushed right, centred on it (tag box 46→79, name ink
   54→71 — both centred on 62.5). Body-14 Medium, not the document's 20px h3: inside
   the card the firm name is a label, and the frame draws it at exactly the ink height
   of the indication rows below it. */
.nv-report-firm-name { display:flex; align-items:center; gap:var(--spacing-8); }
.nv-report-firm-name > h3 { flex:1 1 auto; min-width:0;
  font:500 14px/20px var(--font-body); color:var(--fg-subtle); }
.nv-report-firm-name > .nv-report-tags { flex:0 0 auto; margin-left:auto; }
.nv-report-firm-name .nv-tag { text-transform:uppercase; }
.nv-report-firm-chart { display:flex; flex-direction:column; gap:var(--spacing-8); }
/* Rows run on 24 (label boxes at 202 / 241 / 281 scaled) = the 20px line box + 4. */
.nv-report-firm-rows { display:flex; flex-direction:column; gap:var(--spacing-4); }

/* Magnitude row. The figure column is fixed, not content-sized: every row is its own
   grid, so a max-content track would start the bars at a different x on each line.
   9.5rem holds the widest reading ("25 active · 37 inactive") without wrapping. */
.nv-demand-row { display:grid; align-items:center; column-gap:var(--spacing-16);
  grid-template-columns:minmax(0, 1fr) minmax(0, 1.2fr) 8rem; }
.nv-demand-name { font:400 14px/20px var(--font-body); color:var(--fg-subtle); }
.nv-demand-num { text-align:right; font:400 12px/16px var(--font-body);
  color:var(--fg-muted); }
/* The canvas is transparent and the BAR is the sized element: its grey run is the
   inactive trials, so it has to stop at this indication's total rather than ruling
   the full column. Progress-bar tokens throughout — --bg-component track, lime fill,
   4px, square ends (frame: bar y 215→221 = 4px at 1.639×, track #1F1F1F). */
.nv-demand-bar { display:block; min-width:0; }
/* display:block on the bar too: .nv-progress is a <span> here, and an inline box
   drops the height outright. */
.nv-demand-bar > .nv-progress { display:block; min-width:var(--stroke-2); }
/* The pane is user-resizable, so the narrow case is a container question, not a
   viewport one: under ~440px of card the label and the figure alone fill the row and
   the bar has to go rather than overlap them. */
.nv-report-firm-rows { container-type:inline-size; }
@container (max-width: 440px) {
  .nv-demand-row { grid-template-columns:minmax(0, 1fr) max-content; }
  .nv-demand-bar { display:none; }
}

/* No left rule, no indent: the quote sits on the card's own 16px inset like every
   other group (its ink starts at x 36, the same column as the firm name). 12 between
   the statement and its attribution (statement box ends 463, attribution opens 482).
   The statement is 14/20 Medium, which is what the frame draws (line pitch 33 at
   1.639×, 6.65px/char); its attribution is 12. */
.nv-report blockquote.nv-report-firm-quote { display:flex; flex-direction:column;
  gap:var(--spacing-12); border-left:0; padding-left:0; }
.nv-report-firm-quote > p { font:500 14px/20px var(--font-body); color:var(--fg-subtle); }
/* Body face, not the document's mono <cite>: the attribution advances at 6.27px/char
   in the frame, where mono-12 would be a flat 7.2. */
.nv-report-firm-quote > p.nv-report-firm-cite { font:400 12px/16px var(--font-body);
  color:var(--fg-muted); }

/* ---- Competition candidate table -----------------------------------------
   One hairline box holding every candidate, entries divided FULL-BLEED at
   --border-base — heavier than the demand card's --border-subtle divider on
   purpose: there the rule separates groups within one entry, here it separates
   whole entries. Inside an entry, the heading pair is ruled off from the body by
   the same inset dashed hairline the demand card uses. Padding and gaps run on
   the demand card's 16 so the two boxes read as siblings; the v9 export of this
   frame measures its own internals slightly tighter (~12), which is one token
   swap here if the frames turn out to disagree deliberately. */
.nv-report-rivals { display:flex; flex-direction:column;
  border:var(--stroke-1) solid var(--border-base); border-radius:var(--radius-4); }
.nv-rival { display:flex; flex-direction:column; gap:var(--spacing-16);
  padding:var(--spacing-16); }
.nv-rival + .nv-rival { border-top:var(--stroke-1) solid var(--border-base); }
.nv-rival > hr { background:repeating-linear-gradient(to right,
    var(--border-base) 0 2px, transparent 2px 4px); }
/* The index is a row number for the whole entry, so the stage hangs in the NAME's
   column rather than under it, and the body below drops back to the card's own left
   inset — the indent belongs to the heading pair, not to the entry. */
/* Centred, not baselined: the index is a row number set beside the name, and the frame
   puts it on the name's midline — as it does the flag on the other side of the row. */
.nv-rival-head { display:grid; align-items:center; column-gap:var(--spacing-24);
  grid-template-columns:auto minmax(0, 1fr) auto; }
.nv-rival-index { grid-column:1; grid-row:1; font:400 12px/16px var(--font-code);
  color:var(--fg-muted); }
/* Body-14 Medium, not the document's 20px h3 — inside the table the candidate name is a
   row label, the same call the demand card's firm name takes. */
.nv-rival-head > h3 { grid-column:2; grid-row:1;
  font:500 14px/20px var(--font-body); color:var(--fg-subtle); }
.nv-rival-flag { grid-column:3; grid-row:1; text-transform:uppercase; }
.nv-rival-stage { grid-column:2; grid-row:2; }
.nv-rival-body { display:flex; flex-direction:column; gap:var(--spacing-4); }
/* 8 on top of the body's 4 = 12 under the organisation line, which is where the
   frame puts its link row. Deliberately NOT a flex row: flex blockifies its items, and
   a long citation then wraps its label while stranding the arrow at the end of the
   flex line. As inline text the arrow rides the last word (bound by an &nbsp;) and the
   pair reflows like a sentence at narrow pane widths. */
/* p.nv-rival-links so the left align clears `.nv-report p`'s justify — otherwise the
   link pair stretches to the measure when it wraps. */
.nv-report p.nv-rival-links { margin-top:var(--spacing-8); text-align:left; }
.nv-rival-links > .nv-link { display:inline; }
.nv-rival-links > .nv-link + .nv-link { margin-left:var(--spacing-16); }

.nv-report-note-block { font:400 12px/16px var(--font-body); }
.nv-report-note-block > summary { cursor:pointer; list-style:none;
  font:500 12px/16px var(--font-code); text-transform:uppercase; letter-spacing:.04em;
  color:var(--fg-muted); }
.nv-report-note-block > summary::-webkit-details-marker { display:none; }
.nv-report-note-block > summary:hover { color:var(--fg-subtle); }
.nv-report-note-block > div { display:flex; flex-direction:column; gap:var(--spacing-8); }
/* Lifted into the modal the block is no longer a <details> (agent.js flattens it —
   the header chevron is the control), so its label is a plain .nv-report-label span
   and the block itself must not sit on the summary's pointer affordances. */
.nv-modal-noteslot .nv-report-note-block { cursor:default; }
/* The lifted note's label steps down to mono-10: inside the dialog it is a caption on
   the header's disclosure, not a section head competing with the letter (Anni,
   2026-08-20). Line box stays 16, so the block's rhythm is unchanged. */
.nv-modal-noteslot .nv-report-note-block > .nv-report-label { font-size:10px; }
.nv-report-note-block strong { color:var(--fg-subtle); font-weight:500; }

/* Print view (agent.js writes a bare document into an iframe) */
.nv-print { background:var(--bg-base); }

/* ---- 5.5 · Narrow viewports ------------------------------------------- */
@media (max-width:1100px) {
  .nv-page-chat.is-split .nv-report-pane { position:fixed; inset:0; z-index:80;
    max-width:none; min-width:0; border-left:0; border-top-left-radius:0; }
  /* Overlay pane — nothing to drag against. */
  .nv-page-chat.is-split .nv-split-handle { display:none; }
  .nv-chat-col { min-width:0; }
}
@media (max-width:820px) {
  .nv-starters { grid-template-columns:1fr; }
  .nv-chat-scroll, .nv-composer-dock { padding-left:var(--spacing-16);
    padding-right:var(--spacing-16); }
}

/* ============================================================
   Task 6 — PAGE LAYER: nv-page-entity
     Directory (list) + detail pages for companies/people/investors/ip.
     Chrome = nv-details-header (breadcrumb + primary tag/actions, matches
     the report-pane header). Identity lives in the content column, capped
     at 1120px, sections hairline-ruled. Composes only Task 2/4 components
     plus the small set of layout primitives below — no new colours, radii
     or spacing values. Consumed by Tasks 7-10.
   ============================================================ */
.nv-page-entity { display:flex; flex-direction:column; min-height:100vh; }
/* Leave the .nv-panel-toggle its slot at the head of the chrome row, and centre
   it there — entity pages have no 8px canvas offset, so the chrome row is 0…56. */
.nv-page-entity > .nv-details-header { padding-left:var(--spacing-48); }
.nv-main:has(> .nv-page-entity) .nv-panel-toggle { top:var(--spacing-16); }
.nv-page-entity-content { flex:1; width:100%; max-width:1120px; margin-inline:auto;
  padding:var(--spacing-32) var(--spacing-40); display:flex; flex-direction:column;
  gap:var(--spacing-24); }
.nv-page-entity-head { display:flex; flex-direction:column; gap:var(--spacing-8); }
.nv-page-entity-lede { max-width:43rem; font:400 14px/20px var(--font-body); color:var(--fg-base); }
.nv-page-entity-note { font:400 12px/16px var(--font-body); color:var(--fg-muted); }
.nv-page-entity-meta { display:flex; flex-wrap:wrap; align-items:center; gap:var(--spacing-8);
  font:400 12px/16px var(--font-code); color:var(--fg-muted); }

/* Breadcrumb — sits inside nv-details-header (chrome), never the content column */
.nv-crumb { display:flex; align-items:center; gap:var(--spacing-8); min-width:0;
  font:400 14px/20px var(--font-body); color:var(--fg-muted); }
.nv-crumb a { color:var(--fg-muted); text-decoration:none; }
.nv-crumb a:hover { color:var(--fg-subtle); }
.nv-crumb-current { color:var(--fg-subtle); overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.nv-crumb-sep { color:var(--border-base); }

/* Filter row — All/type pills; nv-tag = active (single lime instance = a
   genuine selected state, not a category hue), nv-tag--transparent = inactive */
.nv-entity-filters { display:flex; flex-wrap:wrap; gap:var(--spacing-8); }
.nv-entity-filters a { text-decoration:none; cursor:pointer;
  transition:background var(--duration-100) var(--ease-in-out), border-color var(--duration-100) var(--ease-in-out), color var(--duration-100) var(--ease-in-out); }
.nv-entity-filters a.nv-tag--transparent:hover { background:var(--bg-button-transparent-hover); border-color:var(--border-base-hover); color:var(--fg-base); }
.nv-entity-filters a.nv-tag:hover { background:var(--bg-tag-hover); }

/* Row list — a plain sequence of nv-table-row (directory rows, sub-lists) */
.nv-entity-rows { display:flex; flex-direction:column; }
.nv-entity-rows .nv-table-row:last-child { border-bottom:0; }
a.nv-table-row { text-decoration:none; color:inherit; cursor:pointer;
  transition:background var(--duration-100) var(--ease-in-out); }
a.nv-table-row:hover { background:var(--bg-base-hover); }

/* nv-info-card as a link (papers-style reference rows) */
a.nv-info-card { text-decoration:none; color:inherit; cursor:pointer;
  transition:background var(--duration-100) var(--ease-in-out); }
a.nv-info-card:hover { background:var(--bg-base-hover); }

/* Two-column body: main content + a narrow fact-card rail */
.nv-entity-cols { display:grid; grid-template-columns:1fr 320px; gap:var(--spacing-32); align-items:start; }
.nv-entity-main { display:flex; flex-direction:column; gap:var(--spacing-24); min-width:0; }
.nv-entity-side { display:flex; flex-direction:column; gap:var(--spacing-12); min-width:0; }
@media (max-width:900px) { .nv-entity-cols { grid-template-columns:1fr; } }

/* Tabs — mono links; a lime underline marks the active one (the same
   selected-state language as the sidebar nav item's lime strip) */
.nv-entity-tabs { display:flex; gap:var(--spacing-24); border-bottom:var(--stroke-1) solid var(--border-subtle); }
.nv-entity-tab { display:inline-flex; align-items:center; gap:var(--spacing-4);
  padding:var(--spacing-12) 0; margin-bottom:-1px; border-bottom:var(--stroke-2) solid transparent;
  font:500 12px/16px var(--font-code); text-transform:uppercase; letter-spacing:.04em;
  color:var(--fg-muted); text-decoration:none;
  transition:color var(--duration-100) var(--ease-in-out), border-color var(--duration-100) var(--ease-in-out); }
.nv-entity-tab:hover { color:var(--fg-base); }
.nv-entity-tab.is-active { color:var(--fg-subtle); border-bottom-color:var(--brand-200); }
.nv-entity-tab-count { color:var(--fg-muted); }
.nv-entity-tab.is-active .nv-entity-tab-count { color:var(--fg-interactive); }

.nv-empty { padding:var(--spacing-32) 0; text-align:center; color:var(--fg-muted);
  font:400 14px/20px var(--font-body); }

/* Task 7 — hero identity row: nv-avatar beside the eyebrow/h32 stack (people
   detail's photo-less "who is this" header). Reuses the existing 28px
   nv-avatar; only the row layout was missing from nv-page-entity-head, which
   is otherwise a plain flex-column with no provision for a leading avatar. */
.nv-page-entity-head-row { display:flex; align-items:center; gap:var(--spacing-12); }

/* ---- 6.x · signal_card partial on Nova pages ---------------------------
   templates/partials/signal_card.html is shared with the legacy shell
   (intelligence/feed, intelligence/workflow, ip/detail, investors/detail) —
   its classes (.signal-card, .kicker, .section-label, .kb-chip, …) are styled
   for that shell in §8, scoped to body.nx-legacy. That scope is what keeps the
   two apart, so on Nova pages (companies/people detail "Signals" tab) the
   partial's structural CSS — not just its colours — is entirely absent without
   this block; every rule below is a full port (layout +
   tokens), not a recolour. Tokens only, no raw hexes; --wf-color keeps
   carrying the per-workflow accent set inline by the workflow_color filter
   (pre-existing, out of scope here). */
.nv-page-entity .signal-card { --wf-color: var(--fg-muted); position:relative;
  padding:var(--spacing-16); background:var(--bg-component);
  border:var(--stroke-1) solid var(--border-subtle); border-radius:var(--radius-8);
  transition:border-color var(--duration-100) var(--ease-in-out), background var(--duration-100) var(--ease-in-out); }
.nv-page-entity .signal-card + .signal-card { margin-top:var(--spacing-8); }
.nv-page-entity .signal-card::before { content:""; position:absolute; left:0; top:0;
  bottom:0; width:2px; background:var(--wf-color); opacity:.85; }
.nv-page-entity .signal-card:hover { border-color:var(--border-base);
  background:var(--bg-component-hover); }
.nv-page-entity .signal-card-internal { border-left:2px solid var(--brand-200);
  background:var(--bg-component); }
.nv-page-entity .signal-card-internal .signal-dot { opacity:.7; }
.nv-page-entity .signal-card-head { display:flex; align-items:center;
  gap:var(--spacing-8); margin-bottom:var(--spacing-8); flex-wrap:wrap; }
.nv-page-entity .signal-dot { width:8px; height:8px; border-radius:var(--radius-999);
  flex-shrink:0; display:inline-block; }
.nv-page-entity .signal-card .kicker { font:500 12px/16px var(--font-code);
  letter-spacing:.04em; color:var(--wf-color); }
.nv-page-entity .signal-card .kicker-muted { color:var(--fg-muted); }
.nv-page-entity .signal-card-time { margin-left:auto; font:400 12px/16px var(--font-code);
  color:var(--fg-muted); }
.nv-page-entity .signal-card-title { margin-bottom:var(--spacing-4);
  font:500 16px/24px var(--font-heading); color:var(--fg-subtle); }
.nv-page-entity .signal-card-title-link { color:inherit; text-decoration:none; }
/* hover only where it is a link — the card title stopped being one when the
   per-signal artifact page was deleted. */
a.nv-page-entity-signal-title:hover, .nv-page-entity a.signal-card-title-link:hover { color:var(--fg-subtle-hover); }
.nv-page-entity .signal-card-summary { margin-bottom:var(--spacing-12); max-width:43rem;
  font:400 14px/20px var(--font-body); color:var(--fg-base); }
.nv-page-entity .signal-card .section-label { font:500 12px/16px var(--font-code);
  letter-spacing:.04em; text-transform:uppercase; color:var(--fg-muted); }
.nv-page-entity .signal-card-theme { margin-bottom:var(--spacing-8);
  font:400 12px/16px var(--font-body); color:var(--fg-base); }
.nv-page-entity .signal-card-touched { display:flex; align-items:flex-start;
  gap:var(--spacing-8); flex-wrap:wrap; padding-top:var(--spacing-8);
  border-top:var(--stroke-1) solid var(--border-subtle); }
.nv-page-entity .touched-label { flex-shrink:0; padding-top:4px; }
.nv-page-entity .touched-row { display:flex; flex-wrap:wrap; gap:var(--spacing-4); flex:1; }
.nv-page-entity .kb-chip { display:inline-flex; align-items:center; gap:var(--spacing-4);
  max-width:26rem; padding:2px var(--spacing-8) 2px 4px; background:var(--bg-base);
  border:var(--stroke-1) solid var(--border-subtle); border-radius:var(--radius-999);
  color:var(--fg-muted); font:500 11px/16px var(--font-body); text-decoration:none;
  transition:background var(--duration-100) var(--ease-in-out), border-color var(--duration-100) var(--ease-in-out), color var(--duration-100) var(--ease-in-out); }
/* The IP / investor chips lost their hrefs with those detail pages, so the hover
   is scoped to the ones that are still links (companies, people). */
.nv-page-entity a.kb-chip:hover { border-color:var(--border-base);
  color:var(--fg-base); background:var(--bg-base-hover); }
.nv-page-entity .kb-chip-kind { font:500 9px/16px var(--font-code); letter-spacing:.08em;
  padding:1px 5px; background:var(--bg-component); border:var(--stroke-1) solid transparent;
  border-radius:var(--radius-2); color:var(--fg-muted); }
.nv-page-entity .kb-chip-ip .kb-chip-kind,
.nv-page-entity .kb-chip-companies .kb-chip-kind,
.nv-page-entity .kb-chip-people .kb-chip-kind,
.nv-page-entity .kb-chip-investors .kb-chip-kind { color:var(--fg-interactive);
  background:var(--bg-component); }
.nv-page-entity .kb-chip-label { overflow:hidden; text-overflow:ellipsis; white-space:nowrap; }
.nv-page-entity .signal-card-body { margin-top:var(--spacing-12); }
.nv-page-entity .signal-card-body summary { cursor:pointer; list-style:none;
  outline:none; display:inline-flex; align-items:center; gap:var(--spacing-4);
  padding:var(--spacing-4) 0; }
.nv-page-entity .signal-card-body summary::-webkit-details-marker { display:none; }
.nv-page-entity .signal-card-body summary::after { content:"▸"; font-size:10px;
  color:var(--fg-muted); transition:transform var(--duration-150) var(--ease-in-out); }
.nv-page-entity .signal-card-body[open] summary::after { transform:rotate(90deg); }
.nv-page-entity .signal-card-body summary .kicker { font:500 12px/16px var(--font-code);
  color:var(--fg-muted); }
.nv-page-entity .signal-card-body summary:hover .kicker { color:var(--fg-subtle); }
.nv-page-entity .signal-card-body-md { margin-top:var(--spacing-8); white-space:pre-wrap;
  font:400 14px/20px var(--font-body); color:var(--fg-base); }

/* ---- Licensing shortlist row (.nv-licensee-row) --------------------------------
   Measured on design/context/licensing/v9/Dark/Shortlist.png — the licensing-specific
   frame. (The exports under licensing/v9/Dark/Results/ are byte-identical to the
   incubation ones, i.e. the investor shortlist mis-filed into that folder; the row
   spec below is NOT theirs, which is why it is scoped to a class the incubation
   .nv-lead-row does not carry.)

   The row box is exactly 140 tall — dividers land at y 442.5 / 582.5 / 722.5 / 846.5
   in the frame — and reads: 16 inset, a 36-high header block, a 24 gap with the
   dashed rule painted on its midline, the rationale, then 16. */
/* row-gap is zeroed and the two internal gaps set as margins instead: the shared row's
   4px gap would otherwise stack on top of the rationale's own 24, pushing the box to
   145 against the frame's 140. */
.nv-licensee-row { row-gap:0; padding:var(--spacing-16); }
.nv-licensee-row .nv-table-row-meta { margin-top:var(--spacing-4); }
/* Header block = name 14/16 + 4 + meta 12/16 = 36, exactly the height of the 36×36
   action box beside it (frame: text ink 461.25→495.5, button box 459.25→494.75). The
   shared row sets both faces at /20, which stretches the block to 44. */
.nv-licensee-row .nv-table-row-name { line-height:16px; }
.nv-licensee-row .nv-table-row-meta { line-height:16px; }
/* The fit score is 12px like the rest of the meta line, not the shared row's 14:
   "88%" inks x 1086→1109.5 in the frame, a 23.5px advance — 12px Inter Medium. It
   keeps its --fg-subtle white against the muted remainder. */
.nv-licensee-row .nv-table-row-fit { font:500 12px/16px var(--font-body); }
/* Ownership reads "ⓘ Public" — the type word only, tickers behind the tooltip. The
   frame's glyph is a 12px outlined info mark inking x 1258.75→1270.25, set 4 off the
   preceding "·" and 4 off the word. */
.nv-meta-info { display:inline-flex; align-items:center; gap:var(--spacing-4);
  cursor:help; }
.nv-meta-info svg { flex:none; }
/* The rationale runs the row's full inset width, starting at the index column
   (x 1049.75 = the 16px inset) rather than under the name, and is 12/16 at
   --fg-subtle — the frame samples #FFFFFF there against the name's #E0E0E0. Needs
   (0,2,1) to clear `.nv-report p`, which would otherwise raise it to 14/20. */
.nv-report .nv-licensee-row .nv-table-row-note { position:relative;
  grid-column:1 / 4; margin-top:var(--spacing-24);
  font:400 12px/16px var(--font-body); color:var(--fg-subtle); }
/* …and the dashed rule sits ON that 24px gap's midline instead of consuming a row of
   it, which is what holds the box at 140 (frame: header bottom 495.5, rule 508, first
   rationale line boxed from 519.5). Painted 2-on/2-off like .nv-report hr, but at
   --border-base: the frame samples #3A3A3A, the card's own hairline weight, not the
   8 % --border-subtle. */
.nv-report .nv-licensee-row .nv-table-row-note::before { content:""; position:absolute;
  left:0; right:0; top:calc(-1 * var(--spacing-12)); height:var(--stroke-1);
  background-image:repeating-linear-gradient(to right,
    var(--border-base) 0 2px, transparent 2px 4px); }

/* ============================================================
   7 · SIGN-IN  (templates/login.html)
   The screen before the shell, so it IS the shell: the same two-tone split the
   app resolves per mode — rail on --bg-subtle (black in dark, gray-100 in light,
   exactly as .nv-sidebar reads in licensing/v9/{Dark,Light}/Default.png) beside a
   --bg-base canvas. No card: the sign-in block sits on the canvas in the chat
   hero's own eyebrow → headline → sub rhythm, because that hero is the next
   thing the reader sees.
   ============================================================ */
.nv-login { display:flex; min-height:100vh; background:var(--bg-base); }

/* Rail — .nv-sidebar's width, padding and brand row, with the nav it can't show
   yet left out rather than faked. */
.nv-login-rail { position:relative; flex:0 0 256px; width:256px; overflow:hidden;
  display:flex; flex-direction:column; justify-content:space-between;
  padding:var(--spacing-16); background:var(--bg-subtle); color:var(--fg-base); }
.nv-login-rail-foot { position:relative; z-index:1; padding-bottom:var(--spacing-8);
  color:var(--fg-muted); }
/* The one signature: the wordmark's own X, oversized and bled off the rail's
   bottom-left, carrying the accent that the locked rail otherwise has nowhere to
   put. Lime on the black rail; ink on the light one, which is how .nusx-x itself
   resolves (lime dark / currentColor light). */
.nv-login-mark { position:absolute; left:var(--spacing-40); bottom:var(--spacing-72);
  width:176px; height:auto; color:var(--brand-200); opacity:.08; pointer-events:none; }
.nv-login-mark path { fill:currentColor; }
:root[data-theme="light"] .nv-login-mark { color:var(--black-100); opacity:.05; }

/* Canvas */
.nv-login-canvas { position:relative; flex:1 1 auto; display:flex;
  align-items:center; justify-content:center;
  padding:var(--spacing-48) var(--spacing-24); }
.nv-login-block { width:100%; max-width:400px;
  display:flex; flex-direction:column; gap:var(--spacing-32); }
.nv-login-head { display:flex; flex-direction:column; gap:var(--spacing-16); }
.nv-login-head .nv-eyebrow { color:var(--fg-subtle); }
.nv-login-sub { color:var(--fg-muted); }

/* Status — the Highlight component (2px rule + body-14), taking the status pair
   instead of its default amber. */
.nv-login-alert { border-left:var(--stroke-2) solid var(--fg-info);
  padding-left:calc(var(--spacing-16) - var(--stroke-2));
  font:400 14px/20px var(--font-body); color:var(--fg-base); }
.nv-login-alert--error { border-left-color:var(--fg-danger); }

.nv-login-actions { display:flex; flex-direction:column; gap:var(--spacing-16); }
.nv-login-google { width:100%; }
/* Google's mark keeps its own colours — it is the one thing on this page that
   is not ours to restyle. */
.nv-login-google svg { width:16px; height:16px; flex:none; }

.nv-login-foot { display:flex; flex-direction:column; gap:var(--spacing-8);
  padding-top:var(--spacing-16); border-top:var(--stroke-1) solid var(--border-subtle);
  color:var(--fg-muted); }
.nv-login-foot .nv-eyebrow { color:var(--fg-muted); }
/* Viewport advice: only where it is actionable. On a laptop the reader is
   already where it would be sending them. */
.nv-login-viewport { display:none; }

/* Theme control — the same three modes and the same localStorage key the shell's
   user menu writes (sidebar.js binds .theme-opt), because this is the only
   screen where a reader can't reach that menu. */
.nv-login-theme { position:absolute; top:var(--spacing-24); right:var(--spacing-24);
  display:flex; gap:var(--spacing-4); padding:var(--spacing-4);
  border:var(--stroke-1) solid var(--border-subtle); border-radius:var(--radius-4); }
.nv-login-theme button { display:inline-flex; align-items:center; justify-content:center;
  width:28px; height:28px; padding:0; border:0; cursor:pointer;
  border-radius:var(--radius-2); background:var(--bg-button-transparent);
  color:var(--fg-muted);
  transition:background var(--duration-100) var(--ease-in-out),
             color var(--duration-100) var(--ease-in-out); }
.nv-login-theme button:hover { background:var(--bg-button-transparent-hover);
  color:var(--fg-base); }
.nv-login-theme button:focus-visible { outline:var(--stroke-1) solid var(--border-active);
  outline-offset:1px; }
/* Selected reads the same as the shell's own theme radios: a stepped neutral and
   the interactive ink (lime in dark, gray in light — see .nv-theme-option). */
.nv-login-theme button[aria-checked="true"],
.nv-login-theme button[aria-checked="true"]:hover {
  background:var(--bg-button-transparent-press); color:var(--fg-interactive); }
.nv-login-theme svg { width:16px; height:16px; }

/* Narrow: the rail becomes a masthead, since a 256px column beside a 400px block
   stops being a split and starts being a margin. */
@media (max-width:900px) {
  .nv-login { flex-direction:column; }
  .nv-login-rail { flex:0 0 auto; width:auto; flex-direction:row; align-items:center;
    justify-content:space-between; padding:var(--spacing-12) var(--spacing-16); }
  .nv-login-rail-foot { padding-bottom:0; }
  .nv-login-mark { display:none; }
  /* 72 over, so the theme control clears the block instead of landing on the
     eyebrow once the canvas is only as wide as the block itself. */
  .nv-login-canvas { padding:var(--spacing-72) var(--spacing-16) var(--spacing-32);
    align-items:flex-start; }
  .nv-login-theme { top:var(--spacing-16); right:var(--spacing-16); }
}
@media (max-width:820px) {
  .nv-login-viewport { display:block; }
}

/* ============================================================
   8 · LEGACY PAGES  (auth-era sections: investors, ip, matchmaking,
   intelligence — templates/base.html)
   These five sections have no Figma frames, so their LAYOUT is unchanged;
   what changed is where their colour, type, radii and motion come from.
   nus.css is gone: every value below now resolves from the Nova tokens in
   §1, so the legacy pages follow light/dark exactly like the Nova shell.
   The old NUSX names survive only as the alias block below — scoped to
   body.nx-legacy so nothing leaks onto a Nova page, which matters because
   the two shells share partials (signal_card, kb-chip) with the same class
   names and different styling.
   ============================================================ */
body.nx-legacy {
  /* Surfaces — the legacy ramp had five steps over claude.ai's warm greys;
     Nova has four semantic families, so panels take --bg-subtle (the rail's
     own surface) and every card-like step lands on --bg-component. */
  --bg-panel:            var(--bg-subtle);
  --bg-surface:          var(--bg-component);
  --bg-surface-raised:   var(--bg-component);
  --bg-raised:           var(--bg-component);
  --bg-hover:            var(--bg-base-hover);
  --bg-active:           var(--bg-base-press);
  --cream-100:           var(--bg-component);
  --cream-300:           var(--border-subtle);
  /* --bg-base and --bg-overlay are Nova's own token names and are deliberately
     NOT redefined here: the legacy canvas is simply the Nova canvas. */

  /* Ink */
  --text-primary:        var(--fg-subtle);
  --text-secondary:      var(--fg-base);
  --text-tertiary:       var(--fg-muted);
  --text-muted:          var(--fg-muted);
  --text-on-accent:      var(--fg-oncolor);
  /* Accent INK is --fg-interactive (lime on dark, gray on light — lime type on
     white is unreadable, see §1); accent FILL stays lime in both modes. */
  --text-accent:         var(--fg-interactive);
  --accent:              var(--fg-interactive);
  --accent-fill:         var(--bg-button);
  --accent-hover:        var(--bg-button-hover);
  --accent-dim:          var(--bg-button-transparent-press);

  /* Borders */
  --border:              var(--border-subtle);
  --border-default:      var(--border-subtle);
  --border-light:        var(--border-subtle);
  --border-strong:       var(--border-base);
  --border-focus:        var(--border-active);

  /* Interactive states */
  --interactive-accent:       var(--bg-button);
  --interactive-accent-hover: var(--bg-button-hover);
  --interactive-hover:        var(--bg-button-transparent-hover);
  --interactive-active:       var(--bg-button-transparent-press);
  --interactive-selected:     var(--bg-button-transparent-press);

  /* Status + the tints the legacy chips fill with. Nova ships no tint tokens,
     so they are mixed from the status ink at the legacy ramp's 14 %. */
  --status-success:      var(--fg-success);
  --status-error:        var(--fg-danger);
  --status-warning:      var(--fg-warning);
  --status-info:         var(--fg-info);
  --status-success-bg:   color-mix(in srgb, var(--fg-success) 14%, transparent);
  --status-error-bg:     color-mix(in srgb, var(--fg-danger) 14%, transparent);
  --status-warning-bg:   color-mix(in srgb, var(--fg-warning) 14%, transparent);
  --status-info-bg:      color-mix(in srgb, var(--fg-info) 14%, transparent);
  --green:  var(--status-success);  --green-dim:  var(--status-success-bg);
  --red:    var(--status-error);    --red-dim:    var(--status-error-bg);
  --amber:  var(--status-warning);  --amber-dim:  var(--status-warning-bg);
  --sky:    var(--status-info);     --sky-dim:    var(--status-info-bg);
  --navy:   var(--status-info);     --navy-dim:   var(--status-info-bg);
  --slate:  var(--fg-base);         --slate-dim:  var(--bg-component);

  /* Disease-area hues. Nova has four non-neutral ramps and the legacy pages
     need four categories, so each area takes one rather than keeping an
     off-system colour of its own. */
  --cat-cardio: var(--fg-info);     --cat-cardio-bg: var(--status-info-bg);
  --cat-liver:  var(--fg-danger);   --cat-liver-bg:  var(--status-error-bg);
  --cat-onco:   var(--fg-warning);  --cat-onco-bg:   var(--status-warning-bg);
  --cat-renal:  var(--fg-success);  --cat-renal-bg:  var(--status-success-bg);
  --purple: var(--cat-renal); --purple-dim: var(--cat-renal-bg);
  --garnet: var(--cat-liver);

  /* Radii — the legacy Tailwind scale collapses onto Nova's 0/2/4/8/999. */
  --radius-sm:   var(--radius-2);
  --radius-md:   var(--radius-4);
  --radius-lg:   var(--radius-8);
  --radius-xl:   var(--radius-8);
  --radius-2xl:  var(--radius-8);
  --radius-pill: var(--radius-999);

  /* Type, stroke, elevation */
  --font-sans:  var(--font-body);
  --font-mono:  var(--font-code);
  --font-serif: var(--font-heading);
  --stroke-hairline: var(--stroke-1);
  --stroke-thick:    var(--stroke-2);
  --shadow-color: var(--black-24);
  --shadow-sm:    var(--elevation-input);
  --modal-animation-duration: var(--modal-open);

  /* Layout constants the legacy shell measures itself with. */
  --sidebar-w: 220px;
  --sidebar-bg:        var(--bg-subtle);
  --sidebar-hover:     var(--bg-subtle-hover);
  --sidebar-text:      var(--fg-base);
  --sidebar-active-bg: var(--bg-subtle-press);
  --mobile-topbar-h: 52px;

  /* The legacy shell is a two-column flex body (sticky rail + main), which the
     Nova base rule has no reason to carry. Type moves to Nova's body-14. */
  display: flex;
  min-height: 100vh;
  background: var(--bg-base);
  color: var(--fg-base);
  font: 400 14px/20px var(--font-body);
}
/* The two element defaults these pages were built on; nova.css leaves <a> and
   <img> alone, so they are restated inside the scope rather than globally. */
.nx-legacy a { color: inherit; text-decoration: none; }
.nx-legacy img, .nx-legacy svg { display: block; max-width: 100%; }


.nx-legacy .sidebar {
    flex: 0 0 var(--sidebar-w);
    width: var(--sidebar-w);
    position: sticky;
    top: 0;
    align-self: flex-start;
    height: 100vh;
    background: var(--sidebar-bg);
    border-right: 1px solid var(--border);
    display: flex;
    flex-direction: column;
    z-index: 50;
    overflow-y: auto;
    overflow-x: hidden;
}

.nx-legacy .app-main {
    flex: 1 1 auto;
    min-width: 0;                 /* critical: let it shrink to the free space */
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}

.nx-legacy .sidebar-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.375rem;
    padding: 0.875rem 0.625rem 0.625rem;
}

.nx-legacy .sidebar-brand {
    display: inline-flex;
    align-items: center;
    min-width: 0;
    font-family: var(--font-sans);
    font-size: 1.1rem;
    font-weight: 500;
    letter-spacing: -0.03em;
    color: var(--text-primary);
    text-decoration: none;
    overflow: hidden;
}

.nx-legacy .sidebar-brand em {
    color: var(--text-accent);
    font-style: normal;
    font-weight: 500;
}

.nx-legacy .sidebar-search {
    margin: 0 0.75rem 0.375rem;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.4375rem 0.625rem;
    background: var(--bg-base);
    border: 1px solid var(--border-light);
    border-radius: var(--radius-sm);
    transition: border-color var(--duration-100) var(--ease-in-out), background var(--duration-100) var(--ease-in-out);
}

.nx-legacy .sidebar-search:focus-within {
    border-color: var(--border-focus);
    outline: var(--stroke-thick) solid var(--border-focus);
    outline-offset: -1px;
    background: var(--bg-surface);
}

.nx-legacy .sidebar-search input {
    flex: 1;
    min-width: 0;
    border: 0;
    background: transparent;
    outline: 0;
    font-family: var(--font-sans);
    font-size: 0.8125rem;
    color: var(--text-primary);
}

.nx-legacy .sidebar-search input::placeholder {
    color: var(--text-muted);
}

.nx-legacy .sidebar-nav {
    flex: 1;
    overflow-y: auto;
    padding: 0.25rem 0.5rem 0.5rem;
}

.nx-legacy .sidebar-group {
    padding: 0.375rem 0 0.25rem;
}

.nx-legacy .nav-item {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 0.5rem;
    border-radius: var(--radius-md);
    font-family: var(--font-mono);
    font-size: 12px;            /* App/Nav */
    font-weight: 500;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    color: var(--sidebar-text);
    transition: background var(--duration-100) var(--ease-in-out), color var(--duration-100) var(--ease-in-out), box-shadow var(--duration-100) var(--ease-in-out);
    cursor: pointer;
    white-space: nowrap;
    overflow: hidden;
}

.nx-legacy .nav-item:hover {
    background: var(--sidebar-hover);
    color: var(--text-primary);
}

.nx-legacy .nav-item.active {
    background: var(--sidebar-active-bg);
    color: var(--text-primary);
    box-shadow: inset 2px 0 0 var(--accent);
}

.nx-legacy .sidebar-foot {
    position: relative;
    padding: 0.5rem;
    border-top: var(--stroke-hairline) solid var(--border-default);
}

.nx-legacy .side-user-menu {
    position: absolute;
    left: 0.5rem; right: 0.5rem;
    bottom: calc(100% + 6px);
    background: var(--bg-surface);
    border: var(--stroke-hairline) solid var(--border-strong);
    border-radius: var(--radius-xl);
    padding: 0.4rem;
    z-index: 60;
}
.nx-legacy .side-user-menu[hidden] { display: none; }
.nx-legacy .side-menu-sec { display: flex; flex-direction: column; gap: 0.3rem; }
.nx-legacy .side-menu-label {
    font-family: var(--font-mono); font-size: 10px; font-weight: 500;
    letter-spacing: 0.6px; text-transform: uppercase; color: var(--text-tertiary);
    padding: 0.15rem 0.4rem 0;
}
.nx-legacy .side-menu-account {
    margin-top: 0.4rem; padding-top: 0.4rem;
    border-top: var(--stroke-hairline) solid var(--border);
}
.nx-legacy .side-signout {
    display: flex; align-items: center; gap: 0.5rem; width: 100%;
    padding: 0.4rem; border-radius: var(--radius-md);
    color: var(--text-secondary); text-decoration: none;
    font-size: 13px; font-weight: 500; transition: background var(--duration-100) var(--ease-in-out), color var(--duration-100) var(--ease-in-out);
}
.nx-legacy .side-signout:hover { background: var(--sidebar-hover); color: var(--text-primary); }
.nx-legacy .side-signout svg { width: 15px; height: 15px; flex: none; color: var(--text-tertiary); }

.nx-legacy .theme-seg { display: flex; flex-direction: column; gap: 2px; }
.nx-legacy .theme-opt {
    display: flex; align-items: center; gap: 0.6rem; width: 100%;
    padding: 0.4rem 0.5rem; border: 0; background: transparent;
    border-radius: var(--radius-md); cursor: pointer;
    color: var(--text-secondary);
    font-family: var(--font-mono); font-size: 11px; font-weight: 500;
    letter-spacing: 0.5px; text-transform: uppercase;
    transition: background var(--duration-100) var(--ease-in-out), color var(--duration-100) var(--ease-in-out);
}
.nx-legacy .theme-opt svg { width: 15px; height: 15px; flex: none; }
.nx-legacy .theme-opt span { flex: 1 1 auto; text-align: left; }
.nx-legacy .theme-opt:hover { background: var(--interactive-hover); color: var(--text-primary); }
.nx-legacy .theme-opt.is-active { color: var(--accent); background: var(--accent-dim); }
.nx-legacy .theme-opt:focus-visible {
    outline: var(--stroke-thick) solid var(--border-focus);
    outline-offset: -1px;
}

.nx-legacy .side-user:hover { background: var(--sidebar-hover); }
.nx-legacy .side-user-caret {
    width: 14px; height: 14px; flex: none; margin-left: auto;
    color: var(--text-tertiary); transition: transform var(--duration-150) var(--ease-in-out);
}
.nx-legacy .side-user[aria-expanded="true"] .side-user-caret { transform: rotate(180deg); }

.nx-legacy .page-bar {
    height: 48px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 1.75rem;
    border-bottom: 1px solid var(--border);
    background: var(--bg-surface);
    flex-shrink: 0;
}

.nx-legacy .page-bar-title {
    font-family: var(--font-serif);
    font-size: 1.0625rem;
    font-weight: 400;
    letter-spacing: -0.01em;
    color: var(--text-primary);
}

.nx-legacy .page-bar-meta {
    font-size: 0.6875rem;
    color: var(--text-muted);
    font-family: var(--font-mono);
}

.nx-legacy .page-content {
    padding: 1.75rem;
    flex: 1;
}

.nx-legacy .section-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 0.875rem;
}

.nx-legacy .section-label {
    font-family: var(--font-mono);   /* App/Label */
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.8px;
    text-transform: uppercase;
    color: var(--text-tertiary);
}

.nx-legacy .stats-row {
    display: flex;
    gap: 1px;
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    overflow: hidden;
    margin-bottom: 1.75rem;
    background: var(--border);
}

.nx-legacy .stat-block {
    flex: 1;
    padding: 1rem 1.25rem;
    background: var(--bg-surface);
}

.nx-legacy .stat-val {
    font-family: var(--font-serif);
    font-size: 2rem;
    font-weight: 300;
    color: var(--text-primary);
    letter-spacing: -0.03em;
    line-height: 1;
}

.nx-legacy .stat-lbl {
    font-size: 0.625rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: var(--text-muted);
    margin-top: 0.375rem;
}

.nx-legacy .tag {
    display: inline-flex;
    align-items: center;
    gap: 0.3125rem;
    padding: 2px 7px;
    border-radius: var(--radius-pill);
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.03em;
    white-space: nowrap;
}

.nx-legacy .tag-dot {
    width: 5px;
    height: 5px;
    border-radius: 50%;
    flex-shrink: 0;
}

.nx-legacy .tag-portfolio { background: var(--green-dim);  color: var(--green); }
.nx-legacy .tag-pipeline { background: var(--amber-dim);  color: var(--amber); }
.nx-legacy .tag-competitive { background: var(--sky-dim);    color: var(--sky); }
.nx-legacy .tag-exit-comp { background: var(--purple-dim); color: var(--purple); }
.nx-legacy .tag-customer { background: var(--slate-dim);  color: var(--slate); }
.nx-legacy .tag-unknown { background: var(--bg-raised);  color: var(--text-muted); }

.nx-legacy .tag-team { background: var(--green-dim);   color: var(--green); }
.nx-legacy .tag-founder { background: var(--navy-dim);    color: var(--navy); }
.nx-legacy .tag-expert { background: var(--purple-dim);  color: var(--purple); }
.nx-legacy .tag-operator { background: var(--sky-dim);     color: var(--sky); }
.nx-legacy .tag-advisor { background: var(--amber-dim);   color: var(--amber); }
.nx-legacy .tag-research-mentor { background: var(--accent-dim);  color: var(--accent); }
.nx-legacy .tag-investor { background: var(--slate-dim);   color: var(--slate); }
.nx-legacy .tag-customer-role { background: var(--slate-dim);   color: var(--slate); }

.nx-legacy .filter-row {
    display: flex;
    align-items: center;
    gap: 0.375rem;
    margin-bottom: 1.25rem;
    flex-wrap: wrap;
}

.nx-legacy .filter-btn {
    padding: 4px 10px;
    border-radius: var(--radius-pill);
    font-size: 0.75rem;
    font-weight: 500;
    border: 1px solid var(--border);
    background: var(--bg-surface);
    color: var(--text-secondary);
    cursor: pointer;
    transition: all var(--duration-100) var(--ease-in-out);
    text-decoration: none;
}

.nx-legacy .filter-btn:hover {
    border-color: var(--border-strong);
    color: var(--text-primary);
    background: var(--bg-raised);
}

.nx-legacy .filter-btn.active {
    border-color: var(--accent);
    color: var(--accent);
    background: var(--accent-dim);
}

.nx-legacy .entity-list {
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    overflow: hidden;
    background: var(--bg-surface);
}

.nx-legacy .entity-row {
    display: grid;
    align-items: center;
    padding: 0.6875rem 1rem;
    border-bottom: 1px solid var(--border-light);
    background: var(--bg-surface);
    transition: background var(--duration-100) var(--ease-in-out);
    text-decoration: none;
    color: inherit;
}

.nx-legacy .entity-row:last-child { border-bottom: none; }
.nx-legacy a.entity-row:hover { background: var(--bg-raised); }
.nx-legacy .person-row { grid-template-columns: 32px 1fr auto 90px 70px; gap: 0.75rem; }

.nx-legacy .entity-row-name {
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.nx-legacy .entity-row-sub {
    font-size: 0.6875rem;
    color: var(--text-muted);
    margin-top: 1px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.nx-legacy .entity-row-count {
    font-size: 0.6875rem;
    font-family: var(--font-mono);
    color: var(--text-muted);
    text-align: right;
}

.nx-legacy .entity-row-cell {
    min-width: 0;
    max-width: 16rem;
    font-size: 0.78rem;
    color: var(--text-secondary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.nx-legacy .entity-list-header {
    display: grid;
    align-items: center;
    padding: 0.5rem 1rem;
    background: var(--bg-base);
    border-bottom: 1px solid var(--border);
    font-size: 0.5625rem;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.nx-legacy .avatar {
    width: 28px;
    height: 28px;
    border-radius: var(--radius-sm);
    background: var(--bg-raised);
    border: 1px solid var(--border);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.625rem;
    font-weight: 700;
    color: var(--text-muted);
    flex-shrink: 0;
}

.nx-legacy .entity-hero {
    display: flex;
    align-items: flex-start;
    gap: 1.25rem;
    padding-bottom: 1.5rem;
    border-bottom: 1px solid var(--border);
    margin-bottom: 1.5rem;
}

.nx-legacy .entity-hero-avatar {
    width: 52px;
    height: 52px;
    border-radius: var(--radius-md);
    background: var(--bg-raised);
    border: 1px solid var(--border);
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: var(--font-serif);
    font-size: 1.375rem;
    font-weight: 400;
    color: var(--text-muted);
    flex-shrink: 0;
}

.nx-legacy .entity-hero-body { flex: 1; min-width: 0; }

.nx-legacy .entity-hero-name {
    font-family: var(--font-serif);
    font-size: 1.75rem;
    font-weight: 300;
    color: var(--text-primary);
    letter-spacing: -0.02em;
    line-height: 1.1;
    margin-bottom: 0.375rem;
}

.nx-legacy .entity-hero-meta {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
    font-size: 0.75rem;
    color: var(--text-muted);
}

.nx-legacy .entity-hero-desc {
    margin-top: 0.625rem;
    font-size: 0.875rem;
    color: var(--text-secondary);
    line-height: 1.65;
    max-width: 60ch;
}

.nx-legacy .tab-count {
    font-size: 0.6875rem;
    font-family: var(--font-mono);
    color: var(--text-muted);
    margin-left: 5px;
    background: var(--bg-raised);
    padding: 1px 5px;
    border-radius: var(--radius-pill);
}

.nx-legacy .timeline { display: flex; flex-direction: column; }

.nx-legacy .two-col {
    display: grid;
    grid-template-columns: 1fr 272px;
    gap: 1.5rem;
    align-items: start;
}

.nx-legacy .info-card {
    background: var(--bg-surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-xl);
    padding: 1rem 1.125rem;
}

.nx-legacy .info-card + .info-card { margin-top: 0.75rem; }

.nx-legacy .info-card-label {
    font-size: 0.5625rem;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--text-muted);
    margin-bottom: 0.75rem;
}

.nx-legacy .info-row {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 0.75rem;
    padding: 0.3125rem 0;
    border-bottom: 1px solid var(--border-light);
    font-size: 0.8125rem;
}

.nx-legacy .info-row:last-child { border-bottom: none; }
.nx-legacy .info-row-key { color: var(--text-muted); flex-shrink: 0; }
.nx-legacy .info-row-val { color: var(--text-primary); font-weight: 500; text-align: right; }

.nx-legacy .chips { display: flex; flex-wrap: wrap; gap: 0.375rem; }

.nx-legacy .chip {
    display: inline-flex;
    align-items: center;
    padding: 2px 8px;
    background: var(--bg-raised);
    border: 1px solid var(--border);
    border-radius: var(--radius-pill);
    font-size: 0.6875rem;
    font-weight: 500;
    color: var(--text-secondary);
    transition: border-color var(--duration-100) var(--ease-in-out), color var(--duration-100) var(--ease-in-out);
}

.nx-legacy .chip:hover { border-color: var(--border-strong); color: var(--text-primary); }

.nx-legacy .artifact-title {
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--text-primary);
}

.nx-legacy .artifact-meta {
    display: flex;
    gap: 0.75rem;
    font-size: 0.6875rem;
    color: var(--text-muted);
    font-family: var(--font-mono);
    margin-top: 2px;
}

.nx-legacy .mono { font-family: var(--font-mono); }
.nx-legacy .text-primary { color: var(--text-primary); }
.nx-legacy .text-secondary { color: var(--text-secondary); }
.nx-legacy .text-muted { color: var(--text-muted); }

.nx-legacy .empty {
    text-align: center;
    padding: 3rem 1rem;
    font-size: 0.875rem;
    color: var(--text-muted);
}

.nx-legacy .kicker {
    font-family: var(--font-mono);
    font-size: 0.6875rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--accent);
    font-weight: 500;
}

.nx-legacy .kicker-muted { color: var(--text-muted); }

.nx-legacy .sidebar-group-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0.375rem 0.625rem 0.4375rem;
    margin-bottom: 0.125rem;
}

.nx-legacy .sidebar-group + .sidebar-group { margin-top: 0.75rem; }

.nx-legacy .sidebar-group-kicker {
    font-family: var(--font-mono);
    font-size: 0.625rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--text-muted);
    font-weight: 600;
}

.nx-legacy .run-form {
    display: inline;
    margin-left: 0.75rem;
}

.nx-legacy .btn-run {
    font-family: var(--font-mono);
    font-size: 0.6875rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--accent);
    background: var(--bg-base);
    border: 1px solid var(--accent);
    border-radius: var(--radius-sm);
    padding: 0.25rem 0.625rem;
    cursor: pointer;
    transition: background var(--duration-100) var(--ease-in-out), color var(--duration-100) var(--ease-in-out);
}

.nx-legacy .btn-run:hover {
    background: var(--accent);
    color: var(--bg-base);
}

.nx-legacy .run-banner {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.625rem 0.875rem;
    margin-bottom: 1rem;
    background: var(--accent-dim);
    border: 1px solid color-mix(in srgb, var(--fg-success) 18%, transparent);
    border-radius: var(--radius-sm);
    font-size: 0.8125rem;
    color: var(--text-secondary);
}

.nx-legacy .run-banner-check {
    color: var(--accent);
    font-weight: 600;
}

.nx-legacy .run-banner a {
    color: var(--accent);
    text-decoration: underline;
    text-underline-offset: 2px;
}

.nx-legacy .feed-filters {
    display: flex;
    gap: 0.5rem;
    margin-bottom: 1.5rem;
    padding-bottom: 1rem;
    border-bottom: 1px solid var(--border-light);
}
.nx-legacy .feed-filter {
    font-family: var(--font-sans);
    font-size: 12px;
    font-weight: 500;
    padding: 0.35rem 0.9rem;
    border: 1px solid var(--border);
    border-radius: var(--radius-pill);
    background: var(--bg-surface);
    color: var(--text-secondary);
    cursor: pointer;
    transition: all var(--duration-150) var(--ease-in-out);
}
.nx-legacy .feed-filter:hover {
    background: var(--bg-hover);
}
.nx-legacy .feed-filter.active {
    background: var(--accent);
    color: white;
    border-color: var(--accent);
}

.nx-legacy .signal-feed, .nx-legacy .signal-list {
    display: flex;
    flex-direction: column;
    gap: 0.625rem;
}

.nx-legacy .signal-card {
    --wf-color: var(--accent);
    position: relative;
    padding: 1rem 1.125rem 0.9375rem 1.25rem;
    background: var(--bg-surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-xl);
    transition: border-color var(--duration-100) var(--ease-in-out), box-shadow var(--duration-100) var(--ease-in-out);
}

.nx-legacy .signal-card::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 3px;
    background: var(--wf-color);
    opacity: 0.85;
}

.nx-legacy .signal-card:hover {
    border-color: var(--border-strong);
    box-shadow: var(--shadow-sm);
}

.nx-legacy .signal-card-internal {
    border-left: 3px solid var(--accent);
    background: linear-gradient(90deg, var(--accent-dim) 0%, transparent 120px);
}
.nx-legacy .signal-card-internal .signal-dot {
    opacity: 0.7;
}

.nx-legacy .signal-card-head {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    margin-bottom: 0.5rem;
    flex-wrap: wrap;
}

.nx-legacy .signal-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    flex-shrink: 0;
    display: inline-block;
}

.nx-legacy .signal-card-time {
    margin-left: auto;
    font-family: var(--font-mono);
    font-size: 0.6875rem;
    color: var(--text-muted);
}

.nx-legacy .signal-card-title {
    font-family: var(--font-serif);
    font-size: 1.125rem;
    font-weight: 500;
    letter-spacing: -0.01em;
    color: var(--text-primary);
    margin-bottom: 0.375rem;
    line-height: 1.25;
}

.nx-legacy .signal-card-summary {
    font-size: 0.8125rem;
    line-height: 1.55;
    color: var(--text-secondary);
    max-width: 72ch;
    margin-bottom: 0.75rem;
}

.nx-legacy .signal-card-theme {
    font-size: 0.75rem;
    color: var(--text-secondary);
    margin-bottom: 0.625rem;
}

.nx-legacy .signal-card-touched {
    display: flex;
    align-items: flex-start;
    gap: 0.625rem;
    flex-wrap: wrap;
    padding-top: 0.5rem;
    border-top: 1px solid var(--border-light);
}

.nx-legacy .touched-label {
    flex-shrink: 0;
    padding-top: 4px;
}

.nx-legacy .touched-row {
    display: flex;
    flex-wrap: wrap;
    gap: 0.3125rem;
    flex: 1;
}

.nx-legacy .kb-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.3125rem;
    padding: 2px 8px 2px 4px;
    border-radius: var(--radius-pill);
    font-size: 0.6875rem;
    font-weight: 500;
    background: var(--bg-raised);
    border: 1px solid var(--border-light);
    color: var(--text-secondary);
    max-width: 26rem;
    text-decoration: none;
    transition: border-color var(--duration-100) var(--ease-in-out), color var(--duration-100) var(--ease-in-out), background var(--duration-100) var(--ease-in-out);
}

.nx-legacy a.kb-chip:hover {
    border-color: var(--border-strong);
    color: var(--text-primary);
    background: var(--bg-surface);
}

.nx-legacy .kb-chip-kind {
    font-family: var(--font-mono);
    font-size: 0.5625rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    padding: 1px 5px;
    border-radius: var(--radius-sm);
    background: var(--bg-surface);
    border: 1px solid var(--border-light);
    color: var(--text-muted);
}

.nx-legacy .kb-chip-label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.nx-legacy .kb-chip-ip .kb-chip-kind { color: var(--cat-renal);  border-color: transparent; background: var(--cat-renal-bg); }
.nx-legacy .kb-chip-companies .kb-chip-kind { color: var(--cat-cardio); border-color: transparent; background: var(--cat-cardio-bg); }
.nx-legacy .kb-chip-people .kb-chip-kind { color: var(--green);      border-color: transparent; background: var(--green-dim); }
.nx-legacy .kb-chip-investors .kb-chip-kind { color: var(--cat-onco);   border-color: transparent; background: var(--cat-onco-bg); }

.nx-legacy .signal-card-body { margin-top: 0.75rem; }
.nx-legacy .signal-card-body summary {
    cursor: pointer;
    list-style: none;
    outline: none;
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.25rem 0;
}

.nx-legacy .signal-card-body summary::-webkit-details-marker { display: none; }
.nx-legacy .signal-card-body summary::after {
    content: "▸";
    font-size: 0.625rem;
    color: var(--text-muted);
    transition: transform var(--duration-150) var(--ease-in-out);
    display: inline-block;
}

.nx-legacy .signal-card-body[open] summary::after { transform: rotate(90deg); }

.nx-legacy .signal-card-body-md {
    white-space: pre-wrap;
    font-family: var(--font-serif);
    font-size: 0.9375rem;
    line-height: 1.6;
    color: var(--text-secondary);
    padding: 0.75rem 0.25rem 0.25rem;
    margin: 0;
    max-width: 70ch;
}
.nx-legacy .person-row { grid-template-columns: 32px 1fr auto 1fr 70px 70px; gap: 0.75rem; }

.nx-legacy .investor-list-header { grid-template-columns: 32px 1fr auto auto auto 90px; gap: 0.75rem; }
.nx-legacy .investor-row { grid-template-columns: 32px 1fr auto auto auto 90px; gap: 0.75rem; }

.nx-legacy .paper-mark {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    border: 1px solid;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.625rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    font-family: var(--font-mono);
    background: var(--bg-surface);
}

.nx-legacy .mark-theme-quantum { color: var(--cat-renal);  border-color: var(--cat-renal-bg); }
.nx-legacy .mark-theme-biomedical { color: var(--cat-liver);  border-color: var(--cat-liver-bg); }
.nx-legacy .mark-theme-ai { color: var(--cat-cardio); border-color: var(--cat-cardio-bg); }
.nx-legacy .mark-theme-materials { color: var(--cat-onco);   border-color: var(--cat-onco-bg); }

.nx-legacy .tag-theme-quantum { background: var(--cat-renal-bg);  color: var(--cat-renal); }
.nx-legacy .tag-theme-biomedical { background: var(--cat-liver-bg);  color: var(--cat-liver); }
.nx-legacy .tag-theme-ai { background: var(--cat-cardio-bg); color: var(--cat-cardio); }
.nx-legacy .tag-theme-materials { background: var(--cat-onco-bg);   color: var(--cat-onco); }

.nx-legacy .pill {
    display: inline-flex;
    align-items: center;
    padding: 1px 7px;
    border-radius: var(--radius-pill);
    font-size: 0.625rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    white-space: nowrap;
    border: 1px solid transparent;
}

.nx-legacy .pill-available { background: var(--green-dim);  color: var(--green);  border-color: color-mix(in srgb, var(--fg-success) 25%, transparent); }
.nx-legacy .pill-licensed { background: var(--amber-dim);  color: var(--amber);  border-color: color-mix(in srgb, var(--fg-warning) 25%, transparent); }
.nx-legacy .pill-spun-out { background: var(--navy-dim);   color: var(--navy);   border-color: color-mix(in srgb, var(--fg-info) 25%, transparent); }

.nx-legacy .paper-hero {
    padding-bottom: 1.5rem;
    border-bottom: 1px solid var(--border);
    margin-bottom: 1.5rem;
}

.nx-legacy .paper-hero .kicker { display: block; margin-bottom: 0.625rem; }

.nx-legacy .paper-hero-authors {
    font-size: 0.9375rem;
    color: var(--text-secondary);
    margin-bottom: 0.375rem;
    font-family: var(--font-serif);
    font-weight: 400;
    font-style: italic;
}

.nx-legacy .paper-hero-meta {
    display: flex;
    gap: 0.5rem;
    align-items: center;
    font-size: 0.8125rem;
    color: var(--text-muted);
    flex-wrap: wrap;
}

.nx-legacy .paper-abstract {
    font-family: var(--font-serif);
    font-size: 1rem;
    line-height: 1.65;
    color: var(--text-secondary);
    max-width: 68ch;
    margin-bottom: 1.5rem;
}

.nx-legacy .linked-entity {
    display: block;
    padding: 0.5rem 0.625rem;
    background: var(--bg-surface);
    border: 1px solid var(--border-light);
    border-radius: var(--radius-sm);
    text-decoration: none;
    transition: border-color var(--duration-100) var(--ease-in-out), background var(--duration-100) var(--ease-in-out);
}

.nx-legacy .linked-entity + .linked-entity { margin-top: 0.375rem; }

.nx-legacy .linked-entity:hover {
    border-color: var(--border-strong);
    background: var(--bg-raised);
}

.nx-legacy .linked-entity-name {
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--text-primary);
    margin-bottom: 2px;
}

.nx-legacy .linked-entity-sub {
    font-size: 0.6875rem;
    color: var(--text-muted);
    display: flex;
    gap: 0.375rem;
    align-items: center;
    flex-wrap: wrap;
}

.nx-legacy .rounds-table {
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    overflow: hidden;
    background: var(--bg-surface);
}

.nx-legacy .rounds-header, .nx-legacy .rounds-row {
    display: grid;
    grid-template-columns: 1.5fr 0.8fr 1fr 0.8fr 0.6fr;
    gap: 0.75rem;
    padding: 0.625rem 1rem;
    align-items: center;
}

.nx-legacy .rounds-header {
    font-size: 0.5625rem;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--text-muted);
    background: var(--bg-base);
    border-bottom: 1px solid var(--border);
}

.nx-legacy .rounds-row {
    border-bottom: 1px solid var(--border-light);
    font-size: 0.8125rem;
}

.nx-legacy .rounds-row:last-child { border-bottom: none; }

.nx-legacy .tag-incubated { background: var(--green-dim); color: var(--green); }
.nx-legacy .tag-market-watch { background: var(--sky-dim);   color: var(--sky); }
.nx-legacy .tag-exit { background: var(--purple-dim); color: var(--purple); }

.nx-legacy .tag-researcher { background: var(--accent-dim); color: var(--accent); }

.nx-legacy .signal-card-title-link { color: inherit; text-decoration: none; }
.nx-legacy a.signal-card-title-link:hover { color: var(--text-primary); }

@media (max-width: 900px) {
    .nx-legacy .two-col { grid-template-columns: 1fr; }
    .nx-legacy .rounds-header, .nx-legacy .rounds-row { grid-template-columns: 1fr; gap: 0.25rem; }
}

.nx-legacy .text-headline {
    font-family: var(--font-serif);
    font-size: clamp(2rem, 4.5vw, 2.75rem);
    font-weight: 400;
    line-height: 1.15;
    letter-spacing: -0.015em;
    color: var(--text-primary);
}

.nx-legacy .text-section-title {
    font-family: var(--font-serif);
    font-size: clamp(1.375rem, 2.6vw, 1.75rem);
    font-weight: 500;
    line-height: 1.2;
    letter-spacing: -0.01em;
    color: var(--text-primary);
}

.nx-legacy .text-label {
    font-family: var(--font-sans);
    font-size: 0.75rem;
    font-weight: 600;
    line-height: 1.4;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--text-secondary);
}

.nx-legacy .text-overline {
    font-family: var(--font-sans);
    font-size: 0.6875rem;
    font-weight: 500;
    line-height: 1.4;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.nx-legacy .text-overline-accent {
    color: var(--accent);
}

.nx-legacy .badge {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    font-family: var(--font-sans);
    font-size: 0.75rem;
    font-weight: 500;
    letter-spacing: 0.02em;
    padding: 0.25rem 0.625rem;
    border-radius: var(--radius-pill);
    border: 1px solid transparent;
    white-space: nowrap;
}

.nx-legacy .eyebrow-pair {
    display: flex;
    flex-direction: column;
    gap: 0.625rem;
    margin-bottom: 1.5rem;
}

.nx-legacy .eyebrow-pair .text-overline { margin: 0; }

.nx-legacy .entity-hero.entity-hero-polished .entity-hero-name {
    font-family: var(--font-serif);
    font-size: clamp(2rem, 4vw, 2.5rem);
    font-weight: 400;
    letter-spacing: -0.015em;
    line-height: 1.1;
}

.nx-legacy .entity-hero.entity-hero-polished .entity-hero-desc {
    font-size: 1rem;
    line-height: 1.55;
    color: var(--text-secondary);
    max-width: 72ch;
}

.nx-legacy .entity-hero-overline {
    font-family: var(--font-sans);
    font-size: 0.6875rem;
    font-weight: 500;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--text-muted);
    margin-bottom: 0.625rem;
}

.nx-legacy .artifact-header {
    margin: 0.5rem 0 1rem;
    padding-bottom: 1rem;
    border-bottom: 1px solid var(--border-default);
}

.nx-legacy .artifact-title {
    font-family: var(--font-serif);
    font-weight: 400;
    font-size: clamp(1.5rem, 2.2vw, 1.875rem);
    line-height: 1.2;
    letter-spacing: -0.015em;
    color: var(--text-primary);
    margin: 0 0 0.625rem;
}

.nx-legacy .artifact-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    align-items: center;
    font-size: 0.8125rem;
    color: var(--text-muted);
}

.nx-legacy .artifact-meta-sep { color: var(--border-light); }

.nx-legacy .artifact-summary {
    font-size: 1rem;
    line-height: 1.6;
    color: var(--text-secondary);
    margin: 0 0 1.75rem;
    max-width: 72ch;
}

.nx-legacy .artifact-section {
    margin-top: 1.75rem;
    padding-top: 1.25rem;
    border-top: 1px solid var(--border-default);
}

.nx-legacy .artifact-section:first-of-type { border-top: none; padding-top: 0; }

.nx-legacy .artifact-section .section-label {
    display: block;
    margin-bottom: 0.875rem;
    font-family: var(--font-sans);
    font-size: 0.6875rem;
    font-weight: 500;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.nx-legacy .artifact-prose {
    font-size: 0.9375rem;
    line-height: 1.65;
    color: var(--text-primary);
    max-width: 72ch;
}

.nx-legacy .artifact-prose p { margin: 0 0 0.875rem; }
.nx-legacy .artifact-prose p:last-child { margin-bottom: 0; }
.nx-legacy .artifact-prose a { color: var(--accent); text-decoration: underline; text-underline-offset: 3px; }
.nx-legacy .artifact-prose strong { font-weight: 600; color: var(--text-primary); }
.nx-legacy .artifact-prose ul, .nx-legacy .artifact-prose ol { margin: 0 0 0.875rem 1.25rem; padding: 0; }
.nx-legacy .artifact-prose li { margin-bottom: 0.375rem; }

.nx-legacy .artifact-links {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.nx-legacy .artifact-links li {
    display: flex;
    align-items: baseline;
    gap: 0.625rem;
    font-size: 0.875rem;
    line-height: 1.5;
}

.nx-legacy .artifact-link-tag {
    display: inline-block;
    font-family: var(--font-sans);
    font-size: 0.625rem;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--accent);
    background: var(--bg-raised);
    border: 1px solid var(--cream-300);
    padding: 0.125rem 0.375rem;
    border-radius: var(--radius-sm);
    flex-shrink: 0;
    min-width: 2.5rem;
    text-align: center;
}

.nx-legacy .artifact-link-tag-co { color: var(--navy); }

.nx-legacy .artifact-links a {
    color: var(--text-primary);
    text-decoration: none;
    font-weight: 500;
    border-bottom: 1px dotted var(--border-light);
}

.nx-legacy .artifact-links a:hover {
    color: var(--text-primary);
    border-bottom-color: var(--text-primary);
}

.nx-legacy .artifact-link-sub { color: var(--text-muted); font-size: 0.8125rem; }

.nx-legacy .artifact-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.375rem;
}

.nx-legacy .artifact-chip {
    display: inline-flex;
    align-items: center;
    padding: 0.3125rem 0.625rem;
    font-size: 0.8125rem;
    font-weight: 500;
    color: var(--text-primary);
    background: var(--bg-raised);
    border: 1px solid var(--cream-300);
    border-radius: var(--radius-pill);
    text-decoration: none;
    transition: background var(--duration-100) var(--ease-in-out), border-color var(--duration-100) var(--ease-in-out);
}

.nx-legacy .artifact-chip:hover {
    background: var(--cream-100);
    border-color: var(--border-strong);
    color: var(--text-primary);
}

.nx-legacy .artifact-chip-inv {
    color: var(--navy);
    border-color: var(--navy);
    background: transparent;
}

.nx-legacy .artifact-chip-inv:hover {
    background: var(--navy);
    color: var(--fg-oncolor);
    border-color: var(--navy);
}

.nx-legacy .artifact-person-card {
    display: flex;
    flex-direction: column;
    gap: 0.375rem;
    padding: 0.75rem 0.875rem;
    background: var(--bg-raised);
    border: 1px solid var(--cream-300);
    border-radius: var(--radius-xl);
    text-decoration: none;
    color: inherit;
    transition: border-color var(--duration-100) var(--ease-in-out);
}

.nx-legacy .artifact-person-card:hover { border-color: var(--border-strong); }

.nx-legacy .artifact-person-name {
    font-weight: 600;
    font-size: 0.875rem;
    color: var(--text-primary);
}

.nx-legacy .artifact-person-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.375rem;
    font-size: 0.75rem;
    color: var(--text-muted);
}

.nx-legacy .artifact-cohort-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
    gap: 0.75rem;
}

.nx-legacy .artifact-cohort-card {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: 0.875rem 1rem;
    background: var(--bg-raised);
    border: 1px solid var(--cream-300);
    border-radius: var(--radius-xl);
    text-decoration: none;
    color: inherit;
    transition: border-color var(--duration-100) var(--ease-in-out), transform var(--duration-100) var(--ease-in-out);
}

.nx-legacy .artifact-cohort-card:hover {
    border-color: var(--border-strong);
    transform: translateY(-1px);
}

.nx-legacy .artifact-cohort-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 0.5rem;
}

.nx-legacy .artifact-cohort-name {
    font-weight: 600;
    font-size: 0.9375rem;
    color: var(--text-primary);
}

.nx-legacy .artifact-cohort-line {
    font-size: 0.8125rem;
    line-height: 1.5;
    color: var(--text-secondary);
    margin: 0;
}

.nx-legacy .artifact-cohort-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    font-size: 0.75rem;
    color: var(--text-muted);
}

.nx-legacy .artifact-target {
    display: grid;
    gap: 0.5rem;
}

.nx-legacy .artifact-target-card {
    padding: 0.875rem 1rem;
    background: var(--bg-raised);
    border: 1px solid var(--cream-300);
    border-radius: var(--radius-xl);
    text-decoration: none;
    color: inherit;
    transition: border-color var(--duration-100) var(--ease-in-out);
}

.nx-legacy .artifact-target-card:hover { border-color: var(--border-strong); }

.nx-legacy .artifact-target-name {
    font-weight: 600;
    font-size: 1rem;
    color: var(--text-primary);
    margin-bottom: 0.25rem;
}

.nx-legacy .artifact-target-line {
    font-size: 0.875rem;
    color: var(--text-secondary);
    line-height: 1.5;
}

.nx-legacy .artifact-people-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    counter-reset: none;
}

.nx-legacy .artifact-person-row {
    display: flex;
    align-items: stretch;
    gap: 0.75rem;
}

.nx-legacy .artifact-person-rank {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 2rem;
    font-family: var(--font-mono);
    font-size: 0.8125rem;
    font-weight: 500;
    color: var(--text-muted);
    background: var(--bg-raised);
    border: 1px solid var(--cream-300);
    border-radius: var(--radius-md);
}

.nx-legacy .artifact-person-row .artifact-person-card {
    flex: 1;
}

.nx-legacy .paper-list {
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    overflow: hidden;
    background: var(--bg-surface);
}

.nx-legacy .paper-list-item {
    display: grid;
    grid-template-columns: 32px 1fr auto;
    column-gap: 1rem;
    align-items: start;
    padding: 0.9375rem 1.125rem;
    border-bottom: 1px solid var(--border-light);
    background: var(--bg-surface);
    transition: background var(--duration-100) var(--ease-in-out);
    text-decoration: none;
    color: inherit;
}

.nx-legacy .paper-list-item:last-child { border-bottom: none; }
.nx-legacy a.paper-list-item:hover { background: var(--bg-raised); }

.nx-legacy .paper-list-item .paper-mark {
    margin-top: 2px;
}

.nx-legacy .paper-list-body {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

.nx-legacy .paper-list-title {
    font-family: var(--font-serif);
    font-size: 1.0625rem;
    font-weight: 500;
    letter-spacing: -0.005em;
    line-height: 1.3;
    color: var(--text-primary);
}

.nx-legacy .paper-list-authors {
    font-size: 0.8125rem;
    color: var(--text-secondary);
    line-height: 1.45;
    overflow: hidden;
    text-overflow: ellipsis;
    display: -webkit-box;
    -webkit-line-clamp: 1;
    -webkit-box-orient: vertical;
}

.nx-legacy .paper-list-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    font-family: var(--font-mono);
    font-size: 0.6875rem;
    color: var(--text-muted);
    margin-top: 0.125rem;
}

.nx-legacy .paper-list-meta .sep {
    color: var(--border);
}

.nx-legacy .paper-list-trailing {
    display: flex;
    align-items: center;
    flex-shrink: 0;
    padding-top: 2px;
}

@media (max-width: 720px) {
    .nx-legacy .paper-list-item {
        grid-template-columns: 32px 1fr;
    }
    .nx-legacy .paper-list-trailing {
        grid-column: 2;
        padding-top: 0;
    }
}
@keyframes agentFade { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }


.nx-legacy .art { max-width: 720px; margin: 0 auto; animation: agentFade var(--modal-animation-duration) var(--ease-out) both; }

.nx-legacy .artifact-prose .md-h, .nx-legacy .art-prose .md-h {
    font-family: var(--font-sans); font-size: 0.7rem; font-weight: 700;
    letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-muted);
    margin: 1.25rem 0 0.45rem;
}
.nx-legacy .artifact-prose .md-h:first-child, .nx-legacy .art-prose .md-h:first-child { margin-top: 0; }
.nx-legacy .artifact-prose p, .nx-legacy .art-prose p { margin: 0 0 0.7rem; line-height: 1.6; }
.nx-legacy .artifact-prose .md-ul, .nx-legacy .art-prose .md-ul { margin: 0 0 0.85rem; padding-left: 1.15rem; }
.nx-legacy .artifact-prose .md-ul li, .nx-legacy .art-prose .md-ul li { margin-bottom: 0.3rem; line-height: 1.55; }
.nx-legacy .artifact-prose strong, .nx-legacy .art-prose strong { color: var(--text-primary); font-weight: 600; }
.nx-legacy .art-rel { font-size: 0.68rem; font-weight: 600; padding: 0.1rem 0.45rem; border-radius: var(--radius-pill); }
.nx-legacy .art-rel-high { color: var(--green); background: var(--green-dim); }
.nx-legacy .art-rel-mid { color: var(--amber); background: var(--amber-dim); }
.nx-legacy .art-rel-low { color: var(--slate); background: var(--slate-dim); }
.nx-legacy .art-rel-watch { color: var(--red); background: var(--red-dim); }

.nx-legacy .lr { display: flex; flex-direction: column; gap: 1.5rem; }

.nx-legacy .kw { font-weight: 600; padding: 0.05rem 0.4rem; border-radius: var(--radius-sm); white-space: nowrap; }

.nx-legacy .trend-arrow {
    font-size: 0.7em;
    margin-left: 0.35rem;
    vertical-align: middle;
}
.nx-legacy .trend-up {
    color: var(--green);
}
.nx-legacy .trend-down {
    color: var(--red);
}
.nx-legacy .lead-list {
    border: 1px solid var(--border);
    border-radius: var(--radius-md);
    overflow: hidden;
    margin: 1rem 0;
}
.nx-legacy .lead-row {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
    padding: 0.85rem 1rem;
    border-bottom: 1px solid var(--border-light);
    background: var(--bg-surface);
    cursor: grab;
    transition: background var(--duration-100) var(--ease-in-out);
}
.nx-legacy .lead-row:last-child {
    border-bottom: none;
}
.nx-legacy .lead-row:hover {
    background: var(--bg-hover);
}

.nx-legacy .mm-shell { max-width: 960px; margin: 0 auto; padding: 3rem 2rem 5rem; }
.nx-legacy .mm-head { margin-bottom: 2.5rem; }
.nx-legacy .mm-h1 { font-family: var(--font-serif); font-weight: 300;
  font-size: 2.8rem; letter-spacing: -0.01em; color: var(--text-primary); margin: 0; }
.nx-legacy .mm-sub { color: var(--text-secondary); margin: 0.3rem 0 1.4rem; }
.nx-legacy .mm-modes { display: flex; gap: 0.5rem; border-bottom: 1px solid var(--border-light, var(--border-subtle)); }
.nx-legacy .mm-mode { padding: 0.6rem 1rem; color: var(--text-secondary); text-decoration: none; font-weight: 500;
  border-bottom: 2px solid transparent; margin-bottom: -1px; }
.nx-legacy .mm-mode.active { color: var(--accent, var(--fg-success)); border-bottom-color: var(--accent, var(--fg-success)); }
.nx-legacy .mm-soon { font-size: 0.6rem; text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--text-tertiary); border: 1px solid var(--border-light, var(--border-subtle)); border-radius: var(--radius-pill); padding: 0.05em 0.45em; }

.nx-legacy .mm-patents { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.75rem; }
.nx-legacy .mm-patent-link { display: flex; align-items: center; gap: 1.25rem; padding: 1.1rem 1.25rem;
  background: var(--bg-base, var(--bg-component)); border: 1px solid var(--border-light, var(--border-subtle)); border-radius: 12px;
  text-decoration: none; color: inherit; box-shadow: none; transition: box-shadow var(--duration-150) var(--ease-in-out), transform var(--duration-150) var(--ease-in-out); }
.nx-legacy .mm-patent-link:hover { box-shadow: none; transform: translateY(-1px); }
.nx-legacy .mm-rank { font-family: var(--font-serif); font-size: 1.6rem; font-weight: 300;
  color: var(--text-primary); width: 1.5rem; text-align: center; flex: none; }
.nx-legacy .mm-patent-main { display: flex; flex-direction: column; gap: 0.2rem; flex: 1; min-width: 0; }
.nx-legacy .mm-patent-title { font-weight: 600; color: var(--text-primary); }
.nx-legacy .mm-patent-meta { font-size: 0.8rem; color: var(--text-tertiary); }
.nx-legacy .mm-patent-matches { font-size: 0.82rem; color: var(--accent, var(--fg-success)); }
.nx-legacy .mm-section-head { display: flex; align-items: baseline; gap: 0.6rem; flex-wrap: wrap;
  margin: 1.6rem 0 0.7rem; }
.nx-legacy .mm-section-head:first-of-type { margin-top: 0.4rem; }
.nx-legacy .mm-section-h { font-family: var(--font-serif); font-weight: 300; font-size: 1.5rem;
  color: var(--text-primary); margin: 0; }
.nx-legacy .mm-section-sub { font-size: 0.78rem; color: var(--text-tertiary); }
.nx-legacy .mm-patent-top .mm-patent-link { border-color: color-mix(in srgb, var(--fg-success) 28%, transparent); background: linear-gradient(180deg, color-mix(in srgb, var(--fg-success) 4%, transparent), var(--bg-base,var(--bg-component)) 60%); }
.nx-legacy .mm-rank-promise { color: var(--green, var(--fg-success)); font-weight: 500; }
.nx-legacy .mm-group-tag { align-self: flex-start; font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.04em;
  color: var(--text-primary); background: color-mix(in srgb, var(--fg-info) 9%, transparent); padding: 0.1rem 0.45rem; border-radius: var(--radius-pill,999px); }
.nx-legacy .mm-promise-note { font-size: 0.86rem; color: var(--text-secondary); line-height: 1.45; margin-top: 0.15rem; }
.nx-legacy .mm-promise-caveat { font-size: 0.8rem; color: var(--text-tertiary); line-height: 1.4; }
.nx-legacy .mm-promise-caveat strong { color: var(--text-secondary); }
.nx-legacy .mm-unlic { color: var(--green, var(--fg-success)); font-weight: 600; }
.nx-legacy .mm-demand { display: flex; flex-direction: column; align-items: center; flex: none; padding-left: 1rem;
  border-left: 1px solid var(--border-light, var(--border-subtle)); }
.nx-legacy .mm-demand-n { font-family: var(--font-serif); font-size: 1.7rem; font-weight: 300; color: var(--text-primary); }
.nx-legacy .mm-demand-l { font-size: 0.62rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-tertiary); }
.nx-legacy .mm-promise { display: flex; flex-direction: column; align-items: center; flex: none; min-width: 4.2rem;
  padding: 0.3rem 0.2rem 0.3rem 1rem; border-left: 1px solid var(--border-light, var(--border-subtle)); }
.nx-legacy .mm-promise-n { font-family: var(--font-serif); font-size: 2rem; font-weight: 300; line-height: 1; }
.nx-legacy .mm-promise-l { font-size: 0.62rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-tertiary); margin-top: 0.1rem; }
.nx-legacy .mm-promise-high .mm-promise-n { color: var(--green, var(--fg-success)); }
.nx-legacy .mm-promise-mid .mm-promise-n { color: var(--cat-cardio); }
.nx-legacy .mm-promise-low .mm-promise-n { color: var(--amber, var(--fg-warning)); }
.nx-legacy .mm-promise-low .mm-promise-l { color: var(--amber, var(--fg-warning)); }

.nx-legacy .mm-teaser { text-align: center; padding: 4rem 2rem; background: var(--bg-raised, var(--bg-subtle));
  border: 1px dashed var(--border-light, var(--border-subtle)); border-radius: var(--radius-xl); }
.nx-legacy .mm-teaser-badge { display: inline-block; font-size: 0.7rem; text-transform: uppercase; letter-spacing: 0.1em;
  color: var(--amber, var(--fg-warning)); margin-bottom: 0.75rem; }
.nx-legacy .mm-teaser-text { max-width: 34rem; margin: 0 auto; color: var(--text-secondary); }

.nx-legacy .mm-deck-shell { max-width: 720px; margin: 0 auto; padding: 1.5rem 1.5rem 4rem; }
.nx-legacy .mm-ctxbar { display: flex; align-items: center; gap: 1rem; padding: 0.75rem 0 1.25rem; border-bottom: 1px solid var(--border-light,var(--border-subtle)); margin-bottom: 1.5rem; }
.nx-legacy .mm-back { color: var(--text-secondary); text-decoration: none; font-size: 0.85rem; flex: none; }
.nx-legacy .mm-ctx { flex: 1; display: flex; flex-direction: column; gap: 0.1rem; align-items: flex-start;
  background: none; border: 0; padding: 0.35rem 0.5rem; margin: -0.35rem -0.5rem; border-radius: var(--radius-lg);
  text-align: left; cursor: pointer; transition: background var(--duration-150) var(--ease-in-out); }
.nx-legacy .mm-ctx:hover { background: color-mix(in srgb, var(--fg-info) 6%, transparent); }
.nx-legacy .mm-ctx-title { font-weight: 600; color: var(--text-primary); }
.nx-legacy .mm-ctx-info { font-size: 0.72rem; font-weight: 500; color: var(--text-primary); white-space: nowrap; }
.nx-legacy .mm-ctx:hover .mm-ctx-info { text-decoration: underline; }
.nx-legacy .mm-ctx-meta { font-size: 0.78rem; color: var(--text-tertiary); }
.nx-legacy .mm-ctx-progress { font-size: 0.8rem; color: var(--text-tertiary); flex: none; }

.nx-legacy .mm-stage { position: relative; min-height: 520px; }
.nx-legacy .mm-card { position: absolute; inset: 0; background: var(--bg-base,var(--bg-component)); border: 1px solid var(--border-light,var(--border-subtle));
  border-radius: var(--radius-2xl); padding: 1.5rem 1.6rem; box-shadow: none;
  display: flex; flex-direction: column; gap: 1rem; overflow-y: auto;
  transition: transform var(--duration-300) var(--ease-emphasis), opacity var(--duration-300) var(--ease-emphasis); }
.nx-legacy .mm-card[hidden] { display: none; }
.nx-legacy .mm-card.mm-gone-left { transform: translateX(-120%) rotate(-8deg); opacity: 0; }
.nx-legacy .mm-card.mm-gone-right { transform: translateX(120%) rotate(8deg); opacity: 0; }

.nx-legacy .mm-card-idrow { display: flex; justify-content: space-between; align-items: center; gap: 0.75rem; }
.nx-legacy .mm-card-id { display: flex; align-items: center; gap: 0.7rem; min-width: 0; }
.nx-legacy .mm-avatar { flex: none; width: 2.6rem; height: 2.6rem; border-radius: 12px; display: inline-flex;
  align-items: center; justify-content: center; font-family: var(--font-sans);
  font-weight: 700; font-size: 0.9rem; letter-spacing: 0.02em; color: var(--fg-oncolor); background: var(--navy,var(--fg-info));
  box-shadow: inset 0 -2px 6px var(--black-16); }
.nx-legacy .mm-avatar-high { background: var(--accent-fill); color: var(--text-on-accent); }
.nx-legacy .mm-avatar-watch { background: var(--garnet,var(--fg-danger)); }
.nx-legacy .mm-card-name { font-family: var(--font-serif); font-weight: 300; font-size: 1.9rem;
  color: var(--text-primary); margin: 0; line-height: 1.05; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nx-legacy .mm-progress { font-size: 0.72rem; color: var(--text-tertiary); flex: none; }
.nx-legacy .mm-card-facts { font-size: 0.82rem; color: var(--text-secondary); line-height: 1.5; }
.nx-legacy .mm-fit { display: inline-flex; align-items: center; margin: 0.6rem 0 0.5rem; font-size: 0.74rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.06em; padding: 0.3em 0.75em; border-radius: var(--radius-pill);
  border: 1px solid transparent; }
.nx-legacy .mm-why { font-size: 0.92rem; color: var(--text-primary); margin: 0; line-height: 1.5; }

.nx-legacy .mm-detail { position: relative; background: var(--bg-base,var(--bg-component)); border: 1px solid var(--border-light,var(--border-subtle));
  border-radius: 16px; padding: 1.6rem 1.7rem; box-shadow: none;
  max-height: 82vh; overflow-y: auto; display: flex; flex-direction: column; gap: 1rem; }
.nx-legacy .mm-detail-x { position: absolute; top: 0.9rem; right: 1rem; border: 0; background: none; cursor: pointer;
  font-size: 1rem; color: var(--text-tertiary); line-height: 1; padding: 0.3rem; }
.nx-legacy .mm-detail-x:hover { color: var(--text-primary); }
.nx-legacy .mm-detail-kicker { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; font-size: 0.7rem;
  text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-tertiary); }
.nx-legacy .mm-detail-rank { color: var(--green,var(--fg-success)); font-weight: 700; }
.nx-legacy .mm-detail-title { font-family: var(--font-serif); font-weight: 300; font-size: 1.55rem;
  color: var(--text-primary); margin: 0; line-height: 1.15; text-wrap: balance; }
.nx-legacy .mm-detail-idrow { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; font-size: 0.82rem; }
.nx-legacy .mm-detail-no { font-weight: 600; color: var(--text-primary); font-variant-numeric: tabular-nums; }
.nx-legacy .mm-detail-link { color: var(--text-primary); text-decoration: none; font-weight: 600; }
.nx-legacy .mm-detail-link:hover { text-decoration: underline; }
.nx-legacy .mm-chip { font-size: 0.66rem; text-transform: uppercase; letter-spacing: 0.04em; padding: 0.12rem 0.5rem;
  border-radius: var(--radius-pill); font-weight: 600; }
.nx-legacy .mm-chip-green { color: var(--green,var(--fg-success)); background: color-mix(in srgb, var(--fg-success) 10%, transparent); }
.nx-legacy .mm-chip-amber { color: var(--amber,var(--fg-warning)); background: color-mix(in srgb, var(--fg-warning) 10%, transparent); }
.nx-legacy .mm-chip-warn { color: var(--garnet,var(--fg-danger)); background: color-mix(in srgb, var(--fg-danger) 10%, transparent); }
.nx-legacy .mm-detail-grid { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: 0.7rem 1.2rem; margin: 0;
  padding: 0.9rem 0; border-top: 1px solid var(--border-light,var(--border-subtle)); border-bottom: 1px solid var(--border-light,var(--border-subtle)); }
.nx-legacy .mm-detail-grid dt { font-size: 0.66rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--text-tertiary); margin-bottom: 0.15rem; }
.nx-legacy .mm-detail-grid dd { margin: 0; font-size: 0.86rem; color: var(--text-primary); }
.nx-legacy .mm-detail-label { font-size: 0.66rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-tertiary); margin-bottom: 0.35rem; }
.nx-legacy .mm-detail-note { font-size: 0.88rem; color: var(--text-primary); line-height: 1.5; margin: 0; }
.nx-legacy .mm-detail-caveat { font-size: 0.82rem; color: var(--text-tertiary); line-height: 1.45; margin: 0.35rem 0 0; }
.nx-legacy .mm-detail-abstract p { font-size: 0.88rem; color: var(--text-primary); line-height: 1.6; margin: 0; }
.nx-legacy .mm-detail-warn { font-size: 0.85rem; color: var(--garnet,var(--fg-danger)); background: color-mix(in srgb, var(--fg-danger) 7%, transparent);
  border: 1px solid color-mix(in srgb, var(--fg-danger) 18%, transparent); border-radius: var(--radius-lg); padding: 0.7rem 0.85rem; line-height: 1.5; }
.nx-legacy .mm-detail-claims { border-top: 1px solid var(--border-light,var(--border-subtle)); padding-top: 0.6rem; }
.nx-legacy .mm-detail-claims summary { cursor: pointer; font-size: 0.8rem; font-weight: 600; color: var(--text-primary); }
.nx-legacy .mm-detail-claimtext { margin: 0.6rem 0 0; max-height: 40vh; overflow-y: auto; white-space: pre-wrap;
  font-family: var(--font-sans); font-size: 0.78rem; color: var(--text-secondary); line-height: 1.5;
  background: var(--bg-raised,var(--bg-subtle)); border-radius: 8px; padding: 0.8rem; }

.nx-legacy .mm-zone { border-top: 1px solid var(--border-light,var(--border-subtle)); padding-top: 0.9rem; }
.nx-legacy .mm-zone-label { font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-tertiary); margin-bottom: 0.55rem; }
.nx-legacy .mm-foot { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.35rem; }
.nx-legacy .mm-foot-row { display: grid; grid-template-columns: 11rem 1fr auto; align-items: center; gap: 0.6rem; font-size: 0.82rem; }
.nx-legacy .mm-foot-area { color: var(--text-primary); }
.nx-legacy .mm-foot-bar { height: 8px; background: var(--bg-active, var(--border-subtle)); border-radius: 4px; overflow: hidden; }
.nx-legacy .mm-foot-fill { display: block; height: 100%; background: var(--navy,var(--fg-info)); }
.nx-legacy .mm-foot-n { text-align: right; color: var(--text-secondary); white-space: nowrap; }
.nx-legacy .mm-trials { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.55rem; }
.nx-legacy .mm-trial-row { display: flex; flex-direction: column; gap: 0.2rem; }
.nx-legacy .mm-trial-title { font-size: 0.85rem; color: var(--text-primary); line-height: 1.35; }
.nx-legacy .mm-trial-mat { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; font-size: 0.76rem; }
.nx-legacy .mm-trial-status { text-transform: capitalize; color: var(--text-tertiary); }
.nx-legacy .mm-trial-status.mm-ts-active { color: var(--green,var(--fg-success)); font-weight: 600; }
.nx-legacy .mm-trial-nct { color: var(--text-tertiary); font-variant-numeric: tabular-nums; margin-left: auto; }
.nx-legacy .mm-foot-row-match .mm-foot-area { color: var(--green,var(--fg-success)); font-weight: 600; }
.nx-legacy .mm-foot-row-match .mm-foot-fill { background: var(--green,var(--fg-success)); }
.nx-legacy .mm-foot-tag { font-size: 0.66rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--green,var(--fg-success));
    background: color-mix(in srgb, var(--fg-success) 10%, transparent); padding: 0.05rem 0.35rem; border-radius: var(--radius-pill,999px); margin-left: 0.3rem; }
.nx-legacy .mm-foot-recent { color: var(--text-muted, var(--fg-muted)); font-size: 0.72rem; }
.nx-legacy .mm-lic { color: var(--amber, var(--fg-warning)); font-weight: 600; }

.nx-legacy .mm-pipe { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.6rem; }
.nx-legacy .mm-pipe-top { font-size: 0.88rem; }
.nx-legacy .mm-pipe-name { font-weight: 600; color: var(--text-primary); }
.nx-legacy .mm-pipe-moa { color: var(--text-secondary); }
.nx-legacy .mm-pipe-mat { display: flex; align-items: center; gap: 0.5rem; font-size: 0.78rem; color: var(--text-secondary); margin-top: 0.15rem; }
.nx-legacy .mm-pipe-status { font-weight: 600; padding: 0.05em 0.5em; border-radius: var(--radius-pill); }
.nx-legacy .mm-status-approved { background: color-mix(in srgb, var(--fg-success) 12%, transparent); color: var(--accent,var(--fg-success)); }
.nx-legacy .mm-status-trial { background: color-mix(in srgb, var(--fg-info) 12%, transparent); color: var(--text-primary); }
.nx-legacy .mm-pipe-sales { color: var(--text-tertiary); }
.nx-legacy .mm-pipe-empty { font-size: 0.85rem; color: var(--text-tertiary); margin: 0; }

.nx-legacy .mm-card-actions { position: sticky; bottom: 0; margin: 0.4rem -1.6rem -1.5rem; padding: 0.85rem 1.6rem 1.05rem;
  display: flex; gap: 0.75rem; background: linear-gradient(180deg, transparent, var(--bg-base,var(--bg-component)) 32%);
  border-top: 1px solid var(--border-light,var(--border-subtle)); }
.nx-legacy .mm-btn { flex: 1; display: inline-flex; align-items: center; justify-content: center; gap: 0.4rem;
  padding: 0.8rem 1rem; border-radius: 12px; font-weight: 600; font-size: 0.95rem; cursor: pointer;
  border: 1px solid transparent; transition: transform var(--duration-100) var(--ease-in-out), box-shadow var(--duration-150) var(--ease-in-out), background var(--duration-150) var(--ease-in-out); }
.nx-legacy .mm-btn:hover { transform: translateY(-1px); }
.nx-legacy .mm-btn:active { transform: translateY(0); }
.nx-legacy .mm-btn-ic { font-size: 0.9em; line-height: 1; }
.nx-legacy .mm-pass { background: var(--bg-surface); border-color: var(--border-light,var(--border-subtle)); color: var(--text-secondary); }
.nx-legacy .mm-pass:hover { border-color: var(--fg-danger); color: var(--garnet,var(--fg-danger)); box-shadow: none; }
.nx-legacy .mm-like { background: var(--accent-fill); color: var(--text-on-accent); text-align: center; }
.nx-legacy .mm-like:hover { background: var(--accent-hover); }
.nx-legacy .mm-like .mm-btn-ic { color: var(--text-on-accent); }
.nx-legacy .mm-done { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; text-align: center; }
.nx-legacy .mm-done[hidden] { display: none; }   .nx-legacy .mm-done-inner { color: var(--text-secondary); }
.nx-legacy .mm-done-h { font-family: var(--font-serif); font-weight: 300; font-size: 1.8rem; color: var(--text-primary); }

.nx-legacy .mm-reason { position: absolute; inset: 0; display: flex; flex-direction: column; justify-content: center;
  align-items: center; gap: 1rem; background: var(--bg-raised,var(--bg-subtle)); border: 1px solid var(--border-light,var(--border-subtle));
  border-radius: var(--radius-2xl); padding: 2rem; text-align: center; }
.nx-legacy .mm-reason-q { color: var(--text-secondary); }
.nx-legacy .mm-reason-q em { color: var(--text-tertiary); font-style: italic; }
.nx-legacy .mm-reason-chips { display: flex; flex-wrap: wrap; gap: 0.5rem; justify-content: center; max-width: 26rem; }
.nx-legacy .mm-reason-chip { padding: 0.45rem 0.85rem; border-radius: var(--radius-pill); border: 1px solid var(--border-light,var(--border-subtle));
  background: var(--bg-surface); color: var(--text-primary); cursor: pointer; font-size: 0.85rem; }
.nx-legacy .mm-reason-chip:hover { border-color: var(--text-primary); color: var(--text-primary); }
.nx-legacy .mm-reason-skip { background: transparent; color: var(--text-tertiary); }

.nx-legacy .mm-overlay { position: fixed; inset: 0; background: var(--bg-overlay); display: flex;
  align-items: center; justify-content: center; padding: 1.5rem; z-index: 50; }
.nx-legacy .mm-overlay-inner { width: 100%; max-width: 540px; }
.nx-legacy .mm-draft-card { background: var(--bg-base,var(--bg-component)); border: 1px solid var(--border-light,var(--border-subtle));
  border-radius: var(--radius-xl); padding: 1.5rem; box-shadow: none; }
.nx-legacy .mm-draft-flag { color: var(--accent,var(--fg-success)); font-weight: 600; font-size: 0.85rem; margin-bottom: 1rem; }
.nx-legacy .mm-draft-field { display: flex; gap: 0.75rem; padding: 0.4rem 0; border-bottom: 1px solid var(--border-light,var(--border-subtle)); font-size: 0.9rem; }
.nx-legacy .mm-draft-k { color: var(--text-tertiary); width: 3.5rem; flex: none; }
.nx-legacy .mm-draft-body { padding: 1rem 0; color: var(--text-primary); font-size: 0.92rem; line-height: 1.5; display: flex; flex-direction: column; gap: 0.6rem; }
.nx-legacy .mm-draft-foot { display: flex; align-items: center; justify-content: space-between; padding-top: 0.5rem; }
.nx-legacy .mm-draft-attach { font-size: 0.85rem; color: var(--text-primary); }
.nx-legacy .mm-draft-foot .mm-like { flex: none; padding: 0.5rem 1.3rem; }

.nx-legacy .side-new {
    display: flex; align-items: center; gap: 0.5rem;
    margin: 0.25rem 0.5rem 0.25rem;
    padding: 0.5rem 0.625rem;
    border: 0;
    border-radius: var(--radius-md);
    background: transparent;
    color: var(--text-primary);
    font-family: var(--font-mono);
    font-size: 12px; font-weight: 500; letter-spacing: 0.5px; text-transform: uppercase;
    cursor: pointer; transition: background var(--duration-100) var(--ease-in-out);
}
.nx-legacy .side-new svg { width: 14px; height: 14px; flex: none; color: currentColor; }
.nx-legacy .side-new:hover { background: var(--interactive-hover); }

.nx-legacy .recent-list { display: flex; flex-direction: column; gap: 1px; }
.nx-legacy .recent-empty {
    padding: 0.25rem 0.5rem; font-size: 12px; line-height: 1.4;
    color: var(--text-tertiary); font-family: var(--font-sans);
}

.nx-legacy .side-user {
    display: flex; align-items: center; gap: 0.5rem; width: 100%;
    padding: 0.45rem 0.5rem; border: 0; background: transparent;
    border-radius: var(--radius-md); cursor: pointer; text-align: left;
    transition: background var(--duration-100) var(--ease-in-out);
}
.nx-legacy .side-user-av {
    width: 26px; height: 26px; flex: none; border-radius: var(--radius-sm);
    display: grid; place-items: center;
    background: var(--accent-fill); color: var(--text-on-accent);
    font-family: var(--font-mono); font-weight: 500; font-size: 12px;
}
.nx-legacy .side-user-meta { display: flex; flex-direction: column; line-height: 1.25; min-width: 0; flex: 1 1 auto; }
.nx-legacy .side-user-name { font-size: 13px; font-weight: 500; color: var(--text-primary); }
.nx-legacy .side-user-role { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.4px;
    text-transform: uppercase; color: var(--text-tertiary); }

.nx-legacy .ax {
    height: 100vh; display: flex; flex-direction: row; min-height: 0;
    background: var(--bg-base);
}

.nx-legacy .ax-error { color: var(--status-error); font-size: 0.9rem; }


.nx-legacy .ax-error { color: var(--status-error); font-size: 0.9rem; }

.nx-legacy .doc { max-width: 620px; color: var(--text-primary); font-family: var(--font-sans); }
.nx-legacy .side-new { border-radius: var(--radius-xl); padding: 0.6rem 0.8rem; }

.nx-legacy .side-new, .nx-legacy .sidebar-group-kicker, .nx-legacy .theme-toggle-label, .nx-legacy .side-user-role, .nx-legacy .ax-eyebrow, .nx-legacy .ax-starter-k, .nx-legacy .ax-step, .nx-legacy .ax-next-label, .nx-legacy .ax-next-t, .nx-legacy .ax-card-type, .nx-legacy .ax-card-open, .nx-legacy .ax-disclaimer, .nx-legacy .ax-attach, .nx-legacy .ax-run, .nx-legacy .ax-art-kicker, .nx-legacy .ax-art-btn, .nx-legacy .doc-kicker, .nx-legacy .doc-letterhead-org, .nx-legacy .lr-kicker {
    font-family: var(--font-sans);
    text-transform: none;
    letter-spacing: normal;
}
.nx-legacy .side-new { font-size: 0.9rem; font-weight: 500; }
.nx-legacy .sidebar-group-kicker { font-size: 0.75rem; font-weight: 500; color: var(--text-tertiary); }
.nx-legacy .theme-toggle-label, .nx-legacy .side-user-role { font-size: 0.8rem; font-weight: 400; }

.nx-legacy .art-* report styling with the flat NUSX + claude aesthetic: drop the saturated green/navy, .nx-legacy flatten the promise ring to the brand accent, .nx-legacy neutralise data chips, .nx-legacy and refine the next-step suggestions. ========================================================================== */ .ax-next { gap: 0.5rem; margin-top: 1.25rem; padding-top: 1.1rem; }

.nx-legacy .art-rel { border-radius: var(--radius-pill); font-weight: 600; }
.nx-legacy .art-rel-high { color: var(--status-success); background: var(--status-success-bg); }
.nx-legacy .art-rel-mid { color: var(--status-warning); background: var(--status-warning-bg); }
.nx-legacy .art-rel-low { color: var(--text-secondary); background: var(--bg-raised); }
.nx-legacy .art-rel-watch { color: var(--status-error); background: var(--status-error-bg); }
.nx-legacy .art-rel, .nx-legacy .art-rel-high, .nx-legacy .art-rel-mid, .nx-legacy .art-rel-low, .nx-legacy .art-rel-watch {
    color: var(--text-secondary); background: var(--bg-raised); font-weight: 500;
}

.nx-legacy .art-rel-high { color: var(--status-success); background: var(--status-success-bg); }
.nx-legacy .art-rel-mid { color: var(--status-warning); background: var(--status-warning-bg); }
.nx-legacy .art-rel-low { color: var(--text-secondary); background: var(--bg-raised); }
.nx-legacy .art-rel-watch { color: var(--status-error);   background: var(--status-error-bg); }

.nx-legacy .nusx-logo { display: block; width: auto; height: 1em; }
.nx-legacy .sidebar-brand { color: var(--text-primary); display: inline-flex; align-items: center; }
.nx-legacy .sidebar-brand .nusx-logo { height: 17px; }

.nx-legacy .nusx-x { fill: var(--text-accent); }

/* remove — compact, hover-revealed (space reserved so the grid never shifts) */

/* Outreach actions live in their own narrow trailing column (see --ldf-cols above) with
   the Proposal / Email buttons STACKED (Anni, 2026-07-29 — the side-by-side pair read as
   crammed against the date). Scoped to min-width so the narrow-screen block below, which
   stacks the whole row via its own grid-areas, isn't outranked. */




.nx-legacy .mobile-topbar { display: none; }
.nx-legacy .sidebar-backdrop { display: none; }

@media (max-width: 900px) {

    .nx-legacy .mobile-topbar {
        display: flex;
        align-items: center;
        gap: 0.375rem;
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        height: var(--mobile-topbar-h);
        padding: 0 0.75rem;
        background: var(--bg-base);
        border-bottom: 1px solid var(--border);
        z-index: 90;
    }
    .nx-legacy .mobile-nav-btn {
        display: grid;
        place-items: center;
        width: 36px;
        height: 36px;
        border: none;
        background: none;
        color: var(--text-secondary);
        border-radius: var(--radius-sm);
        cursor: pointer;
    }
    .nx-legacy .mobile-nav-btn svg { width: 20px; height: 20px; }
    .nx-legacy .mobile-nav-btn:hover { background: var(--bg-raised); color: var(--text-primary); }
    .nx-legacy .mobile-nav-btn:focus-visible { outline: 1.5px solid var(--accent); outline-offset: 1px; }
    .nx-legacy .mobile-brand { display: inline-flex; align-items: center; color: var(--text-primary); }
    .nx-legacy .mobile-brand .nusx-logo { height: 15px; }

    .nx-legacy .sidebar {
        position: fixed;
        top: 0;
        left: 0;
        bottom: 0;
        height: 100dvh;
        transform: translateX(-100%);
        transition: transform var(--duration-300) var(--ease-emphasis);
        z-index: 110;
    }
    body.nx-legacy.sidebar-open .sidebar { transform: none; }
    body.nx-legacy.sidebar-open { overflow: hidden; }

    .nx-legacy .sidebar-backdrop {
        display: block;
        position: fixed;
        inset: 0;
        background: var(--bg-overlay);
        opacity: 0;
        pointer-events: none;
        transition: opacity var(--duration-200) var(--ease-out);
        z-index: 100;
    }
    body.nx-legacy.sidebar-open .sidebar-backdrop { opacity: 1; pointer-events: auto; }

    .nx-legacy .ax { height: calc(100vh - var(--mobile-topbar-h)); height: calc(100dvh - var(--mobile-topbar-h)); }
}

@media (max-width: 900px) and (prefers-reduced-motion: reduce) {
    .nx-legacy .sidebar, .nx-legacy .sidebar-backdrop { transition: none; }
}

@media (max-width: 720px) {
    .nx-legacy .page-bar { padding: 0 1rem; gap: 0.75rem; }
    .nx-legacy .page-bar-meta {
        min-width: 0;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
    .nx-legacy .page-content { padding: 1.25rem 1rem 2rem; }

    .nx-legacy .investor-list-header { grid-template-columns: 32px 1fr auto; }
    .nx-legacy .investor-list-header span:nth-child(3), .nx-legacy .investor-list-header span:nth-child(4), .nx-legacy .investor-list-header span:nth-child(5) { display: none; }
    .nx-legacy .investor-row { grid-template-columns: 32px 1fr auto; row-gap: 0.3rem; }
    .nx-legacy .investor-row .avatar { grid-row: 1; grid-column: 1; }
    .nx-legacy .investor-row .entity-row-main { grid-row: 1; grid-column: 2; }
    .nx-legacy .investor-row .entity-row-count { grid-row: 1; grid-column: 3; }
    .nx-legacy .investor-row .entity-row-cell {
        grid-column: 2 / -1;
        max-width: none;
        white-space: normal;
    }
    .nx-legacy .investor-row .entity-row-cell.is-empty { display: none; }

    .nx-legacy .mm-shell { padding: 2rem 1.25rem 4rem; }
    .nx-legacy .mm-deck-shell { padding: 1.25rem 1rem 3rem; }
    .nx-legacy .mm-card-name { white-space: normal; font-size: 1.5rem; line-height: 1.15; }

    .nx-legacy .stats-row { flex-wrap: wrap; }
    .nx-legacy .stat-block { flex: 1 1 40%; }
}