/* ============================================================
   AI Stock Analyzer — "precision instrument" fintech UI
   Dark-first, mobile-first. Numbers are the hero: everything
   monetary uses tabular mono so digits line up down a column.
   ============================================================ */

@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Sans+Thai:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500;600;700&display=swap');

:root {
  /* canvas: deep blue-black, lifted in layers rather than flat boxes */
  --bg: #080A0F;
  --bg-glow: radial-gradient(1200px 600px at 50% -10%, rgba(0, 224, 164, .07), transparent 60%);
  --surface: #0F131A;
  --surface-2: #161B24;
  --surface-3: #1D242F;
  --line: rgba(255, 255, 255, .07);
  --line-strong: rgba(255, 255, 255, .13);

  --text: #E9EEF5;
  --text-dim: #A3AEBF;
  --muted: #6E7A8C;

  /* one signal colour, used sparingly, so it always means something */
  --accent: #00E0A4;
  --accent-dim: rgba(0, 224, 164, .14);
  --accent-line: rgba(0, 224, 164, .35);

  --up: #2FD08A;
  --down: #FF5C7A;
  --warn: #FFB020;
  --info: #58A6FF;
  --gold: #E8B339;

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, .4);
  --shadow: 0 4px 16px -4px rgba(0, 0, 0, .5);
  --shadow-lg: 0 18px 40px -12px rgba(0, 0, 0, .7);

  --r-sm: 8px;
  --r: 14px;
  --r-lg: 20px;

  --nav-h: 62px;

  --chart-bg: #0F131A;
  --chart-grid: rgba(255, 255, 255, .05);
  --chart-text: #6E7A8C;
}

