/* ==============================================================
 * Components — ticker, header, cards, tables, tooltips, forms
 * ============================================================== */

.ticker-wrap {
  /* background, border, border-radius, box-shadow inherited from .t-card, .ticker-wrap in 02-base.css */
  position: relative;
  overflow: hidden;
  height: 36px;
}
.ticker-wrap::before,
.ticker-wrap::after {
  content: '';
  position: absolute;
  top: 0; bottom: 0;
  width: 32px;
  z-index: 2;
  pointer-events: none;
}
.ticker-wrap::before {
  left: 0;
  background: linear-gradient(to right, var(--bg-card), transparent);
  border-radius: var(--radius-card, 14px) 0 0 var(--radius-card, 14px);
}
.ticker-wrap::after {
  right: 0;
  background: linear-gradient(to left, var(--bg-card), transparent);
  border-radius: 0 var(--radius-card, 14px) var(--radius-card, 14px) 0;
}
.ticker-wrap:has(.info-anchor:hover) { overflow: visible; }
.ticker-wrap .info-bubble {
  top: calc(100% + 6px);
  bottom: auto;
  transform: translateX(-50%) translateY(-5px);
}
.ticker-wrap .info-anchor:hover .info-bubble,
.ticker-wrap .info-anchor:focus .info-bubble {
  transform: translateX(-50%) translateY(0);
}
.ticker-track {
  display: flex;
  align-items: center;
  height: 100%;
  white-space: nowrap;
  will-change: transform;
  width: max-content;
}
.ticker-track.running {
  animation: ticker-scroll var(--ticker-dur, 30s) linear infinite;
}
.ticker-item {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 0 18px;
}
/* Override Tailwind text-sm/text-xs line-heights so align-items:center works */
.ticker-item .tk-val,
.ticker-item .text-xs,
.ticker-item .ticker-lbl,
.ticker-item .ticker-sep { line-height: 1; }
.ticker-sep { color: var(--text-dim); opacity: 0.35; font-size: 0.7rem; }
.ticker-lbl { font-size: 0.6rem; font-weight: 700; opacity: 0.55; }
.ticker-chgs { display: inline-flex; align-items: center; gap: 4px; }
@keyframes ticker-scroll {
  0%   { transform: translateX(0); }
  100% { transform: translateX(var(--ticker-shift, -50%)); }
}
/* Thin progress bar fixed at the very top of the page — VS Code / Material indeterminate */
#top-loader {
  position: fixed; top: 0; left: 0; right: 0; height: 1px; z-index: var(--z-toploader);
  background: color-mix(in srgb, var(--accent) 22%, transparent);
  opacity: 0; pointer-events: none; overflow: hidden;
}
#top-loader.is-loading { opacity: 1; }
#top-loader.is-done    { opacity: 0; visibility: hidden; }
#top-loader.is-loading::before {
  content: ''; position: absolute; top: 0; height: 100%;
  background: var(--accent);
  animation: vscode-bar1 4.0s cubic-bezier(0.65, 0.815, 0.735, 0.395) infinite;
}
@keyframes vscode-bar1 {
  0%   { left: -15%; right: 100%; }
  100% { left: 115%; right: -30%; }
}

/* ── Universal "soft small button" treatment ────────────────────────────────
 * Subtle fill at rest, no border; accent border on hover and keyboard focus.
 * Shared by every neutral, secondary small button — the header controls, the
 * table-row edit button, outlined utility buttons, and the inactive state of
 * toggle groups like the period selector. Each consumer keeps its own
 * size/typography in its own rule (the height/padding/font-size of header
 * controls differ from period buttons); only the visual treatment is shared
 * here. New buttons can opt in by adding the .btn-soft class.
 *
 * Primary CTAs (.btn-accent*), destructive (.btn-danger-sm, .btn-delete),
 * the active state of toggles (.tab-active, .period-active), and nav tabs
 * deliberately stay distinct — they carry different semantics.
 *
 * The 1px border at rest is transparent so revealing it on hover never shifts
 * layout. Per-theme rules (e.g. [data-theme="amoled"] .period-inactive) still
 * cascade on top and override per theme.
 * ─────────────────────────────────────────────────────────────────────────── */
