/* ============================================================
   EKPA — "The Ledger"
   Tokens are the law: no one-off colors, faces, or spacing.
   Teal ink + blue on pale-teal paper — private-bank stationery.
   Color only ever means something:
     --navy (blue) = you can act here · --gold (deep teal) = the house accent ·
     gain/loss = money moved
   ============================================================ */

:root {
  color-scheme: light;

  /* palette */
  --paper: #daecec;
  --ink: #182f2f; /* near-black teal — headings and primary text */
  --ink-soft: #264443; /* long-form reading text */
  --slate: #4d6564;
  --rule: #c0d8d8;
  --navy: #254d79; /* slate blue — interactive / primary ("you can act here") */
  --navy-deep: #1d3e63; /* blue hover */
  --gold: #305e5f; /* deep teal — the house accent (token name kept from the canary era) */
  --gold-deep: #24494a; /* darker teal that must carry contrast on paper (accent text) */
  --gold-soft: #bfdfdf; /* soft teal tint (active tabs, chips, selection) */
  --gain: #156b3f;
  --loss: #a8402f;

  /* type — reducto-style: serif headlines, squarish sans everywhere else */
  --font-display: "Newsreader", Georgia, "Times New Roman", serif;
  --font-brand: "Wix Madefor Display", "Wix Madefor Text", -apple-system, sans-serif;
  --font-body: "Wix Madefor Text", -apple-system, "Segoe UI", sans-serif;
  --font-mono: "Reddit Mono", ui-monospace, monospace;

  /* spacing scale */
  --s1: 4px;
  --s2: 8px;
  --s3: 12px;
  --s4: 16px;
  --s5: 24px;
  --s6: 32px;
  --s7: 48px;
  --s8: 72px;

  --ring: 0 0 0 3px rgba(37, 77, 121, 0.3);

  /* card surfaces — shared by landing artifacts today, app refresh later.
     (.app-frame re-maps --card/--radius/--shadow; these are the global names.) */
  --card-bg: #f6fbfb;
  --card-bg-2: #e9f3f3;
  --radius-card: 16px;
  --shadow-card: 0 12px 28px -18px rgba(24, 47, 47, 0.2);
}

* {
  box-sizing: border-box;
}

[hidden] {
  display: none !important;
}

html {
  scrollbar-color: var(--rule) var(--paper);
}

body {
  margin: 0;
  min-width: 320px;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 15.5px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3 {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -0.01em;
}

button,
input {
  font: inherit;
}

button {
  cursor: pointer;
}

button:disabled,
input:disabled {
  cursor: not-allowed;
  opacity: 0.5;
}

:focus-visible {
  outline: none;
  box-shadow: var(--ring);
  border-radius: 2px;
}

.mono {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}

.positive {
  color: var(--gain);
}

.negative {
  color: var(--loss);
}

/* ---------- Wordmark & bars ---------- */

.wordmark {
  font-family: var(--font-brand);
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -0.01em;
}

.wordmark-dot {
  color: var(--gold);
}

.site-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s5);
  max-width: 1080px;
  margin: 0 auto;
  padding: var(--s5) var(--s5) var(--s4);
}

.bar-nav {
  display: flex;
  align-items: center;
  gap: var(--s4);
}

/* ---------- App chrome: utility row, greeting, floating tab nav ----------
   One column. The utility row and greeting sit above the nav and scroll away;
   the nav row alone sticks. All three are direct children of .app-frame so the
   sticky nav's containing block is the whole frame, not a chrome wrapper that
   would end an inch below it. */

.app-frame {
  min-height: 100vh;
}

/* The utility row runs full-bleed: the wordmark and the session cluster belong
   to the page's corners, not to the content column. Everything below it —
   greeting, nav, main — shares one centered axis instead. */
.chrome-utility {
  display: flex;
  align-items: center;
  gap: var(--s4);
  /* Wraps only at the very narrow end (~320px), where the cluster drops to its
     own right-aligned line rather than breaking "Log out" across two. */
  flex-wrap: wrap;
  padding: var(--s5) var(--s7) 0;
}

/* Session state, quietly: the connection pill, the address, and the way out. */
.chrome-account {
  display: flex;
  align-items: center;
  gap: var(--s4);
  margin-left: auto;
  color: var(--slate);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.03em;
  white-space: nowrap;
}

/* Centered on the same axis as the nav and the main column below it. */
.chrome-greet {
  width: 100%;
  max-width: 960px;
  margin: 0 auto;
  padding: var(--s4) var(--s5) 0;
  text-align: center;
}

.chrome-title {
  margin: 0;
  font-family: var(--font-display);
  font-size: clamp(28px, 3.2vw, 36px);
  font-weight: 500;
  line-height: 1.1;
  letter-spacing: -0.01em;
}

.nav-sentinel {
  height: 1px;
}

.nav-row {
  position: sticky;
  top: 0;
  z-index: 20;
  background: var(--paper);
}

.nav-row.is-stuck {
  box-shadow: 0 1px 0 var(--rule);
}

.nav-tabs {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: clamp(18px, 3vw, 44px);
  padding: var(--s4) var(--s5) 6px;
}

.nav-tab {
  position: relative;
  padding: 4px 2px 9px;
  border: 0;
  background: none;
  color: var(--slate);
  font-size: 15px;
  font-weight: 500;
  white-space: nowrap;
  transition: color 0.16s ease;
}

/* Width reservation: the label again at the active weight, measured but never
   painted (and out of the a11y tree via visibility), so going active doesn't
   widen the button and slide the centered row sideways. */
.nav-tab::before {
  content: attr(data-label);
  display: block;
  height: 0;
  overflow: hidden;
  visibility: hidden;
  font-weight: 600;
}

.nav-tab:hover {
  color: var(--ink);
}

.nav-tab.active {
  color: var(--ink);
  font-weight: 600;
}

.nav-tab.active::after {
  content: "";
  position: absolute;
  left: 10%;
  right: 10%;
  bottom: 2px;
  height: 2px;
  border-radius: 2px;
  background: var(--gold);
}

.user-email {
  max-width: 100%;
  overflow: hidden;
  color: var(--slate);
  font-size: 12px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.account-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  color: var(--slate);
  font-size: 13px;
  white-space: nowrap;
}

/* The pill is a <button> so the connected state can act as the door to the
   accounts panel; unlink states keep the default cursor. */
button.account-pill {
  border: 0;
  font-family: inherit;
  cursor: default;
}

.account-pill.is-link {
  cursor: pointer;
}

.account-pill.is-link:hover {
  color: var(--ink-soft);
}

.status-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--slate);
}

.status-dot.ready {
  background: var(--gain);
}

/* ---------- Buttons ---------- */

.primary-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 40px;
  padding: 0 var(--s4);
  border: 1px solid var(--navy);
  border-radius: 4px;
  background: var(--navy);
  color: #ffffff;
  font-size: 15px;
  font-weight: 500;
}

.primary-button:hover:not(:disabled) {
  background: var(--navy-deep);
  border-color: var(--navy-deep);
}

.secondary-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 40px;
  padding: 0 var(--s4);
  border: 1px solid var(--ink);
  border-radius: 4px;
  background: transparent;
  color: var(--ink);
  font-size: 15px;
  font-weight: 500;
}

.secondary-button:hover:not(:disabled) {
  background: var(--ink);
  color: var(--paper);
}

.text-button {
  padding: 0;
  border: 0;
  background: none;
  color: var(--navy);
  font-size: inherit;
  font-weight: 500;
}

.text-button:hover:not(:disabled) {
  text-decoration: underline;
}

.text-button.danger {
  color: var(--loss);
}

/* ---------- The signature: accountant's total ---------- */

.ledger-total {
  max-width: max-content;
  min-width: 260px;
  border-top: 1px solid var(--ink);
  padding-top: var(--s3);
}

.ledger-label {
  display: block;
  color: var(--slate);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.ledger-figure {
  display: block;
  margin-top: var(--s2);
  padding-bottom: var(--s3);
  border-bottom: 3px double var(--gold);
  font-family: var(--font-mono);
  font-size: 40px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
  line-height: 1.05;
}

/* ---------- Landing ---------- */

.landing {
  max-width: 1080px;
  margin: 0 auto;
  padding: var(--s8) var(--s5) var(--s7);
}

.hero {
  display: grid;
  grid-template-columns: minmax(0, 1.2fr) minmax(280px, 0.8fr);
  gap: var(--s7);
  align-items: start;
}

.hero h1 {
  grid-column: 1;
  margin: 0;
  font-size: clamp(44px, 6.5vw, 76px);
  font-weight: 500;
  letter-spacing: -0.015em;
}

.hero-sub {
  grid-column: 1;
  max-width: 520px;
  margin: var(--s5) 0 0;
  color: var(--slate);
  font-size: 17px;
}

.hero-actions {
  grid-column: 1;
  display: flex;
  align-items: center;
  gap: var(--s5);
  margin-top: var(--s6);
}

.specimen {
  grid-column: 2;
  grid-row: 1 / span 3;
  margin: var(--s3) 0 0;
  padding: var(--s5);
  border: 1px solid var(--rule);
  background: #f4fafa;
}

.specimen-table {
  width: 100%;
  margin-top: var(--s5);
  border-collapse: collapse;
  font-family: var(--font-mono);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
}

.specimen-table td {
  padding: var(--s2) 0;
  border-bottom: 1px solid var(--rule);
}

.specimen-table td:nth-child(n + 2) {
  text-align: right;
}

.specimen figcaption {
  margin-top: var(--s3);
  color: var(--slate);
  font-size: 12px;
}

.site-footer {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s4);
  max-width: 1080px;
  margin: 0 auto;
  padding: var(--s5);
  border-top: 1px solid var(--rule);
  color: var(--slate);
  font-size: 12px;
}

