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

/* ── Inter (self-hosted, variable font — no CDN/runtime dependency) ─── */
@font-face {
  font-family: 'Inter Variable';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  src: url('/fonts/inter-latin-wght-normal.woff2') format('woff2-variations'),
       url('/fonts/inter-latin-wght-normal.woff2') format('woff2');
}
@font-face {
  font-family: 'Inter Variable';
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
  unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
  src: url('/fonts/inter-latin-ext-wght-normal.woff2') format('woff2-variations'),
       url('/fonts/inter-latin-ext-wght-normal.woff2') format('woff2');
}

/* ── Design tokens ───────────────────────────────────────────────────
   TradeZella-style light theme: a violet/indigo brand accent on a soft
   lavender-tinted neutral scale, generous rounding, card elevation. Same
   token names as before so no selector elsewhere needs to change — only
   the values shift (visual only, same vanilla-JS/zero-build architecture
   underneath). */
:root {
  --background:        hsl(0 0% 100%);
  --foreground:         hsl(240 10% 12%);
  --card:                hsl(0 0% 100%);
  --card-foreground:     hsl(240 10% 12%);
  --popover:             hsl(0 0% 100%);
  --popover-foreground:  hsl(240 10% 12%);
  --primary:             hsl(262 83% 58%);
  --primary-foreground:  hsl(0 0% 100%);
  --secondary:           hsl(262 60% 97%);
  --secondary-foreground: hsl(262 47% 32%);
  --muted:               hsl(260 30% 96.5%);
  --muted-foreground:    hsl(250 10% 46%);
  --accent:              hsl(262 70% 95.5%);
  --accent-foreground:   hsl(262 83% 33%);
  --destructive:         hsl(0 84.2% 60.2%);
  --destructive-foreground: hsl(210 40% 98%);
  --border:              hsl(250 20% 91%);
  --input:               hsl(250 20% 91%);
  --ring:                hsl(262 83% 66%);
  --radius:              0.75rem;

  /* Page sits one step below --card — soft lavender-gray, not flat white,
     so white cards read as elevated surfaces (TradeZella's dashboard
     canvas is a tinted off-white, not pure white). */
  --page-bg: hsl(250 45% 98.2%);

  /* Shared soft elevation for card-like surfaces (table, tiles, charts). */
  --card-shadow: 0 1px 2px rgb(0 0 0 / 0.03), 0 1px 3px rgb(0 0 0 / 0.05);

  --mono: ui-monospace, 'JetBrains Mono', Consolas, 'Courier New', monospace;

  /* Outcome/direction semantics — not part of the neutral scale, kept as
     their own tokens. Reduced to green/red/amber as the only "colored"
     outcome signals (win/loss/needs-attention); MANUAL_CLOSE and
     PARTIAL_CLOSE aren't pass/fail signals so they read as neutral gray,
     same as CANCELLED — text (the badge label) disambiguates them, not
     color. Kept out of row backgrounds entirely (badge column only). */
  --long:    #16a34a;
  --short:   #dc2626;
  --c-tp:    #16a34a;
  --c-sl:    #dc2626;
  --c-mc:    #64748b;
  --c-pc:    #64748b;
  --c-canc:  #64748b;
  --c-unk:   #b45309;
  --c-open:  #2563eb;
}

body {
  font-family: 'Inter Variable', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
  font-feature-settings: 'cv11', 'ss01';
  background: var(--page-bg);
  color: var(--foreground);
  font-size: 13px;
  min-height: 100vh;
}

/* Native checkboxes → cheap, zero-JS shadcn-ish recolor (all evergreen
   browsers support accent-color; no custom-built checkbox needed). */
input[type="checkbox"] { accent-color: var(--primary); width: 14px; height: 14px; }

/* shadcn's signature interactive detail: a visible focus-visible ring
   (not a heavy default outline) on every focusable control. */
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
  outline: none;
  box-shadow: 0 0 0 2px var(--background), 0 0 0 4px var(--ring);
}

/* ── Top bar ─────────────────────────────────────────────────────── */
.topbar {
  /* Set via Settings > Appearance (--journal-accent-color custom property
     on :root) so dev/prod (or any two environments sharing this UI on
     separate DBs) can be told apart at a glance. Unset = default --card. */
  background: var(--journal-accent-color, var(--card));
  color: var(--foreground);
  border-bottom: 1px solid var(--border);
  box-shadow: 0 1px 2px rgb(0 0 0 / 0.03);
  padding: 0 24px;
  height: 56px;
  display: flex;
  align-items: center;
  gap: 14px;
  position: sticky;
  top: 0;
  z-index: 20;
}
.topbar-logo { font-size: 15px; font-weight: 700; letter-spacing: -.2px; white-space: nowrap; color: var(--primary); }
.topbar-sep  { width: 1px; height: 20px; background: var(--border); flex-shrink: 0; }
.topbar-account {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  color: var(--muted-foreground);
  white-space: nowrap;
}
.topbar-account select {
  background: var(--background);
  color: var(--foreground);
  border: 1px solid var(--border);
  border-radius: calc(var(--radius) - 3px);
  padding: 5px 8px;
  font-size: 12px;
  font-family: inherit;
}
/* ── Buttons (shadcn Button variants) ───────────────────────────────
   .topbar-btn = default (primary, brand-colored) / dialog submit buttons
   reuse it too; .btn-danger = destructive. */