.btn-soft,
.theme-select,
.btn-edit-sm,
.btn-outlined-subtle,
.period-inactive {
  background: var(--bg-deep);
  color: var(--text-sub);
  border: 1px solid transparent;
  cursor: pointer;
  outline: none;
  transition: border-color 0.15s;
}
.btn-soft:hover,
.theme-select:hover,
.btn-edit-sm:hover,
.btn-outlined-subtle:hover,
.period-inactive:hover {
  border-color: var(--accent);
}
.btn-soft:focus-visible,
.theme-select:focus-visible,
.btn-edit-sm:focus-visible,
.btn-outlined-subtle:focus-visible,
.period-inactive:focus-visible {
  border-color: var(--accent);
}

/* Size + typography for the header controls. */
.theme-select {
  display: inline-flex; align-items: center;
  height: 24px; box-sizing: border-box;
  border-radius: var(--radius-sm, 6px);
  padding: 0 8px;
  font-size: 0.75rem;
}

/* Keep the picker trigger outlined while its menu is open. */
.theme-picker[data-open] .theme-picker-btn { border-color: var(--border); }
#eurusd-badge { border-radius: var(--radius-sm, 4px); }
#pct-mode-btn { width: 32px; padding: 0; justify-content: center; }

/* Custom theme picker */
.theme-picker { position: relative; display: inline-block; }
.theme-picker-btn {
  display: flex; align-items: center; gap: 5px;
  white-space: nowrap; line-height: 1;
}
.theme-picker-icon { display: flex; align-items: center; flex-shrink: 0; }
.theme-picker-icon svg { display: block; }
.theme-picker-chevron { opacity: 0.45; transition: transform 0.15s; flex-shrink: 0; }
.theme-picker[data-open] .theme-picker-chevron { transform: rotate(180deg); }
.theme-picker-list {
  display: none;
  position: absolute; right: 0; top: calc(100% + 4px);
  background: var(--bg-card); border: 1px solid var(--border);
  border-radius: min(var(--radius-sm, 6px), 10px);
  box-shadow: 0 4px 20px rgba(0,0,0,0.18);
  padding: 3px; z-index: var(--z-dropdown);
  min-width: 128px; list-style: none; margin: 0;
}
.theme-picker[data-open] .theme-picker-list { display: block; }
.theme-picker-item {
  display: flex; align-items: center; gap: 7px;
  padding: 4px 7px;
  cursor: pointer; font-size: 0.75rem; color: var(--text-sub);
  transition: background 0.1s, color 0.1s; white-space: nowrap;
  border-radius: min(calc(var(--radius-sm, 6px) - 2px), 8px);
}
.theme-picker-item:hover { background: var(--bg-hover); color: var(--text-primary); }
.theme-picker-item[aria-selected="true"] { color: var(--text-primary); background: var(--bg-hover); }

/* Table fade-in — only on initial data load (JS adds .animate-rows class once) */
@keyframes row-fade-in { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
#table-body.animate-rows tr { animation: row-fade-in 0.2s ease both; }
#table-body.animate-rows tr:nth-child(1)  { animation-delay: 0ms;  }
#table-body.animate-rows tr:nth-child(2)  { animation-delay: 30ms; }
#table-body.animate-rows tr:nth-child(3)  { animation-delay: 55ms; }
#table-body.animate-rows tr:nth-child(4)  { animation-delay: 75ms; }
#table-body.animate-rows tr:nth-child(5)  { animation-delay: 90ms; }
#table-body.animate-rows tr:nth-child(n+6){ animation-delay: 105ms; }

/* Pre/post market session badge in Today column */
.ext-badge {
  font-size: 9px; padding: 1px 5px; border-radius: 3px; margin-left: 3px;
  background: var(--bg-deep); color: var(--text-muted);
  border: 1px solid var(--border); vertical-align: middle;
}

/* Subtotals row */
.totals-row td { border-top: 2px solid var(--border); }

::-webkit-scrollbar       { width: 4px; height: 4px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--scrollbar); border-radius: 4px; }

/* ==============================================================
 * Design system improvements — modular, consumes theme tokens
 * ============================================================== */

