/* #region zone:desk.style.base — ฟอนต์ โทเค็นสี และสไตล์พื้นฐาน */
/* Super_T Web Desk — all styling lives here (CSP forbids inline <style>).
   Tokens from STRUCTURE.md §5 / the spec's §6 "Style" paragraph. Apple-like:
   generous, consistent rounding, soft shadows, no sharp corners anywhere. */

@font-face {
  font-family: 'Anuphan';
  src: url('fonts/Anuphan.ttf') format('truetype');
  font-weight: 400 700;
  font-display: swap;
}
@font-face {
  font-family: 'JetBrains Mono';
  src: url('fonts/JetBrainsMono.ttf') format('truetype');
  font-weight: 400 700;
  font-display: swap;
}

/* All design tokens (colour, radius, logo depth, type/spacing/motion scale) moved to
   desk-tokens.css (2026-09-26, batch J) — one home per concept, loaded before this file. */

* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; }
html { -webkit-text-size-adjust: 100%; }
body {
  background: var(--bg);
  color: var(--text);
  font-family: 'Anuphan', system-ui, -apple-system, 'Segoe UI', sans-serif;
  font-size: var(--u-text-sm);
  -webkit-font-smoothing: antialiased;
  padding-left: max(0px, env(safe-area-inset-left, 0px));
  padding-right: max(0px, env(safe-area-inset-right, 0px));
}
[hidden] { display: none !important; }
img { max-width: 100%; }
a { color: var(--accent-text); text-decoration: none; }
a:hover { text-decoration: underline; }
input, button, textarea { font-family: inherit; color: inherit; }
input::placeholder, textarea::placeholder { color: var(--faint); }
button { cursor: pointer; }
.mono { font-family: 'JetBrains Mono', ui-monospace, monospace; }
.tabular-nums { font-variant-numeric: tabular-nums; }

::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-thumb { background: var(--line); border-radius: 4px; }
::-webkit-scrollbar-track { background: transparent; }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 4px;
}
/* The header and phone tab bar use the accent-text colour (--mint) for the focus ring: >=4.5:1 on --header-bg. */
.app-header :focus-visible, .bottom-tabbar :focus-visible { outline-color: var(--mint); }
/* Text fields set outline:none for their resting look; this restores a visible focus state. */
.auth-form input:focus, .chat-form textarea:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--acc-ring); }
.search-wrap input:focus { border-color: var(--mint); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; }
}

@keyframes stPulse { 0%, 100% { opacity: 1; } 50% { opacity: .35; } }
@keyframes stIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@keyframes stSpin { to { transform: rotate(360deg); } }
@keyframes stProgress { 0% { transform: translateX(-100%) scaleX(.4); } 50% { transform: translateX(20%) scaleX(.6); } 100% { transform: translateX(100%) scaleX(.4); } }
/* Expanding/fading ring behind the live-price status dot (owner request: the realtime indicator
   must visibly pulse). The global prefers-reduced-motion rule above already clamps this to a
   single near-instant cycle, leaving just the solid coloured dot/pill behind. */
@keyframes stStatusRing { 0% { transform: scale(1); opacity: .55; } 100% { transform: scale(2.2); opacity: 0; } }

/* Prevent Mobile Safari's rubber-band page scroll from fighting the chart's own drag/pinch and
   the app's fixed header/bottom-tab-bar chrome; individual scrollable panes opt back into
   vertical panning below. -webkit-tap-highlight-color removes Safari's grey tap flash on every
   button/link (we already show our own :hover/:active/:focus-visible states). */
html, body { touch-action: pan-y; -webkit-tap-highlight-color: transparent; }
button, a, input, textarea { -webkit-tap-highlight-color: transparent; }
/* #endregion */

/* #region zone:desk.style.login — หน้า login */
/* ================= Login screen ================= */
/* Page-level centering, the split card and the brand-panel wave now live in the shared
   login-shell.css (.login-shell/.login-shell-card/.login-shell-brand/.login-shell-form, loaded
   right after desk-tokens.css so this file keeps final say on any Desk-specific tweak — 2026-09-26
   login redesign). This region keeps only what's specific to the Desk's own form content: the
   heading, tabs, auth-form fields, hints/errors and the help line. */
/* Desk-only BLUE brand panel (owner 2026-10-12: every other web keeps the shared GREEN panel).
   #login-screen exists only on this page, so these cannot leak into Map/Disaster/Account/Monitor. */
#login-screen .login-shell-brand{color:#eef3fb;background:linear-gradient(145deg,var(--brand-panel-start),var(--brand-panel-end))}
#login-screen .login-shell-brand::before,#login-screen .login-shell-brand::after{border-color:rgba(208,224,245,.13)}
#login-screen .login-shell-brand::before{background:radial-gradient(ellipse,rgba(88,166,255,.14),transparent 68%)}
#login-screen .login-shell-quote{border-top-color:rgba(208,224,245,.24);color:#d4def0}
#login-screen .login-shell-brand .login-shell-eyebrow{color:#c9d6ee}
#login-screen .login-shell-brand .login-shell-tagline{color:#d4def0}
.login-shell-form h1 { font-size: var(--u-text-xl); font-weight: 700; margin: 0 auto 18px; letter-spacing: -.02em; }
.tabs {
  display: flex; width: 100%;
}
.tab {
  flex: 1;
}
.auth-form { width: 100%; display: flex; flex-direction: column; gap: var(--sp-1); }
.auth-form label { font-size: var(--u-text-xs); color: var(--muted); margin-top: var(--sp-2); }
.auth-form input {
  margin-top: var(--sp-1);
}
.hint { font-size: var(--u-text-xs); color: var(--faint); line-height: 1.5; min-height: 1.2em; }
.form-error {
  font-size: var(--u-text-xs); color: var(--down); background: var(--down-soft);
  padding: var(--sp-2) 10px; border-radius: var(--r-inner); line-height: 1.5; margin-top: var(--sp-1);
}
.btn-primary {
  margin-top: 10px; width: 100%;
}

/* Small inline spinner used inside a disabled/pending btn-primary (Luna/Gemma analyse, chat send). */
.btn-spinner {
  width: 14px; height: 14px; border-radius: 50%; flex-shrink: 0;
  border: 2px solid rgba(255, 255, 255, .4); border-top-color: var(--on-accent);
  animation: stSpin .7s linear infinite; /* the global prefers-reduced-motion rule above already
  clamps this to a near-static ring, which still reads as "busy" without the spin */
}
.login-help { font-size: var(--u-text-xs); color: var(--muted); text-align: center; line-height: 1.6; margin: var(--sp-1) auto 0; }
/* #endregion */

/* #region zone:desk.style.shell — โครงหน้าและหัวเว็บ */
/* ================= App shell ================= */
/* min-height (not a hard height:100vh) lets the whole shell grow past one viewport and the
   page scroll as a unit instead of clipping the bottom row at short viewports (~1000px) — the
   chart card still gets its own minimum height below, and the bottom cards size to content. */
.app-shell { display: flex; flex-direction: column; min-height: 100vh; min-height: 100dvh; background: var(--bg); }

/* Thin indeterminate bar at the very top of the viewport while a ticker's data loads (Task 17:
   3px + a soft accent glow so it reads clearly as "loading", not just a hairline). */
.top-progress {
  position: fixed; top: 0; left: 0; right: 0; height: 3px; z-index: 60;
  background: var(--line); overflow: hidden;
}
.top-progress span {
  display: block; width: 100%; height: 100%; background: var(--accent);
  box-shadow: 0 0 8px 1px var(--accent);
  animation: stProgress 1.1s ease-in-out infinite;
  transform-origin: left center;
}

.app-header {
  display: flex; align-items: center; gap: var(--sp-3);
  height: 56px; flex-shrink: 0; padding: 0 var(--sp-4);
  background: var(--header-bg); border-bottom: 1px solid var(--header-line);
  color: var(--header-text);
}
.brand { display: flex; align-items: center; gap: var(--sp-2); flex-shrink: 0; }
.brand img { width: 30px; height: 30px; border-radius: var(--r-logo); display: block; }
.brand-text { display: flex; flex-direction: column; line-height: 1.15; }
.brand-name { font-weight: 700; font-size: 15px; letter-spacing: -.02em; color: var(--header-text); }
.brand-sub { font-family: var(--font-mono); font-size: var(--u-text-xs); color: var(--mint); }

.search-wrap { flex-shrink: 1; flex-grow: 0; width: 260px; max-width: 260px; min-width: 120px; position: relative; }
.search-wrap svg { position: absolute; left: 10px; top: 18px; transform: translateY(-50%); width: 14px; height: 14px; color: var(--header-well-text); pointer-events: none; }
.search-wrap input {
  width: 100%; height: 36px; padding: 0 var(--sp-3) 0 var(--sp-8); box-sizing: border-box;
  background: var(--header-well-bg); border: 1px solid var(--header-well-line); border-radius: var(--r-control);
  color: var(--header-text); font-size: var(--u-text-compact); outline: none;
}
.search-wrap input::placeholder { color: var(--header-well-placeholder); }
/* #endregion */

/* #region zone:desk.style.search — ผลค้นหาหุ้นใต้ช่องค้นหา */
/* ---- symbol search results (owner round 2): a listbox hanging under the box, in the page's own
   theme (the header stays dark). Rows: logo · ticker · name · market chip. ---- */
.search-pop {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 60;
  width: max(100%, 380px); max-height: min(500px, calc(100vh - 96px)); overflow-y: auto; overscroll-behavior: contain;
  padding: 6px; background: var(--panel); color: var(--text);
  border: 1px solid var(--line); border-radius: var(--r-inner); box-shadow: var(--pop-shadow);
  scrollbar-width: thin;
}
.search-head { padding: 6px var(--sp-2) var(--sp-1); font-size: var(--u-text-xs); font-weight: 600; color: var(--faint); }
.search-opt {
  display: grid; grid-template-columns: var(--logo-xs) 52px minmax(0, 1fr) auto; align-items: center;
  gap: 10px; height: 40px; padding: 0 var(--sp-2); border-radius: 10px; cursor: pointer;
  transition: background-color .12s ease;
}
.search-opt:hover, .search-opt.active { background: var(--hover); }
.search-opt.active { box-shadow: inset 0 0 0 1px var(--acc-ring); }
.search-opt .wl-logo { grid-area: auto; --logo-size: var(--logo-xs); --k: .6; }
.search-ticker { min-width: 0; overflow: hidden; text-overflow: ellipsis; font-family: var(--font-mono); font-size: var(--u-text-compact); font-weight: 700; letter-spacing: -.01em; white-space: nowrap; }
.search-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--u-text-xs); color: var(--muted); }
.search-pop mark { background: var(--acc-soft); color: var(--accent-text); border-radius: 3px; padding: 0 1px; margin: 0 -1px; }
.mkt-chip {
  display: inline-flex; align-items: center; height: 18px; padding: 0 6px; border-radius: 6px;
  border: 1px solid var(--line); background: var(--panel2); color: var(--muted);
  font-family: var(--font-mono); font-size: var(--u-text-xs); font-weight: 700; letter-spacing: .04em;
}
.search-note { display: flex; flex-direction: column; align-items: center; gap: 3px; padding: var(--sp-4) var(--sp-3); text-align: center; }
.search-note-main { font-size: var(--u-text-sm); font-weight: 600; color: var(--text); }
.search-note-sub { font-size: var(--u-text-xs); color: var(--faint); }
@media (prefers-reduced-motion: reduce) { .search-opt { transition: none; } }

.ai-chip {
  flex-shrink: 0; height: 36px; box-sizing: border-box; display: flex; align-items: center;
  font-size: var(--u-text-xs); font-weight: 600; padding: 0 10px;
  background: var(--header-well-bg); border: 1px solid var(--header-well-line); border-radius: var(--r-control); color: var(--mint);
  white-space: nowrap;
}
.ai-chip.denied { color: var(--down); }
.ai-chip:hover { background: var(--header-well-hover); }

.clock { flex-shrink: 0; display: flex; align-items: center; height: 36px; font-family: var(--font-mono); font-size: var(--u-text-xs); color: var(--header-well-text); }
/* #endregion */