.topbar-btn  {
  padding: 5px 12px;
  background: var(--primary);
  color: var(--primary-foreground);
  border: 1px solid var(--primary);
  border-radius: calc(var(--radius) - 2px);
  cursor: pointer;
  font-family: inherit;
  font-size: 11px;
  font-weight: 500;
  white-space: nowrap;
  flex-shrink: 0;
  transition: opacity .12s;
}
.topbar-btn:hover { opacity: .85; }
.topbar-info {
  margin-left: auto;
  font-size: 11px;
  color: var(--muted-foreground);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Groups the save-filters pin and the settings cog into one visual unit,
   right at the topbar's edge -- tighter gap than the 14px .topbar uses
   between its other children. */
.topbar-icon-group {
  display: flex;
  align-items: center;
  gap: 2px;
  margin-left: auto;
  position: relative;
}
/* Absolutely positioned (not a normal flex sibling) so its empty state
   takes up zero space -- otherwise it'd force the pin/cog apart by the
   .topbar gap on each side even with no text in it. */
.topbar-info-float {
  position: absolute;
  top: 100%;
  right: 0;
  margin-top: 6px;
  font-size: 11px;
  color: var(--muted-foreground);
  white-space: nowrap;
  background: var(--popover);
  border: 1px solid var(--border);
  border-radius: calc(var(--radius) - 3px);
  padding: 3px 8px;
  box-shadow: 0 4px 6px -4px rgb(0 0 0 / 0.1);
  pointer-events: none;
}
.topbar-info-float:empty { display: none; }

.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: calc(var(--radius) - 3px);
  background: transparent;
  color: var(--muted-foreground);
  cursor: pointer;
  transition: background .1s, color .1s;
}
.icon-btn:hover, .icon-btn[aria-expanded="true"] { background: var(--accent); color: var(--accent-foreground); }
.icon-btn:disabled { opacity: .35; cursor: not-allowed; }
.icon-btn:disabled:hover { background: transparent; color: var(--muted-foreground); }
/* #save-filters-btn: filled in once the current topbar filters match the
   saved defaults, so it's obvious at a glance whether the view is "pinned". */
.icon-btn.active { background: var(--accent); color: var(--primary); }
.icon-btn.active svg { fill: currentColor; }
.icon-btn svg { width: 16px; height: 16px; }

.dropdown-menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 30;
  min-width: 160px;
  background: var(--popover);
  border: 1px solid var(--border);
  border-radius: calc(var(--radius) - 2px);
  box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
  padding: 4px;
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.dropdown-item {
  display: block;
  width: 100%;
  text-align: left;
  padding: 6px 10px;
  border: none;
  border-radius: calc(var(--radius) - 4px);
  background: transparent;
  color: var(--foreground);
  cursor: pointer;
  font-family: inherit;
  font-size: 12px;
  font-weight: 500;
}
.dropdown-item:hover { background: var(--accent); }
.dropdown-item.is-highlighted { background: var(--accent); }
.dropdown-item-danger { color: var(--destructive); }
.dropdown-item-danger:hover { background: hsl(0 84.2% 60.2% / .1); }

/* ── Icon-enhanced <select> (native <option> can't render <img>, so the
   visual layer is a custom trigger+popup; see enhanceSelectWithIcons in
   app.js — the native <select> itself stays functional, just hidden). ── */
.select-native-hidden { display: none; }
.select-wrap { position: relative; display: inline-flex; }
.select-trigger {
  display: flex;
  align-items: center;
  gap: 6px;
  background: var(--background);
  color: var(--foreground);
  border: 1px solid var(--border);
  border-radius: calc(var(--radius) - 3px);
  padding: 5px 8px;
  font-size: 12px;
  font-family: inherit;
  cursor: pointer;
  max-width: 220px;
}
.select-trigger:hover { border-color: var(--ring); }
.select-trigger:disabled { opacity: .6; cursor: not-allowed; }
.select-trigger-icon { display: inline-flex; width: 14px; height: 14px; flex-shrink: 0; }
.select-trigger-icon .broker-favicon,
.select-option-icon .broker-favicon { margin-right: 0; }
.select-trigger-label {
  flex: 1;
  min-width: 0;
  text-align: left;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.select-trigger-caret { width: 12px; height: 12px; flex-shrink: 0; color: var(--muted-foreground); }
.select-popup {
  left: 0;
  right: auto;
  min-width: 100%;
  max-height: 320px;
  overflow-y: auto;
}
.select-option {
  display: flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
}
.select-option-icon { display: inline-flex; width: 14px; height: 14px; flex-shrink: 0; }
.select-option-label { overflow: hidden; text-overflow: ellipsis; }
.select-option.is-selected { background: var(--secondary); }
.select-option.is-highlighted { background: var(--accent); }
.select-option:disabled { color: var(--muted-foreground); cursor: not-allowed; }
.select-option:disabled:hover { background: transparent; }

/* ── Topbar date-range filter (ToggleGroup-style, not full pills) ──── */
.topbar-daterange { display: flex; align-items: center; gap: 2px; background: var(--muted); padding: 2px; border-radius: var(--radius); }
.range-btn {
  padding: 4px 10px;
  background: transparent;
  color: var(--muted-foreground);
  border: none;
  border-radius: calc(var(--radius) - 4px);
  cursor: pointer;
  font-family: inherit;
  font-size: 11px;
  white-space: nowrap;
  transition: background .1s, color .1s;
}
.range-btn:hover  { color: var(--foreground); }
.range-btn.active { background: var(--card); color: var(--primary); font-weight: 600; box-shadow: 0 1px 2px rgb(0 0 0 / 0.06); }
.topbar-daterange-custom { display: flex; align-items: center; gap: 4px; color: var(--muted-foreground); font-size: 11px; margin-left: 4px; }
.topbar-daterange-custom input[type="date"] {
  background: var(--background);
  color: var(--foreground);
  border: 1px solid var(--border);
  border-radius: calc(var(--radius) - 4px);
  padding: 3px 6px;
  font-size: 11px;
  font-family: inherit;
  color-scheme: light;
}

/* ── Tab nav (shadcn TabsList: segmented control) ───────────────────── */
.tab-nav {
  display: inline-flex;
  gap: 2px;
  margin: 16px 24px 0;
  padding: 3px;
  background: var(--muted);
  border-radius: var(--radius);
  width: fit-content;
}
.tab-btn {
  padding: 5px 14px;
  border: none;
  border-radius: calc(var(--radius) - 3px);
  background: transparent;
  color: var(--muted-foreground);
  cursor: pointer;
  font-family: inherit;
  font-size: 12px;
  font-weight: 500;
  transition: background .12s, color .12s, box-shadow .12s;
}
.tab-btn:hover    { color: var(--foreground); }
.tab-btn.active   { background: var(--card); color: var(--foreground); box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.08), 0 1px 2px -1px rgb(0 0 0 / 0.08); }