.site-footer span:first-child {
  font-family: var(--font-brand);
  font-weight: 700;
  color: var(--ink);
}

/* ---------- Auth ---------- */

.auth-shell {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: var(--s5);
}

.auth-card {
  width: min(380px, 100%);
  padding: var(--s6);
  border: 1px solid var(--rule);
  background: #f4fafa;
}

.auth-back {
  display: block;
  margin-bottom: var(--s5);
  font-size: 13px;
}

.auth-card .wordmark {
  display: block;
}

.auth-card h1 {
  margin: var(--s5) 0 var(--s1);
  font-size: 26px;
}

.auth-sub {
  margin: 0;
  color: var(--slate);
  font-size: 14px;
}

.auth-card .notice {
  margin: var(--s4) 0 0;
}

.auth-submit {
  width: 100%;
  margin-top: var(--s5);
}

.auth-toggle {
  margin: var(--s5) 0 0;
  color: var(--slate);
  font-size: 13px;
  text-align: center;
}

/* Sits under the password field, right-aligned, so it reads as an escape hatch
   from that field rather than a second action competing with "Log in". */
.auth-forgot {
  margin: var(--s2) 0 0;
  font-size: 13px;
  text-align: right;
}

.auth-resend {
  margin: var(--s4) 0 0;
  color: var(--slate);
  font-size: 13px;
  text-align: center;
}

/* Matches the code card in onboarding: monospaced and spaced out, so six
   digits are easy to check against the email. */
.auth-code {
  font-family: var(--font-mono);
  font-size: 20px;
  letter-spacing: 0.4em;
  text-indent: 0.4em;
  text-align: center;
}

/* ---------- Forms ---------- */

.field-label {
  display: block;
  margin: var(--s4) 0 var(--s2);
  font-size: 13px;
  font-weight: 600;
}

.text-input {
  width: 100%;
  min-height: 40px;
  padding: 0 var(--s3);
  border: 1px solid var(--rule);
  border-radius: 4px;
  outline: none;
  background: #ffffff;
  color: var(--ink);
}

.text-input::placeholder {
  color: var(--slate);
  opacity: 0.7;
}

.text-input:focus {
  border-color: var(--navy);
  box-shadow: var(--ring);
}

/* ---------- Notices ---------- */

.notice {
  margin-bottom: var(--s5);
  padding: var(--s3) var(--s4);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--slate);
  background: #f4fafa;
  font-size: 14px;
}

.notice.success {
  border-left-color: var(--gain);
}

.notice.warning {
  border-left-color: #9c6f1f;
}

.notice.error {
  border-left-color: var(--loss);
}

/* ---------- App layout ---------- */

.main {
  min-width: 0;
  padding: var(--s6) var(--s6) var(--s8);
}

.tab-panel {
  display: none;
}

.tab-panel.active {
  display: block;
}

.section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--s4);
  margin-top: var(--s7);
}

.section-head h2 {
  margin: 0;
}

/* A section head can carry more than one text action (Refresh · Change my
   answers); the wrapper keeps them together on the right edge. */
.section-head-actions {
  display: flex;
  align-items: baseline;
  gap: var(--s4);
}

.section-label {
  font-size: 17px;
}

.quiet-note {
  margin: var(--s4) 0 0;
  color: var(--slate);
  font-size: 14px;
}

/* ---------- Dashboard ---------- */

.tape {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--s5);
  flex-wrap: wrap;
}

.tape .ledger-figure {
  font-size: 56px;
}

.tape-side {
  display: flex;
  align-items: center;
  gap: var(--s4);
  padding-bottom: var(--s2);
}

.sync-note {
  color: var(--slate);
  font-size: 12px;
}

.empty-cta {
  max-width: 480px;
  margin-top: var(--s6);
  padding-top: var(--s5);
  border-top: 1px solid var(--ink);
}

.empty-cta h2 {
  margin: 0;
  font-size: 24px;
}

.empty-cta p {
  margin: var(--s3) 0 var(--s5);
  color: var(--slate);
}

/* ---------- Table ---------- */

.table-wrap {
  margin-top: var(--s4);
  overflow-x: auto;
}

.ledger-table {
  width: 100%;
  min-width: 920px;
  border-collapse: collapse;
  font-size: 14px;
}

.ledger-table th,
.ledger-table td {
  padding: var(--s3) var(--s3);
  text-align: left;
  vertical-align: top;
}

.ledger-table th {
  border-bottom: 1px solid var(--ink);
  color: var(--slate);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
}

.ledger-table td {
  border-bottom: 1px solid var(--rule);
}

.ledger-table tbody tr {
  transition: background 0.12s ease;
}

.ledger-table tbody tr:hover {
  background: rgba(24, 47, 47, 0.03);
}

.ledger-table th.num,
.ledger-table td.mono:not(:first-child) {
  text-align: right;
}

.ledger-table td:first-child {
  padding-left: 0;
}

.ledger-table th:first-child {
  padding-left: 0;
}

.ledger-table td strong {
  display: block;
  font-weight: 600;
}

.asset-name {
  display: block;
  max-width: 240px;
  overflow: hidden;
  color: var(--slate);
  font-family: var(--font-body);
  font-size: 12px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.ledger-table td:last-child {
  color: var(--slate);
  font-size: 12px;
  white-space: nowrap;
}

/* ---------- Research ---------- */

.research-intro .section-head {
  margin-top: 0;
}

.research-intro h2 {
  font-size: 26px;
}

.intro-copy {
  max-width: 68ch;
  margin: var(--s3) 0 0;
  color: var(--ink-soft);
}

.ai-context {
  margin-top: var(--s6);
  padding-top: var(--s3);
  border-top: 1px solid var(--ink);
}

.ai-context p {
  margin: var(--s2) 0 0;
  line-height: 1.65;
}

.plain-bullets {
  margin: var(--s3) 0 0;
  padding-left: 18px;
  line-height: 1.65;
}

.plain-bullets li + li {
  margin-top: var(--s2);
}

.rec-list {
  display: grid;
  gap: var(--s3);
  margin-top: var(--s4);
}

.rec-entry {
  padding: var(--s4) var(--s5) var(--s5);
  border: 1px solid var(--rule);
  border-radius: 10px;
  background: #f4fafa;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.rec-entry:hover {
  border-color: #a9c4c4;
  box-shadow: 0 6px 20px -14px rgba(24, 47, 47, 0.3);
}

.rec-head {
  display: flex;
  align-items: baseline;
  gap: var(--s4);
}

.rec-head h3 {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 17px;
  font-weight: 600;
}

.rec-meta {
  flex: 1;
  color: var(--slate);
  font-size: 12px;
}

.tag {
  padding: 3px 10px;
  border-radius: 999px;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  white-space: nowrap;
}

.tag.act-buy {
  background: rgba(21, 107, 63, 0.1);
  color: var(--gain);
}

.tag.act-sell {
  background: rgba(168, 64, 47, 0.1);
  color: var(--loss);
}

.tag.act-hold,
.tag.tag-off {
  background: rgba(93, 100, 97, 0.1);
  color: var(--slate);
}

.tag.tag-on {
  background: rgba(21, 107, 63, 0.1);
  color: var(--gain);
}

/* Discover risk levels: blue (lower) → yellow (medium) → orange (higher).
   Tinted backgrounds with text dark enough to read on the paper background. */
.tag.risk-lower {
  background: rgba(37, 77, 121, 0.12);
  color: #1d3e63;
}

.tag.risk-medium {
  /* literal amber — risk colors are semantic (blue/yellow/orange), not brand
     chrome, so this no longer rides --gold-deep now that the accent is teal */
  background: rgba(198, 154, 22, 0.2);
  color: #7d5e00;
}

.tag.risk-higher {
  background: rgba(199, 94, 33, 0.16);
  color: #b0521f;
}

.share-line {
  margin: var(--s3) 0 0;
  font-size: 16px;
  font-weight: 600;
}

.rec-reasoning {
  margin: var(--s2) 0 0;
  color: var(--ink-soft);
  font-size: 15px;
  line-height: 1.65;
}

.disclaimer {
  margin-top: var(--s6);
  font-size: 12px;
}

/* ---------- News ---------- */

.news-filters {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
  margin-top: var(--s4);
}

.news-filter-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 12px;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: none;
  color: var(--slate);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}

.news-filter-chip:hover {
  border-color: var(--ink);
  color: var(--ink);
}

.news-filter-chip.active {
  border-color: var(--ink);
  background: var(--ink);
  color: var(--paper);
}

.news-filter-count {
  font-size: 10px;
  font-weight: 500;
  opacity: 0.65;
}

.news-list {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  align-items: start;
  gap: var(--s4);
  margin-top: var(--s4);
}

.news-item {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border: 1px solid var(--rule);
  border-radius: 12px;
  background: #f4fafa;
  color: inherit;
  text-decoration: none;
  transition: border-color 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease;
}

a.news-item:hover {
  border-color: var(--navy);
  box-shadow: 0 10px 28px -14px rgba(24, 47, 47, 0.35);
  transform: translateY(-2px);
}

a.news-item:focus-visible {
  border-color: var(--navy);
}