:root[data-theme="light"] {
  --bg: #F4F6F9;
  --bg-glow: radial-gradient(1200px 600px at 50% -10%, rgba(0, 176, 130, .10), transparent 60%);
  --surface: #FFFFFF;
  --surface-2: #F2F5F8;
  --surface-3: #E8EDF3;
  --line: rgba(9, 20, 35, .09);
  --line-strong: rgba(9, 20, 35, .16);

  --text: #0C1420;
  --text-dim: #465468;
  --muted: #7C8798;

  --accent: #00A97B;
  --accent-dim: rgba(0, 169, 123, .12);
  --accent-line: rgba(0, 169, 123, .32);

  --up: #0F9D62;
  --down: #E11D48;
  --warn: #B45309;
  --info: #2563EB;
  --gold: #B27B10;

  --shadow-sm: 0 1px 2px rgba(16, 30, 54, .06);
  --shadow: 0 6px 18px -6px rgba(16, 30, 54, .14);
  --shadow-lg: 0 20px 44px -16px rgba(16, 30, 54, .22);

  --chart-bg: #FFFFFF;
  --chart-grid: rgba(9, 20, 35, .06);
  --chart-text: #7C8798;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

/* The root size scales across the phone range, so a 320px screen and a 430px
 * one get proportionally sized text and spacing instead of the same fixed
 * pixels. Everything else in this file is already in rem, so it all follows.
 *
 * The ceiling is 1rem — the browser's own base — so anything 480px and wider,
 * desktop included, resolves exactly as it did before. This was meant to fix
 * phones, not to quietly resize a layout that was working.
 *
 * Written in rem rather than px because 1rem means the reader's configured
 * base size: someone who has turned their phone's text up still gets it. */
html {
  -webkit-text-size-adjust: 100%;
  font-size: clamp(0.9375rem, 0.75rem + 0.85vw, 1rem);   /* 15px at 320 → 16px at 480+ */
}

body {
  background: var(--bg);
  background-image: var(--bg-glow);
  background-repeat: no-repeat;
  background-attachment: fixed;
  color: var(--text);
  font-family: "IBM Plex Sans Thai", "Noto Sans Thai", "Leelawadee UI", system-ui, sans-serif;
  font-size: 1rem;          /* was a fixed 15px while everything else used rem */
  line-height: 1.55;
  /* 100vh on mobile Safari counts the strip behind the collapsing URL bar, so
   * the page ends up taller than what is actually visible. dvh tracks the real
   * height; the vh line stays first as a fallback for older browsers. */
  min-height: 100vh;
  min-height: 100dvh;
  padding-bottom: calc(var(--nav-h) + env(safe-area-inset-bottom, 0px));
  -webkit-font-smoothing: antialiased;
}

/* every figure in the app: same width per digit so columns align */
.num, .val, .gauge-num, #curPrice, #overallScore, td, th,
input[type="number"], .money {
  font-family: "IBM Plex Mono", ui-monospace, "Cascadia Mono", monospace;
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

::selection { background: var(--accent-dim); color: var(--text); }

/* ---------------- app bar ---------------- */
header {
  position: sticky; top: 0; z-index: 40;
  background: color-mix(in srgb, var(--bg) 82%, transparent);
  backdrop-filter: saturate(160%) blur(14px);
  border-bottom: 1px solid var(--line);
}
.header-row {
  display: flex; align-items: center; gap: 12px;
  max-width: 1160px; margin: 0 auto; padding: 10px 16px;
  /* Nothing in here may push the page wider than the screen. A phone held
     sideways lands at 812px, which is past the 768px breakpoint, so it gets
     the desktop header - and once the nav grew to five buttons the row needed
     839px and the theme toggle hung 5px off the edge, giving the whole app a
     horizontal scroll in landscape. */
  min-width: 0; overflow: hidden;
}
.brand {
  display: flex; flex-direction: column; line-height: 1.15;
  font-weight: 700; font-size: 1rem; letter-spacing: -.015em; white-space: nowrap;
  /* the title may be clipped before anything is pushed off-screen */
  min-width: 0; overflow: hidden; text-overflow: ellipsis;
}
.brand small {
  font-family: "IBM Plex Mono", monospace;
  font-size: .72rem; font-weight: 400; color: var(--muted);
  letter-spacing: .08em; text-transform: uppercase;
}
.brand-mark {
  display: inline-flex; align-items: center; justify-content: center;
  width: 30px; height: 30px; margin-right: 2px; border-radius: 9px;
  background: linear-gradient(145deg, var(--accent), color-mix(in srgb, var(--accent) 55%, var(--info)));
  color: #04120D; font-weight: 700; font-size: .95rem; flex: none;
  box-shadow: 0 2px 10px -2px var(--accent-line);
}

/* desktop segmented nav (hidden on phones — bottom bar takes over) */
.mainnav {
  display: none; gap: 2px; margin-left: auto;
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: 12px; padding: 3px;
  /* five buttons no longer fit a landscape phone at the desktop breakpoint, so
     the strip scrolls rather than shoving the row off-screen */
  min-width: 0; overflow-x: auto; scrollbar-width: none;
}
.mainnav::-webkit-scrollbar { display: none; }
.mainnav button {
  background: none; border: none; color: var(--text-dim); cursor: pointer;
  padding: 7px 16px; border-radius: 9px; font: inherit; font-size: .88rem; font-weight: 600;
  transition: color .18s, background .18s; white-space: nowrap; flex: none;
}
.mainnav button:hover { color: var(--text); }
.mainnav button.active {
  background: var(--surface); color: var(--accent);
  box-shadow: var(--shadow-sm); border: 1px solid var(--accent-line);
}

.icon-btn {
  background: var(--surface-2); color: var(--text-dim);
  border: 1px solid var(--line); border-radius: 11px;
  width: 38px; height: 38px; flex: none; cursor: pointer; font-size: 1rem;
  display: inline-flex; align-items: center; justify-content: center;
  transition: border-color .18s, color .18s, transform .1s;
}
.icon-btn:hover { color: var(--text); border-color: var(--line-strong); }
.icon-btn:active { transform: scale(.94); }

/* ---------------- live price indicator ---------------- */
.live-badge {
  display: inline-flex; align-items: center; gap: 6px; flex: none;
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: 999px; padding: 4px 6px 4px 10px;
  font-family: "IBM Plex Mono", monospace; font-size: .72rem;
  letter-spacing: .06em; color: var(--text-dim);
}
.live-dot {
  width: 7px; height: 7px; border-radius: 50%; flex: none;
  background: var(--up); box-shadow: 0 0 0 0 var(--up);
}
.live-dot.live { animation: pulse 2s ease-out infinite; }
.live-dot.paused { background: var(--muted); box-shadow: none; animation: none; }
.live-dot.stale { background: var(--warn); animation: none; }
@keyframes pulse {
  0% { box-shadow: 0 0 0 0 color-mix(in srgb, var(--up) 70%, transparent); }
  70% { box-shadow: 0 0 0 7px transparent; }
  100% { box-shadow: 0 0 0 0 transparent; }
}
.live-clock { color: var(--muted); }
.live-toggle {
  background: none; border: none; color: var(--text-dim); cursor: pointer;
  font-size: .7rem; padding: 2px 5px; border-radius: 6px; line-height: 1;
}
.live-toggle:hover { color: var(--accent); background: var(--accent-dim); }

/* a value that just moved gets a brief tint — the app-trader tell that
   something is genuinely live rather than a stale render */
@keyframes flashUp {
  0% { background: color-mix(in srgb, var(--up) 30%, transparent); }
  100% { background: transparent; }
}
@keyframes flashDown {
  0% { background: color-mix(in srgb, var(--down) 30%, transparent); }
  100% { background: transparent; }
}
.flash-up { animation: flashUp 1s ease-out; border-radius: 5px; }
.flash-down { animation: flashDown 1s ease-out; border-radius: 5px; }

/* ---------------- bottom tab bar (mobile) ---------------- */
.tabbar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 50;
  display: flex; align-items: stretch;
  height: calc(var(--nav-h) + env(safe-area-inset-bottom, 0px));
  padding-bottom: env(safe-area-inset-bottom, 0px);
  background: color-mix(in srgb, var(--surface) 92%, transparent);
  backdrop-filter: saturate(180%) blur(18px);
  border-top: 1px solid var(--line);
}
.tabbar button {
  flex: 1; background: none; border: none; cursor: pointer; font: inherit;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 3px; color: var(--muted); position: relative;
  font-size: .74rem; font-weight: 600; letter-spacing: .01em;
  transition: color .2s;
  -webkit-tap-highlight-color: transparent;
}
.tabbar button .ic { font-size: 1.25rem; line-height: 1; transition: transform .22s cubic-bezier(.34,1.56,.64,1); }
.tabbar button.active { color: var(--accent); }
.tabbar button.active .ic { transform: translateY(-2px) scale(1.1); }
.tabbar button.active::before {
  content: ""; position: absolute; top: 0; left: 50%; translate: -50% 0;
  width: 26px; height: 2.5px; border-radius: 0 0 3px 3px; background: var(--accent);
  box-shadow: 0 0 12px var(--accent);
}

/* ---------------- layout ---------------- */
.view { display: none; }
.view.active { display: block; animation: rise .32s cubic-bezier(.22,1,.36,1); }
@keyframes rise { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }

main, .port-wrap, .analyze-bar, .status { max-width: 1160px; margin: 0 auto; }
main, .port-wrap { padding: 16px; }
.analyze-bar { padding: 16px 16px 0; }
.status { padding: 10px 16px; color: var(--text-dim); font-size: .88rem; }
.status.error { color: var(--down); }
.hidden { display: none !important; }

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r);
  padding: 16px;
  margin-bottom: 12px;
  box-shadow: var(--shadow-sm);
  position: relative;
}
.card > h2 {
  font-size: .95rem; font-weight: 700; letter-spacing: -.01em;
  margin-bottom: 12px; display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
}
h3 {
  font-size: .78rem; font-weight: 600; color: var(--muted);
  text-transform: uppercase; letter-spacing: .09em; margin: 18px 0 8px;
}

