:root{
  /* Ledger-green ramp: deep ink-green base with warm paper-ivory text --
     the look of a bound annual report, not a SaaS dashboard. One emerald
     accent carries the whole brand (single-accent discipline); old gold is
     reserved for the "your analysis" semantic only. Lightness steps match
     the old navy ramp, so the verified contrast ratios carry over. */
  --bg:#0b100d; --panel:#111813; --panel2:#161f19; --panel3:#1d2921; --border:#2a382e;
  /* One step brighter than the original ramp (user feedback: text was hard
     to read on the dark ground). Brightening light-on-dark text only raises
     contrast, so the old AA-verified floor still holds. */
  --text:#ffffff; --muted:#e6e4dd; --muted-dim:#cbc9c1;
  --accent:#d9b356; --accent-soft:#d9b3561f;
  /* Text color for anything sitting ON the gold gradient -- gold is a light
     surface, so it takes dark ink, not white (white-on-gold fails contrast). */
  --on-grad:#221a0b;
  --analysis:#d4a13f; --analysis-soft:#d4a13f1f;
  --green:#3fbf7f; --red:#e0684f; --amber:#d4a13f;
  /* Alias names that .lynchCat consumes. They were REFERENCED but never
     declared anywhere in this project, so `border:1px solid var(--line)` was
     invalid at computed-value time and fell back to `border-style:none` --
     the six Peter Lynch cards have been rendering with NO border at all, in
     both themes, and the .on severity border-colors could never show. Kept
     as pure aliases of tokens that already exist rather than four new
     colours, so each theme resolves them from its own block and neither
     palette gains a value it did not already have. */
  --line:var(--border); --good:var(--green); --warn:var(--amber); --bad:var(--red);
  --space-1:4px; --space-2:8px; --space-3:12px; --space-4:16px; --space-5:24px; --space-6:32px;
  --radius-sm:6px; --radius-md:10px; --radius-lg:14px;
  /* Owned here (the base tokens file) rather than in landing.css, which only
     ever consumed these -- the app itself gets the same premium typographic
     and gradient treatment the landing page always had, instead of falling
     back to a generic system font the moment you actually log in. */
  /* Gold mix on every clickable surface (buttons, active tabs, nav pills,
     landing CTAs all consume this one token): deep bronze into bright gold,
     the black-and-gold "private bank" read. Anything on this surface uses
     --on-grad dark ink, never white. */
  --grad:linear-gradient(135deg,#987d3c 0%,#d9b356 48%,#face63 100%);
  --grad-soft:linear-gradient(135deg,var(--accent-soft) 0%,var(--accent-soft) 100%);
  --display-font:'Bricolage Grotesque','Segoe UI',system-ui,sans-serif;
  /* Promoted from .landing so the app can use the same serif for editorial
     numerals -- the running numbers in the report are typography, not UI
     chrome, and must match the landing's 01/02/03 treatment. */
  --serif:'Fraunces',Georgia,'Times New Roman',serif;
  /* Elevation scale: three tiers rather than one flat shadow everywhere, so
     depth actually communicates hierarchy (a resting card vs. a hovered one
     vs. a floating overlay) instead of every surface looking the same. */
  --shadow-sm:0 1px 2px rgba(0,0,0,.10);
  --shadow-md:0 8px 24px rgba(0,0,0,.16);
  --shadow-lg:0 16px 48px rgba(0,0,0,.28);
  --shadow-glow:0 0 0 1px var(--accent-soft),0 8px 28px -8px #a87d4155;
}
/* Two theme states: dark is the default design; an explicit user choice of
   data-theme="light" on <html> (persisted in localStorage via theme.js)
   switches to the light reading theme.

   Light is PARCHMENT, not white. The neutrals used to sit in the green
   family (hue ~81deg) while the accent is gold (hue ~40deg) -- a warm accent
   on cool ground, which is why the page read as both flat and faintly "off":
   the two families fought instead of supporting each other. Every neutral
   below is rotated into the accent's own hue band (38-43deg) at the SAME
   channel spread the green ramp used, so the chroma budget is unchanged.
   This is a hue move, not a saturation move -- the target is the off-white a
   broadsheet or an annual report is printed on, not cream.

   Lightness is deliberately almost untouched (CIE L*: --bg 94.8 -> 93.5,
   --panel 98.9 -> 98.0), so every ratio verified against the old ramp carries
   over; --bg simply stops throwing back full-page glare. The --bg / --panel
   gap WIDENS (dL* 4.1 -> 4.5), which matters because below 700px the cards go
   full-bleed and that gap plus --border is the only thing separating them --
   so --border is a deliberate step stronger too (dL* to --panel 15.8 -> 17.4).
   Verified: --text on --bg 14.8:1, --muted on --panel 7.2:1 (was 6.8:1),
   --muted-dim on --panel3 4.8:1 (was 4.5:1 and failing). */
/* Neutrals follow Claude's warm-gray ramp (sampled from its design tokens:
   gray-10 #fcfcfb, gray-30 #f6f6f4, gray-50 #f0efec, gray-80 #e7e6e1).

   The previous warm ramp had the right HUE but far too much CHROMA -- --panel
   measured 62% saturation and --bg 36%, against roughly 11-14% across Claude's
   whole light ramp. That is the entire difference between "warm paper" and
   "beige": hue says which direction, saturation says how far, and this ramp had
   gone about four times too far. Surfaces now sit at 10-14% and the inks fall to
   ~3%, which is Claude's other move -- its neutrals DESATURATE as they darken,
   so text reads as near-black rather than as brown.

   The gold accent is untouched and still works, because these greys sit at
   45-60deg, the same warm family as the 40deg gold, just drained of chroma. */
:root[data-theme="light"]{ --bg:#f0efec; --panel:#fcfcfb; --panel2:#f6f6f4; --panel3:#e7e6e1; --border:#dbdad2; --text:#000000; --muted:#2b2a27; --muted-dim:#3d3b37; --accent:#d4a017; --accent-soft:#d4a01714; --analysis:#d4a017; --analysis-soft:#d4a0171a;
  /* Status colours are DARKENED for paper, not merely re-hued: at their
     dark-theme brightness they failed AA as small text on a light ground
     (--green 4.1:1 and --red 4.1:1 on --panel2, and --amber was never
     declared in this block at all -- it fell through to the dark #d4a13f and
     ran at 2.2:1). These clear 4.5:1 on --panel, --panel2 AND --panel3.
     Hue is held: green stays ~152deg, red ~10deg, amber moves to ~32deg so
     "caution" stays distinct from the 40deg gold accent beside it.
     Kept as 6-digit hex on purpose -- .rangeBarTrack concatenates an alpha
     pair onto var(--red)/var(--green), which only parses against #rrggbb. */
  --green:#16714a; --red:#ac402c; --amber:#8c5314;
  /* Same gold mix as dark, one step deeper so the chips still read as
     "lit" against bright cream surroundings. */
  --grad:linear-gradient(135deg,#997311 0%,#d4a017 48%,#fabd1b 100%);
  --on-grad:#221a0b;
  /* Identical geometry, identical alphas -- only the shadow's own hue moves
     out of the old green-grey into the warm neutral family. The leftover
     emerald in --shadow-glow (a survivor of the pre-gold brand, still ringing
     the DCF headline stat in green on a gold theme) becomes the theme's own
     gold at a LOWER alpha than before (33 -> 26): nothing here glows harder
     than it already did. */
  --shadow-sm:0 1px 2px rgba(46,36,20,.06); --shadow-md:0 8px 24px rgba(46,36,20,.08); --shadow-lg:0 16px 48px rgba(46,36,20,.14); --shadow-glow:0 0 0 1px var(--accent-soft),0 8px 28px -8px #96703a26; }
/* The landing's ivory display color must track the theme too, or serif
   headlines vanish on light paper. Warmed with the rest of the light ramp --
   it was the last green-cast ink left, and it sets the biggest type on the
   page. Same lightness, so contrast on --bg is unchanged (14.4:1). */
:root[data-theme="light"] .landing{--ivory:#1f1b14;}
/* Theme toggle: a quiet segmented control, not a novelty sun/moon switch. */
.themeToggle{display:inline-flex;gap:2px;background:var(--panel2);border:1px solid var(--border);
  border-radius:999px;padding:3px;}
.themeToggle button{background:none;border:none;color:var(--muted);font-family:inherit;font-size:10.5px;
  font-weight:700;letter-spacing:.04em;text-transform:uppercase;padding:4px 10px;border-radius:999px;
  cursor:pointer;transition:background .12s ease,color .12s ease;}
.themeToggle button:hover{color:var(--text);}
.themeToggle button.active{background:var(--accent);color:var(--on-grad);}

/* Same visual language as the theme toggle -- a quiet segmented control. */
.langToggle{display:inline-flex;gap:2px;background:var(--panel2);border:1px solid var(--border);
  border-radius:999px;padding:3px;}
.langToggle button{background:none;border:none;color:var(--muted);font-family:inherit;font-size:10.5px;
  font-weight:700;letter-spacing:.02em;padding:4px 10px;border-radius:999px;
  cursor:pointer;transition:background .12s ease,color .12s ease;}
.langToggle button:hover{color:var(--text);}
.langToggle button.active{background:var(--accent);color:var(--on-grad);}
*{box-sizing:border-box;}
html{scroll-behavior:smooth;}
body{margin:0;background:var(--bg);color:var(--text);font-family:'Inter','Segoe UI',system-ui,Arial,sans-serif;line-height:1.55;-webkit-font-smoothing:antialiased;}
/* Every heading, site-wide, renders upper case (by request) -- a transform,
   not literal caps in the markup, so DOM text/screen readers/copy-paste and
   the Chinese i18n strings (case-less, unaffected either way) stay in their
   natural case. A couple of headings below explicitly override this back
   to none where a title is meant to read as a normal sentence. */
h1,h2,h3,h4{text-transform:uppercase;}
/* A faint, fixed radial wash behind everything -- purely atmospheric, low
   enough contrast to never compete with content, but it's the difference
   between "flat charcoal rectangle" and a surface with actual depth. Fixed
   (not absolute) so it doesn't reflow or repeat as the page scrolls. */
body::before{content:'';position:fixed;inset:0;z-index:-1;pointer-events:none;
  background:
    radial-gradient(900px 500px at 15% -10%, #a87d4114, transparent 60%),
    radial-gradient(700px 420px at 100% 0%, #d4a13f0f, transparent 55%);}
header{padding:16px 24px;border-bottom:1px solid var(--border);background:var(--panel);position:sticky;top:0;z-index:20;display:flex;align-items:center;justify-content:space-between;gap:16px;}

/* How far the investor has scrolled down the current page/section -- a tab
   being open doesn't prove its content was actually read; scrolling to the
   bottom is the closer proxy, and this makes that visible instead of implicit. */
#scrollProgressBar{position:fixed;top:0;left:0;right:0;height:3px;z-index:30;pointer-events:none;background:transparent;}
#scrollProgressFill{height:100%;width:0%;background:var(--accent);transition:width .1s linear;}
.scrollProgressPct{position:fixed;top:10px;right:16px;z-index:30;background:var(--panel);border:1px solid var(--border);
  color:var(--text);font-size:11px;font-weight:700;padding:4px 11px;border-radius:20px;
  box-shadow:0 2px 10px rgba(0,0,0,.18);pointer-events:none;font-variant-numeric:tabular-nums;}
header h1{font-family:var(--display-font);font-size:19px;margin:0;font-weight:800;letter-spacing:-.02em;}
header .sub{color:var(--muted);font-size:12px;margin-top:2px;}
main{padding:24px 24px 64px;max-width:940px;margin:0 auto;}

/* ---- page nav: Live Data / Deep-Dive Report / Checklist ---- */
.pageNav{display:flex;gap:4px;background:var(--panel);border:1px solid var(--border);
  border-radius:var(--radius-md);padding:4px;margin-bottom:var(--space-4);
  position:sticky;top:72px;z-index:15;box-shadow:var(--shadow-md);}
.pageTab{flex:1;display:flex;align-items:center;justify-content:center;gap:7px;
  padding:10px 12px;border-radius:var(--radius-sm);text-decoration:none;
  font-size:13px;font-weight:700;color:var(--muted);white-space:nowrap;
  transition:background .12s ease,color .12s ease;}
.pageTab:hover{color:var(--text);background:var(--panel2);}
.pageTab.active{background:var(--grad);color:var(--on-grad);}
.pageTab.active:hover{background:var(--grad);color:var(--on-grad);}
.tabBadge{font-size:10.5px;font-weight:700;padding:1px 7px;border-radius:20px;
  background:var(--panel2);color:var(--muted);border:1px solid var(--border);
  font-variant-numeric:tabular-nums;}
.pageTab.active .tabBadge{background:rgba(0,0,0,.16);color:var(--on-grad);border-color:transparent;}
.tabBadge:empty{display:none;}
@media(max-width:640px){
  .pageNav{position:static;}
  .pageTab{font-size:12px;padding:9px 6px;}
}

.view[hidden]{display:none;}

/* ---- section grouping: separates "live data" from "your analysis" ---- */
.section-eyebrow{display:flex;align-items:center;gap:10px;font-family:var(--display-font);font-size:19px;font-weight:800;text-transform:uppercase;letter-spacing:.04em;margin:var(--space-6) 0 var(--space-3);
  background:var(--grad);-webkit-background-clip:text;background-clip:text;color:transparent;
  filter:drop-shadow(0 0 11px rgba(201,154,53,.22));}
.section-eyebrow:first-child{margin-top:0;}
.section-eyebrow::before{content:'';width:16px;height:3px;border-radius:2px;background:var(--accent);flex:none;}
.section-eyebrow.analysis::before{background:var(--analysis);}
.section-eyebrow .eyebrow-note{font-weight:400;letter-spacing:0;text-transform:none;color:var(--muted-dim);font-size:11px;-webkit-text-fill-color:var(--muted-dim);}
/* Phone: the title and its note fought for one row, so the title broke across
   two lines with the note squeezed beside it. Stack them instead. */
@media(max-width:640px){
  .section-eyebrow{flex-wrap:wrap;gap:4px 10px;font-size:16px;}
  .section-eyebrow .eyebrow-note{flex-basis:100%;padding-left:26px;}
}

.card{background:var(--panel);border:1px solid var(--border);border-radius:var(--radius-lg);padding:20px;margin-bottom:var(--space-4);box-shadow:var(--shadow-sm);transition:box-shadow .18s ease,border-color .18s ease;}
.card:hover{box-shadow:var(--shadow-md);border-color:color-mix(in srgb,var(--border) 60%,var(--accent));}
/* Card titles in gold. Deliberately NOT applied to every heading -- the
   collapsible <summary> titles stay ivory because their field labels below
   are already gold, and two golds stacked would compete instead of ranking.
   The rule is: gold marks where a block STARTS, neutral carries content. */
.card h2{font-family:var(--display-font);margin:0 0 4px;font-size:16px;font-weight:800;letter-spacing:-.015em;
  color:var(--accent);text-shadow:0 0 16px rgba(201,154,53,.13);}
.card h2 + .muted{margin-top:0;margin-bottom:var(--space-4);}

/* A settings card whose contents stay folded until asked for. The <summary>
   carries the card's own h2, so a collapsed card is visually identical to a
   normal one -- only the chevron says it opens. */
/* Hide the body explicitly rather than trusting the browser's built-in
   closed-<details> behaviour. Some embedded/older engines render the children
   of a closed <details> anyway, which for THIS card would mean three password
   boxes sitting open exactly when they should not be. */
.settingsDisclosure:not([open]) > *:not(summary){display:none;}
.settingsDisclosure > summary{list-style:none;cursor:pointer;display:flex;align-items:center;
  justify-content:space-between;gap:10px;}
.settingsDisclosure > summary::-webkit-details-marker{display:none;}
.settingsDisclosure > summary h2{margin:0;}
/* Chevron drawn in CSS rather than an icon font, and rotated on open so the
   control states which way it is going. */
.settingsDisclosure > summary::after{content:'';width:8px;height:8px;flex:none;
  border-right:2px solid var(--muted);border-bottom:2px solid var(--muted);
  transform:rotate(45deg) translate(-2px,-2px);transition:transform .18s ease,border-color .18s ease;}
.settingsDisclosure[open] > summary::after{transform:rotate(225deg) translate(-2px,-2px);}
.settingsDisclosure > summary:hover h2{filter:brightness(1.15);}
.settingsDisclosure > summary:hover::after{border-color:var(--accent);}
.settingsDisclosure > summary:focus-visible{outline:2px solid var(--accent);outline-offset:3px;border-radius:4px;}
.card h3{margin:0 0 var(--space-2);font-size:12px;color:var(--muted);text-transform:uppercase;letter-spacing:.06em;font-weight:700;}

.row{display:flex;gap:12px;flex-wrap:wrap;align-items:end;}
.field{display:flex;flex-direction:column;gap:5px;font-size:12px;color:var(--muted);}
label{font-weight:600;}
input,select,textarea{background:var(--panel2);border:1px solid var(--border);color:var(--text);padding:9px 11px;border-radius:var(--radius-sm);font-size:13px;font-family:inherit;transition:border-color .12s ease;}
input,select{min-width:120px;}
input:focus,select:focus,textarea:focus{outline:none;border-color:var(--accent);}
input:read-only{color:var(--muted);}
/* Keyboard-only focus ring, site-wide: default browser outlines get lost against
   this dark theme, and several custom controls (chips, tabs, the prose-view divs)
   have no visible focus state at all otherwise. :focus-visible skips mouse clicks. */
a:focus-visible,button:focus-visible,[tabindex]:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible{
  outline:2px solid var(--accent);outline-offset:2px;border-radius:2px;}
textarea{width:100%;min-height:76px;resize:vertical;line-height:1.65;}
.ddProse{min-height:220px;overflow-y:hidden;}
.ddAutoGrow{overflow-y:hidden;}
/* Rendered read view sits over the raw-markdown textarea -- click to edit swaps back to it. */
/* Long-form reading surface: slightly larger type, looser leading, and a
   capped measure -- an investor reads thousands of words here, and 90+
   character lines at 13px are what makes that tiring. */
.ddProseView{display:none;width:100%;min-height:220px;background:var(--panel2);border:1px solid var(--border);border-radius:var(--radius-sm);padding:14px 16px;font-size:14px;line-height:1.7;max-width:76ch;white-space:pre-wrap;cursor:text;}
.ddProseView:hover{border-color:var(--muted-dim);}
.ddProseView strong{color:var(--accent);font-weight:800;}
.ddProseView.empty{color:var(--muted-dim);}
/* .btn works on <button> and <a> alike -- the Google sign-in control is an anchor. */
.btn{background:var(--grad);color:var(--on-grad);border:none;padding:10px 18px;border-radius:var(--radius-sm);cursor:pointer;font-weight:700;font-size:13px;white-space:nowrap;font-family:inherit;line-height:1.4;text-decoration:none;text-align:center;
  box-shadow:0 4px 14px -4px #a87d4166;transition:transform .14s ease,box-shadow .14s ease,filter .14s ease;}
.btn.secondary{background:var(--panel2);color:var(--text);border:1px solid var(--border);box-shadow:none;font-weight:600;}
.btn.small{padding:6px 11px;font-size:12px;}
.btn:hover{filter:brightness(1.08);transform:translateY(-1px);box-shadow:0 6px 20px -4px #a87d4177;}
.btn.secondary:hover{box-shadow:none;border-color:var(--accent);color:var(--accent);}
.btn:active{transform:translateY(0);filter:brightness(.96);}
.btn:disabled{opacity:.5;cursor:not-allowed;filter:none;transform:none;box-shadow:none;}

/* ---- Premium table system (applies to every data table in the app) ----
   Terminal-grade conventions: micro-caps headers over a tinted band with a
   brand-gradient underline, hairline rows, an accent rail + emerald wash on
   the hovered row, tabular figures throughout. One system, all tables. */
table{width:100%;border-collapse:collapse;font-size:13px;margin-top:var(--space-3);font-variant-numeric:tabular-nums;}
/* LightweightCharts lays its panes out with a real <table>, so the global
   table rule above was applying a 12px top margin inside every chart. That
   pushed the chart down and shoved the bottom of the time-axis row past the
   container edge -- which is why the date labels rendered with their lower
   half sliced off on every graph. Neutralise our table styling in there. */
.tv-lightweight-charts table{margin:0;width:auto;font-size:inherit;border-collapse:separate;}
.tv-lightweight-charts th,.tv-lightweight-charts td{padding:0;border:none;white-space:normal;}
th,td{padding:10px 13px;text-align:left;border-bottom:1px solid var(--border);white-space:nowrap;}
th{color:var(--muted);font-weight:800;font-size:10.5px;text-transform:uppercase;letter-spacing:.07em;}
/* Gradient underline drawn as a layered background so it works on sticky
   headers too (border-image breaks border-collapse edges). */
thead th{background:var(--grad) bottom/100% 2px no-repeat,var(--panel2);}
tbody td{transition:background .12s ease,box-shadow .12s ease;}
tbody tr:hover td{background:var(--accent-soft);}
tbody tr:hover td:first-child{box-shadow:inset 2.5px 0 0 var(--accent);}
tbody tr:nth-child(even) td{background:var(--panel2);}
tbody tr:nth-child(even):hover td{background:var(--panel3);}

.muted{color:var(--muted);font-size:13px;line-height:1.55;}
.hint{color:var(--muted-dim);font-size:12px;line-height:1.5;margin:2px 0 var(--space-3);}

.grid4{display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin-top:var(--space-2);}
@media(max-width:900px){.grid4{grid-template-columns:repeat(2,1fr);}}
@media(max-width:480px){.grid4{grid-template-columns:1fr 1fr;}}
.stat{background:var(--panel2);border:1px solid var(--border);border-radius:var(--radius-md);padding:12px 14px;transition:border-color .15s ease,transform .15s ease;}
.stat:hover{border-color:color-mix(in srgb,var(--border) 50%,var(--accent));transform:translateY(-1px);}
.stat .v{font-family:var(--display-font);font-size:20px;font-weight:800;font-variant-numeric:tabular-nums;letter-spacing:-.02em;}
.stat .v.good{color:var(--green);} .stat .v.mid{color:var(--amber);} .stat .v.bad{color:var(--red);}
.stat .l{font-size:10.5px;color:var(--muted);margin-top:3px;text-transform:uppercase;letter-spacing:.04em;}

.newsItem{padding:11px 0;border-bottom:1px solid var(--border);}
.newsItem:last-child{border-bottom:none;}
.newsItem a{color:var(--accent);text-decoration:none;font-weight:600;font-size:13px;}
.newsItem a:hover{text-decoration:underline;}
.newsItem .meta{font-size:11px;color:var(--muted-dim);margin-top:3px;}

.err{color:var(--red);font-size:13px;padding:8px 0;}
.loading{color:var(--muted);font-size:13px;padding:8px 0;display:flex;align-items:center;gap:8px;}
.loading::before{content:'';width:12px;height:12px;border-radius:50%;border:2px solid var(--border);border-top-color:var(--accent);animation:spin .7s linear infinite;flex:none;}
@keyframes spin{to{transform:rotate(360deg);}}

.authOverlay{position:fixed;inset:0;z-index:100;background:var(--bg);display:flex;align-items:center;justify-content:center;padding:24px;}
.authCard{background:var(--panel);border:1px solid var(--border);border-radius:var(--radius-lg);padding:28px;width:100%;max-width:340px;box-shadow:0 4px 24px rgba(0,0,0,.18);}
.authTabs{display:flex;gap:4px;background:var(--panel2);border:1px solid var(--border);border-radius:var(--radius-sm);padding:3px;margin-bottom:16px;}
.authTab{flex:1;background:none;border:none;padding:8px 0;border-radius:calc(var(--radius-sm) - 2px);cursor:pointer;font-weight:600;font-size:13px;color:var(--muted);}
.authTab.active{background:var(--grad);color:var(--on-grad);}
/* Text-only action inside a form ("Forgot your password?"). A <button>, not an
   <a>: it triggers a view change, not navigation, so a link would offer a
   meaningless href and break middle-click/open-in-new-tab expectations. */
.linkBtn{display:block;width:100%;background:none;border:none;padding:0;font:inherit;font-size:12.5px;
  color:var(--muted);cursor:pointer;text-align:center;text-decoration:underline;text-underline-offset:2px;}
.linkBtn:hover{color:var(--accent);}

.authForm .field{margin-bottom:0;}
/* Scoped to the text-entry controls this was written for. #providerForm reuses
   .authForm but holds RADIOS -- an unscoped width:100% stretched each radio to
   the full row, pushing its label hard right and wrapping "No preference" onto
   two lines. Radios and checkboxes size themselves. */
.authForm input:not([type='radio']):not([type='checkbox']){width:100%;}
.authForm input[type='radio'],.authForm input[type='checkbox']{flex:none;margin:0;}
.authDivider{display:flex;align-items:center;gap:10px;color:var(--muted-dim);font-size:11px;margin:16px 0;}
.authDivider::before,.authDivider::after{content:'';flex:1;height:1px;background:var(--border);}
/* The three perks are separate data-i18n spans (translatable independently),
   so the middot separator is added here in CSS rather than typed into the
   copy -- baking "&middot;" into one perk's text would put a stray dot in
   front of whichever language re-orders or drops it. Without this rule the
   three spans sat flush with no whitespace: "Free to startNo credit card...". */
.authPerks{display:flex;flex-wrap:wrap;justify-content:center;gap:8px;margin-top:14px;
  font-size:11.5px;color:var(--muted-dim);text-align:center;}
.authPerks span+span{display:flex;align-items:center;gap:8px;}
.authPerks span+span::before{content:'\00b7';}
.userMenu{display:flex;align-items:center;gap:12px;font-size:13px;}
/* Reports-remaining pill in the header. Tabular numerals so the figure does
   not jitter as it counts down, and colour that escalates only near the
   limit -- a permanent warning colour would train people to ignore it. */
.reportsBadge{display:inline-flex;align-items:center;gap:6px;cursor:pointer;
  background:var(--panel2);border:1px solid var(--border);border-radius:999px;
  padding:4px 11px;font:inherit;font-size:12px;font-weight:700;color:var(--text);
  font-variant-numeric:tabular-nums;white-space:nowrap;transition:border-color .15s ease,color .15s ease;}
.reportsBadge:hover{border-color:var(--accent);color:var(--accent-ink);}
.reportsBadge .rbLabel{font-weight:500;color:var(--muted);}
.reportsBadge.low{border-color:color-mix(in srgb,var(--amber) 55%,transparent);color:var(--amber);}
.reportsBadge.out{border-color:color-mix(in srgb,var(--red) 55%,transparent);color:var(--red);}
@media(max-width:700px){.reportsBadge .rbLabel{display:none;}}
.backLink{display:inline-block;color:var(--muted);text-decoration:none;font-size:13px;font-weight:600;margin-bottom:16px;}
.backLink:hover{color:var(--text);}
.reportRow{display:flex;align-items:center;justify-content:space-between;gap:10px;background:var(--panel2);
  border:1px solid var(--border);border-radius:var(--radius-md);padding:10px 12px;margin-bottom:8px;}
.reportRow .reportRowInfo{min-width:0;}
.reportRow .reportRowTicker{font-weight:700;}
.reportRow .reportRowLabel{color:var(--muted);font-size:12px;}
.reportRow .reportRowDate{color:var(--muted-dim);font-size:11px;}
.reportRow .reportRowActions{display:flex;gap:6px;flex:none;}
.reportRow .reportRowCo{font-weight:500;color:var(--muted);font-size:12.5px;}
.reportRow .reportRowIndustry{color:var(--accent);font-size:11px;font-weight:600;margin-top:2px;}
.sectorGroup{margin-bottom:20px;}
.sectorGroupHead{display:flex;align-items:center;gap:8px;font-size:11px;font-weight:800;text-transform:uppercase;
  letter-spacing:.09em;color:var(--muted);padding-bottom:7px;margin-bottom:9px;border-bottom:1px solid var(--border);}
.sectorCount{background:var(--panel3);color:var(--muted-dim);border-radius:999px;padding:1px 8px;
  font-size:10.5px;letter-spacing:0;}
.repeatMeta{color:var(--accent);font-weight:600;font-size:12px;}
#providerForm .field label{display:flex;align-items:center;gap:6px;color:var(--text);font-weight:500;margin-bottom:6px;cursor:pointer;}
.savedReportsList{display:flex;flex-wrap:wrap;gap:8px;}
.savedReportsList .chip{background:var(--panel2);border:1px solid var(--border);border-radius:999px;padding:6px 13px;font-size:12px;font-weight:600;cursor:pointer;color:var(--text);}
.savedReportsList .chip:hover{border-color:var(--accent);color:var(--accent);}
.savedReportsList .chip .updated{color:var(--muted-dim);font-weight:400;margin-left:6px;}

/* ---- company name -> ticker autocomplete ---- */
.searchField{position:relative;}
.searchResults{position:absolute;top:100%;left:0;right:0;z-index:40;margin-top:4px;
  background:var(--panel);border:1px solid var(--border);border-radius:var(--radius-md);
  box-shadow:0 10px 30px rgba(0,0,0,.28);max-height:290px;overflow-y:auto;}
.searchResults[hidden]{display:none;}
.searchRow{display:flex;align-items:baseline;gap:10px;padding:9px 12px;cursor:pointer;
  border-bottom:1px solid var(--border);font-size:13px;}
.searchRow:last-child{border-bottom:none;}
.searchRow:hover,.searchRow.active{background:var(--panel2);}
.searchRow .sym{font-weight:700;font-variant-numeric:tabular-nums;flex:none;color:var(--accent);}
.searchRow .nm{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.searchRow .exch{font-size:11px;color:var(--muted-dim);flex:none;}
.searchEmpty{padding:11px 12px;font-size:12.5px;color:var(--muted);}

/* ---- SEC EDGAR cross-check ---- */
.secCheck{font-size:11.5px;line-height:1.6;margin:8px 0 0;padding:9px 11px;border-radius:var(--radius-sm);
  border:1px solid var(--border);background:var(--panel2);}
.secCheck:empty{display:none;}
.secCheck.match{border-color:var(--green);color:var(--green);}
.secCheck.mismatch{border-color:var(--amber);color:var(--amber);}
.secCheck a{color:inherit;text-decoration:underline;font-weight:600;}
.secCheck a:hover{opacity:.85;}

/* ---- data provenance note ---- */
.sourceNote{font-size:11px;color:var(--muted-dim);line-height:1.6;margin:12px 0 0;
  padding-top:10px;border-top:1px solid var(--border);}
.sourceNote a{color:var(--muted);text-decoration:underline;}
.sourceNote a:hover{color:var(--accent);}

/* ---- year-on-year change cells ---- */
#finTable td.yoy,#finTable th:nth-child(3),#finTable th:nth-child(5){white-space:nowrap;}
td.yoy{font-variant-numeric:tabular-nums;font-weight:600;}
td.yoy.up{color:var(--green);}
td.yoy.down{color:var(--red);}
.stmtTableWrap td.up{color:var(--green);}
.stmtTableWrap td.down{color:var(--red);}

/* ---- filing-sourced business detail: collapsible categories ---- */
.filingCat{background:var(--panel2);border:1px solid var(--border);border-radius:var(--radius-md);margin-top:10px;}
.filingCat summary{padding:12px 16px;cursor:pointer;font-weight:700;font-size:13.5px;color:var(--text);list-style:none;
  display:flex;justify-content:space-between;align-items:center;gap:12px;}
.filingCat summary::-webkit-details-marker{display:none;}
.filingCat summary::after{content:'+';font-size:18px;font-weight:400;color:var(--accent);flex:none;transition:transform .15s ease;}
.filingCat[open] summary::after{transform:rotate(45deg);}
.filingCatBody{padding:0 16px 14px;font-size:13px;line-height:1.6;}
.filingCatBody strong{color:var(--text);}
.filingCatBody table{font-size:12.5px;}

/* ---- company website screenshot ---- */
.websiteShot{display:block;width:100%;height:auto;border-radius:var(--radius-sm);border:1px solid var(--border);}

/* ---- research report reader ---- */
.reportList{margin:6px 0 0;padding-left:18px;font-size:13px;color:var(--text);line-height:1.55;}
.reportList li{margin-bottom:4px;}
td.yoy.flat{color:var(--muted-dim);}
.marginDelta{font-size:10.5px;font-weight:600;margin-left:5px;}
.marginDelta.up{color:var(--green);}
.marginDelta.down{color:var(--red);}

/* ---- DCF panel ---- */
.dcfPanel{background:var(--panel2);border:1px solid var(--border);border-radius:var(--radius-md);
  padding:16px;margin-top:var(--space-4);}
.dcfHead{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:10px;font-size:13px;}
.dcfBase{font-size:11.5px;color:var(--muted-dim);margin-bottom:12px;line-height:1.6;}
.dcfInputs{margin-bottom:4px;}
.dcfResult{display:flex;gap:10px;flex-wrap:wrap;margin:14px 0 4px;}
.dcfStat{background:var(--panel);border:1px solid var(--border);border-radius:var(--radius-md);
  padding:11px 14px;flex:1;min-width:130px;transition:transform .15s ease;}
.dcfStat.headline{border-color:var(--accent);background:var(--accent-soft);box-shadow:var(--shadow-glow);}
.dcfStat.headline:hover{transform:translateY(-1px);}
.dcfStat .v{font-family:var(--display-font);font-size:19px;font-weight:800;font-variant-numeric:tabular-nums;letter-spacing:-.02em;}
.dcfStat .l{font-size:10px;color:var(--muted);text-transform:uppercase;letter-spacing:.05em;margin-top:3px;}
.dcfStat .v.up{color:var(--green);}
.dcfStat .v.down{color:var(--red);}
.dcfBand{font-size:12px;margin-top:8px;padding:8px 11px;border-radius:var(--radius-sm);
  background:var(--panel);border:1px solid var(--border);}
.dcfBand.good{border-color:var(--green);color:var(--green);}
.dcfBand.mid{border-color:var(--amber);color:var(--amber);}
.dcfBand.bad{border-color:var(--red);color:var(--red);}
.dcfWarn{font-size:12.5px;color:var(--red);padding:10px 0;}
#dcfSensTable,#dcfProjTable{font-size:12px;margin-top:12px;}
#dcfSensTable th,#dcfSensTable td,#dcfProjTable th,#dcfProjTable td{padding:7px 11px;text-align:right;}
#dcfSensTable th:first-child,#dcfSensTable td:first-child,
#dcfProjTable th:first-child,#dcfProjTable td:first-child{text-align:left;}
#dcfSensTable td.base{background:var(--accent-soft);font-weight:800;color:var(--accent);}
.dcfDetail{margin-top:12px;}
.dcfDetail summary{font-size:12px;color:var(--muted);cursor:pointer;}

/* ---- quality scores (Piotroski / DuPont) ---- */
.qualityGrid{display:grid;grid-template-columns:180px 1fr;gap:16px;margin-top:var(--space-4);}
@media(max-width:700px){.qualityGrid{grid-template-columns:1fr;}}
.fscoreBox{background:var(--panel2);border:1px solid var(--border);border-radius:var(--radius-md);
  padding:18px 14px;text-align:center;display:flex;flex-direction:column;justify-content:center;}
.fscoreNum{font-family:var(--display-font);font-size:44px;font-weight:800;letter-spacing:-.03em;line-height:1;font-variant-numeric:tabular-nums;}
.fscoreNum.strong{color:var(--green);}
.fscoreNum.mid{color:var(--amber);}
.fscoreNum.weak{color:var(--red);}
.fscoreLabel{font-size:11px;text-transform:uppercase;letter-spacing:.06em;color:var(--muted);margin-top:8px;font-weight:700;}
.fscoreVerdict{font-size:12px;color:var(--muted-dim);margin-top:6px;line-height:1.4;}

.fscoreTests{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:2px 14px;align-content:start;}
.fsTest{display:flex;align-items:center;gap:8px;font-size:12.5px;padding:5px 0;}
.fsMark{width:17px;height:17px;border-radius:5px;flex:none;display:flex;align-items:center;
  justify-content:center;font-size:11px;font-weight:800;}
.fsMark.pass{background:#2ecc7126;color:var(--green);}
.fsMark.fail{background:#ff6b6b26;color:var(--red);}
.fsMark.unknown{background:var(--panel3);color:var(--muted-dim);}
.fsTest.unknown span:last-child{color:var(--muted-dim);}

.dupontStrip{display:flex;align-items:stretch;gap:8px;flex-wrap:wrap;margin-top:var(--space-4);}
.dupontCell{background:var(--panel2);border:1px solid var(--border);border-radius:var(--radius-md);
  padding:11px 14px;flex:1;min-width:130px;}
.dupontCell.result{border-color:var(--accent);background:var(--accent-soft);box-shadow:var(--shadow-glow);}
.dupontCell .v{font-family:var(--display-font);font-size:18px;font-weight:800;font-variant-numeric:tabular-nums;letter-spacing:-.01em;}
.dupontCell .v.up{color:var(--green);}
.dupontCell .v.down{color:var(--red);}
.dupontCell .l{font-size:10px;color:var(--muted);text-transform:uppercase;letter-spacing:.05em;margin-top:3px;}
.dupontOp{display:flex;align-items:center;color:var(--muted-dim);font-weight:700;font-size:15px;}
@media(max-width:700px){.dupontOp{display:none;}}

#marginTable{margin-top:var(--space-4);font-size:12.5px;}
#marginTable th,#marginTable td{padding:7px 12px;}
#marginTable td:not(:first-child),#marginTable th:not(:first-child){text-align:right;}

/* ---- financial statements ---- */
.stmtControls{display:flex;gap:8px;align-items:center;}
.stmtTypeTabs{display:inline-flex;margin:14px 0 4px;}
.stmtUnit{font-size:11px;color:var(--muted-dim);margin:6px 0 2px;}
.stmtTableWrap{overflow-x:auto;border-radius:var(--radius-md);border:1px solid var(--border);box-shadow:var(--shadow-sm);}
#stmtTable,.stmtTableWrap table{font-size:12.5px;border-collapse:collapse;width:100%;}
#stmtTable th,#stmtTable td,.stmtTableWrap th,.stmtTableWrap td{padding:9px 12px;white-space:nowrap;}
/* Sticky cells need SOLID fills (translucent hover washes would let the
   scrolled content ghost through), so this family keeps opaque panel steps
   while inheriting the same gradient-underline header band. */
#stmtTable thead th,.stmtTableWrap thead th{position:sticky;top:0;z-index:1;
  background:var(--grad) bottom/100% 2px no-repeat,var(--panel2);
  font-size:10.5px;text-transform:uppercase;letter-spacing:.07em;color:var(--muted);font-weight:800;border-bottom:none;}
#stmtTable th:first-child,#stmtTable td:first-child,.stmtTableWrap th:first-child,.stmtTableWrap td:first-child{
  text-align:left;position:sticky;left:0;background:var(--panel);z-index:2;min-width:220px;}
#stmtTable thead th:first-child,.stmtTableWrap thead th:first-child{z-index:3;
  background:var(--grad) bottom/100% 2px no-repeat,var(--panel2);}
#stmtTable th:not(:first-child),#stmtTable td:not(:first-child),
.stmtTableWrap th:not(:first-child),.stmtTableWrap td:not(:first-child){text-align:right;font-variant-numeric:tabular-nums;}
#stmtTable tbody tr:nth-child(even) td,.stmtTableWrap tbody tr:nth-child(even) td{background:var(--panel2);}
#stmtTable tbody tr:nth-child(even) td:first-child,.stmtTableWrap tbody tr:nth-child(even) td:first-child{background:var(--panel2);}
#stmtTable tbody tr:hover td,.stmtTableWrap tbody tr:hover td{background:var(--panel3);}
#stmtTable tbody tr:hover td:first-child,.stmtTableWrap tbody tr:hover td:first-child{background:var(--panel3);
  box-shadow:inset 2.5px 0 0 var(--accent);}
#stmtTable tr.emphasis td,.stmtTableWrap tr.emphasis td{font-weight:700;border-top:1px solid var(--border);}
.stmtTableWrap td .delta{display:inline-block;margin-left:8px;font-size:10.5px;font-weight:700;padding:1px 5px;border-radius:999px;font-variant-numeric:tabular-nums;}
.stmtTableWrap td .delta.up{color:var(--green);background:#2ecc7120;}
.stmtTableWrap td .delta.down{color:var(--red);background:#ff6b6b20;}

/* ---- Statement KPI panel: small multiples of the three line items that
   characterise each statement. Two stacked encodings per card, because
   they answer different questions and one cannot do both honestly:
   (a) LEVEL -- zero-baseline bars, true to scale. Never truncated: a
       cropped baseline makes a 5% move look like a doubling.
   (b) CHANGE -- a diverging strip scaled to the deltas themselves, which
       is what makes small period-over-period moves actually visible.
   Status green/red is reserved for the change strip and the headline
   delta; the level bars stay one neutral brand hue so magnitude is never
   confused with direction. ---- */
.kpiPanel{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin:2px 0 8px;}
@media(max-width:760px){.kpiPanel{grid-template-columns:1fr;}}
.kpiCard{background:var(--panel2);border:1px solid var(--border);border-radius:var(--radius-md);padding:13px 14px 10px;}
.kpiName{font-size:10.5px;font-weight:800;text-transform:uppercase;letter-spacing:.07em;color:var(--muted);}
.kpiValRow{display:flex;align-items:baseline;gap:8px;margin:5px 0 10px;flex-wrap:wrap;}
.kpiVal{font-family:var(--display-font);font-size:25px;font-weight:800;letter-spacing:-.02em;
  font-variant-numeric:tabular-nums;line-height:1;}
.kpiChange{font-size:11.5px;font-weight:800;font-variant-numeric:tabular-nums;padding:2px 8px;border-radius:999px;}
.kpiChange.up{color:var(--green);background:#2ecc7120;}
.kpiChange.down{color:var(--red);background:#ff6b6b20;}

/* Macro Statistics chart titles: kpiName's muted/small treatment reads fine
   as a label next to a big statement figure, but disappears as a chart
   title at a glance -- these need to read instantly, so full-contrast text
   color and a real size, not a dim caption. */
.macroChartTitle{font-size:14px;font-weight:800;letter-spacing:-.01em;color:var(--text);}
/* Per-chart range tabs (1D/1M/6M/1Y/5Y/MAX) inside each Macro Statistics
   card -- each chart switches its own range independently, so this is a
   small inline group under the title, not the page-level range picker. */
.macroChartRangeTabs{margin:0 0 10px;width:fit-content;transition:opacity .15s ease;}
/* Phone: 24px-tall range buttons are too small to hit reliably. Let the group
   span the card and give each button a real touch height. */
@media(max-width:640px){
  .macroChartRangeTabs{width:100%;}
  .macroChartRangeTabs .rangeTab{flex:1;min-height:44px;font-size:12px;padding:8px 6px;}
}
/* One line per metric, fitted to the data's own range so the trajectory is
   obvious. Colour carries direction (green rising / red falling) and every
   point is value-labelled underneath, so no figure has to be read off the
   pixel height. */
.kpiLine{width:100%;height:38px;display:block;overflow:visible;}
.kpiStroke{fill:none;stroke:var(--accent);stroke-width:1.8;vector-effect:non-scaling-stroke;
  stroke-linecap:round;stroke-linejoin:round;}
.kpiArea{fill:var(--accent);opacity:.12;}
.kpiDot{fill:var(--accent);opacity:.55;vector-effect:non-scaling-stroke;}
.kpiDotNow{fill:var(--accent);stroke:var(--panel2);stroke-width:1.5;vector-effect:non-scaling-stroke;}
.kpiCard.up .kpiStroke,.kpiCard.up .kpiDot,.kpiCard.up .kpiDotNow{stroke:var(--green);}
.kpiCard.up .kpiStroke{stroke:var(--green);}
.kpiCard.up .kpiDot,.kpiCard.up .kpiDotNow{fill:var(--green);}
.kpiCard.up .kpiArea{fill:var(--green);}
.kpiCard.up .kpiDotNow{stroke:var(--panel2);}
.kpiCard.down .kpiStroke{stroke:var(--red);}
.kpiCard.down .kpiDot,.kpiCard.down .kpiDotNow{fill:var(--red);}
.kpiCard.down .kpiArea{fill:var(--red);}
.kpiCard.down .kpiDotNow{stroke:var(--panel2);}
.kpiValues{display:grid;gap:2px;margin-top:7px;}
.kpiValues span{font-size:10.5px;font-weight:700;color:var(--text);text-align:center;
  font-variant-numeric:tabular-nums;white-space:nowrap;}
.kpiValues span:last-child{color:var(--accent);}
.kpiCard.up .kpiValues span:last-child{color:var(--green);}
.kpiCard.down .kpiValues span:last-child{color:var(--red);}
.kpiFoot{display:flex;justify-content:space-between;font-size:9.5px;color:var(--muted-dim);margin-top:4px;
  font-variant-numeric:tabular-nums;}
.kpiUnitsNote{font-size:11px;color:var(--muted-dim);margin:0 0 16px;}

/* Inline per-row trend line, so every line item shows its shape -- not just
   the three featured metrics. */
.sparkCol{width:64px;min-width:64px;}
.rowSpark{width:56px;height:18px;display:block;opacity:.8;}
.rowSpark.up{color:var(--green);}
.rowSpark.down{color:var(--red);}
.stmtTableWrap tbody tr:hover .rowSpark{opacity:1;}

/* Headline bar chart above a statement table: single sequential hue (the
   app's accent), thin rounded bars, chronological left-to-right, value +
   period direct-labeled -- per the dataviz skill's form/color rules
   (magnitude-over-discrete-periods = bar, one hue, status colors reserved
   for the delta badges above, not the bars themselves). */
.stmtHeadlineChart{display:flex;gap:14px;align-items:flex-end;margin:4px 0 18px;padding:14px 10px 4px;
  background:var(--panel2);border:1px solid var(--border);border-radius:var(--radius-md);}
.stmtHeadlineChart .col{flex:1;display:flex;flex-direction:column;align-items:center;gap:6px;min-width:0;}
.stmtHeadlineChart .track{width:100%;max-width:44px;height:84px;display:flex;align-items:flex-end;}
.stmtHeadlineChart .bar{width:100%;border-radius:4px 4px 0 0;background:var(--grad);min-height:3px;transition:opacity .12s ease;}
.stmtHeadlineChart .col:hover .bar{opacity:.85;}
.stmtHeadlineChart .val{font-size:11.5px;font-weight:700;font-variant-numeric:tabular-nums;white-space:nowrap;}
.stmtHeadlineChart .prd{font-size:10px;color:var(--muted-dim);white-space:nowrap;}
#stmtTable td.neg{color:var(--red);}

/* ---- analyst consensus ---- */
.analystTargetBar{margin-top:14px;}
.analystTargetBar .row4{display:flex;gap:10px;flex-wrap:wrap;margin-bottom:14px;}
.analystTargetBar .row4 .dupontCell{flex:1;min-width:110px;}
.targetTrack{position:relative;height:8px;border-radius:20px;background:var(--panel3);margin:26px 8px 10px;}
.targetTrack .rangeFill{position:absolute;top:0;bottom:0;background:var(--accent-soft);border-radius:20px;}
.targetTrack .marker{position:absolute;top:50%;width:2px;height:22px;transform:translate(-50%,-50%);}
.targetTrack .marker .dot{position:absolute;top:-8px;left:-5px;width:12px;height:12px;border-radius:50%;border:2px solid var(--bg);}
.targetTrack .marker .lbl{position:absolute;top:14px;left:50%;transform:translateX(-50%);font-size:10px;
  white-space:nowrap;color:var(--muted-dim);font-weight:700;}
.targetTrack .marker.mean{background:var(--accent);}
.targetTrack .marker.mean .dot{background:var(--accent);}
.targetTrack .marker.current{background:var(--analysis);}
.targetTrack .marker.current .dot{background:var(--analysis);}
.targetEnds{display:flex;justify-content:space-between;font-size:11px;color:var(--muted-dim);margin:0 8px;}

.analystTrendBar{display:flex;height:26px;border-radius:8px;overflow:hidden;margin-top:20px;
  border:1px solid var(--border);}
.analystTrendBar .seg{display:flex;align-items:center;justify-content:center;font-size:11px;
  font-weight:800;color:#fff;min-width:0;overflow:hidden;white-space:nowrap;}
.trendLegend{display:flex;gap:14px;flex-wrap:wrap;margin-top:10px;font-size:11px;color:var(--muted);}
.trendLegend span{display:flex;align-items:center;gap:5px;}
.trendLegend i{width:9px;height:9px;border-radius:3px;display:inline-block;}

/* ---- dividend safety ---- */
.dividendVerdict{font-size:12.5px;padding:10px 12px;border-radius:var(--radius-sm);margin-top:14px;
  border:1px solid var(--border);background:var(--panel2);}
.dividendVerdict.good{border-color:var(--green);color:var(--green);}
.dividendVerdict.mid{border-color:var(--amber);color:var(--amber);}
.dividendVerdict.bad{border-color:var(--red);color:var(--red);}
/* Neutral variant, for statements of FACT rather than verdicts. Red and green
   carry a hard meaning in an investment tool -- loss and gain -- so they must
   not be spent on a classification that is merely descriptive. Peter Lynch's
   six categories are the case that forced this: rendering "Cyclical" in red
   reads as a warning, when Lynch treats cyclicals as where fortunes are made
   IF you time the cycle, and treats fast growers as the most dangerous of the
   six. Neither maps to good/bad. Uses --accent-ink, the AA-compliant gold, so
   the block still reads as notable without implying a direction. */
.dividendVerdict.info{border-color:var(--accent);color:var(--text);}
/* Body copy stays in normal ink. Tinting a whole paragraph gold destroys the
   thing colour is FOR: if every word is emphasised, none of them are, and a
   long "why" paragraph in accent colour is harder to read than plain text.
   The gold is spent on the two places that earn it -- the category name and
   the growth-rate chip -- and emphasis inside the prose is carried by bold,
   which is what the prompts already emit as **markdown**. */
.dividendVerdict.info .kpiVal{color:var(--accent-ink);}
.dividendVerdict.info .kpiChange{color:var(--accent-ink);background:var(--accent-soft);}
.dividendVerdict.info strong{color:var(--text);font-weight:800;}

/* ---- sell discipline trip-wires ---- */
.sellDisciplineOk{font-size:12.5px;padding:10px 12px;border-radius:var(--radius-sm);border:1px solid var(--green);color:var(--green);background:var(--panel2);}
.sellDisciplineFlag{font-size:12.5px;padding:10px 12px;border-radius:var(--radius-sm);border:1px solid var(--red);color:var(--red);background:var(--panel2);margin-bottom:8px;}
.sellDisciplineFlag strong{font-weight:800;}

/* ---- recommended videos: styled like a YouTube results list, not a form ---- */
#ddVideosList{display:flex;flex-direction:column;gap:10px;}
.ddVideoCard{display:flex;align-items:flex-start;gap:14px;background:var(--panel2);border:1px solid var(--border);border-radius:var(--radius-md);padding:12px;}
.ddVideoThumb{display:block;width:140px;height:79px;flex:none;border-radius:var(--radius-sm);overflow:hidden;background:var(--panel3);border:1px solid var(--border);}
.ddVideoThumb img{width:100%;height:100%;object-fit:cover;display:block;}
.ddVideoThumbEmpty{width:100%;height:100%;display:flex;align-items:center;justify-content:center;font-size:10.5px;color:var(--muted-dim);text-align:center;padding:4px;}
.ddVideoBody{flex:1;min-width:0;}
.ddVideoTitleLink{display:block;font-size:14.5px;font-weight:700;color:var(--text);text-decoration:none;line-height:1.35;}
.ddVideoTitleLink:hover{color:var(--accent);text-decoration:underline;}
.ddVideoChannelLine{margin-top:5px;font-size:12px;color:var(--muted);}
.ddVideoEdit{display:flex;flex-direction:column;gap:6px;margin-top:10px;}
.ddVideoEdit[hidden]{display:none;}
.ddVideoEdit input{font-size:12.5px;}
.ddVideoEditToggle{margin-top:8px;background:none;border:none;padding:0;color:var(--accent);font-size:12px;font-weight:600;cursor:pointer;font-family:inherit;}
.ddVideoEditToggle:hover{text-decoration:underline;}
.ddVideoCard .ddRemoveVideo{flex:none;align-self:flex-start;}

/* ---- technical indicators: MA toggles + RSI badge ---- */
.chartToolbar{display:flex;align-items:center;justify-content:space-between;gap:12px;
  flex-wrap:wrap;margin-top:10px;}
.maToggles{display:flex;gap:6px;flex-wrap:wrap;}
.maToggle{display:flex;align-items:center;gap:6px;background:var(--panel2);border:1px solid var(--border);
  border-radius:20px;padding:4px 10px 4px 8px;font-size:11px;font-weight:700;color:var(--muted);
  cursor:pointer;font-family:inherit;transition:opacity .12s ease,border-color .12s ease;}
.maToggle::before{content:'';width:8px;height:8px;border-radius:50%;background:var(--dot);flex:none;opacity:.35;}
.maToggle.active{color:var(--text);border-color:var(--dot);}
.maToggle.active::before{opacity:1;}
.maToggle:disabled{opacity:.35;cursor:not-allowed;}
.statBadges{display:flex;gap:14px;flex-wrap:wrap;align-items:center;}
.rsiBadge{font-size:12px;color:var(--muted);font-variant-numeric:tabular-nums;}
.rsiBadge:empty{display:none;}

/* ---- 52-week range position bar ---- */
.rangeBarWrap{margin-top:12px;}
.rangeBarWrap:empty{display:none;}
.rangeBarHead{display:flex;justify-content:space-between;font-size:11px;color:var(--muted-dim);margin-bottom:5px;}
.rangeBarTrack{position:relative;height:6px;border-radius:20px;
  background:linear-gradient(90deg,var(--red)55,var(--panel3) 15% 85%,var(--green)55);}
.rangeBarTrack .now{position:absolute;top:50%;width:11px;height:11px;border-radius:50%;
  background:var(--accent);border:2px solid var(--bg);transform:translate(-50%,-50%);}

/* ---- earnings calendar ---- */
.earningsNext{display:flex;gap:14px;flex-wrap:wrap;align-items:center;margin:14px 0;
  padding:12px 14px;background:var(--panel2);border:1px solid var(--border);border-radius:var(--radius-md);}
.earningsNext .big{font-family:var(--display-font);font-size:19px;font-weight:800;letter-spacing:-.01em;}
.earningsNext .sub{font-size:12px;color:var(--muted);}
/* Fixed-height track with a pixel-height fill (set inline by JS) -- percentage
   heights on a column-flex child are unreliable across browsers, so the bar
   itself is sized in real pixels, not '%'. */
.surpriseBars{display:flex;gap:10px;align-items:flex-end;margin-top:16px;padding:0 4px;}
.surpriseBars .bar{flex:1;display:flex;flex-direction:column;align-items:center;gap:6px;}
.surpriseBars .bar .track{width:100%;max-width:38px;height:60px;display:flex;align-items:flex-end;}
.surpriseBars .bar .col{width:100%;border-radius:4px 4px 0 0;background:var(--green);min-height:3px;}
.surpriseBars .bar .col.miss{background:var(--red);}
.surpriseBars .bar .pct{font-size:11px;font-weight:700;}
.surpriseBars .bar .qtr{font-size:10px;color:var(--muted-dim);}

/* ---- peer comps ---- */
.peerBtnRow{margin-top:14px;}
#peerTable{margin-top:12px;}
#peerTable:empty{display:none;}

/* ---- TradingView-style price chart ---- */
.chartHead{display:flex;align-items:center;justify-content:space-between;gap:14px;flex-wrap:wrap;}
.rangeTabs{display:flex;gap:2px;background:var(--panel2);border:1px solid var(--border);
  border-radius:var(--radius-sm);padding:3px;}
.rangeTab{background:none;border:none;color:var(--muted);font-weight:700;font-size:11.5px;
  padding:5px 11px;border-radius:calc(var(--radius-sm) - 2px);cursor:pointer;font-family:inherit;
  letter-spacing:.02em;transition:background .12s ease,color .12s ease;}
.rangeTab:hover{color:var(--text);}
.rangeTab.active{background:var(--grad);color:var(--on-grad);}

/* Statement Analysis sub-nav: these are top-level document tabs (Balance
   Sheet / Income Statement / Cash Flow), not a compact range picker like
   the 1M/6M/1Y control, so they get real tab sizing. Scoped by id so the
   chart range tabs elsewhere stay small. */
#stmtAnalysisSubNav{gap:4px;padding:4px;}
.stmtAnalysisTab{margin-top:22px;}
#stmtAnalysisSubNav .rangeTab{font-size:12.5px;font-weight:700;padding:8px 15px;letter-spacing:-.01em;}
@media(max-width:560px){
  #stmtAnalysisSubNav{flex-wrap:wrap;}
  #stmtAnalysisSubNav .rangeTab{flex:1;min-width:120px;min-height:44px;font-size:13.5px;padding:9px 12px;}
}

.chartLegend{display:flex;gap:14px;flex-wrap:wrap;align-items:baseline;margin:12px 0 8px;
  font-size:12px;font-variant-numeric:tabular-nums;min-height:19px;}
.chartLegend .lgItem{color:var(--muted-dim);}
.chartLegend .lgItem b{font-weight:700;margin-left:4px;}
.chartLegend .lgDate{font-weight:700;color:var(--text);font-size:12.5px;}
.chartLegend .up{color:var(--green);}
.chartLegend .down{color:var(--red);}

/* Extra bottom padding: the chart's time-axis row sits flush against the
   bottom of its box, so with an even 6px inset the date labels touched the
   rounded border and read as cut off. */
.tvChartWrap{position:relative;background:var(--panel2);border:1px solid var(--border);
  border-radius:var(--radius-md);padding:6px 6px 12px;}
#tvChart{width:100%;height:380px;}
@media(max-width:640px){#tvChart{height:300px;}}
.chartLoading{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;
  background:color-mix(in srgb,var(--panel2) 78%,transparent);color:var(--muted);font-size:13px;
  border-radius:var(--radius-md);}
.chartLoading[hidden]{display:none;}
.chartHint{font-size:11px;color:var(--muted-dim);margin-top:8px;}

/* Links are provenance, not the point -- in gold they pulled the eye away
   from the figures they support. Grey keeps them legible and obviously
   clickable (underlined) while the data stays the loudest thing on screen. */
a.link{color:var(--muted);text-decoration:underline;
  text-decoration-color:color-mix(in srgb,var(--muted) 45%,transparent);text-underline-offset:2px;}
a.link:hover{color:var(--text);text-decoration-color:currentColor;}
.apikeyNote{font-size:12px;color:var(--muted);margin-top:6px;line-height:1.5;}

/* ---- empty state (before a ticker is analyzed) ---- */
.emptyState{text-align:center;padding:52px 24px;}
.emptyState .emptyGlyph{width:44px;height:44px;margin:0 auto 14px;border-radius:12px;background:var(--accent-soft);display:flex;align-items:center;justify-content:center;color:var(--accent);font-size:20px;font-weight:700;}
.emptyState h2{margin:0 0 6px;font-size:16px;}
.emptyState p{color:var(--muted);font-size:13px;max-width:440px;margin:0 auto;line-height:1.6;}

/* ---- deep-dive report: in-page nav + numbered sections ---- */
/* not sticky any more -- the page nav above it owns the sticky slot */
.ddNav{display:flex;flex-direction:column;gap:8px;margin:0 0 var(--space-5);padding:10px 12px;background:var(--panel2);border:1px solid var(--border);border-radius:var(--radius-md);position:sticky;top:8px;z-index:5;}
/* One labelled row per category. The label is a fixed-width gutter so the
   pills line up down the left edge across every group. */
/* Label in a fixed gutter, pills in their own wrapping column. The wrapper
   is what keeps a second row of pills aligned with the first instead of
   sliding back under the label. */
.ddNavGroup{display:flex;align-items:flex-start;gap:14px;}
.ddNavGroup + .ddNavGroup{padding-top:10px;border-top:1px solid color-mix(in srgb,var(--border) 55%,transparent);}
.ddNavGroupLabel{flex:none;width:88px;padding-top:7px;font-size:9.5px;font-weight:800;
  letter-spacing:.09em;line-height:1.3;text-transform:uppercase;color:var(--muted-dim);user-select:none;}
.ddNavGroupPills{display:flex;flex-wrap:wrap;gap:5px 6px;flex:1;min-width:0;}
.ddNav button{font-size:11.5px;font-weight:700;color:var(--muted);background:none;padding:5px 10px;border-radius:20px;border:1px solid transparent;cursor:pointer;font-family:inherit;text-transform:uppercase;letter-spacing:.05em;}
.ddNav button:hover{color:var(--text);border-color:var(--border);background:var(--panel);}
/* One section visible at a time now (real tabs, not scroll-to-anchor) -- the
   active pill needs to read clearly as "you are here" against the others. */
.ddNav button.active{color:var(--on-grad);background:var(--grad);border-color:transparent;box-shadow:0 3px 10px -3px #a87d4166;}
.ddNav button.active:hover{color:var(--on-grad);background:var(--grad);}
/* Marks a pill once its section has actually been opened, so an investor can
   tell at a glance which of the 20 sections they still haven't read -- not
   just which one they're on right now (that's .active, above). */
.ddNav button.visited:not(.active){border-color:var(--accent);background:var(--accent-soft);color:var(--text);}
/* Phone section navigation: an expandable panel (user-chosen over a
   horizontal scroller). A single "Sections" bar shows the current section;
   tapping it unfolds all 17 pills as a wrapped, tappable grid and picking
   one folds it back. Desktop never sees any of this -- the toggle is
   display:none outside the media query and the pills render as always. */
.ddNavToggle{display:none;}
@media(max-width:640px){
  .ddNavToggle{display:flex;align-items:center;justify-content:space-between;gap:10px;
    width:100%;min-height:48px;margin:0 0 var(--space-4);padding:12px 14px;
    background:var(--panel2);border:1px solid var(--border);border-radius:var(--radius-md);
    color:var(--text);font-family:inherit;font-size:13.5px;font-weight:700;cursor:pointer;}
  .ddNavToggle .ddNavToggleLabel{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
  .ddNavToggle::after{content:'▾';color:var(--accent);flex:none;transition:transform .18s ease;}
  .ddNavToggle.open::after{transform:rotate(180deg);}
  .ddNav{display:none;}
  .ddNav.open{display:flex;flex-direction:column;gap:10px;max-height:55vh;overflow-y:auto;
    animation:ddNavUnfold .16s ease;}
  /* On a phone the gutter would leave too little room for the pills, so the
     label sits on its own line above them. */
  .ddNavGroup{flex-direction:column;gap:6px;}
  .ddNavGroupLabel{width:100%;padding-top:0;margin-bottom:2px;}
  .ddNavGroupPills{width:100%;gap:8px;}
  .ddNav button{min-height:44px;padding:12px 14px;font-size:12.5px;}
}
@keyframes ddNavUnfold{from{opacity:0;transform:translateY(-4px);}to{opacity:1;transform:none;}}
.ddNav button.visited:not(.active)::before{content:'✓';color:var(--accent);font-weight:800;margin-right:4px;}


.ddSection{padding-top:var(--space-5);margin-top:var(--space-5);border-top:1px solid var(--border);scroll-margin-top:120px;}
.ddSection:first-of-type{border-top:none;margin-top:0;padding-top:0;}
/* Tabbed sections don't need the stacked-card divider styling anymore --
   each one is the only thing on screen while active. */
.ddSection[data-tabbed]{padding-top:0;margin-top:0;border-top:none;}
.ddSection h3{display:flex;align-items:center;gap:9px;font-family:var(--display-font);font-size:17px;text-transform:uppercase;letter-spacing:.04em;font-weight:800;
  background:var(--grad);-webkit-background-clip:text;background-clip:text;color:transparent;
  /* drop-shadow (not text-shadow) so the glow hugs the gradient-clipped
     glyphs instead of painting a flat box behind transparent text. */
  filter:drop-shadow(0 0 9px rgba(201,154,53,.22));}
.ddSection h3::before{content:'';width:12px;height:3px;border-radius:2px;background:var(--grad);flex:none;}
/* Sub-headings within a section ("Treasury Yield Curve", "Thesis Tripwires",
   "Official US Statistics"). These were plain ivory and read as flat runs of
   text between charts; gold plus a short rule marks where each block starts.
   Solid gold rather than the h3 gradient so the hierarchy still reads. */
.ddSection h4{display:flex;align-items:center;gap:11px;color:var(--accent);
  font-size:17px;font-weight:800;letter-spacing:.02em;}
.ddSection h4::before{content:'';width:12px;height:3px;border-radius:2px;background:var(--accent);flex:none;opacity:.8;}
.ddSection .sectionHint{margin:-4px 0 10px;}

/* Categorized narrative blocks (Moat sources, Competitive dimensions):
   each category is visually its own answer -- an accent rule on the left
   plus its own heading -- so the reader can jump to just the one they
   care about instead of scanning one long merged essay. */
/* Numbered like the business-detail fields: these blocks stack several long
   narrative answers in a row (Management runs to five or six), and without a
   running number there is nothing to hold your place by. Counter is reset per
   section body so each list reads 1..n. */
.ddSection,.filingCatBody,.card{counter-reset:catBlock;}
.catBlock{border-left:2px solid var(--accent);padding:2px 0 2px 18px;margin:0 0 30px;
  transition:border-color .15s ease;}
.catBlock:hover{border-left-color:var(--analysis);}
/* A real heading, not a label: display face, mixed case, sized to lead the
   paragraph beneath it. The teal moved to the left rule so the heading text
   itself can carry full contrast. */
.catHead{margin:0 0 12px;font-family:var(--display-font);font-size:17.5px;font-weight:800;
  letter-spacing:-.015em;color:var(--text);
  display:flex;align-items:center;gap:12px;flex-wrap:wrap;line-height:1.25;}
/* Editorial numeral, not a badge. Both the boxed and the outlined versions
   read as UI chrome; a large gradient serif figure reads as typography and
   matches the 01/02/03 numerals already used on the landing page, so the
   whole product numbers things one way. Leading zero for even width. */
.catHead::before{counter-increment:catBlock;content:'0' counter(catBlock);
  flex:none;font-family:var(--serif);font-size:26px;font-weight:560;line-height:1;
  letter-spacing:-.02em;font-variant-numeric:tabular-nums;
  /* Soft-tinted rounded square behind the numeral, matching .emptyGlyph.
     The figure stays gradient-clipped type; the box just seats it. */
  width:46px;height:46px;border-radius:12px;background:var(--accent-soft);
  display:inline-flex;align-items:center;justify-content:center;
  background-image:var(--grad);-webkit-background-clip:text;background-clip:text;color:transparent;
  box-shadow:inset 0 0 0 46px var(--accent-soft);
  filter:drop-shadow(0 0 10px rgba(201,154,53,.18));align-self:center;}
.catBadge{font-size:10.5px;font-weight:800;letter-spacing:.02em;text-transform:none;
  border-radius:999px;padding:2px 9px;border:1px solid currentColor;}
.catBadge.good{color:var(--green);}
.catBadge.mid{color:var(--amber);}
.catBadge.bad{color:var(--red);}

/* ---- Investment Risks: ranked cards for the material risks, so severity
   and the early-warning signal are readable at a glance instead of buried
   in a form grid. The left edge is colour-coded by severity -- the one
   place a status colour genuinely belongs here. ---- */
.riskCard{background:var(--panel2);border:1px solid var(--border);border-left:3px solid var(--muted-dim);
  border-radius:var(--radius-md);padding:14px 16px;margin-bottom:10px;}
.riskCard:has(.riskPill.bad){border-left-color:var(--red);}
.riskCard:has(.riskPill.mid):not(:has(.riskPill.bad)){border-left-color:var(--amber);}
.riskCardHead{display:flex;align-items:center;gap:10px;flex-wrap:wrap;}
/* Same seated numeral as .catHead / .ddDetailField -- one numbering language
   across the whole report. Inset box-shadow paints the square (see note on
   .ddDetailField::before for why a background can't be used here). */
.riskRank{width:40px;height:40px;border-radius:11px;flex:none;
  font-family:var(--serif);font-size:21px;font-weight:560;line-height:1;
  letter-spacing:-.02em;font-variant-numeric:tabular-nums;
  background-image:var(--grad);-webkit-background-clip:text;background-clip:text;color:transparent;
  box-shadow:inset 0 0 0 40px var(--accent-soft);
  filter:drop-shadow(0 0 8px rgba(201,154,53,.16));
  display:flex;align-items:center;justify-content:center;}
.riskTitle{font-family:var(--display-font);font-size:16px;font-weight:800;letter-spacing:-.01em;flex:1;min-width:180px;}
.riskPills{display:flex;gap:6px;flex-wrap:wrap;}
.riskPill{font-size:10.5px;font-weight:800;border-radius:999px;padding:3px 10px;border:1px solid currentColor;
  color:var(--muted-dim);white-space:nowrap;}
.riskPill.bad{color:var(--red);}
.riskPill.mid{color:var(--amber);}
.riskPill.good{color:var(--green);}
.riskCat{font-size:10.5px;font-weight:700;text-transform:uppercase;letter-spacing:.07em;color:var(--accent);
  margin:8px 0 0;}
.riskWhat{margin:8px 0 10px;font-size:14px;line-height:1.6;}
.riskLine{font-size:13px;line-height:1.6;color:var(--muted);padding:6px 0;border-top:1px solid var(--border);}
.riskLine b{display:block;font-size:10.5px;text-transform:uppercase;letter-spacing:.07em;color:var(--muted-dim);
  margin-bottom:2px;font-weight:800;}
.riskLine.watch b{color:var(--analysis);}

/* The proof block: styled as an actual quotation with a visible left rule,
   distinct from the analyst's own prose above/below it, so "here is the
   checkable evidence" reads as a different kind of content, not just
   another paragraph. */
.riskEvidence{background:var(--panel);border:1px solid var(--border);border-left:3px solid var(--analysis);
  border-radius:var(--radius-sm);padding:10px 14px;margin:10px 0;}
.riskEvidenceLabel{font-size:10.5px;font-weight:800;text-transform:uppercase;letter-spacing:.07em;
  color:var(--analysis);margin-bottom:6px;}
.riskQuote{margin:0 0 8px;padding:0;font-size:13.5px;font-style:italic;color:var(--text);line-height:1.55;
  border:none;}
.riskEvidenceMeta{display:flex;flex-wrap:wrap;gap:10px;align-items:center;font-size:11px;color:var(--muted-dim);}
.riskEvidenceFigure{font-weight:800;color:var(--text);font-variant-numeric:tabular-nums;}
.riskEvidenceDoc{font-style:normal;}
.riskEvidenceLink{color:var(--accent);text-decoration:none;font-weight:700;}
.riskEvidenceLink:hover{text-decoration:underline;}
.riskEvidenceNoLink{color:var(--muted-dim);font-style:italic;}
/* Recent Bad News: a dated timeline, most recent first -- red rail so it
   reads as distinctly negative-news, separate from the analytical risk
   cards above it. */
.badNewsTimeline{border-left:2px solid var(--red);padding-left:0;}
.badNewsItem{display:grid;grid-template-columns:96px 1fr;gap:14px;padding:10px 0 10px 16px;
  margin-left:-2px;border-left:2px solid transparent;position:relative;}
.badNewsItem::before{content:'';position:absolute;left:-5px;top:15px;width:8px;height:8px;border-radius:50%;
  background:var(--red);}
.badNewsDate{font-size:11px;font-weight:800;color:var(--red);font-variant-numeric:tabular-nums;padding-top:1px;}
.badNewsHeadline{font-size:13.5px;font-weight:700;color:var(--text);line-height:1.45;}
.badNewsWhy{font-size:12.5px;color:var(--muted);line-height:1.55;margin:4px 0 6px;}
@media(max-width:520px){.badNewsItem{grid-template-columns:1fr;gap:3px;}}

.boilerWrap{display:flex;flex-wrap:wrap;gap:7px;}
.boilerChip{font-size:11.5px;color:var(--muted-dim);background:var(--panel2);border:1px dashed var(--border);
  border-radius:999px;padding:4px 12px;}
.ddRow{background:var(--panel2);border:1px solid var(--border);border-radius:var(--radius-md);padding:12px;margin-bottom:8px;}

/* ---- checklist: grouped, scannable categories instead of a 25-row wall ---- */
.checklistCategory{border:1px solid var(--border);border-radius:var(--radius-md);background:var(--panel2);padding:2px 14px 6px;margin-top:14px;}
.checklistCategory:first-of-type{margin-top:4px;}
.catHeader{display:flex;align-items:center;justify-content:space-between;gap:10px;margin:12px 0 4px;}
.catHeader h3{margin:0;}
.catBadge{font-size:11px;font-weight:700;color:var(--muted);background:var(--panel3);border:1px solid var(--border);border-radius:20px;padding:2px 9px;white-space:nowrap;font-variant-numeric:tabular-nums;}
.catBadge.complete{color:var(--green);border-color:var(--green);}
.checklistRow{display:grid;grid-template-columns:1fr 130px 220px;gap:10px;align-items:center;padding:9px 0;border-bottom:1px solid var(--border);font-size:13px;}
.checklistRow:last-child{border-bottom:none;}
@media(max-width:800px){.checklistRow{grid-template-columns:1fr;}}
.ddChkAnswer[value="Yes"],.ddChkAnswer.ans-Yes{color:var(--green);}
.ddChkAnswer.ans-No{color:var(--red);}
.ddChkAnswer.ans-Partial,.ddChkAnswer.ans-Unsure{color:var(--amber);}

@media(max-width:640px){
  main{padding:16px 16px 48px;}
  /* The logged-in user menu (name + language toggle + three buttons) is
     ~520px laid out inline -- wider than the phone itself. Since neither the
     header nor the menu could wrap, the whole PAGE was forced that wide and
     every section below appeared shifted/clipped. Let both wrap. */
  header{padding:12px 16px;flex-wrap:wrap;gap:8px;}
  header h1{font-size:16px;}
  /* The tagline costs a full wrapped line under a sticky header that already
     spans several rows when logged in -- drop it on phones. */
  header .sub{display:none;}
  .userMenu{flex-wrap:wrap;gap:8px;row-gap:8px;}
  .card{padding:16px;}
  .ddNav{position:static;}
}

/* Source-quality grade chips (A-E) appended to AI citations. Graded by the
   SOURCE's authority, not the model's confidence -- so a reader can see at a
   glance which figures rest on filed accounts and which on commentary.
   Green = primary/audited, amber = press/secondary, red = unverifiable. */
.srcGrade{display:inline-flex;align-items:center;justify-content:center;
  width:17px;height:17px;margin-left:4px;border-radius:5px;
  font-size:10px;font-weight:800;line-height:1;vertical-align:1px;cursor:help;}
.srcGrade-A{color:var(--green);background:color-mix(in srgb,var(--green) 16%,transparent);border:1px solid color-mix(in srgb,var(--green) 40%,transparent);}
.srcGrade-B{color:var(--green);background:color-mix(in srgb,var(--green) 10%,transparent);border:1px solid color-mix(in srgb,var(--green) 26%,transparent);}
.srcGrade-C{color:var(--amber);background:color-mix(in srgb,var(--amber) 12%,transparent);border:1px solid color-mix(in srgb,var(--amber) 30%,transparent);}
.srcGrade-D{color:var(--amber);background:color-mix(in srgb,var(--amber) 8%,transparent);border:1px solid color-mix(in srgb,var(--amber) 22%,transparent);}
.srcGrade-E{color:var(--red);background:color-mix(in srgb,var(--red) 12%,transparent);border:1px solid color-mix(in srgb,var(--red) 32%,transparent);}

/* Numeric figures inside rendered prose/tables (mdBoldToHtml's numifyTextNodes)
   get the same tabular-nums display font as the KPI stat cards (.stat .v,
   .kpiVal) instead of plain text, so a percentage or a dollar figure reads as
   DATA wherever it appears, not just in a dedicated stat box. Deliberately no
   font-size here -- it must inherit whatever size the surrounding text/table
   cell already uses, not the 18-25px those standalone stat cards are set at. */
.numHighlight{font-family:var(--display-font);font-variant-numeric:tabular-nums;font-weight:800;letter-spacing:-.01em;}

/* Business-detail fields: label as its own heading line, answer beneath.
   These answers run to several clauses plus a citation and a grade chip, so
   the old inline "Label: answer" form gave the eye nothing to scan by. */
/* Numbered down the left edge: these sections run to a dozen fields, and a
   running number gives the eye a fixed anchor to track position by. The
   counter resets per section so each reads 1..n rather than continuing
   across the whole report. */
.filingCatBody{counter-reset:ddField;}
.ddDetailField{display:grid;grid-template-columns:36px 1fr;column-gap:16px;margin:22px 0;}
.ddDetailField:first-child{margin-top:4px;}
/* Same seated numeral as .catHead, sized down for a field list. The tinted
   square is painted with an inset box-shadow, not a background: this element
   uses background-clip:text for the gradient figure, which would otherwise
   clip any fill away with it. */
.ddDetailField::before{counter-increment:ddField;content:'0' counter(ddField);
  grid-row:1 / span 2;justify-self:start;align-self:start;
  width:36px;height:36px;border-radius:10px;
  display:inline-flex;align-items:center;justify-content:center;
  font-family:var(--serif);font-size:19px;font-weight:560;line-height:1;
  letter-spacing:-.02em;font-variant-numeric:tabular-nums;
  background-image:var(--grad);-webkit-background-clip:text;background-clip:text;color:transparent;
  box-shadow:inset 0 0 0 36px var(--accent-soft);
  filter:drop-shadow(0 0 8px rgba(201,154,53,.16));}
.ddDetailLabel{font-size:11px;font-weight:800;text-transform:uppercase;letter-spacing:.07em;
  color:var(--accent);margin-bottom:7px;padding-top:5px;}
.ddDetailValue{font-size:13.5px;line-height:1.65;color:var(--text);}
.ddDetailValue .muted{color:var(--muted);}

/* Financial ratio table: dense two-column list grouped by category, in place
   of large stat tiles. Sixteen ratios as cards forced heavy scrolling and made
   cross-row comparison hard; a table reads like the ratio pages investors
   already know. Explanations live in each row's title tooltip. */
.ratioTable{font-size:13px;}
.ratioTable td{padding:7px 12px;white-space:nowrap;}
.ratioTable tbody tr:hover td{background:var(--accent-soft);cursor:help;}
/* Real separation before each new category: a category header that sits
   flush against the previous group's last row reads as just another row.
   The gap is drawn with a thick top border in the header's own colour so it
   works inside a table, where margins on rows are ignored. */
.ratioGroupRow td{background:var(--panel2)!important;color:var(--accent);
  font-size:11.5px;font-weight:800;text-transform:uppercase;letter-spacing:.08em;
  padding:14px 12px 10px;border-bottom:1px solid var(--border);
  border-top:14px solid var(--panel);}
.ratioTable tbody tr.ratioGroupRow:first-child td{border-top:none;}
.ratioTable tbody tr.ratioGroupRow:hover td{background:var(--panel2)!important;cursor:default;}
.ratioName{color:var(--text);}
/* Period provenance (FY vs MRQ) sits beside the name the way ratio pages
   label TTM/MRQ, so a quarterly figure is never mistaken for a full year. */
.ratioPeriodTag{font-size:9.5px;font-weight:700;letter-spacing:.06em;color:var(--muted-dim);
  border:1px solid var(--border);border-radius:4px;padding:1px 4px;margin-left:6px;vertical-align:1px;}
.ratioVal{text-align:right;font-variant-numeric:tabular-nums;font-weight:700;color:var(--text);}
.ratioVal.up{color:var(--green);}
.ratioVal.down{color:var(--red);}

/* Peer comparison columns */
.ratioPeerVal{color:var(--muted);font-weight:600;}
.ratioVs{font-size:11.5px;font-weight:800;color:var(--muted-dim);}
.ratioVs.up{color:var(--green);}
.ratioVs.down{color:var(--red);}

/* Discipline checklists (circle of competence, bias check, Lynch's 13).
   A row per item with the prompt beneath the label, so the question is
   readable rather than compressed into a single line of small text. */
.ddCheckRow{display:flex;align-items:flex-start;gap:12px;padding:11px 12px;
  border-bottom:1px solid var(--border);cursor:pointer;transition:background .12s ease;}
.ddCheckRow:last-child{border-bottom:none;}
.ddCheckRow:hover{background:var(--accent-soft);}
.ddCheckRow input[type=checkbox]{flex:none;width:17px;height:17px;margin-top:2px;accent-color:var(--accent);cursor:pointer;}
.ddCheckLabel{display:block;font-size:13.5px;font-weight:700;color:var(--text);line-height:1.45;}
.ddCheckSub{display:block;font-size:12.5px;color:var(--muted);line-height:1.55;margin-top:3px;}

/* Peter Lynch's six categories, shown as a persistent six-up frame above the
   business detail. Always rendered -- the matched card lights up, the other
   five stay readable so you can see what the company is not. */
.lynchCats{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;margin:0 0 16px;}
.lynchCat{border:1px solid var(--line);border-radius:10px;padding:11px 13px;background:var(--panel2);opacity:.62;transition:opacity .18s,border-color .18s,transform .18s;}
.lynchCat.on{opacity:1;transform:translateY(-2px);border-width:2px;box-shadow:0 6px 20px rgba(0,0,0,.28);}
.lynchCat.on.good{border-color:var(--good);}
.lynchCat.on.mid{border-color:var(--warn);}
.lynchCat.on.bad{border-color:var(--bad);}
.lynchCatName{font-family:var(--serif);font-size:16px;font-weight:700;letter-spacing:.01em;margin-bottom:5px;display:flex;align-items:center;gap:8px;flex-wrap:wrap;}
.lynchCat.on .lynchCatName{background:var(--grad);-webkit-background-clip:text;background-clip:text;color:transparent;}
.lynchCatTick{font-family:var(--sans,inherit);font-size:9.5px;font-weight:900;letter-spacing:.09em;padding:2px 7px;border-radius:99px;background:var(--grad);color:var(--on-grad);-webkit-text-fill-color:var(--on-grad);white-space:nowrap;}
.lynchCatGist{font-size:12.5px;line-height:1.5;color:var(--muted);}
.lynchCat.on .lynchCatGist{color:var(--text);}
@media(max-width:900px){.lynchCats{grid-template-columns:repeat(2,1fr);}}
@media(max-width:560px){.lynchCats{grid-template-columns:1fr;}}

/* ==========================================================================
   MOBILE LAYOUT PASS
   --------------------------------------------------------------------------
   Everything below is inside a media query -- the desktop layout is not
   touched. Four problems, in the order they were measured:
     (1) horizontal overflow: controls that refuse to shrink
     (2) one shared left gutter instead of four competing ones
     (3) 44px minimum touch targets
     (4) a 12px minimum size for reading text
   No new colours: every value here comes from the existing tokens.
   ========================================================================== */

/* -- (1) OVERFLOW: rows whose column template is written inline by JS -------
   ddRenderTripwireRow / ddRenderValMethodRow set a 5-column grid as an
   INLINE style, which outranks the plain `.checklistRow{1fr}` rule below
   800px -- so those rows stayed 5 columns wide on a phone and pushed the
   page past the viewport. !important is the only way to reach past an
   inline style without touching the JS. Once the rows stack, the separate
   column-header strip labels nothing (every field carries the same text as
   its own placeholder), so it is dropped rather than left dangling. */
@media(max-width:800px){
  .checklistRow,.ddTripwireRow,.ddValMethodRow{grid-template-columns:1fr!important;}
  #ddValMethodsHead,#ddTripwiresHead{display:none!important;}
}

@media(max-width:700px){

  /* -- (1) OVERFLOW: the global min-width floor on form controls ------------
     `input,select{min-width:120px}` is a hard floor: inside any narrow
     container the control cannot shrink, so it pushes the container -- and
     the page -- wider than the screen. On a phone the container is always
     the constraint, so the floor is removed and replaced with a ceiling. */
  input,select,textarea{min-width:0;max-width:100%;}

  /* The position-sizing, Kelly and decision-journal fields are bare
     `<label>text<input></label>` pairs inside .grid4 -- the label is inline
     at the inherited 16px and the input keeps its intrinsic (~196px) width,
     so label and input sat side by side and neither could give way. Stack
     them and let the input fill its column. */
  .grid4 > label{display:block;font-size:12px;font-weight:600;color:var(--muted);line-height:1.4;}
  .grid4 > label > input,.grid4 > label > select{display:block;width:100%;margin-top:6px;}

  /* -- (2) ONE GUTTER ------------------------------------------------------
     main is padded 16px; a .card added another 16px, so card content sat at
     33px while section headings sat at 16px. Pulling each card out to the
     screen edge by exactly main's padding and giving it back the same
     padding puts card content on the same 16px gutter as everything else,
     without changing main. Square corners and no side borders because the
     card now meets the screen edge. */
  main{padding:16px 16px 48px;}
  .card{margin-left:calc(-1 * var(--space-4));margin-right:calc(-1 * var(--space-4));
    padding-left:var(--space-4);padding-right:var(--space-4);
    border-left:0;border-right:0;border-radius:0;}

  /* Same move one level down, for the three full-width containers that nest
     inside a card and were pushing their own content out to ~50px: filing
     categories, the DCF panel, and checklist categories. Small tiles (.stat,
     .kpiCard, .dupontCell, .riskCard) are deliberately left as tiles. */
  .filingCat,.dcfPanel,.checklistCategory{
    margin-left:calc(-1 * var(--space-4));margin-right:calc(-1 * var(--space-4));
    border-left:0;border-right:0;border-radius:0;}
  .checklistCategory{padding-left:var(--space-4);padding-right:var(--space-4);}
  /* .filingCat summary / .filingCatBody / .dcfPanel already carry 16px of
     horizontal padding, so their content lands on the gutter unaided. */

  /* The ticker row: input and button were sharing one 343px line, leaving
     the app's most-used control about 200px wide. Full-width input, button
     beneath it on its own line. */
  .row .searchField{flex:1 1 100%;}
  #analyzeBtn{width:100%;}

  /* 47 business-detail fields carried the densest prose in the report and
     were indented 52px past their own container by the numeral column,
     leaving ~250px of measure. Keep the numeral -- it is the report's
     numbering language -- but move it beside the label and let the answer
     span the full width, back on the gutter. */
  .ddDetailField{grid-template-columns:auto 1fr;column-gap:12px;row-gap:7px;margin:20px 0;}
  .ddDetailField::before{grid-row:1;grid-column:1;align-self:center;
    width:30px;height:30px;border-radius:9px;font-size:16px;
    box-shadow:inset 0 0 0 30px var(--accent-soft);}
  .ddDetailLabel{grid-row:1;grid-column:2;align-self:center;margin:0;padding-top:0;font-size:12px;}
  .ddDetailValue{grid-row:2;grid-column:1 / -1;}

  /* Headings: one size per level, and only the section title keeps a left
     rule -- sub-heads sit on the gutter with everything else. h4 is styled
     here for both cases (inside .ddSection and bare inside a card) because
     the bare ones were falling through to the browser default. */
  .ddSection h3{font-size:16px;}
  .card h4,.ddSection h4{font-size:13.5px;font-weight:800;letter-spacing:.06em;color:var(--accent);}
  .ddSection h4::before{display:none;}
  .filingCat summary,.dcfDetail summary{font-size:13.5px;}

  /* -- (3) TOUCH TARGETS: 44px minimum -------------------------------------
     Checkboxes and radios are excluded from the input rules -- forcing a
     44px box on the native widget stretches the glyph; their rows are
     enlarged instead, further down. */
  input:not([type=checkbox]):not([type=radio]),select,
  .ddVideoEdit input{min-height:44px;padding:11px 12px;font-size:16px;}
  textarea{padding:12px 13px;font-size:16px;}
  /* Read view and edit view of the same prose must match, or the text jumps
     size when you tap into it. */
  .ddProseView{font-size:16px;}

  .btn{min-height:44px;display:inline-flex;align-items:center;justify-content:center;}
  .btn.small{min-height:44px;padding:10px 14px;}

  /* 21px was the worst target in the app. The wrapper padding drops from 3px
     to 2px so the segmented control does not grow more than it has to. */
  .themeToggle,.langToggle{padding:2px;}
  .themeToggle button,.langToggle button{min-height:44px;padding:0 16px;font-size:12px;
    display:inline-flex;align-items:center;justify-content:center;}

  /* Segmented range/tab controls span the row and wrap rather than
     overflowing; wrapping (not shrinking) is what keeps overflow at zero. */
  .rangeTabs{width:100%;flex-wrap:wrap;}
  .rangeTab{flex:1 1 auto;min-height:44px;font-size:12.5px;padding:8px 12px;
    display:inline-flex;align-items:center;justify-content:center;}
  .maToggle{min-height:44px;padding:0 14px 0 12px;}
  .pageTab{min-height:44px;}
  .authTab{min-height:44px;}
  /* 44px tall chips pushed seven saved reports onto four rows and ate most of
     the first screen. These are a pick-list, not primary controls, so they take
     36px -- comfortably tappable, roughly twice as many per screen. The date
     shrinks more than the ticker, since the ticker is what you aim at. */
  .savedReportsList{gap:6px;}
  .savedReportsList .chip{min-height:36px;display:inline-flex;align-items:center;
    padding:5px 11px;font-size:11.5px;}
  .savedReportsList .chip .updated{font-size:10px;margin-left:5px;}
  .searchRow{min-height:44px;padding:12px;}
  .filingCat summary{min-height:44px;}
  .dcfDetail summary{min-height:44px;display:flex;align-items:center;}
  .ddVideoEditToggle{min-height:44px;}
  .ddCheckRow{min-height:44px;padding:12px;}
  .ddCheckRow input[type=checkbox]{width:20px;height:20px;margin-top:1px;}
  #providerForm .field label{min-height:44px;}

  /* Header: the logged-in menu is name + language + three buttons. At 44px
     each that cannot share a line with the title, so it gets its own row as
     an even three-up. The header stops being sticky here -- at this height
     it would eat roughly a fifth of the viewport on every screen. */
  /* flex-wrap is repeated here (it already exists at 640px) because this
     block starts at 700px -- without it the full-width menu could not wrap
     in the 640-700px band and would push the header wider than the screen. */
  header{position:static;flex-wrap:wrap;}
  /* .pageNav sticks at top:72px, an offset that only made sense under a
     sticky header. It is already static below 640px; match that up to 700. */
  .pageNav{position:static;}
  .userMenu{width:100%;gap:8px;flex-wrap:wrap;}
  #userMenuName{width:100%;font-size:12px;}
  .userMenu .btn.small{flex:1 1 auto;}

  /* -- (4) TYPE FLOOR: 12px for anything meant to be read ------------------
     Deliberately scoped to reading text. Micro-caps labels (th, .stat .l,
     .kpiName, badges, chart tick labels) stay at their current size: they
     are scanned, not read, and enlarging them would re-break table density. */
  .scrollProgressPct{font-size:12px;padding:5px 12px;}
  .section-eyebrow .eyebrow-note{font-size:12px;}
  .secCheck,.dcfBase,.sourceNote,.chartHint,.kpiUnitsNote,.stmtUnit,
  .newsItem .meta,.riskEvidenceMeta,.badNewsDate,.boilerChip,
  .reportRow .reportRowDate,.reportRow .reportRowIndustry,
  .searchRow .exch,.trendLegend,.authDivider{font-size:12px;}
  /* The page disclaimer sets 11.5px inline; !important is the only reach. */
  #companyWorkspace > p.muted{font-size:12px!important;}
}

/* ---------------------------------------------------------------------------
   Small accent text in LIGHT mode only.

   --accent (#96703a, deep bronze) measures 4.38:1 on --panel -- close, but
   under the 4.5:1 WCAG AA wants for small text, and it degrades further on the
   darker surfaces. .ddDetailLabel alone sets it at 12px/800 in 47 places, in
   the densest reading area of the report.

   --accent itself is NOT changed: buttons, the gradient, borders, glyphs and
   every large heading use the chosen bronze. --accent-ink is the same hue at
   86% lightness (#816032), applied only where the accent is used as SMALL
   TEXT. Measured on every light ground: panel 5.60, panel2 5.31, panel3 4.60,
   bg 5.00, and 4.54 on the darkest (#ebe4d5) -- all clear AA.

   Dark mode is untouched: --accent-ink falls back to --accent there, which
   already passes comfortably against the dark grounds. */
/* Dark mode uses ONE gold: gold text is the same #d9b356 as the button and the
   gradient's mid stop, so a gold word and a gold control read as the same
   material. It can afford to -- on the dark grounds it runs 7.6-9.6:1, far
   clear of AA, so there is no legibility reason to hold text at a separate
   value. Light mode cannot do this: #d4a017 is only 2.6:1 on white paper, so
   there the ink has to stay darker than the fill. */
:root{--accent-ink:#d9b356;}
:root[data-theme="light"]{--accent-ink:#7f600e;}
:root[data-theme="light"] .ddDetailLabel,
:root[data-theme="light"] .card h2,
:root[data-theme="light"] .card h4,
:root[data-theme="light"] .ddSection h3,
:root[data-theme="light"] .ddSection h4,
:root[data-theme="light"] .riskCat,
:root[data-theme="light"] .newsItem a,
:root[data-theme="light"] .ratioGroupRow td,
:root[data-theme="light"] .ddVideoEditToggle,
:root[data-theme="light"] .reportRow .reportRowIndustry,
:root[data-theme="light"] .repeatMeta,
:root[data-theme="light"] .searchRow .sym,
:root[data-theme="light"] .kpiValues span:last-child,
:root[data-theme="light"] .riskEvidenceLink,
:root[data-theme="light"] .riskEvidenceLabel,
:root[data-theme="light"] .riskLine b,
:root[data-theme="light"] .ddProseView strong,
:root[data-theme="light"] .sourceNote a:hover{color:var(--accent-ink);}

/* Paragraphs inside the long-form prose views. Spacing does the separating --
   the last paragraph carries no trailing margin so the block does not gain a
   phantom gap above whatever follows it. */
/* Unscoped: the same paragraph splitting now also renders the provider company
   profile in #coDesc, which is not inside a .ddProseView. */
.ddProsePara{margin:0 0 13px;}
.ddProsePara:last-child{margin-bottom:0;}

/* Subtitles inside the Lynch verdict: the inline labels ("Drifting:",
   "How to hold it:") and the three evidence source headers. These are
   NAVIGATION -- they tell you what kind of statement follows -- so they take
   the gold, while the sentences after them stay in reading ink. Scoped to the
   label classes rather than to `strong`, so bold used for emphasis inside the
   prose (**$450,000 per day**) is untouched and keeps its job. */
.dividendVerdict.info .ddVerdictLabel,
.dividendVerdict.info .ddEvidenceLabel{color:var(--accent-ink);}
.ddEvidenceBlock{margin-top:10px;padding-left:12px;border-left:2px solid var(--accent);}
.ddEvidenceLabel{margin:0 0 3px;font-size:11px;font-weight:800;letter-spacing:.06em;text-transform:uppercase;}

/* ---------------------------------------------------------------------------
   Checklist report: the score, the statement, and the per-section table that
   sit above the questions. */
.chkReport{border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--panel2);
  padding:16px;margin-bottom:20px;}
.chkReportHead{display:flex;gap:20px;align-items:flex-start;flex-wrap:wrap;margin-bottom:14px;}
.chkScore{font-family:var(--display-font);font-size:40px;font-weight:800;line-height:1;letter-spacing:-.02em;}
.chkScoreLabel{font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  color:var(--muted);margin-top:5px;white-space:nowrap;}
.chkVerdict{flex:1;min-width:240px;font-size:13px;line-height:1.65;color:var(--text);}
.chk-good{color:var(--green);} .chk-mid{color:var(--amber);} .chk-bad{color:var(--red);}
.chkTable{width:100%;border-collapse:collapse;font-size:12.5px;}
.chkTable th{text-align:left;font-size:10px;font-weight:800;letter-spacing:.07em;text-transform:uppercase;
  color:var(--muted);padding:0 10px 7px 0;border-bottom:1px solid var(--border);}
.chkTable td{padding:8px 10px 8px 0;border-bottom:1px solid var(--border);}
.chkTable tfoot td{border-bottom:none;border-top:2px solid var(--border);padding-top:10px;}
.chkTable .num{text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap;}
/* Bar track sits on --panel3 so it stays visible on --panel2 in both themes. */
.chkBar{display:block;height:6px;border-radius:99px;background:var(--panel3);overflow:hidden;}
.chkBarFill{display:block;height:100%;border-radius:99px;}
.chkBarFill.good{background:var(--green);} .chkBarFill.mid{background:var(--amber);} .chkBarFill.bad{background:var(--red);}
.checklistCategory{margin-bottom:26px;}
.catHeader{display:flex;align-items:baseline;justify-content:space-between;gap:12px;margin-bottom:2px;}
.catBadge{font-size:10.5px;font-weight:800;letter-spacing:.05em;color:var(--muted);
  background:var(--panel3);border-radius:99px;padding:3px 9px;white-space:nowrap;}
.catBadge.complete{color:var(--on-grad);background:var(--grad);}
@media(max-width:700px){
  .chkReportHead{gap:12px;}
  .chkScore{font-size:32px;}
  .chkTable{font-size:12px;}
}

/* The four-column report table does not fit a 375px phone: section names are
   long ("Valuation & Margin of Safety") and the bar column has a minimum
   width, so the row overflowed by 45px. Rather than scroll it sideways --
   which hides the percentage, the one column you actually scan -- the bar is
   dropped on narrow screens and the numbers stay. The bar is redundant there
   anyway: it encodes the same value as the % beside it. */
@media(max-width:700px){
  .chkTable{table-layout:fixed;width:100%;}
  .chkTable th:nth-child(3),.chkTable td:nth-child(3){display:none;}
  .chkTable th:first-child,.chkTable td:first-child{width:auto;word-break:break-word;}
  .chkTable th.num,.chkTable td.num{width:64px;padding-right:0;}
  .chkTable td{padding:9px 8px 9px 0;}
  /* Side by side, the verdict was squeezed into a ~150px column beside the
     score and broke into seven short lines. Stacked, the score reads as a
     headline and the statement gets the full width it needs. */
  .chkReportHead{flex-direction:column;gap:12px;}
  .chkScoreLabel{white-space:normal;}
  .chkScore{font-size:34px;}
  .chkVerdict{min-width:0;width:100%;font-size:12.5px;}
  .chkReport{padding:14px;}
}

/* ---------------------------------------------------------------------------
   Mobile: stacked table rows.

   Each row becomes a block and each cell a label/value pair, so nothing hides
   behind a sideways scroll. Following the mobile-table guidance: smaller type,
   horizontal rules only (no vertical lines, no zebra striping -- both "trap the
   eye" on a narrow screen), values top-aligned, and the label carried in the
   left column so the cell content never repeats it. */
@media(max-width:700px){
  table.stackable{display:block;width:100%;border-collapse:collapse;font-size:12px;}
  table.stackable thead{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;}
  table.stackable tbody,table.stackable tr,table.stackable td{display:block;width:auto;}
  /* One rule between records, and a little air, so rows read as separate cards
     without the cost of borders on four sides. */
  table.stackable tbody tr{padding:10px 0;border-bottom:1px solid var(--border);}
  table.stackable tbody tr:last-child{border-bottom:none;}
  table.stackable td{
    display:grid;grid-template-columns:minmax(88px,40%) 1fr;gap:10px;
    align-items:start;padding:3px 0;border:none;white-space:normal;text-align:left;
  }
  table.stackable td[data-label]::before{
    content:attr(data-label);
    font-size:10px;font-weight:800;letter-spacing:.05em;text-transform:uppercase;
    color:var(--muted);line-height:1.5;padding-top:1px;
  }
  /* The first cell is the row's identity (the account name, the peer, the
     metric) -- promoted to a heading rather than shown as another label/value
     pair, which is what makes the stack scannable. */
  table.stackable tbody tr td:first-child{
    display:block;font-weight:800;font-size:13px;color:var(--text);margin-bottom:5px;
  }
  table.stackable tbody tr td:first-child::before{display:none;}
  table.stackable td[data-fullspan]{display:block;}
  table.stackable td[data-fullspan]::before{display:none;}
  /* The wrapper no longer needs to scroll, and leaving it scrollable would keep
     a phantom drag on a stacked list. */
  .vsTableWrap,.stmtTableWrap,.tableWrap{overflow-x:visible;}
}

/* ---------------------------------------------------------------------------
   Mobile: bottom tab bar.

   The three sections were a row of pills at the top of the page, which on a
   phone meant scrolling back up to switch view. Native apps put primary
   navigation at the bottom because that is where the thumb rests, and it stays
   put while the content scrolls. Same three destinations, same markup -- only
   the position changes below the breakpoint.

   env(safe-area-inset-bottom) keeps the bar clear of the home indicator on
   iPhones; it resolves to 0 everywhere else, so it is safe unconditionally. */
@media(max-width:700px){
  .pageNav{
    /* top:auto is load-bearing: the base rule is position:sticky;top:72px, and
       leaving that set alongside bottom:0 stretches the fixed bar to fill the
       whole viewport (measured 740px tall before this). */
    position:fixed;top:auto;left:0;right:0;bottom:0;z-index:40;
    display:flex;gap:0;margin:0;border-radius:0;
    border:none;border-top:1px solid var(--border);
    background:var(--panel);
    padding:6px 6px calc(6px + env(safe-area-inset-bottom));
    box-shadow:0 -6px 20px rgba(0,0,0,.10);
  }
  .pageTab{
    flex:1;flex-direction:column;gap:3px;
    min-height:46px;padding:6px 4px;border-radius:10px;
    font-size:10.5px;font-weight:700;letter-spacing:.02em;text-align:center;line-height:1.25;
  }
  /* The active tab is marked with colour and weight rather than the full gold
     gradient -- a saturated block across a third of a fixed bar is heavy to sit
     under while reading, and this bar is always on screen. */
  .pageTab.active{background:var(--accent-soft);color:var(--accent-ink);}
  .pageTab.active:hover{background:var(--accent-soft);color:var(--accent-ink);}
  .pageTab .tabBadge{font-size:9.5px;padding:1px 6px;}
  .pageTab.active .tabBadge{background:var(--accent);color:var(--on-grad);border-color:transparent;}
  /* Clearance so the fixed bar never covers the end of the page. */
  main{padding-bottom:96px;}
}

/* ---------------------------------------------------------------------------
   Light mode reading ink.

   --text is pure black and --muted was pulled from #5f5d58 to #2b2a27, because
   --muted is not only used for labels: long-form body copy renders through it
   too (the company description is a p.muted running several hundred words), and
   at the old value that read as washed-out grey rather than as text.

   Hierarchy still exists -- it is just carried by weight, size and caps now
   rather than by fading the words out. Links keep a distinctly LIGHTER grey so
   they remain the one thing on the page that is not near-black. */
:root[data-theme="light"] a.link,
:root[data-theme="light"] .sourceNote a,
:root[data-theme="light"] .ddDetailValue a,
:root[data-theme="light"] .newsItem .meta a{color:#6b6862;}
:root[data-theme="light"] a.link:hover,
:root[data-theme="light"] .sourceNote a:hover{color:#4a4843;}

/* Dark is the same rule mirrored: --text is pure white and --muted was lifted
   from #b6bcab to #e6e4dd so body copy reads as white rather than as a dim
   sage grey. Links move the OTHER way here -- dimmer than the surrounding
   text -- so in both themes the link is the one thing that is not full-contrast
   ink, and it stays identifiable without colour. */
a.link,.sourceNote a,.ddDetailValue a,.newsItem .meta a{color:#a9a79f;}
a.link:hover,.sourceNote a:hover{color:#d2d0c8;}

/* ---------------------------------------------------------------------------
   Mobile header. At 134px it was a fifth of the screen before any content --
   the title, the account row and four 44px controls each on their own line.
   The controls are secondary (you sign in once), so they take 34px and sit on
   one row with the language toggle, leaving the title as the only full-size
   element. */
@media(max-width:700px){
  header{padding-top:10px;padding-bottom:10px;gap:8px;}
  header h1{font-size:15px;line-height:1.2;}
  header .tagline,header .subtitle{display:none;}
  .userMenu{gap:6px;font-size:11.5px;flex-wrap:wrap;}
  .userMenu .btn,.userMenu button{min-height:34px;padding:6px 11px;font-size:11.5px;}
  .langToggle button{min-height:28px;padding:4px 9px;font-size:10px;}
  .userMenu .userEmail,.userMenu .who{font-size:11px;}
}

/* ---------------------------------------------------------------------------
   Auth modal close button.

   Previously unstyled entirely, so it rendered as a default browser button --
   a bordered grey box sitting above the logo in the top-LEFT, where it read as
   part of the content rather than as a dismiss control. Moved to the top-right
   (where every dialog puts it) and drawn as a quiet circular target.

   The glyph is drawn with two rotated bars rather than the "×" character: the
   text glyph sits slightly off-centre in most fonts and its weight changes with
   the font stack, which is what made the original look crooked. Two 1.5px bars
   are always optically centred and always the same weight. */
.authCard{position:relative;}
.authClose{
  position:absolute;top:12px;right:12px;
  width:32px;height:32px;padding:0;
  display:flex;align-items:center;justify-content:center;
  background:transparent;border:1px solid transparent;border-radius:50%;
  color:transparent;font-size:0;line-height:0;    /* hide the &times; text node */
  cursor:pointer;transition:background .15s ease,border-color .15s ease,transform .15s ease;
}
.authClose::before,.authClose::after{
  content:'';position:absolute;width:13px;height:1.5px;border-radius:2px;
  background:var(--muted);transition:background .15s ease;
}
.authClose::before{transform:rotate(45deg);}
.authClose::after{transform:rotate(-45deg);}
.authClose:hover{background:var(--panel2);border-color:var(--border);}
.authClose:hover::before,.authClose:hover::after{background:var(--text);}
.authClose:active{transform:scale(.92);}
.authClose:focus-visible{outline:2px solid var(--accent);outline-offset:2px;}
/* The logo mark sat under the old top-left button; with the button moved it
   needs the right-hand gutter kept clear so a long title cannot run under it. */
.authCard .mark{margin-top:0;}
.authCard h1{padding-right:34px;}
@media(max-width:700px){
  /* 32px is below the 44px touch minimum, so the tap area is extended past the
     drawn circle rather than making the visible control heavier. */
  .authClose{top:8px;right:8px;width:44px;height:44px;}
}

/* Country code + number as one control. The select is sized to its content so
   a long country name does not squeeze the number field, and both share the
   input border treatment so the pair reads as a single field rather than two. */
.phoneField{display:flex;gap:8px;}
.phoneField select{flex:0 0 auto;max-width:132px;}
.phoneField input{flex:1 1 auto;min-width:0;}

/* ---------------------------------------------------------------------------
   Country code picker (signup phone field).

   A native <select> is always as wide as its LONGEST option, so listing
   "United Arab Emirates" made the collapsed control enormous even when
   Malaysia was selected. This is the pattern phone fields normally use: the
   trigger shows only flag + dial code, and the country name lives inside the
   dropdown where there is room for it. */
.ccPicker{position:relative;flex:0 0 auto;}
.ccTrigger{
  display:flex;align-items:center;gap:6px;height:100%;min-height:38px;
  padding:0 9px;border:1px solid var(--border);border-radius:var(--radius-sm);
  background:var(--panel2);color:var(--text);font-family:inherit;font-size:13px;
  font-weight:600;cursor:pointer;white-space:nowrap;
}
.ccTrigger:hover{border-color:var(--accent);}
.ccTrigger:focus-visible{outline:2px solid var(--accent);outline-offset:1px;}
.ccFlag{display:flex;align-items:center;}
.ccFlagGlyph{font-size:16px;line-height:1;}
/* Fallback when the platform has no flag glyphs (Windows): a small ISO chip
   reading "MY" is honest and legible, where a broken emoji is neither. */
.ccIso{font-size:9.5px;font-weight:800;letter-spacing:.04em;padding:2px 4px;border-radius:3px;
  background:var(--panel3);color:var(--muted);line-height:1;}
.ccCode{font-variant-numeric:tabular-nums;}
.ccCaret{width:0;height:0;margin-left:1px;border-left:3.5px solid transparent;
  border-right:3.5px solid transparent;border-top:4px solid var(--muted);}

.ccPanel{position:absolute;z-index:60;top:calc(100% + 5px);left:0;width:236px;
  background:var(--panel);border:1px solid var(--border);border-radius:var(--radius-sm);
  box-shadow:var(--shadow-md);overflow:hidden;}
.ccSearch{width:100%;border:none;border-bottom:1px solid var(--border);border-radius:0;
  padding:9px 11px;font-size:12.5px;background:transparent;color:var(--text);}
.ccSearch:focus{outline:none;border-bottom-color:var(--accent);}
.ccList{max-height:210px;overflow-y:auto;}
.ccOpt{display:flex;align-items:center;gap:9px;width:100%;padding:8px 11px;
  border:none;background:transparent;cursor:pointer;text-align:left;font-family:inherit;
  font-size:12.5px;color:var(--text);}
.ccOpt:hover{background:var(--panel2);}
.ccOpt[aria-selected="true"]{background:var(--accent-soft);color:var(--accent-ink);font-weight:700;}
.ccOptName{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.ccOptCode{color:var(--muted);font-variant-numeric:tabular-nums;font-size:12px;}
.ccEmpty{padding:12px;font-size:12px;color:var(--muted);text-align:center;}
@media(max-width:700px){
  .ccTrigger{min-height:44px;}
  .ccOpt{padding:11px;}
}

/* Real flag images. A thin border keeps flags with white fields (Japan, Poland)
   from bleeding into a light background, and object-fit stops any one flag's
   aspect ratio from distorting the row. */
.ccFlagImg{width:20px;height:15px;object-fit:cover;border-radius:2px;
  border:1px solid rgba(128,128,128,.28);flex:none;display:block;}

/* Moat 1-10 score. The bar exists so the number is read against its scale --
   a bare "7" tells you nothing about whether the scale tops out at 7 or 10. */
.moatScoreBox{border:1px solid var(--border);border-radius:var(--radius-sm);
  background:var(--panel2);padding:14px;margin-bottom:12px;}
.moatScoreHead{display:flex;align-items:center;gap:16px;flex-wrap:wrap;}
.moatScoreNum{font-family:var(--display-font);font-size:38px;font-weight:800;line-height:1;letter-spacing:-.02em;}
.moatScoreMax{font-size:15px;font-weight:700;color:var(--muted);margin-left:2px;}
.moatScoreBarWrap{flex:1;min-width:170px;}
.moatScoreScale{font-size:11px;color:var(--muted);margin-top:6px;line-height:1.45;}
@media(max-width:700px){
  .moatScoreHead{gap:10px;}
  .moatScoreNum{font-size:30px;}
}

/* Long-term potential: verdict is uppercased in CSS, not in the stored string,
   so the underlying value still matches the JSON enum the prompt returns and
   any future comparison against it keeps working. */
.potentialVerdict{text-transform:uppercase;letter-spacing:.01em;}
.potentialHorizon{text-transform:uppercase;letter-spacing:.03em;font-size:11px!important;}

/* Quality-compounder screen table */
.qsTarget{color:var(--muted);font-variant-numeric:tabular-nums;white-space:nowrap;}
.qsNote{font-size:11px;color:var(--muted);margin-top:3px;line-height:1.45;}
.qsMark{display:inline-flex;align-items:center;justify-content:center;
  width:19px;height:19px;border-radius:50%;font-size:11px;font-weight:800;}
.qsMark.ok{background:color-mix(in srgb,var(--green) 18%,transparent);color:var(--green);}
.qsMark.no{background:color-mix(in srgb,var(--red) 18%,transparent);color:var(--red);}
.qsMark.unk{background:var(--panel3);color:var(--muted);}
@media(max-width:700px){
  /* Kept as a real table (noStack): four short columns already fit, and
     stacking nine rows into label/value pairs would quadruple its height for
     no gain. Only the target column is dropped -- it is the least scanned.

     Scoped to .qsTarget alone. This used to also carry a bare
     `.chkTable th:nth-child(2)`, which hit every table sharing .chkTable --
     the checklist summary and the Graham table included. Both keep their
     second BODY cell, so hiding only their second HEADER cell shifted their
     whole header one column left: "Cleared" vanished and "%" sat above the
     ratio column. The .qsTable block below already hides that column for the
     quality screen properly, header and body together. */
  .chkTable .qsTarget{display:none;}
}

/* The quality screen reuses .chkTable for its typography, but NOT its mobile
   column rules. The checklist hides its third column on narrow screens because
   there it is a progress bar duplicating the % beside it; in this table the
   third column is the ACTUAL FIGURE -- the whole point of the row. Restore it,
   and drop the target column instead, which is the one a reader can infer. */
@media(max-width:700px){
  .qsTable th:nth-child(3),.qsTable td:nth-child(3){display:table-cell;}
  .qsTable th:nth-child(2),.qsTable td:nth-child(2){display:none;}
  .qsTable td:first-child{font-size:12px;}
  .qsTable .num{width:auto;}
}

/* Quality screen column widths. Fixed layout with explicit widths so a long
   note in the first column or a long figure in the third cannot push the table
   past its container -- the failure that produced a page-wide horizontal
   scrollbar. The workings line wraps; only the headline figure stays on one. */
.qsTable{table-layout:fixed;width:100%;}
.qsTable th:nth-child(1),.qsTable td:nth-child(1){width:auto;}
.qsTable th:nth-child(2),.qsTable td:nth-child(2){width:86px;}
.qsTable th:nth-child(3),.qsTable td:nth-child(3){width:150px;}
.qsTable th:nth-child(4),.qsTable td:nth-child(4){width:42px;}
.qsActual{white-space:normal;vertical-align:top;}
.qsWorkings{font-size:10.5px;font-weight:400;color:var(--muted);margin-top:3px;
  line-height:1.4;white-space:normal;text-align:right;}
@media(max-width:700px){
  .qsTable th:nth-child(3),.qsTable td:nth-child(3){width:118px;}
  .qsTable th:nth-child(4),.qsTable td:nth-child(4){width:34px;}
}

/* Rows were overlapping: the metric cell is top-aligned while the workings
   wrap to two or three lines, so a long workings line ran into the row below.
   Align every cell to the top and give the row real vertical padding so the
   tallest cell sets the row height. */
.qsTable td{vertical-align:top;padding-top:11px;padding-bottom:11px;}
.qsTable td:first-child{line-height:1.45;}
.qsWorkings{max-width:100%;overflow-wrap:anywhere;}

/* Divider marking where the quality tests end and the valuation tests begin.
   The two answer different questions -- "is this a good business" versus "is it
   cheap today" -- and a company can legitimately pass one set and fail the
   other, so they must not read as one continuous score. */
.qsDivider td{padding:14px 0 6px!important;border-bottom:none!important;
  font-size:10px;font-weight:800;letter-spacing:.07em;text-transform:uppercase;
  color:var(--muted);}

/* The note under each metric inherited white-space:nowrap from the base table
   rule, so a long explanation (335px of text in a 223px cell) ran straight out
   of its column and printed over the figures to its right. Notes are prose --
   they wrap. */
.qsNote{white-space:normal;overflow-wrap:anywhere;}
.qsTable td:first-child{white-space:normal;}

/* SPECIFICITY FIX. `.chkTable .num` sets white-space:nowrap at (0,2,0); the
   earlier `.qsActual{white-space:normal}` was only (0,1,0) and silently lost,
   so long values ("Not meaningful / Negative Net Income") overflowed their
   150px cell by 27px and printed over the pass/fail mark. These selectors
   match or beat (0,2,0), so the figure column wraps as intended. */
.qsTable td.qsActual{white-space:normal;word-break:normal;overflow-wrap:anywhere;}
.qsTable td.qsActual .qsWorkings{white-space:normal;}
.qsTable td.num{white-space:normal;}

/* Editable target. Styled as text until hovered so the column still reads as a
   value rather than as a row of buttons -- the affordance appears when the
   pointer is on it, which is enough for a control most people will never touch. */
.qsTargetBtn{background:none;border:1px dashed transparent;border-radius:5px;
  padding:2px 6px;margin:-2px -6px;font:inherit;color:var(--muted);cursor:pointer;
  font-variant-numeric:tabular-nums;white-space:nowrap;}
.qsTargetBtn:hover{border-color:var(--accent);color:var(--accent-ink);}
.qsTargetBtn:focus-visible{outline:2px solid var(--accent);outline-offset:1px;}
.qsTargetBtn.fixed{cursor:default;border-color:transparent;}
.qsTargetBtn.fixed:hover{color:var(--muted);border-color:transparent;}

/* Graham Test tables (defensive-investor / enterprising-investor). Three
   columns -- Test, pass/fail mark, Detail -- not the quality screen's four, so
   .qsTable's nth-child widths don't apply and bare .chkTable left the mark
   column to auto table-layout, which sized it off the widest content in each
   table independently. The defensive and enterprising tables ended up with
   differently-sized mark columns and the badge drifted rather than forming a
   clean rail down the page. Fixed layout with explicit widths pins it down,
   and the mark is centred in its own narrow column (not right-aligned against
   the Detail column) since it sits between two text columns, not at the row's
   outer edge. Compound selector (.chkTable.grahamTable) so this wins over the
   base .chkTable rules regardless of source order. */
.chkTable.grahamTable{table-layout:fixed;width:100%;}
.chkTable.grahamTable th:nth-child(1),.chkTable.grahamTable td:nth-child(1){width:auto;}
.chkTable.grahamTable th:nth-child(2),.chkTable.grahamTable td:nth-child(2){
  width:40px;padding-left:0;padding-right:0;text-align:center;white-space:nowrap;}
.chkTable.grahamTable th:nth-child(3),.chkTable.grahamTable td:nth-child(3){width:38%;}
.chkTable.grahamTable td:nth-child(3){white-space:normal;overflow-wrap:anywhere;}
@media(max-width:700px){
  /* The generic .chkTable mobile rule (above) hides the 3rd column on the
     assumption it's a redundant progress bar -- true for the checklist
     summary table it was written for, but here column 3 is the Detail text,
     the evidence behind the pass/fail mark and the actual point of the row.
     Restore it and shrink the mark column further instead of hiding content. */
  .chkTable.grahamTable th:nth-child(3),.chkTable.grahamTable td:nth-child(3){
    display:table-cell;width:auto;}
  .chkTable.grahamTable th:nth-child(2),.chkTable.grahamTable td:nth-child(2){width:30px;}
}
.qsTargetInput{width:74px;padding:2px 6px;font:inherit;font-variant-numeric:tabular-nums;
  border:1px solid var(--accent);border-radius:5px;background:var(--panel);color:var(--text);}
.qsResetBtn{background:none;border:none;padding:0 0 0 8px;font:inherit;font-size:10px;
  font-weight:700;letter-spacing:.04em;text-transform:uppercase;color:var(--muted);
  cursor:pointer;text-decoration:underline;text-underline-offset:2px;}
.qsResetBtn:hover{color:var(--accent-ink);}

/* The customise hint sits under the screen's label, small and grey -- it is an
   affordance note, not a control, so it must not compete with the score beside
   it. white-space:normal because the score column is narrow. */
.qsHint{font-size:10.5px;font-weight:500;letter-spacing:0;text-transform:none;
  color:var(--muted);margin-top:4px;line-height:1.45;white-space:normal;max-width:190px;}
.qsHint .qsResetBtn{font-size:10.5px;text-transform:none;letter-spacing:0;padding:0;}

/* "QUALITY-COMPOUNDER SCREEN" is the heading for the whole block, but it was
   inheriting .chkScoreLabel -- a 11px caption sized to sit under a big number
   as a subtitle. Given its own size so it reads as a section title, with the
   caps and tracking kept so it still matches the other headings on the page. */
#potentialBody .chkScoreLabel{font-size:19px;letter-spacing:.04em;color:var(--accent-ink);}
@media(max-width:700px){
  #potentialBody .chkScoreLabel{font-size:16px;}
}

/* Evidence line inside a Six Brand Moats row: reading ink, not label grey,
   because it carries the actual facts; separated from the grey gist above it
   by a small gap so the two do not read as one caption. */
.bmEvidence{font-size:12.5px;line-height:1.55;color:var(--text);margin-top:6px;white-space:normal;}

/* Inside a stacked row the whole first cell inherits the identity styling
   (font-weight:800), which bolded the brand-moat evidence and gist wholesale --
   and once everything is bold, the **emphasised** figures inside the evidence
   vanish into it. The name keeps its weight; the prose under it returns to
   normal so bold means something again. */
@media(max-width:700px){
  table.stackable tbody tr td:first-child .qsNote,
  table.stackable tbody tr td:first-child .bmEvidence{font-weight:400;font-size:12px;}
  table.stackable tbody tr td:first-child .bmEvidence strong{font-weight:800;}
}

/* ============================================================
   INTRO SPLASH -- the name alone, then the site.
   ============================================================
   Timing is the whole design here: 1.7s total. Long enough to register the
   name, short enough that a returning visitor never feels held up -- and it
   only plays ONCE per browser session (see app.js), because a splash on every
   navigation is the fastest way to make people hate a site.

   Everything is CSS animation with fill-mode:forwards, so the overlay clears
   itself even if JavaScript never runs. Script can only dismiss it sooner. */
.splash{position:fixed;inset:0;z-index:9999;display:flex;flex-direction:column;
  align-items:center;justify-content:center;gap:14px;background:var(--bg);
  animation:splashFade .55s cubic-bezier(.4,0,.2,1) 1.15s forwards;}
/* visibility (not just opacity) so the finished overlay stops intercepting
   clicks -- an invisible layer over the page would break every button. */
@keyframes splashFade{to{opacity:0;visibility:hidden;}}

.splashMark{font-family:'Fraunces',Georgia,'Times New Roman',serif;font-optical-sizing:auto;
  font-size:clamp(34px,7vw,58px);font-weight:600;letter-spacing:.28em;text-transform:uppercase;
  line-height:1;padding-right:.28em;
  background:linear-gradient(100deg,
    #8a6420 0%, #c9992f 14%, #f2dc9e 30%, #ffffff 38%, #f2dc9e 46%,
    #d4a13f 58%, #a87c28 74%, #e8c86f 88%, #c9992f 100%);
  background-size:260% 100%;background-position:120% 50%;
  -webkit-background-clip:text;background-clip:text;color:transparent;
  filter:drop-shadow(0 0 26px rgba(212,161,63,.3));
  /* Rises and settles, then the same highlight sweep used on the masthead --
     so the first thing a visitor sees is exactly how the logo behaves later. */
  animation:splashRise .85s cubic-bezier(.22,.8,.3,1) both,
            wordmarkSheen 6s cubic-bezier(.45,0,.25,1) .35s infinite;}
@keyframes splashRise{from{opacity:0;transform:translateY(14px) scale(.97);letter-spacing:.42em;}
                      to{opacity:1;transform:none;letter-spacing:.28em;}}

/* A hairline that draws itself outward under the name: motion that reads as
   "opening" rather than "loading", which is the feeling wanted here. */
.splashRule{height:1px;width:0;background:linear-gradient(90deg,transparent,#d4a13f,transparent);
  animation:splashRuleGrow .9s cubic-bezier(.22,.8,.3,1) .25s forwards;}
@keyframes splashRuleGrow{to{width:min(260px,42vw);}}

/* Skip entirely for anyone who asked for less motion, and for repeat visits
   (app.js adds .splashDone). Display:none rather than a fast animation so
   there is no flash of the overlay at all. */
.splash.splashDone{display:none;}
@media(prefers-reduced-motion:reduce){.splash{display:none;}}

/* ---- Free-tier section locks ----
   A locked section stays VISIBLE and readable rather than hidden: seeing the
   Moat and Valuation headings with their explanation is what makes the paid
   plan concrete. Only the inputs are unusable. */
.lockNotice{display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  background:color-mix(in srgb,var(--accent) 7%,var(--panel2));
  border:1px solid color-mix(in srgb,var(--accent) 30%,transparent);
  border-radius:var(--radius-sm);padding:10px 13px;margin:0 0 12px;font-size:12.5px;}
.lockNoticeIcon{display:inline-flex;color:var(--accent);flex:none;}
.lockNoticeText{flex:1;min-width:200px;color:var(--muted);line-height:1.5;}
.lockNoticeBtn{flex:none;}

/* Dim and de-interact the section body, but leave the lock notice at full
   strength -- the one thing in a locked section that must stay legible is the
   explanation of why it is locked. */
/* Blurred past reading, not merely dimmed: at 40% opacity the text was still
   perfectly legible, which gave the paid sections away. The heading and the
   lock notice stay sharp so the reader knows what they are looking at and how
   to unlock it. */
.sectionLocked > *:not(.lockNotice):not(h3){
  filter:blur(7px) saturate(.45);opacity:.55;
  pointer-events:none;user-select:none;
  transform:scale(.998);   /* hides the soft edge blur leaves at the bounds */
}
.sectionLocked > h3{opacity:.85;}
@media(max-width:640px){.sectionLocked > *:not(.lockNotice):not(h3){filter:blur(5px) saturate(.45);}}
/* Reduced-motion users still get the blur -- it is a privacy control, not an
   effect -- but no scaling. */
@media(prefers-reduced-motion:reduce){.sectionLocked > *:not(.lockNotice):not(h3){transform:none;}}

/* Locked entries in the jump nav: a small padlock, so it is obvious before
   clicking rather than after. */
/* Locked: unmistakably unavailable, and it does not open the section --
   the click goes to the upgrade page instead. */
.ddNav button.navLocked{opacity:.42;cursor:not-allowed;color:var(--muted-dim);}
.ddNav button.navLocked:hover{color:var(--accent);border-color:transparent;background:none;opacity:.65;}
.ddNav button.navLocked::after{content:'\1F512';font-size:9px;margin-left:5px;opacity:.8;}

/* Plain-language explanation under a metric heading. Distinct from .hint
   (which carries sourcing and caveats in small grey type): this is the
   primary read for someone meeting the metric for the first time, so it gets
   body-text size, a comfortable measure, and a gold rule to mark it as
   guidance rather than data. */
.metricExplain{margin:6px 0 12px;padding-left:12px;max-width:78ch;
  border-left:2px solid color-mix(in srgb,var(--accent) 45%,transparent);
  font-size:13px;line-height:1.65;color:var(--muted);}
.metricExplain + .hint{margin-top:-4px;}

/* Section headings inside Quality Scores. The shared .card h3 is 12px grey
   uppercase -- right for a minor label, far too quiet for what are really
   distinct analyses stacked in one card. Gold and larger so each block reads
   as its own section, with real space above to separate it from the table
   that ended the previous one. */
#companyQuality h3{font-family:var(--display-font);font-size:16px;font-weight:800;
  letter-spacing:-.01em;text-transform:none;color:var(--accent);
  margin:38px 0 4px;padding-top:20px;border-top:1px solid var(--border);
  text-shadow:0 0 16px rgba(201,154,53,.13);}
/* The first heading follows the F-Score block, not a table, so it needs less
   air above and no rule -- the block boundary is already obvious there. */
#companyQuality h3:first-of-type{margin-top:26px;padding-top:0;border-top:none;}

/* .authForm makes inputs full-width (radios/checkboxes are already excluded),
   so the checkbox only needs to be pulled inline with its label. Alignment is
   stated explicitly -- justify/text-align/width are all pinned so the row sits
   hard against the left edge of the form regardless of what any inherited or
   later rule tries to do to it. */
/* Pinned left. This row has drifted twice -- once from a stray margin:0
   override, once from a mobile `input{min-width:120px}` that stretched the
   checkbox to 120px and pushed the label into the middle -- so every property
   that could move it is stated here, scoped tightly enough to win. */
.authForm .rememberRow,.rememberRow{display:flex;align-items:center;justify-content:flex-start;
  gap:8px;margin:12px 0 0;width:100%;max-width:100%;text-align:left;padding:0;
  font-size:13px;color:var(--muted);cursor:pointer;user-select:none;}
.authForm .rememberRow input[type="checkbox"],.rememberRow input{flex:0 0 auto;
  width:15px;min-width:15px;max-width:15px;height:15px;
  accent-color:var(--accent);cursor:pointer;margin:0;}
/* The label must not stretch and centre its own text. */
.authForm .rememberRow span,.rememberRow span{flex:0 1 auto;text-align:left;margin:0;}

/* The checklist card carries a named product feature rather than a section
   label, so its heading is set larger than the standard 16px .card h2 and
   given room beneath before the purpose line. */
#companyChecklist > h2{font-size:23px;letter-spacing:-.02em;margin-bottom:10px;line-height:1.2;}
/* The purpose line is the first thing read on this page, so it gets breathing
   room on both sides rather than the tighter default .metricExplain spacing
   used where these blocks sit between dense tables. */
#companyChecklist > .metricExplain{margin:20px 0 28px;padding-top:2px;padding-bottom:2px;}

/* ---- User-added checklist questions ---- */
/* An added question is a normal row -- same checkbox, same weight in the score
   -- so it is marked only by a small tag and a remove control, not by a
   different row style that would make it read as less important. */
.ddCustomTag{display:inline-block;margin-left:8px;padding:1px 6px;border-radius:999px;
  font-size:10px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;
  color:var(--accent);background:color-mix(in srgb,var(--accent) 14%,transparent);
  border:1px solid color-mix(in srgb,var(--accent) 30%,transparent);vertical-align:middle;}
.ddRemoveQ{margin-left:8px;padding:0 6px;border:none;background:none;cursor:pointer;
  color:var(--muted-dim);font-size:16px;line-height:1;border-radius:4px;vertical-align:middle;}
.ddRemoveQ:hover{color:var(--bad,#e5484d);background:color-mix(in srgb,currentColor 12%,transparent);}

.ddAddQuestion{margin:8px 0 4px;}
.ddAddQBtn{background:none;border:1px dashed var(--border);border-radius:var(--radius-sm);
  color:var(--muted);cursor:pointer;font-family:inherit;font-size:12.5px;font-weight:600;
  padding:7px 12px;transition:border-color .15s,color .15s;}
.ddAddQBtn:hover{border-color:color-mix(in srgb,var(--accent) 55%,transparent);color:var(--accent);}
.ddAddQForm{display:flex;flex-direction:column;gap:8px;padding:10px;border-radius:var(--radius-sm);
  border:1px solid color-mix(in srgb,var(--accent) 28%,transparent);
  background:color-mix(in srgb,var(--accent) 5%,transparent);}
.ddAddQInput{width:100%;font-family:inherit;font-size:13px;}
.ddAddQActions{display:flex;align-items:center;gap:10px;}
.ddAddQActions .btn{padding:6px 14px;font-size:12.5px;}
.ddAddQError{margin:0;font-size:12px;color:var(--bad,#e5484d);}

/* ---- Monitoring walkthrough ---- */
/* A docked coach panel rather than a modal: the point is to watch the section
   fill in while you read, so the page behind must stay visible and usable. */
.tourPanel{position:fixed;right:20px;bottom:20px;z-index:120;width:min(400px,calc(100vw - 40px));
  max-height:min(70vh,640px);overflow-y:auto;padding:16px 18px 14px;
  background:var(--panel);border:1px solid color-mix(in srgb,var(--accent) 42%,transparent);
  border-radius:var(--radius-md);box-shadow:0 18px 48px -12px rgba(0,0,0,.6);}
.tourHead{display:flex;align-items:center;justify-content:space-between;margin-bottom:6px;}
.tourCount{font-size:10.5px;font-weight:800;letter-spacing:.10em;text-transform:uppercase;color:var(--accent);}
.tourClose{background:none;border:none;color:var(--muted);font-size:20px;line-height:1;cursor:pointer;padding:0 2px;border-radius:4px;}
.tourClose:hover{color:var(--text);}
.tourTitle{margin:0 0 8px;font-family:var(--display-font);font-size:16px;font-weight:800;
  letter-spacing:-.01em;color:var(--accent);text-transform:none;}
.tourBody{font-size:13px;line-height:1.65;color:var(--text);}
.tourBody p{margin:9px 0 0;}
.tourBody em{color:var(--muted);}
.tourNote{color:var(--muted);font-size:12px;}
.tourFoot{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-top:14px;
  padding-top:12px;border-top:1px solid var(--border);}
.tourFoot .tourBack:disabled{opacity:.35;cursor:default;}
.tourFoot .btn{padding:7px 20px;}

/* The element being explained. outline (not border) so nothing reflows as the
   highlight moves from step to step. */
.tourTarget{outline:2px solid var(--accent);outline-offset:6px;border-radius:6px;
  animation:tourPulse 1.6s ease-in-out infinite;}
@keyframes tourPulse{0%,100%{outline-color:color-mix(in srgb,var(--accent) 95%,transparent);}
  50%{outline-color:color-mix(in srgb,var(--accent) 35%,transparent);}}
@media(prefers-reduced-motion:reduce){.tourTarget{animation:none;}}

@media(max-width:640px){
  .tourPanel{right:10px;left:10px;bottom:10px;width:auto;max-height:62vh;}
}
/* The walkthrough button sits on its own line under the section intro, with
   clear air on both sides so it never crowds the text around it. */
.teachMeRow{margin:18px 0 26px;}
/* Leaving the walkthrough has to look as available as continuing it, or the
   panel reads as a wizard you are obliged to finish. */
.tourFootLeft{display:flex;align-items:center;gap:14px;}
.tourSkip{color:var(--muted-dim);}
.tourSkip:hover{color:var(--text);}

/* ---- Pricing: what each tier adds that the one below does not ---- */
/* A buyer comparing three near-identical lists cannot see what the extra
   money buys. These mark the difference explicitly. */
/* Beats .priceFeatures li, which sets the padding and the tick pseudo-element. */
.priceFeatures li.priceGroupLabel{padding:14px 0 2px;border-top:none;
  font-size:9.5px;font-weight:800;letter-spacing:.12em;text-transform:uppercase;
  color:var(--accent);}
.priceFeatures li.priceGroupLabel::before{content:none;}
.priceFeatures li.priceExclusive{color:var(--text);font-weight:600;}

/* ---- Pricing cards in caps ---- */
/* Uppercase carries a slight legibility cost on long lines, so the tracking is
   opened up and the weight lifted to compensate. */
#pricing .priceFeatures li,
#pricing .priceFor,
#pricing .priceNote,
#pricing .priceReports .u,
#pricing .priceBadge,
#pricing .priceName{text-transform:uppercase;letter-spacing:.045em;}
#pricing .priceFeatures li{font-size:12px;line-height:1.65;font-weight:600;}
#pricing .priceFeatures li.priceExclusive{font-weight:700;}
#pricing .priceFor{font-size:11.5px;font-weight:700;}



/* ---- Settings: reviews listing ---- */
.settingsReviewRow{display:flex;gap:14px;padding:14px 0;border-top:1px solid var(--border);}
.settingsReviewRow:first-child{border-top:none;}
.settingsReviewMain{flex:1;min-width:0;}
.settingsReviewQuote{margin:6px 0 6px;font-size:13px;line-height:1.6;color:var(--text);}
.settingsReviewWho{font-size:11.5px;color:var(--muted-dim);}
.settingsReviewStars{display:flex;gap:2px;}
.settingsReviewStars .rStar{display:inline-flex;color:var(--border);}
.settingsReviewStars .rStar svg{fill:currentColor;width:12px;height:12px;}
.settingsReviewStars .rStar.on{color:var(--accent);}
.settingsReviewCount{font-size:12px;color:var(--muted);margin:2px 0 14px;}
/* Half stars in the Settings listing, same technique as the landing cards. */
.settingsReviewStars .rStar{position:relative;line-height:0;}
.settingsReviewStars .rStar svg{display:block;}
.settingsReviewStars .rStar.half > .rStarFill{position:absolute;top:0;left:0;width:50%;
  overflow:hidden;color:var(--accent);line-height:0;}

/* ---- Leave a review (Settings) ---- */
.reviewForm{margin-top:16px;}
.reviewForm select,.reviewForm textarea,.reviewForm input[type="text"]{width:100%;font-family:inherit;}
.reviewForm textarea{resize:vertical;min-height:110px;line-height:1.6;}
.reviewCount{margin-top:4px;text-align:right;font-size:11px;color:var(--muted-dim);}
.reviewStatus{font-size:12.5px;color:var(--muted);}
.reviewStatus.ok{color:var(--green,#7fd1a6);}
.reviewStatus.bad{color:var(--bad,#e5484d);}
/* The header upgrade button: gold, so it reads as the one action that costs
   money rather than blending into Profile/Settings. */
#upgradeBtn{background:var(--grad);color:var(--on-grad);border:none;font-weight:700;}
#upgradeBtn:hover{filter:brightness(1.06);}

/* ---- Company banner ---- */
/* Once you are inside a company, which company you are inside is the single
   most important thing on screen -- previously it was only legible in the
   search box further up the page. */
.companyBanner{display:flex;align-items:flex-end;justify-content:space-between;gap:18px;
  flex-wrap:wrap;margin:var(--space-5) 0 var(--space-3);padding-bottom:14px;
  border-bottom:1px solid var(--border);}
.companyBannerMain{min-width:0;}
.companyBannerName{margin:0;font-family:var(--display-font);font-size:clamp(26px,3.4vw,40px);
  font-weight:800;letter-spacing:-.025em;line-height:1.1;color:var(--text);}
.companyBannerName .cbTicker{color:var(--accent);}
.companyBannerMeta{margin-top:6px;font-size:12.5px;color:var(--muted);
  display:flex;flex-wrap:wrap;gap:6px 14px;}
.companyBannerMeta .cbDot{color:var(--muted-dim);}
@media(max-width:640px){
  .companyBanner{align-items:flex-start;flex-direction:column;gap:10px;}
  .companyBannerName{font-size:26px;}
}

/* ---- Upgrade page ---- */
/* Uses the landing page's own .pricingGrid/.priceCard, so prices and features
   can never drift between what a visitor sees and what a subscriber sees. */
.upgradeHead{max-width:760px;margin:var(--space-6) auto var(--space-5);text-align:center;}
.upgradeTitle{margin:0 0 10px;font-family:var(--display-font);font-size:clamp(24px,3vw,34px);
  font-weight:800;letter-spacing:-.02em;line-height:1.15;color:var(--text);}
.upgradeSub{margin:0;font-size:14px;line-height:1.7;color:var(--muted);}
.upgradeCurrent{margin-top:16px;padding:10px 16px;display:inline-block;font-size:13px;
  color:var(--text);background:var(--panel2);border:1px solid var(--border);border-radius:999px;}
.upgradeCurrent:empty{display:none;}
/* Its own centred container: .pricingGrid is a four-column landing layout, and
   three cards inside the app's narrower shell came out cramped. */
#view-upgrade{max-width:1120px;margin:0 auto;padding:0 20px;}
.upgradeGrid{grid-template-columns:repeat(3,1fr) !important;gap:22px;margin-bottom:var(--space-6);}
.upgradeGrid .priceCard{padding:28px 24px 24px;}
.upgradeGrid .priceAmount{font-size:clamp(30px,3.4vw,40px);}
.upgradeGrid .priceFeatures li{font-size:12.5px;line-height:1.6;}
.upgradeGrid .btnLg{margin-top:auto;}
@media(max-width:900px){.upgradeGrid{grid-template-columns:1fr !important;max-width:460px;margin-inline:auto;}}
.upgradeNote{max-width:760px;margin:0 auto var(--space-6);text-align:center;
  font-size:12.5px;line-height:1.7;color:var(--muted-dim);}
#view-upgrade [data-upgrade]:disabled{opacity:.5;cursor:default;}

/* Remaining reports, shown large beside the company name. The header pill is
   easy to miss; this sits where the decision to spend one is actually made. */
.companyBannerRight{display:flex;align-items:center;gap:12px;flex:none;}
.bannerQuota{display:flex;align-items:center;gap:10px;padding:8px 14px;cursor:pointer;
  background:var(--panel2);border:1px solid var(--border);border-radius:var(--radius-md);
  color:var(--text);font-family:inherit;text-align:left;transition:border-color .15s;}
.bannerQuota:hover{border-color:var(--accent);}
.bannerQuota .bqNum{font-family:var(--display-font);font-size:26px;font-weight:800;
  line-height:1;color:var(--accent);}
.bannerQuota .bqLabel{font-size:10.5px;line-height:1.35;color:var(--muted);
  text-transform:uppercase;letter-spacing:.04em;font-weight:700;}
.bannerQuota.low{border-color:color-mix(in srgb,#e8b34a 55%,transparent);}
.bannerQuota.low .bqNum{color:#e8b34a;}
.bannerQuota.out{border-color:color-mix(in srgb,#e5484d 55%,transparent);}
.bannerQuota.out .bqNum{color:#e5484d;}
@media(max-width:640px){.companyBannerRight{width:100%;justify-content:space-between;}}
/* The wordmark doubles as the way home, as every user expects it to.
   It inherits the gradient/sheen from .wordmark; the only additions are the
   uppercase (a <button> will not reliably inherit text-transform) and a
   pointer. Deliberately NO hover opacity change -- dimming the brand made it
   look like it was disappearing. */
.brandHomeBtn{background:none;border:none;padding:0;margin:0;cursor:pointer;
  font:inherit;color:inherit;letter-spacing:inherit;line-height:inherit;
  text-transform:uppercase;-webkit-font-smoothing:inherit;
  background-image:inherit;-webkit-background-clip:inherit;background-clip:inherit;
  -webkit-text-fill-color:inherit;animation:inherit;}
.brandHomeBtn:hover{opacity:1;}
.brandHomeBtn:focus-visible{outline:2px solid var(--accent);outline-offset:4px;border-radius:4px;}

/* ---- Hub and zoom ---- */
/* HUB: the three choices stand alone, with no section content beneath them,
   so the page reads as "pick one" rather than as a tab strip. */
.hubMode > #view-data,
.hubMode > #view-report,
.hubMode > #view-checklist{display:none !important;}
/* position:static matters. As a tab strip .pageNav is sticky with an opaque
   panel background, which is fine -- it pins to the top and hides what scrolls
   under it. In hub mode it is not a tab strip, it IS the page content, and the
   background is stripped to none. Left sticky, it pinned a transparent block
   over the page and everything scrolling beneath showed through the gaps
   between the three cards. Worst when narrow, because the cards stack and the
   block grows tall enough to cover most of the viewport. */
.hubMode > .pageNav{display:grid !important;grid-template-columns:repeat(3,1fr);gap:14px;
  position:static;box-shadow:none;
  background:none;border:none;padding:0;margin:var(--space-4) 0 var(--space-6);}
.hubMode > .pageNav .pageTab{display:flex;flex-direction:column;align-items:flex-start;
  justify-content:center;gap:6px;min-height:104px;padding:22px 22px;
  background:var(--panel);border:1px solid var(--border);border-radius:var(--radius-md);
  font-family:var(--display-font);font-size:17px;font-weight:800;letter-spacing:-.01em;
  color:var(--text);transition:border-color .16s ease,transform .16s ease,background .16s ease;}
.hubMode > .pageNav .pageTab:hover{border-color:var(--accent);transform:translateY(-2px);
  background:var(--panel2);}
.hubMode > .pageNav .pageTab.active{background:var(--panel);color:var(--text);}
.hubMode > .pageNav .pageTab::after{content:'\2192';color:var(--accent);font-size:19px;font-weight:700;}

/* ZOOM: one section fills the page; the chooser and the way-in chrome step out. */
/* My Research stays visible inside a section -- switching companies is
   something you do FROM the report, not only from the landing page. */
.zoomMode > #searchCard,
.zoomMode > .emptyState,
.zoomMode > .pageNav{display:none !important;}
.zoomBar{display:flex;align-items:center;gap:16px;margin:var(--space-4) 0 var(--space-3);
  padding-bottom:12px;border-bottom:1px solid var(--border);}
.zoomBack{display:inline-flex;align-items:center;gap:7px;padding:8px 14px;cursor:pointer;
  background:var(--panel2);border:1px solid var(--border);border-radius:999px;
  color:var(--muted);font-family:inherit;font-size:12.5px;font-weight:700;
  transition:color .15s,border-color .15s;}
.zoomBack:hover{color:var(--accent);border-color:var(--accent);}
.zoomTitle{font-family:var(--display-font);font-size:15px;font-weight:800;
  letter-spacing:.02em;text-transform:uppercase;color:var(--accent);}
@media(max-width:760px){
  .hubMode > .pageNav{grid-template-columns:1fr;gap:10px;}
  .hubMode > .pageNav .pageTab{min-height:0;padding:18px;flex-direction:row;
    align-items:center;justify-content:space-between;}
}
/* Hub choice cards: a soft gold glow on hover so the whole box reads as the
   click target, not just the arrow. */
.hubMode > .pageNav .pageTab{position:relative;}
.hubMode > .pageNav .pageTab:hover{border-color:var(--accent);
  box-shadow:0 0 0 1px color-mix(in srgb,var(--accent) 45%,transparent),
             0 10px 34px -14px rgba(0,0,0,.7),
             0 0 26px -6px color-mix(in srgb,var(--accent) 42%,transparent);}
.hubMode > .pageNav .pageTab:hover::after{transform:translateX(3px);}
.hubMode > .pageNav .pageTab::after{transition:transform .16s ease;}
@media(prefers-reduced-motion:reduce){
  .hubMode > .pageNav .pageTab,
  .hubMode > .pageNav .pageTab::after{transition:none;}
  .hubMode > .pageNav .pageTab:hover{transform:none;}
}

/* ---- Two-action analyze ---- */
/* One company name, two buttons, each carrying its price. Loading live data
   was always free and only the research spent a report, but a single
   "Analyze Company" button gave no way to tell which click was which. */
.analyzeActions{display:flex;gap:10px;flex:none;}
.analyzeActions .btn{white-space:nowrap;}
.analyzeHint{margin:10px 0 0;font-size:12px;line-height:1.6;color:var(--muted-dim);}
@media(max-width:640px){
  .analyzeActions{width:100%;}
  .analyzeActions .btn{flex:1;}
}

/* ---- Hover glow on cards ---- */
/* Every card lifts slightly and picks up a soft gold rim under the cursor, so
   the thing you are pointing at is obvious without clicking it. */
.card{transition:border-color .18s ease, box-shadow .18s ease, transform .18s ease;}
.card:hover{border-color:color-mix(in srgb,var(--accent) 42%,transparent);
  box-shadow:0 0 0 1px color-mix(in srgb,var(--accent) 22%,transparent),
             0 14px 38px -18px rgba(0,0,0,.65),
             0 0 30px -10px color-mix(in srgb,var(--accent) 34%,transparent);}
/* A locked section must not look invitingly clickable. */
.card:has(> .sectionLocked):hover,
.sectionLocked:hover{box-shadow:none;border-color:var(--border);}
@media(prefers-reduced-motion:reduce){.card{transition:none;}}

/* The app-header wordmark carries the same sheen as the landing one, so the
   brand behaves identically in both places. */
.brandHomeBtn{
  background-image:var(--grad);
  -webkit-background-clip:text;background-clip:text;
  -webkit-text-fill-color:transparent;color:transparent;
  background-size:220% 100%;
  animation:wordmarkSheen 6s cubic-bezier(.45,0,.25,1) .35s infinite;}
@media(prefers-reduced-motion:reduce){.brandHomeBtn{animation:none;}}

/* Disclosure bodies get room once opened. */
.settingsDisclosure > .disclosureBody{padding-top:4px;}

/* ---- Provider buttons hidden ---- */
/* Every section used to offer "Research with Claude" / "Research with Gemini",
   asking the investor to choose an engine they have no basis to choose
   between, and putting two vendors' brands through the whole product. The pair
   is hidden and replaced by one button named after what it does.
   The originals still work: localStorage.corva_show_providers = '1' brings
   them back for debugging. */
[data-provider-ui]{display:none !important;}
html.showProviders [data-provider-ui]{display:inline-flex !important;}
html.showProviders .providerProxy{display:none !important;}
/* The PER-SECTION research buttons are redundant now that one press runs
   everything the plan opens, so they stay hidden. The main one is not
   per-section -- it is the button that runs the report -- and this rule was
   swallowing it too, leaving the report page with no way to start research at
   all. Excluded by its proxy target. */
.providerProxy:not([data-proxy-for="ddAutoResearchBtn"]){display:none !important;}
html.showProviders .providerProxy{display:none !important;}

/* ---- Thesis points & ESG as prose ---- */
/* Both are drafted for the reader rather than typed by them, so they render as
   prose and only become textareas when clicked. A fixed-height box clipping
   its own sentence was the wrong default. */
.thesisRow{display:flex;align-items:flex-start;gap:14px;}
.thesisBullet{flex:none;width:7px;height:7px;margin-top:11px;border-radius:50%;
  background:var(--grad);box-shadow:0 0 10px -1px color-mix(in srgb,var(--accent) 70%,transparent);}
.thesisBody{flex:1;min-width:0;}
.ddProseView.thesisView{display:block;min-height:0;padding:10px 14px;margin:0;
  background:transparent;border:1px solid transparent;font-size:14px;line-height:1.72;
  color:var(--text);cursor:text;}
.ddProseView.thesisView:hover{border-color:var(--border);background:var(--panel2);}
.ddProseView.thesisView .ddProsePara{margin:0 0 8px;}
.ddProseView.thesisView .ddProsePara:last-child{margin-bottom:0;}
.ddProseView.esgProseView{display:block;min-height:0;padding:12px 14px;font-size:13.5px;
  line-height:1.75;cursor:text;}
.ddProseView.esgProseView .ddProsePara{margin:0 0 9px;}
.ddProseView.esgProseView .ddProsePara:last-child{margin-bottom:0;}

/* Explainer for the two DCF assumptions. Collapsed by default: it must not
   push the inputs down the page for someone who already knows what WACC is,
   but the numbers are consequential enough that a first-time reader needs
   somewhere to look other than a search engine. */
.valGuide{margin:2px 0 14px;}
.valGuide summary{font-size:12.5px;color:var(--accent);font-weight:700;}
.valGuideBody{margin-top:10px;padding:14px 16px;background:var(--panel2);
  border:1px solid var(--border);border-radius:var(--radius-md);
  font-size:13px;line-height:1.62;color:var(--muted);max-width:78ch;}
.valGuideBody h4{margin:16px 0 6px;font-family:var(--display-font);font-size:13.5px;
  font-weight:800;letter-spacing:.01em;color:var(--text);}
.valGuideBody h4:first-child{margin-top:0;}
.valGuideBody p{margin:0 0 9px;}
.valGuideBody strong{color:var(--text);}
.valGuideRange{padding:8px 11px;background:var(--panel3);border-radius:var(--radius-sm);}
.valGuideWarn{margin:14px 0 9px;padding:10px 12px;border-left:2px solid var(--amber,var(--accent));
  background:color-mix(in srgb,var(--amber,var(--accent)) 8%,transparent);
  border-radius:0 var(--radius-sm) var(--radius-sm) 0;}

/* ---- Brand mark in the app header ----
   Lives INSIDE the home button so the whole lockup is one click target. The
   button clips its gradient to text, so the SVG must opt back out of that or
   its fill goes transparent. */
.appBrand .brandHomeBtn{display:inline-flex;align-items:center;gap:10px;}
.appBrand .brandMark{flex:none;-webkit-text-fill-color:initial;background:none;
  filter:drop-shadow(0 1px 0 rgba(0,0,0,.45)) drop-shadow(0 0 12px rgba(212,161,63,.30));}