.news-body {
  display: flex;
  flex-direction: column;
  flex: 1;
  padding: var(--s4) var(--s4) var(--s4);
}

.news-head {
  display: flex;
  align-items: center;
  gap: var(--s3);
}

.news-symbol {
  padding: 2px 9px;
  border-radius: 999px;
  background: rgba(24, 47, 47, 0.06);
  color: var(--ink);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
}

.news-meta {
  flex: 1;
  color: var(--slate);
  font-size: 12px;
}

.news-arrow {
  color: var(--slate);
  font-size: 14px;
  opacity: 0;
  transform: translate(-2px, 2px);
  transition: opacity 0.15s ease, transform 0.15s ease, color 0.15s ease;
}

a.news-item:hover .news-arrow {
  color: var(--navy);
  opacity: 1;
  transform: none;
}

.news-headline {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  margin: var(--s3) 0 0;
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 600;
  line-height: 1.45;
  transition: color 0.15s ease;
}

a.news-item:hover .news-headline {
  color: var(--navy);
}

.news-summary {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  margin: var(--s2) 0 0;
  color: var(--ink-soft);
  font-size: 13.5px;
  line-height: 1.55;
}

/* ---------- Discover ---------- */

/* .disc-option rows are shared with the Alerts form. */
.disc-options {
  border-top: 1px solid var(--rule);
}

.disc-option {
  display: flex;
  align-items: center;
  gap: var(--s3);
  padding: var(--s3) var(--s2);
  border-bottom: 1px solid var(--rule);
  cursor: pointer;
  transition: background 0.12s ease;
}

.disc-option:hover {
  background: rgba(24, 47, 47, 0.03);
}

.disc-option input {
  accent-color: var(--navy);
}

.disc-option span {
  font-size: 15px;
}

.disc-watch strong {
  color: var(--ink);
  font-weight: 600;
}

.disc-risk-why strong {
  color: var(--ink);
  font-weight: 600;
}

/* The card's handoff to chat ("Why is this right for me?"). */
.disc-why {
  display: inline-block;
  margin-top: var(--s3);
  font-weight: 600;
}

/* ---------- Security / trust statement ---------- */

.trust-points {
  margin: var(--s5) 0 0;
  padding: 0;
  list-style: none;
  text-align: left;
}

.trust-points li {
  padding: var(--s3) 0;
  border-top: 1px solid var(--rule);
  color: var(--ink-soft);
  font-size: 14px;
  line-height: 1.6;
}

.trust-points strong {
  color: var(--ink);
  font-weight: 600;
}

.trust-more {
  margin-top: var(--s4);
  text-align: left;
}

.trust-more summary {
  color: var(--slate);
  font-size: 13px;
  cursor: pointer;
}

/* Beat .app-frame .empty-cta p's centered 42ch column — the trust explainer
   reads as normal left-aligned prose. */
.app-frame .empty-cta .trust-more p,
.trust-more p {
  max-width: 70ch;
  margin: var(--s3) 0 0;
  color: var(--ink-soft);
  font-size: 14px;
  line-height: 1.65;
}

.trust-card {
  max-width: 640px;
  margin-top: var(--s6);
  margin-inline: auto; /* capped narrower than the column, so it centers in it */
  padding: var(--s5);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--card);
  box-shadow: var(--shadow-sm);
}

.trust-card h2 {
  margin: 0;
  font-size: 18px;
}

.trust-card .trust-points {
  margin-top: var(--s3);
}

.trust-card .trust-points li:first-child {
  border-top: 0;
}

.disc-risk-source {
  display: block;
  margin-top: 2px;
  color: var(--slate);
  font-size: 12px;
}

/* ---------- Signup & onboarding — one question per screen ----------
   The austere shell: a single bordered card on paper, serif question, no
   shadow. Scenes cross-fade; the card floats up and settles as it arrives.
   Selection is --gold-soft, action is blue, dates and codes are mono. */

.onb-shell {
  position: relative;
  min-height: 100vh;
  min-height: 100dvh;
}

.onb-scene {
  min-height: 100vh;
  /* 100vh on mobile Safari runs under the browser chrome, pushing the card's
     buttons below the visible screen — dvh tracks what's actually shown. */
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: var(--s5);
  animation: onb-fade-in 0.5s ease both;
}

.onb-scene.is-leaving {
  animation: onb-fade-out 0.45s ease both;
}

@keyframes onb-fade-in {
  from {
    opacity: 0;
  }
}

@keyframes onb-fade-out {
  to {
    opacity: 0;
  }
}

/* The float-up-and-settle every card and headline arrives on. */
.onb-rise {
  opacity: 0;
  transform: translateY(20px);
  filter: blur(4px);
  transition:
    opacity 0.85s ease-out,
    transform 0.85s cubic-bezier(0.16, 0.84, 0.3, 1),
    filter 0.85s ease-out;
}

.onb-rise.is-in {
  opacity: 1;
  transform: translateY(0);
  filter: blur(0);
}

/* ---- welcome ---- */

.onb-welcome {
  grid-auto-flow: row;
  align-content: center;
  justify-items: center;
  text-align: center;
}

.onb-brand {
  margin: 0 0 var(--s6);
  color: var(--gold-deep);
  font-size: 14px;
  letter-spacing: 0.32em;
}

.onb-welcome-title {
  margin: 0;
  font-size: clamp(38px, 7vw, 64px);
  font-weight: 500;
  line-height: 1.12;
  letter-spacing: -0.01em;
}

.onb-welcome-sub {
  margin: var(--s3) 0 0;
  color: var(--gold-deep);
  font-family: var(--font-display);
  font-size: clamp(22px, 3.4vw, 30px);
  font-style: italic;
}

.onb-welcome-lede {
  margin: var(--s7) 0 0;
  color: var(--slate);
  font-size: 18px;
}

/* ---- the card ---- */

.onb-card {
  width: min(620px, 100%);
  padding: var(--s7) clamp(var(--s5), 5vw, 56px) var(--s6);
  border: 1px solid var(--rule);
  border-radius: 8px;
  background: var(--card-bg);
}

.onb-card.is-wide {
  width: min(660px, 100%);
}

.onb-kicker {
  margin: 0 0 var(--s5);
  color: var(--slate);
  font-size: 12px;
  letter-spacing: 0.26em;
}

.onb-q {
  margin: 0 0 var(--s2);
  font-size: clamp(26px, 4.2vw, 33px);
  font-weight: 500;
  line-height: 1.22;
}

.onb-q:focus-visible {
  box-shadow: none;
  outline: none;
}

.onb-note {
  margin: 0 0 var(--s5);
  color: var(--slate);
  font-size: 15px;
}

.onb-note:empty {
  display: none;
}

/* A card with no note would leave the body 8px under the question. Hand it the
   gap the note would have opened, so noteless cards don't read as cramped. */
.onb-note:empty + .onb-body {
  margin-top: var(--s5);
}

.onb-notice {
  margin: var(--s4) 0 0;
}

.onb-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s4);
  margin-top: var(--s6);
}

.onb-dots {
  display: flex;
  gap: var(--s2);
}

.onb-dots i {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--rule);
}

.onb-dots i.is-done {
  background: var(--gold-soft);
}

.onb-dots i.is-now {
  background: var(--navy);
}

.onb-foot-actions {
  display: flex;
  align-items: center;
  gap: var(--s4);
  margin-left: auto;
}

.onb-foot-actions .primary-button {
  border-radius: 8px;
  padding: 13px 30px;
}

/* ---- fields ---- */

.onb-field + .onb-field {
  margin-top: var(--s4);
}

.onb-field-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s4);
}

.onb-label {
  display: block;
  margin-bottom: var(--s2);
  color: var(--slate);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

.onb-input {
  width: 100%;
  height: 54px;
  padding: 0 var(--s4);
  border: 1px solid var(--rule);
  border-radius: 6px;
  background: #ffffff;
  color: var(--ink);
  font-size: 19px;
  transition:
    border-color 0.25s ease,
    box-shadow 0.25s ease;
}

.onb-input::placeholder {
  color: var(--slate);
  opacity: 0.7;
}

.onb-input:focus,
.onb-input:focus-visible {
  border-color: var(--navy);
  outline: none;
  box-shadow: var(--ring);
}

.onb-input.mono {
  letter-spacing: 0.04em;
}

.onb-input.onb-code {
  font-family: var(--font-mono);
  font-size: 26px;
  letter-spacing: 0.4em;
  text-align: center;
}

/* The one open-text answer: same paper as the inputs, given room to breathe and
   a fixed height so the card doesn't grow while you type. */
.onb-textarea {
  height: auto;
  min-height: 132px;
  padding: var(--s3) var(--s4);
  font-family: inherit;
  font-size: 17px;
  line-height: 1.6;
  resize: vertical;
}

.onb-count {
  margin: var(--s2) 0 0;
  color: var(--slate);
  font-size: 12px;
  letter-spacing: 0.04em;
  text-align: right;
}

.onb-inline-action {
  margin: var(--s4) 0 0;
  color: var(--slate);
  font-size: 13.5px;
}

/* ---- broker card ---- */

.onb-lede {
  margin: 0;
  max-width: 52ch;
  color: var(--ink-soft);
  font-size: 15.5px;
  line-height: 1.6;
}

.onb-safety {
  display: flex;
  align-items: center;
  gap: 7px;
  margin: var(--s4) 0 0;
  color: var(--slate);
  font-size: 13.5px;
}

.onb-safety svg {
  flex: none;
}

.onb-connect {
  margin-top: var(--s4);
}

/* ---- chips (experience) ---- */

.onb-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2) 10px;
  border: 0;
  padding: 0;
  margin: 0;
}

