/* ==========================================================================
   FinNexus Global Terminal — design tokens (v3)
   The contract every page reads from. DESIGN_SYSTEM.md is the prose version.

   Three layers, in this order:
     1. --nx-*      brand + surface palette, one value per theme
     2. semantic    meaning: positive / negative / warning / info / neutral /
                    no-data. Colour is reserved for meaning — a green number
                    means the number is positive, not that we liked it.
     3. aliases     the older names (--bg, --ink, --accent, --pos …) that 17
                    pages and the chart renderers already read. They point at
                    layer 1/2, so the whole app moves when a token moves.

   Text-on-surface pairs are WCAG AA. Where a brand or semantic value is too
   light to be read as text on white (the spec's emerald, amber, teal), it
   keeps its exact value for fills, icons and charts and gets a darker *-ink
   sibling for text. Both are listed; nothing silently substitutes.
   ========================================================================== */
:root{
  color-scheme:light;

  /* ---- type ---- */
  --font-sans:"Inter var","Inter",-apple-system,BlinkMacSystemFont,"Segoe UI",
    Roboto,"Helvetica Neue",Arial,sans-serif;
  --font-display:"Manrope","Inter var","Inter",-apple-system,BlinkMacSystemFont,
    "Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
  --font-mono:"JetBrains Mono",ui-monospace,"SF Mono",Menlo,Consolas,monospace;

  /* Type and spacing travel their full range between a 360px phone and a
     1600px desktop, then hold. Past that, growing the text further hurts
     readability — the extra width goes into spacing and column count. */
  --fs-2xs:clamp(9.5px, 0.08065vw + 9.21px, 10.5px);
  --fs-xs:clamp(10.5px, 0.121vw + 10.06px, 12px);
  --fs-sm:clamp(11.5px, 0.1613vw + 10.92px, 13.5px);
  --fs-base:clamp(13px, 0.2016vw + 12.27px, 15.5px);
  --fs-md:clamp(14px, 0.2419vw + 13.13px, 17px);
  --fs-lg:clamp(16px, 0.3226vw + 14.84px, 20px);
  --fs-xl:clamp(20px, 0.6452vw + 17.68px, 28px);
  --fs-2xl:clamp(24px, 0.9677vw + 20.52px, 36px);
  --fs-3xl:clamp(32px, 1.613vw + 26.19px, 52px);
  /* named roles on top of the scale (DESIGN_SYSTEM.md §Typography) */
  --fs-display:clamp(34px, 2.4194vw + 25.290px, 64px);
  --fs-h1:clamp(26px, 1.1290vw + 21.935px, 40px);
  --fs-h2:clamp(21px, 0.7258vw + 18.387px, 30px);
  --fs-h3:clamp(16px, 0.3226vw + 14.839px, 20px);
  --fs-label:clamp(10.5px, 0.1210vw + 10.065px, 12px);

  /* the two smallest steps stay fixed — a 4px gap is a 4px gap at any size */
  --sp-1:4px;
  --sp-2:8px;
  --sp-3:clamp(10px, 0.1613vw + 9.419px, 12px);
  --sp-4:clamp(12px, 0.4032vw + 10.55px, 17px);
  --sp-5:clamp(16px, 0.8065vw + 13.1px, 26px);
  --sp-6:clamp(20px, 1.29vw + 15.35px, 36px);
  --sp-7:clamp(28px, 2.258vw + 19.87px, 56px);
  --sp-8:clamp(40px, 3.548vw + 27.23px, 84px);

  /* ---- geometry: one radius per role, no others ---- */
  --r-sm:8px;     /* small controls, chips */
  --r-md:10px;    /* inputs, buttons */
  --r-lg:14px;    /* every analytical card */
  --r-xl:18px;    /* large marketing panels */
  --r-pill:999px;

  --nx-shell-topbar:64px;
  --nx-shell-sidebar:232px;
  --nx-max-app:1800px;
  --nx-max-marketing:1440px;

  /* ---- motion: restrained, shared, never looping on data ---- */
  --motion-fast:140ms;
  --motion-normal:220ms;
  --motion-panel:320ms;
  --motion-enter:520ms;
  --motion-chart:700ms;
  --ease-nx:cubic-bezier(.22,.61,.36,1);
  --ease:var(--ease-nx);
  --nx-px:0px;           /* world-network parallax offset, set by script */
  --nx-py:0px;

  /* ---- 1. brand + surfaces (light) ---- */
  --nx-bg:#F5FAFE;
  --nx-bg-secondary:#EEF7FC;
  --nx-bg-gradient:linear-gradient(180deg,#F7FBFF 0%,#F5FAFE 40%,#EEF7FC 100%);
  --nx-surface:#FFFFFF;
  --nx-surface-soft:#F8FBFE;
  --nx-surface-elevated:#FFFFFF;
  --nx-surface-glass:rgba(255,255,255,.86);
  --nx-navy-950:#06182E;
  --nx-navy-900:#082442;
  --nx-navy-800:#0A3564;
  --nx-text:#0A2242;
  --nx-text-2:#26405E;               /* between primary and secondary */
  --nx-text-secondary:#516A82;
  --nx-text-muted:#7E94A8;           /* decorative / non-essential only */
  --nx-text-muted-ink:#5D758B;       /* muted, AA-readable as text */
  --nx-border:#DCEAF4;
  --nx-border-strong:#C5DCEB;
  --nx-border-heavy:#A7C3D8;
  --nx-blue:#1477E8;
  --nx-blue-ink:#0F68D0;             /* AA as text and under white */
  --nx-blue-deep:#0B4FA6;
  --nx-blue-soft:#E7F2FD;
  --nx-cyan:#16C7E8;
  --nx-teal:#0CB9AE;
  --nx-teal-ink:#08857D;
  --nx-brand-green:#0AA77C;
  --nx-brand-gradient:linear-gradient(100deg,#0F68D0 0%,#0CA7C2 52%,#0AA77C 100%);
  --nx-primary-bg:linear-gradient(180deg,#0C3D72 0%,#082B55 100%);
  --nx-primary-bg-hover:linear-gradient(180deg,#0F4A88 0%,#0A3564 100%);
  --nx-focus-ring:0 0 0 3px rgba(20,119,232,.22);

  --nx-shadow-card:0 10px 35px rgba(18,61,94,.08);
  --nx-shadow-elevated:0 18px 50px rgba(13,57,91,.10);
  --nx-shadow-hairline:0 1px 2px rgba(18,61,94,.06);

  /* the world-network motif (DESIGN_SYSTEM.md §World network) */
  --nx-map-dot:#0A3564;
  --nx-map-arc:#1A8BD6;
  --nx-map-node:#1477E8;
  --nx-map-node-ring:rgba(20,119,232,.18);
  --nx-map-pulse:#16C7E8;
  --nx-map-opacity-marketing:.09;
  --nx-map-opacity-app:.035;
  --nx-map-arc-opacity:.65;

  /* ---- 2. semantic (light) ---- */
  --nx-positive:#0DAA78;   --nx-positive-ink:#08795A;  --nx-positive-soft:#E5F6EF;
  --nx-negative:#E45667;   --nx-negative-ink:#C2374A;  --nx-negative-soft:#FDECEE;
  --nx-warning:#E6A43A;    --nx-warning-ink:#94600C;   --nx-warning-soft:#FDF4E3;
  --nx-info:#307FE8;       --nx-info-ink:#1F66C9;      --nx-info-soft:#E8F1FD;
  --nx-neutral:#74879A;    --nx-neutral-ink:#5B6E80;   --nx-neutral-soft:#EEF2F6;
  --nx-nodata:#A2AFBB;     --nx-nodata-ink:#677685;    --nx-nodata-soft:#F1F4F7;

  /* ---- charts: one palette for every chart in the product ---- */
  --chart-primary:#10BFB3;        /* the security */
  --chart-benchmark:#397FF2;
  --chart-secondary:#7868E8;
  --chart-tertiary:#2AB1D7;
  --chart-positive:#0DBD91;       /* positive strategy */
  --chart-negative:#E75A69;       /* negative / drawdown */
  --chart-warning:#E6A33B;
  --chart-candle-up:#0ABF98;
  --chart-candle-down:#E45D70;
  --chart-volume-up:rgba(10,191,152,.45);
  --chart-volume-down:rgba(228,93,112,.38);
  --chart-ma-20:#13C5D9;
  --chart-ma-50:#357DF3;
  --chart-ma-100:#6B73E8;
  --chart-ma-200:#8867DE;
  --chart-vwap:#E8A83D;           /* VWAP / reference */
  --chart-support-fill:rgba(13,189,145,.12);
  --chart-support-line:#0DBD91;
  --chart-resistance-fill:rgba(231,90,105,.11);
  --chart-resistance-line:#E75A69;
  --chart-reference:#8294A6;
  --chart-grid:rgba(10,53,100,.07);
  --chart-grid-faint:rgba(10,53,100,.025);
  --chart-axis:#7E94A8;
  --chart-area-top:rgba(16,191,179,.20);
  --chart-area-bottom:rgba(16,191,179,0);

  /* ---- 3. aliases read by existing pages and renderers ---- */
  --bg:var(--nx-bg);
  --surface:var(--nx-surface);
  --surface-2:var(--nx-surface-soft);
  --surface-3:var(--nx-bg-secondary);
  --ink:var(--nx-text);
  --ink-2:var(--nx-text-2);
  --ink-3:var(--nx-text-secondary);
  --ink-4:var(--nx-text-muted-ink);
  --line:var(--nx-border);
  --line-2:var(--nx-border-strong);
  --line-3:var(--nx-border-heavy);

  --accent:var(--nx-blue-ink);
  --accent-ink:var(--nx-blue-deep);
  --accent-soft:var(--nx-blue-soft);

  --pos:var(--nx-positive-ink);   --pos-soft:var(--nx-positive-soft);
  --neg:var(--nx-negative-ink);   --neg-soft:var(--nx-negative-soft);
  --warn:var(--nx-warning-ink);   --warn-soft:var(--nx-warning-soft);
  --info:var(--nx-info-ink);      --info-soft:var(--nx-info-soft);
  --muted-rail:var(--nx-nodata);

  --shadow-sm:var(--nx-shadow-hairline);
  --shadow-md:var(--nx-shadow-card);
  --shadow-lg:var(--nx-shadow-elevated);

  --console-bg:#06182E;
  --console-ink:#C9DAEA;
  --console-dim:#7790A8;
}

/* Dark is a terminal, not an inversion: hierarchy comes from surface
   elevation and border luminosity, not from glow. */
[data-theme="dark"]{
  color-scheme:dark;

  --nx-bg:#031225;
  --nx-bg-secondary:#04182C;
  --nx-bg-gradient:linear-gradient(180deg,#020D1A 0%,#03172B 45%,#041B32 100%);
  --nx-surface:#071C33;
  --nx-surface-soft:#0A223B;
  --nx-surface-elevated:#0D2947;
  --nx-surface-glass:rgba(7,28,51,.88);
  --nx-text:#F3F9FE;
  --nx-text-2:#D2E0EC;
  --nx-text-secondary:#A9BED2;
  --nx-text-muted:#748CA3;
  --nx-text-muted-ink:#8099B0;
  --nx-border:rgba(91,178,233,.14);
  --nx-border-strong:rgba(80,192,240,.24);
  --nx-border-heavy:rgba(80,192,240,.36);
  --nx-blue:#3F98FF;
  --nx-blue-ink:#5AA8FF;
  --nx-blue-deep:#8CC3FF;
  --nx-blue-soft:rgba(63,152,255,.14);
  --nx-cyan:#26D5F4;
  --nx-teal:#16D1BD;
  --nx-teal-ink:#16D1BD;
  --nx-brand-green:#17C693;
  --nx-brand-gradient:linear-gradient(100deg,#3F98FF 0%,#26D5F4 50%,#17C693 100%);
  --nx-primary-bg:linear-gradient(180deg,#1A6FD6 0%,#1259B5 100%);
  --nx-primary-bg-hover:linear-gradient(180deg,#2580EA 0%,#1667C8 100%);
  --nx-focus-ring:0 0 0 3px rgba(38,213,244,.26);

  --nx-shadow-card:0 10px 30px rgba(0,6,16,.38);
  --nx-shadow-elevated:0 18px 50px rgba(0,6,16,.50);
  --nx-shadow-hairline:0 1px 2px rgba(0,6,16,.40);

  --nx-map-dot:#5FB4F0;
  --nx-map-arc:#26D5F4;
  --nx-map-node:#3F98FF;
  --nx-map-node-ring:rgba(38,213,244,.22);
  --nx-map-pulse:#7FE8FA;
  --nx-map-opacity-marketing:.12;
  --nx-map-opacity-app:.055;
  --nx-map-arc-opacity:.7;

  --nx-positive:#24C997;   --nx-positive-ink:#24C997;  --nx-positive-soft:rgba(36,201,151,.13);
  --nx-negative:#FF7180;   --nx-negative-ink:#FF7180;  --nx-negative-soft:rgba(255,113,128,.13);
  --nx-warning:#E6A43A;    --nx-warning-ink:#E6A43A;   --nx-warning-soft:rgba(230,164,58,.13);
  --nx-info:#5B9BF0;       --nx-info-ink:#5B9BF0;      --nx-info-soft:rgba(91,155,240,.14);
  --nx-neutral:#8A9DB0;    --nx-neutral-ink:#A3B4C5;   --nx-neutral-soft:rgba(138,157,176,.12);
  --nx-nodata:#5E7186;     --nx-nodata-ink:#8A9BAD;    --nx-nodata-soft:rgba(94,113,134,.14);

  --chart-grid:rgba(120,190,240,.09);
  --chart-grid-faint:rgba(120,190,240,.03);
  --chart-axis:#748CA3;
  --chart-reference:#7F93A8;
  --chart-area-top:rgba(16,191,179,.26);

  --console-bg:#020D1A;
  --console-ink:#C2D3E4;
  --console-dim:#6D86A0;
}

/* The aliases are restated wherever data-theme is set, not only on :root.
   A custom property that references another is resolved on the element that
   declares it — so if data-theme sits on <body> (the design snapshots do
   this) and the aliases lived only on <html>, <body> would inherit aliases
   already resolved against the light palette. */
[data-theme="dark"],[data-theme="light"]{
  --bg:var(--nx-bg);
  --surface:var(--nx-surface);
  --surface-2:var(--nx-surface-soft);
  --surface-3:var(--nx-bg-secondary);
  --ink:var(--nx-text);
  --ink-2:var(--nx-text-2);
  --ink-3:var(--nx-text-secondary);
  --ink-4:var(--nx-text-muted-ink);
  --line:var(--nx-border);
  --line-2:var(--nx-border-strong);
  --line-3:var(--nx-border-heavy);
  --accent:var(--nx-blue-ink);
  --accent-ink:var(--nx-blue-deep);
  --accent-soft:var(--nx-blue-soft);
  --pos:var(--nx-positive-ink);   --pos-soft:var(--nx-positive-soft);
  --neg:var(--nx-negative-ink);   --neg-soft:var(--nx-negative-soft);
  --warn:var(--nx-warning-ink);   --warn-soft:var(--nx-warning-soft);
  --info:var(--nx-info-ink);      --info-soft:var(--nx-info-soft);
  --muted-rail:var(--nx-nodata);
  --shadow-sm:var(--nx-shadow-hairline);
  --shadow-md:var(--nx-shadow-card);
  --shadow-lg:var(--nx-shadow-elevated);
}

*{box-sizing:border-box}
/* clip, not hidden: hidden on <html> breaks position:sticky in some browsers */
html{-webkit-text-size-adjust:100%;overflow-x:clip}
body{overflow-x:clip;max-width:100vw}
body{
  margin:0;background:var(--bg);color:var(--ink);
  font-family:var(--font-sans);font-size:var(--fs-base);line-height:1.62;
  letter-spacing:-.005em;
  -webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;
}
a{color:var(--accent);text-decoration:none}
a:hover{text-decoration:underline;text-underline-offset:2px}
::selection{background:var(--accent-soft);color:var(--accent-ink)}
:focus-visible{outline:2px solid var(--accent);outline-offset:2px;border-radius:3px}

/* numbers are mono and tabular everywhere they appear */
.num,.v,.sc,.px,.scorebadge .v,.mono,td.num,th.num{
  font-family:var(--font-mono);font-variant-numeric:tabular-nums;
  font-feature-settings:"tnum" 1;letter-spacing:-.01em}

/* ---------------------------------------------------------------- topbar */
.topbar{
  position:sticky;top:0;z-index:50;
  background:color-mix(in srgb,var(--surface) 88%,transparent);
  backdrop-filter:saturate(180%) blur(12px);
  border-bottom:1px solid var(--line);
}
/* content lines up with the page below instead of hugging the screen edges */
.topbar .inner{
  display:flex;align-items:center;gap:var(--sp-4);
  padding:var(--sp-3) clamp(14px, 3vw, 56px)}
.brand{
  font-weight:650;font-size:var(--fs-md);letter-spacing:-.02em;color:var(--ink);
  white-space:nowrap;display:flex;align-items:baseline;gap:var(--sp-3)}
.brandmark{
  width:26px;height:26px;border-radius:6px;flex:none;align-self:center;display:block;
  box-shadow:0 1px 3px rgba(16,24,40,.22)}
[data-theme="dark"] .brandmark{box-shadow:0 1px 3px rgba(0,0,0,.5)}
.brand small{
  color:var(--ink-3);font-size:var(--fs-xs);font-weight:400;letter-spacing:0}
.navlinks{
  display:flex;gap:var(--sp-1);margin-left:auto;align-items:center;flex:none;
  flex-wrap:wrap;justify-content:flex-end}
.topbar .brand{min-width:0;overflow:hidden;text-overflow:ellipsis}
.homelink{color:var(--ink-4)!important}
.navlinks a{
  color:var(--ink-3);font-size:var(--fs-2xs);font-weight:700;letter-spacing:.08em;
  text-transform:uppercase;padding:7px var(--sp-3);border-radius:var(--r-sm);
  transition:.14s var(--ease);border:1px solid transparent}
.navlinks a:hover{color:var(--ink);background:var(--surface-3);text-decoration:none}
.navlinks a.active{
  color:var(--accent-ink);background:var(--accent-soft);
  border-color:color-mix(in srgb,var(--accent) 28%,transparent)}
.navlinks a.homelink{
  color:var(--ink-4)!important;font-weight:600;letter-spacing:.06em}

.pill{
  border:1px solid var(--line-2);border-radius:999px;padding:2px 10px;
  font-size:var(--fs-xs);font-weight:500;color:var(--ink-3);white-space:nowrap}
.pill.ok{color:var(--pos);border-color:transparent;background:var(--pos-soft)}
.pill.off{color:var(--warn);border-color:transparent;background:var(--warn-soft)}

.themetoggle{
  display:flex;align-items:center;justify-content:center;width:32px;height:32px;
  border:1px solid var(--line-2);border-radius:var(--r-sm);background:var(--surface);
  color:var(--ink-3);cursor:pointer;transition:.14s;padding:0;flex:none}
.themetoggle:hover{color:var(--ink);border-color:var(--line-3)}
.themetoggle svg{width:15px;height:15px}
.themetoggle .moon{display:none}
[data-theme="dark"] .themetoggle .moon{display:block}
[data-theme="dark"] .themetoggle .sun{display:none}

/* full-bleed: this is a terminal, the data should use the screen it is given.
   Prose blocks keep their own ch-based caps so lines stay readable. */
.wrap{padding:var(--sp-6) clamp(14px, 3vw, 56px) var(--sp-8)}

/* ---------------------------------------------------------------- search */
.searchbox{position:relative;display:flex;gap:var(--sp-3);margin:var(--sp-2) 0}
.searchbox input{
  flex:1;background:var(--surface);border:1px solid var(--line-2);
  border-radius:var(--r-md);color:var(--ink);font-family:var(--font-sans);
  font-size:var(--fs-md);padding:14px var(--sp-4);outline:none;
  box-shadow:var(--shadow-sm);transition:.15s}
.searchbox input::placeholder{color:var(--ink-4)}
.searchbox input:focus{
  border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
.searchbox button{
  background:var(--accent);color:#fff;border:0;border-radius:var(--r-md);
  padding:0 var(--sp-5);font-family:var(--font-sans);font-weight:600;
  font-size:var(--fs-sm);cursor:pointer;letter-spacing:.01em;transition:.15s}
.searchbox button:hover{background:var(--accent-ink)}
.searchbox button:disabled{opacity:.5;cursor:not-allowed}
.suggest{
  position:absolute;top:54px;left:0;right:120px;background:var(--surface);
  border:1px solid var(--line-2);border-radius:var(--r-md);overflow:hidden;
  z-index:40;box-shadow:var(--shadow-lg)}
.suggest div{
  padding:10px var(--sp-4);cursor:pointer;display:flex;justify-content:space-between;
  gap:var(--sp-4);font-size:var(--fs-sm);border-bottom:1px solid var(--line)}
.suggest div:last-child{border-bottom:0}
.suggest div:hover,.suggest div.sel{background:var(--surface-3)}
.suggest .tk{
  color:var(--ink-4);font-family:var(--font-mono);font-size:var(--fs-xs)}
.hint{color:var(--ink-4);font-size:var(--fs-xs);margin:var(--sp-3) 0 var(--sp-6)}
.hint b{color:var(--ink-3);font-weight:600}

/* --------------------------------------------------------------- console */
.console{
  background:var(--console-bg);border:1px solid var(--line);
  border-radius:var(--r-md);padding:var(--sp-3) var(--sp-4);
  max-height:280px;overflow-y:auto;margin-bottom:var(--sp-5);
  font-family:var(--font-mono);font-size:var(--fs-xs);line-height:1.75}
.console.hidden{display:none}
.cl{display:flex;gap:var(--sp-3);padding:1px 0;align-items:baseline;
  animation:slidein .2s ease}
@keyframes slidein{from{opacity:0;transform:translateY(3px)}to{opacity:1}}
.cl .t{color:var(--console-dim);min-width:60px;font-size:10px}
.cl .s{min-width:50px;font-weight:700;font-size:10px;letter-spacing:.06em}
.cl .m{color:var(--console-ink);flex:1;opacity:.88}
.cl .m b{color:#fff;font-weight:600;opacity:1}
.s.start{color:#6a9bf4} .s.ok{color:#3fb984} .s.warn{color:#dda13c}
.s.error{color:#ef6a6a} .s.PASS{color:#3fb984} .s.WARN{color:#dda13c}
.s.FAIL{color:#ef6a6a} .s.NA{color:#6d7d8f} .s.info{color:#a78bfa}

/* ---------------------------------------------------------------- panels */
.grid{display:grid;gap:var(--sp-4)}
.g2{grid-template-columns:1fr 1fr}
.g3{grid-template-columns:repeat(3,1fr)}
@media(max-width:900px){.g2,.g3{grid-template-columns:1fr}}
@media(min-width:1700px){.g2{grid-template-columns:repeat(3,1fr)}}

.panel{
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-xl);
  padding:var(--sp-5) var(--sp-6) var(--sp-6);margin-bottom:var(--sp-4);
  box-shadow:var(--shadow-sm);scroll-margin-top:120px}
.panel h3{
  margin:0 0 var(--sp-1);font-size:var(--fs-md);letter-spacing:-.02em;color:var(--ink);
  text-transform:none;font-weight:640;display:flex;align-items:center;
  gap:var(--sp-3);line-height:1.3}
.panel-num{
  font-family:var(--font-mono);color:var(--ink-4);font-weight:600;
  background:var(--surface-3);border:1px solid var(--line);border-radius:6px;
  padding:2px 7px;font-size:var(--fs-2xs);letter-spacing:.02em;flex:none}
.panel .sub{
  color:var(--ink-3);font-size:var(--fs-sm);margin:var(--sp-2) 0 var(--sp-5);
  max-width:88ch;line-height:1.6}
.panel .sub b{color:var(--ink-2);font-weight:600}

/* ---------------------------------------------------------- header block */
.hdr{
  display:flex;flex-wrap:wrap;gap:var(--sp-5);align-items:flex-start;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:var(--sp-5);margin-bottom:var(--sp-4);box-shadow:var(--shadow-sm)}
.hdr .name{
  font-size:var(--fs-xl);font-weight:680;letter-spacing:-.024em;line-height:1.2}
.hdr .meta{
  color:var(--ink-3);font-size:var(--fs-sm);margin-top:var(--sp-2);
  display:flex;flex-wrap:wrap;gap:0 var(--sp-3)}
.hdr .px{
  font-size:var(--fs-2xl);font-weight:640;margin-left:auto;text-align:right;
  letter-spacing:-.03em;line-height:1.1}
.hdr .px small{
  display:block;font-size:var(--fs-xs);font-weight:500;color:var(--ink-3);
  font-family:var(--font-sans);letter-spacing:0;margin-top:var(--sp-2)}
.scorebadge{
  text-align:center;border-left:1px solid var(--line);padding-left:var(--sp-5);
  min-width:132px}
.scorebadge .v{font-size:var(--fs-3xl);font-weight:700;line-height:1;letter-spacing:-.04em}
/* A withheld score must not look like a low score. Muted and dashed, so the
   badge reads as "we did not measure this" rather than "this scored badly". */
.scorebadge.unscored .v{font-size:var(--fs-2xl);color:var(--ink-4)}
.scorebadge.unscored{border-left-style:dashed}
.scorebadge.unscored .b{color:var(--ink-4)!important;letter-spacing:.06em}

/* A missing value states its reason inline. Kept small and unemphatic: it is
   an explanation, not a warning, and it sits in a numeric column. */
.src.na{font-style:normal;white-space:normal;text-align:right;display:inline-block;
  max-width:34ch;line-height:1.35}
/* Age, on the other hand, is a warning. */
.stale{
  display:inline-block;margin-left:6px;padding:0 5px;border-radius:4px;
  background:var(--warn-soft);color:var(--warn);
  font-size:var(--fs-2xs);font-weight:650;letter-spacing:.04em;text-transform:uppercase}
@media print{
  .stale{-webkit-print-color-adjust:exact;print-color-adjust:exact;
    border:1px solid currentColor}
}
.scorebadge .o{color:var(--ink-4);font-size:var(--fs-xs);margin-top:2px}
.scorebadge .b{
  letter-spacing:.1em;font-size:10px;margin-top:var(--sp-2);font-weight:700;
  text-transform:uppercase}
.up{color:var(--pos)} .down{color:var(--neg)} .flat{color:var(--ink-3)}

/* ---------------------------------------------------------------- tables */
table{width:100%;border-collapse:collapse;font-size:var(--fs-sm)}
/* Every cell carries padding on BOTH sides. Zeroing padding-right on numeric
   cells — which is what this used to do — left right-aligned values touching the
   next cell, producing "23.31xYahoo Finance" and "WEIGHTREADING". Only the outer
   edges of the table sit flush. */
th{
  text-align:left;color:var(--ink-4);font-weight:700;font-size:var(--fs-2xs);
  letter-spacing:.1em;text-transform:uppercase;
  padding:0 var(--sp-4) var(--sp-2) var(--sp-4);
  border-bottom:1px solid var(--line-2);white-space:nowrap;background:var(--surface)}
td{
  padding:10px var(--sp-4);border-bottom:1px solid var(--line);
  vertical-align:top;color:var(--ink-2)}
th:first-child,td:first-child{padding-left:0}
th:last-child,td:last-child{padding-right:0}
tbody tr:last-child td,tr:last-child td{border-bottom:0}
td.num,th.num{text-align:right}
tr:hover td{background:var(--surface-2)}

.src{color:var(--ink-4);font-size:var(--fs-xs);line-height:1.5}
/* An annotation that follows a value on the same line needs air before it. A
   .src that *is* the whole cell must not be indented, hence :not(:first-child). */
td > .src:not(:first-child),
th > .src:not(:first-child),
.v > .src:not(:first-child),
.kpi .v > .src:not(:first-child){margin-left:.45em}
/* Inside a cell an annotation normally belongs on its own line under the value. */
td > div.src{display:block;margin-left:0;margin-top:2px}
.chip{
  display:inline-block;border:1px solid var(--line-2);border-radius:4px;
  padding:0 6px;font-size:10px;color:var(--ink-4);margin-left:6px;white-space:nowrap}

/* ------------------------------------------------------------- red flags */
.flag{
  border:1px solid var(--line);border-left:3px solid var(--muted-rail);
  border-radius:var(--r-md);padding:var(--sp-4);background:var(--surface-2)}
.flag.PASS{border-left-color:var(--pos)}
.flag.WARN{border-left-color:var(--warn)}
.flag.FAIL{border-left-color:var(--neg);background:var(--neg-soft)}
.flag.NA{border-left-color:var(--muted-rail)}
.flag .row{display:flex;justify-content:space-between;align-items:center;gap:var(--sp-3)}
.flag .lab{font-weight:640;font-size:var(--fs-base);letter-spacing:-.01em}
.flag .st{
  font-size:10px;font-weight:750;letter-spacing:.08em;padding:2px 8px;
  border-radius:999px;background:var(--surface-3)}
.flag.PASS .st{background:var(--pos-soft)}
.flag.WARN .st{background:var(--warn-soft)}
.flag.FAIL .st{background:var(--neg-soft)}
.flag .q{color:var(--ink-4);font-size:var(--fs-xs);margin:var(--sp-2) 0 var(--sp-3)}
.flag .hl{font-size:var(--fs-sm);color:var(--ink-2)}
.flag details{margin-top:var(--sp-3)}
.flag summary{
  color:var(--ink-4);font-size:var(--fs-xs);cursor:pointer;font-weight:500;
  list-style:none;display:inline-flex;align-items:center;gap:5px}
.flag summary::-webkit-details-marker{display:none}
.flag summary:before{content:"▸";transition:transform .15s;display:inline-block}
.flag details[open] summary:before{transform:rotate(90deg)}
.flag summary:hover{color:var(--accent)}
.flag pre{
  background:var(--surface-3);border:1px solid var(--line);border-radius:var(--r-sm);
  padding:var(--sp-3);font-size:var(--fs-xs);overflow-x:auto;margin:var(--sp-2) 0 0;
  color:var(--ink-3);white-space:pre-wrap;word-break:break-word;
  font-family:var(--font-mono);line-height:1.65}

/* ------------------------------------------------------------- scorecard */
.subscore{border-bottom:1px solid var(--line);padding:var(--sp-4) 0}
.subscore:first-of-type{padding-top:0}
.subscore:last-of-type{border-bottom:0}
.subscore .top{display:flex;align-items:center;gap:var(--sp-4)}
.subscore .nm{font-weight:600;min-width:148px;font-size:var(--fs-sm)}
.subscore .wt{
  color:var(--ink-4);font-size:var(--fs-xs);min-width:40px;
  font-family:var(--font-mono)}
.bar{
  flex:1;height:8px;background:var(--surface-3);border-radius:999px;
  overflow:hidden;min-width:60px}
.bar i{display:block;height:100%;border-radius:999px;
  transition:width .45s cubic-bezier(.4,0,.2,1)}
.subscore .sc{min-width:80px;text-align:right;font-weight:650;font-size:var(--fs-sm)}
.subscore .fx{
  color:var(--ink-4);font-size:var(--fs-xs);margin-top:var(--sp-2);
  font-family:var(--font-mono);line-height:1.6}
.subscore .inp{color:var(--ink-3);font-size:var(--fs-xs);margin-top:3px;
  font-family:var(--font-mono);word-break:break-word}
.mathbox{
  background:var(--surface-3);border:1px solid var(--line);border-radius:var(--r-md);
  padding:var(--sp-4);font-size:var(--fs-xs);color:var(--ink-2);white-space:pre;
  overflow-x:auto;margin-top:var(--sp-4);line-height:1.85;
  font-family:var(--font-mono);font-variant-numeric:tabular-nums}
.mathbox b{color:var(--ink);font-weight:700}

/* ---------------------------------------------------------- swot / debate */
.swot{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-4)}
@media(min-width:1700px){.swot{grid-template-columns:repeat(4,1fr)}}
@media(max-width:820px){.swot{grid-template-columns:1fr}}
.swot .q{
  border:1px solid var(--line);border-radius:var(--r-md);padding:var(--sp-4);
  background:var(--surface-2)}
.swot .q h4{
  margin:0 0 var(--sp-3);font-size:10px;letter-spacing:.12em;text-transform:uppercase;
  font-weight:700;display:flex;align-items:center;gap:6px}
.swot .q h4:before{content:"";width:6px;height:6px;border-radius:50%;background:currentColor}
.swot .S h4{color:var(--pos)} .swot .W h4{color:var(--neg)}
.swot .O h4{color:var(--info)} .swot .T h4{color:var(--warn)}
.swot ul{margin:0;padding:0}
.swot li{
  margin-bottom:var(--sp-3);font-size:var(--fs-sm);list-style:none;position:relative;
  padding-left:var(--sp-4);color:var(--ink-2);line-height:1.6}
.swot li:last-child{margin-bottom:0}
.swot li:before{
  content:"";position:absolute;left:2px;top:8px;width:4px;height:4px;
  border-radius:50%;background:var(--line-3)}
.cite{
  color:var(--ink-4);font-size:var(--fs-xs);font-family:var(--font-mono);
  white-space:nowrap}

.turn{
  border:1px solid var(--line);border-left:3px solid var(--muted-rail);
  border-radius:var(--r-md);padding:var(--sp-4);margin-bottom:var(--sp-3);
  background:var(--surface-2);animation:slidein .3s ease}
.turn.BULL{border-left-color:var(--pos)}
.turn.BEAR{border-left-color:var(--neg)}
.turn .who{
  font-size:10px;font-weight:750;letter-spacing:.1em;margin-bottom:var(--sp-2)}
.turn.BULL .who{color:var(--pos)} .turn.BEAR .who{color:var(--neg)}
.turn .who span{color:var(--ink-4);font-weight:500;letter-spacing:0;margin-left:var(--sp-2)}
.turn p{margin:0;font-size:var(--fs-sm);color:var(--ink-2);line-height:1.65}
.adjudication{
  border:1px dashed var(--line-2);border-radius:var(--r-md);padding:var(--sp-4);
  color:var(--ink-3);font-size:var(--fs-sm);margin-top:var(--sp-3);
  background:var(--surface-2)}
.adjudication b{color:var(--ink)}

/* ------------------------------------------------------------------ misc */
.kpi{display:grid;grid-template-columns:repeat(auto-fit,minmax(122px,1fr));gap:var(--sp-3)}
.kpi div{
  background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r-md);
  padding:var(--sp-3) var(--sp-4);transition:border-color .15s var(--ease)}
.kpi div:hover{border-color:var(--line-2)}
.kpi .k{
  color:var(--ink-4);font-size:10px;letter-spacing:.08em;text-transform:uppercase;
  font-weight:600}
.kpi .v{font-size:var(--fs-lg);font-weight:650;margin-top:4px;letter-spacing:-.025em;
  line-height:1.15}
.note{
  color:var(--ink-4);font-size:var(--fs-xs);margin-top:var(--sp-4);line-height:1.65;
  max-width:92ch}
.banner{
  border:1px solid var(--line-2);border-radius:var(--r-md);padding:var(--sp-3) var(--sp-4);
  font-size:var(--fs-sm);margin-bottom:var(--sp-4);background:var(--surface-2);
  color:var(--ink-2)}
.banner.warn{border-color:transparent;background:var(--warn-soft);color:var(--warn)}
.banner.err{border-color:transparent;background:var(--neg-soft);color:var(--neg)}
.banner.ok{border-color:transparent;background:var(--pos-soft);color:var(--pos)}
.banner.sim{
  border:1px solid var(--warn);background:var(--warn-soft);color:var(--warn);
  letter-spacing:.1em;text-align:center;font-weight:700;font-size:var(--fs-xs)}
.loading{color:var(--ink-4);font-size:var(--fs-sm);padding:var(--sp-5) 0}
.skel{display:block;border-radius:var(--r-sm);
  background:linear-gradient(90deg,var(--surface-3) 25%,var(--surface-2) 37%,var(--surface-3) 63%);
  background-size:400% 100%;animation:shimmer 1.4s ease infinite}
@keyframes shimmer{0%{background-position:100% 50%}100%{background-position:0 50%}}
.skel-row{height:14px;margin-bottom:10px}
.skel-row:nth-child(3n){width:78%}
.skel-row:nth-child(3n+1){width:92%}
.skel-panel{
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-xl);
  padding:var(--sp-5) var(--sp-6);margin-bottom:var(--sp-4)}

.scenario{
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-md);
  padding:var(--sp-4);cursor:pointer;transition:.16s;box-shadow:var(--shadow-sm)}
.scenario:hover{border-color:var(--line-3);transform:translateY(-1px);
  box-shadow:var(--shadow-md)}
.scenario.active{border-color:var(--accent);background:var(--accent-soft)}
.scenario .t{font-weight:640;font-size:var(--fs-base)}
.scenario .d{color:var(--ink-3);font-size:var(--fs-sm);margin-top:var(--sp-2)}
.scenario .m{color:var(--ink-4);font-size:var(--fs-xs);margin-top:var(--sp-3);
  font-family:var(--font-mono)}

.ctrl{display:flex;gap:var(--sp-3);align-items:center;margin:var(--sp-4) 0;flex-wrap:wrap}
.ctrl button,.adm-sched button,.adm-job button,.adm-run{
  background:var(--surface);border:1px solid var(--line-2);color:var(--ink-2);
  border-radius:var(--r-sm);padding:7px var(--sp-4);font-family:var(--font-sans);
  font-size:var(--fs-sm);font-weight:500;cursor:pointer;transition:.14s;
  box-shadow:var(--shadow-sm)}
.ctrl button:hover,.adm-sched button:hover,.adm-job button:hover,.adm-run:hover{border-color:var(--line-3);color:var(--ink);background:var(--surface-3)}
.ctrl button.on{border-color:var(--accent);color:var(--accent-ink);background:var(--accent-soft)}
/* A destructive action that has been armed: the second click is the one that
 * deletes, and it must not look like the first. */
.ctrl button.danger,button.btn.danger{
  border-color:var(--neg);color:var(--neg);background:var(--neg-soft);font-weight:600}
.ctrl button.danger:hover{background:var(--neg);color:#fff;border-color:var(--neg)}
.ctrl select,.ctrl label{
  background:var(--surface);border:1px solid var(--line-2);color:var(--ink-2);
  border-radius:var(--r-sm);padding:7px var(--sp-3);font-family:var(--font-sans);
  font-size:var(--fs-sm)}
.ctrl label{display:flex;align-items:center;gap:6px;color:var(--ink-3)}
.ctrl label select{border:0;padding:0 0 0 4px;background:transparent}
.ctrl .src{flex:1;min-width:220px}

/* ---- buttons ----------------------------------------------------------
 *
 * These lived in landing.css, which only the seven marketing pages load. Every
 * `.btn` and `.btn-ghost` in the application — the Analyse links on the screen,
 * Open on a holding, Move, the ✕ on a position, twelve of them in the page
 * scripts alone — therefore rendered as unstyled text on every page that
 * matters. It explains a report of a button that "is not aligned": it was not
 * a button at all.
 *
 * A component used by the whole application belongs in the stylesheet the
 * whole application loads. The marketing-only variants stay in landing.css.
 */
.btn{
  display:inline-flex;align-items:center;gap:var(--sp-2);border-radius:var(--r-sm);
  font-family:var(--font-sans);font-size:var(--fs-sm);font-weight:600;
  padding:9px var(--sp-4);cursor:pointer;transition:.15s;
  border:1px solid var(--line-2);background:var(--surface);color:var(--ink-2);
  white-space:nowrap;text-decoration:none}
.btn:hover{border-color:var(--line-3);color:var(--ink);background:var(--surface-3);
  text-decoration:none}
.btn-primary,a.btn-primary{
  background:var(--accent);color:#fff;border-color:var(--accent);
  box-shadow:var(--shadow-sm)}
.btn-primary:hover,a.btn-primary:hover{
  background:var(--accent-ink);color:#fff;border-color:var(--accent-ink);
  text-decoration:none}
.btn-ghost,a.btn-ghost{
  background:var(--surface);color:var(--ink-2);border-color:var(--line-2);
  box-shadow:var(--shadow-sm)}
.btn-ghost:hover,a.btn-ghost:hover{
  border-color:var(--line-3);color:var(--ink);background:var(--surface-3);
  text-decoration:none}
.btn-lg{font-size:var(--fs-base);padding:13px var(--sp-5)}
.btn[disabled]{opacity:.5;cursor:default}

/* ---- spacing and small components, so the stylesheet owns them ---------
 *
 * These exist because 185 inline style attributes had accumulated in the page
 * scripts. About sixty of those are data — a bar's width *is* the number it
 * represents — and they stay where they are. The rest were static design
 * decisions written into JavaScript string templates, where a stylesheet
 * cannot reach them: forty-nine margins, a disclosure summary styled six
 * separate times, a chart height, a few font sizes.
 *
 * The consequence was that this file only controlled about seventy per cent of
 * how the application looks. Anyone restyling it — a designer, or me next
 * month — would change the tokens and find a third of the page ignoring them.
 */
.mt-2{margin-top:var(--sp-2)}
.mt-3{margin-top:var(--sp-3)}
.mt-4{margin-top:var(--sp-4)}
.mt-5{margin-top:var(--sp-5)}
.mt-0{margin-top:0}
.mb-0{margin-bottom:0}
.mb-2{margin-bottom:var(--sp-2)}
.mb-3{margin-bottom:var(--sp-3)}
.mb-4{margin-bottom:var(--sp-4)}

/* A <summary> that opens a section. Was written inline six times, each time
 * slightly differently. */
.disclosure{cursor:pointer;font-weight:600;color:var(--ink)}
.disclosure:hover{color:var(--accent)}
.disclosure-wide{cursor:pointer;font-weight:600;padding:var(--sp-3) 0}

/* The price and NAV charts. Height is a layout decision, not a datum. */
.chartbox{height:300px}

.strong{font-weight:650}
.fs-base{font-size:var(--fs-base)}

/* Semantic colour, named by meaning rather than written as a variable
 * reference in a template. A designer changing what "warn" looks like should
 * not have to find fourteen places in JavaScript. */
.c-pos{color:var(--pos)}
.c-warn{color:var(--warn)}
.c-neg{color:var(--neg)}
.c-muted{color:var(--ink-4)}

.chartbox-lg{height:320px}
.chartbox-sm{height:220px}
/* a panel heading that carries a run id rather than a title */
.h3-plain{font-weight:400;letter-spacing:0;text-transform:none}

/* ---- the quality screen ------------------------------------------------
 * Its first build laid the criteria out as a table with a paragraph of prose
 * in every row: nine rows three lines tall, and the numbers a reader actually
 * changes were the smallest things on the screen. These classes exist to make
 * the controls compact enough that the answer fits above the fold. */
.qs-head{display:flex;align-items:baseline;gap:var(--sp-3);flex-wrap:wrap;
  margin-bottom:var(--sp-2)}
.qs-count{font-family:var(--font-mono);font-size:var(--fs-xl);font-weight:650;
  line-height:1}
.qs-of{color:var(--ink-3);font-size:var(--fs-sm)}

.qs-grid{display:grid;gap:var(--sp-2);
  grid-template-columns:repeat(auto-fill,minmax(188px,1fr))}
.qs-f{border:1px solid var(--line);border-radius:var(--r-sm);
  padding:8px 10px;background:var(--surface);display:flex;
  flex-direction:column;gap:5px;transition:.14s}
.qs-f.off{opacity:.45;background:var(--surface-2)}
.qs-f:hover{border-color:var(--line-2)}
.qs-f .top{display:flex;align-items:center;gap:7px;min-height:20px}
.qs-f .top label{display:flex;align-items:center;gap:7px;cursor:pointer;
  font-size:var(--fs-sm);font-weight:600;color:var(--ink);line-height:1.25}
.qs-f .why{margin-left:auto;color:var(--ink-4);cursor:help;font-size:11px;
  border:1px solid var(--line-2);border-radius:50%;width:16px;height:16px;
  display:grid;place-items:center;flex:none}
.qs-f .why:hover{color:var(--accent);border-color:var(--accent)}
.qs-f .set{display:flex;align-items:center;gap:6px}
.qs-f .cmp{font-family:var(--font-mono);color:var(--ink-3);font-size:var(--fs-sm)}
.qs-f input[type=number]{width:100%;min-width:0;font-family:var(--font-mono);
  font-size:var(--fs-sm);padding:4px 7px;border:1px solid var(--line-2);
  border-radius:var(--r-sm);background:var(--surface);color:var(--ink)}
.qs-f .unit{color:var(--ink-4);font-size:var(--fs-xs);flex:none;min-width:12px}   /* every input ends at the same edge */

/* the optional filters: present, but not competing with the eight that are
 * already on. Closed, twelve more controls cost one line of the page. */
.qs-more{margin-top:var(--sp-3);border-top:1px solid var(--line);
  padding-top:var(--sp-3)}
.qs-more>summary{cursor:pointer;font-size:var(--fs-sm);color:var(--ink-2);
  font-weight:550;list-style:none;display:flex;align-items:baseline;gap:var(--sp-2);
  flex-wrap:wrap}
.qs-more>summary::-webkit-details-marker{display:none}
.qs-more>summary::before{content:"+";font-family:var(--font-mono);color:var(--ink-4);
  font-weight:400}
.qs-more[open]>summary::before{content:"−"}
.qs-more>summary:hover{color:var(--accent)}
.qs-group{margin-top:var(--sp-3)}
.qs-gname{font-size:var(--fs-xs);text-transform:uppercase;letter-spacing:.06em;
  color:var(--ink-4);margin-bottom:var(--sp-2)}

/* market chips: `.ctrl label` gives every label a border and a background,
 * which turned three checkboxes into three full-width boxes that wrapped. */
.qs-mkt{display:inline-flex;align-items:center;gap:5px;border:1px solid var(--line-2);
  border-radius:999px;padding:3px 10px;background:var(--surface);
  font-size:var(--fs-sm);color:var(--ink-2);cursor:pointer;flex:none}
.qs-mkt input{margin:0}
.qs-mkt.on{border-color:var(--accent);background:var(--accent-soft);
  color:var(--accent-ink)}

/* ---- the weekly screen's pick list -------------------------------------
 * Each pick used to render a full two-column dossier inline — factor bars and
 * a levels table and pivots — fifteen times over. The list was not a list; it
 * was fifteen reports stacked. These make a pick one scannable line that opens
 * into the same detail when asked. */
.pick{border:1px solid var(--line);border-radius:var(--r-sm);
  margin-bottom:6px;background:var(--surface);overflow:hidden}
.pick[open]{border-color:var(--line-2);box-shadow:var(--shadow-sm)}
.pick>summary{list-style:none;cursor:pointer;padding:9px 12px;
  display:grid;align-items:center;gap:var(--sp-3);
  grid-template-columns:28px minmax(150px,2.2fr) minmax(90px,1fr) auto auto auto 16px}
.pick>summary::-webkit-details-marker{display:none}
.pick>summary:hover{background:var(--surface-2)}
.pick .rk{font-family:var(--font-mono);color:var(--ink-4);font-size:var(--fs-sm)}
.pick .co b{font-size:var(--fs-sm);color:var(--ink)}
.pick .co .src{display:block;line-height:1.35}
.pick .pst{font-size:var(--fs-xs);color:var(--ink-3);line-height:1.35}
.pick .px{font-family:var(--font-mono);font-size:var(--fs-sm);color:var(--ink-2);
  text-align:right;white-space:nowrap}
.pick .scr{font-family:var(--font-mono);font-weight:700;font-size:var(--fs-md);
  text-align:right;min-width:38px}
.pick .chev{color:var(--ink-4);transition:.15s;font-size:11px;text-align:center}
.pick[open] .chev{transform:rotate(90deg)}
.pick .body{padding:0 12px 12px;border-top:1px solid var(--line)}
@media (max-width:760px){
  /* rank · company · risk · score · chevron: five visible, five columns (it
     had four, so the score fell into the chevron's 16px and was cut) */
  .pick>summary{grid-template-columns:24px minmax(0,1fr) auto auto 16px;gap:var(--sp-2)}
  .pick .pst,.pick .px{display:none}
}

/* the verdict strip: the record this screen has, before the names it likes */
.scoreline{display:flex;flex-wrap:wrap;align-items:baseline;gap:var(--sp-2) var(--sp-5)}
.scoreline .m{display:flex;align-items:baseline;gap:7px}
.scoreline .m .v{font-family:var(--font-mono);font-size:var(--fs-lg);font-weight:650;
  line-height:1}
.scoreline .m .k{color:var(--ink-3);font-size:var(--fs-xs);text-transform:uppercase;
  letter-spacing:.06em}

/* the funnel as bars rather than a seven-column table */
.qs-funnel{display:flex;flex-direction:column;gap:2px;margin-top:var(--sp-3)}
.qs-step{display:grid;grid-template-columns:minmax(150px,1.3fr) 1fr minmax(118px,auto);
  align-items:center;gap:var(--sp-3);padding:5px 0;
  border-bottom:1px solid var(--line)}
.qs-step:last-child{border-bottom:0}
.qs-step .nm{font-size:var(--fs-sm);color:var(--ink);font-weight:550}
.qs-step .nm b{font-family:var(--font-mono);color:var(--ink-3);font-weight:500;
  font-size:var(--fs-xs);margin-left:5px}
.qs-track{position:relative;height:16px;background:var(--surface-3);
  border-radius:3px;overflow:hidden}
.qs-track i{position:absolute;left:0;top:0;bottom:0;background:var(--accent);
  opacity:.80}
.qs-track i.gone{background:var(--neg);opacity:.16}
.qs-step .cnt{font-family:var(--font-mono);font-size:var(--fs-sm);
  text-align:right;color:var(--ink-2);white-space:nowrap}
.qs-step .cnt b{color:var(--ink)}
.qs-step.empties .cnt b{color:var(--neg)}
.qs-step .cnt small{color:var(--ink-4);font-size:var(--fs-xs);margin-left:5px;white-space:nowrap}
/* phones: the test and its counts on one line, the bar full width beneath */
@media(max-width:560px){
  .qs-step{grid-template-columns:minmax(0,1fr) auto;row-gap:6px;padding:8px 0}
  .qs-step .nm{grid-column:1;grid-row:1}
  .qs-step .cnt{grid-column:2;grid-row:1;white-space:normal;max-width:62vw}
  .qs-step .qs-track{grid-column:1 / -1;grid-row:2}
}
/* a company's name gets room, and its flag never parts from its ticker */
.qs-name{min-width:150px}
.qs-name .src{white-space:nowrap}
.qs-name .qs-co{color:inherit;text-decoration:none}
.qs-name .qs-co:hover b{color:var(--accent);text-decoration:underline}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
/* the match and near-miss tables: every column fits */
.qs-table{min-width:0!important;table-layout:auto}
.qs-table th{white-space:normal;vertical-align:bottom;line-height:1.3;font-size:var(--fs-2xs);padding-left:8px;padding-right:8px}
.qs-table td{padding-left:8px;padding-right:8px;vertical-align:top}
.qs-table td.num{white-space:nowrap}
.qs-table .qs-name{min-width:170px;max-width:260px}
.qs-table .qs-name .src{white-space:normal}
.qs-table .qs-fail{color:var(--neg);background:color-mix(in srgb,var(--neg) 8%,transparent)}
.qs-table .qs-pass{color:var(--pos)}
.qs-missed{font-size:var(--fs-2xs);color:var(--neg);margin-top:3px}
.qs-table .qs-open{width:34px;padding-right:0;text-align:right}
.qs-open a{display:inline-grid;place-items:center;width:28px;height:28px;border-radius:50%;border:1px solid var(--line-2);
  color:var(--accent);text-decoration:none;font-weight:700}
.qs-open a:hover,.qs-open a:focus-visible{background:var(--accent);color:#fff;border-color:var(--accent)}
.qs-table tbody tr:hover .qs-co b{color:var(--accent)}
/* phones: each company a card, its figures in a grid, labelled */
@media(max-width:700px){
  .qs-tablewrap{overflow:visible}
  .qs-table,.qs-table tbody,.qs-table tr,.qs-table td{display:block}
  .qs-table thead{display:none}
  .qs-table tr{position:relative;display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:6px 10px;
    padding:12px 0;border-bottom:1px solid var(--line)}
  .qs-table td{border:0;padding:0!important;text-align:left!important;white-space:normal!important}
  .qs-table td.qs-name{grid-column:1 / -1;max-width:none;min-width:0;padding-right:40px!important}
  .qs-table td[data-label]::before{content:attr(data-label);display:block;font-size:var(--fs-2xs);
    color:var(--ink-4);font-family:var(--font-sans);font-weight:600;line-height:1.25;margin-bottom:1px}
  .qs-table td.qs-fail{border-radius:6px;padding:3px 5px!important;margin:-3px -5px}   /* shaded, but in line */
  .qs-table td.qs-open{position:absolute;top:12px;right:0;width:auto}
}

.footer{
  color:var(--ink-4);font-size:var(--fs-xs);text-align:center;
  padding:var(--sp-6) var(--sp-5) var(--sp-5);border-top:1px solid var(--line);
  margin-top:var(--sp-7);line-height:1.9}

/* --------------------------------------------------------- weight sliders */
.weightrow{padding:var(--sp-2) 0 2px}
.weightrow input[type=range]{
  width:100%;height:4px;-webkit-appearance:none;appearance:none;
  background:var(--surface-3);border-radius:999px;outline:none;cursor:pointer}
.weightrow input[type=range]::-webkit-slider-thumb{
  -webkit-appearance:none;width:14px;height:14px;border-radius:50%;
  background:var(--accent);cursor:pointer;border:2px solid var(--surface);
  box-shadow:var(--shadow-sm)}
.weightrow input[type=range]::-moz-range-thumb{
  width:14px;height:14px;border-radius:50%;background:var(--accent);cursor:pointer;
  border:2px solid var(--surface);box-shadow:var(--shadow-sm)}

/* --------------------------------------------------------------- watchlist */
.wl td.name{font-weight:600;color:var(--ink)}
.wl .scorecell{font-weight:700}
.wl .flagcell span{font-weight:700;margin-right:6px}
.wl tr.empty td{color:var(--ink-4);font-style:italic}
.mini{
  display:inline-block;width:46px;height:6px;background:var(--surface-3);
  border-radius:999px;overflow:hidden;vertical-align:middle;margin-right:8px}
.mini i{display:block;height:100%;border-radius:999px}
.spark{display:block;width:92px;height:28px;overflow:visible}
.spark path.line{fill:none;stroke-width:1.4;vector-effect:non-scaling-stroke}
.spark path.area{stroke:none;opacity:.13}
.spark circle{stroke:var(--surface);stroke-width:1.4}

/* --------------------------------------------------------------- scrollbar */
::-webkit-scrollbar{width:10px;height:10px}
::-webkit-scrollbar-track{background:transparent}
::-webkit-scrollbar-thumb{background:var(--line-2);border-radius:5px;
  border:2px solid var(--bg);background-clip:padding-box}
::-webkit-scrollbar-thumb:hover{background:var(--line-3);background-clip:padding-box}

@media(prefers-reduced-motion:reduce){
  *{animation-duration:.001ms!important;transition-duration:.001ms!important}
}

/* ------------------------------------------------------- printed report head */
.print-header{display:none}

/* ==========================================================================
   PRINT / PDF — the same DOM, restyled. A separate PDF renderer would drift
   away from the page it claims to be a copy of.
   ========================================================================== */
@media print{
  @page{size:A4;margin:14mm 12mm 16mm}
  html,body{background:#fff!important;color:#111!important;font-size:9.4pt}
  .topbar,.searchbox,.suggest,.hint,.console,.no-print,#landing,
  .ctrl,#nx-toolbar,.weightrow,.navlinks,#nx-weight-ctrl,.themetoggle{display:none!important}
  a{color:#111!important;text-decoration:none}
  .wrap{max-width:none;padding:0}

  .panel,.hdr,.flag,.turn,.swot .q,.adjudication,.banner,.mathbox,.kpi div,.scenario{
    background:#fff!important;border-color:#c8ced6!important;color:#111!important;
    box-shadow:none!important}
  .panel{break-inside:avoid;page-break-inside:avoid;margin:0 0 8mm;padding:4mm 0 0;
    border:0;border-top:1px solid #c8ced6;border-radius:0}
  .panel h3{color:#000!important;font-size:8.4pt}
  .panel .sub,.note,.src,.fx,.inp,.chip,.cite{color:#4a5560!important}
  .panel-num{color:#98a2ad!important;background:transparent!important}

  /* masthead on the printed report — the mark is the only place the logo
     appears in the PDF, so it brands the page without competing with the data */
  .print-header{
    display:flex!important;align-items:center;gap:4mm;
    border-bottom:1px solid #c8ced6;padding-bottom:3mm;margin-bottom:5mm}
  .print-header img{width:13mm;height:13mm;border-radius:2.6mm}
  .print-header .pt{font-size:13pt;font-weight:700;letter-spacing:-.02em;color:#000}
  .print-header .ps{font-size:8.4pt;color:#4a5560;margin-top:.6mm}
  .print-header .pm{margin-left:auto;text-align:right;font-size:8pt;color:#4a5560;
    line-height:1.5}
  .print-header .pm b{color:#000;display:block;font-size:9pt}

  .hdr{border:0;border-bottom:2px solid #111;border-radius:0;padding:0 0 4mm;
    margin-bottom:5mm}
  .hdr .name{font-size:17pt}
  .scorebadge{border-left:1px solid #c8ced6}
  .scorebadge .v{font-size:26pt}

  th{color:#000!important;border-bottom:1px solid #111;
     padding:0 3mm 1.5mm 3mm}
  td{border-bottom:1px solid #e2e6ea;color:#222!important;padding:1.8mm 3mm}
  th:first-child,td:first-child{padding-left:0}
  th:last-child,td:last-child{padding-right:0}
  td > .src:not(:first-child),th > .src:not(:first-child){margin-left:.45em}
  tr:hover td{background:transparent!important}
  .mathbox{border:1px solid #c8ced6;color:#111!important;font-size:8.2pt}
  .mathbox b{color:#000!important}
  .bar,.mini{background:#e2e6ea!important}

  .flag{break-inside:avoid;page-break-inside:avoid}
  .flag.PASS{border-left-color:#0b7a4b!important}
  .flag.WARN{border-left-color:#9a6a08!important}
  .flag.FAIL{border-left-color:#c02a2a!important;background:#fff!important}
  .flag.NA{border-left-color:#9aa4ae!important}
  .flag .st{background:transparent!important;border:1px solid #c8ced6!important}
  .turn.BULL{border-left-color:#0b7a4b!important}
  .turn.BEAR{border-left-color:#c02a2a!important}
  .up{color:#0b7a4b!important} .down{color:#c02a2a!important} .flat{color:#4a5560!important}
  .banner.warn{border:1px solid #9a6a08!important;background:#fff!important;color:#7a5500!important}
  .banner.err{border:1px solid #c02a2a!important;background:#fff!important;color:#8e0e16!important}
  .banner.ok{border:1px solid #0b7a4b!important;background:#fff!important;color:#0e5c2f!important}
  .banner.sim{background:#fff!important;border:2px solid #9a6a08!important;color:#7a5500!important}

  /* a printed audit trail is useless with half of it behind a triangle */
  details{display:block!important}
  details>summary{display:none!important}
  .flag pre{background:#f6f7f9!important;border-color:#dde1e6!important;
    color:#333!important;font-size:7.6pt}

  .swot,.grid.g2{grid-template-columns:1fr 1fr}
  canvas{max-height:62mm!important}
  .footer{border-top:1px solid #c8ced6;color:#4a5560!important;
    page-break-inside:avoid;font-size:8pt}
}

/* ---------------------------------------------------- technical panels */
.subhead{
  margin:0 0 var(--sp-3);font-size:var(--fs-2xs);letter-spacing:.11em;
  text-transform:uppercase;color:var(--ink-4);font-weight:700;
  padding-bottom:var(--sp-2);border-bottom:1px solid var(--line)}
.posture{
  display:grid;grid-template-columns:repeat(3,1fr);gap:var(--sp-3);
  margin-bottom:var(--sp-5)}
@media(max-width:700px){.posture{grid-template-columns:1fr}}
.pcell{
  background:var(--surface-2);border:1px solid var(--line);border-radius:var(--r-md);
  padding:var(--sp-3) var(--sp-4)}
.pcell .k{
  color:var(--ink-4);font-size:10px;letter-spacing:.08em;text-transform:uppercase;
  font-weight:600}
.pcell .v{
  font-size:var(--fs-md);font-weight:650;margin-top:3px;letter-spacing:-.015em;
  text-transform:capitalize}
.pcell .s{color:var(--ink-4);font-size:var(--fs-xs);margin-top:2px;
  font-family:var(--font-mono)}

.tagp,.tagf,.tagw,.tagn{
  display:inline-block;font-size:9px;font-weight:750;letter-spacing:.07em;
  padding:1px 7px;border-radius:999px;text-transform:uppercase}
.tagp{color:var(--pos);background:var(--pos-soft)}
.tagf{color:var(--neg);background:var(--neg-soft)}
.tagw{color:var(--warn);background:var(--warn-soft)}
.tagn{color:var(--ink-4);background:var(--surface-3)}

/* ------------------------------------------------ allocation calculator */
.alloc{display:grid;grid-template-columns:1fr 1fr;gap:var(--sp-5)}
@media(max-width:900px){.alloc{grid-template-columns:1fr}}
.allocbar{
  display:flex;height:34px;border-radius:var(--r-sm);overflow:hidden;
  border:1px solid var(--line);margin:var(--sp-2) 0}
.allocbar i{
  display:flex;align-items:center;justify-content:center;font-size:var(--fs-xs);
  font-weight:650;color:#fff;font-family:var(--font-mono);min-width:0;overflow:hidden}
.allocbar i.LOW{background:var(--pos)}
.allocbar i.MEDIUM{background:var(--warn)}
.allocbar i.HIGH{background:var(--neg)}
.allocbar i.UNSCORED{background:var(--line-3)}
.targetrow{display:flex;align-items:center;gap:var(--sp-3);padding:var(--sp-2) 0}
.targetrow label{min-width:74px;font-size:var(--fs-sm);font-weight:600}
.targetrow input[type=range]{flex:1}
.targetrow .val{
  min-width:52px;text-align:right;font-family:var(--font-mono);font-size:var(--fs-sm)}
.targetrow .gap{min-width:74px;text-align:right;font-size:var(--fs-xs);
  font-family:var(--font-mono)}
.obs{margin:0;padding:0;list-style:none}
.obs li{
  font-size:var(--fs-sm);color:var(--ink-2);padding:var(--sp-2) 0 var(--sp-2) var(--sp-4);
  position:relative;border-bottom:1px solid var(--line);line-height:1.55}
.obs li:last-child{border-bottom:0}
.obs li:before{
  content:"";position:absolute;left:2px;top:14px;width:5px;height:5px;border-radius:50%;
  background:var(--warn)}

/* ==========================================================================
   Instrument bar + tab strip
   Two clearly separated rows: what you are looking at, then where you are in it.
   ========================================================================== */
.ctxbar{
  position:sticky;top:53px;z-index:40;margin:0 0 var(--sp-5);
  background:var(--surface);
  border:1px solid var(--line-2);border-radius:var(--r-lg);
  box-shadow:var(--shadow-md);overflow:hidden}

/* ---- row 1: the instrument ---- */
.ctxbar .row{
  display:flex;align-items:center;gap:var(--sp-4);
  padding:var(--sp-3) var(--sp-5);background:var(--surface-2)}
.ctxbar .flag{font-size:var(--fs-md);flex:none;line-height:1}
.ctxbar .nm{
  font-weight:640;font-size:var(--fs-base);letter-spacing:-.015em;color:var(--ink);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
.ctxbar .tk{
  color:var(--ink-3);font-family:var(--font-mono);font-size:var(--fs-xs);
  background:var(--surface-3);border:1px solid var(--line);border-radius:5px;
  padding:2px 7px;flex:none;letter-spacing:.02em}
.ctxbar .spacer{flex:1}
.ctxbar .px{
  font-family:var(--font-mono);font-weight:650;font-size:var(--fs-md);
  font-variant-numeric:tabular-nums;letter-spacing:-.02em;white-space:nowrap;
  color:var(--ink)}
.ctxbar .chg{
  font-family:var(--font-mono);font-size:var(--fs-xs);font-weight:600;
  padding:2px 7px;border-radius:5px;white-space:nowrap}
.ctxbar .chg.up{color:var(--pos);background:var(--pos-soft)}
.ctxbar .chg.down{color:var(--neg);background:var(--neg-soft)}
.ctxbar .chg.flat{color:var(--ink-3);background:var(--surface-3)}
.ctxbar .sc{
  display:flex;align-items:baseline;gap:3px;flex:none;
  font-family:var(--font-mono);font-weight:700;font-size:var(--fs-md);
  padding:3px 11px;border-radius:7px;border:1px solid currentColor;
  line-height:1.25;white-space:nowrap}
.ctxbar .sc small{font-size:var(--fs-2xs);font-weight:500;opacity:.65}

/* The 52-week band, kept in the sticky bar so the reader can see where the
   quoted price sits inside its own year from any tab. Hidden on narrow
   screens rather than allowed to squeeze the name out of the row. */
.ctxbar .ctx-w52{
  display:none;align-items:center;gap:var(--sp-2);flex:none;
  font-family:var(--font-mono);font-size:var(--fs-2xs);
  font-variant-numeric:tabular-nums;color:var(--ink-3);white-space:nowrap}
@media (min-width:900px){.ctxbar .ctx-w52{display:flex}}
.ctxbar .ctx-w52 .bar{
  position:relative;width:clamp(56px,7vw,96px);height:4px;border-radius:2px;
  background:linear-gradient(90deg,var(--neg-soft),var(--surface-3),var(--pos-soft));
  border:1px solid var(--line)}
.ctxbar .ctx-w52 .bar i{
  position:absolute;top:50%;width:2px;height:11px;border-radius:1px;
  background:var(--ink);transform:translate(-1px,-50%)}

/* the same reading, at panel scale, inside the snapshot */
/* Classes the templates have always used and the stylesheet never defined.
 * Each was written in a page script and silently did nothing: the wrapper of
 * the 52-week bar, the labels at its two ends, and the market chip in a
 * report's header. Found by asserting that every class a template applies
 * exists here — which is a cheap test and found a real gap on its first run. */
.w52-scale{display:flex;flex-direction:column;gap:6px}
.w52-ends .lo,.w52-ends .hi,.ctxbar .ctx-w52 .lo,.ctxbar .ctx-w52 .hi{
  font-family:var(--font-mono);font-size:var(--fs-xs);color:var(--ink-3);
  white-space:nowrap}
.meta .mkt{font-weight:600;color:var(--ink-2)}
.note.mt-note{margin-top:var(--sp-3)}

/* Shown only on paper. Without this the fund report printed its print-header
 * on screen, above the report it was meant to head. */
.print-only{display:none}
@media print{
  .print-only{display:block}
  .printhdr{margin-bottom:4mm;padding-bottom:2mm;border-bottom:.4pt solid #c8ced6}
  .printhdr b{font-size:12pt;color:#000}
  .printhdr .src{font-size:8pt;color:#4a5560}

  /* ---- the quality screen on paper ------------------------------------
   * The filter cards are number inputs, and a spinner is not information
   * once it is ink. They are replaced by .qs-applied, which says the same
   * thing as a sentence — a printed funnel whose thresholds are unknown
   * cannot be checked by the person holding it.
   *
   * The optional filters are hidden outright. The global print rule opens
   * every <details> on purpose, because an audit trail behind a triangle is
   * useless on paper; this one is the exception, since expanding it would
   * print twelve controls that were switched off. */
  .qs-grid,.qs-more{display:none!important}
  .qs-applied{border:.4pt solid #c8ced6;padding:3mm;margin-bottom:4mm}
  .qs-aname{font-size:7.4pt;letter-spacing:.09em;text-transform:uppercase;
    color:#4a5560;margin-bottom:2mm}
  .qs-alist{display:flex;flex-wrap:wrap;gap:1.6mm 5mm;font-size:8.6pt;color:#111}
  .qs-alist b{color:#000;font-weight:650}
  .qs-ameta{margin-top:2.5mm;font-size:7.8pt;color:#4a5560;line-height:1.5}

  /* The funnel is the page. Browsers drop background colour when printing
   * unless told otherwise, which would turn every bar into an empty box and
   * leave the one panel worth printing blank. */
  .qs-step{break-inside:avoid;page-break-inside:avoid}
  .qs-track{border:.4pt solid #c8ced6;height:3.4mm;
    -webkit-print-color-adjust:exact;print-color-adjust:exact}
  .qs-track i{-webkit-print-color-adjust:exact;print-color-adjust:exact;
    background:#2f4f8f!important;opacity:1}
  .qs-track i.gone{background:#e2e6ea!important;opacity:1}
  .qs-count{color:#000!important}
  .qs-head{border-bottom:.4pt solid #c8ced6;padding-bottom:2mm}

  /* This page's tables carry a column per enabled filter — up to twenty-one
   * columns on a sheet of A4. The shared rule holds headers on one line,
   * which is right for a six-column table and is what pushed this one off the
   * right edge of the paper. Scoped to the quality page so the layouts that
   * were verified elsewhere are untouched. */
  /* `fixed` rather than `auto`, because `auto` lets one unbreakable cell set
   * the table's width and the overflow is then clipped at the edge of the
   * paper rather than wrapped. That is what hid the Failed column: the chip
   * "Promoter / controlling holding" is thirty characters the browser was
   * told never to break (#out .chip sets white-space:nowrap), so with a
   * column per enabled filter the table ran off the sheet and took the two
   * right-hand columns with it. Fixed layout cannot exceed 100%, so the cells
   * wrap instead — and the chips are allowed to. */
  .q-page table{font-size:7pt;table-layout:fixed;width:100%}
  .q-page .chip{white-space:normal!important;margin:0 2px 1px 0;
    padding:0 3px;font-size:6.4pt;line-height:1.35}
  /* `break-word`, not `anywhere`: `anywhere` breaks inside a word even when
   * the word would have fitted on its own line, which turned the sector
   * "Basic Materials" into "Basic Mater ials". */
  .q-page td{overflow-wrap:break-word}
  /* A figure and its unit are already one token — `cells()` writes "13.90x"
   * with no space in it. It split because `anywhere` breaks inside a word;
   * `break-word` above is the whole fix, and forcing nowrap here as well
   * would only let a long value spill into the next column. */
  .q-page td.num,.q-page th.num{font-size:6.4pt}
  /* The company column carries words — name, ticker, sector and the tests it
   * missed — so it gets the room; the figures share what is left. The failed
   * tests are named in that cell and shaded in their own column, so no
   * separate column of unbreakable chips can push the table off the sheet. */
  .q-page th:first-child{width:34mm}
  .q-page .qs-open{display:none}             /* the arrow is a link, useless on paper */
  .q-page .qs-fail{-webkit-print-color-adjust:exact;print-color-adjust:exact}
  .q-page .qs-missed{white-space:normal}
  .q-page th{white-space:normal;padding:0 1.6mm 1.2mm 1.6mm;font-size:6.2pt;
    letter-spacing:.04em}
  .q-page td{padding:1.3mm 1.6mm}
  .q-page .tablewrap{overflow:visible}
  .q-page td b{font-size:7.4pt}
  .q-page .btn{display:none!important}   /* "Analyse" is a link, useless on paper */
}

.w52{margin-top:var(--sp-4)}
.w52-track{
  position:relative;height:7px;border-radius:4px;
  background:linear-gradient(90deg,var(--neg-soft),var(--surface-3),var(--pos-soft));
  border:1px solid var(--line)}
.w52-mark{
  position:absolute;top:50%;width:3px;height:17px;border-radius:2px;
  background:var(--ink);transform:translate(-1.5px,-50%);
  box-shadow:0 0 0 2px var(--surface)}
.w52-ends{
  display:flex;justify-content:space-between;margin-top:var(--sp-2);
  font-family:var(--font-mono);font-size:var(--fs-2xs);
  font-variant-numeric:tabular-nums;color:var(--ink-3)}
.w52-read{margin-top:var(--sp-2);font-size:var(--fs-sm);color:var(--ink-2)}

/* ---- row 2: the tab strip ---- */
.tabs{
  display:flex;gap:0;border-top:1px solid var(--line-2);
  overflow-x:auto;scrollbar-width:none;background:var(--surface)}
.tabs::-webkit-scrollbar{display:none}
.tabs button{
  appearance:none;background:none;border:0;
  border-bottom:2px solid transparent;
  color:var(--ink-3);font-family:var(--font-sans);
  font-size:var(--fs-2xs);font-weight:700;letter-spacing:.09em;text-transform:uppercase;
  padding:12px var(--sp-5) 10px;cursor:pointer;white-space:nowrap;
  transition:color .14s var(--ease),background .14s var(--ease);
  display:flex;align-items:center;gap:9px;position:relative}
.tabs button + button:before{
  content:"";position:absolute;left:0;top:11px;bottom:11px;width:1px;
  background:var(--line)}
.tabs button:hover{color:var(--ink);background:var(--surface-2)}
.tabs button:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}

/* the active tab has to be unmistakable — colour, weight, rail and fill */
.tabs button[aria-selected="true"]{
  color:var(--accent-ink);background:var(--accent-soft);
  border-bottom-color:var(--accent)}
.tabs button[aria-selected="true"]:before,
.tabs button[aria-selected="true"] + button:before{background:transparent}

.tabs button .n{
  font-family:var(--font-mono);font-size:var(--fs-2xs);font-weight:700;
  letter-spacing:0;color:var(--ink-4);background:var(--surface-3);
  border:1px solid var(--line);border-radius:999px;
  min-width:19px;height:19px;display:inline-flex;align-items:center;
  justify-content:center;padding:0 5px;line-height:1}
.tabs button[aria-selected="true"] .n{
  background:var(--accent);border-color:var(--accent);color:#fff}

.tabpanel{animation:tabin .22s var(--ease)}
.tabpanel[hidden]{display:none}
@keyframes tabin{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}}

/* ---- how the bar behaves as the screen narrows -------------------------
   1200+  full labels, wide padding
   1000+  padding tightens
    860+  tabs share the width equally instead of hugging the left
    700+  tabs scroll horizontally, snapping to each one
    560+  the instrument row wraps to two lines
   Every step keeps all five tabs reachable; none of them hides a tab. */
@media(min-width:1400px){
  .tabs button{padding:14px var(--sp-6) 12px}
  .ctxbar .row{padding:var(--sp-4) var(--sp-6)}
}
@media(max-width:1000px){
  .tabs button{padding:12px var(--sp-4) 10px}
}
@media(max-width:860px){
  .tabs{justify-content:stretch}
  .tabs button{flex:1 1 0;justify-content:center;padding:12px var(--sp-3) 10px;
    letter-spacing:.05em}
}
@media(max-width:700px){
  .tabs{justify-content:flex-start;scroll-snap-type:x mandatory;
    -webkit-overflow-scrolling:touch}
  .tabs button{flex:0 0 auto;scroll-snap-align:start;gap:6px;
    padding:12px var(--sp-4) 10px}
  /* a soft edge so it is obvious the strip scrolls */
  .ctxbar{position:relative}
  .ctxbar:after{
    content:"";position:absolute;right:0;bottom:0;width:26px;height:42px;
    pointer-events:none;
    background:linear-gradient(90deg,transparent,var(--surface))}
}
@media(max-width:560px){
  .ctxbar{top:49px}
  .ctxbar .row{flex-wrap:wrap;gap:var(--sp-2) var(--sp-3);padding:var(--sp-3) var(--sp-4)}
  .ctxbar .spacer{display:none}
  .ctxbar .nm{flex:1 1 100%;order:1}
  .ctxbar .flag{order:0}
  .ctxbar .tk{order:2}
  .ctxbar .px{order:3;margin-left:auto}
  .ctxbar .chg{order:4}
  .ctxbar .sc{order:5}
}
/* touch pointers get targets they can actually hit */
@media(pointer:coarse){
  .tabs button{min-height:46px}
  .navlinks a{min-height:44px;padding:0 12px}           /* a 44px target, the same for every item */
  .ctrl button{min-height:42px}
}

/* ==========================================================================
   Landing page additions
   ========================================================================== */
.statband{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));
  gap:1px;background:var(--line);border:1px solid var(--line);
  border-radius:var(--r-xl);overflow:hidden;margin:var(--sp-6) 0}
.statband div{background:var(--surface);padding:var(--sp-5) var(--sp-4);text-align:center}
.statband .n{
  font-family:var(--font-mono);font-size:var(--fs-2xl);font-weight:650;
  letter-spacing:-.035em;color:var(--ink);line-height:1}
.statband .l{color:var(--ink-3);font-size:var(--fs-xs);margin-top:var(--sp-2);
  line-height:1.45}

.showcase{display:grid;gap:var(--sp-4);grid-template-columns:repeat(2,minmax(0,1fr))}
@media(max-width:860px){.showcase{grid-template-columns:1fr}}
.shot{
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-xl);
  overflow:hidden;box-shadow:var(--shadow-md)}
.shot .cap{
  padding:var(--sp-3) var(--sp-5);border-bottom:1px solid var(--line);
  background:var(--surface-3);font-size:var(--fs-xs);color:var(--ink-3);
  display:flex;align-items:center;gap:var(--sp-2)}
.shot .cap b{color:var(--ink);font-weight:600}
.shot .body{padding:var(--sp-4) var(--sp-5) var(--sp-5)}

.catalogue{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:var(--sp-4)}
.catalogue section{
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:var(--sp-4) var(--sp-5)}
.catalogue h4{
  margin:0 0 var(--sp-3);font-size:var(--fs-2xs);letter-spacing:.11em;
  text-transform:uppercase;color:var(--ink-4);font-weight:700}
.catalogue ul{margin:0;padding:0;list-style:none;
  display:flex;flex-wrap:wrap;gap:5px}
.catalogue li{
  font-size:var(--fs-xs);color:var(--ink-2);background:var(--surface-3);
  border:1px solid var(--line);border-radius:5px;padding:2px 7px;
  font-family:var(--font-mono)}

.faq details{
  border:1px solid var(--line);border-radius:var(--r-lg);background:var(--surface);
  margin-bottom:var(--sp-3);overflow:hidden}
.faq summary{
  padding:var(--sp-4) var(--sp-5);cursor:pointer;font-weight:600;
  font-size:var(--fs-base);list-style:none;display:flex;align-items:center;
  justify-content:space-between;gap:var(--sp-4);transition:.15s var(--ease)}
.faq summary::-webkit-details-marker{display:none}
.faq summary:hover{background:var(--surface-2)}
.faq summary:after{content:"+";color:var(--ink-4);font-size:var(--fs-lg);
  font-weight:400;flex:none;transition:transform .2s var(--ease)}
.faq details[open] summary:after{transform:rotate(45deg)}
.faq .a{padding:0 var(--sp-5) var(--sp-4);color:var(--ink-2);font-size:var(--fs-sm);
  line-height:1.7;max-width:78ch}

.compare{width:100%;border-collapse:collapse;font-size:var(--fs-sm)}
.compare th{background:var(--surface-3);padding:var(--sp-3) var(--sp-4);
  border-bottom:1px solid var(--line-2)}
.compare td{padding:var(--sp-3) var(--sp-4);border-bottom:1px solid var(--line);
  vertical-align:top}
.compare td:first-child{font-weight:600;color:var(--ink)}
.compare .ours{color:var(--pos)}
.compare .theirs{color:var(--ink-3)}

@media print{
  .tabs,.ctxbar{display:none!important}
  .tabpanel[hidden]{display:block!important}
  .statband,.showcase,.faq,.catalogue{break-inside:avoid}
}

/* ==========================================================================
   Responsive behaviour for the rest of the app
   ========================================================================== */

/* Wide tables get their own scroll rather than forcing the page sideways. */
.tablewrap{overflow-x:auto;-webkit-overflow-scrolling:touch;margin:0 -2px;padding:0 2px}
.tablewrap table{min-width:520px}
/* tables wrapped on phones by theme.js: as wide as the card, wider only when
   they have enough columns to need it */
.tablewrap--auto table{min-width:100%}
/* in px: on a phone these tables set a smaller font, so an em width came out
   too narrow to help */
.tablewrap--auto table.is-wide{min-width:480px}
@media(max-width:700px){.tablewrap table.is-xwide{min-width:680px}}
@media(max-width:700px){
  .tablewrap--auto{margin:0;padding:0}
  .tablewrap--auto th,.tablewrap--auto td{padding-left:10px;padding-right:10px}
  .tablewrap--auto th:first-child,.tablewrap--auto td:first-child{padding-left:0}
  .tablewrap--auto th:last-child,.tablewrap--auto td:last-child{padding-right:0}
}

@media(max-width:1100px){
  .grid.g3{grid-template-columns:repeat(2,minmax(0,1fr))}
}
@media(max-width:820px){
  /* minmax(0,…): a plain 1fr column grows to its widest table and takes the
     card past the screen edge with it */
  .grid.g2,.grid.g3{grid-template-columns:minmax(0,1fr)}
  .swot{grid-template-columns:1fr}
  .hdr{gap:var(--sp-4)}
  .hdr .px{margin-left:0;text-align:left;width:100%}
  .scorebadge{border-left:0;padding-left:0;border-top:1px solid var(--line);
    padding-top:var(--sp-3);width:100%;text-align:left;display:flex;
    align-items:baseline;gap:var(--sp-3)}
  .scorebadge .b{margin-top:0}
  .subscore .top{flex-wrap:wrap;gap:var(--sp-2) var(--sp-3)}
  .subscore .nm{min-width:0;flex:1 1 100%}
  .subscore .sc{min-width:0}
  .panel{padding:var(--sp-4) var(--sp-4) var(--sp-5)}
}
@media(max-width:620px){
  .searchbox{flex-wrap:wrap}
  .searchbox input{flex:1 1 100%}
  .searchbox button{flex:1 1 100%;padding:12px}
  .suggest{right:0;top:auto;margin-top:56px}
  .kpi{grid-template-columns:repeat(auto-fit,minmax(104px,1fr))}
  .console{max-height:200px}
  .mathbox{font-size:10px}
  table{font-size:var(--fs-xs)}
  td,th{padding-right:var(--sp-2)}
}

/* Very wide screens: use the room rather than stretching two columns across it. */
@media(min-width:1700px){
  .kpi{grid-template-columns:repeat(auto-fit,minmax(150px,1fr))}
}

@media(prefers-reduced-motion:reduce){
  .tabpanel{animation:none}
}

/* The full strategy report is built for the PDF, not for the screen — it would
   otherwise repeat on the page everything the selector already shows. */
.st-full{display:none}
.st-full:not(:empty){display:block;margin-top:var(--sp-5)}
@media screen{
  .st-full:not(:empty):before{
    content:"Prepared for download — every signal, below.";
    display:block;font-size:var(--fs-xs);color:var(--ink-4);
    padding-bottom:var(--sp-2);border-bottom:1px solid var(--line);
    margin-bottom:var(--sp-4)}
}
@media print{
  .st-full canvas{max-height:52mm!important}
  .st-full .panel{break-inside:avoid;page-break-inside:avoid}

  /* Browsers drop background images when printing, which would leave the
     52-week bar as an empty box with a marker floating in it. Force the fill,
     and keep an outline so the reading survives even if the browser refuses. */
  .w52{break-inside:avoid;page-break-inside:avoid}
  .w52-track{
    -webkit-print-color-adjust:exact;print-color-adjust:exact;
    background:#eceff3!important;border:1px solid #b9c0c9!important}
  .w52-mark{
    -webkit-print-color-adjust:exact;print-color-adjust:exact;
    background:#0f1419!important;height:15px}
}


/* Short "use it to / it will not" lists. Restrained on purpose: this is the
   first thing a reader meets on the Screen page and it should orient them,
   not decorate. */
ul.plain{margin:0;padding:0;list-style:none}
ul.plain li{
  position:relative;padding:4px 0 4px 18px;color:var(--ink-2);
  font-size:var(--fs-sm);line-height:1.5}
ul.plain li::before{
  content:"";position:absolute;left:2px;top:12px;width:5px;height:5px;
  border-radius:50%;background:var(--ink-4)}


/* This week's pick, joined to what the screen has said about it before. */
.pickhist{
  display:flex;align-items:baseline;gap:var(--sp-2);flex-wrap:wrap;
  margin:var(--sp-2) 0 0;padding:var(--sp-2) var(--sp-3);
  background:var(--surface-3);border-radius:var(--r-sm);
  font-size:var(--fs-sm)}
.tag.new{background:var(--info-soft);color:var(--info)}
.tag.again{background:var(--accent-soft);color:var(--accent-ink)}
.tag.new,.tag.again{
  font-family:var(--font-mono);font-size:var(--fs-2xs);font-weight:700;
  letter-spacing:.06em;padding:2px 7px;border-radius:4px}
@media print{
  .pickhist{-webkit-print-color-adjust:exact;print-color-adjust:exact;
    border:1px solid var(--line)}
}

/* ==========================================================================
   Funds — mutual funds, ETFs and SIPs. Reuses every token above; these are
   only the few elements the stock pages do not already have.
   ========================================================================== */
.fundsbar{
  position:sticky;top:53px;z-index:40;margin:0 0 var(--sp-5);
  background:var(--surface);border:1px solid var(--line-2);
  border-radius:var(--r-lg);box-shadow:var(--shadow-md);overflow:hidden}
.fundsbar .row{
  display:flex;align-items:center;gap:var(--sp-3);flex-wrap:wrap;
  padding:var(--sp-3) var(--sp-5);background:var(--surface-2)}
.fundsbar .nm{font-weight:640;font-size:var(--fs-base);letter-spacing:-.015em}
.fundsbar .spacer{flex:1}
.fxlabel{
  display:flex;align-items:center;gap:var(--sp-2);color:var(--ink-3);
  font-size:var(--fs-xs);white-space:nowrap}
.fxlabel input,.fxlabel select{
  background:var(--surface);border:1px solid var(--line-2);border-radius:var(--r-sm);
  color:var(--ink);font-family:var(--font-mono);font-size:var(--fs-xs);
  padding:5px var(--sp-2)}
.fundsbar .tabs{border-top:1px solid var(--line-2)}

/* the add/import forms: plain rows that wrap rather than a grid that fights */
.formrow{
  display:flex;gap:var(--sp-2);flex-wrap:wrap;align-items:center;
  margin:var(--sp-3) 0}
.formrow input,.formrow select,#out textarea{
  background:var(--surface);border:1px solid var(--line-2);border-radius:var(--r-sm);
  color:var(--ink);font-family:var(--font-sans);font-size:var(--fs-sm);
  padding:7px var(--sp-3)}
.formrow input{min-width:12ch}
#out textarea{
  width:100%;font-family:var(--font-mono);font-size:var(--fs-xs);
  line-height:1.5;resize:vertical}
.formrow button{
  background:var(--surface);border:1px solid var(--line-2);border-radius:var(--r-sm);
  color:var(--ink-2);font-size:var(--fs-sm);padding:7px var(--sp-4);cursor:pointer}
.formrow button:hover{border-color:var(--line-3);color:var(--ink)}
.formrow button.btn-primary{background:var(--accent);border-color:var(--accent);color:#fff}
.formrow button.btn-primary:hover{background:var(--accent-ink)}

/* a chip naming which fund an exposure arrived through */
#out .chip{
  display:inline-block;background:var(--surface-3);border:1px solid var(--line);
  border-radius:999px;padding:1px 8px;margin:1px 2px 1px 0;
  font-size:var(--fs-2xs);color:var(--ink-3);white-space:nowrap}

/* ==========================================================================
   FinNexus Global Terminal — foundation layer (v3)
   Shared patterns every page may use. Names are documented in
   DESIGN_SYSTEM.md; a page that needs something new adds it here, not in
   its own <style>. Order: base · buttons · cards · status · provenance ·
   missing data · score ring · world network · motion · print.
   ========================================================================== */

/* ---------------------------------------------------------------- base */
html{background:var(--bg)}
body{
  background-color:var(--bg);background-image:var(--nx-bg-gradient);
  background-repeat:no-repeat;background-size:100% 100vh;
  font-feature-settings:"cv11" 1,"ss01" 1}
h1,h2,h3,.nx-display{font-family:var(--font-display);color:var(--ink)}
:focus-visible{outline:2px solid var(--nx-blue);outline-offset:2px}
::selection{background:color-mix(in srgb,var(--nx-cyan) 26%,transparent);color:var(--ink)}
/* the new mark is a transparent glyph, not a tile — a drop shadow outlines nothing */
.brandmark,[data-theme="dark"] .brandmark{box-shadow:none;border-radius:0;object-fit:contain}

/* theme switch: colours ease for one beat, then transitions are removed again
   so nothing else on the page inherits a stray animation (theme.js) */
html.nx-theme-switching,html.nx-theme-switching *,
html.nx-theme-switching *::before,html.nx-theme-switching *::after{
  transition:background-color var(--motion-normal) var(--ease-nx),
    border-color var(--motion-normal) var(--ease-nx),
    color var(--motion-normal) var(--ease-nx),
    fill var(--motion-normal) var(--ease-nx),
    stroke var(--motion-normal) var(--ease-nx)!important}

/* ---------------------------------------------------------- lockup (brand) */
.nx-lockup{display:inline-flex;align-items:center;gap:10px;color:var(--ink);
  text-decoration:none;min-width:0}
.nx-lockup:hover{text-decoration:none}
.nx-lockup img{width:34px;height:34px;flex:none;object-fit:contain}
.nx-lockup .nx-word{display:flex;flex-direction:column;line-height:1;min-width:0}
.nx-lockup .nx-word b{
  font-family:var(--font-display);font-size:19px;font-weight:750;letter-spacing:-.025em;
  color:var(--nx-navy-800);white-space:nowrap}
.nx-lockup .nx-word b span{
  background:linear-gradient(90deg,#0B8F9A,#0AA77C);-webkit-background-clip:text;
  background-clip:text;color:transparent}
.nx-lockup .nx-word small{
  font-size:9px;font-weight:600;letter-spacing:.42em;text-transform:uppercase;
  color:var(--ink-3);margin-top:4px;padding-left:1px}
[data-theme="dark"] .nx-lockup .nx-word b{color:#F3F9FE}
[data-theme="dark"] .nx-lockup .nx-word b span{
  background:linear-gradient(90deg,#26D5F4,#17C693);-webkit-background-clip:text;background-clip:text}

/* ------------------------------------------------------------- buttons
   Primary is deep navy in light (12:1 under white) and a mid blue in dark;
   never the light accent, which white text cannot sit on at AA. */
.btn{border-radius:var(--r-md);
  transition:background-color var(--motion-fast) var(--ease-nx),border-color var(--motion-fast) var(--ease-nx),
    color var(--motion-fast) var(--ease-nx),transform var(--motion-fast) var(--ease-nx),
    box-shadow var(--motion-fast) var(--ease-nx)}
.btn-primary,a.btn-primary{
  background:var(--nx-primary-bg);color:#fff;border-color:transparent;
  box-shadow:0 6px 18px -8px rgba(8,36,66,.55)}
.btn-primary:hover,a.btn-primary:hover{
  background:var(--nx-primary-bg-hover);color:#fff;border-color:transparent}
.btn-primary:active,.btn-ghost:active{transform:translateY(1px)}
.btn:focus-visible{outline:none;box-shadow:var(--nx-focus-ring)}
.btn .nx-ico{width:16px;height:16px;flex:none}
/* the search submit is a primary action too: same fill, same AA guarantee */
.searchbox button{background:var(--nx-primary-bg)}
.searchbox button:hover{background:var(--nx-primary-bg-hover)}

/* --------------------------------------------- AnalyticalCard / ChartCard
   card > head (icon · title · info · action) > body > foot (source/status) */
.nx-card{
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);
  box-shadow:var(--shadow-sm);padding:var(--sp-4) var(--sp-5);min-width:0;position:relative}
.nx-card--elevated{box-shadow:var(--shadow-lg)}
.nx-card__head{display:flex;align-items:center;gap:var(--sp-2);margin-bottom:var(--sp-3);min-width:0}
.nx-card__icon{
  width:34px;height:34px;border-radius:10px;flex:none;display:grid;place-items:center;
  color:var(--nx-blue-ink);background:var(--nx-blue-soft);
  border:1px solid color-mix(in srgb,var(--nx-blue) 16%,transparent)}
.nx-card__icon svg{width:18px;height:18px}
.nx-card__title{font-family:var(--font-display);font-size:var(--fs-h3);font-weight:700;
  letter-spacing:-.015em;color:var(--ink);margin:0;line-height:1.25}
.nx-card__meta{color:var(--ink-3);font-size:var(--fs-xs)}
.nx-card__action{margin-left:auto;flex:none;color:var(--ink-4)}
.nx-card__body{min-width:0}
.nx-card__foot{margin-top:var(--sp-3);padding-top:var(--sp-3);border-top:1px solid var(--line);
  color:var(--ink-4);font-size:var(--fs-xs);display:flex;gap:var(--sp-3);flex-wrap:wrap}
/* only interactive cards move — a static analytical card never floats */
.nx-card.is-interactive,a.nx-card{
  cursor:pointer;color:inherit;text-decoration:none;
  transition:transform var(--motion-normal) var(--ease-nx),box-shadow var(--motion-normal) var(--ease-nx),
    border-color var(--motion-normal) var(--ease-nx)}
.nx-card.is-interactive:hover,a.nx-card:hover{
  transform:translateY(-2px);box-shadow:var(--shadow-md);border-color:var(--line-2);text-decoration:none}
.nx-card.is-interactive:focus-visible,a.nx-card:focus-visible{outline:none;box-shadow:var(--nx-focus-ring)}

/* --------------------------------------------------------- StatusBadge
   Icon + text + colour, never colour alone. N/A is grey and never resembles PASS. */
.nx-status{
  display:inline-flex;align-items:center;gap:5px;border-radius:var(--r-pill);
  padding:2px 9px 2px 7px;font-size:var(--fs-2xs);font-weight:750;letter-spacing:.06em;
  text-transform:uppercase;white-space:nowrap;line-height:1.6;border:1px solid transparent}
.nx-status::before{
  font-family:var(--font-sans);font-size:10px;font-weight:800;line-height:1;
  width:13px;height:13px;border-radius:50%;display:grid;place-items:center;
  color:var(--surface)}
.nx-status--pass{color:var(--nx-positive-ink);background:var(--nx-positive-soft)}
.nx-status--pass::before{content:"✓";background:var(--nx-positive)}
.nx-status--warn{color:var(--nx-warning-ink);background:var(--nx-warning-soft)}
.nx-status--warn::before{content:"!";background:var(--nx-warning)}
.nx-status--fail{color:var(--nx-negative-ink);background:var(--nx-negative-soft)}
.nx-status--fail::before{content:"✕";background:var(--nx-negative)}
.nx-status--na{color:var(--nx-nodata-ink);background:transparent;border:1px dashed var(--nx-nodata)}
.nx-status--na::before{content:"–";background:var(--nx-nodata)}
.nx-status--info{color:var(--nx-info-ink);background:var(--nx-info-soft)}
.nx-status--info::before{content:"i";background:var(--nx-info)}

/* ---------------------------------------- SourceBadge / Provenance / As-of */
.nx-source{
  display:inline-flex;align-items:center;gap:6px;flex-wrap:wrap;
  font-size:var(--fs-2xs);color:var(--ink-4);font-family:var(--font-mono);letter-spacing:0}
.nx-source b{font-family:var(--font-sans);font-weight:650;color:var(--ink-3)}
.nx-source .nx-kind{
  border:1px solid var(--line-2);border-radius:4px;padding:0 5px;text-transform:uppercase;
  font-family:var(--font-sans);font-weight:700;letter-spacing:.06em;font-size:9px}
.nx-source .nx-kind.is-derived{color:var(--nx-teal-ink);border-color:color-mix(in srgb,var(--nx-teal) 40%,transparent)}
.nx-source .nx-kind.is-reported{color:var(--nx-info-ink);border-color:color-mix(in srgb,var(--nx-info) 40%,transparent)}
.nx-source .nx-kind.is-ai{color:var(--ink-3);border-style:dashed}
.nx-source .nx-conflict{color:var(--nx-warning-ink)}
.nx-asof{
  display:inline-flex;align-items:center;gap:6px;font-size:var(--fs-xs);color:var(--ink-3);
  font-variant-numeric:tabular-nums;white-space:nowrap}
.nx-asof::before{
  content:"";width:6px;height:6px;border-radius:50%;flex:none;
  background:var(--nx-neutral);box-shadow:0 0 0 3px var(--nx-neutral-soft)}
/* stored data is not live data: no green dot, no pulse, unless a page proves
   the source is live and adds .is-live itself */
.nx-asof.is-live::before{background:var(--nx-positive);box-shadow:0 0 0 3px var(--nx-positive-soft)}

/* ------------------------------------------------------------ MissingData */
.nx-missing{
  display:inline-flex;align-items:center;gap:6px;color:var(--nx-nodata-ink);
  font-size:var(--fs-xs);font-style:normal;font-family:var(--font-sans)}
.nx-missing::before{
  content:"";width:10px;height:10px;border-radius:2px;flex:none;
  background:repeating-linear-gradient(135deg,var(--nx-nodata) 0 2px,transparent 2px 4px)}
.nx-empty{
  border:1px dashed var(--line-2);border-radius:var(--r-lg);padding:var(--sp-6);
  text-align:center;color:var(--ink-3);background:var(--surface-2)}
.nx-empty h4{margin:0 0 var(--sp-2);color:var(--ink);font-size:var(--fs-md)}

/* --------------------------------------------------------------- ScoreRing
   Analytical, not a verdict: neutral brand colour regardless of the value. */
.nx-ring{--val:0;--size:112px;--stroke:3px;position:relative;width:var(--size);
  height:var(--size);flex:none;display:grid;place-items:center}
.nx-ring svg{position:absolute;inset:0;transform:rotate(-90deg)}
.nx-ring .nx-ring__track{fill:none;stroke:var(--line);stroke-width:var(--stroke)}
.nx-ring .nx-ring__val{fill:none;stroke:var(--nx-teal);
  stroke-width:var(--stroke);stroke-linecap:round;
  stroke-dasharray:var(--val) 100;transition:stroke-dasharray 800ms var(--ease-nx)}
.nx-ring .nx-ring__num{text-align:center;line-height:1}
.nx-ring .nx-ring__num b{display:block;font-family:var(--font-mono);font-size:calc(var(--size) * .27);
  font-weight:700;letter-spacing:-.04em;color:var(--ink);font-variant-numeric:tabular-nums}
.nx-ring .nx-ring__num small{font-size:11px;color:var(--ink-4);font-family:var(--font-mono)}

/* ----------------------------------------------------------- WorldNetwork
   One component (static/js/world-network.js). Mount with
   <div class="nx-world" data-world-network="marketing|app"></div>.
   Always decorative: aria-hidden, no pointer events, below content. */
.nx-world{position:absolute;inset:0;pointer-events:none;overflow:hidden;z-index:0;
  contain:strict}
.nx-world svg{position:absolute;left:50%;top:50%;width:max(100%,1200px);height:auto;
  transform:translate(-50%,-50%) translate3d(var(--nx-px,0px),var(--nx-py,0px),0);
  transition:transform 600ms var(--ease-nx)}
.nx-world[data-world-network="marketing"] .nx-world__dots{opacity:var(--nx-map-opacity-marketing)}
.nx-world[data-world-network="app"] .nx-world__dots{opacity:var(--nx-map-opacity-app)}
.nx-world__dots{stroke:var(--nx-map-dot);fill:none;stroke-width:2.9}
.nx-world__arc{fill:none;stroke:var(--nx-map-arc);stroke-width:1.35;stroke-linecap:round;
  opacity:var(--nx-map-arc-opacity);vector-effect:non-scaling-stroke}
.nx-world[data-world-network="app"] .nx-world__arc{opacity:calc(var(--nx-map-arc-opacity) * .35)}
.nx-world__pulse{fill:var(--nx-map-pulse);filter:drop-shadow(0 0 4px var(--nx-map-pulse))}
.nx-world[data-world-network="app"] .nx-world__pulse{display:none}
.nx-world__node circle.core{fill:var(--nx-map-node);stroke:var(--surface);stroke-width:2}
.nx-world__node circle.ring{fill:var(--nx-map-node-ring);
  transition:r var(--motion-panel) var(--ease-nx),fill var(--motion-panel) var(--ease-nx)}
.nx-world__node text{font-family:var(--font-sans);font-size:11px;font-weight:650;
  fill:var(--ink-2);letter-spacing:.02em}
.nx-world__node rect{fill:var(--nx-surface-glass);stroke:var(--line-2)}
/* Admin → Data → Markets: one switch per market */
.adm-markets{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:8px;margin:12px 0}
.adm-mkt{display:flex;align-items:center;gap:10px;padding:10px 12px;border:1px solid var(--line);border-radius:10px;
  cursor:pointer;opacity:.6;transition:opacity 150ms,border-color 150ms}
.adm-mkt.on{opacity:1;border-color:color-mix(in srgb,var(--nx-blue) 40%,var(--line))}
.adm-mkt__flag{font-size:20px;line-height:1}
.adm-mkt__name{display:flex;flex-direction:column;min-width:0}
.adm-mkt__name .src{font-size:var(--fs-xs)}

.nx-world[data-world-network="app"] .nx-world__node{opacity:.45}
.nx-world[data-world-network="app"] .nx-world__node text,
.nx-world[data-world-network="app"] .nx-world__node rect{display:none}
/* a selected market lights its node; the others step back */
.nx-world.has-selection .nx-world__node{opacity:.35}
.nx-world.has-selection .nx-world__node.is-selected{opacity:1}
.nx-world__node.is-selected circle.ring{fill:color-mix(in srgb,var(--nx-cyan) 34%,transparent)}
@media(max-width:720px){.nx-world__node text,.nx-world__node rect{display:none}}

/* ------------------------------------------------------------------ motion
   Enter once, then hold still. Pure CSS, so with JavaScript off the content
   is simply there — no hidden state waiting on a script to reveal it.
   .nx-reveal on any block; style="--i:N" staggers siblings by 50ms each. */
@keyframes nx-enter{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
@keyframes nx-tab-in{from{opacity:0;transform:translateX(6px)}to{opacity:1;transform:none}}
.nx-reveal{animation:nx-enter var(--motion-enter) var(--ease-nx) both;
  animation-delay:calc(var(--i,0) * 50ms)}
.nx-tab-enter{animation:nx-tab-in var(--motion-normal) var(--ease-nx) both}
@media(prefers-reduced-motion:reduce){
  .nx-reveal,.nx-tab-enter{animation:none}
  html.nx-theme-switching,html.nx-theme-switching *{transition:none!important}
  .nx-world svg{transition:none}
  .nx-ring .nx-ring__val{transition:none}
  .nx-card.is-interactive:hover,a.nx-card:hover{transform:none}
}

/* -------------------------------------------------------------------- print */
@media print{
  .nx-world{display:none!important}
  .nx-status,.nx-asof::before,.nx-missing::before{print-color-adjust:exact;-webkit-print-color-adjust:exact}
  body{background-image:none!important}
}

/* ==========================================================================
   FinNexus Global Terminal — application layer (v3)
   The shared shell (partials/app-shell.html) and the v3 treatment of the
   components every terminal page renders. Restyles existing classes only:
   no selector a script or test relies on is renamed.
   ========================================================================== */

/* -------------------------------------------------------------- AppShell */
.skip-link{position:absolute;left:-9999px;top:8px;z-index:200;background:var(--surface);
  color:var(--ink);padding:8px 14px;border-radius:var(--r-md);box-shadow:var(--shadow-md)}
.skip-link:focus{left:16px}

/* AppTopbar: solid, not frosted — backdrop-filter would make the topbar the
   containing block for the fixed sidebar inside it */
.topbar{
  background:var(--surface);backdrop-filter:none;-webkit-backdrop-filter:none;
  border-bottom:1px solid var(--line);z-index:60}
[data-theme="dark"] .topbar{background:color-mix(in srgb,var(--nx-surface) 94%,#000)}
.topbar .inner{min-height:var(--nx-shell-topbar);padding:0 clamp(14px,2vw,28px);gap:var(--sp-4)}
.topbar .brand{flex:none}
.app-menu{
  display:none;width:38px;height:38px;flex:none;place-items:center;padding:0;cursor:pointer;
  border:1px solid var(--line-2);border-radius:var(--r-md);background:var(--surface);color:var(--ink-2)}
.app-menu svg{width:18px;height:18px}
.app-menu:focus-visible{outline:none;box-shadow:var(--nx-focus-ring)}
.app-crumb{
  font-size:var(--fs-sm);font-weight:650;color:var(--ink-2);white-space:nowrap;
  padding-left:var(--sp-4);border-left:1px solid var(--line);line-height:28px}
.app-crumb:empty{display:none}
.app-markets{margin-left:auto;display:flex;gap:4px;flex:none}
.app-markets i{
  font-style:normal;font-size:var(--fs-2xs);font-weight:700;letter-spacing:.05em;color:var(--ink-3);
  border:1px solid var(--line);border-radius:7px;padding:3px 8px;background:var(--surface-2)}

/* Sidebar: the same .navlinks the pages always had, now a fixed rail */
.navlinks{
  position:fixed;top:var(--nx-shell-topbar);left:0;bottom:0;z-index:55;
  width:var(--nx-shell-sidebar);margin:0;padding:var(--sp-4) 12px var(--sp-3);
  display:flex;flex-direction:column;flex-wrap:nowrap;align-items:stretch;
  justify-content:flex-start;gap:4px;overflow-y:auto;overscroll-behavior:contain;
  background:var(--surface);border-right:1px solid var(--line)}
[data-theme="dark"] .navlinks{background:color-mix(in srgb,var(--nx-surface) 94%,#000)}
/* One rhythm on a 4px grid: every item the same height, every section heading
   the same space above (20px) and below (4px), the divider the same space on
   both sides — so the list reads as evenly spaced at any size. */
.navlinks .nav-sec{
  display:block;margin:20px 0 4px;padding:0 12px;line-height:16px;
  font-size:var(--fs-2xs);font-weight:700;letter-spacing:.12em;text-transform:uppercase;
  color:var(--ink-4)}

.navlinks a{
  display:flex;align-items:center;gap:12px;min-height:40px;padding:0 12px;border-radius:10px;flex:none;
  font-size:var(--fs-sm);font-weight:600;letter-spacing:0;text-transform:none;
  color:var(--ink-3);border:0;position:relative;
  transition:background-color var(--motion-fast) var(--ease-nx),color var(--motion-fast) var(--ease-nx)}
.navlinks a svg{width:18px;height:18px;flex:none;fill:none;stroke:currentColor;stroke-width:1.8;
  stroke-linecap:round;stroke-linejoin:round}
.navlinks a small{margin-left:6px;font-size:9.5px;font-weight:700;letter-spacing:.06em;
  text-transform:uppercase;color:var(--ink-4);border:1px solid var(--line-2);border-radius:5px;padding:0 4px}
.navlinks a:hover{color:var(--ink);background:var(--surface-3);text-decoration:none}
.navlinks a.homelink{color:var(--ink-3)!important;font-weight:600;letter-spacing:0}
.navlinks a.nav-sub{padding:6px 12px 6px 41px;font-size:var(--fs-xs);font-weight:550}
.navlinks a.is-parent{color:var(--ink)}
/* selected: soft blue fill + blue rail in light, deep panel + cyan edge in dark */
.navlinks a.active{
  color:var(--accent);background:var(--accent-soft);border-color:transparent;
  box-shadow:inset 3px 0 0 var(--nx-blue)}
[data-theme="dark"] .navlinks a.active{
  color:#fff;background:linear-gradient(90deg,rgba(38,213,244,.16),rgba(63,152,255,.06));
  box-shadow:inset 3px 0 0 var(--nx-cyan),0 0 22px -10px rgba(38,213,244,.6)}
[data-theme="dark"] .navlinks a.active svg{color:var(--nx-cyan)}
.navlinks a:focus-visible{outline:none;box-shadow:var(--nx-focus-ring)}
.navlinks .nav-foot{
  margin-top:auto;padding:var(--sp-3) 6px 0;border-top:1px solid var(--line);
  display:flex;align-items:center;justify-content:space-between;gap:var(--sp-3)}
.navlinks .nav-note{font-size:var(--fs-2xs);color:var(--ink-4);line-height:1.4}
.app-scrim{display:none}

/* the page column sits to the right of the rail */
@media(min-width:1101px){
  body:has(> .topbar) > :not(.topbar):not(.app-scrim):not(.skip-link):not(script){
    margin-left:var(--nx-shell-sidebar)}
}
/* narrower: the rail becomes a drawer */
@media(max-width:1100px){
  .app-menu{display:grid}
  .navlinks{transform:translateX(-102%);visibility:hidden;
    transition:transform var(--motion-panel) var(--ease-nx),visibility 0s linear var(--motion-panel);
    box-shadow:var(--shadow-lg);
    /* the drawer is as tall as the screen you can see: on a phone, "bottom: 0"
       is behind the browser's own toolbar, which hid the theme switch and the
       legal links; and it clears the home indicator */
    padding-bottom:calc(var(--sp-3) + env(safe-area-inset-bottom, 0px))}
  @supports (height:100dvh){ .navlinks{bottom:auto;height:calc(100dvh - var(--nx-shell-topbar))} }
  html.nx-nav-open .navlinks{transform:none;visibility:visible;
    transition:transform var(--motion-panel) var(--ease-nx)}
  .app-scrim{display:block;position:fixed;inset:var(--nx-shell-topbar) 0 0 0;z-index:54;
    background:rgba(3,18,37,.38);opacity:0;pointer-events:none;
    transition:opacity var(--motion-panel) var(--ease-nx)}
  html.nx-nav-open .app-scrim{opacity:1;pointer-events:auto}
}
@media(max-width:760px){.app-markets{display:none}
  /* the market chips pushed the account button right; without them it does it itself */
  .topbar .nx-user{margin-left:auto}}
@media(max-width:520px){
  .app-crumb{display:none}
  .topbar .nx-lockup .nx-word small{display:none}
}
@media(prefers-reduced-motion:reduce){.navlinks,.app-scrim{transition:none!important}}

.wrap{padding:var(--sp-5) clamp(16px,2.4vw,40px) var(--sp-8);max-width:var(--nx-max-app)}
.footer{text-align:left;max-width:var(--nx-max-app);
  padding:var(--sp-5) clamp(16px,2.4vw,40px);margin-top:var(--sp-6);line-height:1.8}

/* -------------------------------------------------------------- PageHeader */
.nx-pagehead{
  position:relative;overflow:hidden;isolation:isolate;
  display:flex;align-items:flex-end;justify-content:space-between;gap:var(--sp-5);flex-wrap:wrap;
  padding:var(--sp-5) var(--sp-6);margin:0 0 var(--sp-5);
  border:1px solid var(--line);border-radius:var(--r-xl);
  background:
    radial-gradient(600px 220px at 92% 0%, color-mix(in srgb,var(--nx-cyan) 9%,transparent), transparent 70%),
    var(--surface);
  box-shadow:var(--shadow-sm)}
.nx-pagehead .nx-world svg{left:auto;right:-12%;width:max(75%,900px);top:40%;
  transform:translate(0,-50%)}
.nx-pagehead .nx-world[data-world-network="app"] .nx-world__dots{opacity:calc(var(--nx-map-opacity-app) * 1.6)}
.nx-pagehead__main{position:relative;z-index:1;max-width:84ch;min-width:0}
.nx-pagehead h1{font-size:var(--fs-h1);font-weight:780;letter-spacing:-.032em;line-height:1.1;
  margin:6px 0 8px;color:var(--ink)}
.nx-pagehead p{margin:0;color:var(--ink-3);font-size:var(--fs-sm);line-height:1.6}
.nx-pagehead__aside{position:relative;z-index:1;display:flex;gap:var(--sp-2);align-items:center;flex-wrap:wrap}
.nx-eyebrow{font-size:var(--fs-label);font-weight:700;letter-spacing:.14em;text-transform:uppercase;
  color:var(--nx-teal-ink)}
@media(max-width:620px){.nx-pagehead{padding:var(--sp-4)}}

/* ------------------------------------------------- analytical surfaces */
.panel{border-radius:var(--r-lg);padding:var(--sp-5) var(--sp-5) var(--sp-5);box-shadow:var(--shadow-sm)}
[data-theme="dark"] .panel,[data-theme="dark"] .hdr,[data-theme="dark"] .ctxbar,
[data-theme="dark"] .nx-pagehead{background:var(--nx-surface)}
.panel h3{font-family:var(--font-display);font-size:var(--fs-md);font-weight:720;letter-spacing:-.018em}
.panel-num{border-radius:6px;background:var(--surface-2);color:var(--ink-4)}
.panel .sub{color:var(--ink-3)}
.grid{gap:var(--sp-4)}
.note{color:var(--ink-3)}
.banner{border-radius:var(--r-md)}
.banner.warn{border:1px solid color-mix(in srgb,var(--nx-warning) 40%,transparent)}
.banner.err{border:1px solid color-mix(in srgb,var(--nx-negative) 40%,transparent)}
.mathbox{background:var(--surface-2);border-radius:var(--r-md)}
.console{border-radius:var(--r-lg);border-color:var(--nx-border-strong);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.04)}
.cl .s.start{color:#5AA8FF} .cl .s.ok,.cl .s.PASS{color:#24C997} .cl .s.warn,.cl .s.WARN{color:#E6A43A}
.cl .s.error,.cl .s.FAIL{color:#FF7180} .cl .s.NA{color:#748CA3} .cl .s.info{color:#26D5F4}

/* search: the primary input on several pages */
.searchbox input{border-radius:12px;border-color:var(--line-2);font-size:var(--fs-base);padding:13px var(--sp-4)}
.searchbox input:focus{border-color:var(--nx-blue);box-shadow:var(--nx-focus-ring)}
.searchbox button{border-radius:12px;letter-spacing:.06em;font-weight:700;padding:0 var(--sp-5)}
.suggest{border-radius:12px;top:56px}
.hint{margin:var(--sp-2) 0 var(--sp-5)}

/* controls */
.ctrl button,.ctrl select,.ctrl label{border-radius:var(--r-md)}
.ctrl button{font-weight:600;transition:background-color var(--motion-fast) var(--ease-nx),
  border-color var(--motion-fast) var(--ease-nx),color var(--motion-fast) var(--ease-nx)}
.ctrl button:focus-visible,.ctrl select:focus-visible{outline:none;box-shadow:var(--nx-focus-ring)}
.pill{border-radius:var(--r-pill)}
.chip{border-radius:5px}

/* KPI tiles: one box per tile — the inner label and value are not boxes */
.kpi{gap:var(--sp-2)}
.kpi > div{border-radius:12px;background:var(--surface-2);padding:var(--sp-3) var(--sp-4)}
.kpi > div > div,.kpi > div > div:hover{background:none;border:0;padding:0;border-radius:0;box-shadow:none}
.kpi .k{color:var(--ink-4);font-weight:700;letter-spacing:.08em}
.kpi .v{font-size:var(--fs-lg);font-weight:700}

/* tables */
th{color:var(--ink-4);background:transparent}
tr:hover td{background:color-mix(in srgb,var(--nx-blue) 4%,transparent)}
.tablewrap{border-radius:var(--r-md)}

/* --------------------------------------------- instrument bar and tabs */
.ctxbar{top:calc(var(--nx-shell-topbar) + 8px);border-radius:var(--r-lg);border-color:var(--line);
  box-shadow:var(--shadow-md)}
.ctxbar .row{background:var(--surface)}
.ctxbar .nm{font-family:var(--font-display);font-weight:750}
.ctxbar .tk{border-radius:6px}
/* the score chip is neutral brand, whatever the value: a score is not a verdict */
.ctxbar .sc{color:var(--nx-teal-ink)!important;border-color:color-mix(in srgb,var(--nx-teal) 45%,transparent);
  background:color-mix(in srgb,var(--nx-teal) 8%,transparent)}
.tabs{border-top:1px solid var(--line);background:var(--surface);padding:0 var(--sp-3)}
.tabs button{font-size:var(--fs-sm);font-weight:650;letter-spacing:0;text-transform:none;
  padding:13px var(--sp-4) 11px;border-bottom-width:2px}
.tabs button + button:before{content:none}
.tabs button[aria-selected="true"]{background:transparent;border-bottom-color:var(--nx-blue)}
[data-theme="dark"] .tabs button[aria-selected="true"]{color:#fff;border-bottom-color:var(--nx-cyan)}
/* at 700px and below the bar scrolls with the page (position:relative); a sticky
   offset left on it would push it down over the first card of every tab */
@media(max-width:700px){.ctxbar{top:auto}}
.tabpanel{animation:none}

/* ----------------------------------------------------- security header */
.hdr{border-radius:var(--r-lg);align-items:center;gap:var(--sp-5);padding:var(--sp-5) var(--sp-6)}
.hdr .name{font-family:var(--font-display);font-size:var(--fs-h1);font-weight:780;letter-spacing:-.03em}
/* a long name (most fund names) wraps inside its own block rather than pushing
   the price and the score ring onto a line of their own */
.hdr > div:first-child{flex:1 1 320px;min-width:0}
.hdr .meta{font-size:var(--fs-sm)}
.hdr .meta .mkt{font-weight:700;color:var(--ink-2)}
.hdr .meta .tkr{font-family:var(--font-mono);color:var(--ink-2)}
.hdr .px{font-size:var(--fs-2xl);font-weight:700}
.hdr .px small{display:flex;flex-direction:column;align-items:flex-end;gap:2px}
/* ScoreRing in the header — .scorebadge keeps its meaning and selectors */
.scorebadge.has-ring{display:flex;align-items:center;gap:var(--sp-3);text-align:left;
  border-left:1px solid var(--line);padding-left:var(--sp-5);min-width:0}
.scorebadge.has-ring .nx-ring{--size:84px}
.scorebadge.has-ring .nx-ring .v{font-size:24px}
.scorebadge.has-ring .o{margin:0}
.scorebadge.has-ring .b{color:var(--ink-3)!important;margin-top:4px}
.scorebadge .lbl{font-family:var(--font-display);font-weight:700;font-size:var(--fs-sm);color:var(--ink)}
.scorebadge .why{font-size:var(--fs-2xs);color:var(--ink-4);margin-top:2px;max-width:18ch;line-height:1.35}
.scorebadge.unscored .nx-ring .nx-ring__val{display:none}
.scorebadge.unscored .nx-ring .nx-ring__track{stroke-dasharray:2 2.2}
@media(max-width:820px){
  .scorebadge.has-ring{border-left:0;padding-left:0;border-top:1px solid var(--line);padding-top:var(--sp-3);width:100%}
  .hdr .px small{align-items:flex-start}
}

/* ------------------------------------------------- score components */
.subscore .nm{font-weight:650;color:var(--ink-2)}
.bar{height:7px;background:var(--surface-3)}
.subscore .bar i{background:linear-gradient(90deg,var(--nx-blue),var(--nx-teal))!important}
.subscore .sc{color:var(--ink)!important}
.subscore .fx{font-family:var(--font-mono);font-size:var(--fs-2xs)}

/* ----------------------------------------------------------- red flags
   Exactly the app's four states; N/A is grey and dashed, never PASS-like */
.flag{border-radius:12px;background:var(--surface);border-left-width:3px;padding:var(--sp-4)}
.flag.FAIL{background:color-mix(in srgb,var(--nx-negative) 5%,var(--surface))}
.flag.NA{border-left-style:dashed;border-left-color:var(--nx-nodata)}
.flag .lab{font-weight:700}
.flag .st{display:inline-flex;align-items:center;gap:5px;padding:2px 9px 2px 6px;border-radius:var(--r-pill)}
.flag .st::before{
  font-size:9px;font-weight:800;line-height:1;width:13px;height:13px;border-radius:50%;
  display:grid;place-items:center;color:var(--surface)}
.flag.PASS .st{color:var(--nx-positive-ink)!important}
.flag.PASS .st::before{content:"✓";background:var(--nx-positive)}
.flag.WARN .st{color:var(--nx-warning-ink)!important}
.flag.WARN .st::before{content:"!";background:var(--nx-warning)}
.flag.FAIL .st{color:var(--nx-negative-ink)!important}
.flag.FAIL .st::before{content:"✕";background:var(--nx-negative)}
.flag.NA .st{color:var(--nx-nodata-ink)!important;background:transparent;border:1px dashed var(--nx-nodata)}
.flag.NA .st::before{content:"–";background:var(--nx-nodata)}
.flag pre{border-radius:var(--r-md)}

/* missing values read as missing, not as a muted number */
.src.na{color:var(--nx-nodata-ink)}

/* SWOT and debate: AI prose is visibly secondary to the arithmetic */
.swot .q{border-radius:12px;border-style:dashed}
.turn{border-radius:12px}
.adjudication{border-radius:12px}

@media print{
  body > *{margin-left:0!important}
  .skip-link,.app-scrim,.app-menu,.nx-pagehead .nx-world{display:none!important}
  .nx-pagehead{border:0;padding:0;margin-bottom:4mm;background:none;box-shadow:none}
  .flag .st::before{print-color-adjust:exact;-webkit-print-color-adjust:exact}
}

/* --------------------------------------------- research overview summary
   The answer on one screen; the detailed panels follow in one column. */
.ctxbar .flag{border:0;padding:0;background:none;box-shadow:none;border-radius:0}
.tabpanel .panel{margin-bottom:var(--sp-4)}
.ov-summary{margin-bottom:var(--sp-5)}
.ov-row{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:var(--sp-4);margin-bottom:var(--sp-3)}
.ov-card{background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:var(--sp-4) var(--sp-5);box-shadow:var(--shadow-sm);min-width:0;display:flex;flex-direction:column}
[data-theme="dark"] .ov-card{background:var(--nx-surface)}
.ov-h{font-family:var(--font-display);font-weight:720;font-size:var(--fs-md);color:var(--ink);
  margin-bottom:var(--sp-3);display:flex;gap:8px;align-items:baseline;flex-wrap:wrap}
.ov-h span{font-family:var(--font-sans);font-weight:500;font-size:var(--fs-xs);color:var(--ink-4)}
.ov-scorebody{display:flex;align-items:center;gap:clamp(28px,3vw,44px)}
.ov-scorebody .nx-ring{--size:132px;--stroke:3.2px}
.ov-scorebody .nx-ring .v{font-size:36px}
.ov-subs{flex:1;min-width:0;display:flex;flex-direction:column;gap:7px}
/* the name column is sized to the longest name, so the bar takes the spare width
   rather than leaving a gap between the label and its bar */
.ov-sub{display:grid;grid-template-columns:minmax(0,9.5em) 36px minmax(48px,1fr) 34px;gap:12px;align-items:center}
.ov-sub .nm{font-size:var(--fs-sm);font-weight:600;color:var(--ink-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ov-sub .wt{font-family:var(--font-mono);font-size:var(--fs-xs);color:var(--ink-4);text-align:right}
.ov-sub .bar{height:6px;min-width:0}
.ov-sub .bar i{background:linear-gradient(90deg,var(--nx-blue),var(--nx-teal))}
.ov-sub .sc{font-family:var(--font-mono);font-weight:700;font-size:var(--fs-sm);text-align:right;color:var(--ink)}
.ov-fx{margin-top:auto;padding-top:var(--sp-3);border-top:1px dashed var(--line-2);font-family:var(--font-mono);
  font-size:var(--fs-xs);color:var(--ink-3);margin-top:var(--sp-3)}
.ov-fx b{color:var(--ink)}
.ov-fx.withheld{font-family:var(--font-sans);color:var(--nx-nodata-ink)}
.ov-plot{position:relative;flex:1;min-height:180px}
.ov-plot svg{display:block;width:100%;height:100%;min-height:180px}
.ov-grid{stroke:var(--chart-grid);stroke-width:1;vector-effect:non-scaling-stroke;fill:none}
.ov-area{fill:url(#ov-area)}
.ov-ma{fill:none;stroke:var(--chart-ma-200);stroke-width:1.3;stroke-dasharray:5 4;vector-effect:non-scaling-stroke;opacity:.85}
.ov-line{fill:none;stroke:var(--chart-primary);stroke-width:2.2;vector-effect:non-scaling-stroke;stroke-linejoin:round;
  stroke-dasharray:1;stroke-dashoffset:1;animation:ov-draw var(--motion-chart) var(--ease-nx) 150ms forwards}
@keyframes ov-draw{to{stroke-dashoffset:0}}
.ov-y{position:absolute;right:0;font-family:var(--font-mono);font-size:var(--fs-2xs);color:var(--chart-axis);
  background:var(--surface);padding:0 4px;border-radius:4px}
.ov-y.hi{top:0}.ov-y.lo{bottom:0}
.ov-x{display:flex;justify-content:space-between;align-items:center;gap:var(--sp-3);margin-top:6px;
  font-family:var(--font-mono);font-size:var(--fs-2xs);color:var(--chart-axis)}
.ov-key{display:inline-flex;align-items:center;gap:6px;font-family:var(--font-sans)}
.ov-key i{width:16px;border-top:1.5px dashed var(--chart-ma-200)}
.ov-kpi{grid-template-columns:repeat(6,minmax(0,1fr));margin-bottom:var(--sp-3)}
.ov-flags{display:grid;grid-template-columns:repeat(auto-fill,minmax(250px,1fr));gap:var(--sp-3)}
.ov-flags .flag{padding:var(--sp-3) var(--sp-4)}
.ov-flags .flag .lab{font-size:var(--fs-sm)}
.ov-flags .flag .hl{font-size:var(--fs-xs);color:var(--ink-3);margin-top:4px;line-height:1.45}
.ov-more{margin-top:var(--sp-4);font-size:var(--fs-xs);color:var(--ink-4);display:flex;align-items:center;gap:var(--sp-3)}
.ov-more::after{content:"";flex:1;height:1px;background:var(--line)}
@media(max-width:1100px){.ov-row{grid-template-columns:1fr}.ov-kpi{grid-template-columns:repeat(3,minmax(0,1fr))}}
@media(max-width:560px){.ov-scorebody{flex-direction:column;align-items:stretch}.ov-scorebody .nx-ring{align-self:center}
  .ov-kpi{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media(prefers-reduced-motion:reduce){.ov-line{animation:none;stroke-dashoffset:0}}
@media print{.ov-line{animation:none;stroke-dashoffset:0}.ov-summary{break-inside:avoid}}

/* ------------------------------------------ technicals + strategy tester */
/* Posture: three independent axes, never blended into one verdict */
.posture{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--sp-3);margin-bottom:var(--sp-3)}
.posture .pcell{border:1px solid var(--line);border-radius:12px;padding:var(--sp-3) var(--sp-4);
  background:var(--surface-2);position:relative;overflow:hidden}
.posture .pcell::before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--nx-blue)}
.posture .pcell:nth-child(2)::before{background:var(--nx-cyan)}
.posture .pcell:nth-child(3)::before{background:var(--nx-teal)}
.posture .k{font-size:var(--fs-2xs);font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-4)}
.posture .v{font-family:var(--font-display);font-size:var(--fs-lg);font-weight:750;color:var(--ink);
  margin-top:2px;text-transform:capitalize}
.posture .s{font-size:var(--fs-xs);color:var(--ink-3);font-family:var(--font-mono)}
@media(max-width:700px){.posture{grid-template-columns:1fr}}

.tag-lvl{display:inline-block;font-size:9px;font-weight:750;letter-spacing:.07em;padding:1px 7px;
  border-radius:var(--r-pill);border:1px solid}
.tag-lvl.support{color:var(--nx-positive-ink);border-color:var(--chart-support-line);background:var(--chart-support-fill)}
.tag-lvl.resistance{color:var(--nx-negative-ink);border-color:var(--chart-resistance-line);background:var(--chart-resistance-fill)}
.ma-key{display:inline-block;width:8px;height:8px;border-radius:2px;margin-right:5px;vertical-align:middle}
.ma-key.ma20{background:var(--chart-ma-20)} .ma-key.ma50{background:var(--chart-ma-50)}
.ma-key.ma100{background:var(--chart-ma-100)} .ma-key.ma200{background:var(--chart-ma-200)}

/* a neutral evidence statement: same look whether the result was good or bad */
.banner.evidence{background:var(--surface-2);color:var(--ink-2);border:1px solid var(--line-2);
  border-left:3px solid var(--nx-blue)}
.b-edge{font-weight:750;color:var(--ink)}
.b-edge::after{content:" ✓";font-size:.85em;color:var(--ink-3)}

.st-grid{display:grid;grid-template-columns:minmax(0,1fr) 300px;gap:var(--sp-5);margin-top:var(--sp-4);align-items:start}
.st-main{min-width:0}
.st-side{border:1px solid var(--line);border-radius:var(--r-lg);padding:var(--sp-4);background:var(--surface-2);
  position:sticky;top:calc(var(--nx-shell-topbar) + 128px)}
.st-stats{margin:0;display:flex;flex-direction:column}
.st-stat{display:grid;grid-template-columns:1fr auto;column-gap:var(--sp-3);padding:8px 0;border-bottom:1px solid var(--line)}
.st-stat:last-child{border-bottom:0}
.st-stat dt{font-size:var(--fs-xs);color:var(--ink-3);font-weight:600}
.st-stat dd{margin:0;text-align:right;font-family:var(--font-mono);font-variant-numeric:tabular-nums;
  font-weight:700;color:var(--ink);font-size:var(--fs-sm)}
.st-stat dd.src{grid-column:1 / -1;text-align:left;font-weight:400;font-size:var(--fs-2xs);color:var(--ink-4);
  font-family:var(--font-sans)}
@media(max-width:1200px){.st-grid{grid-template-columns:1fr}.st-side{position:static}}
@media print{.st-side{position:static}}

/* ------------------------------------------------------- MarketSelector */
.nx-mktsel{display:inline-flex;flex-wrap:wrap;gap:2px;padding:3px;border:1px solid var(--line-2);border-radius:12px;
  background:var(--surface-2)}
.nx-mktsel button{appearance:none;border:0;background:transparent;color:var(--ink-3);cursor:pointer;
  font:600 var(--fs-xs)/1 var(--font-sans);padding:8px 12px;border-radius:9px;white-space:nowrap;
  transition:background-color var(--motion-fast) var(--ease-nx),color var(--motion-fast) var(--ease-nx)}
.nx-mktsel button:hover{color:var(--ink)}
.nx-mktsel button[aria-pressed="true"]{background:var(--surface);color:var(--accent);box-shadow:var(--shadow-sm)}
[data-theme="dark"] .nx-mktsel button[aria-pressed="true"]{background:var(--nx-surface-elevated);color:#fff;
  box-shadow:inset 0 -2px 0 var(--nx-cyan)}
.nx-mktsel button:focus-visible{outline:none;box-shadow:var(--nx-focus-ring)}
/* a selected market lights its node even on the faint app-variant map */
.nx-pagehead .nx-world.has-selection .nx-world__node.is-selected{opacity:1}
.nx-pagehead .nx-world.has-selection .nx-world__node.is-selected circle.ring{r:13}

/* ---------------------------------------------------- screening funnel */
.qs-track{border-radius:6px;overflow:hidden}
.qs-track i{background:linear-gradient(90deg,var(--nx-blue),var(--nx-teal))}
.qs-track i.gone{background:var(--nx-negative);opacity:.28}
.qs-track i.nodata{position:absolute;top:0;bottom:0;opacity:1;
  background:repeating-linear-gradient(135deg,var(--nx-nodata) 0 2px,transparent 2px 5px)}
.qs-step .cnt small.f{color:var(--nx-negative-ink)}
.qs-legend{display:flex;gap:var(--sp-4);margin-top:var(--sp-2);font-size:var(--fs-xs);color:var(--ink-3)}
.qs-legend span{display:inline-flex;align-items:center;gap:6px}
.qs-legend span::before{content:"";width:14px;height:8px;border-radius:2px}
.qs-legend .k-pass::before{background:linear-gradient(90deg,var(--nx-blue),var(--nx-teal))}
.qs-legend .k-fail::before{background:var(--nx-negative);opacity:.4}
.qs-legend .k-nd::before{background:repeating-linear-gradient(135deg,var(--nx-nodata) 0 2px,transparent 2px 5px);
  outline:1px solid var(--nx-nodata)}
@keyframes qs-grow{from{transform:scaleX(0)}to{transform:none}}
.nx-first .qs-track i{transform-origin:left center;animation:qs-grow 650ms var(--ease-nx) both}
.qs-f{border-radius:12px}
.qs-mkt{border-radius:var(--r-pill)}
.pick{border-radius:12px}
@media(prefers-reduced-motion:reduce){.nx-first .qs-track i{animation:none}}
@media print{.qs-track i.nodata{print-color-adjust:exact;-webkit-print-color-adjust:exact}
  .qs-legend span::before{print-color-adjust:exact;-webkit-print-color-adjust:exact}}

/* ---------------------------------------------------- portfolio analytics */
.nx-donut{display:flex;align-items:center;gap:var(--sp-4);margin:var(--sp-2) 0 var(--sp-4)}
.nx-donut svg{width:120px;height:120px;flex:none}
.nx-donut ul{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:5px;min-width:0;flex:1}
.nx-donut li{display:grid;grid-template-columns:10px 1fr auto;gap:8px;align-items:center;font-size:var(--fs-xs);color:var(--ink-2)}
.nx-donut li i{width:10px;height:10px;border-radius:3px}
.nx-donut li span{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.nx-donut li b{font-weight:700;color:var(--ink)}
@media print{.nx-donut circle,.nx-donut li i{print-color-adjust:exact;-webkit-print-color-adjust:exact}}
.mini{height:7px;border-radius:var(--r-pill)}
.allocbar{border-radius:10px;overflow:hidden}
.allocbar i.LOW{background:var(--nx-positive)}
.allocbar i.MEDIUM{background:var(--nx-warning)}
.allocbar i.HIGH{background:var(--nx-negative)}
.allocbar i.UNSCORED{background:repeating-linear-gradient(135deg,var(--nx-nodata) 0 2px,transparent 2px 5px)}
/* the headline answers come first and read as stat cards */
.panel > .kpi:first-of-type > div .v{font-size:var(--fs-xl)}
.scorebadge.has-ring .v{color:var(--ink)!important}

/* --------------------------------------------- funds: look-through chain */
.lt-chain{display:grid;grid-template-columns:minmax(0,1fr) 28px minmax(0,1fr) 28px minmax(0,1fr);
  align-items:stretch;margin:var(--sp-2) 0 var(--sp-3)}
.lt-node{border:1px solid var(--line);border-radius:12px;padding:var(--sp-3) var(--sp-4);background:var(--surface-2);
  display:flex;flex-direction:column;gap:2px;min-width:0}
.lt-node:last-child{border-color:color-mix(in srgb,var(--nx-teal) 45%,transparent);
  background:color-mix(in srgb,var(--nx-teal) 6%,var(--surface))}
.lt-node .k{font-size:var(--fs-2xs);font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-4)}
.lt-node b{font-family:var(--font-display);font-size:var(--fs-base);color:var(--ink);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.lt-arrow{position:relative}
.lt-arrow::before{content:"";position:absolute;left:4px;right:6px;top:50%;height:1px;background:var(--line-3)}
.lt-arrow::after{content:"";position:absolute;right:4px;top:50%;width:7px;height:7px;
  border-top:1px solid var(--line-3);border-right:1px solid var(--line-3);transform:translateY(-50%) rotate(45deg)}
.lt-cover{display:flex;height:9px;border-radius:var(--r-pill);overflow:hidden;background:var(--surface-3)}
.lt-cover i{display:block;height:100%}
.lt-cover i.a{background:linear-gradient(90deg,var(--nx-blue),var(--nx-teal))}
.lt-cover i.u,.lt-cover i.n{background:repeating-linear-gradient(135deg,var(--nx-nodata) 0 2px,transparent 2px 5px)}
.lt-cover i.n{opacity:.55}
.lt-key{display:flex;gap:var(--sp-4);font-size:var(--fs-xs);color:var(--ink-3);margin:6px 0 var(--sp-4)}
.lt-key span::before{content:"";display:inline-block;width:12px;height:7px;border-radius:2px;margin-right:6px;vertical-align:middle}
.lt-key .a::before{background:linear-gradient(90deg,var(--nx-blue),var(--nx-teal))}
.lt-key .u::before,.lt-key .n::before{background:repeating-linear-gradient(135deg,var(--nx-nodata) 0 2px,transparent 2px 5px);
  outline:1px solid var(--nx-nodata)}
.lt-score{color:var(--ink)}
@media(max-width:820px){.lt-chain{grid-template-columns:1fr;row-gap:6px}.lt-arrow{height:16px}
  .lt-arrow::before{left:50%;right:auto;top:0;bottom:4px;width:1px;height:auto}
  .lt-arrow::after{left:50%;right:auto;top:auto;bottom:2px;transform:translateX(-50%) rotate(135deg)}}
@media print{.lt-cover i,.lt-key span::before{print-color-adjust:exact;-webkit-print-color-adjust:exact}}
/* a missing value's reason inside a tile is an explanation, not a figure */
.kpi .v .src,.kpi .v .src.na{display:block;font-family:var(--font-sans);font-size:var(--fs-2xs);
  font-weight:450;line-height:1.4;letter-spacing:0;text-align:left;max-width:none;color:var(--nx-nodata-ink)}

/* ---------------------------------------------------------- watchlist */
.wl td{vertical-align:middle}
.wl .mktcell{white-space:nowrap;font-size:var(--fs-xs);font-weight:700;color:var(--ink-3)}
.wl .scorecell{color:var(--ink)}
.wl .flagcell span{display:inline-flex;align-items:center;gap:3px}
.wl .flagcell span.down::before{content:"✕";font-size:.8em}
.wl .flagcell span.c-warn::before{content:"!";font-size:.85em}
.wl .flagcell span.up::before{content:"✓";font-size:.8em}
/* row actions appear on hover or keyboard focus; always shown on touch */
.wl-acts{white-space:nowrap}
.wl-acts .btn{padding:5px 10px;font-size:var(--fs-xs)}
.wl-acts .js-rm{appearance:none;border:1px solid var(--line-2);background:var(--surface);color:var(--ink-3);
  border-radius:8px;width:30px;height:30px;cursor:pointer;margin-left:4px}
.wl-acts .js-rm:hover{color:var(--nx-negative-ink);border-color:var(--nx-negative)}
@media(hover:hover) and (pointer:fine){
  .wl tr .wl-acts > *{opacity:0;transition:opacity var(--motion-fast) var(--ease-nx)}
  .wl tr:hover .wl-acts > *,.wl tr:focus-within .wl-acts > *{opacity:1}
}

/* ---------------------------------------------------------- market pulse */
.nx-pulse-map{position:relative;overflow:hidden;isolation:isolate;margin:0 0 var(--sp-5);
  height:clamp(260px,26vw,380px);border:1px solid var(--line);border-radius:var(--r-xl);
  background:radial-gradient(700px 300px at 70% 30%,color-mix(in srgb,var(--nx-cyan) 9%,transparent),transparent 70%),var(--surface)}
.nx-pulse-map .nx-world svg{top:58%}
.nx-pulse-map .nx-world[data-interactive]{pointer-events:none}
.nx-pulse-map .nx-world[data-interactive] .nx-world__node{pointer-events:auto;cursor:pointer;outline:none}
.nx-pulse-map .nx-world__node:focus-visible circle.ring,.nx-pulse-map .nx-world__node:hover circle.ring{
  fill:color-mix(in srgb,var(--nx-cyan) 30%,transparent)}
.nx-pulse-map .nx-world__node text{font-size:12px}
.nx-pulse-map__ui{position:absolute;left:var(--sp-5);bottom:var(--sp-5);z-index:1;display:flex;flex-direction:column;
  gap:var(--sp-2);max-width:min(520px,calc(100% - 2 * var(--sp-5)))}
.nx-pulse-map__ui .src{margin:0;background:var(--nx-surface-glass);padding:6px 10px;border-radius:8px}
.nx-mktsel button:disabled{opacity:.45;cursor:not-allowed}

/* ------------------------------------------------------------------ demo */
.scenario{border-radius:var(--r-lg);padding:var(--sp-4) var(--sp-5)}
.scenario .t{font-family:var(--font-display);font-weight:720}
.scenario.active{box-shadow:inset 3px 0 0 var(--nx-blue)}
@media(max-width:620px){.searchbox button{padding:12px var(--sp-5);min-height:46px}}

/* a finished run folds its log to a strip; the report is what matters now */
.console.is-done:not(.is-open){max-height:58px;overflow:hidden;position:relative;
  -webkit-mask-image:linear-gradient(#000 40%,transparent);mask-image:linear-gradient(#000 40%,transparent)}
.console-toggle{appearance:none;border:1px solid var(--line-2);background:var(--surface);color:var(--ink-3);
  border-radius:var(--r-pill);padding:4px 12px;font:600 var(--fs-xs)/1.4 var(--font-sans);cursor:pointer;
  margin:0 0 var(--sp-2)}
.console-toggle:hover{color:var(--ink);border-color:var(--line-3)}
.console-toggle:focus-visible{outline:none;box-shadow:var(--nx-focus-ring)}
.console-toggle[hidden]{display:none}
.hdr{scroll-margin-top:calc(var(--nx-shell-topbar) + 16px)}
.ov-score{gap:0}
.ov-chart{gap:0}

/* ==========================================================================
   Accounts — sign-in pages, user menu, account & security, admin
   Same tokens, same card geometry, same world network: not a separate
   product bolted on.
   ========================================================================== */
.auth-page{min-height:100vh;display:flex;flex-direction:column;align-items:center;position:relative;
  overflow-x:clip;isolation:isolate;padding:0 16px var(--sp-5);
  background:radial-gradient(900px 480px at 50% -5%, color-mix(in srgb,var(--nx-cyan) 13%,transparent), transparent 70%),
    var(--nx-bg-gradient)}
.auth-page > .nx-world{position:fixed}
.auth-page > .nx-world svg{top:34%;width:max(110%,1200px)}
.auth-top{position:relative;z-index:1;width:100%;max-width:1100px;display:flex;align-items:center;
  justify-content:space-between;padding:var(--sp-4) 0}
.auth-card{position:relative;z-index:1;width:100%;max-width:440px;margin:clamp(12px,6vh,72px) auto var(--sp-4);
  background:var(--nx-surface-glass);border:1px solid var(--line);border-radius:var(--r-xl);
  box-shadow:var(--shadow-lg);padding:clamp(22px,4vw,36px);
  backdrop-filter:blur(14px) saturate(160%);-webkit-backdrop-filter:blur(14px) saturate(160%)}
[data-theme="dark"] .auth-card{border-color:var(--nx-border-strong)}
.auth-card h1{font-family:var(--font-display);font-size:clamp(22px,2.4vw,28px);font-weight:780;
  letter-spacing:-.03em;margin:0 0 6px;color:var(--ink)}
.auth-lead{color:var(--ink-3);font-size:var(--fs-sm);margin:0 0 var(--sp-5);line-height:1.6}
.auth-alt,.auth-switch,.auth-fine{font-size:var(--fs-sm);color:var(--ink-3);margin:var(--sp-4) 0 0;text-align:center}
.auth-switch{padding-top:var(--sp-4);border-top:1px solid var(--line)}
.auth-fine{font-size:var(--fs-xs);color:var(--ink-4);text-align:left}
.auth-foot{position:relative;z-index:1;font-size:var(--fs-xs);color:var(--ink-4);margin-top:auto;text-align:center}
.field{margin-bottom:var(--sp-4)}
.field label{display:block;font-size:var(--fs-sm);font-weight:650;color:var(--ink-2);margin-bottom:6px}
.field input{width:100%;font:500 var(--fs-base)/1.4 var(--font-sans);color:var(--ink);background:var(--surface);
  border:1px solid var(--line-2);border-radius:var(--r-md);padding:12px 14px;
  transition:border-color var(--motion-fast) var(--ease-nx),box-shadow var(--motion-fast) var(--ease-nx)}
.field input:focus{outline:none;border-color:var(--nx-blue);box-shadow:var(--nx-focus-ring)}
.field input[aria-invalid="true"]{border-color:var(--nx-negative)}
.field-err{margin:6px 0 0;font-size:var(--fs-xs);color:var(--nx-negative-ink);min-height:0}
.field-err:empty{display:none}
.field-help{margin:6px 0 0;font-size:var(--fs-xs);color:var(--ink-4)}
.pw-wrap{position:relative}
.pw-wrap input{padding-right:48px}
.pw-toggle{position:absolute;right:6px;top:50%;transform:translateY(-50%);width:36px;height:36px;
  display:grid;place-items:center;border:0;background:transparent;color:var(--ink-4);border-radius:8px;cursor:pointer}
.pw-toggle svg{width:18px;height:18px}
.pw-toggle[aria-pressed="true"]{color:var(--accent)}
.pw-toggle:focus-visible{outline:none;box-shadow:var(--nx-focus-ring)}
.pw-guide{display:flex;align-items:center;gap:10px;margin-top:8px;font-size:var(--fs-xs);color:var(--ink-3)}
.pw-meter{flex:0 0 80px;height:5px;border-radius:var(--r-pill);background:var(--surface-3);overflow:hidden}
.pw-meter i{display:block;height:100%;width:0;background:var(--nx-nodata);transition:width var(--motion-normal) var(--ease-nx)}
.pw-guide[data-level="ok"] .pw-meter i{background:linear-gradient(90deg,var(--nx-blue),var(--nx-teal))}
.pw-guide[data-level="strong"] .pw-meter i{background:var(--nx-positive)}
/* one real input dressed as six cells: typing, paste, autofill and screen
   readers all see a single field */
.field input.otp{font-family:var(--font-mono);font-size:26px;font-weight:700;letter-spacing:.62em;
  text-align:center;padding:12px 0 12px .62em;caret-color:var(--nx-blue)}
.form-msg{border-radius:var(--r-md);padding:10px 12px;font-size:var(--fs-sm);margin:0 0 var(--sp-4);
  background:var(--surface-2);border:1px solid var(--line-2);color:var(--ink-2)}
.form-msg.err{background:var(--nx-negative-soft);border-color:color-mix(in srgb,var(--nx-negative) 40%,transparent);color:var(--nx-negative-ink)}
.form-msg.warn{background:var(--nx-warning-soft);border-color:color-mix(in srgb,var(--nx-warning) 45%,transparent);color:var(--nx-warning-ink)}
.form-msg.ok{background:var(--nx-positive-soft);border-color:color-mix(in srgb,var(--nx-positive) 40%,transparent);color:var(--nx-positive-ink)}
.form-msg a{font-weight:700;color:inherit;text-decoration:underline}
.btn-block{width:100%;justify-content:center;padding:13px var(--sp-4);font-size:var(--fs-base)}
.btn[disabled]{opacity:.6;cursor:progress}
.linkbtn{appearance:none;border:0;background:none;color:var(--accent);font:inherit;font-weight:650;cursor:pointer;padding:0}
.linkbtn:disabled{color:var(--ink-4);cursor:default}
.linkbtn:focus-visible{outline:none;box-shadow:var(--nx-focus-ring);border-radius:4px}
.countdown{color:var(--ink-4);font-size:var(--fs-xs);margin-left:6px}

/* user menu (app top bar and site header) */
.nx-user{position:relative;flex:none}
.nx-user:empty{display:none}
.nx-user__btn{appearance:none;border:1px solid var(--line-2);background:var(--surface);border-radius:var(--r-pill);
  padding:2px;cursor:pointer}
.nx-user__btn:focus-visible{outline:none;box-shadow:var(--nx-focus-ring)}
.nx-avatar{display:grid;place-items:center;width:32px;height:32px;border-radius:50%;
  font:700 12px/1 var(--font-sans);letter-spacing:.02em;color:#fff;background:var(--nx-primary-bg)}
.nx-user__menu{position:absolute;right:0;top:calc(100% + 8px);z-index:80;min-width:230px;
  background:var(--surface);border:1px solid var(--line-2);border-radius:12px;box-shadow:var(--shadow-lg);
  padding:6px;display:flex;flex-direction:column}
.nx-user__menu[hidden]{display:none}
.nx-user__who{padding:8px 10px 10px;border-bottom:1px solid var(--line);margin-bottom:4px;display:flex;flex-direction:column}
.nx-user__who b{font-size:var(--fs-sm);color:var(--ink);overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:260px}
.nx-user__who span{font-size:var(--fs-2xs);color:var(--ink-4);text-transform:uppercase;letter-spacing:.08em;font-weight:700}
.nx-user__menu [role=menuitem]{appearance:none;border:0;background:none;text-align:left;font:550 var(--fs-sm)/1.3 var(--font-sans);
  color:var(--ink-2);padding:9px 10px;border-radius:8px;cursor:pointer;text-decoration:none}
.nx-user__menu [role=menuitem]:hover,.nx-user__menu [role=menuitem]:focus-visible{background:var(--surface-3);color:var(--ink);outline:none}
.site-signin[hidden]{display:none}

/* account & security */
.acct-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--sp-4);align-items:start}
.acct-wide{grid-column:1 / -1}
.acct-grid .panel{margin:0}
.acct-dl{margin:var(--sp-3) 0 0;display:grid;gap:10px}
.acct-dl > div{display:grid;grid-template-columns:130px 1fr;gap:var(--sp-3);align-items:center}
.acct-dl dt{font-size:var(--fs-xs);color:var(--ink-4);text-transform:uppercase;letter-spacing:.08em;font-weight:700}
.acct-dl dd{margin:0;color:var(--ink);font-weight:600;overflow-wrap:anywhere}
.acct-grid form{margin-top:var(--sp-3);max-width:520px}
.ctrl button.danger-soft{color:var(--nx-negative-ink);border-color:color-mix(in srgb,var(--nx-negative) 40%,transparent)}
.acct-delete{border-top:1px dashed var(--line-2);padding-top:var(--sp-3)}
.btn.danger{background:var(--nx-negative-soft);color:var(--nx-negative-ink);border:1px solid var(--nx-negative)}
@media(max-width:900px){.acct-grid{grid-template-columns:minmax(0,1fr)}}

/* admin */
.admin-tabs{border:1px solid var(--line);border-radius:var(--r-lg);margin-bottom:var(--sp-4);background:var(--surface)}
.admin-panel[hidden]{display:none}
.admin-acts{white-space:nowrap}
.admin-acts .btn{padding:5px 10px;font-size:var(--fs-xs);margin-left:4px}

/* Role-gated controls (see api.js markRole). Hidden until the role is known,
   so a regular user never sees an admin button flash in. */
html:not(.nx-is-admin) [data-admin-only],
html.nx-role-pending [data-member-only],
html.nx-is-admin [data-member-only] { display: none !important; }

/* ==========================================================================
   Depth layer (motion3d.js, globe3d.js) — DESIGN_SYSTEM.md §Depth
   Decorative motion on top of v3: nothing here changes a layout, a colour
   token or a number. html.nx-depth is set only when motion is allowed, so
   every rule below is inert under prefers-reduced-motion.
   ========================================================================== */
:root{
  --globe-dot:#2D7FC8; --globe-node:#1477E8; --globe-arc:#1A8BD6;
  --globe-pulse:#16C7E8; --globe-rim:rgba(20,119,232,.10); --globe-label:#0A2242;
  --globe-body:rgba(20,119,232,.035);
  --depth-glare:rgba(255,255,255,.55); --depth-spot:rgba(20,119,232,.07);
  --depth-ease:cubic-bezier(.2,.8,.2,1);
  /* set per element at runtime by motion3d.js; these are the resting values */
  --rx:0deg; --ry:0deg; --gx:50%; --gy:50%; --mx:-999px; --my:-999px;
  --tx:0px; --ty:0px; --rd:0ms; --d:0ms; --fd:0ms;
}
[data-theme="dark"]{
  --globe-dot:#5FB4F0; --globe-node:#3F98FF; --globe-arc:#26D5F4;
  --globe-pulse:#7FE8FA; --globe-rim:rgba(38,213,244,.16); --globe-label:#D2E0EC;
  --globe-body:rgba(63,152,255,.10);
  --depth-glare:rgba(160,220,255,.16); --depth-spot:rgba(38,213,244,.08);
}

/* ---- the globe ---- */
.nx-globe{position:relative;aspect-ratio:1;cursor:grab;touch-action:pan-y;
  opacity:0;transition:opacity 900ms var(--depth-ease)}
.nx-globe.is-ready{opacity:1}
.nx-globe.is-dragging{cursor:grabbing}
.nx-globe canvas{display:block;width:100%;height:100%}

/* ---- tilt: the element leans towards the pointer, a glare follows it ---- */
html.nx-depth .nx-3d{transform-style:preserve-3d;will-change:transform;
  transform:perspective(1100px) rotateX(var(--rx,0deg)) rotateY(var(--ry,0deg));
  transition:transform 600ms var(--depth-ease),box-shadow 600ms var(--depth-ease)}
html.nx-depth .nx-3d.is-tilting{transition:transform 120ms linear,box-shadow 300ms var(--depth-ease);
  box-shadow:0 30px 60px -20px rgba(10,34,66,.28),0 12px 24px -12px rgba(10,34,66,.16)}
html.nx-depth .nx-3d{position:relative}
html.nx-depth .nx-3d::after{content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;
  background:radial-gradient(420px circle at var(--gx,50%) var(--gy,50%),var(--depth-glare),transparent 45%);
  opacity:0;transition:opacity 400ms var(--depth-ease);mix-blend-mode:soft-light;z-index:3}
html.nx-depth .nx-3d.is-tilting::after{opacity:1}

/* ---- spotlight: a soft light under the pointer; the surface never moves ---- */
html.nx-depth .nx-spot{position:relative}
html.nx-depth .nx-spot::before{content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;
  background:radial-gradient(520px circle at var(--mx,-999px) var(--my,-999px),var(--depth-spot),transparent 42%);
  opacity:0;transition:opacity 350ms var(--depth-ease);z-index:0}
html.nx-depth .nx-spot.nx-lit::before{opacity:1}
html.nx-depth .nx-spot > *{position:relative;z-index:1}
html.nx-depth .nx-spot.nx-lit{border-color:color-mix(in srgb,var(--nx-blue) 28%,var(--line))}

/* ---- reveal3d: rises into place in perspective, once ---- */
html.nx-depth .nx-reveal3d{opacity:0;transform:perspective(1200px) translateY(28px) rotateX(9deg) scale(.985);
  transform-origin:50% 0;filter:blur(3px);
  transition:opacity 700ms var(--depth-ease) var(--rd,0ms),transform 800ms var(--depth-ease) var(--rd,0ms),
    filter 700ms var(--depth-ease) var(--rd,0ms)}
html.nx-depth .nx-reveal3d.is-in{opacity:1;transform:none;filter:none}

/* ---- magnetic primary buttons ---- */
html.nx-depth .nx-magnet{transform:translate3d(var(--tx,0px),var(--ty,0px),0);
  transition:transform 300ms var(--depth-ease),box-shadow 300ms var(--depth-ease)}
html.nx-depth .nx-magnet:hover{box-shadow:0 10px 24px -10px color-mix(in srgb,var(--nx-blue) 60%,transparent)}
html.nx-depth .nx-magnet:active{transform:translate3d(var(--tx,0px),calc(var(--ty,0px) + 1px),0) scale(.98)}

/* ---- report tabs swing in from the side they were chosen on ---- */
html.nx-depth .tabpanel.nx-tab-enter{animation:nx-swing 520ms var(--depth-ease) both;transform-origin:50% 0}
@keyframes nx-swing{from{opacity:0;transform:perspective(1400px) rotateX(6deg) translateY(14px)}
  to{opacity:1;transform:none}}

@media (prefers-reduced-motion: reduce){
  .nx-globe{transition:none;opacity:1}
}
/* paper never waits for a scroll: everything visible, flat, unlit */
@media print{
  .nx-reveal3d,.nx-3d,.nx-magnet,.tabpanel.nx-tab-enter{opacity:1!important;transform:none!important;filter:none!important;animation:none!important}
  .nx-3d::after,.nx-spot::before{display:none!important}
  .nx-globe{display:none!important}
}
/* Market Pulse: the globe rises on the right; choosing a market turns it there */
.nx-pulse-map .nx-globe{position:absolute;z-index:0;right:3%;top:-8%;
  height:132%;width:auto;aspect-ratio:1}
/* on a desktop the globe (WebGL, or the canvas one without it) is the map: the
   flat map is never shown, so nothing appears and then gives way as it loads.
   A phone, where the globe is hidden, keeps the flat map. */
@media(min-width:861px){ .nx-pulse-map > .nx-world{display:none} }
@media(max-width:860px){ .nx-pulse-map .nx-globe{display:none} }
/* WebGL globe: canvas fills the host; labels are real text placed by the projection */
.nx-globe[data-globe-gl] canvas{display:block}
.nx-glabel{position:absolute;left:0;top:0;pointer-events:none;white-space:nowrap;z-index:2;
  margin:-30px 0 0 12px;padding:3px 9px;border-radius:999px;font:600 11.5px/1.3 var(--font-sans);
  letter-spacing:.01em;color:var(--globe-label);background:color-mix(in srgb,var(--surface) 78%,transparent);
  border:1px solid color-mix(in srgb,var(--globe-node) 30%,transparent);
  backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
  transition:opacity 200ms linear,background-color 300ms ease,color 300ms ease;will-change:transform}
/* the WebGL globe places each label itself, clear of the others (globe-gl.js) */
.nx-glabel.is-placed{margin:0}
/* the selected market reads the same as the rest, marked by its border and weight */
.nx-glabel.is-focus{color:var(--globe-label);border-color:var(--globe-node);font-weight:700;
  box-shadow:0 0 0 1px var(--globe-node)}
:root{--globe-ocean:#EAF3FB;--globe-rim-gl:#9CC8EE;--globe-glow:#5AA8F0;--globe-dot-hi:#1466C7}
[data-theme="dark"]{--globe-ocean:#06203B;--globe-rim-gl:#2AA9E0;--globe-glow:#1FA6E6;--globe-dot-hi:#9FE3FF}

/* ==========================================================================
   One 3D language across every page (nx-scenes.js + nx-gl.js)
   ========================================================================== */
/* the signature: a live globe in every page header */
.has-headglobe{position:relative}
.nx-headglobe{position:absolute;z-index:0;right:clamp(8px,2vw,32px);top:50%;width:clamp(150px,15vw,230px);
  height:auto;aspect-ratio:1;transform:translateY(-50%);pointer-events:auto}
.page-hero .nx-headglobe{width:clamp(200px,22vw,340px);right:clamp(8px,4vw,64px)}
.has-headglobe > :not(.nx-headglobe):not(.nx-world){position:relative;z-index:1}
.nx-pagehead.has-headglobe .nx-pagehead__main{max-width:calc(100% - clamp(150px,15vw,230px))}
.nx-pagehead.has-headglobe .nx-pagehead__aside{margin-right:clamp(150px,16vw,250px)}
html.nx-gl .has-headglobe > .nx-world{opacity:.45}
@media(max-width:760px){ .nx-headglobe{display:none} .nx-pagehead.has-headglobe .nx-pagehead__aside{margin-right:0}
  .nx-pagehead.has-headglobe .nx-pagehead__main{max-width:none} }

/* every scene canvas */
.nx-scene{position:relative}
.nx-gl-canvas{display:block;touch-action:pan-y}
.nx-scene--score{position:absolute;inset:-14px;z-index:0;pointer-events:none;contain:strict}
.nx-scene--score .nx-gl-canvas{position:absolute;left:0;top:0}
.nx-scene.is-lost{display:none}
.ov-score.has-scene .ov-scorebody{position:relative}
.ov-score.has-scene .ov-scorebody > :not(.nx-scene){position:relative;z-index:1}
.ov-score.has-scene .nx-ring__track{opacity:.35}

/* living report: red flags flip in, the overview line draws itself */
html.nx-depth .ov-flags .flag.nx-flip{animation:nx-flip 720ms var(--depth-ease) both;animation-delay:var(--fd,0ms);
  transform-origin:50% 50%;backface-visibility:hidden}
@keyframes nx-flip{from{opacity:0;transform:perspective(900px) rotateY(-88deg) translateZ(-40px)}
  60%{opacity:1}to{opacity:1;transform:none}}
html.nx-depth .ov-flags .flag.nx-flip .st{animation:nx-stamp 520ms var(--depth-ease) both;animation-delay:calc(var(--fd,0ms) + 420ms)}
@keyframes nx-stamp{from{transform:scale(1.8);opacity:0}to{transform:none;opacity:1}}
html.nx-depth .ov-plot.nx-draw .ov-line{stroke-dasharray:1;stroke-dashoffset:1;animation:nx-draw 1.5s var(--depth-ease) forwards}
html.nx-depth .ov-plot.nx-draw .ov-area,html.nx-depth .ov-plot.nx-draw .ov-ma{animation:nx-fade 1.2s ease .6s both}
@keyframes nx-draw{to{stroke-dashoffset:0}}
@keyframes nx-fade{from{opacity:0}to{opacity:1}}

/* ---- the command palette ---- */
.nx-pal{position:fixed;inset:0;z-index:300}
.nx-pal[hidden]{display:none}
.nx-pal__scrim{position:absolute;inset:0;background:rgba(3,14,28,.42);backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);
  opacity:0;transition:opacity 180ms ease}
.nx-pal__box{position:relative;margin:min(14vh,140px) auto 0;width:min(680px,calc(100vw - 24px));
  background:color-mix(in srgb,var(--surface) 96%,transparent);border:1px solid var(--line-2);border-radius:18px;
  box-shadow:0 40px 100px -30px rgba(3,14,28,.55),0 0 0 1px color-mix(in srgb,var(--nx-blue) 12%,transparent);
  overflow:hidden;opacity:0;transform:translateY(-10px) scale(.97);
  transition:opacity 200ms var(--depth-ease),transform 260ms var(--depth-ease)}
.nx-pal.is-open .nx-pal__scrim{opacity:1}
.nx-pal.is-open .nx-pal__box{opacity:1;transform:none}
.nx-pal__head{display:flex;align-items:center;gap:12px;padding:14px 16px;border-bottom:1px solid var(--line)}
.nx-pal__orb{width:14px;height:14px;border-radius:50%;flex:none;
  background:radial-gradient(circle at 35% 35%,#fff,var(--globe-pulse) 40%,var(--globe-node) 75%);
  box-shadow:0 0 14px var(--globe-pulse);animation:nx-orb 2.4s ease-in-out infinite}
@keyframes nx-orb{50%{box-shadow:0 0 24px var(--globe-pulse),0 0 0 6px color-mix(in srgb,var(--globe-pulse) 15%,transparent)}}
.nx-pal__in{flex:1;border:0;outline:0;background:transparent;font:500 17px/1.3 var(--font-sans);color:var(--ink)}
.nx-pal__in::placeholder{color:var(--ink-4)}
.nx-pal kbd{font:600 10.5px/1 var(--font-sans);color:var(--ink-3);background:var(--surface-2);border:1px solid var(--line);
  border-radius:6px;padding:3px 6px}
.nx-pal__list{list-style:none;margin:0;padding:6px;max-height:min(52vh,460px);overflow-y:auto}
.nx-pal__grp{padding:10px 10px 4px;font-size:10.5px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--ink-4)}
.nx-pal__it{display:flex;align-items:center;gap:12px;padding:9px 10px;border-radius:12px;cursor:pointer;
  animation:nx-palin 260ms var(--depth-ease) both;animation-delay:var(--d,0ms)}
@keyframes nx-palin{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}
.nx-pal__it[aria-selected="true"]{background:linear-gradient(90deg,color-mix(in srgb,var(--nx-blue) 12%,transparent),
  color-mix(in srgb,var(--nx-cyan) 6%,transparent));box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--nx-blue) 22%,transparent)}
.nx-pal__ic{width:30px;height:30px;border-radius:9px;display:grid;place-items:center;flex:none;background:var(--surface-2);
  border:1px solid var(--line);color:var(--accent)}
.nx-pal__ic svg{width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.nx-pal__t{flex:1;min-width:0;display:flex;flex-direction:column}
.nx-pal__t b{font-size:var(--fs-sm);font-weight:600;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.nx-pal__t small{font-size:var(--fs-xs);color:var(--ink-4);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.nx-pal__go{color:var(--ink-4);opacity:0;transition:opacity 120ms}
.nx-pal__it[aria-selected="true"] .nx-pal__go{opacity:1}
.nx-pal__empty{padding:22px;text-align:center;color:var(--ink-4)}
.nx-pal__foot{display:flex;gap:16px;align-items:center;padding:9px 16px;border-top:1px solid var(--line);
  font-size:var(--fs-xs);color:var(--ink-4)}
.nx-pal__hint{margin-left:auto}
@media (prefers-reduced-motion: reduce){ .nx-pal__box,.nx-pal__scrim{transition:none} .nx-pal__it,.nx-pal__orb{animation:none} }

/* ---- page-to-page transitions: one continuous surface, not a reload ---- */
@view-transition{navigation:auto}
.topbar,.site-header{view-transition-name:nx-bar}
.nx-headglobe,.hero-shot .nx-globe{view-transition-name:nx-globe}
.nx-pagehead h1,.page-hero h1{view-transition-name:nx-title}
::view-transition-old(root){animation:nx-vt-out 240ms cubic-bezier(.4,0,1,1) both}
::view-transition-new(root){animation:nx-vt-in 460ms cubic-bezier(.2,.8,.2,1) both}
::view-transition-group(nx-globe),::view-transition-group(nx-title){animation-duration:560ms;
  animation-timing-function:cubic-bezier(.2,.8,.2,1)}
@keyframes nx-vt-out{to{opacity:0;transform:scale(.985);filter:blur(3px)}}
@keyframes nx-vt-in{from{opacity:0;transform:translateY(14px) scale(1.01);filter:blur(4px)}}
@media (prefers-reduced-motion: reduce){
  @view-transition{navigation:none}
}
/* the header globe is exactly as tall as its header, so the sphere is never cut */
.nx-pagehead .nx-headglobe{top:6px;bottom:6px;height:auto;width:auto;aspect-ratio:1;transform:none;
  max-width:240px}
.nx-pagehead.has-headglobe .nx-pagehead__aside{margin-right:clamp(130px,13vw,250px)}

/* Fund watchlist: the name gets room to read as a name, figures stay on one
   line, and the two actions sit side by side at the same height */
.fwl td{vertical-align:middle}
.fwl th,.fwl td{padding-left:10px;padding-right:10px}
.fwl th{white-space:normal;vertical-align:bottom;line-height:1.35}
.fwl td.fwl-name{min-width:200px;max-width:320px}
.fwl td.fwl-name b{display:block;line-height:1.35}
.fwl td.num{white-space:nowrap}
.fwl td.fwl-act{white-space:nowrap;text-align:right}
.fwl .fwl-act__in{display:inline-flex;align-items:center;gap:6px}
.fwl .fwl-act__in .btn{height:36px;padding:0 14px;display:inline-flex;align-items:center;justify-content:center;margin:0}
.fwl .fwl-act__in .js-drop{width:36px;padding:0}

/* ---- phone polish (mobile audit) ---- */
.nowrap{white-space:nowrap}
@media(max-width:700px){
  /* the meta lines run as ordinary text, so a wrapped line never starts with "·" */
  .hdr .meta{display:block;line-height:1.6}
  .hdr .meta .mkt,.hdr .meta .tkr{margin-right:6px}
  /* the score is already in the bar beneath and on the overview card: a third
     copy in the header only pushes the report down */
  .hdr .scorebadge{display:none}
  /* in a table that scrolls, the first column names the row: it keeps room for
     the name, and the figures scroll beside it */
  .tablewrap :is(table.is-wide,table.is-xwide) :is(th,td):first-child:not(.num){min-width:9.5em}
  /* figure tiles: two to a row, and an odd last tile takes the row rather
     than sitting alone beside a gap */
  .kpi{grid-template-columns:repeat(2,minmax(0,1fr))}
  .kpi > :last-child:nth-child(odd){grid-column:1 / -1}
  /* a select never runs past its card, and the selects in a control row line
     up at full width rather than a ragged edge */
  .ctrl label{max-width:100%;min-width:0}
  .ctrl select{max-width:100%;min-width:0}
  .ctrl label:has(> select){flex:1 1 100%}
  .ctrl label > select{flex:1 1 auto;text-align:left}
}

/* Bull vs Bear: the closing summary */
.db-sum{margin-top:var(--sp-5);padding:var(--sp-4) var(--sp-5);border:1px solid var(--line);border-radius:var(--r-lg);
  background:var(--surface-2)}
.db-sum .k{font-size:var(--fs-2xs);font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-4);
  margin:var(--sp-4) 0 6px}
.db-sum__sides{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--sp-3)}
.db-sum__side{padding:var(--sp-3) var(--sp-4);border-radius:var(--r-md);background:var(--surface);border-left:3px solid var(--pos)}
.db-sum__side.BEAR{border-left-color:var(--neg)}
.db-sum__side .k{margin-top:0}
.db-sum__side p{margin:0;color:var(--ink-2);font-size:var(--fs-sm);line-height:1.5}
.db-sum__list{margin:0;padding-left:18px;color:var(--ink-2);font-size:var(--fs-sm);line-height:1.55}
.db-sum__list li{margin:3px 0}
.db-sum__list .tagp,.db-sum__list .tagf,.db-sum__list .tagw{margin-right:6px}
@media(max-width:560px){.db-sum__sides{grid-template-columns:minmax(0,1fr)}}

/* News sentiment: beside the score, in its own colours, never inside it */
.nx-sent{display:flex;flex-wrap:wrap;align-items:center;gap:6px 10px;margin-top:var(--sp-3);padding:8px 12px;
  border-radius:var(--r-md);background:var(--surface-2);border:1px solid var(--line);font-size:var(--fs-xs)}
.nx-sent .k{font-size:var(--fs-2xs);font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--ink-4)}
.nx-sent .v{font-family:var(--font-mono);font-size:var(--fs-sm);text-transform:capitalize}
.nx-sent--pos .v{color:var(--pos)} .nx-sent--neg .v{color:var(--neg)} .nx-sent--mix .v{color:var(--ink-2)}
.nx-sent .src{flex:1 1 220px;min-width:0}
.nx-sent--none{background:transparent;border-style:dashed}
.nx-sent__table td{vertical-align:top}
.nx-sent__bar{position:relative;display:inline-block;width:72px;height:6px;border-radius:3px;background:var(--surface-3);
  vertical-align:middle;overflow:hidden}
.nx-sent__bar::before{content:"";position:absolute;left:50%;top:-1px;bottom:-1px;width:1px;background:var(--line-2)}
.nx-sent__bar i{position:absolute;top:0;bottom:0;border-radius:3px}
.nx-sent__bar i.pos{background:var(--pos)} .nx-sent__bar i.neg{background:var(--neg)}
.nx-tone{font-family:var(--font-mono);font-weight:650}
.nx-tone.positive{color:var(--pos)} .nx-tone.negative{color:var(--neg)} .nx-tone.neutral{color:var(--ink-3)}
.nx-sentchip{font-family:var(--font-mono);font-size:var(--fs-xs);font-weight:650;padding:3px 8px;border-radius:var(--r-pill);
  border:1px solid var(--line-2);color:var(--ink-2);background:var(--surface-2);white-space:nowrap}
.nx-sentchip.pos{color:var(--pos);border-color:color-mix(in srgb,var(--pos) 40%,transparent)}
.nx-sentchip.neg{color:var(--neg);border-color:color-mix(in srgb,var(--neg) 40%,transparent)}
@media(max-width:560px){.ctxbar .nx-sentchip{order:6}}

/* Legal documents, the sign-up agreement and the acceptance prompt */
.legal__doc{max-width:820px;margin:0 auto;color:var(--ink-2);line-height:1.7;font-size:var(--fs-base)}
.section .legal__doc h2,.legal__doc h2{font-size:var(--fs-lg);line-height:1.3;max-width:none;color:var(--ink);
  margin:var(--sp-6) 0 var(--sp-2);letter-spacing:-.01em}
.legal__doc ul{padding-left:20px} .legal__doc li{margin:6px 0}
.legal__meta{font-size:var(--fs-xs);color:var(--ink-4);font-family:var(--font-mono)}
.legal__docs{display:flex;flex-wrap:wrap;gap:8px;margin-bottom:var(--sp-4)}
.legal__docs a{padding:6px 12px;border:1px solid var(--line-2);border-radius:var(--r-pill);font-size:var(--fs-sm);
  color:var(--ink-2);text-decoration:none}
.legal__docs a[aria-current="page"]{border-color:var(--nx-blue);color:var(--accent);background:color-mix(in srgb,var(--nx-blue) 7%,transparent)}
.legal__callout{padding:var(--sp-4) var(--sp-5);border-left:3px solid var(--nx-blue);background:var(--surface-2);
  border-radius:var(--r-md);margin:var(--sp-4) 0}
.legal__table{width:100%;font-size:var(--fs-sm)} .legal__table td{vertical-align:top}
.legal-accept__row{display:flex;gap:10px;align-items:flex-start;font-size:var(--fs-sm);line-height:1.5;color:var(--ink-2);
  font-weight:400;cursor:pointer}
.legal-accept__row input{margin-top:3px;flex:none;width:18px;height:18px}
.nav-legal{display:block;margin-top:4px} .nav-legal a{color:inherit}
html.nx-legal-open{overflow:hidden}
.nx-legal{position:fixed;inset:0;z-index:1000;display:grid;place-items:center;padding:16px;
  background:color-mix(in srgb,#020B17 55%,transparent);backdrop-filter:blur(4px);-webkit-backdrop-filter:blur(4px)}
.nx-legal__box{width:min(560px,100%);background:var(--surface);border:1px solid var(--line-2);border-radius:var(--r-lg);
  box-shadow:var(--shadow-lg);padding:var(--sp-5) var(--sp-6);color:var(--ink-2);line-height:1.6}
.nx-legal__box h2{margin:0 0 var(--sp-3);font-size:var(--fs-lg);color:var(--ink)}
.nx-legal__key{padding:10px 12px;background:var(--surface-2);border-radius:var(--r-md);font-size:var(--fs-sm)}
.nx-legal__row{display:flex;gap:10px;align-items:flex-start;margin-top:var(--sp-3);cursor:pointer}
.nx-legal__row input{margin-top:4px;width:18px;height:18px;flex:none}
.nx-legal__err{color:var(--neg);font-size:var(--fs-sm);min-height:1em;margin:6px 0 0}
.nx-legal__actions{display:flex;justify-content:flex-end;gap:10px;margin-top:var(--sp-3);flex-wrap:wrap}

.navlinks .nav-legal{display:flex;flex-wrap:wrap;gap:2px 8px;margin-top:4px}
.navlinks .nav-legal a{display:inline;padding:0;margin:0;min-height:0;border:0;background:none;font-size:inherit;
  font-weight:500;color:var(--ink-3);text-decoration:underline;text-underline-offset:2px}
.navlinks .nav-legal a::before,.navlinks .nav-legal a::after{content:none}

/* admin · Data */
.adm-job{display:flex;flex-wrap:wrap;align-items:center;gap:6px 10px;padding:10px 0;border-bottom:1px solid var(--line)}
.adm-job:last-of-type{border-bottom:0}
.adm-run{padding:4px 12px}
.adm-run:disabled,.ctrl button:disabled{opacity:.5;cursor:not-allowed}
.adm-job.is-running{border-left:3px solid var(--nx-blue);padding-left:10px}
.adm-job .src{flex:1 1 100%}
.adm-bar{display:block;flex:1 1 100%;height:6px;border-radius:3px;background:var(--surface-3);overflow:hidden}
.adm-bar i{display:block;height:100%;background:linear-gradient(90deg,var(--nx-blue),var(--nx-teal))}
.adm-bar.is-high i{background:var(--neg)}
.adm-sched{display:flex;flex-wrap:wrap;align-items:center;gap:8px 14px;margin:10px 0 12px}
.adm-check{display:inline-flex;align-items:center;gap:6px;font-size:var(--fs-sm);color:var(--ink);cursor:pointer}
.adm-log{max-height:300px;overflow:auto;margin:8px 0 0;padding:10px 12px;border-radius:8px;background:var(--surface-2);
  font:12px/1.5 var(--font-mono);color:var(--ink-2);white-space:pre-wrap;word-break:break-word}
.adm-pending{margin:0;padding-left:18px;color:var(--ink-2);font-size:var(--fs-sm);line-height:1.6}
.nx-sent--fund .nx-sent__sep{flex-basis:100%;height:0}

/* ==========================================================================
   Portfolio (static/js/portfolio.js)
   ========================================================================== */
/* the book at a glance: a squarified treemap, grouped by sector */
.pf-map{position:relative;width:100%;aspect-ratio:1000/460;min-height:280px;margin-top:var(--sp-3);
  border-radius:10px;overflow:hidden;background:var(--surface-2)}
.pf-map__group{position:absolute;box-sizing:border-box;border:1px solid var(--line-2);border-radius:6px}
.pf-map__sector{position:absolute;left:8px;top:3px;right:8px;font-size:var(--fs-2xs);font-weight:700;
  letter-spacing:.06em;text-transform:uppercase;color:var(--ink-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.pf-map__tile{position:absolute;box-sizing:border-box;border:2px solid var(--surface);border-radius:6px;
  display:flex;flex-direction:column;justify-content:center;align-items:center;gap:1px;overflow:hidden;
  color:var(--ink);text-decoration:none;font-size:var(--fs-xs);line-height:1.15;text-align:center;
  transition:filter var(--motion-fast) var(--ease-nx)}
.pf-map__tile b{font-weight:700;letter-spacing:.01em}
.pf-map__tile span{font-size:var(--fs-2xs);color:var(--ink-2);font-variant-numeric:tabular-nums}
.pf-map__tile:hover{filter:brightness(.94);text-decoration:none}
[data-theme="dark"] .pf-map__tile:hover{filter:brightness(1.2)}
.pf-map__tile:focus-visible{outline:none;box-shadow:var(--nx-focus-ring)}
.pf-map__key{display:flex;flex-wrap:wrap;gap:6px 18px;margin-top:var(--sp-3)}
.pf-map__key i{display:inline-block;width:12px;height:12px;border-radius:3px;margin-right:6px;vertical-align:-2px;
  border:1px solid var(--line-2)}
@media(max-width:640px){ .pf-map{aspect-ratio:1000/900} }
.pf-fl{margin-right:6px}

/* holdings: the name gets the room, every row stays at two lines */
.pf-holdings td.name{min-width:240px}
.pf-holdings td.name .src{white-space:nowrap}
.pf-flag{display:inline-block;margin-left:6px;padding:0 6px;border-radius:999px;font-size:var(--fs-2xs);
  font-weight:700;color:var(--neg);background:color-mix(in srgb,var(--neg) 10%,transparent);
  border:1px solid color-mix(in srgb,var(--neg) 28%,transparent);vertical-align:1px;cursor:help}

/* what has moved it most: best and worst as a matched pair */
.pf-gap{margin-top:var(--sp-5)!important}
.pf-movers{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:var(--sp-3)}
.pf-mover{border:1px solid var(--line);border-radius:12px;padding:var(--sp-3) var(--sp-4);background:var(--surface-2)}
.pf-mover__row{display:flex;justify-content:space-between;align-items:baseline;gap:var(--sp-3);margin-top:4px}
.pf-mover .v{font-family:var(--font-mono);font-weight:700;font-size:var(--fs-lg);white-space:nowrap}

/* grey notes on this page meet 4.5:1 */
.pf .src,.pf .note{color:var(--ink-3)}

@media print{
  /* a long card flows across pages instead of jumping whole to the next one —
     "avoid" on a card taller than the space left is what left half-empty pages;
     headings stay with what follows them, and a row or a tile is never split */
  /* only the two long cards (holdings, exposure) flow across pages; every
     other card stays whole, so no heading is left alone at a page's foot */
  .pf .panel.pf-long{break-inside:auto;page-break-inside:auto}
  .pf .panel h3,.pf .subhead{break-after:avoid;page-break-after:avoid}
  .pf tr,.pf .kpi,.pf .pf-map,.pf .pf-mover,.pf .nx-donut{break-inside:avoid;page-break-inside:avoid}
  .pf-map{aspect-ratio:1000/520;-webkit-print-color-adjust:exact;print-color-adjust:exact}
  /* every column on the page: no scrolling box on paper, a smaller type, and
     the account column (a control, not a figure) left off */
  .pf .tablewrap{overflow:visible}
  .pf-holdings{font-size:7.5pt;width:100%;table-layout:fixed}
  .pf-holdings tr > *{padding:1.4mm 1mm;overflow:hidden;text-overflow:ellipsis}
  /* fixed widths that fit A4: the name gets the room, each figure its own */
  .pf-holdings tr > :nth-child(1){width:56mm}
  .pf-holdings tr > :nth-child(2),.pf-holdings tr > :nth-child(3),.pf-holdings tr > :nth-child(4),
  .pf-holdings tr > :nth-child(5){width:16mm}
  .pf-holdings tr > :nth-child(6){width:18mm}
  .pf-holdings tr > :nth-child(7){width:12mm}
  .pf-holdings tr > :nth-child(8){width:15mm}
  .pf-holdings tr > :nth-child(9){width:10mm}
  .pf-holdings tr > :nth-child(10),.pf-holdings tr > :nth-child(11){display:none}
  .pf-holdings td.name{min-width:0}
  .pf-holdings td.name,.pf-holdings td.name .src{white-space:nowrap}
  .pf-holdings th{white-space:normal;text-overflow:clip}       /* "Gain or loss" wraps, never "GAIN OR L…" */
}

/* the currency switch under the totals: label and switch on one centred line */
.pf-ccyrow{display:flex;align-items:center;flex-wrap:wrap;gap:var(--sp-2) var(--sp-3)}
.pf-ccy button{padding:6px 12px}

/* holdings: a compact account picker, and the remove button pinned to the
   table's right edge, so it is in reach without scrolling the table sideways */
.pf-holdings .js-acct{max-width:132px;font-size:var(--fs-xs);padding:4px 6px;border-radius:8px}
/* the account column (second from last, before Record) keeps room for its picker */
/* right:-2px: flush with the scroller's clip edge, past its 2px padding,
   where the scrolled columns would otherwise peek out */
.pf-holdings .pf-act{position:sticky;right:-2px;z-index:1;width:44px;padding-right:6px;background:var(--surface);
  box-shadow:-10px 0 10px -10px rgba(16,24,40,.18)}
.pf-holdings .js-rm{appearance:none;width:28px;height:28px;border-radius:8px;border:1px solid var(--line-2);
  background:var(--surface);color:var(--ink-3);font-size:13px;line-height:1;cursor:pointer}
.pf-holdings .js-rm:hover{color:var(--nx-negative-ink);border-color:var(--nx-negative)}
/* Sell beside remove; its form opens as a row under the holding */
.pf-holdings .pf-act{width:auto;white-space:nowrap}
.pf-holdings .js-sell,.pf-holdings .js-div{appearance:none;height:28px;padding:0 10px;margin-right:4px;border-radius:8px;
  border:1px solid var(--line-2);background:var(--surface);color:var(--ink-2);font-size:var(--fs-xs);cursor:pointer}
.pf-holdings .js-sell:hover:not(:disabled),.pf-holdings .js-div:hover:not(:disabled){color:var(--ink);border-color:var(--line-3)}
.pf-holdings .js-sell:disabled,.pf-holdings .js-div:disabled{opacity:.45;cursor:not-allowed}
/* Sell over + Dividend, ✕ beside them: a narrow pinned column that leaves Account in view */
.pf-holdings .pf-rec{display:inline-flex;flex-direction:column;gap:4px;vertical-align:top;margin-right:4px}
.pf-holdings .pf-rec button{margin-right:0;width:100%}
.pf-sellrow td{background:var(--surface-2)}
.pf-sellrow .formrow{margin:var(--sp-2) 0}
/* the row is as wide as the scrolled table; the form stays in view and wraps */
.pf-sellrow .formrow{position:sticky;left:0;max-width:calc(100vw - 72px)}
@media (min-width:900px){.pf-sellrow .formrow{max-width:none;position:static}}
.pf-sellrow label{display:flex;flex-direction:column;gap:2px;font-size:var(--fs-xs);color:var(--ink-3)}
.pf-sellrow input{width:13ch;min-width:0}
.pf-sellrow .js-sell-preview{flex-basis:100%}
/* realised: each holding's sales open under it */
.pf-realised details summary{cursor:pointer;color:var(--ink-3);font-size:var(--fs-xs)}
.pf-realised details ul{margin:4px 0 0;padding-left:16px;font-size:var(--fs-xs);color:var(--ink-3)}
.pf-realised details li{margin:2px 0}
.pf-realised .js-undo,.pf-realised .js-undiv{margin-left:6px;font-size:var(--fs-2xs);padding:1px 8px}
.pf-realised > div > details > ul{list-style:none;padding-left:0}

/* ---- fund report: what the fund holds, at a glance ----
   The holdings as the portfolio's treemap (sector groups, tiles by weight)
   beside the sector donut; the table opens on its top ten. */
.fh-map{aspect-ratio:1000/520;margin-top:var(--sp-2)}
.fh-tile{cursor:default}
.fh-tile b{font-size:var(--fs-xs);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}
.fh-sec{list-style:none;margin:var(--sp-2) 0 0;padding:0;display:grid;grid-template-columns:1fr 1fr;gap:10px 40px}
.fh-sec li{display:grid;grid-template-columns:minmax(0,1.1fr) minmax(60px,1fr) 52px;gap:12px;align-items:center;
  font-size:var(--fs-sm);color:var(--ink-2)}
.fh-sec__name{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.fh-sec__name i{display:inline-block;width:10px;height:10px;border-radius:3px;margin-right:8px;vertical-align:-1px}
.fh-sec__name em{font-style:normal;font-size:var(--fs-2xs);margin-left:4px}
.fh-sec__bar{display:block;height:8px;border-radius:999px;background:var(--surface-3);overflow:hidden}
.fh-sec__bar i{display:block;height:100%;border-radius:999px;opacity:.85}
.fh-sec b{text-align:right;color:var(--ink);font-weight:600}
.fh-more{margin-top:var(--sp-3)}
.fh-more > .tablewrap,.fh-more > table{margin-top:var(--sp-2)}
.fh-table td{vertical-align:middle}
.fh-table .fh-wbar{width:22%;min-width:90px;padding-left:0}
.fh-table .fh-wbar .bar{display:block;height:6px}
.fh-table .fh-wbar .bar i{background:linear-gradient(90deg,var(--nx-blue),var(--nx-teal))}
.fh-match{display:inline-block;padding:2px 8px;border-radius:999px;font-size:var(--fs-2xs);font-weight:600;
  white-space:nowrap;background:var(--surface-3);color:var(--ink-3)}
.fh-match--isin{background:color-mix(in srgb,var(--pos) 14%,var(--surface));color:var(--nx-positive-ink,var(--pos))}
.fh-match--name{background:color-mix(in srgb,var(--nx-blue) 12%,var(--surface));color:var(--nx-blue)}
@media(max-width:900px){ .fh-sec{grid-template-columns:1fr} }
@media(max-width:640px){ .fh-map{aspect-ratio:1000/1100} .fh-table .fh-wbar,.fh-table tr > :nth-child(5){display:none} }
@media print{ .fh-map,.fh-sec{break-inside:avoid;page-break-inside:avoid}
  .fh-tile,.fh-sec i,.fh-match{-webkit-print-color-adjust:exact;print-color-adjust:exact}
  .fh-more{display:block} .fh-more > summary{display:none} }

/* weekly screen: one market's list at a time on screen, every market on paper */
/* ten markets fit on one line at desktop width, and wrap rather than hide one off the edge */
.sc-tabs{flex-wrap:wrap;overflow:visible}
.sc-tabs button{padding:12px var(--sp-3) 10px;gap:7px}
@media print{ .sc-mkt[hidden]{display:block!important} }

/* fund report: the scheme's facts and asset mix, from the shared library */
.fh-facts .fh-fact{font-size:var(--fs-sm);line-height:1.35;font-family:var(--font-sans);font-weight:600}
.fh-assetbar{display:flex;height:14px;border-radius:999px;overflow:hidden;margin-top:var(--sp-4);background:var(--surface-3)}
.fh-assetbar i{display:block;height:100%}
.fh-assetbar i + i{box-shadow:-2px 0 0 var(--surface)}
.fh-assetkey{list-style:none;margin:var(--sp-2) 0 0;padding:0;display:flex;flex-wrap:wrap;gap:6px 18px;font-size:var(--fs-sm);color:var(--ink-2)}
.fh-assetkey i{display:inline-block;width:10px;height:10px;border-radius:3px;margin-right:6px;vertical-align:-1px}
.fh-assetkey b{color:var(--ink);font-weight:600;margin-left:4px}
@media print{ .fh-assetbar i,.fh-assetkey i{-webkit-print-color-adjust:exact;print-color-adjust:exact} }