/* ---------------- buttons ---------------- */
button.primary {
  background: var(--accent); color: #04140E; border: none;
  border-radius: 11px; padding: 10px 18px; cursor: pointer;
  font: inherit; font-weight: 700; font-size: .9rem;
  box-shadow: 0 2px 12px -3px var(--accent-line);
  transition: filter .16s, transform .1s;
}
button.primary:hover { filter: brightness(1.08); }
button.primary:active { transform: scale(.97); }
button.primary.small { padding: 8px 14px; font-size: .84rem; }

.row-btn {
  background: var(--surface-2); border: 1px solid var(--line); color: var(--text-dim);
  border-radius: 9px; padding: 6px 12px; font: inherit; font-size: .78rem; font-weight: 600;
  cursor: pointer; transition: all .16s; white-space: nowrap;
}
.row-btn:hover { color: var(--accent); border-color: var(--accent-line); background: var(--accent-dim); }
.row-btn:active { transform: scale(.96); }

/* ---------------- inputs ---------------- */
input, select {
  background: var(--surface-2); color: var(--text);
  border: 1px solid var(--line); border-radius: 11px;
  padding: 10px 13px; font: inherit; outline: none;
  /* Never below 16px. Safari on iPhone zooms the page in when a field with
   * smaller text is focused and does not zoom back out, so every entry left
   * the user pinching to recover. All twelve fields were at 14.7px. */
  font-size: max(16px, .92rem);
  transition: border-color .16s, box-shadow .16s;
  min-width: 0;
}
input:focus, select:focus {
  border-color: var(--accent-line);
  box-shadow: 0 0 0 3px var(--accent-dim);
}
input::placeholder { color: var(--muted); }

.searchbar { display: flex; gap: 8px; }
.searchbar input { flex: 1; }