.onb-chip {
  position: relative;
  display: inline-flex;
  padding: 12px 20px;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: #ffffff;
  color: var(--ink-soft);
  font-size: 16px;
  font-weight: 500;
  cursor: pointer;
  transition:
    border-color 0.2s ease,
    background 0.2s ease,
    color 0.2s ease;
}

.onb-chip input,
.onb-pref input {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  padding: 0;
  border: 0;
  opacity: 0;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  overflow: hidden;
}

.onb-chip:hover,
.onb-pref:hover {
  border-color: var(--slate);
}

.onb-chip:has(input:focus-visible),
.onb-pref:has(input:focus-visible) {
  border-color: var(--navy);
  box-shadow: var(--ring);
}

.onb-chip:has(input:checked) {
  border-color: var(--gold-deep);
  background: var(--gold-soft);
  color: var(--gold-deep);
  font-weight: 600;
}

/* ---- preference cards (trading style) ---- */

.onb-prefs {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s3);
  border: 0;
  padding: 0;
  margin: 0;
}

.onb-pref {
  position: relative;
  display: block;
  padding: 18px 18px 16px;
  border: 1px solid var(--rule);
  border-radius: 8px;
  background: #ffffff;
  cursor: pointer;
  transition:
    border-color 0.2s ease,
    background 0.2s ease;
}

.onb-pref b {
  display: block;
  margin-bottom: var(--s1);
  font-family: var(--font-brand);
  font-size: 17px;
  font-weight: 600;
}

.onb-pref-note {
  display: block;
  color: var(--slate);
  font-size: 13.5px;
  line-height: 1.45;
  max-width: 90%;
}

.onb-pref .onb-tick {
  position: absolute;
  top: 16px;
  right: 16px;
  display: grid;
  place-items: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--gold-deep);
  color: #ffffff;
  font-size: 12px;
  opacity: 0;
  transform: scale(0.4);
  transition:
    opacity 0.25s ease,
    transform 0.25s ease;
}

.onb-pref:has(input:checked) {
  border-color: var(--gold-deep);
  background: var(--gold-soft);
}

.onb-pref:has(input:checked) b {
  color: var(--gold-deep);
}

.onb-pref:has(input:checked) .onb-tick {
  opacity: 1;
  transform: scale(1);
}

/* ---- "setting up your ledger" interstitial ---- */

.onb-build {
  grid-auto-flow: row;
  align-content: center;
  justify-items: center;
}

.onb-build-line {
  margin: 0 0 var(--s5);
  font-family: var(--font-display);
  font-size: clamp(24px, 4vw, 30px);
  font-weight: 500;
  text-align: center;
}

.onb-bar {
  width: min(300px, 80vw);
  height: 3px;
  border-radius: 2px;
  background: var(--rule);
  overflow: hidden;
}

.onb-bar i {
  display: block;
  width: 0;
  height: 100%;
  background: var(--gold);
  transition: width 1.6s cubic-bezier(0.3, 0, 0.2, 1);
}

.onb-bar.is-filling i {
  width: 100%;
}

/* The dashboard rises out of the interstitial, then its top blocks settle in. */
.app-frame.onb-reveal {
  animation: onb-slide-up 0.95s cubic-bezier(0.18, 0.85, 0.22, 1) both;
}

@keyframes onb-slide-up {
  from {
    transform: translateY(100%);
  }
}

@media (max-width: 560px) {
  .onb-field-row,
  .onb-prefs {
    grid-template-columns: 1fr;
  }

  /* Top-aligned, not centered: centered in the viewport, the card's primary
     button lands behind the software keyboard. The welcome and build scenes
     keep their own align-content and are unaffected. */
  .onb-scene {
    align-items: start;
  }

  .onb-card {
    padding: var(--s6) var(--s5) var(--s5);
  }

  .onb-foot {
    flex-wrap: wrap;
  }
}

/* ---------- Alerts ---------- */

.alerts-form {
  margin-top: var(--s6);
}

.alerts-enable {
  border-top: 1px solid var(--rule);
}

.alerts-enable span {
  font-weight: 600;
}

.alerts-settings {
  margin-top: var(--s5);
  transition: opacity 0.15s ease;
}

.alerts-settings.is-off {
  opacity: 0.45;
}

.alerts-fieldset {
  margin: 0 0 var(--s5);
  padding: 0;
  border: 0;
}

.alerts-fieldset .field-label {
  display: block;
  margin-bottom: var(--s2);
}

.alerts-hint {
  margin-left: var(--s2);
  color: var(--slate);
  font-size: 12px;
  font-style: normal;
}

/* Per-holding pick list: compact ticker chips under the scope radios. */
.alerts-symbols {
  padding: var(--s3) var(--s2) 0;
}

.alerts-symbols-tools {
  display: flex;
  gap: var(--s4);
  margin-bottom: var(--s3);
}

.alerts-symbol-grid {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
}

.symbol-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 12px;
  border: 1px solid var(--rule);
  border-radius: var(--radius-pill);
  cursor: pointer;
  font-size: 13px;
  font-weight: 600;
  transition: background 0.12s ease, border-color 0.12s ease;
}

.symbol-chip:hover {
  background: rgba(24, 47, 47, 0.03);
}

.symbol-chip input {
  accent-color: var(--navy);
}

.symbol-chip:has(input:checked) {
  background: rgba(24, 47, 47, 0.06);
  border-color: var(--navy);
}

/* A picked ticker the user no longer holds — kept so the selection round-trips. */
.symbol-chip.is-unheld {
  opacity: 0.55;
}

.alerts-to {
  margin-bottom: var(--s5);
}

.alerts-actions {
  display: flex;
  align-items: center;
  gap: var(--s4);
  margin-top: var(--s5);
}

#alertsStatus {
  margin-top: var(--s3);
}

#alertsStatus.is-error,
#profileStatus.is-error {
  color: var(--loss);
}

/* ---------- Responsive ---------- */

@media (max-width: 900px) {
  /* The address is the first thing to go; the pill and the way out stay. */
  .chrome-account .user-email {
    display: none;
  }

  /* Eight tabs stop fitting, so the row scrolls sideways on one line rather
     than wrapping — the underline stays a single rail. Scrollbar hidden, and
     .nav-row's fade at the right edge is the hint that there's more. */
  .nav-tabs {
    justify-content: flex-start;
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }

  .nav-tabs::-webkit-scrollbar {
    display: none;
  }

  .nav-row::after {
    content: "";
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    width: 32px;
    background: linear-gradient(to right, transparent, var(--paper));
    pointer-events: none;
  }

  .hero {
    grid-template-columns: 1fr;
  }

  .specimen {
    grid-column: 1;
    grid-row: auto;
    max-width: 420px;
  }

}

@media (max-width: 720px) {
  .news-list {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 640px) {
  .site-bar {
    flex-wrap: wrap;
    gap: var(--s3);
  }

  .user-email {
    display: none;
  }

  .landing {
    padding: var(--s6) var(--s4);
  }

  .hero-actions {
    align-items: stretch;
    flex-direction: column;
    gap: var(--s3);
  }

  .main {
    padding: var(--s5) var(--s4) var(--s7);
  }

  .tape {
    align-items: stretch;
    flex-direction: column;
  }

  .tape .ledger-figure {
    font-size: 40px;
  }

  .rec-head {
    flex-wrap: wrap;
  }

  .site-footer {
    flex-direction: column;
    gap: var(--s2);
  }
}

@media (prefers-reduced-motion: reduce) {
  * {
    animation: none !important;
    transition: none !important;
  }

  /* The onboarding cards start hidden and are revealed by a transition, so
     with transitions off they need to be visible from the start — the flow
     itself is unchanged, only the float-in is gone. */
  .onb-rise {
    opacity: 1;
    transform: none;
    filter: none;
  }

  .onb-bar i {
    width: 100%;
  }
}

/* ============================================================
   MODERN PLATFORM THEME — scoped to #appShell only.
   The marketing landing and the auth/onboarding shells keep the
   "Ledger" identity (they still read the :root tokens). Inside the
   app we re-map those same tokens to a light-broker palette and add
   card / stat-tile / chart components on top. Because these rules
   are scoped under .app-frame they out-specify the base app rules.
   ============================================================ */

.app-frame {
  /* re-mapped tokens — the card/tile layout on the house Ledger palette
     (pale-teal paper + teal ink + blue action + teal accent) */
  --paper: #daecec;
  --card: #f6fbfb;
  --card-2: #e9f3f3;
  --ink: #182f2f;
  --ink-soft: #264443;
  --slate: #4d6564;
  --rule: #c0d8d8;
  --navy: #254d79; /* slate blue — interactive / brand accent */
  --navy-deep: #1d3e63;
  --accent-soft: #bfdfdf;
  --gain: #156b3f;
  --loss: #a8402f;
  --gold: #305e5f;
  --gold-deep: #24494a;
  --gold-soft: #bfdfdf;

  /* headings are serif here too (trust), same as the landing; body stays sans */
  --font-display: "Newsreader", Georgia, "Times New Roman", serif;

  --radius: 16px;
  --radius-sm: 10px;
  --radius-pill: 999px;
  --shadow-sm: 0 1px 2px rgba(22, 42, 42, 0.05);
  --shadow: 0 1px 3px rgba(22, 42, 42, 0.06), 0 10px 26px -16px rgba(22, 42, 42, 0.28);
  --shadow-lg: 0 24px 64px -24px rgba(22, 42, 42, 0.4);

  background: var(--paper);
}

/* categorical palette for allocation charts (validated on card #f6fbfb:
   worst adjacent CVD ΔE 13.4, normal-vision ΔE 19.6, light).
   --cat-1/--cat-3 carry the brand blue/teal stepped up to chart lightness;
   slots 4–5 sit under 3:1 vs the surface, so the donut must always ship
   with its named legend (it does) — re-validate if you reorder. */
.app-frame {
  --cat-1: #2f6ec2;
  --cat-2: #eb6834;
  --cat-3: #1d9d99;
  --cat-4: #eda100;
  --cat-5: #e87ba4;
  --cat-6: #008300;
  --cat-7: #4a3aa7;
  --cat-8: #e34948;
  --cat-other: #9aa8a8;
}

/* ---------- Chrome ----------
   Layout lives in the base "App chrome" block; these are the platform-theme
   trims (the wordmark scale and the status pill's chip). */

.app-frame .chrome-utility .wordmark {
  font-size: 24px;
}

.app-frame .account-pill {
  padding: 3px 9px;
  border-radius: var(--radius-pill);
  background: var(--card-2);
  font-size: 11px;
}

/* ---------- Main content shell ---------- */

.app-frame .main {
  /* 960 rather than the old 1180: the tab row's ink is ~760px wide, so a
     1084px content slab left the centered nav looking like an island floating
     over it. At 960 the column reads as the same spine the nav sits on, and
     every dashboard grid is fluid 2-col so nothing gets cramped.
     width:100% keeps this filling its column — without it, margin:0 auto
     shrinks the block to its content and wide tabs (dashboard) render wider
     than short ones (news). */
  width: 100%;
  max-width: 960px;
  margin: 0 auto;
  padding: var(--s6) var(--s5) var(--s8);
}

/* Wide tabs opt out of the cap (set in activateTab): the Learn player reads
   as a squeezed strip inside 960, so it takes the full screen; Alerts centers
   at ~3/4 of the page below. Padding stays inherited so the responsive
   gutters keep working on phones. */
.app-frame .main.is-wide {
  max-width: none;
}

.app-frame .main.is-wide #alerts {
  width: 100%;
  max-width: 75vw;
  margin: 0 auto;
}