/* #region zone:desk.style.account — เมนูบัญชีมุมขวาบน */
/* ---- account menu (top-right avatar + name/tier + popover/sheet) ---- */
/* align-self:stretch makes .account exactly as tall as .app-header (56px) instead of just
   hugging the avatar, so .account-popover's top:100% lands precisely on the header's own
   bottom edge — see the +8px gap comment below. */
.account { position: relative; align-self: stretch; flex-shrink: 0; display: flex; align-items: center; gap: 10px; margin-left: auto; }
.member-avatar {
  width: 30px; height: 30px; border-radius: 50%; flex-shrink: 0; background: var(--header-well-bg); border: 1px solid var(--header-well-line);
  display: flex; align-items: center; justify-content: center; padding: 0;
  font-family: var(--font-mono); font-size: var(--u-text-xs); font-weight: 700; color: var(--mint);
}
.member-avatar:hover, .member-avatar[aria-expanded="true"] { background: var(--header-well-hover); }
/* Plus-tier ring, same accent used for the tier badge below. */
.member-avatar.plus { box-shadow: 0 0 0 2px var(--header-well-bg), 0 0 0 3.5px var(--accent); }
/* Elite ring (package-elite, 2026-09-27): its own color so Elite reads as a distinct tier, not "Plus". */
.member-avatar.elite { box-shadow: 0 0 0 2px var(--header-well-bg), 0 0 0 3.5px var(--amber); }
.member-name-tier { display: flex; align-items: center; gap: 6px; }
.tier-badge { font-size: var(--u-text-xs); font-weight: 700; padding: 2px 7px; border-radius: var(--u-radius-pill); background: var(--acc-soft); color: var(--accent-text); text-transform: uppercase; letter-spacing: .04em; }

/* Desktop/tablet dropdown: right-aligned under the avatar, 8px below the header's bottom edge. */
.account-popover {
  position: absolute; top: calc(100% + 8px); right: 0; z-index: 55;
  width: 240px;
}
/* #account-panel is the shared visual box — reused as-is inside the phone bottom sheet below,
   just with its corners/padding overridden there (see .logout-sheet-panel .account-panel). 12px
   padding is the one inset every direct child (header block, dividers, item rows) sits inside;
   item rows add a further 5px of their own so their hover/focus pill reads as inset from that
   padded edge, not flush against it. */
.account-panel {
  background: var(--panel); color: var(--text); border: 1px solid var(--line); border-radius: var(--r-inner);
  box-shadow: var(--shadow); overflow: hidden; padding: var(--sp-3);
}
.account-panel-head { display: flex; flex-direction: column; gap: var(--sp-1); }
.account-panel-name { font-size: var(--u-text-label); font-weight: 700; }
.account-panel-login { font-size: var(--u-text-xs); color: var(--muted); }
.account-panel-meta { display: flex; align-items: center; gap: var(--sp-2); margin-top: var(--sp-1); }
.account-panel-quota { font-size: var(--u-text-xs); color: var(--faint); }
/* 1px lines inset by the panel's own 12px padding — plain block children with no extra margin
   of their own, so they land exactly at that padding edge (narrower than the item pills below,
   which add a further 5px). */
.account-panel-divider { height: 1px; background: var(--line); margin: var(--sp-2) 0; }
.account-panel-item {
  width: calc(100% - 10px); height: 42px; margin: 0 5px; border: 0; border-radius: 8px;
  background: transparent; color: var(--text); outline: none;
  display: flex; align-items: center; gap: 10px; padding: 0 9px; font-size: var(--u-text-sm); font-weight: 600; text-align: left;
}
.account-panel-item:hover { background: var(--hover); }
/* Selector specificity beats .app-header :focus-visible (desk.css §general) so this — not the
   default outset ring — wins regardless of source order: an inset ring that follows the item's
   own radius, never the full-bleed top/bottom lines an outset outline would draw. */
.account-panel .account-panel-item:focus-visible { background: var(--hover); box-shadow: inset 0 0 0 2px var(--accent); }
.account-panel-item-icon { width: 15px; height: 15px; flex-shrink: 0; color: var(--muted); }
.account-panel-danger { color: var(--down); }
/* #endregion */

/* #region zone:desk.style.layout — เลย์เอาต์สามคอลัมน์ */
/* ================= Layout B: watchlist | chart hero + info strip | chat =================
   Owner 2026-09-24: "กราฟตรงกลาง มันควรจะถูกโฟกัส"; 2026-09-25: "ทำให้ข้อมูลด้านขวามาย่อไว้ด้านล่าง …
   เอาแชทไปไว้ขวาให้สรุปผ่านแชท". The centre column (chart, then the tabbed info strip) scrolls with
   the page; the watchlist and the chat column stick under the (sticky) header and scroll inside
   themselves. Widths are tokens so the rail/overlay states and the breakpoints only swap numbers. */
.app-shell {
  --wl-w: 264px; --chat-w: 380px; --gap: 16px; --head-h: 56px;
  --side-top: calc(var(--head-h) + var(--gap));
  --side-h: calc(100vh - var(--head-h) - 2 * var(--gap));
}
@supports (height: 100dvh) {
  .app-shell { --side-h: calc(100dvh - var(--head-h) - 2 * var(--gap)); }
}
.app-shell.wl-rail { --wl-w: 76px; }
@media (max-width: 1439px) {
  .app-shell { --wl-w: 236px; --chat-w: 348px; }
  .app-shell.wl-rail { --wl-w: 76px; }
}
@media (min-width: 900px) {
  .app-header { position: -webkit-sticky; position: sticky; top: 0; z-index: 30; }
}

.app-grid {
  flex: 1; min-height: 0;
  display: grid; grid-template-columns: var(--wl-w) minmax(0, 1fr) var(--chat-w);
  align-items: start; gap: var(--gap); padding: var(--gap);
  transition: grid-template-columns .2s var(--ease-out);
}

/* ---- icon-only ghost button (watchlist toggle, sheet close) ---- */
.icon-btn {
  width: 28px; height: 28px; flex-shrink: 0; padding: 0; border: 0; border-radius: 8px;
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent; color: var(--muted);
  transition: background-color .15s ease, color .15s ease;
}
.icon-btn svg { width: 18px; height: 18px; }
.icon-btn:hover { background: var(--hover); color: var(--text); }
.icon-btn:active { background: var(--line); }
/* #endregion */

/* #region zone:desk.style.components — คลาสส่วนประกอบกลาง (การ์ด ปุ่ม ช่องกรอก) */


/* #endregion */