.quick { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.quick span {
  border: 1px solid var(--line); background: var(--surface);
  border-radius: 999px; padding: 5px 13px; font-size: .8rem; font-weight: 500;
  color: var(--text-dim); cursor: pointer; transition: all .16s;
}
.quick span:hover { color: var(--accent); border-color: var(--accent-line); background: var(--accent-dim); }

/* ---------------- hero / overview ---------------- */
.overview { display: grid; gap: 12px; }
.score-card { overflow: hidden; }
.score-card::after {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 1px;
  background: linear-gradient(90deg, transparent, var(--accent-line), transparent);
}
.company { font-size: .82rem; color: var(--muted); letter-spacing: .01em; }
.price-row { display: flex; align-items: baseline; gap: 10px; margin: 6px 0 16px; flex-wrap: wrap; }
#curPrice { font-size: 2rem; font-weight: 600; letter-spacing: -.03em; }
#curChange { font-size: 1rem; font-weight: 600; }

.up { color: var(--up); }
.down { color: var(--down); }

.gauge-wrap { display: flex; align-items: center; gap: 14px; }
.gauge {
  flex: 1; height: 7px; border-radius: 99px; overflow: hidden;
  background: var(--surface-3);
  box-shadow: inset 0 1px 2px rgba(0,0,0,.3);
}
.gauge-fill {
  height: 100%; width: 0; border-radius: 99px;
  transition: width .9s cubic-bezier(.22,1,.36,1);
  box-shadow: 0 0 12px -2px currentColor;
}
.gauge-num { font-size: 1.5rem; font-weight: 600; min-width: 58px; text-align: right; letter-spacing: -.02em; }
.verdict { margin-top: 10px; font-size: 1.02rem; font-weight: 700; letter-spacing: -.01em; }
.strong-buy, .buy { color: var(--up); }
.hold { color: var(--warn); }
.caution { color: #FF8A3D; }
.sell { color: var(--down); }

/* timeframe chips */
.tf-summary { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.tf-chip {
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: var(--r-sm); padding: 12px 8px; text-align: center; cursor: pointer;
  transition: border-color .18s, transform .12s;
}
.tf-chip:hover { border-color: var(--accent-line); transform: translateY(-1px); }
.tf-chip .tf-name { color: var(--muted); font-size: .74rem; letter-spacing: .02em; }
.tf-chip .tf-score {
  font-family: "IBM Plex Mono", monospace; font-variant-numeric: tabular-nums;
  font-size: 1.45rem; font-weight: 600; margin: 3px 0; letter-spacing: -.03em;
}
.tf-chip .tf-verdict { font-size: .72rem; font-weight: 600; }

/* ---------------- sub tabs ---------------- */
.tabs {
  display: flex; gap: 4px; margin: 4px 0 14px; padding-bottom: 2px;
  overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch;
}
.tabs::-webkit-scrollbar { display: none; }
.tabs button {
  background: var(--surface); color: var(--text-dim);
  border: 1px solid var(--line); border-radius: 999px;
  padding: 8px 15px; cursor: pointer; font: inherit; font-size: .84rem; font-weight: 600;
  white-space: nowrap; transition: all .18s;
}
.tabs button:hover { color: var(--text); }
.tabs button.active {
  background: var(--accent-dim); color: var(--accent); border-color: var(--accent-line);
}
.tab-pane { display: none; }
.tab-pane.active { display: block; animation: rise .28s cubic-bezier(.22,1,.36,1); }

/* ---------------- datagrid: table on desktop, cards on phone ---------------- */
.datagrid { display: flex; flex-direction: column; gap: 8px; }
.dg-head { display: none; }                       /* phones: no header row */
.rowcard {
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: var(--r); padding: 13px 14px;
  display: grid; gap: 8px;
  transition: border-color .18s, transform .12s;
  animation: rise .3s cubic-bezier(.22,1,.36,1) backwards;
}
.rowcard:hover { border-color: var(--line-strong); }
.rowcard .cell { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; min-width: 0; }
.rowcard .cell::before {
  content: attr(data-label);
  font-size: .72rem; color: var(--muted); font-weight: 500; flex: none;
  letter-spacing: .01em;
}
.rowcard .cell.no-label::before { content: none; }
.rowcard .cell > * { min-width: 0; }
.cell-v { font-weight: 600; text-align: right; }

/* the identity cell of each card (symbol + name) spans the top */
.rc-title { display: flex; align-items: center; gap: 9px; min-width: 0; }
.rc-sym { font-weight: 700; font-size: 1rem; letter-spacing: -.01em; }
.rc-name { font-size: .74rem; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.rc-actions { display: flex; gap: 6px; flex-wrap: wrap; }

/* rank badge for scanner / backtest */
.rank {
  display: inline-flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; flex: none; border-radius: 8px;
  background: var(--surface-3); color: var(--text-dim);
  font-family: "IBM Plex Mono", monospace; font-size: .78rem; font-weight: 700;
}
.rank.top { background: var(--accent-dim); color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent-line); }

/* strength / weight meters */
.meter { height: 6px; border-radius: 99px; background: var(--surface-3); overflow: hidden; flex: 1; min-width: 40px; }
.meter > i { display: block; height: 100%; border-radius: 99px; }
.meter-row { display: flex; align-items: center; gap: 8px; width: 100%; }

/* legacy tables (fundamentals etc.) still readable */
table { width: 100%; border-collapse: collapse; font-size: .86rem; }
th, td { text-align: left; padding: 9px 10px; border-bottom: 1px solid var(--line); }
tr:last-child td { border-bottom: none; }
th {
  color: var(--muted); font-weight: 600; font-size: .7rem;
  text-transform: uppercase; letter-spacing: .08em;
  font-family: "IBM Plex Sans Thai", sans-serif;
}
.scroll-x { overflow-x: auto; -webkit-overflow-scrolling: touch; }

/* correlation heatmap — square-ish cells so a 4-asset matrix fits a phone */
.corr-table { font-size: .78rem; }
.corr-table th, .corr-table td { padding: 7px 6px; text-align: center; border: 1px solid var(--line); }
.corr-table th { font-size: .74rem; color: var(--text-dim); text-transform: none; letter-spacing: 0; white-space: nowrap; }
.corr-table td { font-family: "IBM Plex Mono", monospace; font-variant-numeric: tabular-nums; border-radius: 4px; }

/* ---------------- chips ---------------- */
.sig, .sent, .buy-now, .badge, .method-tag {
  display: inline-flex; align-items: center; gap: 5px;
  border-radius: 999px; padding: 3px 11px;
  font-size: .74rem; font-weight: 600; line-height: 1.5;
  border: 1px solid transparent;
}
.sig.buy   { background: color-mix(in srgb, var(--up) 14%, transparent); color: var(--up); border-color: color-mix(in srgb, var(--up) 30%, transparent); }
.sig.hold  { background: var(--surface-3); color: var(--text-dim); border-color: var(--line); }
.sig.caution { background: color-mix(in srgb, var(--warn) 15%, transparent); color: var(--warn); border-color: color-mix(in srgb, var(--warn) 32%, transparent); }
.sig.sell  { background: color-mix(in srgb, var(--down) 14%, transparent); color: var(--down); border-color: color-mix(in srgb, var(--down) 30%, transparent); }
.sent.positive { background: color-mix(in srgb, var(--up) 13%, transparent); color: var(--up); }
.sent.negative { background: color-mix(in srgb, var(--down) 13%, transparent); color: var(--down); }
.sent.neutral  { background: var(--surface-3); color: var(--muted); }
.badge { background: var(--surface-3); color: var(--text-dim); font-family: "IBM Plex Mono", monospace; }
.method-tag { background: var(--surface-3); color: var(--info); font-size: .74rem; padding: 2px 9px; margin: 1px 2px 1px 0; }
.buy-now.yes { background: color-mix(in srgb, var(--up) 14%, transparent); color: var(--up); }
.buy-now.no  { background: color-mix(in srgb, var(--warn) 14%, transparent); color: var(--warn); }

/* ---------------- entry plan ---------------- */
.entry-card {
  background: linear-gradient(160deg, color-mix(in srgb, var(--up) 8%, var(--surface)), var(--surface) 60%);
  border-color: color-mix(in srgb, var(--up) 26%, transparent);
}
.entry-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 8px; margin-top: 10px; }
.entry-item, .psum, .bt-item, .fund-item, .comp {
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: var(--r-sm); padding: 11px 13px;
}
.entry-item .lbl, .psum .lbl, .bt-item .lbl, .fund-item .lbl {
  font-size: .7rem; color: var(--muted); letter-spacing: .02em;
}
.entry-item .val, .psum .val, .bt-item .val, .fund-item .val {
  font-size: 1.12rem; font-weight: 600; margin-top: 3px; letter-spacing: -.02em;
}

/* ---------------- portfolio ---------------- */
.port-head { display: flex; justify-content: space-between; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 10px; }
.port-head h2 { margin: 0; }
.port-head > div { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; }
.port-form {
  display: grid; gap: 8px; margin: 12px 0; padding: 13px;
  background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r);
}
.port-summary { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; margin: 12px 0; }
.port-summary .psum:first-child {
  grid-column: 1 / -1;
  background: linear-gradient(150deg, var(--surface-3), var(--surface-2));
  border-color: var(--line-strong);
}
.port-summary .psum:first-child .val { font-size: 1.7rem; }
.sym-link { color: var(--text); }
.sym-link:hover { color: var(--accent); text-decoration: none; }

.dca-box { background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r); padding: 14px; margin-top: 12px; }
.dca-inputs { display: flex; gap: 8px; flex-wrap: wrap; align-items: center; margin: 8px 0; }
.dca-result { display: grid; grid-template-columns: repeat(auto-fit, minmax(130px, 1fr)); gap: 8px; margin-top: 10px; }