.app-frame .page-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--s4);
  flex-wrap: wrap;
}

.app-frame .page-title {
  margin: 0;
  font-size: 30px;
  font-weight: 700;
  letter-spacing: -0.02em;
}

/* Dashboard only: the greeting moved up into the chrome, so this head carries
   just the sync stamp and the actions, on one baseline. */
.app-frame .page-head.is-meta {
  align-items: baseline;
}

.app-frame .page-head.is-meta .page-sub {
  margin: 0;
}

.app-frame .page-sub {
  margin: 6px 0 0;
  color: var(--slate);
  font-size: 13px;
}

.app-frame .page-actions {
  display: flex;
  align-items: center;
  gap: var(--s3);
}

/* ---------- Cards ---------- */

.app-frame .card {
  padding: var(--s5);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--card);
  box-shadow: var(--shadow-sm);
}

.app-frame .card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
  margin-bottom: var(--s4);
}

.app-frame .card-head h2 {
  margin: 0;
  font-size: 16px;
  font-weight: 700;
}

/* ---------- Overview: portfolio card (total + trend) beside allocation ---------- */

.app-frame .overview {
  display: grid;
  grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
  gap: var(--s4);
  margin-top: var(--s5);
}

/* Strategy Lab launch card — dashboard announcement for users without the
   Lab yet. Same shape as the Learn nudge, but signed with the gold double
   rule so a product launch reads different from a study tip. */
.app-frame .lab-launch {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--s4);
  margin-top: var(--s5);
  padding: var(--s4) var(--s5);
  border: 1px solid var(--rule);
  border-bottom: 3px double var(--gold);
  border-radius: var(--radius) var(--radius) 0 0;
  background: var(--card);
}

.app-frame .lab-launch-tag {
  display: inline-block;
  padding: 2px 8px;
  margin-right: var(--s2);
  border: 1px solid var(--gold);
  border-radius: var(--radius-pill);
  background: var(--gold-soft);
  color: var(--gold-deep);
  font-size: 10px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  vertical-align: 1px;
}

.app-frame .lab-launch-copy strong {
  color: var(--ink);
}

.app-frame .lab-launch-copy > span {
  display: block;
  margin-top: 2px;
  color: var(--ink-soft);
  font-size: 14px;
  max-width: 52em;
}

.app-frame .lab-launch-actions {
  display: flex;
  align-items: center;
  gap: var(--s4);
}

.app-frame .hero-card {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--s2);
  background: linear-gradient(150deg, #1d3e63 0%, #254d79 100%);
  border-color: transparent;
  color: #fff;
  box-shadow: var(--shadow);
}

.app-frame .hero-card .stat-label {
  color: rgba(255, 255, 255, 0.72);
}

.app-frame .hero-figure {
  font-family: var(--font-mono);
  font-size: clamp(34px, 4.4vw, 46px);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
  line-height: 1.05;
}

.app-frame .hero-delta {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: 15px;
  font-variant-numeric: tabular-nums;
}

.app-frame .hero-delta .chip {
  padding: 2px 9px;
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, 0.16);
  font-size: 13px;
  font-weight: 600;
}

.app-frame .hero-delta.up {
  color: #8ff0bc;
}

.app-frame .hero-delta.down {
  color: #ffb4ac;
}

.app-frame .stat-tiles {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s4);
}

.app-frame .stat {
  display: flex;
  flex-direction: column;
  gap: 6px;
  justify-content: center;
}

.app-frame .stat-label {
  color: var(--slate);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
}

.app-frame .stat-val {
  font-family: var(--font-mono);
  font-size: 24px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.01em;
}

.app-frame .stat-sub {
  color: var(--slate);
  font-size: 12.5px;
}

.app-frame .stat-sub.up {
  color: var(--gain);
}

.app-frame .stat-sub.down {
  color: var(--loss);
}

/* ---------- Holdings price-trend line, now living inside the hero card
   under the total + delta ---------- */

.app-frame .value-chart {
  position: relative;
  flex: 1;
  min-height: 184px;
  display: flex;
  align-items: center;
}

.app-frame .value-chart svg {
  display: block;
}

.app-frame .value-cap {
  margin: 0;
  color: var(--slate);
  font-size: 11px;
}

/* The chart sits on the hero card's dark navy gradient, so its quiet text
   swaps slate for translucent white to stay readable. */
.app-frame .hero-card .value-chart {
  margin-top: var(--s2);
}

.app-frame .hero-card .value-cap,
.app-frame .hero-card .chart-empty {
  color: rgba(255, 255, 255, 0.66);
}

/* ---------- Dashboard feeds: top news + ideas under the chart ---------- */

.app-frame .dash-feeds {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: var(--s4);
  margin-top: var(--s4);
}

/* The grid stretches both feed cards to the height of the taller one, so the
   shorter card carries dead space under its last row. Hand that space to the
   body: it lets the news list measure what it's been given and fill it (see
   fitDashNews), instead of leaving a gap whose size depends on the sibling. */
.app-frame .dash-feed {
  display: flex;
  flex-direction: column;
}

.app-frame .dash-feed-body {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
}

/* Rows are separated by hairline rules, ledger-style; the whole row is the
   target (a link for news, a button that opens Discover for ideas). */
.app-frame .dash-feed-item {
  display: flex;
  flex-direction: column;
  /* Whatever height is left after the last row that fits gets shared out
     between the rows instead of pooling as dead space at the bottom of the
     card. Never shrink: rows keep their natural height when the list is too
     long, which is what lets fitDashNews detect the overflow and drop one. */
  flex: 1 0 auto;
  justify-content: center;
  gap: var(--s2);
  padding: var(--s3) 0;
  border-top: 1px solid var(--rule);
  text-align: left;
  text-decoration: none;
  color: inherit;
  background: none;
  border-left: 0;
  border-right: 0;
  border-bottom: 0;
  cursor: pointer;
  width: 100%;
  font: inherit;
  transition: background 0.12s ease;
}

.app-frame .dash-feed-item:first-child {
  border-top: 0;
}

.app-frame .dash-feed-item.dash-feed-item-static {
  cursor: default;
}

.app-frame .dash-feed-item:hover:not(.dash-feed-item-static),
.app-frame .dash-feed-item:focus-visible:not(.dash-feed-item-static) {
  background: var(--card-2);
  outline: none;
}

.app-frame .dash-feed-item:focus-visible {
  box-shadow: var(--ring);
  border-radius: var(--radius-sm);
}

.app-frame .dash-feed-top {
  display: flex;
  align-items: center;
  gap: var(--s2);
}

.app-frame .dash-feed-meta {
  color: var(--slate);
  font-size: 11.5px;
}