/* #region zone:desk.style.watchlist — รายการหุ้นและคอลัมน์กลาง */
/* ---- watchlist ---- */
.watchlist-panel {
  /* Owner 2026-10-19: as tall as its rows and the PAGE scrolls — no sticky cap, no inner scroll box
     (the index chips added 2026-10-18 shrank a capped list to one row). position:relative keeps the
     900–1199px overlay (z-index, below) above the chart. */
  position: relative; height: auto;
  display: flex; flex-direction: column; min-width: 0;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-card);
  box-shadow: var(--card-shadow); overflow: hidden;
}
.panel-head { display: flex; align-items: flex-start; gap: var(--sp-2); padding: 14px var(--sp-3) 10px var(--sp-4); border-bottom: 1px solid var(--line); flex-shrink: 0; }
.panel-head-text { display: flex; flex-direction: column; gap: 3px; min-width: 0; flex: 1; }
.eyebrow { font-size: var(--u-text-sm); font-weight: 700; color: var(--text); letter-spacing: -.01em; }
.header-line { font-size: var(--u-text-xs); color: var(--faint); line-height: 1.5; display: flex; flex-wrap: wrap; column-gap: var(--sp-1); row-gap: 1px; }
.header-line span { white-space: nowrap; }
/* A formula list older than the newest price bar: its last segment says "สแกนยังไม่อัปเดต" in amber (polish 2026-10-13). */
.header-line.is-stale span:last-child { color: var(--amber); font-weight: 600; }
.wl-toggle svg { transition: transform .2s var(--ease-out); }
.wl-rail .wl-toggle svg { transform: scaleX(-1); }
.watchlist-rows { padding: var(--sp-2); display: flex; flex-direction: column; gap: var(--sp-1); overflow: visible; }
.wl-row, .stock-row {
  position: relative; display: grid; grid-template-columns: var(--logo-md) minmax(0, 1fr) auto; align-items: center;
  grid-template-areas: "logo main price" "logo name change"; align-content: center; flex-shrink: 0;
  gap: 2px 10px; padding: 0 10px; height: 56px; border-radius: var(--r-inner); border: 0; background: transparent; width: 100%; text-align: left;
  transition: background-color .15s ease;
}
.wl-row:hover, .wl-row:focus-visible { background: var(--hover); }
/* Selected = tinted fill plus a hairline accent ring, so it still reads as "current" while hovered. */
.wl-row.selected { background: var(--acc-soft); box-shadow: inset 0 0 0 1px var(--acc-ring); }
.wl-logo { grid-area: logo; --logo-size: var(--logo-md); --k: .8; }
.wl-main { grid-area: main; display: flex; align-items: center; gap: 6px; min-width: 0; white-space: nowrap; }
.wl-ticker { font-family: var(--font-mono); font-weight: 700; font-size: var(--u-text-compact); flex-shrink: 0; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
/* Signal chip (owner round 2): one refined pill everywhere — watchlist rows, stock header, rail.
   A leading tone dot, faint tint, 1px tone hairline; 18px tall with the text optically centred so
   it sits on the ticker's line. */
.sig-chip {
  flex-shrink: 0; display: inline-flex; align-items: center; gap: 5px; height: 18px; padding: 0 7px 0 6px;
  border: 1px solid transparent; border-radius: var(--u-radius-pill); white-space: nowrap;
  font-family: 'Anuphan', system-ui, sans-serif; font-size: var(--u-text-xs); font-weight: 600; line-height: 1; letter-spacing: .01em;
}
.sig-chip::before { content: ""; width: 5px; height: 5px; border-radius: 50%; background: currentColor; flex-shrink: 0; }
.sig-chip.buy { color: var(--sig-buy-fg); background: var(--sig-buy-bg); border-color: var(--sig-buy-line); }
.sig-chip.watch { color: var(--sig-wait-fg); background: var(--sig-wait-bg); border-color: var(--sig-wait-line); }
.sig-chip.buy::before { box-shadow: 0 0 0 2px var(--sig-buy-bg); }
.wl-stars { flex-shrink: 0; font-size: var(--u-text-xs); font-weight: 600; color: var(--amber); line-height: 1.5; padding: 0 3px; margin-left: -3px; border-radius: 4px; }
.wl-stars:hover { background: var(--amber-soft); }
/* padding-right matches .wl-change's pill padding so the price digits and the percent digits
   share one right edge. */
.wl-price { grid-area: price; justify-self: end; padding-right: 5px; font-family: var(--font-mono); font-size: var(--fs-lg); font-weight: 600; text-align: right; white-space: nowrap; }
.wl-sub { grid-area: name; display: flex; align-items: center; gap: 6px; min-width: 0; }
.wl-name { font-size: var(--u-text-xs); color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.wl-change { grid-area: change; justify-self: end; font-family: var(--font-mono); font-size: var(--fs-sm); font-weight: 600; padding: 1px var(--sp-2); border-radius: var(--r-pill); white-space: nowrap; }
.wl-change.up { color: var(--up-text); background: var(--up-soft); }
.wl-change.down { color: var(--down-text); background: var(--down-soft); }
.wl-change.flat { color: var(--muted); background: var(--panel2); }
.panel-foot { padding: 10px var(--sp-4) 14px; border-top: 1px solid var(--line); font-size: var(--u-text-xs); color: var(--faint); line-height: 1.5; flex-shrink: 0; }
.wl-empty { padding: var(--sp-6) 14px; color: var(--muted); font-size: var(--u-text-xs); text-align: center; }
.wl-load-error {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--sp-2); min-height: 160px; padding: var(--sp-4); text-align: center; color: var(--muted);
}
.wl-load-error p { margin: 0; }
.wl-load-error button { min-height: var(--tap-min); }
.wl-skeleton { display: flex; flex-direction: column; gap: var(--sp-2); }
.wl-skeleton-row {
  height: 56px; border-radius: var(--r-inner);
  background: linear-gradient(90deg, var(--panel2) 25%, var(--hover) 37%, var(--panel2) 63%);
  background-size: 400% 100%; animation: stPulse 1.4s ease-in-out infinite;
}
.search-mobile-mount:empty { display: none; }

/* Slim rail: logo + ticker only; the row tooltip carries the full name and sector. */
.wl-rail .panel-head { justify-content: center; padding: var(--sp-3) 0 10px; }
.wl-rail .panel-head-text, .wl-rail .panel-foot, .wl-rail .search-mobile-mount { display: none; }
.wl-rail .watchlist-rows { padding: 6px; gap: 2px; scrollbar-width: none; }
.wl-rail .watchlist-rows::-webkit-scrollbar { display: none; }
.wl-rail .wl-row {
  height: auto; padding: var(--sp-2) 2px 6px; grid-template-columns: minmax(0, 1fr); gap: var(--sp-1);
  grid-template-areas: "logo" "main"; justify-items: center;
}
.wl-rail .wl-logo { --logo-size: var(--logo-sm); --k: .75; }
.wl-rail .wl-main { justify-content: center; max-width: 100%; }
.wl-rail .wl-ticker { font-size: var(--u-text-xs); }
.wl-rail .wl-sub, .wl-rail .wl-price, .wl-rail .wl-change { display: none; }
/* Rail: the chip shrinks to its tone dot, pinned to the badge's top-right corner so the ticker
   stays centred (its text remains for screen readers). */
.wl-rail .wl-signal {
  position: absolute; top: 5px; left: calc(50% + 6px); z-index: 3;
  width: 11px; height: 11px; padding: 0; gap: 0; justify-content: center; font-size: 0;
  box-shadow: 0 0 0 2px var(--panel);
}
.wl-rail .wl-row:hover .wl-signal, .wl-rail .wl-row:focus-visible .wl-signal { box-shadow: 0 0 0 2px var(--hover); }
.wl-rail .wl-row.selected .wl-signal { box-shadow: 0 0 0 2px var(--acc-soft); }
.wl-rail .wl-signal::before { width: 5px; height: 5px; box-shadow: none; }
.wl-rail .wl-signal.buy, .wl-rail .wl-signal.watch { background: var(--panel); }
.wl-rail .wl-skeleton-row { height: 52px; }

/* ---- centre column ---- */
.main-col { display: flex; flex-direction: column; gap: var(--sp-3); min-width: 0; }

/* Stock header: the chart card's top row, split from the toolbar by a hairline, so the centre
   column's first card edge shares the side rails' top line. Side padding matches the toolbar. */
.symbol-header { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: var(--sp-2) var(--sp-3); min-width: 0; padding: var(--sp-3); }
.logo-disc { --logo-size: var(--logo-lg); }
.sym-id { display: flex; flex-direction: column; justify-content: center; align-self: stretch; gap: var(--sp-1); min-width: 0; }
.sym-ticker-row { display: flex; align-items: center; gap: var(--sp-2); }
.sym-ticker { font-size: var(--u-text-xl); font-weight: 700; letter-spacing: -.03em; line-height: 1.2; }
/* Small spinner next to the ticker while a newly-selected stock's data is loading (Task 17). */
.sym-spinner {
  width: 13px; height: 13px; border-radius: 50%; flex-shrink: 0;
  border: 2px solid var(--line); border-top-color: var(--accent);
  animation: stSpin .7s linear infinite;
}
.sym-name { color: var(--muted); font-size: var(--u-text-xs); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; border-radius: 4px; }
.sym-price-wrap { display: flex; align-items: center; align-self: stretch; justify-self: end; gap: var(--sp-2); white-space: nowrap; }
.sym-price { font-family: var(--font-mono); font-size: 24px; font-weight: 600; letter-spacing: -.03em; line-height: 1.2; }
.sym-change { font-family: var(--font-mono); font-size: var(--u-text-xs); font-weight: 600; padding: 3px 7px; border-radius: 8px; white-space: nowrap; }
.sym-change.up { color: var(--up); background: var(--up-soft); }
.sym-change.down { color: var(--down); background: var(--down-soft); }
.sym-change.flat { color: var(--muted); background: var(--panel2); }
.sym-note { margin-left: 0; font-size: var(--u-text-xs); color: var(--faint); border-radius: var(--u-radius-pill); flex-shrink: 0; }
/* #endregion */

/* #region zone:desk.style.logo — โลโก้บริษัทและตัวอักษรแทนโลโก้ */
/* ---- company badge (.wl-logo / .logo-disc) ----
   TradingView's logo art is drawn to sit inside a circle, so the image fills a circle edge to
   edge. Depth is layered, all scaled by --k (the size step) so 30px chips never go muddy:
   - the badge's own box-shadow: tight contact shadow + soft ambient (+ a faint halo in dark);
   - ::before: the glass rim, a 1px gradient ring (light top, dark bottom) cut out with a mask;
   - ::after: a soft specular highlight upper-left plus a faint inner shadow on the bottom edge.
   Both pseudo-elements are positioned, so they paint over the image/monogram text. */
.wl-logo, .logo-disc {
  --k: 1; --gloss: .18;
  position: relative; width: var(--logo-size); height: var(--logo-size); flex-shrink: 0;
  border-radius: 50%; overflow: hidden; background: var(--logo-well); isolation: isolate;
  display: flex; align-items: center; justify-content: center;
  font-family: 'Anuphan', system-ui, sans-serif; font-weight: 600; letter-spacing: -.01em;
  font-size: max(12px, calc(var(--logo-size) * .38)); line-height: 1; color: #FFFFFF;
  box-shadow:
    0 1px 2px var(--logo-contact),
    0 calc(4px * var(--k)) calc(10px * var(--k)) var(--logo-ambient),
    0 0 0 1px var(--logo-halo);
  transition: transform 150ms var(--ease-out), box-shadow 150ms var(--ease-out);
}
.logo-disc { --k: .95; }
.wl-logo::before, .logo-disc::before,
.wl-logo::after, .logo-disc::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
}
.wl-logo::before, .logo-disc::before {
  z-index: 2; padding: 1px;
  background: linear-gradient(180deg, var(--logo-rim-top), var(--logo-rim-mid) 48%, var(--logo-rim-bottom));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0);
}
.wl-logo::after, .logo-disc::after {
  z-index: 1;
  background: radial-gradient(55% 45% at 30% 22%, rgb(255 255 255 / calc(var(--gloss) * var(--k))), rgb(255 255 255 / 0));
  box-shadow: inset 0 -1px calc(2px * var(--k)) var(--logo-curve);
}
/* Watchlist rows: the badge lifts 1px and its shadow deepens on hover/focus/selected. */
.wl-row:hover .wl-logo, .wl-row:focus-visible .wl-logo, .wl-row.selected .wl-logo {
  transform: translateY(-1px);
  box-shadow:
    0 2px 3px var(--logo-contact),
    0 calc(6px * var(--k)) calc(14px * var(--k)) var(--logo-ambient-lift),
    0 0 0 1px var(--logo-halo);
}
.wl-logo img, .logo-disc img {
  display: block; width: 100%; height: 100%; object-fit: cover; border-radius: inherit;
  opacity: 0; transition: opacity 150ms var(--ease-out);
}
.wl-logo img.is-loaded, .logo-disc img.is-loaded { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  .wl-logo, .logo-disc, .wl-logo img, .logo-disc img { transition: none; }
}
/* Monogram: a glossy token — 135° two-stop tone and a slightly stronger highlight. The top
   stops are deepened so white text stays ≥4.7:1 even under the highlight (≥6.5:1 without). */