/* allocation bar */
.alloc-bar { display: flex; height: 10px; border-radius: 99px; overflow: hidden; margin: 8px 0 10px; background: var(--surface-3); }
.alloc-bar > div { height: 100%; }
.alloc-legend { display: flex; flex-wrap: wrap; gap: 10px; font-size: .76rem; color: var(--text-dim); margin-bottom: 8px; }
.alloc-legend i { display: inline-block; width: 9px; height: 9px; border-radius: 3px; margin-right: 5px; }

/* score components */
.comp-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 8px; }
.comp .comp-head { display: flex; justify-content: space-between; font-weight: 600; margin-bottom: 6px; font-size: .86rem; }
.comp ul { list-style: none; }
.comp li { font-size: .8rem; color: var(--text-dim); padding: 2px 0; line-height: 1.5; }
.comp li::before { content: "▸ "; color: var(--accent); }

.fund-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; margin: 12px 0; }
.fund-item .fnote { font-size: .72rem; color: var(--muted); }
.fund-item .fbar { height: 4px; border-radius: 99px; background: var(--surface-3); margin-top: 7px; overflow: hidden; }
.fund-item .fbar > div { height: 100%; border-radius: 99px; }
.company-info { font-size: .84rem; color: var(--text-dim); line-height: 1.65; margin-top: 8px; }