.app-frame .dash-feed-headline {
  font-size: 14px;
  line-height: 1.4;
  color: var(--ink);
  /* clamp to two lines so both cards stay the same tidy height */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.app-frame .dash-idea-name {
  font-size: 12.5px;
  color: var(--ink-soft);
}

/* ---------- Segmented control ---------- */

.app-frame .seg {
  display: inline-flex;
  padding: 3px;
  border-radius: var(--radius-pill);
  background: var(--card-2);
  border: 1px solid var(--rule);
}

.app-frame .seg button {
  padding: 5px 12px;
  border: 0;
  border-radius: var(--radius-pill);
  background: none;
  color: var(--slate);
  font-size: 12.5px;
  font-weight: 600;
  transition: background 0.14s ease, color 0.14s ease;
}

.app-frame .seg button.active {
  background: var(--card);
  color: var(--ink);
  box-shadow: var(--shadow-sm);
}

/* ---------- Allocation donut + legend ---------- */

.app-frame .alloc-body {
  display: grid;
  grid-template-columns: 168px minmax(0, 1fr);
  align-items: center;
  gap: var(--s5);
}

.app-frame .donut-wrap {
  position: relative;
  width: 168px;
  height: 168px;
}

.app-frame .donut-center {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  pointer-events: none;
}

.app-frame .donut-center .dc-label {
  color: var(--slate);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
}

.app-frame .donut-center .dc-value {
  font-family: var(--font-mono);
  font-size: 17px;
  font-weight: 600;
}

.app-frame .donut-wrap svg path {
  transition: opacity 0.14s ease;
  cursor: default;
}

.app-frame .donut-wrap.has-hover svg path:not(.is-hover) {
  opacity: 0.4;
}

.app-frame .legend {
  margin: 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 2px;
  max-height: 200px;
  overflow-y: auto;
}

.app-frame .legend li {
  display: grid;
  grid-template-columns: 12px minmax(0, 1fr) auto;
  align-items: center;
  gap: var(--s3);
  padding: 5px 6px;
  border-radius: 8px;
  font-size: 13px;
  cursor: default;
}

.app-frame .legend li:hover,
.app-frame .legend li.is-hover {
  background: var(--card-2);
}

.app-frame .legend li.lg-clickable {
  cursor: pointer;
}

.app-frame .legend li.lg-clickable:focus-visible {
  background: var(--card-2);
  outline: 2px solid var(--navy);
  outline-offset: -2px;
}

.app-frame .legend .swatch {
  width: 11px;
  height: 11px;
  border-radius: 3px;
}

.app-frame .legend .lg-name {
  overflow: hidden;
  font-weight: 600;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.app-frame .legend .lg-name small {
  color: var(--slate);
  font-weight: 500;
}

.app-frame .legend .lg-pct {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  color: var(--ink-soft);
}

/* ---------- Positions table ---------- */

.app-frame .positions-card {
  margin-top: var(--s4);
  padding: var(--s5) var(--s5) var(--s3);
}

.app-frame .pos-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13.5px;
}

.app-frame .pos-table th {
  padding: var(--s3);
  border-bottom: 1px solid var(--rule);
  color: var(--slate);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  text-align: right;
  white-space: nowrap;
}

.app-frame .pos-table th:first-child,
.app-frame .pos-table th.left {
  text-align: left;
}

.app-frame .pos-table th.sortable {
  cursor: pointer;
  user-select: none;
}

.app-frame .pos-table th.sortable:hover {
  color: var(--ink);
}

.app-frame .pos-table th .caret {
  margin-left: 4px;
  opacity: 0;
  font-size: 9px;
  vertical-align: middle;
}

.app-frame .pos-table th.sorted .caret {
  opacity: 1;
}

.app-frame .pos-table td {
  padding: var(--s3);
  border-bottom: 1px solid var(--rule);
  text-align: right;
  vertical-align: middle;
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
}

.app-frame .pos-table tbody tr:last-child td {
  border-bottom: 0;
}

.app-frame .pos-table td.left {
  text-align: left;
  font-family: var(--font-body);
}

.app-frame .pos-table tbody tr {
  cursor: pointer;
  transition: background 0.12s ease;
}

.app-frame .pos-table tbody tr:hover {
  background: var(--card-2);
}

.app-frame .pos-sym {
  display: flex;
  align-items: center;
  gap: var(--s3);
}

.app-frame .pos-sym .acct-badge {
  width: 30px;
  height: 30px;
  font-size: 12px;
}

.app-frame .pos-sym strong {
  display: block;
  font-family: var(--font-mono);
  font-weight: 600;
}

.app-frame .pos-sym .asset-name {
  display: block;
  max-width: 200px;
  overflow: hidden;
  color: var(--slate);
  font-family: var(--font-body);
  font-size: 12px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.app-frame .pill {
  display: inline-block;
  min-width: 62px;
  padding: 3px 8px;
  border-radius: var(--radius-pill);
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 600;
  text-align: center;
}

.app-frame .pill.up {
  background: rgba(10, 125, 67, 0.1);
  color: var(--gain);
}

.app-frame .pill.down {
  background: rgba(195, 58, 48, 0.1);
  color: var(--loss);
}

.app-frame .pill.flat {
  background: var(--card-2);
  color: var(--slate);
}

.app-frame .spark {
  display: block;
}

/* ---------- Holding detail drawer ---------- */

.app-frame .drawer-scrim {
  position: fixed;
  inset: 0;
  z-index: 40;
  background: rgba(22, 42, 42, 0.32);
  backdrop-filter: blur(2px);
  animation: scrim-in 0.16s ease;
}

@keyframes scrim-in {
  from {
    opacity: 0;
  }
}

.app-frame .drawer {
  position: fixed;
  top: 0;
  right: 0;
  z-index: 41;
  width: min(460px, 94vw);
  height: 100vh;
  overflow-y: auto;
  padding: var(--s6) var(--s5);
  background: var(--card);
  border-left: 1px solid var(--rule);
  box-shadow: var(--shadow-lg);
  animation: drawer-in 0.2s cubic-bezier(0.22, 1, 0.36, 1);
}

@keyframes drawer-in {
  from {
    transform: translateX(24px);
    opacity: 0.4;
  }
}

.app-frame .drawer-close {
  position: absolute;
  top: var(--s4);
  right: var(--s4);
  width: 32px;
  height: 32px;
  border: 0;
  border-radius: 50%;
  background: var(--card-2);
  color: var(--slate);
  font-size: 18px;
  line-height: 1;
}

.app-frame .drawer-close:hover {
  background: var(--rule);
  color: var(--ink);
}

.app-frame .drawer-sym {
  display: flex;
  align-items: center;
  gap: var(--s3);
}

.app-frame .drawer-sym h2 {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 22px;
  font-weight: 600;
}

.app-frame .drawer-name {
  margin: 4px 0 0;
  color: var(--slate);
  font-size: 13px;
}

.app-frame .drawer-price {
  margin: var(--s4) 0 2px;
  font-family: var(--font-mono);
  font-size: 30px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.app-frame .drawer-chart {
  position: relative;
  margin-top: var(--s4);
}

.app-frame .drawer-ranges {
  display: inline-flex;
  gap: 2px;
  margin-top: var(--s3);
}

.app-frame .drawer-ranges button {
  padding: 4px 11px;
  border: 0;
  border-radius: 8px;
  background: none;
  color: var(--slate);
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 600;
}

.app-frame .drawer-ranges button.active {
  background: var(--accent-soft);
  color: var(--gold-deep);
}

.app-frame .drawer-stats {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1px;
  margin-top: var(--s5);
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  overflow: hidden;
  background: var(--rule);
}

.app-frame .drawer-stats div {
  padding: var(--s3) var(--s4);
  background: var(--card);
}

.app-frame .drawer-stats dt {
  color: var(--slate);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

.app-frame .drawer-stats dd {
  margin: 4px 0 0;
  font-family: var(--font-mono);
  font-size: 15px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.app-frame .chart-tip {
  position: absolute;
  z-index: 2;
  padding: 5px 9px;
  border-radius: 8px;
  background: var(--ink);
  color: #fff;
  font-family: var(--font-mono);
  font-size: 11.5px;
  white-space: nowrap;
  pointer-events: none;
  transform: translate(-50%, -120%);
  opacity: 0;
  transition: opacity 0.1s ease;
}

.app-frame .chart-tip.show {
  opacity: 1;
}

.app-frame .chart-empty {
  display: grid;
  place-items: center;
  height: 160px;
  color: var(--slate);
  font-size: 13px;
}

/* ---------- Empty / connect state ---------- */

.app-frame .empty-cta {
  max-width: none;
  margin-top: var(--s5);
  padding: var(--s7) var(--s6);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--card);
  box-shadow: var(--shadow-sm);
  text-align: center;
}

.app-frame .empty-cta h2 {
  font-size: 22px;
}

.app-frame .empty-cta p {
  margin-left: auto;
  margin-right: auto;
  max-width: 42ch;
}

/* ---------- Buttons (app-scoped) ---------- */

.app-frame .primary-button {
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-sm);
}

.app-frame .secondary-button {
  border-radius: var(--radius-sm);
  border-color: var(--rule);
  background: var(--card);
}

.app-frame .secondary-button:hover:not(:disabled) {
  background: var(--card-2);
  border-color: var(--slate);
  color: var(--ink);
}

.app-frame .ghost-button {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 38px;
  padding: 0 var(--s4);
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  background: var(--card);
  color: var(--ink);
  font-size: 14px;
  font-weight: 600;
}

.app-frame .ghost-button:hover:not(:disabled) {
  background: var(--card-2);
  border-color: var(--slate);
}

/* ---------- Restyle secondary tabs into the card language ---------- */

.app-frame .research-intro h2,
.app-frame .empty-cta h2 {
  font-family: var(--font-display);
}

.app-frame .rec-entry,
.app-frame .news-item {
  border-radius: var(--radius);
  background: var(--card);
  box-shadow: var(--shadow-sm);
}

.app-frame .rec-entry:hover {
  border-color: var(--rule);
  box-shadow: var(--shadow);
}

.app-frame .ai-context {
  padding: var(--s5);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--card);
  box-shadow: var(--shadow-sm);
}

.app-frame .alerts-form {
  padding: var(--s5);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--card);
  box-shadow: var(--shadow-sm);
}

.app-frame .news-symbol,
.app-frame .news-filter-chip.active {
  background: var(--accent-soft);
  color: var(--gold-deep);
}

/* ---------- Notice (app) ---------- */

.app-frame .notice {
  border-radius: var(--radius-sm);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--slate);
  background: var(--card);
  box-shadow: var(--shadow-sm);
}