/* --- Header utility classes --- */
.header-icon-btn {
  background: none;
  border: none;
  cursor: pointer;
  padding: 2px;
  display: inline-flex;
  align-items: center;
  opacity: 0.45;
  transition: opacity 0.15s, transform 0.15s;
  color: inherit;
}
.header-icon-btn:hover { opacity: 0.9; }

/* --- Market hours compact chips --- */
.mkt-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 0.68rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  padding: 2px 10px;
  border-radius: var(--radius-sm, 4px);
  background: var(--bg-deep);
  border: 1px solid transparent;
  cursor: default;
  white-space: nowrap;
  flex-shrink: 0;
  position: relative;
  transition: border-color 0.15s;
  color: var(--text-sub);
}
/* Same softening as .theme-select: subtle fill, no resting border, accent
   outline on hover. Border declared above stays 1px transparent (size-stable). */
.mkt-chip:hover { border-color: var(--accent); }
.mkt-chip::before {
  content: '';
  width: 5px; height: 5px;
  border-radius: 50%;
  flex-shrink: 0;
}
.mkt-chip[data-status="open"]::before   { background: var(--gain); }
.mkt-chip[data-status="pre"]::before    { background: var(--warn); }
.mkt-chip[data-status="post"]::before   { background: var(--warn); }
.mkt-chip[data-status="maint"]::before  { background: var(--warn); }
.mkt-chip[data-status="closed"]::before { background: var(--text-muted); opacity: 0.45; }
/* Tooltip */
.mkt-tip {
  position: absolute;
  top: calc(100% + 7px);
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  gap: 4px;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: min(var(--radius-sm, 6px), 10px);
  padding: 6px 10px;
  font-size: 0.72rem;
  white-space: nowrap;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.15s;
  z-index: var(--z-dropdown);
  box-shadow: 0 4px 20px rgba(0,0,0,0.18);
}
.mkt-chip:hover .mkt-tip { opacity: 1; }
.mkt-tip-row   { display: flex; align-items: center; gap: 6px; }
.mkt-tip-name  { color: var(--text-primary); font-weight: 500; min-width: 3.5rem; }
.mkt-tip-hours { color: var(--text-muted); }

/* --- Refresh progress ring --- */
.refresh-ring-btn {
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: 26px; height: 26px;
  color: inherit;
  /* It's the last item in .hdr-status (gap-4 = 1rem on its left) but the parent
     row uses gap-3 (0.75rem) to the major separator on its right. Add the 0.25rem
     difference so the ring sits symmetrically between the two separators. */
  margin-right: 0.25rem;
}
.refresh-ring-svg {
  display: block;
  transform: rotate(-90deg);
}
.refresh-ring-track {
  fill: none;
  stroke: var(--border);
  stroke-width: 1.5;
  opacity: 0.5;
}
.refresh-ring-arc {
  fill: none;
  stroke: var(--accent);
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-dasharray: 56.55;
  stroke-dashoffset: 0;
  opacity: 0.55;
  transition: stroke-dashoffset 0.95s linear, opacity 0.15s;
}
.refresh-ring-btn:hover .refresh-ring-arc { opacity: 1; }

/* Status colour drives both the centre dot (background: currentColor) and the
   refresh arrows (stroke: currentColor), so they always match. Set by
   renderStatusDot() via data-state on the button. */
.refresh-ring-btn[data-state="live"]  { color: var(--gain); }
.refresh-ring-btn[data-state="stale"] { color: var(--warn); }
.refresh-ring-btn[data-state="error"] { color: var(--loss); }

/* Centre status light — visible at rest, pulses only when live. */
.refresh-core {
  position: absolute;
  top: 50%; left: 50%;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: currentColor;
  transform: translate(-50%, -50%) scale(1);
  transition: opacity 0.18s ease, transform 0.18s ease;
  pointer-events: none;
}
.refresh-ring-btn[data-state="live"] .refresh-core { animation: pulse 2s infinite; }

/* Refresh arrows — hidden at rest; cross-fade + scale in on hover, inheriting
   the status colour. The wrapper owns the morph transform; the inner svg owns
   the click-spin rotation (set inline by manualRefresh) so the two don't fight. */