/* ---------------- multi-factor blend ---------------- */
.factor-summary { display: flex; align-items: center; gap: 14px; margin: 14px 0 4px; }
.factor-summary .fs-num { font-family: "IBM Plex Mono", monospace; font-size: 2.1rem; font-weight: 600; line-height: 1; }
.factor-summary .fs-txt { font-size: .88rem; line-height: 1.5; }
.factor-summary .fs-txt .mini-note { margin: 2px 0 0; }

.factor-caveat {
  font-size: .78rem; color: var(--text-dim); line-height: 1.6;
  background: color-mix(in srgb, var(--warn) 10%, transparent);
  border-left: 3px solid var(--warn); border-radius: 8px; padding: 9px 12px; margin: 10px 0;
}

.factor-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 10px; margin: 12px 0; }
.factor-card { background: var(--surface-2); border: 1px solid var(--line); border-radius: 12px; padding: 12px 13px; }
.factor-card.off { opacity: .62; }
.factor-head { display: flex; justify-content: space-between; align-items: baseline; gap: 8px; }
.factor-name { font-weight: 600; font-size: .87rem; }
.factor-score { font-family: "IBM Plex Mono", monospace; font-weight: 600; font-size: 1.15rem; }
.factor-card .fbar { height: 4px; border-radius: 99px; background: var(--surface-3); margin: 8px 0 9px; overflow: hidden; }
.factor-card .fbar > div { height: 100%; border-radius: 99px; }
.factor-why { font-size: .69rem; color: var(--muted); line-height: 1.55; }
.factor-rows { margin-top: 9px; border-top: 1px solid var(--line); padding-top: 7px; }
.factor-row { display: grid; grid-template-columns: 1fr auto 34px; gap: 8px; align-items: baseline; padding: 3px 0; font-size: .76rem; }
.factor-row .frl { color: var(--text-dim); }
.factor-row .frv { font-weight: 600; }
.factor-row .frs { text-align: right; font-family: "IBM Plex Mono", monospace; font-size: .72rem; }

.bt-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(120px, 1fr)); gap: 8px; margin-top: 8px; }
.bt-item { text-align: center; }

/* news */
.news-item { padding: 12px 0; border-bottom: 1px solid var(--line); }
.news-item:last-child { border-bottom: none; }
.news-item a { color: var(--text); font-weight: 600; font-size: .9rem; line-height: 1.45; }
.news-item a:hover { color: var(--accent); text-decoration: none; }
.news-meta { font-size: .72rem; color: var(--muted); margin-top: 4px; }

/* chart */
.chart-box {
  height: 300px; border-radius: var(--r); overflow: hidden;
  border: 1px solid var(--line); margin-bottom: 8px; background: var(--chart-bg);
}
.legend { font-size: .74rem; color: var(--muted); margin-bottom: 10px; }
.legend .g { color: var(--up); } .legend .r { color: var(--down); }

/* ai panel */
.ai-controls { display: flex; gap: 8px; margin: 12px 0; flex-wrap: wrap; }
.ai-controls input { flex: 1; min-width: 180px; }
.claude-out {
  background: var(--surface-2); border: 1px solid var(--line);
  border-radius: var(--r); padding: 16px; line-height: 1.8;
  white-space: pre-wrap; font-size: .9rem;
}