/* ── Content ─────────────────────────────────────────────────────── */
#mainSection { padding: 20px 24px; }

/* ── Stats strip (Badge-as-filter chips) ────────────────────────────── */
.stats-strip { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; }
.stat-chip {
  padding: 3px 11px;
  border-radius: 9999px;
  font-size: 11px;
  font-weight: 600;
  font-family: inherit;
  border: 1px solid;
  white-space: nowrap;
  cursor: pointer;
  transition: opacity .12s, box-shadow .12s;
}
.stat-chip:hover { opacity: .85; }
.stat-chip.active { box-shadow: 0 0 0 2px currentColor inset; }
/* A specific outcome is selected — dim every other chip (including Total)
   so the active one reads as "this is what you're viewing", same idea as
   the old fOutcome filter buttons this replaced. */
#statsStrip.has-active-filter .stat-chip:not(.active) { opacity: .45; }
/* Only the two outcomes that matter most at a glance (TP/SL) get a
   colored fill — everything else (including Total) is flat/neutral text
   so the strip doesn't read as noise before you even reach the table. */
.sc-total,
.sc-mc,
.sc-pc,
.sc-canc  { background: var(--secondary); border-color: transparent; color: var(--muted-foreground); font-weight: 500; }
.sc-tp    { background: #dcfce7; border-color: #86efac; color: var(--c-tp); }
.sc-sl    { background: #fee2e2; border-color: #fca5a5; color: var(--c-sl); }
.sc-unk   { background: #fef9c3; border-color: #fde047; color: var(--c-unk); }
.sc-open  { background: #dbeafe; border-color: #93c5fd; color: var(--c-open); }

/* ── Filters (ToggleGroup / Toggle — rounded-md, not full pill) ─────── */
.filter-bar { display: flex; gap: 6px; flex-wrap: wrap; margin-bottom: 14px; align-items: center; }
.filter-sep { width: 1px; height: 22px; background: var(--border); }
.filter-sep-strong { width: 2px; height: 26px; background: var(--muted-foreground); margin: 0 2px; border-radius: 1px; opacity: .4; }
.fbtn {
  padding: 3px 11px;
  border: 1px solid var(--border);
  border-radius: calc(var(--radius) - 3px);
  background: var(--card);
  color: var(--foreground);
  cursor: pointer;
  font-family: inherit;
  font-size: 11px;
  white-space: nowrap;
  transition: all .1s;
}
.fbtn:hover { background: var(--accent); border-color: var(--ring); }
.fbtn.active { background: var(--primary); color: var(--primary-foreground); border-color: var(--primary); }

.positions-count { margin-left: auto; color: var(--muted-foreground); font-size: 12px; }

/* ── Table ───────────────────────────────────────────────────────── */
.table-wrap {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--card-shadow);
  overflow: auto;
  max-height: calc(100vh - 160px);
}
table { border-collapse: collapse; font-size: 12px; white-space: nowrap; width: 100%; }

thead th {
  background: var(--muted);
  border-bottom: 1px solid var(--border);
  padding: 10px 12px;
  text-align: left;
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--muted-foreground);
  user-select: none;
  position: sticky;
  top: 0;
  z-index: 10;
}
thead th.sortable       { cursor: pointer; }
thead th.sortable:hover { color: var(--foreground); }
thead th.asc::after     { content: ' \2191'; }
thead th.desc::after    { content: ' \2193'; }

/* Column groups get extra left whitespace instead of a hard vertical
   rule — softer separation that doesn't turn the table into a grid. */
thead th.grp-start, tbody td.grp-start { padding-left: 18px; }

/* Hidden "detail" columns — shown only when table has .show-extra */
th.col-extra, td.col-extra { display: none; }
table.show-extra th.col-extra,
table.show-extra td.col-extra { display: table-cell; }

/* "Account" column — shown only in the "All accounts" combined view, an
   independent toggle from .show-extra since it's tied to account scope,
   not the unrelated "Show details" preference. */
th.col-account, td.col-account { display: none; }
table.show-account th.col-account,
table.show-account td.col-account { display: table-cell; }

/* No outcome tinting at row level, deliberately — that turns the whole
   table into a heatmap and outcome ends up dominating every other data
   point. The outcome badge (its own column) is the only color signal.
   Hairline row separators only — no vertical column borders. */
tbody tr { border-bottom: 1px solid var(--border); cursor: pointer; transition: background-color .08s; }
tbody tr:last-child  { border-bottom: none; }
tbody tr:hover       { background-color: var(--accent); }
tbody tr.row-highlight { box-shadow: 0 0 0 2px var(--ring) inset; }

td { padding: 10px 12px; vertical-align: middle; }

/* ── Cell types ──────────────────────────────────────────────────── */
.c-date { font-weight: 500; }
.c-time { color: var(--muted-foreground); }
.c-sym  { font-weight: 600; }
.c-dim  { font-size: 10px; color: var(--muted-foreground); }

/* Direction: small arrow + colored text, no fill — this is a data value,
   not a clickable control, so it shouldn't carry button-level visual
   weight (unlike Outcome, which stays a real badge below). */
.dir-cell { display: inline-flex; align-items: center; gap: 3px; font-size: 11px; font-weight: 600; }
.dir-long { color: var(--long); }
.dir-short { color: var(--short); }
.dir-unknown { color: var(--muted-foreground); font-weight: 500; }

/* Outcome badges (shadcn Badge: rounded-full, small, semibold) — the
   only place green/red/amber are used as fills. MANUAL_CLOSE/
   PARTIAL_CLOSE/CANCELLED aren't pass/fail signals, so they're neutral
   gray like everything else non-semantic; the label text (not color)
   tells them apart. */
.badge  {
  display: inline-flex; align-items: center; padding: 2px 8px; border-radius: 9999px;
  font-size: 10px; font-weight: 600; white-space: nowrap;
}
.b-tp    { background: #dcfce7; color: var(--c-tp); }
.b-sl    { background: #fee2e2; color: var(--c-sl); }
.b-mc, .b-pc, .b-canc { background: var(--secondary); color: var(--c-canc); }
.b-unk   { background: #fef9c3; color: var(--c-unk); }
.b-open  { background: #dbeafe; color: var(--c-open); }

/* Numeric / monospace cells */
td.num  { font-family: var(--mono); font-size: 11px; text-align: right; font-variant-numeric: tabular-nums; }
td.tmcl { font-family: var(--mono); font-size: 11px; color: var(--muted-foreground); font-variant-numeric: tabular-nums; }
/* Placed-but-not-filled value (e.g. an SL/TP that was never hit) — dimmed
   and italic so it visually reads as "the plan", not "what happened". */
td.num-planned { color: var(--muted-foreground); font-style: italic; cursor: help; }

/* Entry type label */
.etype  { font-size: 10px; color: var(--muted-foreground); }

.note-icon { cursor: help; display: inline-flex; color: var(--c-unk); vertical-align: middle; }
.note-icon svg { width: 13px; height: 13px; }

/* ── Empty state ─────────────────────────────────────────────────── */
.tbl-empty { padding: 36px; text-align: center; color: var(--muted-foreground); }
.hidden { display: none !important; }

/* ── Dialogs (shadcn Dialog: border + shadow-lg, rounded-lg) ────────── */
dialog {
  background: var(--popover);
  color: var(--popover-foreground);
  border: 1px solid var(--border);
  border-radius: calc(var(--radius) + 2px);
  padding: 20px;
  box-shadow: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
}

dialog::backdrop {
  background: rgba(15, 23, 42, .5);
}

dialog form {
  display: flex;
  flex-direction: column;
  gap: 10px;
  min-width: 280px;
}

dialog h2 {
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -.2px;
}

dialog label {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 12px;
  color: var(--muted-foreground);
}

dialog input:not([type="checkbox"]),
dialog select {
  border: 1px solid var(--input);
  border-radius: calc(var(--radius) - 2px);
  padding: 6px 9px;
  font-size: 13px;
  font-family: inherit;
  background: var(--background);
  color: var(--foreground);
  transition: border-color .1s;
}
dialog input:not([type="checkbox"]):hover,
dialog select:hover { border-color: var(--ring); }
dialog select:disabled { opacity: .6; cursor: not-allowed; }

dialog menu {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin: 4px 0 0;
  padding: 0;
}

dialog button {
  padding: 5px 14px;
  border: 1px solid var(--border);
  border-radius: calc(var(--radius) - 2px);
  background: var(--background);
  color: var(--foreground);
  cursor: pointer;
  font-family: inherit;
  font-size: 12px;
  font-weight: 500;
  transition: background .1s, opacity .1s;
}
dialog button:hover { background: var(--accent); }
dialog button[type="submit"] { background: var(--primary); color: var(--primary-foreground); border-color: var(--primary); }
dialog button[type="submit"]:hover { opacity: .85; background: var(--primary); }
dialog button.btn-danger { background: var(--destructive); border-color: var(--destructive); color: var(--destructive-foreground); }
dialog button.btn-danger:hover { opacity: .85; background: var(--destructive); }
dialog button.btn-danger:disabled { background: var(--muted-foreground); border-color: var(--muted-foreground); cursor: not-allowed; opacity: .5; }
#delete-account-message { font-size: 12px; color: var(--muted-foreground); margin: 0; }
#delete-account-count { color: var(--foreground); font-weight: 600; }
#import-dialog-status { font-size: 12px; color: var(--muted-foreground); margin: 0; }
#new-account-status { font-size: 12px; color: var(--muted-foreground); margin: 0; }
#manage-brokers-status { font-size: 12px; color: var(--muted-foreground); margin: 0; }

/* ── Broker favicon badge — used wherever an account/broker is identified
   inline (Positions table Account column, journal modal, Manage brokers). */
.broker-favicon {
  width: 14px;
  height: 14px;
  border-radius: 3px;
  vertical-align: middle;
  margin-right: 5px;
  object-fit: contain;
}
.broker-favicon-placeholder {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--secondary);
  color: var(--secondary-foreground);
  font-size: 9px;
  font-weight: 600;
}

/* ── Settings dialog (Accounts / Brokers / Journal defaults / Appearance
   panels, tab-switched — replaces the old ⋮ menu + separate New account /
   Manage brokers dialogs) ───────────────────────────────────────────── */
#settings-dialog { width: min(780px, 62vw); height: calc(97vh * .75); padding: 0; overflow: auto; } /* ~65% of #journal-dialog's width, 75% of its height -- narrower and shorter, since a form-heavy panel doesn't need journal's full 1200x97vh footprint */
.settings-modal { display: flex; flex-direction: column; padding: 18px; gap: 14px; min-width: 0; min-height: 100%; }
.settings-modal-header { display: flex; align-items: center; padding-right: 30px; }
.settings-modal-header h2 { margin: 0; }

.settings-tabs {
  display: flex;
  gap: 4px;
  border-bottom: 1px solid var(--border);
  padding-bottom: 10px;
  flex-wrap: wrap;
}
.settings-tab {
  padding: 5px 10px;
  border: none;
  border-radius: calc(var(--radius) - 2px);
  background: transparent;
  color: var(--muted-foreground);
  font-size: 12px;
  font-weight: 500;
  cursor: pointer;
}
.settings-tab:hover { background: var(--accent); color: var(--foreground); }
.settings-tab.active { background: var(--secondary); color: var(--secondary-foreground); }

.settings-panel { display: flex; flex-direction: column; gap: 10px; }
.settings-panel h3 { font-size: 13px; font-weight: 600; margin: 0; }
.settings-panel hr { border: none; border-top: 1px solid var(--border); margin: 4px 0; width: 100%; }

/* ── Manage brokers panel (lives inside the Brokers settings tab) ───── */
#brokers-list, #accounts-list { display: flex; flex-direction: column; gap: 6px; }
/* Form-like sections stay a sane input width even inside the wide
   dialog -- only the lists above are meant to use the full width. */
.settings-narrow-field, #new-account-form, .broker-add-row { max-width: 480px; }
.settings-panel[data-settings-panel="journal"],
.settings-panel[data-settings-panel="appearance"] { max-width: 480px; }
.broker-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 8px;
  border: 1px solid var(--border);
  border-radius: calc(var(--radius) - 3px);
}
.broker-row .broker-favicon,
.broker-row .broker-favicon-placeholder { width: 20px; height: 20px; margin-right: 0; flex-shrink: 0; }
.broker-row-main { flex: 1; min-width: 0; }
.broker-edit-fields { display: flex; gap: 6px; }
.broker-edit-fields input, .broker-edit-fields select { flex: 1; min-width: 0; }
.broker-row-name { font-size: 12px; font-weight: 500; }
.broker-row-url {
  display: block;
  font-size: 10px;
  color: var(--muted-foreground);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.broker-row-error { font-size: 10px; color: var(--c-unk); }
.broker-row-count { font-size: 10px; color: var(--muted-foreground); white-space: nowrap; }
.broker-upload-label { position: relative; overflow: hidden; }
.hidden-file-input {
  position: absolute;
  inset: 0;
  opacity: 0;
  cursor: pointer;
  width: 100%;
}
.broker-add-row { display: flex; gap: 6px; }
.broker-add-row input { flex: 1; }
.new-account-row { display: flex; gap: 6px; }
.new-account-row label { flex: 1; min-width: 0; }

/* Icon-only close (X) button, top-right — shadcn DialogClose convention */
.dialog-close-x {
  position: absolute;
  top: 12px;
  right: 12px;
  width: 26px;
  height: 26px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: calc(var(--radius) - 2px);
  background: transparent;
  color: var(--muted-foreground);
  cursor: pointer;
  transition: background .1s, color .1s;
}
.dialog-close-x:hover { background: var(--accent); color: var(--foreground); }
/* flex-shrink:0 — being an inline-flex child of an absolutely positioned
   button, this svg otherwise gets flex-shrunk to 0 width once the dialog
   is actually rendered (not visible at all until fixed). */
.dialog-close-x svg { width: 15px; height: 15px; flex-shrink: 0; }
dialog { position: relative; }

/* ── Journal ─────────────────────────────────────────────────────── */
.c-journal { display: flex; align-items: center; gap: 6px; }

.journal-btn {
  border: none;
  background: none;
  cursor: pointer;
  display: inline-flex;
  padding: 3px;
  border-radius: calc(var(--radius) - 3px);
  color: var(--muted-foreground);
  opacity: .4;
  transition: background .1s, opacity .1s, color .1s;
}
.journal-btn svg { width: 14px; height: 14px; }
.journal-btn:hover { opacity: 1; background: var(--accent); }
.journal-btn.has-journal { opacity: 1; color: var(--primary); }

.tag-badges { display: inline-flex; gap: 4px; flex-wrap: wrap; }
.tag-badge {
  display: inline-block;
  padding: 1px 7px;
  border-radius: 9999px;
  font-size: 10px;
  font-weight: 600;
  background: var(--secondary);
  color: var(--secondary-foreground);
  white-space: nowrap;
}

/* ── Tags chip input (journal modal) — decorates a hidden <input>, same
   philosophy as the .select-wrap combobox above; see createTagsInput in
   app.js. ── */
.tags-input {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 4px;
  border: 1px solid var(--input);
  border-radius: calc(var(--radius) - 2px);
  padding: 4px 6px;
  background: var(--background);
}
.tags-input:focus-within { border-color: var(--ring); }
/* The add-tag control (input + its suggestion dropdown) stays a fixed,
   reasonable width instead of stretching to fill the row -- the chips
   themselves are what's meant to spread across the available width. */
.tags-add-control {
  position: relative;
  width: 200px;
  flex: 0 0 auto;
}
.tags-input-tail {
  width: 100%;
  border: none;
  outline: none;
  background: transparent;
  font: inherit;
  font-size: 13px;
  color: var(--foreground);
  padding: 2px 0;
}
/* Selected tags in the journal modal's tags-input read at the same size as
   the setup-grade chips next to them, rather than the small 10px pill used
   for read-only tag lists elsewhere (positions table, calendar). */
.tags-input .tag-badge {
  padding: 4px 14px;
  font-size: 12px;
  font-weight: 700;
}
.tag-badge-removable { display: inline-flex; align-items: center; gap: 4px; }
.tag-badge-remove {
  border: none;
  background: transparent;
  color: inherit;
  font-size: 13px;
  line-height: 1;
  padding: 0;
  cursor: pointer;
  opacity: .6;
}
.tag-badge-remove:hover { opacity: 1; }
.tags-input-dropdown {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  right: auto;
  width: 100%;
  max-height: 200px;
  overflow-y: auto;
  z-index: 30;
}

/* ── Setup grade chip picker (journal modal) — AA best down to C so-so.
   Reuses the same green/blue/amber/gray tokens already used for outcome
   badges (TP/OPEN/UNKNOWN/CANCELLED) rather than inventing a new palette;
   .is-selected reuses the inset-ring "active chip" idiom from .stat-chip. ── */
.grade-picker { display: flex; gap: 6px; flex-wrap: wrap; }
.grade-chip {
  padding: 4px 14px;
  border-radius: 9999px;
  font-size: 12px;
  font-weight: 700;
  font-family: inherit;
  border: none;
  cursor: pointer;
  transition: opacity .12s, box-shadow .12s;
}
.grade-chip:hover { opacity: .8; }
.grade-chip[data-grade="AA"] { background: #dcfce7; color: var(--c-tp); }
.grade-chip[data-grade="A"]  { background: #dbeafe; color: var(--c-open); }
.grade-chip[data-grade="B"]  { background: #fef9c3; color: var(--c-unk); }
.grade-chip[data-grade="C"]  { background: #fee2e2; color: var(--c-sl); }
.grade-chip.is-selected { box-shadow: 0 0 0 2px currentColor inset; }
/* B's own text color (var(--c-unk), amber-700) reads as reddish/brown at
   ring width -- override just the selected-state ring with a brighter
   amber so it doesn't get mistaken for the red C-grade/missing-field ring. */
.grade-chip[data-grade="B"].is-selected { box-shadow: 0 0 0 2px #f59e0b inset; }

/* Followed plan Yes/No picker reuses the same .grade-picker/.grade-chip
   widget (createGradePicker in app.js) with its own data-grade values --
   same green/red tokens as the AA/C setup grades above. */
.grade-chip[data-grade="yes"] { background: #dcfce7; color: var(--c-tp); }
.grade-chip[data-grade="no"]  { background: #fee2e2; color: var(--c-sl); }

#journal-dialog {
  width: min(1200px, 95vw);
  height: 97vh; /* fixed, not max -- so it never resizes as content changes (#settings-dialog is a fixed height off this same value too, see below) */
  overflow: auto;
  padding: 0;
}

.journal-modal {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 18px;
  min-width: 0;
}

.journal-modal-header {
  display: flex;
  align-items: center;
  gap: 10px;
  padding-right: 38px;
}
.journal-modal-header h2 {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  font-size: 23px;
  margin: 0;
}

.journal-modal-status {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 18px;
  font-weight: 400;
  color: var(--muted-foreground);
}
.journal-modal-status .etype { font-size: 18px; }
/* Direction (Long/Short + arrow) and outcome (TP/SL/...) badges are shared,
   app-wide components (positions table, calendar) sized for small inline
   use elsewhere -- scoped up here to match the modal title's 23px instead
   of bumping their shared base size everywhere else. */
.journal-modal-status .dir-cell {
  font-size: 23px;
  gap: 5px;
}
.journal-modal-status .badge {
  font-size: 23px;
  padding: 4px 14px;
}

/* Bigger than the default .icon-btn glyph size -- these sit right next to
   the now-larger modal title, and the default size read as too small
   next to it. */
#journal-prev-btn, #journal-next-btn {
  font-size: 26px;
}

/* Scoped to the journal modal specifically -- other dialogs (Settings,
   Import, etc.) keep the shared .dialog-close-x default size. */
#journal-dialog .dialog-close-x {
  width: 30px;
  height: 30px;
}
#journal-dialog .dialog-close-x svg {
  width: 19px;
  height: 19px;
}

.journal-save-status {
  font-size: 11px;
  color: var(--muted-foreground);
  white-space: nowrap;
}

.journal-body {
  display: flex;
  gap: 16px;
  align-items: flex-start;
  min-width: 0;
}

#journal-editor { flex: 1; min-width: 0; min-height: 600px; border: 1px solid var(--border); border-radius: calc(var(--radius) - 2px); overflow: hidden; }

.journal-props {
  width: 235px;
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: 14px;
}

/* Shared boxed-card look for the three groups in the properties column
   (setup / outcome / metadata) — Entry/SL/TP live in the top one, emphasized
   as the values a trader retypes into TradingView's position tool. */
.journal-block {
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 10px;
  border: 1px solid var(--border);
  border-radius: calc(var(--radius) - 2px);
  background: var(--muted);
}

.journal-ts-item { display: flex; flex-direction: column; gap: 3px; }
.journal-ts-label { font-size: 11px; color: var(--muted-foreground); }

.journal-ts-value {
  all: unset;
  box-sizing: border-box;
  position: relative;
  display: flex;
  align-items: baseline;
  gap: 6px;
  width: 100%;
  white-space: nowrap;
  padding: 3px 5px;
  border-radius: calc(var(--radius) - 4px);
  font-family: var(--mono);
  font-size: 16px;
  font-weight: 600;
  color: var(--foreground);
  cursor: pointer;
}
.journal-ts-value:hover:not(:disabled) { background: var(--accent); color: var(--accent-foreground); }
.journal-ts-value:focus-visible { outline: 2px solid var(--ring); outline-offset: 1px; }
.journal-ts-value:disabled { color: var(--muted-foreground); font-weight: 400; font-size: 13px; cursor: default; }

.journal-ts-copied {
  position: absolute;
  right: 0;
  bottom: 100%;
  margin-bottom: 3px;
  font-size: 10px;
  font-weight: 500;
  color: var(--primary-foreground);
  background: var(--primary);
  padding: 1px 6px;
  border-radius: 3px;
  white-space: nowrap;
  opacity: 0;
  transition: opacity 0.15s;
  pointer-events: none;
}
.journal-ts-value.copied .journal-ts-copied { opacity: 1; }

.journal-prop {
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-size: 12px;
}
.journal-prop dt { color: var(--muted-foreground); }
.journal-prop dd {
  margin: 0;
  color: var(--foreground);
  font-size: 13px;
  overflow-wrap: anywhere;
}

.journal-sidebar {
  width: 180px;
  flex: 0 0 auto;
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.journal-field-label {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 4px;
  font-size: 12px;
  color: var(--muted-foreground);
}
.journal-field-label input,
.journal-field-label select {
  width: 100%;
  border: 1px solid var(--input);
  border-radius: calc(var(--radius) - 2px);
  padding: 6px 8px;
  font-size: 13px;
  font-family: inherit;
  background: var(--background);
  color: var(--foreground);
}

/* Mandatory journal fields (Note, Timeframe, Strategy, Setup grade,
   TradingView link) — the red outline disappears once a field is filled, so
   it only ever draws the eye while something's actually missing (see
   updateMandatoryMark in app.js, which toggles .field-missing on the
   field's own <label>). */
.journal-field-label.field-missing input,
.journal-textarea-label.field-missing textarea {
  border-color: var(--c-sl);
}
.journal-field-label.field-missing .grade-picker {
  outline: 1px solid var(--c-sl);
  outline-offset: 3px;
  border-radius: 9999px;
}

.journal-field-checkbox {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--muted-foreground);
}
.journal-field-checkbox input { width: auto; }

.journal-extra-fields {
  display: flex;
  gap: 16px;
}

.journal-tags-row {
  flex-direction: row;
  align-items: flex-start;
  gap: 8px;
  width: 100%;
}
.journal-tags-row > .journal-tags-label {
  padding-top: 6px;
}
.journal-tags-row .tags-input {
  flex: 1;
  min-width: 0;
}

.journal-textarea-label {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 12px;
  color: var(--muted-foreground);
}
.journal-textarea-label textarea {
  width: 100%;
  resize: vertical;
  border: 1px solid var(--input);
  border-radius: calc(var(--radius) - 2px);
  padding: 6px 8px;
  font-size: 13px;
  font-family: inherit;
  line-height: 1.4;
  background: var(--background);
  color: var(--foreground);
}

/* Shrink the Toast UI toolbar (default ~45px, chunky icon buttons) via
   zoom rather than resizing buttons directly — zoom scales the sprite-
   sheet background-position offsets along with the box, so icons stay
   correctly aligned instead of getting clipped. */
#journal-dialog .toastui-editor-defaultUI-toolbar { zoom: .8; }

/* dialogs open via .showModal() are centered by the UA's default
   `margin: auto`, but the global `* { margin: 0 }` reset (top of file)
   clobbers that — restore it here so #journal-dialog/#new-account-dialog
   land in the middle of the viewport instead of pinned to the top. */
dialog { margin: auto; }

/* ── Image lightbox ──────────────────────────────────────────────── */
#image-lightbox {
  padding: 0;
  border: none;
  background: transparent;
  box-shadow: none;
  max-width: 96vw;
  max-height: 96vh;
}
#image-lightbox::backdrop { background: rgba(0, 0, 0, .85); }
#image-lightbox img {
  display: block;
  max-width: 96vw;
  max-height: 96vh;
  border-radius: var(--radius);
  cursor: zoom-out;
}

/* ── Calendar tab ────────────────────────────────────────────────── */
#calendarSection { padding: 20px 24px 32px; display: flex; flex-direction: column; gap: 14px; }

.calendar-header {
  display: flex;
  align-items: center;
  gap: 10px;
}
.calendar-header h2 {
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -.2px;
  min-width: 160px;
}
.calendar-month-summary {
  margin-left: auto;
  font-size: 13px;
  font-weight: 600;
  color: var(--muted-foreground);
}

.calendar-grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr) 90px;
  gap: 6px;
}
.calendar-grid-header {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--muted-foreground);
  text-align: center;
}

/* Height grows with --trade-rows (set per-month in JS to the busiest
   day's trade count, floored/capped in renderCalendarGrid) so every cell
   in the visible month can show its trades without an inner scrollbar. */
.calendar-day {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--card-shadow);
  min-height: calc(22px + var(--trade-rows, 4) * 18px);
  padding: 6px 8px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.calendar-day-head { display: flex; align-items: baseline; justify-content: space-between; gap: 6px; }
.calendar-day-num { font-size: 11px; color: var(--muted-foreground); font-variant-numeric: tabular-nums; }
.calendar-day-r { font-size: 13px; font-weight: 700; font-variant-numeric: tabular-nums; }

.calendar-day-trades { display: flex; flex-direction: column; gap: 1px; overflow: hidden; }
.calendar-trade {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 1px 3px;
  border-radius: calc(var(--radius) - 4px);
  font-size: 10.5px;
  cursor: pointer;
  transition: background .1s;
}
.calendar-trade:hover { background: rgb(0 0 0 / .06); }
.ct-dir { width: 10px; text-align: center; font-size: 11px; line-height: 1; flex-shrink: 0; }
.ct-dir.dir-long { color: var(--long); }
.ct-dir.dir-short { color: var(--short); }
.ct-sym { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.ct-time { flex-shrink: 0; color: var(--muted-foreground); font-variant-numeric: tabular-nums; }
.ct-r { flex-shrink: 0; font-variant-numeric: tabular-nums; font-weight: 600; }
.ct-r.ct-r-pos { color: var(--c-tp); }
.ct-r.ct-r-neg { color: var(--c-sl); }
.ct-flag {
  flex-shrink: 0;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--warning, #f59e0b);
}

/* Same "no journal entry yet" flag as .ct-flag on the Calendar tab, scaled
   up to match the modal header's larger (23px) title text. */
.journal-modal-empty-flag {
  width: 12px;
  height: 12px;
}

.calendar-day.day-outside { background: transparent; border-color: transparent; box-shadow: none; opacity: .35; }
.calendar-day.day-empty { color: var(--muted-foreground); }
.calendar-day.day-positive { background: #dcfce7; border-color: #86efac; }
.calendar-day.day-positive .calendar-day-r { color: var(--c-tp); }
.calendar-day.day-negative { background: #fee2e2; border-color: #fca5a5; }
.calendar-day.day-negative .calendar-day-r { color: var(--c-sl); }
.calendar-day.day-neutral .calendar-day-r { color: var(--muted-foreground); }

.calendar-week-total {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  border-radius: var(--radius);
  background: var(--muted);
  font-variant-numeric: tabular-nums;
  color: var(--muted-foreground);
}
.calendar-week-total .cwt-r { font-size: 13px; font-weight: 600; }
.calendar-week-total .cwt-count { font-size: 10.5px; font-weight: 500; color: var(--muted-foreground); }
.calendar-week-total.day-positive .cwt-r { color: var(--c-tp); }
.calendar-week-total.day-negative .cwt-r { color: var(--c-sl); }

/* ── Stats tab ───────────────────────────────────────────────────── */
#statsSection { padding: 20px 24px 32px; display: flex; flex-direction: column; gap: 20px; }

.stats-tiles { display: flex; gap: 12px; flex-wrap: wrap; }
.stat-tile {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--card-shadow);
  padding: 14px 18px;
  min-width: 120px;
  flex: 1 1 140px;
}
.stat-tile-value { font-size: 22px; font-weight: 600; font-variant-numeric: tabular-nums; letter-spacing: -.3px; }
.stat-tile-label { font-size: 11px; color: var(--muted-foreground); margin-top: 2px; display: flex; align-items: center; gap: 4px; }
.stat-tile-sub { font-size: 10px; color: var(--muted-foreground); margin-top: 4px; opacity: .75; }

/* Info-icon tooltip: hover/focus-triggered, pure CSS via data-tip attr. */
.info-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 13px;
  height: 13px;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--muted);
  color: var(--muted-foreground);
  font-size: 9px;
  font-style: italic;
  font-family: Georgia, 'Times New Roman', serif;
  line-height: 1;
  cursor: help;
  position: relative;
  text-transform: none;
  letter-spacing: normal;
}
.info-icon:hover,
.info-icon:focus-visible {
  background: var(--primary);
  color: var(--primary-foreground);
  outline: none;
}
.info-icon::after {
  content: attr(data-tip);
  position: absolute;
  top: calc(100% + 8px);
  left: 50%;
  transform: translateX(-50%);
  width: max-content;
  max-width: 260px;
  background: var(--popover);
  color: var(--popover-foreground);
  border: 1px solid var(--border);
  border-radius: calc(var(--radius) - 4px);
  box-shadow: var(--card-shadow);
  padding: 8px 10px;
  font-size: 11.5px;
  font-weight: 400;
  font-style: normal;
  /* Not `inherit` -- .info-icon itself sets the Georgia serif stack for its
     "i" glyph, and this popup is a child of .info-icon, so `inherit` would
     pull that serif font into the tooltip text too. */
  font-family: 'Inter Variable', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
  line-height: 1.45;
  text-align: left;
  white-space: normal;
  opacity: 0;
  visibility: hidden;
  transition: opacity .12s ease;
  pointer-events: none;
  z-index: 50;
}
.info-icon:hover::after,
.info-icon:focus-visible::after {
  opacity: 1;
  visibility: visible;
}
.chart-card h3 .info-icon::after { top: auto; bottom: calc(100% + 8px); }

.stats-section h2 { font-size: 13px; font-weight: 600; color: var(--foreground); margin-bottom: 10px; }

.stats-subheading {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--muted-foreground);
  margin: 16px 0 10px;
}
.stats-subheading-note { text-transform: none; font-weight: 400; letter-spacing: normal; }

.stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
  gap: 12px;
}

.chart-card {
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--card-shadow);
  padding: 14px 18px;
  min-width: 0;
}
.chart-card-wide { grid-column: span 2; }
@media (max-width: 900px) { .chart-card-wide { grid-column: span 1; } }