.refresh-icon-inner {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%) scale(0.4);
  opacity: 0;
  transition: opacity 0.18s ease, transform 0.18s ease;
  pointer-events: none;
  line-height: 0;
}
#refresh-icon { display: block; transition: transform 0.6s linear; }

/* Hover: morph the dot out and the arrows in. */
.refresh-ring-btn:hover .refresh-core {
  opacity: 0;
  transform: translate(-50%, -50%) scale(0.4);
  animation: none;
}
.refresh-ring-btn:hover .refresh-icon-inner {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
}

/* Header group separators */
.hdr-sep {
  width: 1px;
  height: 1rem;
  background: var(--border);
  opacity: 0.6;
  flex-shrink: 0;
}
.hdr-sep--major {
  height: 1.4rem;
  opacity: 0.8;
}
.tabular-nums-countdown {
  display: inline-block;
  min-width: 2ch;
  text-align: right;
  font-variant-numeric: tabular-nums;
}

/* --- Sticky glass header --- */
#sticky-top {
  position: sticky;
  top: 0;
  z-index: var(--z-header);
}
header {
  background: var(--header-bg, var(--bg-card)) !important;
  backdrop-filter: var(--header-blur, none);
  -webkit-backdrop-filter: var(--header-blur, none);
}

/* Hairline accent border at header bottom — adapted per theme */
[data-theme="dark"] header::after,
[data-theme="midnight"] header::after,
[data-theme="amoled"] header::after,
[data-theme="soft"] header::after,
[data-theme="aurora"] header::after,
[data-theme="glass"] header::after,
[data-theme="light"] header::after,
[data-theme="valence"] header::after {
  content: '';
  position: absolute;
  /* Sit over the .t-border-b border row (bottom: -1px) so the accent is the
     last color downward — at bottom: 0 the 1px border showed beneath it. */
  bottom: -1px; left: 0; right: 0; height: 1px;
}

/* Dark: subtle blue light-leak */
[data-theme="dark"] header::after {
  background: linear-gradient(90deg, transparent 0%, rgba(138,184,216,0.67) 30%, rgba(138,184,216,0.67) 70%, transparent 100%);
}
/* Midnight: GitHub blue, more precise */
[data-theme="midnight"] header::after {
  background: linear-gradient(90deg, transparent 0%, rgba(47,129,247,0.67) 30%, rgba(47,129,247,0.67) 70%, transparent 100%);
}
/* AMOLED: white hairline, neon terminal feel */
[data-theme="amoled"] header::after {
  background: linear-gradient(90deg, transparent 0%, rgba(226,226,226,0.59) 30%, rgba(226,226,226,0.59) 70%, transparent 100%);
}
/* Soft: indigo glow matching pill UI accent */
[data-theme="soft"] header::after {
  background: linear-gradient(90deg, transparent 0%, rgba(99,102,241,0.92) 30%, rgba(99,102,241,0.92) 70%, transparent 100%);
}
/* Aurora: violet northern-lights shimmer */
[data-theme="aurora"] header::after {
  background: linear-gradient(90deg, transparent 0%, rgba(167,139,250,0.71) 25%, rgba(196,181,253,0.71) 50%, rgba(167,139,250,0.71) 75%, transparent 100%);
}
/* Glass: prismatic white refraction edge */
[data-theme="glass"] header::after {
  background: linear-gradient(90deg, transparent 0%, rgba(255,255,255,0.77) 30%, rgba(255,255,255,0.77) 70%, transparent 100%);
}
/* Light: blue fintech accent hairline */
[data-theme="light"] header::after {
  background: linear-gradient(90deg, transparent 0%, rgba(37,99,235,0.56) 30%, rgba(37,99,235,0.56) 70%, transparent 100%);
}
/* Valence: steel-blue brand line */
[data-theme="valence"] header::after {
  background: linear-gradient(90deg, transparent 0%, rgba(58,90,144,0.92) 30%, rgba(58,90,144,0.92) 70%, transparent 100%);
}

/* --- Summary card accent top stripe --- (gradient borders defined per-theme below) */