.mini-note { color: var(--muted); font-size: .8rem; margin: 4px 0; line-height: 1.55; }
.disclaimer { color: var(--muted); font-size: .72rem; text-align: center; margin: 20px 0 8px; opacity: .85; }
.spin { display: inline-block; animation: spin 1s linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

/* stagger the reveal of list items — one orchestrated moment, not noise */
.rowcard:nth-child(1) { animation-delay: .02s }
.rowcard:nth-child(2) { animation-delay: .06s }
.rowcard:nth-child(3) { animation-delay: .10s }
.rowcard:nth-child(4) { animation-delay: .14s }
.rowcard:nth-child(5) { animation-delay: .18s }
.rowcard:nth-child(n+6) { animation-delay: .22s }

/* ============================================================
   TABLET / DESKTOP
   ============================================================ */
@media (min-width: 720px) {
  /* was 15.5px — kept to the same value, but in rem so it stays inside the
     one sizing system instead of being a second, fixed one */
  body { padding-bottom: 0; font-size: .97rem; }
  .tabbar { display: none; }
  .mainnav { display: flex; }
  .header-row { padding: 12px 24px; }
  main, .port-wrap { padding: 20px 24px 40px; }
  .analyze-bar { padding: 20px 24px 0; }
  .card { padding: 20px; border-radius: var(--r-lg); }
  .chart-box { height: 400px; }
  #curPrice { font-size: 2.3rem; }
  .overview { grid-template-columns: 340px 1fr; align-items: start; }
  .port-summary { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
  .port-summary .psum:first-child { grid-column: auto; }
  .port-summary .psum:first-child .val { font-size: 1.12rem; }
  .port-form { grid-auto-flow: column; grid-auto-columns: max-content; align-items: center; }

  /* datagrid becomes a real table: aligned columns + sticky-ish header */
  .datagrid { gap: 0; border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; }
  /* the column template only exists from tablet up — on phones each row stays
     a single-column card, which is why --cols is a variable and not inline CSS */
  .dg-head, .rowcard { grid-template-columns: var(--cols); }
  .dg-head {
    display: grid; gap: 12px; padding: 10px 14px;
    background: var(--surface-2); border-bottom: 1px solid var(--line);
    font-size: .74rem; color: var(--muted); font-weight: 600;
    text-transform: uppercase; letter-spacing: .08em;
  }
  .rowcard {
    align-items: center; gap: 12px;
    border: none; border-bottom: 1px solid var(--line); border-radius: 0;
    background: var(--surface); padding: 12px 14px;
  }
  .rowcard:last-child { border-bottom: none; }
  .rowcard:hover { background: var(--surface-2); }
  .rowcard .cell { display: block; }
  .rowcard .cell::before { content: none; }     /* header row supplies the labels */
  .rowcard .cell:not(.rc-first):not(.rc-sigline) { text-align: right; }
  .rowcard .cell:not(.rc-first):not(.rc-sigline) .cell-v { text-align: right; }
  .dg-head > span:not(:first-child) { text-align: right; }
  .dg-head > span:last-child { text-align: left; }
  /* the signal sub-line sits under its row, full width */
  .rc-sigline { border-top: 1px dashed var(--line); padding-top: 6px; margin-top: 2px; }
  .rowcard .rc-title .sig { margin-left: 8px !important; }
}

@media (min-width: 1000px) {
  .comp-grid { grid-template-columns: repeat(4, 1fr); }
}

/* respect reduced motion */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

/* ---------------- touch targets ----------------
 * Last in the file on purpose: these are overrides, and several of the rules
 * they correct (.rc-actions, .row-btn) are declared further down than where
 * this block would otherwise sit, so an earlier copy silently lost.
 *
 * Keyed to the input device rather than screen width — a finger needs room
 * whatever size the phone is, and a mouse does not need it on a narrow window.
 * 48px is Android's Material minimum and the larger of the two common
 * guidelines (Apple asks 44), so it satisfies both. Before this block, 15 of
 * 21 controls were under it: the live-price toggle was 21x15px, and "ลบ" sat
 * 6px from "แก้ไข" at 33px tall — a delete button narrower than a thumb. */
@media (pointer: coarse) {
  button, .row-btn, .icon-btn, .live-toggle, input, select, .chip { min-height: 48px; }
  button, .row-btn { padding-block: 11px; }
  .icon-btn { width: 48px; height: 48px; }
  .live-toggle {
    min-width: 48px; display: inline-flex; align-items: center; justify-content: center;
  }
  .rc-actions { gap: 12px; }               /* was 6px, between DCA / แก้ไข / ลบ */
  .row-btn { padding-inline: 14px; }
  .rowcard a { display: inline-block; min-height: 48px; line-height: 2.8; }
  /* Height was already 48px; width was not, so a two-character button like
     "ลบ" came out 41px across and a short ticker link 38px - both below the
     48dp Android asks for in *both* directions, and both of them destructive
     or navigational enough that a missed tap costs something. */
  .row-btn, .rowcard a, .icon-btn, .chip { min-width: 48px; }
}

/* ---------------- narrow phones ----------------
 * The header was a flex row of fixed-width parts: a brand locked to nowrap,
 * a live badge carrying dot + "LIVE" + clock + toggle, and a theme button.
 * Together they measured 429px, so every iPhone from the SE at 320 up to the
 * Pro Max at 430 scrolled sideways on the very first screen. It went unseen
 * because the preview pane is 446px wide — just wide enough to hide it.
 *
 * The word "LIVE" goes first: the dot beside it already carries that state in
 * colour. The clock stays — on a live-price app, knowing how fresh a number
 * is matters more than a label repeating what the dot says. */
@media (max-width: 480px) {
  .header-row { gap: 8px; padding: 10px 12px; }
  .brand {
    font-size: .92rem;
    min-width: 0; overflow: hidden; text-overflow: ellipsis;   /* last-resort truncation */
  }
  .brand small { display: none; }
  #liveText { display: none; }
  .live-badge { padding: 4px 4px 4px 8px; gap: 5px; }
}

/* ---------------- settings page ---------------- */
.set-grid { display: flex; flex-direction: column; gap: 2px; margin: 10px 0 4px; }
.set-row {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  padding: 11px 0; border-bottom: 1px solid var(--line); min-width: 0;
}
.set-row:last-child { border-bottom: none; }
.set-row > span:first-child { color: var(--text-dim); font-size: .86rem; flex: 1; min-width: 0; }
.set-row > b { font-weight: 600; text-align: right; word-break: break-word; }
.set-row input[type="number"], .set-row select { max-width: 190px; flex: none; }
.set-row input[type="checkbox"] { width: 22px; height: 22px; accent-color: var(--accent); flex: none; }
.set-row code { font-size: .74rem; word-break: break-all; }

/* ==================== CALENDAR ==================== */
.cal-filters { display: flex; flex-wrap: wrap; gap: 6px; margin: 10px 0 14px; }
.chip {
  background: var(--surface-2); color: var(--text-dim);
  border: 1px solid var(--line); border-radius: 999px;
  padding: 6px 12px; font-size: .8rem; cursor: pointer;
  font-family: inherit; transition: background .15s, color .15s;
}
.chip:hover { color: var(--text); }
.chip.on { background: var(--accent); color: #fff; border-color: var(--accent); }

.cal-day { display: flex; gap: 12px; padding: 10px 0; border-top: 1px solid var(--line); }
.cal-day:first-child { border-top: none; }
.cal-date {
  flex: 0 0 58px; text-align: center; display: flex; flex-direction: column;
  align-items: center; justify-content: flex-start; padding-top: 4px;
}
.cal-dnum { font-size: 1.5rem; font-weight: 700; line-height: 1; }
.cal-dmon { font-size: .74rem; color: var(--text-dim); }
.cal-dwd  { font-size: .7rem; color: var(--muted); margin-top: 2px; }
.cal-items { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 8px; }

.cal-item {
  background: var(--surface-2); border-radius: 8px;
  border-left: 3px solid var(--muted); padding: 8px 11px;
}
.cal-item.past { opacity: .5; }
.cal-item-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 7px; }
.cal-time { font-variant-numeric: tabular-nums; color: var(--text-dim); font-size: .8rem; }
.cal-imp  { color: var(--warn); font-size: .68rem; letter-spacing: 1px; }
.cal-cd   { margin-left: auto; font-size: .76rem; color: var(--accent); font-variant-numeric: tabular-nums; }
.cal-detail { font-size: .8rem; color: var(--text-dim); margin-top: 4px; line-height: 1.5; }
.cal-local  { font-size: .72rem; color: var(--muted); margin-top: 3px; }

/* An estimated date must not be able to pass for a confirmed one at a glance. */
.cal-flag { font-size: .74rem; padding: 1px 7px; border-radius: 999px; white-space: nowrap; }
.cal-flag.ok  { background: color-mix(in srgb, var(--up) 18%, transparent); color: var(--up); }
.cal-flag.est { background: color-mix(in srgb, var(--warn) 20%, transparent); color: var(--warn); }

@media (max-width: 640px) {
  .cal-date { flex-basis: 46px; }
  .cal-dnum { font-size: 1.25rem; }
  .cal-cd { margin-left: 0; flex-basis: 100%; }
}

/* live event results */
.live-box {
  background: var(--surface-2); border-radius: var(--r-sm);
  border-left: 3px solid var(--accent); padding: 11px 13px; margin-bottom: 12px;
}
.live-box.watching { border-left-color: var(--down); }
.live-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px; margin-bottom: 9px; }
.live-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(155px, 1fr)); gap: 9px; }
.live-cell { background: var(--surface); border-radius: var(--r-sm); padding: 9px 11px; }
.lc-lbl { font-size: .74rem; color: var(--text-dim); }
.lc-val { font-size: 1.1rem; font-weight: 700; margin: 2px 0; font-variant-numeric: tabular-nums; }
.lc-sub { font-size: .7rem; color: var(--muted); }
.lc-link { font-size: .72rem; color: var(--accent); text-decoration: none; display: inline-block; margin-top: 4px; }
.lc-link:hover { text-decoration: underline; }