.wl-logo.is-monogram, .logo-disc.is-monogram { --gloss: .24; }
.logo-tone-0 { background: linear-gradient(135deg, #3C636B, #2C505A); }
.logo-tone-1 { background: linear-gradient(135deg, #475D8A, #33476E); }
.logo-tone-2 { background: linear-gradient(135deg, #6C537D, #503D5F); }
.logo-tone-3 { background: linear-gradient(135deg, #844E5A, #6B3B47); }
.logo-tone-4 { background: linear-gradient(135deg, #6F5939, #5E4A2E); }
.logo-tone-5 { background: linear-gradient(135deg, #4C6341, #3E5335); }
.logo-tone-6 { background: linear-gradient(135deg, #535D69, #3D4550); }
.logo-tone-7 { background: linear-gradient(135deg, #5B5690, #433F6E); }
/* Live-price status as a small pill with a coloured dot (owner request: it must visibly pulse —
   live/delayed get an expanding, fading ring behind the dot; closed/none stay static grey). The
   same markup/classes render the intraday candle-series status (timeframes.js's seriesStatus())
   through this same #sym-status element, so both read identically, on desktop and on phone. */
.status-pill {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 10px; border-radius: var(--u-radius-pill); background: var(--panel2); color: inherit; font-weight: 600;
}
.status-dot { position: relative; display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: var(--faint); flex-shrink: 0; }
.status-ring { position: absolute; inset: 0; border-radius: 50%; background: currentColor; opacity: 0; pointer-events: none; }
.sym-note.tone-live .status-pill { background: var(--up-soft); color: var(--up); }
.sym-note.tone-live .status-dot { background: var(--up); }
.sym-note.tone-live .status-ring { background: var(--up); animation: stStatusRing 1.6s ease-out infinite; }
.sym-note.tone-delayed .status-pill { background: var(--amber-soft); color: var(--amber); }
.sym-note.tone-delayed .status-dot { background: var(--amber); }
.sym-note.tone-delayed .status-ring { background: var(--amber); animation: stStatusRing 2.4s ease-out infinite; }
.sym-note.tone-closed .status-pill { background: var(--panel2); color: var(--muted); }
.sym-note.tone-closed .status-dot { background: var(--muted); }
.sym-note.tone-none .status-pill { background: transparent; color: var(--faint); padding-left: 0; font-weight: 400; }
.sym-note.tone-none .status-dot { background: var(--faint); }
/* 2026-09-23 fix: DeskStock.staleAsOf notice — a small amber line under the price header, shown
   only while the served analysis is stale and the backend is on-demand-regenerating it. */
.sym-stale-notice {
  margin: 10px var(--sp-3) 0; padding: 6px var(--sp-3); border-radius: var(--r-control);
  background: var(--amber-soft); color: var(--amber); font-size: var(--u-text-xs); font-weight: 600; line-height: 1.5;
}
/* #endregion */

/* #region zone:desk.style.chart.toolbar — การ์ดกราฟและแถบเครื่องมือ */
/* ---- chart card: toolbar row, chart, range bar ---- */
/* No overflow clipping: the toolbar popovers hang down over the chart. The corners stay round
   because the toolbar and range bar (panel-coloured) own them, not the chart canvas. */
.chart-card {
  display: flex; flex-direction: column; min-width: 0; background: var(--panel);
  border: 1px solid var(--line); border-radius: var(--r-card); box-shadow: var(--card-shadow);
}

/* One calm row, TradingView-like. Every control shares one height (--tb-h: 32px, 40px on touch)
   and one radius; groups are split by hairline separators, not by filled teal pills. */
.chart-card { --tb-h: 32px; --r-tb: 10px; }
@media (pointer: coarse) { .chart-card { --tb-h: 40px; } }
.chart-toolbar {
  position: relative; display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); min-width: 0;
  padding: var(--sp-2) var(--sp-3); border-bottom: 1px solid var(--line);
}
.tf-seg { order: 1; }
.tb-type { order: 3; }
.tb-ind { order: 4; }
.tb-tools { order: 10; margin-left: auto; display: flex; align-items: center; gap: var(--sp-2); }
/* Desktop: the phone tools sheet is not a box at all — its children are toolbar items. */
.tb-sheet { display: contents; }
.tb-sheet-head, .tb-pop-head, .tb-sheet-label, .chart-toolbar .tb-more-btn { display: none; }
.tb-sep { width: 1px; height: 18px; flex-shrink: 0; margin: 0 var(--sp-1); background: var(--line); }

.tb-btn {
  height: var(--tb-h); min-width: var(--tb-h); flex-shrink: 0; padding: 0 var(--sp-2); gap: 6px;
  display: inline-flex; align-items: center; justify-content: center;
  border: 0; border-radius: var(--r-tb); background: transparent; color: var(--muted);
  font-size: var(--u-text-xs); font-weight: 600; white-space: nowrap; text-decoration: none; /* .tb-btn is also an <a> (#tv-open-btn) */
  transition: background-color .15s ease, color .15s ease;
}
.tb-btn svg { width: 18px; height: 18px; flex-shrink: 0; }
.tb-btn.tb-icon { width: var(--tb-h); padding: 0; }
.tb-btn:hover, .tb-btn[aria-expanded="true"] { background: var(--hover); color: var(--text); }
.tb-btn:active { background: var(--line); }
.tb-btn:disabled, .tb-btn.is-disabled { opacity: .45; cursor: default; background: transparent; pointer-events: none; }
#type-btn[data-type="line"] .ico-candle, #type-btn:not([data-type="line"]) .ico-line { display: none; }
.tb-count {
  min-width: 18px; height: 18px; padding: 0 5px; border-radius: var(--u-radius-pill);
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--acc-soft); color: var(--accent-text); font-size: var(--u-text-compact); font-weight: 700;
}
.lock-toggle[aria-pressed="true"] { background: var(--acc-soft); color: var(--accent-text); }
.lock-toggle[aria-pressed="true"]:hover { background: var(--acc-soft); color: var(--accent-text); box-shadow: inset 0 0 0 1px var(--acc-ring); }
.lock-toggle .ico-unlocked, .lock-toggle[aria-pressed="false"] .ico-locked { display: none; }
.lock-toggle[aria-pressed="false"] .ico-unlocked { display: block; }

/* Segmented control (timeframe, range bar, login tabs keep their own): a quiet well with the
   active segment lifted onto a white chip in teal text — the Apple-like segmented look. */
.seg { flex-shrink: 0; }

/* #endregion */

/* #region zone:desk.style.chart.popovers — ป๊อปโอเวอร์ของแถบเครื่องมือ */
/* ---- toolbar popovers (desktop dropdowns; bottom sheets below 900px) ---- */
.tb-pop-wrap { position: relative; display: flex; }
.tb-pop {
  display: none; position: absolute; top: calc(100% + 6px); left: 0; z-index: 40;
  flex-direction: column; gap: 2px; min-width: 180px; padding: 6px;
  background: var(--u-sheet); color: var(--text); border: 1px solid var(--line);
  border-radius: var(--r-inner); box-shadow: var(--shadow);
}
.tb-pop.open { display: flex; animation: popIn .16s var(--ease-out); }
@keyframes popIn { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
.type-menu { min-width: 168px; }
.type-item {
  display: flex; align-items: center; gap: 10px; height: 36px; padding: 0 10px; width: 100%;
  border: 0; border-radius: 10px; background: transparent; color: var(--text); font-size: var(--u-text-compact); font-weight: 600; text-align: left;
  transition: background-color .15s ease, color .15s ease;
}
.type-item svg { width: 18px; height: 18px; flex-shrink: 0; color: var(--muted); }
.type-item:hover { background: var(--hover); }
.type-item:focus-visible { outline-offset: -2px; }
.type-item[aria-checked="true"] { background: var(--acc-soft); color: var(--accent-text); }
.type-item[aria-checked="true"] svg { color: currentColor; }
.tb-backdrop { position: fixed; inset: 0; z-index: 55; border: 0; padding: 0; background: var(--scrim); cursor: default; }

/* Chart height: the hero — ~60% of the viewport, never under 420px. */
.chart-host { position: relative; flex: 0 0 auto; height: max(420px, 60vh); min-height: 0; background: var(--chart-bg); touch-action: none; }
@supports (height: 100dvh) { .chart-host { height: max(420px, 60dvh); } }
.chart-host > div:first-child { position: absolute; inset: 0; width: 100%; height: 100%; }
/* #region zone:desk.style.chart.popovers.draw-tools — รางเว้นช่องซ้ายไม่ให้บังแท่งราคา */
@media (min-width: 601px) {
  .chart-host:has(#draw-tools-rail:not([hidden])) > #chart-canvas {
    left: var(--draw-rail-gutter);
    width: calc(100% - var(--draw-rail-gutter));
  }
  .chart-host:has(#draw-tools-rail:not([hidden])) > .chart-skeleton { left: var(--draw-rail-gutter); }
  .chart-host:has(#draw-tools-rail:not([hidden])) .sub-legend { left: calc(var(--draw-rail-gutter) + var(--sp-2)); }
}
@media (max-width: 600px) {
  .chart-host:has(#draw-tools-rail:not([hidden])) > #chart-canvas {
    top: var(--draw-rail-gutter);
    height: calc(100% - var(--draw-rail-gutter));
  }
  .chart-host:has(#draw-tools-rail:not([hidden])) > .chart-skeleton { top: var(--draw-rail-gutter); }
}
/* #endregion */
/* #endregion */

/* #region zone:desk.style.chart.range — แถบช่วงวันที่ใต้กราฟ */
/* ---- date-range bar: under the chart, same segmented look at a smaller size ---- */
.range-strip {
  display: flex; align-items: center; padding: 6px var(--sp-3); border-top: 1px solid var(--line);
  min-width: 0; flex-wrap: wrap; gap: var(--sp-2); border-radius: 0 0 var(--r-card) var(--r-card);
}
.range-strip::-webkit-scrollbar { display: none; }
.range-strip .range-seg,
.range-strip .tb-tools {
  box-sizing: border-box;
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  min-height: 36px;
  height: auto;
  padding: var(--sp-1);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--panel2);
}
.range-strip .range-seg { flex-wrap: wrap; max-width: 100%; }
.range-strip .seg-btn { height: 26px; border-radius: var(--r-pill); }
.range-strip .tb-icon { width: 26px; min-width: 26px; height: 26px; border-radius: 50%; }
.range-strip .tb-sep { height: 18px; margin: 0; }
.range-seg .seg-btn { font-size: var(--u-text-xs); padding: 0 9px; min-width: 0; }
/* #endregion */

/* #region zone:desk.style.tooltip — ฟอง tooltip กลาง */
/* ---- shared tooltip bubble (tooltip.js) ---- */
.ui-tip {
  position: fixed; top: 0; left: 0; z-index: 80; display: flex; align-items: center; gap: var(--sp-2);
  max-width: min(280px, calc(100vw - 16px)); padding: 6px 10px; border-radius: 8px;
  background: var(--tip-bg); color: var(--tip-fg); font-size: var(--u-text-xs); line-height: 1.45;
  box-shadow: 0 6px 18px rgba(17, 20, 24, .18); pointer-events: none;
  animation: tipIn .12s ease-out;
}
@keyframes tipIn { from { opacity: 0; } to { opacity: 1; } }
.ui-tip-kbd {
  flex-shrink: 0; font-family: var(--font-mono); font-size: var(--u-text-xs); font-weight: 600; line-height: 1.5;
  padding: 0 6px; border-radius: 5px; background: var(--tip-kbd);
}
#ui-tip-text { white-space: pre-line; }
/* #endregion */

/* #region zone:desk.style.chart.legend — คำอธิบายกราฟตามเมาส์และป้ายเหตุการณ์ */
/* ---- hover legend: TradingView-style OHLC chip, top-left of the price pane ----
   Translucent chip so candles behind it stay visible; pointer-events:none so it never steals a
   hover or drag from the chart — only the small collapse toggle takes clicks. max-width keeps it
   clear of the right price scale (~64px). z-index sits under the skeleton (5). */
.chart-legend {
  position: absolute; top: 6px; left: 8px; z-index: 3; max-width: calc(100% - 80px);
  display: flex; flex-direction: column; gap: 2px; padding: var(--sp-1) 6px var(--sp-1) var(--sp-2); border-radius: 8px;
  background: color-mix(in srgb, var(--chart-bg) 78%, transparent); color: var(--text);
  font-family: var(--font-mono); font-size: var(--u-text-compact); line-height: 1.35;
  font-variant-numeric: tabular-nums; pointer-events: none;
}
.legend-row { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: var(--sp-2); row-gap: 0; min-width: 0; }
.lg-ticker { font-family: 'Anuphan', system-ui, sans-serif; font-weight: 700; font-size: var(--u-text-xs); }
.lg-time { color: var(--muted); }
.lg-pair { display: inline-flex; gap: 3px; white-space: nowrap; }
.lg-k { color: var(--muted); font-family: var(--font-sans); }
.lg-v { font-weight: 600; white-space: nowrap; }
.lg-v .lg-unit { font-family: var(--font-sans); }
.lg-v.up { color: var(--up); }
.lg-v.down { color: var(--down); }
.legend-toggle {
  pointer-events: auto; align-self: center; width: 20px; height: 20px; padding: 0; margin-left: -2px;
  display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
  border: 0; border-radius: 6px; background: transparent; color: var(--muted); cursor: pointer;
}
.legend-toggle svg { width: 12px; height: 12px; transition: transform .18s ease; }
.legend-toggle:hover { background: var(--hover); color: var(--text); }
.chart-legend.collapsed .legend-toggle svg { transform: rotate(180deg); }
.chart-legend.collapsed .lg-time, .chart-legend.collapsed .lg-ohl,
.chart-legend.collapsed .lg-chg, .chart-legend.collapsed #lg-vol-pair,
.chart-legend.collapsed .legend-ind { display: none; }
/* Indicator values in their line colours (chart.js COLORS). */
.lg-e20 .lg-k, .lg-e20 .lg-v { color: var(--ema20); }
.lg-e50 .lg-k, .lg-e50 .lg-v { color: var(--ema50); }
.lg-e200 .lg-k, .lg-e200 .lg-v { color: var(--ema200); }
.lg-bbU .lg-k, .lg-bbU .lg-v, .lg-bbL .lg-k, .lg-bbL .lg-v { color: #5B7FE0; }
.lg-rsi .lg-k, .lg-rsi .lg-v { color: #7E57C2; }
.lg-macd .lg-k, .lg-macd .lg-v { color: #2962FF; }
.lg-signal .lg-k, .lg-signal .lg-v { color: #FF6D00; }
.lg-hist.up .lg-v { color: var(--up); }
.lg-hist.down .lg-v { color: var(--down); }
:root[data-theme="dark"] .lg-macd .lg-k, :root[data-theme="dark"] .lg-macd .lg-v { color: #5C8BFF; }
/* Event-marker tooltip: positioned by desk.js (transform), clamped inside .chart-host. */
.chart-tip {
  position: absolute; top: 0; left: 0; z-index: 4; width: max-content; max-width: min(300px, calc(100% - 12px));
  display: flex; flex-direction: column; gap: var(--sp-2); padding: 9px 11px; border-radius: 10px;
  background: var(--panel); color: var(--text); border: 1px solid var(--line); box-shadow: var(--shadow);
  font-size: var(--u-text-xs); line-height: 1.45; pointer-events: none;
}
.tip-row { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.tip-kind { align-self: flex-start; font-size: var(--u-text-xs); font-weight: 700; padding: 1px 7px; border-radius: var(--u-radius-pill); color: #FFFFFF; }
.tip-kind.tip-scan, .tip-kind.tip-scan-watch { background: var(--ev-scan); }
.tip-kind.tip-news { background: var(--ev-news); }
.tip-kind.tip-bull { background: var(--ev-bull); }
.tip-kind.tip-bear { background: var(--ev-bear); }
.tip-kind.tip-earn { background: var(--ev-earn); }
.tip-kind.tip-xd { background: var(--ev-xd); }
.tip-kind.tip-neutral { background: var(--muted); }
:root[data-theme="dark"] .tip-kind { color: #06231F; }
.tip-title { font-weight: 600; overflow-wrap: anywhere; }
.tip-detail { color: var(--muted); font-size: var(--u-text-xs); overflow-wrap: anywhere; }

/* The legend shortens with the chart's own width (not the viewport's): a narrow chart column at
   tablet widths drops the time and O/H/L first. */
.chart-host { container-type: inline-size; }
@container (max-width: 560px) {
  .lg-time, .lg-ohl { display: none; }
}

/* RSI / MACD pane readouts: desk.js sets `top` to the pane's own top edge. */
.sub-legend {
  position: absolute; left: 8px; z-index: 3; max-width: calc(100% - 80px);
  display: flex; flex-wrap: wrap; column-gap: var(--sp-2); padding: 1px 6px; border-radius: 6px;
  background: color-mix(in srgb, var(--chart-bg) 78%, transparent);
  font-family: var(--font-mono); font-size: var(--u-text-xs); line-height: 1.4;
  font-variant-numeric: tabular-nums; pointer-events: none;
}
/* #endregion */
/* #region zone:desk.style.chart.skeleton — โครงกราฟระหว่างโหลด */
/* Chart-shaped loading skeleton: the same reserved plot box as #chart-canvas, one SVG in
   real pixels from chart-skeleton.js (panes, axis column, time row, candles, EMAs, volume,
   RSI/MACD) plus a legend placeholder where the real legend sits. Colours are the theme's own
   up/down/EMA tokens mixed toward the chart background, so it reads as "a chart is coming", not
   as data. A short fade (.is-leaving) reveals the real chart drawn underneath. */
.chart-skeleton {
  --sk-up: color-mix(in srgb, var(--up) 30%, var(--chart-bg));
  --sk-down: color-mix(in srgb, var(--down) 24%, var(--chart-bg));
  --sk-block: color-mix(in srgb, var(--line) 85%, var(--chart-bg));
  --sk-shine: color-mix(in srgb, var(--chart-bg) 72%, transparent);
  position: absolute; inset: 0; z-index: 5; overflow: hidden; pointer-events: none;
  background: var(--chart-bg); transition: opacity .12s ease-out;
}
:root[data-theme="dark"] .chart-skeleton {
  --sk-up: color-mix(in srgb, var(--up) 34%, var(--chart-bg));
  --sk-down: color-mix(in srgb, var(--down) 32%, var(--chart-bg));
  --sk-block: color-mix(in srgb, var(--line) 90%, var(--chart-bg));
  --sk-shine: color-mix(in srgb, var(--text) 5%, transparent);
}
.chart-skeleton.is-leaving { opacity: 0; }
.chart-skeleton-chart { position: absolute; inset: 0; }
.chart-skeleton-svg { display: block; width: 100%; height: 100%; }
.sk-grid { fill: var(--grid); }
.sk-chrome { fill: var(--line); }
.sk-ticks { fill: var(--sk-block); }
.sk-candle.up, .sk-last-tag.up { fill: var(--sk-up); }
.sk-candle.down, .sk-last-tag.down { fill: var(--sk-down); }
.sk-vol.up, .sk-hist.up { fill: var(--sk-up); opacity: .55; }
.sk-vol.down, .sk-hist.down { fill: var(--sk-down); opacity: .55; }
.sk-last-text { fill: var(--chart-bg); opacity: .6; }
.chart-skeleton-svg path { fill: none; stroke-width: 1.5; stroke-linejoin: round; stroke-linecap: round; }
.sk-line { stroke: color-mix(in srgb, var(--accent) 40%, var(--chart-bg)); stroke-width: 2; }
.sk-ema20, .sk-signal { stroke: color-mix(in srgb, var(--ema20) 42%, var(--chart-bg)); }
.sk-ema50, .sk-macd { stroke: color-mix(in srgb, var(--ema50) 38%, var(--chart-bg)); }
.sk-rsi { stroke: color-mix(in srgb, var(--muted) 40%, var(--chart-bg)); }
.chart-skeleton-svg .sk-guide { stroke: var(--line); stroke-width: 1; stroke-dasharray: 3 3; }
.chart-skeleton-svg .sk-last-line { stroke-width: 1; stroke-dasharray: 1 3; }
.sk-last-line.up { stroke: var(--sk-up); }
.sk-last-line.down { stroke: var(--sk-down); }
/* Legend placeholder: the real legend's position, padding and row height (.chart-legend). */
.sk-legend {
  position: absolute; top: 6px; left: 8px; right: calc(var(--sk-axis-width, 54px) + 8px);
  display: flex; flex-direction: column; gap: 2px; padding: var(--sp-1) 6px var(--sp-1) var(--sp-2);
}
.sk-legend-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-2); min-height: 15.5px; }
.sk-legend-label {
  display: inline-flex; align-items: center; gap: 6px; flex-shrink: 0; white-space: nowrap;
  font-size: var(--u-text-xs); font-weight: 600; color: var(--muted);
}
.sk-dot {
  width: 6px; height: 6px; border-radius: 50%; background: var(--accent);
  animation: stPulse 1.2s ease-in-out infinite;
}
.sk-pill { flex-shrink: 0; height: 7px; border-radius: 3.5px; background: var(--sk-block); }
.sk-pill-time { width: 58px; }
.sk-pill-ohl, .sk-pill-c { width: 42px; }
.sk-pill-chg { width: 70px; }
.sk-pill-vol { width: 52px; }
.sk-pill-e20, .sk-pill-e50 { width: 64px; }
.sk-pill-e20 { background: color-mix(in srgb, var(--ema20) 30%, var(--chart-bg)); }
.sk-pill-e50 { background: color-mix(in srgb, var(--ema50) 26%, var(--chart-bg)); }
@container (max-width: 560px) {
  .sk-pill-time, .sk-pill-ohl { display: none; }
}
/* Shimmer: a soft band sweeping across the whole skeleton (transform only, so it stays on the
   compositor). Static under prefers-reduced-motion. */
.chart-skeleton-shimmer { position: absolute; inset: 0; overflow: hidden; }
.chart-skeleton-shimmer::after {
  content: ''; position: absolute; top: 0; bottom: 0; left: 0; width: max(35%, 220px);
  background: linear-gradient(100deg, transparent 0%, var(--sk-shine) 50%, transparent 100%);
  transform: translateX(-100%); animation: skSweep 1.8s cubic-bezier(.45, 0, .25, 1) infinite;
}
@keyframes skSweep { to { transform: translateX(100cqw); } }
/* End state (endChartSkeleton): the load finished with nothing to draw. The faux chart, legend
   (with its pulsing dot) and shimmer go; the opaque box stays so a previous ticker's bars never
   show under the new header, and a calm label says why. */
.sk-status { display: none; }
.sk-slow { display: none; }
.chart-skeleton.is-slow:not(.is-failed) .sk-slow {
  position: absolute; left: 8px; right: calc(var(--sk-axis-width, 54px) + 8px);
  bottom: calc(var(--sk-time-height, 28px) + 8px); display: block;
  padding: var(--sp-2); text-align: center; overflow-wrap: anywhere;
  color: var(--muted); font-size: var(--u-text-sm); font-weight: 600;
}
.chart-skeleton.is-failed .chart-skeleton-chart,
.chart-skeleton.is-failed .sk-legend,
.chart-skeleton.is-failed .chart-skeleton-shimmer { display: none; }
.chart-skeleton.is-failed .sk-status {
  position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center;
  justify-content: center; gap: var(--sp-2); padding: var(--sp-4); text-align: center;
  color: var(--muted); font-size: var(--u-text-sm); font-weight: 600;
}
.sk-status-icon { width: 28px; height: 28px; color: var(--faint); }
/* In-place retry on the failed end state: only for a real load failure (data-end=failed), never the "no data" label. */
.chart-skeleton[data-end="failed"] .chart-retry-btn { display: inline-flex; }
.chart-retry-btn {
  display: none; align-items: center; justify-content: center; min-height: 36px; margin-top: var(--sp-1);
  padding: 0 var(--sp-4); border: 1px solid var(--line); border-radius: var(--r-inner);
  background: var(--panel2); color: var(--text); font: inherit; font-weight: 600; cursor: pointer;
}
.chart-retry-btn { pointer-events: auto; } /* the skeleton box itself is pointer-events:none */
.chart-retry-btn:hover { background: var(--hover); }
.chart-retry-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) {
  .chart-skeleton { transition: none; }
  .sk-dot { animation: none; }
  .chart-skeleton-shimmer { display: none; }
}
/* Reusable shimmer row for the bottom cards + quick-read card while a new ticker's /stock is
   in flight (Task 17). Uses --line (not --panel2, like the watchlist/chart skeletons) because
   this one also renders inside #plan-ladder, whose own background IS --panel2 — a --panel2
   skeleton block there would be nearly invisible against it. */
.card-skeleton-block {
  height: 14px; border-radius: var(--r-inner);
  background: linear-gradient(90deg, var(--line) 25%, var(--hover) 37%, var(--line) 63%);
  background-size: 400% 100%; animation: stPulse 1.4s ease-in-out infinite;
}
.card-skeleton-block + .card-skeleton-block { margin-top: var(--sp-2); }
/* #endregion */

/* #region zone:desk.style.chart.tv-fallback — สำรองกราฟด้วย TradingView */
/* Same box as #chart-canvas/#chart-skeleton (inset:0 in .chart-host, z-index above both so it
   fully replaces the real chart, never overlays it). Fluid at every width (F-owner rule): the
   banner wraps to two lines rather than the retry button ever shrinking or clipping. */
.chart-tv-fallback {
  position: absolute; inset: 0; z-index: 6; display: flex; flex-direction: column;
  background: var(--chart-bg);
}
.tv-fallback-banner {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--sp-2) var(--sp-3);
  padding: var(--sp-2) var(--sp-3); background: var(--amber-soft); color: var(--amber);
  font-size: var(--u-text-compact); font-weight: 600; line-height: 1.4; flex: 0 0 auto;
}
.tv-fallback-text { cursor: help; } /* data-tip carries the "overlays not available" note */
.tv-fallback-retry {
  flex-shrink: 0; padding: 5px var(--sp-3); border-radius: var(--r-control); border: 1px solid var(--amber);
  background: transparent; color: var(--amber); font-size: var(--u-text-compact); font-weight: 700; cursor: pointer;
}
.tv-fallback-retry:hover { background: color-mix(in srgb, var(--amber) 12%, transparent); }
.tv-fallback-frame-wrap { flex: 1 1 auto; min-height: 0; }
.tv-fallback-frame { display: block; width: 100%; height: 100%; border: 0; }
@container (max-width: 560px) {
  .tv-fallback-banner { font-size: var(--u-text-xs); padding: 6px 10px; }
}
/* #endregion */

/* #region zone:desk.style.cards — แถบข้อมูลใต้กราฟ คอลัมน์แชท และการ์ด */
/* ---- info strip under the chart: one tabbed card (desk-strip.js), compact so the chart keeps the
   screen. A panel taller than the cap scrolls inside itself. ---- */
.info-strip {
  display: flex; flex-direction: column; min-width: 0; background: var(--panel);
  border: 1px solid var(--line); border-radius: var(--r-card); box-shadow: var(--card-shadow);
}
.strip-tabs {
  display: flex; gap: var(--u-space-2); flex-shrink: 0; min-width: 0; padding: var(--sp-2) var(--sp-3); border-bottom: 1px solid var(--line);
  overflow-x: auto; scrollbar-width: none;
}
.strip-tabs::-webkit-scrollbar { display: none; }
.strip-tab {
  height: 32px; flex-shrink: 0; padding: 0 var(--sp-3); border: 0; border-radius: 10px; background: transparent;
  color: var(--muted); font-size: var(--u-text-compact); font-weight: 600; white-space: nowrap;
  transition: background-color .15s ease, color .15s ease;
}
.strip-tab:not(.active):hover { background: var(--hover); color: var(--text); }
.strip-tab.active { background: var(--acc-soft); color: var(--accent-text); }
.strip-panel {
  min-width: 0; padding: var(--sp-3); max-height: clamp(280px, 44vh, 480px);
  overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; border-radius: 0 0 var(--r-card) var(--r-card);
}
.strip-panel:focus-visible { outline-offset: -3px; }
.strip-grid { display: flex; flex-wrap: wrap; gap: var(--sp-3); align-items: flex-start; align-content: flex-start; /* DUI-29: a short card never stretches to its neighbour */ }
/* Fluid row: every card grows to share the whole strip (a wrapping flex row, so the full-width link below never
   leaves empty grid tracks), and the long quick read takes two shares when there is room. */
.strip-grid > .rail-card { flex: 1 1 min(100%, 18rem); min-width: 0; }
.strip-grid > .quickread-card { flex-grow: 2; align-self: flex-start; }
.strip-grid > .alt-unsupported, .strip-grid > #fund-link { flex: 1 1 100%; }
.info-strip .rail-card { box-shadow: none; border-radius: var(--r-inner); padding: var(--sp-3) 14px 14px; }
.info-strip .fund-grid { grid-template-columns: repeat(auto-fit, minmax(148px, 1fr)); }
.info-strip .luna-btn-row .btn-primary { max-width: 360px; }

/* ---- chat column: full height beside the chart; only the messages scroll ---- */
.chat-col {
  position: -webkit-sticky; position: sticky; top: var(--side-top); height: var(--side-h);
  display: flex; flex-direction: column; min-width: 0;
}
.chat-col .chat-card { flex: 1 1 auto; min-height: 0; }
.rail-card {
  display: flex; flex-direction: column; gap: 10px; flex-shrink: 0; min-width: 0;
  padding: 14px var(--sp-4) var(--sp-4); background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-card);
  box-shadow: var(--card-shadow);
}
.rail-card h2 { display: flex; flex-wrap: wrap; align-items: baseline; column-gap: var(--sp-2); font-size: var(--u-text-sm); font-weight: 700; color: var(--text); margin: 0; }
.daily-note { font-size: var(--u-text-xs); font-weight: 600; color: var(--faint); text-transform: none; letter-spacing: 0; }
.text-btn {
  align-self: flex-start; min-height: 32px; padding: 0 2px; border: 0; background: transparent;
  color: var(--accent-text); font-size: var(--u-text-xs); font-weight: 600; border-radius: 6px;
}
.text-btn:hover { text-decoration: underline; }
.quickread-card h2 .daily-note { margin-left: 0; }
.plan-ladder { display: flex; flex-direction: column; background: var(--panel2); border-radius: var(--r-inner); overflow: hidden; }
.plan-ladder > div { display: grid; grid-template-columns: 56px 1fr; align-items: center; gap: var(--sp-2); height: 36px; padding: 0 10px; font-size: var(--u-text-xs); border-bottom: 1px solid var(--line); }
.plan-ladder > div:last-child { border-bottom: 0; }
/* The "no plan yet" note is one line of words, not a label/value row: full width, wraps (longer in English). */
.plan-ladder > .empty-note { display: block; height: auto; padding: 10px; line-height: 1.4; }
.plan-ladder .lab { color: var(--muted); }
.plan-ladder .val { font-family: var(--font-mono); font-weight: 600; text-align: right; }
.plan-decision { font-size: var(--u-text-compact); font-weight: 600; }
.plan-reasons { display: flex; flex-direction: column; gap: var(--sp-1); font-size: var(--u-text-xs); color: var(--text); margin: 0; padding: 0; list-style: none; }
.plan-reasons li { padding-left: var(--sp-3); position: relative; }
.plan-reasons li::before { content: ''; position: absolute; left: 0; top: .6em; width: 5px; height: 5px; border-radius: 50%; background: var(--accent); }
.card-footer { font-size: var(--u-text-xs); color: var(--faint); line-height: 1.5; margin-top: auto; }

.fund-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1px; background: var(--line); border-radius: var(--r-inner); overflow: hidden; }
.fund-cell { display: flex; flex-direction: column; justify-content: center; gap: 2px; min-height: 56px; padding: var(--sp-2) 10px; background: var(--panel2); min-width: 0; }
.fund-cell .lab { font-size: var(--u-text-xs); color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.fund-cell .val { font-family: var(--font-mono); font-variant-numeric: tabular-nums; font-size: var(--u-text-sm); line-height: 1.25; font-weight: 600; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow-wrap: anywhere; }
.fund-cell .val.words { font-family: 'Anuphan', sans-serif; font-weight: 600; }

.forecast-lines { display: flex; flex-direction: column; gap: var(--sp-1); font-size: var(--u-text-sm); line-height: 1.5; margin: 0; padding: 0; list-style: none; }
/* Same round accent bullet as .plan-reasons — the browser's default marker hung outside the
   card's left edge because the list has no padding. */
.forecast-lines li { position: relative; padding-left: var(--sp-3); }
.forecast-lines li::before { content: ''; position: absolute; left: 0; top: .6em; width: 5px; height: 5px; border-radius: 50%; background: var(--accent); }
.forecast-img { display: block; width: 100%; border-radius: var(--r-inner); }
.forecast-placeholder {
  display: flex; align-items: center; justify-content: center; width: 100%; height: 96px;
  border: 1px dashed var(--line); border-radius: var(--r-inner); color: var(--faint); font-size: var(--u-text-xs);
}
.forecast-next { font-size: var(--u-text-label); font-weight: 700; color: var(--text); line-height: 1.5; }
.forecast-asof { font-size: var(--u-text-xs); color: var(--faint); }
.forecast-reason { font-size: var(--u-text-xs); color: var(--muted); line-height: 1.6; }

.brief-chips { display: flex; flex-direction: column; gap: var(--sp-2); }
.brief-chip { background: var(--panel2); border-radius: var(--r-inner); padding: 10px var(--sp-3); }
.brief-slot-row { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-1) var(--sp-2); }
.brief-chip .slot { font-size: var(--u-text-xs); font-weight: 700; padding: 2px var(--sp-2); border-radius: var(--u-radius-pill); background: var(--acc-soft); color: var(--accent-text); white-space: nowrap; }
.brief-chip .at { font-size: var(--u-text-xs); color: var(--faint); white-space: nowrap; font-variant-numeric: tabular-nums; }
.brief-chip .text {
  font-size: var(--u-text-xs); margin-top: 6px; line-height: 1.55; white-space: pre-wrap;
  display: -webkit-box; -webkit-line-clamp: 7; -webkit-box-orient: vertical; overflow: hidden;
}
.brief-chip .text.expanded { -webkit-line-clamp: unset; overflow: visible; }
.brief-more {
  border: 0; background: transparent; color: var(--accent-text); font-size: var(--u-text-xs); font-weight: 600;
  min-height: 28px; padding: var(--sp-1) 0 0; margin-top: 2px;
}
.empty-note { font-size: var(--u-text-xs); color: var(--muted); }

.luna-card h2, .quickread-card h2 { margin: 0; }
.luna-card { gap: 10px; }
.luna-title-row { display: flex; align-items: center; gap: var(--sp-2); }
.quickread-trend { font-size: 14px; line-height: 1.6; }
.quickread-reasons, .luna-sources { display: flex; flex-direction: column; gap: 6px; margin: 0; padding: 0; list-style: none; font-size: var(--u-text-xs); }
.quickread-reasons li { padding-left: var(--sp-3); position: relative; }
.quickread-reasons li::before { content: ''; position: absolute; left: 0; top: .5em; width: 6px; height: 6px; border-radius: 50%; background: var(--accent); }
.level-ladder { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin: 6px 0 var(--sp-1); }
.level-tag { font-variant-numeric: tabular-nums; font-size: var(--u-text-compact); padding: 5px 10px; border-radius: var(--r-control); background: var(--panel2); }
.pattern-list { display: flex; flex-direction: column; gap: 10px; margin-top: 6px; }
.pattern-item { border-radius: var(--r-control); background: var(--panel2); padding: 10px var(--sp-3); }
.pattern-item .name { font-size: var(--u-text-xs); font-weight: 600; }
.pattern-item .bias { font-size: var(--u-text-xs); font-weight: 700; line-height: 1.5; padding: 0 6px; border-radius: var(--u-radius-pill); margin-left: 6px; white-space: nowrap; }
.pattern-item .bias.bullish { color: var(--up-text); background: var(--up-soft); }
.pattern-item .bias.bearish { color: var(--down-text); background: var(--down-soft); }
.pattern-item .bias.caution { color: var(--amber); background: var(--amber-soft); }
.pattern-item .bias.watch { color: var(--muted); background: var(--panel); }
.pattern-item .note { font-size: var(--u-text-xs); color: var(--muted); display: block; margin-top: 3px; }

#luna-body { display: flex; flex-direction: column; gap: 10px; }
.luna-helper { font-size: var(--u-text-xs); color: var(--muted); line-height: 1.5; margin: 0; }
.luna-btn-row { display: flex; }
.luna-btn-row .btn-primary { height: 44px; }
.luna-progress { font-size: var(--u-text-xs); color: var(--faint); text-align: center; animation: stPulse 1.6s ease-in-out infinite; }
.luna-empty { font-size: var(--u-text-xs); color: var(--muted); }
.luna-skeleton { display: flex; flex-direction: column; gap: var(--sp-2); }
.luna-skeleton-bar {
  height: 12px; border-radius: 6px;
  background: linear-gradient(90deg, var(--panel2) 25%, var(--hover) 37%, var(--panel2) 63%);
  background-size: 400% 100%; animation: stPulse 1.4s ease-in-out infinite;
}
.luna-skeleton-bar:nth-child(2) { width: 90%; }
.luna-skeleton-bar:nth-child(3) { width: 70%; }
.luna-summary { font-size: var(--u-text-compact); line-height: 1.6; }
.luna-field { font-size: var(--u-text-xs); line-height: 1.6; }
.luna-field b { font-weight: 600; }
.luna-conf { display: flex; align-items: center; gap: var(--sp-3); }
.luna-conf-ring {
  position: relative; width: 64px; height: 64px; border-radius: 50%; flex-shrink: 0;
  background: conic-gradient(var(--accent) 0deg, var(--line) 0deg);
}
.luna-conf-ring::after {
  content: attr(data-score); position: absolute; inset: 6px; border-radius: 50%; background: var(--panel);
  display: flex; align-items: center; justify-content: center; font-family: var(--font-mono);
  font-size: 14px; font-weight: 700;
}
.luna-conf-caption { font-size: var(--u-text-xs); color: var(--muted); line-height: 1.5; }

/* #endregion */

/* #region zone:desk.style.luna-deep — การ์ดวิเคราะห์เชิงลึกของ Luna */
/* ---- deep Luna analysis card (round 3 §2.4) ---- */
.deep-headline { font-size: 14px; font-weight: 700; line-height: 1.5; margin: 0; }
.deep-stance-row { display: flex; align-items: center; gap: 10px; }
.deep-stance-pill { font-size: var(--u-text-xs); font-weight: 700; padding: 3px 10px; border-radius: var(--u-radius-pill); }
.deep-stance-pill.tone-up { color: var(--up); background: var(--up-soft); }
.deep-stance-pill.tone-amber { color: var(--amber); background: var(--amber-soft); }
.deep-stance-pill.tone-down { color: var(--down); background: var(--down-soft); }
.deep-conf-ring { width: 44px; height: 44px; }
.deep-conf-ring::after { inset: 4px; font-size: var(--u-text-xs); }
.deep-conf-reason { font-size: var(--u-text-xs); color: var(--muted); line-height: 1.5; margin: 0; }
.deep-drivers { display: flex; flex-direction: column; gap: 6px; }
.deep-driver { display: flex; align-items: flex-start; gap: var(--sp-2); font-size: var(--u-text-xs); line-height: 1.5; }
.deep-driver .glyph { flex-shrink: 0; font-weight: 700; width: 14px; text-align: center; }
.deep-driver .scope-chip { flex-shrink: 0; font-size: var(--u-text-xs); font-weight: 600; padding: 1px 7px; border-radius: var(--u-radius-pill); background: var(--panel); border: 1px solid var(--line); color: var(--muted); }
.deep-driver .driver-text { flex: 1; min-width: 0; }
.deep-section { border-top: 1px solid var(--line); padding-top: var(--sp-2); }
.deep-section summary { cursor: pointer; font-size: var(--u-text-compact); font-weight: 600; list-style: none; border-radius: 6px; }
.deep-section summary:hover { color: var(--accent-text); }
.deep-section summary::-webkit-details-marker { display: none; }
.deep-section summary::before { content: '▸ '; color: var(--muted); }
.deep-section[open] summary::before { content: '▾ '; }
.deep-section p { font-size: var(--u-text-xs); line-height: 1.6; margin: 6px 0 0; }
.deep-section ul { margin: 6px 0 0; padding: 0 0 0 14px; font-size: var(--u-text-xs); line-height: 1.6; }
.deep-generated-at { font-size: var(--u-text-xs); color: var(--faint); }
.deep-ask-more {
  display: inline-flex; align-items: center; width: fit-content;
  border: 1px solid var(--line); background: transparent; color: var(--accent-text);
  font-size: var(--u-text-xs); font-weight: 600; min-height: 32px; padding: 6px 14px; border-radius: var(--u-radius-pill);
}
.deep-ask-more:hover { background: var(--acc-soft); }

.news-list { display: flex; flex-direction: column; gap: 2px; }
.news-item { display: grid; grid-template-columns: 8px minmax(0, 1fr); gap: 10px; padding: 9px 0; border-bottom: 1px solid var(--line); }
.news-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--accent); margin-top: 6px; }
.news-title { font-size: var(--u-text-compact); line-height: 1.5; }
.news-title a { color: var(--text); }
.news-title a:hover { color: var(--accent-text); }
.news-list:not(.expanded) .news-item:nth-child(n+6) { display: none; }
.news-item:last-child { border-bottom: 0; }
.news-meta { font-size: var(--u-text-xs); color: var(--muted); margin-top: 3px; }
/* #endregion */

/* #region zone:desk.style.chat — การ์ดแชท */
/* ---- chat card: fills the chat column (always on screen on desktop, the แชท tab on phones) ---- */
.chat-card {
  display: flex; flex-direction: column; min-width: 0; background: var(--panel);
  border: 1px solid var(--line); border-radius: var(--r-card); box-shadow: var(--card-shadow);
}
.chat-card-head { display: flex; flex-wrap: nowrap; align-items: center; gap: var(--sp-1) 10px; padding: 14px var(--sp-4) var(--sp-3); border-bottom: 1px solid var(--line); }
.chat-card-head h2 { margin: 0; font-size: 14px; font-weight: 700; }
/* DUI-12: the subtitle is one line that ends in an ellipsis, so the clear button stays on the title row. */
.chat-card-sub { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: var(--u-text-xs); color: var(--muted); }
.chat-card-head .chat-clear-btn { flex: none; margin-left: auto; }
.quota-line { margin-left: auto; font-size: var(--u-text-xs); color: var(--faint); }
/* overflow-x:hidden (owner screenshot, 09-26): a long unbroken URL in a reply has no whitespace
   for pre-wrap to break on, so without .chat-msg's own overflow-wrap below the bubble — and this
   whole list — grew wider than the column and forced a horizontal scrollbar. Belt-and-suspenders:
   even if some future content still doesn't wrap, the list itself now clips instead of scrolling. */
.chat-messages { flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden; overscroll-behavior: contain; scrollbar-width: thin; display: flex; flex-direction: column; gap: 10px; padding: 14px var(--sp-4); }
.chat-hello { font-size: var(--u-text-xs); color: var(--muted); line-height: 1.6; padding: 10px var(--sp-3); border: 1px dashed var(--line); border-radius: var(--r-inner); }
.chat-msg { max-width: 82%; padding: 9px var(--sp-3); border-radius: var(--r-inner); font-size: var(--u-text-compact); line-height: 1.6; white-space: pre-wrap; overflow-wrap: anywhere; border: 1px solid var(--line); }
.chat-msg.user { align-self: flex-end; background: var(--acc-soft); border-color: var(--acc-ring); }
.chat-msg.bot { align-self: flex-start; background: var(--panel2); color: var(--text); }
.chat-msg.system { align-self: flex-start; background: transparent; color: var(--muted); font-size: var(--u-text-xs); border-style: dashed; }
.chat-msg .label { display: block; font-size: var(--u-text-xs); font-weight: 700; color: var(--muted); margin-bottom: 3px; }
.chat-attachments { display: flex; flex-direction: column; gap: 6px; margin-top: var(--sp-2); }
.chat-attachment { border: 1px solid var(--line); border-radius: var(--r-inner); padding: var(--sp-2); background: var(--panel); font-size: var(--u-text-xs); }
.chat-attachment button { border: 1px solid var(--line); background: transparent; color: var(--accent-text); font-size: var(--u-text-xs); padding: 3px 9px; border-radius: var(--u-radius-pill); margin-top: var(--sp-1); transition: background-color .15s ease; }
.chat-attachment button:not(:disabled):hover { background: var(--acc-soft); }
.chat-suggestions { display: flex; border-top: 1px solid var(--line); }
.chat-suggestions button { border: 1px solid var(--line); background: transparent; color: var(--muted); font-size: var(--u-text-xs); border-radius: var(--u-radius-pill); transition: background-color .15s ease, color .15s ease; }
.chat-suggestions button:hover { background: var(--hover); color: var(--text); }
.chat-form { display: flex; flex-direction: column; gap: var(--sp-2); padding: 10px var(--sp-4) 14px; }
/* Shift+Enter adds lines: the box grows with its text (field-sizing) up to ~5 lines, then scrolls;
   browsers without field-sizing keep the one-line box and scroll inside it. */
.chat-form textarea { flex: 1; min-width: 0; resize: none; height: 40px; padding: 9px var(--sp-3); line-height: 1.5; background: var(--panel2); border: 1px solid var(--line); border-radius: var(--r-input); font-size: var(--u-text-sm); outline: none; }
@supports (field-sizing: content) {
  .chat-form textarea { field-sizing: content; height: auto; min-height: 40px; max-height: 128px; }
}
.chat-form .btn-send { width: auto; height: 40px; margin-top: 0; padding: 0 18px; flex-shrink: 0; }
/* #endregion */

/* #region zone:desk.style.tabbar — แท็บล่างบนมือถือ */
/* ---- bottom tab bar (phone only) ---- */
.bottom-tabbar {
  display: none; /* switched on at <768px below */
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 40;
  height: calc(56px + env(safe-area-inset-bottom, 0px));
  padding-bottom: env(safe-area-inset-bottom, 0px);
  background: var(--header-bg); border-top: 1px solid var(--header-line);
}
.tabbar-btn {
  flex: 1; height: 56px; border: 0; background: transparent; color: var(--header-well-text);
  font-size: var(--u-text-xs); font-weight: 600;
  display: flex; align-items: center; justify-content: center;
}
.tabbar-btn:not(.active):hover { color: var(--header-text); }
.tabbar-btn.active { color: var(--mint); background: var(--header-well-hover); box-shadow: inset 0 2px 0 var(--mint); }
/* #endregion */

/* #region zone:desk.style.sheet — แผ่นเมนูบัญชีบนมือถือ */
/* ---- account sheet (phone: opened by tapping the header avatar) ---- */
/* #account-panel (relocated here by desk.js's syncAccountPanelMount()) supplies its own
   background/border/shadow — same box as the desktop popover — but sits edge-to-edge and flush
   against the viewport bottom here, so its corners/padding are overridden below: top-only radius,
   the device's safe-area inset added on top of the panel's own 12px bottom padding, and a small
   drag-handle bar standing in for the desktop popover's "opened near the trigger" affordance. */
.logout-sheet { position: fixed; inset: 0; z-index: 55; }
.logout-sheet-backdrop { position: absolute; inset: 0; border: 0; padding: 0; background: var(--scrim); }
.logout-sheet-panel {
  position: absolute; left: 0; right: 0; bottom: 0;
}
.logout-sheet-panel .account-panel {
  position: relative; border-radius: var(--r-inner) var(--r-inner) 0 0; border-bottom: 0;
  padding: var(--sp-5) var(--sp-3) calc(var(--sp-3) + env(safe-area-inset-bottom, 0px));
}
.logout-sheet-panel .account-panel::before {
  content: ''; position: absolute; top: 8px; left: 50%; transform: translateX(-50%);
  width: 36px; height: 4px; border-radius: var(--u-radius-pill); background: var(--line);
}
.logout-sheet-panel .account-panel-item { height: 48px; font-size: 14px; }

/* Member name + tier only show beside the avatar at ≥1024px — below that the account menu is
   avatar-only, matching the compact header. */
@media (max-width: 1023px) {
  .member-name-tier { display: none; }
}
/* #endregion */

/* #region zone:desk.style.responsive.tablet — จอ 900–1199px */
/* ================= Responsive: 900–1199px ================= */
/* The watchlist is a rail by default here; its toggle opens the full list over the chart
   (desk.js: .wl-overlay), and a pick or an outside click closes it again. */
@media (max-width: 1199px) {
  .app-shell, .app-shell.wl-rail { --wl-w: 76px; --chat-w: 320px; --gap: 12px; }
  .watchlist-panel { z-index: 25; }
  .wl-overlay .watchlist-panel { width: 292px; box-shadow: var(--shadow); }
  .symbol-header { gap: var(--sp-2) var(--sp-3); }
}
/* Narrow desktop (900–1023px): a slimmer chat column so the chart keeps ~480px or more. */
@media (min-width: 900px) and (max-width: 1023px) {
  .app-shell, .app-shell.wl-rail { --chat-w: 296px; }
}
/* #endregion */

/* #region zone:desk.style.responsive.phone — จอมือถือและแท็บเล็ต (<900px) และเป้าสัมผัส */
/* ================= Responsive: phone + tablet (<900px) ================= */
@media (max-width: 899px) {
  .bottom-tabbar { display: flex; }
  .app-shell { padding-bottom: calc(56px + env(safe-area-inset-bottom, 0px)); --gap: 16px; }

  /* Slightly tighter card corners on phone than the desktop 22px — this cascades to every card
     that already keys off --r-card (watchlist/chart/chat, rail cards, login). */
  :root { --r-card: 18px; }

  /* ---- header: 52px tall, collapses to logo + quick-tools + avatar only ---- */
  .app-header { height: 52px; padding: 0 var(--sp-3); gap: var(--sp-2); }
  .brand-sub { display: none; }
  .search-wrap, .ai-chip, .clock { display: none; }
  /* tapping the avatar opens the bottom sheet (wired in desk.js, gated to this breakpoint). */
  .account { gap: 0; }
  .member-avatar { cursor: pointer; width: 36px; height: 36px; font-size: var(--u-text-xs); }
  .search-mobile-mount { padding: var(--sp-2) var(--sp-2) 0; }
  .search-mobile-mount .search-wrap { display: block; width: 100%; max-width: 100%; }
  .search-mobile-mount .search-wrap input { background: var(--panel2); border-color: var(--line); color: var(--text); }
  .search-mobile-mount .search-wrap input::placeholder { color: var(--faint); }
  .search-mobile-mount .search-wrap input:focus { border-color: var(--accent); }
  .search-mobile-mount .search-wrap svg { color: var(--faint); }
  /* In the list tab the results push the rows down instead of floating over them. */
  .search-mobile-mount .search-pop { position: static; width: auto; min-width: 0; margin-top: var(--sp-2); box-shadow: var(--card-shadow); }

  /* ---- one section per bottom tab: รายการ / กราฟ / สรุป / แชท ---- */
  .app-grid { display: block; padding: var(--sp-4); }
  .watchlist-panel, .main-col, .chat-col { display: none; }
  .wl-toggle { display: none; }
  /* HIGH fix (audit 2026-09-26; the desktop cap itself was dropped 2026-10-19): the desktop rule
     capped the panel at max-height:var(--side-h) with overflow:hidden so only .watchlist-rows scrolled. On
     phone the panel is the whole tab's content and the PAGE scrolls, but that cap+clip still
     applied here — rows past --side-h were clipped off with nothing to reach them. Reset both so
     the mobile list rule's own overflow:visible on .watchlist-rows actually reaches every row. */
  #app-shell[data-mobile-tab="list"] .watchlist-panel {
    display: flex; position: static; height: auto; max-height: none; overflow: visible;
  }
  #app-shell[data-mobile-tab="list"] .watchlist-rows { overflow: visible; }
  #app-shell[data-mobile-tab="chart"] .main-col,
  #app-shell[data-mobile-tab="summary"] .main-col { display: flex; }
  #app-shell[data-mobile-tab="chart"] .info-strip { display: none; }
  #app-shell[data-mobile-tab="summary"] .chart-card { display: none; }
  /* สรุป tab: the info strip is the whole view — its panels grow with the page instead of scrolling. */
  .strip-panel { max-height: none; overflow: visible; }
  .strip-grid > .rail-card { flex-basis: min(100%, 300px); }
  .strip-tabs {
    position: -webkit-sticky; position: sticky; top: 0; z-index: 2;
    background: var(--panel); border-radius: var(--r-card) var(--r-card) 0 0;
  }

  /* Chart tab: full-bleed chart card (stock header row on top) filling the space between the
     header and the tab bar. */
  #app-shell[data-mobile-tab="chart"] .app-grid { padding: 0; }
  #app-shell[data-mobile-tab="chart"] .main-col {
    height: calc(100vh - 52px - 56px - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px));
    height: calc(100dvh - 52px - 56px - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px));
    min-height: 460px;
  }
  #app-shell[data-mobile-tab="chart"] .symbol-header { padding: var(--sp-3) var(--sp-4); }
  #app-shell[data-mobile-tab="chart"] .sym-stale-notice { margin: var(--sp-2) var(--sp-4) 0; }
  #app-shell[data-mobile-tab="chart"] .chart-card {
    flex: 1 1 auto; min-height: 0; border: 0; border-radius: 0; box-shadow: none;
  }
  #app-shell[data-mobile-tab="chart"] .chart-host { flex: 1 1 auto; height: auto; min-height: 260px; }
  #app-shell[data-mobile-tab="chart"] .range-strip { border-radius: 0; }

  /* Chat tab: the card fills the screen; only the messages scroll. */
  #app-shell[data-mobile-tab="chat"] .chat-col {
    display: flex; position: static;
    height: calc(100vh - 52px - 56px - 32px - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px));
    height: calc(100dvh - 52px - 56px - 32px - env(safe-area-inset-top, 0px) - env(safe-area-inset-bottom, 0px));
    min-height: 360px;
  }
  .chat-card-sub { display: none; }

  /* ---- symbol header ---- */
  .logo-disc { --logo-size: 30px; }
  .sym-ticker { font-size: 18px; }
  .sym-price { font-size: var(--u-text-xl); }

  /* ---- toolbar: [timeframe] [ตัวชี้วัด] [⋯]; the rest lives in a bottom sheet ---- */
  .chart-toolbar { gap: var(--sp-2); padding: var(--sp-2) var(--sp-3); }
  .tf-seg .seg-btn { min-width: 36px; padding: 0 6px; }
  .chart-toolbar .tb-more-btn { display: inline-flex; margin-left: auto; order: 5; }
  .tb-sheet {
    display: none; position: fixed; left: 0; right: 0; bottom: 0; top: auto; z-index: 56;
    width: auto; max-height: 78vh; overflow-y: auto; overscroll-behavior: contain;
    flex-direction: column; gap: var(--sp-3); padding: var(--sp-2) var(--sp-4) calc(var(--sp-4) + env(safe-area-inset-bottom, 0px));
    background: var(--panel); color: var(--text); border: 1px solid var(--line); border-bottom: 0;
    border-radius: var(--r-card) var(--r-card) 0 0; box-shadow: var(--shadow);
  }
  .tb-sheet.open { display: flex; animation: sheetUp .22s var(--ease-out); }
  .tb-pop-head {
    display: flex; align-items: center; justify-content: space-between; flex-shrink: 0;
    font-size: 15px; font-weight: 700; padding: 6px 0 6px var(--sp-1); position: relative;
  }
  .tb-pop-head::before {
    content: ''; position: absolute; top: -2px; left: 50%; transform: translateX(-50%);
    width: 36px; height: 4px; border-radius: var(--u-radius-pill); background: var(--line);
  }
  .tb-pop-close { width: 40px; height: 40px; }
  .tb-type #type-btn { display: none; }
  .tb-type .type-menu {
    display: flex; position: static; flex-direction: row; gap: 2px; min-width: 0; width: 100%; padding: 2px;
    background: var(--panel2); border: 0; border-radius: 12px; box-shadow: none; animation: none;
  }
  .type-item { flex: 1; justify-content: center; height: 40px; }
  .type-item[aria-checked="true"] { background: var(--seg-on); box-shadow: var(--seg-shadow); }
  .tb-tools { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-2); margin-left: 0; }
  .tb-tools .tb-sep { display: none; }
  .tb-tools .tb-btn.tb-icon {
    width: auto; height: 60px; flex-direction: column; gap: var(--sp-1); padding: 0 var(--sp-1);
    background: var(--panel2); color: var(--text); border-radius: 12px;
  }
  .tb-tools .lock-toggle[aria-pressed="true"] { background: var(--acc-soft); color: var(--accent-text); }
  .tb-sheet-label { display: block; font-size: var(--u-text-xs); font-weight: 600; }

  .range-strip { padding: 6px var(--sp-3); scroll-snap-type: x proximity; }
  .range-strip .range-seg {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    width: 100%;
    border-radius: var(--r-inner);
  }
  .range-seg .seg-btn:last-child { grid-column: span 2; }
  .range-seg .seg-btn { scroll-snap-align: start; }
  /* Legend: one line only on phones — C, change %, Vol. */
  .chart-legend { top: 4px; left: 6px; font-size: var(--u-text-xs); padding: 3px 6px; }
  .legend-main { flex-wrap: nowrap; }
  .lg-ticker, .lg-time, .lg-ohl, .lg-chg, .legend-ind, .legend-toggle { display: none; }
  .sub-legend { font-size: var(--u-text-xs); left: 6px; }

  /* ---- watchlist rows: 56px, 36px logo, 12px name line, 14px mono prices ---- */
  .wl-name { font-size: var(--u-text-xs); }
  .wl-ticker { font-size: var(--u-text-sm); }
  .wl-price { font-size: 14px; }
  .wl-signal, .wl-change { font-size: var(--u-text-xs); }
  .panel-head { padding: 14px 14px 10px; }
  .wl-empty, .header-line, .panel-foot { font-size: var(--u-text-xs); }
  .eyebrow { font-size: 14px; }

  /* ---- summary cards: same 15/14/13/12/11 scale as before ---- */
  .rail-card h2 { font-size: 15px; }
  .plan-decision { font-size: var(--u-text-sm); }
  .plan-reasons { font-size: var(--u-text-xs); }
  .forecast-placeholder { font-size: var(--u-text-xs); }
  .brief-chip .slot { font-size: var(--u-text-xs); }
  .brief-chip .text { font-size: var(--u-text-xs); }
  .daily-note { font-size: var(--u-text-xs); }
  .tier-badge { font-size: var(--u-text-xs); }
  .quickread-trend { font-size: 14px; line-height: 1.5; }
  .level-ladder { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-2); margin: var(--sp-2) 0 6px; }
  .level-tag { text-align: center; padding: var(--sp-2) 10px; font-size: var(--u-text-xs); }
  .pattern-list { gap: 10px; margin-top: var(--sp-2); }
  .pattern-item { padding: var(--sp-3); }
  .pattern-item .name { font-size: var(--u-text-sm); }
  .pattern-item .bias { font-size: var(--u-text-xs); }
  .luna-helper { font-size: var(--u-text-sm); }
  .luna-sources { font-size: var(--u-text-sm); }
  .luna-conf-caption { font-size: var(--u-text-xs); }
  .deep-drivers { gap: var(--sp-2); }
  .deep-driver .scope-chip { font-size: var(--u-text-xs); }
  .deep-section summary, .deep-section p, .deep-section ul { font-size: 14px; }
  .deep-generated-at { font-size: var(--u-text-xs); }
  .deep-ask-more { font-size: var(--u-text-xs); }
  .news-title { font-size: var(--u-text-sm); }
  .news-meta { font-size: var(--u-text-xs); }
  .chat-msg { font-size: var(--u-text-sm); max-width: 88%; }
  .chat-msg.system { font-size: var(--u-text-xs); }
  .chat-msg .label { font-size: var(--u-text-xs); }
  .chat-attachment { font-size: var(--u-text-xs); }
  .quota-line { font-size: var(--u-text-xs); }

  /* iOS Safari zooms the viewport on focusing any input/textarea under 16px — the generic rule
     covers unstyled fields, and the three below re-assert 16px against their own more-specific
     13px/12.5px rules (a class-qualified selector otherwise outranks this media query). */
  input, textarea, select { font-size: 16px; }
  .auth-form input, .search-wrap input, .chat-form textarea { font-size: 16px; }
  .auth-form input { height: 48px; }
  .auth-form label { font-size: var(--u-text-xs); }
  .btn-primary { height: 48px; }
  .hint, .login-help { font-size: var(--u-text-xs); }
  .tab { font-size: var(--u-text-sm); }
}
@keyframes sheetUp { from { transform: translateY(24px); opacity: 0; } to { transform: none; opacity: 1; } }
/* Very narrow phones: the indicator button drops its word, keeping the icon and the count. */
@media (max-width: 359px) {
  .tb-ind .tb-btn-label > span:not(.tb-count) { display: none; }
}

/* ================= Touch input: finger-sized hit targets ================= */
/* Keyed off the input device, not the viewport, so an iPad in landscape (desktop layout) gets
   finger-sized toolbar controls too (--tb-h is 40px there, set on .chart-card above), while a
   mouse-driven narrow window keeps the 32px row. */
@media (pointer: coarse) {
  .seg-btn { min-width: 40px; }
  .deep-ask-more { min-height: 40px; }
  .brief-more, .text-btn { min-height: 40px; }
  .icon-btn { width: 40px; height: 40px; }
}
/* #endregion */

/* #region zone:desk.style.support — ปุ่มผู้ช่วยสนับสนุนในแชท */
/* Support assistant chips (support.js) */
.chat-support-chips { display: flex; flex-wrap: wrap; gap: 5px; margin-top: var(--sp-2); }
.chat-support-chips button, .chat-suggestions .chat-help-chip { border: 1px solid var(--line); background: transparent; color: inherit; font-size: var(--u-text-xs); padding: var(--sp-1) 9px; border-radius: var(--u-radius-pill); cursor: pointer; transition: background-color .15s ease; }
.chat-support-chips button:hover { background: var(--hover); }
.chat-suggestions .chat-help-chip { border-color: var(--acc-ring); color: var(--accent-text); font-weight: 600; }
.chat-suggestions .chat-help-chip:hover { background: var(--acc-soft); color: var(--accent-text); }
/* #endregion */

/* #region zone:desk.style.brand-motion — แบรนด์และภาพเคลื่อนไหว */
.super-t-mark { display: block; flex-shrink: 0; background: currentColor; color: var(--brand-mark); mask: url("super-t-mark.svg") center / contain no-repeat; }
.header-mark { width: 30px; height: 30px; }
:root[data-board] .brand .brand-accent { color: var(--brand-mark); }
.login-shell-brand { background: linear-gradient(145deg, var(--brand-panel-start), var(--brand-panel-end)); }
.login-shell-brand .super-t-mark { color: var(--brand-on-panel); }
.desk-agent-stage { position: relative; width: 100%; height: clamp(380px,55vh,580px); align-self: center; }
.desk-agent-stage .login-agent, .desk-agent-effects { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; }
.desk-agent-effects { pointer-events: none; }
.login-shell-brand-inner { gap: var(--sp-3); }
@media(max-width:759px) { .desk-agent-stage { grid-column: 1 / -1; grid-row: 3; height: 260px; } }
@media(max-width:600px) { .desk-agent-stage { display: none; } }
/* #endregion */


/* #region zone:desk.chat.retry-style — ตัวเลือกโมเดลสำรองที่ผู้ใช้กดเอง */
.chat-support-chips .chat-retry-luna {
  font-size: 0.8em;
  text-decoration: underline;
  background: transparent;
  border-color: transparent;
}
/* #endregion */