/* ---------- Responsive ---------- */

@media (max-width: 900px) {
  .app-frame .main {
    padding: var(--s5) var(--s4) var(--s7);
  }

  /* 3/4-page centering is a big-screen affordance; phones use the full width. */
  .app-frame .main.is-wide #alerts {
    max-width: none;
  }

  /* Follow the main column's narrower gutters so the wordmark, the greeting,
     and the first tab all still hang off the content's left edge. */
  .app-frame .chrome-utility,
  .app-frame .chrome-greet {
    padding-left: var(--s4);
    padding-right: var(--s4);
  }

  /* Narrow screens drop the centered spine: the column already fills the
     viewport, so the greeting goes back on the same left rail as the scrolling
     tab row and the content under it. */
  .app-frame .chrome-greet {
    text-align: left;
  }

  .app-frame .nav-tabs {
    padding-left: var(--s4);
    padding-right: var(--s4);
  }

  .app-frame .overview,
  .app-frame .dash-feeds {
    grid-template-columns: 1fr;
  }
}

@media (max-width: 560px) {
  .app-frame .stat-tiles {
    grid-template-columns: 1fr 1fr;
  }

  .app-frame .alloc-body {
    grid-template-columns: 1fr;
    justify-items: center;
    text-align: left;
  }

  .app-frame .legend {
    width: 100%;
  }

  .app-frame .pos-table .col-price,
  .app-frame .pos-table .col-cost {
    display: none;
  }
}

/* ---------- Diversification read (allocation card) ---------- */

.app-frame .diversify-read {
  margin-top: var(--s4);
  padding-top: var(--s4);
  border-top: 1px solid var(--rule);
}

.app-frame .div-stats {
  margin: 0;
  font-size: 12px;
  letter-spacing: 0.02em;
  color: var(--slate);
  font-variant-numeric: tabular-nums;
}

.app-frame .div-verdict {
  margin: var(--s2) 0 0;
  font-size: 14px;
  line-height: 1.55;
  color: var(--ink-soft);
}

/* ---------- In-app article summaries (News tab) ---------- */

.app-frame .news-cell {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--s2);
}

/* Cards size to their own content — a summarized card must not stretch its
   row neighbors (align-items:start on the grid keeps each cell top-aligned). */
.app-frame .news-cell .news-item {
  flex: 0 0 auto;
}

/* Small pill floated into the card's top-right corner. It stays a sibling of
   the <a> (never nested) so clicking it doesn't open the article. */
.app-frame .news-sum-btn {
  position: absolute;
  top: var(--s3);
  right: var(--s3);
  z-index: 2;
  padding: 3px 10px;
  border: 1px solid var(--rule);
  border-radius: 999px;
  background: var(--card);
  color: var(--navy);
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  line-height: 1.5;
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease, color 0.15s ease;
}

.app-frame .news-sum-btn:hover {
  border-color: var(--navy);
  background: rgba(24, 47, 47, 0.05);
}

.app-frame .news-sum-btn:disabled {
  opacity: 0.6;
  cursor: default;
}

/* Reserve room on the header row so the symbol/date never slide under the
   floated button ("Impact on me" is the widest label). */
.app-frame .news-head {
  padding-right: 118px;
}

.app-frame .news-head .news-meta {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.app-frame .news-sum-panel {
  padding: var(--s3) var(--s4);
  border: 1px solid var(--rule);
  border-left: 3px solid var(--navy);
  border-radius: var(--radius-sm);
  background: var(--card);
  box-shadow: var(--shadow-sm);
}

.app-frame .news-sum-text {
  margin: 0;
  font-size: 14px;
  line-height: 1.6;
  color: var(--ink-soft);
}

.app-frame .news-sum-meta {
  margin: 6px 0 0;
  font-size: 11px;
  letter-spacing: 0.04em;
  color: var(--slate);
}

/* ---------- Profile: the two answers, editable in place ----------
   Same chips and preference cards as the onboarding cards, dropped into an
   app card so the answers read as one continuous thing across surfaces. */

/* Capped for readability, so it has to be centered in the column — left-aligned
   it was the one panel still hanging off the left edge under the centered nav. */
.app-frame .profile-editor {
  max-width: 720px;
  margin-top: var(--s5);
  margin-inline: auto;
  padding: var(--s5);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--card);
  box-shadow: var(--shadow-sm);
}

.app-frame .p-field {
  border: 0;
  margin: 0;
  padding: 0;
}

.app-frame .p-field + .p-field {
  margin-top: var(--s6);
  padding-top: var(--s5);
  border-top: 1px solid var(--rule);
}

/* Floated so the legend renders as an ordinary block instead of sitting
   inside the fieldset's border, which would break the rule above it. */
.app-frame .p-field legend {
  float: left;
  width: 100%;
  padding: 0;
  margin-bottom: var(--s4);
  font-family: var(--font-display);
  font-size: 18px;
  font-weight: 600;
  letter-spacing: -0.01em;
}

.app-frame .p-field .onb-chips,
.app-frame .p-field .onb-prefs {
  clear: both;
}

.app-frame .p-field .onb-chip,
.app-frame .p-field .onb-pref {
  background: var(--card-2);
}

.app-frame .p-field .onb-chip {
  padding: 9px 16px;
  font-size: 14.5px;
}

.app-frame .p-field .onb-pref {
  border-radius: var(--radius-sm);
}

.app-frame .p-field .onb-chip:has(input:checked),
.app-frame .p-field .onb-pref:has(input:checked) {
  background: var(--accent-soft);
}

.app-frame .p-actions {
  display: flex;
  align-items: center;
  gap: var(--s4);
  margin-top: var(--s5);
}

.app-frame .p-actions .quiet-note {
  margin: 0;
}

@media (max-width: 720px) {
  .app-frame .p-field .onb-prefs {
    grid-template-columns: 1fr;
  }
}

/* ---------- Information file: type chips + evidence blocks ---------- */

.app-frame .info-types {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: var(--s4);
}

.app-frame .info-type-chip {
  padding: 6px 14px;
  border: 1px solid var(--rule);
  border-radius: var(--radius-pill);
  background: var(--card);
  color: var(--slate);
  font-size: 13px;
  font-weight: 600;
  transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}

.app-frame .info-type-chip:hover {
  border-color: var(--slate);
  color: var(--ink);
}

.app-frame .info-type-chip.active {
  background: var(--accent-soft);
  border-color: var(--gold);
  color: var(--gold-deep);
}

/* ---------- Information: ticker search + back ---------- */

.app-frame .info-head {
  align-items: center;
  gap: var(--s3);
}

.app-frame .info-head-left {
  display: flex;
  align-items: center;
  gap: var(--s3);
  min-width: 0;
}

.app-frame .info-back-btn {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 14px;
  border: 1px solid var(--rule);
  border-radius: var(--radius-pill);
  background: var(--card);
  color: var(--slate);
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
  transition: border-color 0.15s ease, color 0.15s ease, background 0.15s ease;
}

.app-frame .info-back-btn:hover {
  border-color: var(--slate);
  color: var(--ink);
}

.app-frame .info-back-btn span {
  font-size: 15px;
  line-height: 1;
}

.app-frame .news-search {
  display: flex;
  align-items: center;
  gap: 8px;
  flex: 0 0 auto;
}

.app-frame .news-search-input {
  min-height: 38px;
  width: 210px;
  max-width: 46vw;
  padding: 0 14px;
  border: 1px solid var(--rule);
  border-radius: var(--radius-pill);
  background: var(--card);
  color: var(--ink);
  font-size: 13px;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.app-frame .news-search-input::placeholder {
  color: var(--slate);
  opacity: 0.7;
  text-transform: none;
  letter-spacing: normal;
}

.app-frame .news-search-input:focus {
  outline: none;
  border-color: var(--gold);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

.app-frame .news-search-btn {
  min-height: 38px;
  padding: 0 18px;
  border: 1px solid var(--gold);
  border-radius: var(--radius-pill);
  background: var(--accent-soft);
  color: var(--gold-deep);
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
  transition: background 0.15s ease, border-color 0.15s ease;
}

.app-frame .news-search-btn:hover {
  background: var(--gold-soft);
  border-color: var(--gold-deep);
}

@media (max-width: 640px) {
  .app-frame .info-head {
    flex-wrap: wrap;
  }
  .app-frame .news-search {
    width: 100%;
  }
  .app-frame .news-search-input {
    flex: 1 1 auto;
    width: auto;
    max-width: none;
  }
}

.app-frame .info-block {
  margin-top: var(--s6);
}

.app-frame .info-sec-head {
  margin: 0 0 var(--s3);
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: 600;
}

.app-frame .info-rows {
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--card);
  box-shadow: var(--shadow-sm);
  padding: 0 var(--s5);
}

.app-frame .info-row {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--s3) var(--s4);
  padding: var(--s3) 0;
  border-top: 1px solid var(--rule);
  font-size: 14px;
}