/* ============================================================
   TOUCH SCREENS: no pointer, so :hover must not linger
   ============================================================
   A tap on Android matches :hover and the style stays applied until something
   else is tapped, so a button the user pressed a minute ago is still lit and a
   card they opened is still raised. Fifteen rules in this file change colour,
   background or position on hover and none of them were guarded.

   Each override restores the element's own resting value - taken from its base
   rule, not guessed - and every selector that has a selected state excludes it,
   because these rules sit at the end of the file and would otherwise outrank
   .active and .on at equal specificity and strip the highlight from whichever
   tab or chip the user is actually on. */
@media (hover: none) {
  a:hover { text-decoration: none; }
  .mainnav button:hover:not(.active) { color: var(--text-dim); }
  .icon-btn:hover { color: var(--text-dim); border-color: var(--line); }
  .live-toggle:hover { color: var(--text-dim); background: none; }
  button.primary:hover { filter: none; }
  .row-btn:hover { color: var(--text-dim); border-color: var(--line); background: var(--surface-2); }
  .quick span:hover { color: var(--text-dim); border-color: var(--line); background: var(--surface); }
  .tf-chip:hover { border-color: var(--line); transform: none; }
  .tabs button:hover:not(.active) { color: var(--text-dim); }
  .rowcard:hover { border-color: var(--line); }
  .sym-link:hover { color: var(--accent); text-decoration: none; }
  .news-item a:hover { color: var(--accent); }
  .chip:hover:not(.on) { color: var(--text-dim); }
  .lc-link:hover { text-decoration: none; }
}

/* The default tap flash is a light blue square, which on this palette reads as
   a rendering fault rather than feedback. */
* { -webkit-tap-highlight-color: color-mix(in srgb, var(--accent) 22%, transparent); }