/* --- Tab shape uses radius token --- */
.tab {
  border-radius: var(--radius-sm, 8px) !important;
  font-size: 0.8rem;
  letter-spacing: 0.01em;
}
.tab:active        { transform: scale(0.97); }
.period-btn:active { transform: scale(0.93); }

/* --- Tabular numbers + smooth row highlight transitions --- */
#table-body td {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum";
  transition: background 0.1s ease;
  line-height: 1.25;
}

/* --- Table header refinement --- */
thead tr th {
  font-size: 0.65rem;
  letter-spacing: 0.07em;
}

/* --- Markets info panel --- */
#markets-info-panel {
  border-top: 1px solid var(--border);
  padding: 10px 2px 6px;
  margin-bottom: 10px;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 5px 24px;
  font-size: 0.7rem;
  color: var(--text-sub);
  line-height: 1.5;
}
#markets-info-panel .info-row-name { font-weight: 700; color: var(--text-primary); }
#markets-info-btn.active { background: var(--bg-hover); opacity: 1; }

/* --- Info tooltip --- */
.info-anchor {
  position: relative;
  display: inline-flex;
  align-items: center;
  cursor: help;
}
.info-anchor .info-bubble,
.stat-tip .info-bubble {
  display: block;
  position: absolute;
  bottom: calc(100% + 6px);
  left: 50%;
  transform: translateX(-50%) translateY(5px);
  opacity: 0;
  transition: opacity 0.15s ease, transform 0.15s ease;
  width: 220px;
  padding: 8px 10px;
  border-radius: var(--radius-sm, 8px);
  background: var(--bg-card);
  border: 1px solid var(--border);
  color: var(--text-sub);
  font-size: 0.7rem;
  line-height: 1.45;
  font-family: sans-serif;
  font-weight: 400;
  letter-spacing: 0;
  box-shadow: 0 4px 16px rgba(0,0,0,0.35);
  z-index: var(--z-tooltip);
  pointer-events: none;
  white-space: normal;
}
.info-anchor:hover .info-bubble,
.info-anchor:focus .info-bubble {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

/* Stat-card tooltip rows — block display preserves vertical stacking. The
   wrapper is the tooltip's positioning context, so it must never clip its
   own absolutely-positioned `.info-bubble` child — `overflow: visible`
   here is part of the contract, not a styling choice. When stat-tip is
   composed with a clipping class (e.g. `.card-label`), that file's
   higher-specificity override re-asserts visible overflow locally. */
.stat-tip {
  position: relative;
  cursor: help;
  overflow: visible;
}
.stat-tip:hover .info-bubble,
.stat-tip:focus .info-bubble {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}
.stat-tip:focus { outline: none; }
.stat-tip:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--radius-tiny, 2px);
}

/* --- Form inputs: border-color focus ring uses accent --- */
input:focus, select:focus {
  border-color: var(--accent) !important;
  outline: none;
}

/* --- Site footer --- */
.site-footer {
  padding: 1.25rem 1.5rem;
  text-align: center;
  font-size: 0.8125rem;
  color: var(--text-muted);
  margin-top: 1rem;
}
.site-footer a {
  color: var(--text-muted);
  text-decoration: none;
  transition: color 0.1s;
}
.site-footer a:hover { color: var(--text-primary); }
.site-footer-sep { margin: 0 0.625rem; opacity: 0.4; }
/* Footer trigger styled as a link (e.g. "Help us improve" opens the feedback modal). */
.footer-link-btn {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  color: var(--text-muted);
  text-decoration: none;
  cursor: pointer;
  transition: color 0.1s;
}
.footer-link-btn:hover { color: var(--text-primary); }

/* Feedback ("Help us improve") modal — wider than the purged Tailwind max-w-lg allows. */
.feedback-modal-card { max-width: 42rem; }

/* ---------- Export menu ---------- */
.export-menu-item {
  display: block; width: 100%; text-align: left;
  padding: 6px 14px; font-size: 0.8rem; background: none; border: none;
  cursor: pointer; color: inherit;
}
.export-menu-item:hover { background: rgba(255,255,255,0.07); }
.export-menu-divider { border-color: var(--border); margin: 4px 0; }