.chart-card h3 {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--muted-foreground);
  margin-bottom: 8px;
}

.chart-container      { height: 240px; }
.chart-container-tall { height: 280px; }

.stats-table-wrap { max-height: 280px; overflow: auto; }
.stats-table { width: 100%; border-collapse: collapse; font-size: 12px; }
.stats-table thead th {
  text-align: left;
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--muted-foreground);
  padding: 6px 8px;
  border-bottom: 1px solid var(--border);
  position: sticky;
  top: 0;
  background: var(--card);
}
.stats-table thead th.num { text-align: right; }
.stats-table td { padding: 5px 8px; border-bottom: 1px solid var(--border); }
.stats-table td.num { font-family: var(--mono); text-align: right; font-variant-numeric: tabular-nums; }
.stats-table tbody tr:last-child td { border-bottom: none; }

.stats-empty-note { color: var(--muted-foreground); font-size: 12px; padding: 12px 0; }

/* ── Stats drill-down dialogs (Journal completion / Data quality tiles) ── */
.stat-tile-clickable { cursor: pointer; transition: border-color .1s; }
.stat-tile-clickable:hover { border-color: var(--ring); }

#incomplete-journal-dialog, #data-quality-dialog { width: min(640px, 92vw); max-height: 80vh; padding: 0; overflow: auto; }
.drilldown-hint { font-size: 12px; color: var(--muted-foreground); margin: 0; }
.drilldown-table-wrap { max-height: 60vh; }
.stats-table tr.drilldown-row { cursor: pointer; }
.stats-table tr.drilldown-row:hover td { background: var(--accent); }

.recon-dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 6px; flex-shrink: 0; }
.missing-field-badge {
  display: inline-block;
  font-size: 10px;
  padding: 1px 6px;
  border-radius: 999px;
  background: var(--muted);
  color: var(--muted-foreground);
  margin: 0 3px 3px 0;
  white-space: nowrap;
}

@keyframes row-flash-highlight {
  from { background: var(--accent); }
  to { background: transparent; }
}
#positions-table tr.row-flash-highlight td { animation: row-flash-highlight 1.6s ease-out; }