.app-frame .info-row:first-child {
  border-top: 0;
}

.app-frame .info-row .info-label {
  color: var(--ink-soft);
}

.app-frame .info-row .info-value {
  margin-left: auto;
  font-weight: 600;
}

.app-frame .info-counts {
  font-size: 12.5px;
}

.app-frame .info-meta {
  color: var(--slate);
  font-size: 12px;
}

.app-frame .info-form {
  padding: 1px 8px;
  border: 1px solid var(--rule);
  border-radius: 6px;
  background: var(--card-2);
  font-size: 11.5px;
  font-weight: 600;
}

.app-frame .info-row .text-button {
  margin-left: auto;
  font-size: 13px;
}

.app-frame .table-wrap {
  overflow-x: auto;
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  background: var(--card);
  box-shadow: var(--shadow-sm);
}

.app-frame .info-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13.5px;
}

.app-frame .info-table th {
  padding: var(--s3) var(--s4);
  border-bottom: 1px solid var(--rule);
  color: var(--slate);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  text-align: right;
}

.app-frame .info-table th:first-child,
.app-frame .info-table td:first-child {
  text-align: left;
}

.app-frame .info-table td {
  padding: var(--s3) var(--s4);
  border-bottom: 1px solid var(--rule);
  text-align: right;
  white-space: nowrap;
}

.app-frame .info-table tr:last-child td {
  border-bottom: 0;
}

/* ---------- Filing rows: what it reports + summarize-in-place ---------- */

.app-frame .info-filing {
  display: block;
}

.app-frame .filing-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: var(--s2) var(--s3);
}

.app-frame .filing-what {
  color: var(--ink-soft);
  font-size: 14px;
}

.app-frame .filing-tools {
  display: flex;
  gap: var(--s4);
  margin-top: 6px;
  font-size: 13px;
}

.app-frame .filing-sum-panel {
  margin-top: var(--s3);
}

/* ---------- Analyst ratings: proportion bar ---------- */

.app-frame .info-analyst-row {
  display: block;
}

.app-frame .analyst-bar {
  display: flex;
  gap: 2px;
  height: 8px;
  margin: var(--s2) 0;
  max-width: 420px;
  border-radius: 999px;
  overflow: hidden;
}

.app-frame .ab-seg {
  min-width: 4px;
}

.app-frame .ab-buy { background: var(--gain); }
.app-frame .ab-hold { background: var(--rule); }
.app-frame .ab-sell { background: var(--loss); }

/* ---------- Actions tab: instruction-first cards ---------- */

/* The 3-month trend in the card foot's bottom-left: the line plus a soft
   fill back to the window's first close, colored by net direction — a red
   slide under "Sell…" makes the instruction land at a glance. Hidden when
   the price feed has no answer. */
.act-spark {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  align-self: center;
}

.act-spark svg {
  display: block;
}

.act-spark .act-day {
  font-size: 11px;
  font-weight: 600;
}

/* The imperative headline — the one sentence a user could act on verbatim.
   Serif like every heading, sized between card head and page title. */
.act-instruction {
  margin: var(--s3) 0 0;
  font-family: var(--font-display);
  font-size: 20px;
  font-weight: 600;
  letter-spacing: -0.01em;
  line-height: 1.3;
}

.act-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s2);
  margin-top: var(--s3);
}

.act-foot .act-why {
  margin-left: auto;
}

/* ---------- Information: personalization ---------- */

/* How much of the user's book a headline touches. */
.app-frame .news-touch {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--gold-deep);
  background: var(--gold-soft);
  border-radius: var(--radius-pill);
  padding: 3px 9px;
  white-space: nowrap;
}

/* The engine's one-line "why this matters to you". */
.app-frame .news-note {
  margin: var(--s2) 0 0;
  color: var(--gold-deep);
  font-size: 13.5px;
  font-weight: 500;
  line-height: 1.5;
}

/* ---------- Dashboard: See-actions door ---------- */

.app-frame .dash-actions-count {
  margin: 0 0 var(--s1);
  color: var(--slate);
  font-size: 11.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* ---------- Chat ---------- */

.app-frame .chat-box {
  margin-top: var(--s5);
  background: var(--card);
  border: 1px solid var(--rule);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  padding: var(--s4) var(--s5) var(--s4);
}

.app-frame .chat-thread {
  display: flex;
  flex-direction: column;
  gap: var(--s3);
  min-height: 120px;
  max-height: 55vh;
  overflow-y: auto;
  padding-bottom: var(--s2);
}

.app-frame .chat-thread:empty {
  min-height: 0;
}

.app-frame .chat-msg {
  max-width: 82%;
  padding: var(--s3) var(--s4);
  font-size: 14.5px;
  line-height: 1.6;
}

.app-frame .chat-msg p {
  margin: 0;
}

.app-frame .chat-msg p + p {
  margin-top: var(--s2);
}

.app-frame .chat-msg.is-user {
  align-self: flex-end;
  background: var(--gold-soft);
  color: var(--ink);
  border-radius: 14px 14px 4px 14px;
}

.app-frame .chat-msg.is-assistant {
  align-self: flex-start;
  background: #fff;
  border: 1px solid var(--rule);
  color: var(--ink-soft);
  border-radius: 14px 14px 14px 4px;
}

/* What the answer was built from — the chat's evidence line. */
.app-frame .chat-grounding {
  display: block;
  margin-top: var(--s2);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--slate);
}

/* Three pulsing dots while the model thinks. */
.app-frame .chat-typing p {
  display: flex;
  gap: 4px;
  align-items: center;
  min-height: 12px;
}

.app-frame .chat-typing span {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--slate);
  animation: chat-dot 1.1s ease-in-out infinite;
}

.app-frame .chat-typing span:nth-child(2) {
  animation-delay: 0.18s;
}

.app-frame .chat-typing span:nth-child(3) {
  animation-delay: 0.36s;
}

@keyframes chat-dot {
  0%, 60%, 100% { opacity: 0.35; transform: translateY(0); }
  30% { opacity: 1; transform: translateY(-3px); }
}

.app-frame .chat-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
  margin-top: var(--s3);
}

.app-frame .chat-chip {
  border: 1px solid var(--rule);
  border-radius: var(--radius-pill);
  background: #fff;
  color: var(--navy);
  font-size: 13px;
  font-weight: 600;
  padding: 7px 15px;
  cursor: pointer;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.app-frame .chat-chip:hover,
.app-frame .chat-chip:focus-visible {
  border-color: var(--navy);
  box-shadow: var(--ring);
  outline: none;
}

.app-frame .chat-composer {
  display: flex;
  gap: var(--s3);
  margin-top: var(--s3);
  padding-top: var(--s3);
  border-top: 1px solid var(--rule);
}

.app-frame .chat-input {
  flex: 1;
  min-height: 42px;
  padding: 0 14px;
  border: 1px solid var(--rule);
  border-radius: var(--radius-sm);
  background: #fff;
  color: var(--ink);
  font: inherit;
  font-size: 14.5px;
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.app-frame .chat-input::placeholder {
  color: var(--slate);
  opacity: 0.7;
}

.app-frame .chat-input:focus {
  outline: none;
  border-color: var(--navy);
  box-shadow: var(--ring);
}

@media (max-width: 640px) {
  .app-frame .chat-msg {
    max-width: 94%;
  }
}

/* ---------- Pre-connect explainer sheet ---------- */

.connect-sheet {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--s4);
  background: rgba(10, 26, 26, 0.45);
}

.connect-sheet-card {
  max-width: 460px;
  padding: var(--s5) var(--s6);
  border: 1px solid var(--rule);
  border-radius: var(--radius, 14px);
  /* The sheet lives outside .app-frame, where --card/--shadow are remapped —
     use concrete values so the card never renders transparent. */
  background: #f6fbfb;
  box-shadow: 0 24px 60px rgba(10, 26, 26, 0.35);
}

.connect-sheet-card h3 {
  margin: 0;
  font-size: 20px;
}

.connect-sheet-card p {
  margin: var(--s3) 0 0;
  color: var(--ink-soft);
  font-size: 14.5px;
  line-height: 1.6;
}

.connect-points {
  margin: var(--s4) 0 0;
  padding-left: 18px;
  color: var(--ink-soft);
  font-size: 14px;
  line-height: 1.6;
}

.connect-points li + li {
  margin-top: var(--s2);
}

.connect-points strong {
  color: var(--ink);
}

.connect-sheet-actions {
  display: flex;
  align-items: center;
  gap: var(--s4);
  margin-top: var(--s5);
}

/* ---------- Actions empty state (no brokerage yet) ---------- */

.rec-empty-head {
  margin: 0 0 var(--s2);
  font-size: 19px;
  color: var(--ink);
}

/* A ghost of a real Actions card: what connecting unlocks, visibly not live. */
.act-ghost {
  margin-top: var(--s4);
  opacity: 0.55;
  filter: grayscale(0.4);
  pointer-events: none;
  user-select: none;
}

/* ---------- Strategy Lab: backtest headline under the chart ---------- */

/* strategies.js swaps the muted mono caption for this sentence once a run
   completes. Doubled selector outranks .lab-cap (strategies.css loads after
   this file), so the headline reads big and fully black. */
.lab-cap.lab-headline {
  font-family: var(--font-body);
  font-size: 17px;
  font-weight: 600;
  color: #000;
}
