/* ============================================================================
   SJ Trade Terminal — design system
   Robinhood-inspired: black canvas, signature green for gains, orange-red for
   losses, minimal chrome, large light numerals. Single source of truth for all
   dashboard pages — no page defines its own CSS.
   ========================================================================== */

/* ---------- 1. Tokens ---------------------------------------------------- */
:root {
    /* Canvas — true black page, near-black surfaces. Tiles are defined by their
       grey edge rather than by a lighter fill, which is what gives the
       Robinhood dark theme its flat, high-contrast feel. Keep the steps between
       these values small; the borders do the structural work. */
    --bg-base:        #000000;
    --bg-panel:       #08080a;
    --bg-panel-alt:   #101013;
    --bg-elevated:    #17171b;
    --bg-input:       #0c0c0e;

    /* Lines — the primary structural device, so they read clearly against black. */
    --border:         #2a2a30;
    --border-strong:  #3a3a42;
    --border-subtle:  #1c1c21;

    /* Type */
    --text:           #ffffff;
    --text-secondary: #a3a3ab;
    --text-muted:     #6f6f78;
    --text-faint:     #4a4a52;

    /* Semantics — green up, orange-red down. */
    --up:             #00c805;
    --up-soft:        #33d43a;
    --up-dim:         rgba(0, 200, 5, 0.14);
    --up-glow:        rgba(0, 200, 5, 0.30);
    --down:           #ff5000;
    --down-soft:      #ff7233;
    --down-dim:       rgba(255, 80, 0, 0.14);
    --down-glow:      rgba(255, 80, 0, 0.30);

    /* Green doubles as the primary accent — the Robinhood signature. */
    --accent:         #00c805;
    --accent-dim:     rgba(0, 200, 5, 0.12);
    --accent-line:    rgba(0, 200, 5, 0.42);

    --warn:           #ffb020;
    --warn-dim:       rgba(255, 176, 32, 0.14);
    --neutral:        #8b8b93;
    --neutral-dim:    rgba(139, 139, 147, 0.14);

    /* Type stacks */
    --font-ui:   'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    --font-mono: 'JetBrains Mono', ui-monospace, 'SF Mono', 'Menlo', 'Consolas', monospace;

    /* Rhythm — roomier than a trading terminal. */
    --r-sm: 4px;
    --r-md: 8px;
    --r-lg: 12px;
    --r-xl: 16px;
    --row-h: 30px;      /* minimum, not a fixed height — rows grow with content */
    --gap: 13px;
    --shadow: 0 0 0 1px rgba(255,255,255,.04), 0 16px 40px -20px rgba(0,0,0,1);
}

/* ---------- 2. Reset ----------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; padding: 0; }

/* The `hidden` attribute must always win.
   Browsers apply `[hidden] { display: none }` from the user-agent stylesheet,
   but ANY author rule that sets `display` beats it — author styles outrank UA
   styles regardless of specificity. `.login-shell` sets `display: grid`, so
   `loginScreen.hidden = true` had no effect: the login card stayed on screen
   at full viewport height and the dashboard rendered underneath it, which is
   why signing in appeared to do nothing until you scrolled down.
   Every page toggles its screens with `.hidden`, so this rule is load-bearing. */
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; background: var(--bg-base); }

body {
    font-family: var(--font-ui);
    background: var(--bg-base);
    color: var(--text);
    font-size: 14px;
    line-height: 1.5;
    min-height: 100vh;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
    font-variant-numeric: tabular-nums;
}

/* A trace of green at the very top edge. Deliberately weak: any more and the
   canvas stops reading as true black, which is the point of this theme. */
body::before {
    content: '';
    position: fixed;
    inset: 0;
    pointer-events: none;
    z-index: 0;
    background: radial-gradient(900px 380px at 50% -16%, rgba(0,200,5,.028), transparent 72%);
}

.app { position: relative; z-index: 1; max-width: 1560px; margin: 0 auto; padding: 0 24px 56px; }

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

/* ---------- 3. Scrollbars ------------------------------------------------ */
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 99px; }
::-webkit-scrollbar-thumb:hover { background: #3d3d44; }
* { scrollbar-width: thin; scrollbar-color: var(--border-strong) transparent; }

/* ---------- 4. Typography helpers ---------------------------------------- */
.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }

.label {
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; letter-spacing: -.01em; }
.pos { color: var(--up); }
.neg { color: var(--down); }
.flat { color: var(--text-secondary); }
.dim { color: var(--text-muted); }

h1, h2, h3, h4 { font-weight: 600; letter-spacing: -.015em; line-height: 1.25; }
h1 { font-size: 24px; }
h2 { font-size: 16px; }
h3 { font-size: 14px; }

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

/* ---------- 5. Top bar --------------------------------------------------- */
.topbar {
    display: flex;
    align-items: center;
    gap: 16px;
    height: 52px;
}

.brand {
    display: flex;
    align-items: center;
    gap: 10px;
    font-weight: 700;
    font-size: 14px;
    letter-spacing: .02em;
    white-space: nowrap;
    color: var(--text);
}
.brand .mark {
    width: 26px; height: 26px;
    display: grid; place-items: center;
    border-radius: 50%;
    background: var(--up);
    color: #000; font-size: 12px;
    box-shadow: 0 0 0 4px var(--up-dim);
}
.brand small {
    font-weight: 500;
    color: var(--text-muted);
    letter-spacing: .05em;
    font-size: 10px;
    padding: 2px 7px;
    border: 1px solid var(--border-strong);
    border-radius: 99px;
    text-transform: uppercase;
}

.topbar-spacer { flex: 1 1 auto; }

.topbar-meta {
    display: flex;
    align-items: center;
    gap: 14px;
    font-size: 12px;
    color: var(--text-secondary);
}

.clock { font-family: var(--font-mono); color: var(--text-secondary); font-size: 12px; }

/* Connection / freshness pill */
.status-pill {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 4px 11px;
    border-radius: 99px;
    border: 1px solid var(--border-strong);
    background: var(--bg-panel);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--text-secondary);
    white-space: nowrap;
}
.status-pill .dot {
    width: 6px; height: 6px; border-radius: 99px;
    background: var(--neutral);
    flex: none;
}
.status-pill.is-live { color: var(--up); border-color: var(--up-glow); background: var(--up-dim); }
.status-pill.is-live .dot { background: var(--up); animation: pulse 2.4s ease-in-out infinite; }
.status-pill.is-stale { color: var(--warn); border-color: rgba(255,176,32,.35); background: var(--warn-dim); }
.status-pill.is-stale .dot { background: var(--warn); }
.status-pill.is-down { color: var(--down); border-color: var(--down-glow); background: var(--down-dim); }
.status-pill.is-down .dot { background: var(--down); }

@keyframes pulse {
    0%, 100% { opacity: 1; box-shadow: 0 0 0 0 var(--up-glow); }
    50%      { opacity: .6; box-shadow: 0 0 0 5px rgba(0,200,5,0); }
}

/* ---------- 6. Navigation (rendered by app.js — never hand-copied) ------- */
/* NOTE: this container must never establish a clipping context. It previously
   carried `overflow-x: auto`, which silently cropped the absolutely-positioned
   .nav-menu — the Crypto dropdown rendered outside the scroll box and was
   unreachable, while the plain top-level links worked fine. Wrapping instead
   of scrolling keeps the menu visible at every width. */
.nav {
    display: flex;
    align-items: stretch;
    flex-wrap: wrap;
    gap: 3px;
    border-bottom: 1px solid var(--border);
    margin-bottom: 18px;
    overflow: visible;
}

.nav-item { position: relative; }

.nav-link {
    display: flex;
    align-items: center;
    gap: 7px;
    padding: 0 12px;
    height: 38px;
    font-size: 13px;
    font-weight: 500;
    color: var(--text-secondary);
    white-space: nowrap;
    border-bottom: 2px solid transparent;
    transition: color .14s, border-color .14s;
    cursor: pointer;
    background: none;
    border-top: 0; border-left: 0; border-right: 0;
    font-family: inherit;
    text-decoration: none;
}
.nav-link:hover { color: var(--text); text-decoration: none; }
.nav-link i { font-size: 12px; opacity: .85; }

.nav-item.active > .nav-link {
    color: var(--text);
    border-bottom-color: var(--up);
}

.nav-caret { font-size: 9px; opacity: .6; margin-left: 2px; transition: transform .14s; }
.nav-item.open .nav-caret { transform: rotate(180deg); }

/* Dropdown — hover on pointer devices, click-toggle everywhere. */
.nav-menu {
    position: absolute;
    top: 100%;
    left: 0;
    min-width: 210px;
    background: var(--bg-elevated);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-md);
    box-shadow: var(--shadow);
    padding: 6px;
    z-index: 300;
    display: none;
}
.nav-item.open > .nav-menu { display: block; }
@media (hover: hover) {
    .nav-item:hover > .nav-menu { display: block; }
}

.nav-menu a {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 11px;
    border-radius: var(--r-sm);
    font-size: 13px;
    color: var(--text-secondary);
    text-decoration: none;
}
.nav-menu a:hover { background: var(--bg-panel-alt); color: var(--text); text-decoration: none; }
.nav-menu a.current { color: var(--up); background: var(--up-dim); }
.nav-menu a i { width: 14px; text-align: center; opacity: .8; font-size: 12px; }

/* ---------- 7. Buttons & controls ---------------------------------------- */
.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    height: 32px;
    padding: 0 14px;
    border-radius: 99px;
    border: 1px solid var(--border-strong);
    background: transparent;
    color: var(--text);
    font-family: inherit;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    transition: all .14s;
    white-space: nowrap;
}
.btn:hover { background: var(--bg-elevated); border-color: #3d3d44; }
.btn:active { transform: scale(.98); }
.btn:disabled { opacity: .4; cursor: not-allowed; transform: none; }

.btn-primary {
    background: var(--up);
    border-color: var(--up);
    color: #000;
}
.btn-primary:hover { background: var(--up-soft); border-color: var(--up-soft); color: #000; }

.btn-danger:hover { color: var(--down); border-color: var(--down-glow); background: var(--down-dim); }
.btn-sm { height: 30px; padding: 0 12px; font-size: 12px; }
.btn-icon { width: 36px; padding: 0; }
.btn-icon.btn-sm { width: 30px; }

.select, .input {
    height: 32px;
    padding: 0 11px;
    border-radius: var(--r-md);
    border: 1px solid var(--border-strong);
    background: var(--bg-input);
    color: var(--text);
    font-family: inherit;
    font-size: 13px;
    outline: none;
    transition: border-color .14s, box-shadow .14s;
}
.select:focus, .input:focus {
    border-color: var(--up);
    box-shadow: 0 0 0 3px var(--up-dim);
}
.input::placeholder { color: var(--text-faint); }

/* Segmented filter control */
.segment {
    display: inline-flex;
    gap: 3px;
    padding: 3px;
    background: var(--bg-panel);
    border: 1px solid var(--border);
    border-radius: 99px;
    flex-wrap: wrap;
}
.segment button {
    height: 28px;
    padding: 0 14px;
    border: 0;
    border-radius: 99px;
    background: transparent;
    color: var(--text-muted);
    font-family: inherit;
    font-size: 12px;
    font-weight: 600;
    cursor: pointer;
    transition: all .14s;
}
.segment button:hover { color: var(--text); }
.segment button.active { background: var(--up); color: #000; }

/* ---------- 8. Panels ---------------------------------------------------- */
.panel {
    background: var(--bg-panel);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    overflow: hidden;
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.panel-head {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 11px 14px;
    border-bottom: 1px solid var(--border);
    flex: none;
}
.panel-head h2, .panel-head h3 {
    font-size: 13.5px;
    font-weight: 600;
    letter-spacing: -.01em;
    text-transform: none;
    color: var(--text);
    display: flex;
    align-items: center;
    gap: 9px;
}
.panel-head h2 i, .panel-head h3 i { color: var(--up); font-size: 13px; }
.panel-head .spacer { flex: 1 1 auto; }
.panel-body { padding: 14px; min-width: 0; }
.panel-body.flush { padding: 0; }
.panel-body.scroll { overflow: auto; }

/* ---------- 9. Metric strip --------------------------------------------- */
.metrics {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(172px, 1fr));
    gap: var(--gap);
    margin-bottom: var(--gap);
}

.metric {
    position: relative;
    background: var(--bg-panel);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    padding: 12px 14px;
    overflow: hidden;
}
.metric::after {
    content: '';
    position: absolute;
    left: 0; top: 0; bottom: 0;
    width: 3px;
    background: transparent;
}
.metric.is-up::after     { background: var(--up); }
.metric.is-down::after   { background: var(--down); }
.metric.is-accent::after { background: var(--up); }
.metric.is-warn::after   { background: var(--warn); }

.metric .label { display: block; margin-bottom: 6px; }
.metric .value {
    font-family: var(--font-mono);
    font-size: 22px;
    font-weight: 500;
    letter-spacing: -.03em;
    line-height: 1.05;
    display: block;
    color: var(--text);
}
.metric .value.sm { font-size: 17px; }
.metric .delta {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    margin-top: 5px;
    font-family: var(--font-mono);
    font-size: 11.5px;
    font-weight: 600;
}
.metric .sub { display: block; margin-top: 4px; font-size: 10.5px; color: var(--text-muted); line-height: 1.35; }

/* ---------- 9b. Tiles: owned positions vs watchlist ---------------------- */
/* Two deliberately different treatments so a holding is never mistaken for
   something merely being watched. Owned tiles are filled and carry a coloured
   P&L edge plus position data; watchlist tiles are outlined, flatter, and show
   price action only. */
.tile-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(196px, 1fr));
    gap: var(--gap);
}

.tile {
    position: relative;
    border-radius: var(--r-md);
    padding: 11px 12px;
    display: flex;
    flex-direction: column;
    gap: 7px;
    min-width: 0;
    transition: transform .14s, border-color .14s, background .14s;
    text-decoration: none;
    color: inherit;
}
.tile:hover { transform: translateY(-2px); text-decoration: none; }

.tile-head { display: flex; align-items: flex-start; gap: 8px; }
.tile-sym { display: flex; flex-direction: column; min-width: 0; flex: 1 1 auto; }
.tile-sym strong {
    font-size: 13.5px; font-weight: 700; letter-spacing: -.01em;
    color: var(--text); line-height: 1.15;
}
.tile-sym span {
    font-size: 10.5px; color: var(--text-muted); overflow: hidden;
    text-overflow: ellipsis; white-space: nowrap; margin-top: 1px; line-height: 1.25;
}
.tile-price {
    font-family: var(--font-mono);
    font-size: 16px;
    font-weight: 500;
    letter-spacing: -.02em;
    color: var(--text);
    line-height: 1.2;
}
.tile-change { font-family: var(--font-mono); font-size: 11.5px; font-weight: 600; line-height: 1.3; }
.tile-foot {
    display: flex; align-items: baseline; justify-content: space-between;
    gap: 7px; padding-top: 7px; border-top: 1px solid var(--border-subtle);
    font-size: 10.5px; color: var(--text-muted);
}
.tile-foot .num { color: var(--text-secondary); font-size: 11px; }
.tile .spark { width: 100%; height: 26px; }

/* --- Owned: filled surface, P&L edge, position facts --------------------- */
.tile-position {
    background: var(--bg-panel);
    border: 1px solid var(--border);
    border-left: 3px solid var(--neutral);
}
.tile-position:hover { background: var(--bg-panel-alt); }
.tile-position.is-up   { border-left-color: var(--up); }
.tile-position.is-down { border-left-color: var(--down); }
.tile-position.is-up:hover   { border-color: var(--up-glow); border-left-color: var(--up); }
.tile-position.is-down:hover { border-color: var(--down-glow); border-left-color: var(--down); }

/* Marks the tile as a real holding without needing a legend. */
.tile-position .tile-badge {
    font-size: 9px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
    padding: 2px 6px; border-radius: 99px; white-space: nowrap;
    background: var(--up-dim); color: var(--up);
}
.tile-position.is-down .tile-badge { background: var(--down-dim); color: var(--down); }

/* --- Exchange (Kraken): a holding, but at a different venue -------------
   Same visual weight as a brokerage position so totals read consistently,
   distinguished by a venue chip and a staked line that brokerage tiles have
   no equivalent for. */
.tile-exchange {
    background: var(--bg-panel);
    border: 1px solid var(--border);
    border-left: 3px solid var(--neutral);
}
.tile-exchange:hover { background: var(--bg-panel-alt); }
.tile-exchange.is-up   { border-left-color: var(--up); }
.tile-exchange.is-down { border-left-color: var(--down); }
.tile-exchange.is-up:hover   { border-color: var(--up-glow); }
.tile-exchange.is-down:hover { border-color: var(--down-glow); }

.tile-exchange .tile-badge {
    font-size: 9px; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
    padding: 2px 6px; border-radius: 99px; white-space: nowrap;
    background: var(--neutral-dim); color: var(--text-secondary);
    border: 1px solid var(--border-strong);
}

/* Staked balance — only exchange tiles carry this. */
.tile-stake {
    display: flex; align-items: baseline; justify-content: space-between; gap: 7px;
    font-size: 10.5px; color: var(--text-muted);
}
.tile-stake .num { font-size: 11px; color: var(--text-secondary); }
.tile-stake .locked { color: var(--warn); }

/* Venue chip on the sub-line, so a symbol held in two places never reads
   ambiguously across the split sections. */
.tile-venue {
    display: inline-block;
    padding: 0 4px;
    margin-right: 5px;
    border-radius: 3px;
    font-size: 9px;
    font-weight: 700;
    letter-spacing: .05em;
    text-transform: uppercase;
    background: var(--bg-elevated);
    color: var(--text-muted);
    vertical-align: 1px;
}

/* --- Watchlist: outlined, unfilled, no position data -------------------- */
.tile-watch {
    background: transparent;
    border: 1px dashed var(--border-strong);
    box-shadow: none;
}
.tile-watch:hover { background: var(--bg-panel); border-style: solid; border-color: var(--text-faint); }
.tile-watch .tile-sym strong { font-weight: 600; color: var(--text-secondary); }
.tile-watch .tile-price { font-size: 15px; color: var(--text-secondary); }
.tile-watch .tile-badge {
    font-size: 9px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
    padding: 2px 6px; border-radius: 99px; white-space: nowrap;
    background: transparent; color: var(--text-faint); border: 1px solid var(--border-strong);
}
.tile-watch .tile-foot { border-top-style: dashed; }

/* ---------- 10. Tables --------------------------------------------------- */
.table-wrap { width: 100%; overflow-x: auto; }

table.data {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    font-size: 12.5px;
}

table.data thead th {
    position: sticky;
    top: 0;
    z-index: 5;
    background: var(--bg-base);
    padding: 7px 12px;
    text-align: right;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--text-muted);
    border-bottom: 1px solid var(--border);
    white-space: nowrap;
    user-select: none;
}
table.data thead th:first-child,
table.data thead th.txt { text-align: left; }

table.data thead th.sortable { cursor: pointer; transition: color .14s; }
table.data thead th.sortable:hover { color: var(--text); }
table.data thead th .arrow { opacity: .3; margin-left: 4px; font-size: 8px; }
table.data thead th.sorted-asc  .arrow,
table.data thead th.sorted-desc .arrow { opacity: 1; color: var(--up); }

table.data tbody td {
    padding: 6px 12px;
    /* On a table cell, `height` behaves as a minimum — the row still grows for
       wrapped content. `min-height` is undefined for table-cell boxes and is
       ignored by browsers, so it must not be used here. */
    height: var(--row-h);
    line-height: 1.35;
    border-bottom: 1px solid var(--border-subtle);
    text-align: right;
    white-space: nowrap;
    color: var(--text-secondary);
    vertical-align: middle;
}
table.data tbody td:first-child, table.data tbody td.txt { text-align: left; }
table.data tbody td.num { font-family: var(--font-mono); color: var(--text); }
table.data tbody td.wrap { white-space: normal; line-height: 1.4; min-width: 200px; }
table.data tbody tr:hover td { background: #131317; }
table.data tbody tr:last-child td { border-bottom: 0; }

table.data tfoot td {
    padding: 8px 12px;
    text-align: right;
    font-family: var(--font-mono);
    font-weight: 600;
    border-top: 1px solid var(--border);
    background: var(--bg-panel-alt);
    color: var(--text);
}
table.data tfoot td:first-child {
    text-align: left;
    font-family: var(--font-ui);
    font-size: 11px;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--text-muted);
}

/* Symbol cell */
.sym { display: flex; align-items: center; gap: 9px; }
.sym-badge {
    width: 23px; height: 23px;
    flex: none;
    display: grid; place-items: center;
    border-radius: 50%;
    background: var(--bg-elevated);
    border: 1px solid var(--border-strong);
    font-family: var(--font-mono);
    font-size: 9.5px;
    font-weight: 700;
    color: var(--text-secondary);
    letter-spacing: -.03em;
}
.sym-name { display: flex; flex-direction: column; line-height: 1.25; min-width: 0; }
.sym-name strong { font-size: 12.5px; font-weight: 600; color: var(--text); }
.sym-name span {
    font-size: 10.5px;
    color: var(--text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 170px;
    white-space: nowrap;
}

/* State rows */
td.state {
    text-align: center !important;
    color: var(--text-muted);
    padding: 22px 12px;
    font-size: 12.5px;
}
td.state i { display: block; font-size: 17px; margin-bottom: 7px; opacity: .3; }
td.state.error { color: var(--down); }

.skeleton {
    display: inline-block;
    height: 10px;
    width: 76px;
    border-radius: 99px;
    background: linear-gradient(90deg, var(--border) 25%, var(--border-strong) 50%, var(--border) 75%);
    background-size: 200% 100%;
    animation: shimmer 1.4s infinite;
}
@keyframes shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }

/* ---------- 11. Signals & tags ------------------------------------------- */
.tag {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 3px 9px;
    border-radius: 99px;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    border: 1px solid transparent;
    white-space: nowrap;
}
.tag-buy     { background: var(--up-dim);      color: var(--up);      border-color: var(--up-glow); }
.tag-sell    { background: var(--down-dim);    color: var(--down);    border-color: var(--down-glow); }
.tag-hold    { background: var(--neutral-dim); color: var(--neutral); border-color: rgba(139,139,147,.3); }
.tag-trim    { background: var(--warn-dim);    color: var(--warn);    border-color: rgba(255,176,32,.3); }
.tag-accent  { background: var(--accent-dim);  color: var(--accent);  border-color: var(--accent-line); }
.tag-none    { background: transparent;        color: var(--text-faint); border-color: var(--border); }
/* Health semantics, used by the Gemini quota pool on /diagnostics. Named for
   the meaning rather than reusing tag-trim/tag-sell, whose names are about
   trade actions and would read as nonsense next to a model name. */
.tag-warn    { background: var(--warn-dim);    color: var(--warn);    border-color: rgba(255,176,32,.3); }
.tag-down    { background: var(--down-dim);    color: var(--down);    border-color: var(--down-glow); }
/* Opt out of the parent .tag uppercase for prose fragments inside a chip. */
.tag .tag-note { text-transform: none; opacity: .75; letter-spacing: 0; }

.conf {
    display: inline-flex;
    gap: 2px;
    vertical-align: middle;
    margin-left: 6px;
}
.conf i { width: 3px; height: 10px; border-radius: 1px; background: var(--border-strong); }
.conf.high i                   { background: var(--up); }
.conf.medium i:nth-child(-n+2) { background: var(--warn); }
.conf.low i:nth-child(1)       { background: var(--down); }

/* ---------- 12. Sparkline ------------------------------------------------ */
.spark { display: block; width: 76px; height: 26px; overflow: visible; }
.spark path { fill: none; stroke-width: 1.6; vector-effect: non-scaling-stroke; }
.spark .fill { stroke: none; opacity: .16; }

/* ---------- 13. Chat / markdown ------------------------------------------ */
.chat {
    display: flex;
    flex-direction: column;
    gap: 14px;
    overflow-y: auto;
    padding: 18px;
    flex: 1 1 auto;
    min-height: 0;
    scroll-behavior: smooth;
}

.msg { display: flex; gap: 11px; max-width: 100%; }
.msg-avatar {
    width: 28px; height: 28px;
    flex: none;
    border-radius: 50%;
    display: grid; place-items: center;
    font-size: 11px;
    background: var(--bg-elevated);
    border: 1px solid var(--border-strong);
    color: var(--text-secondary);
}
.msg.bot .msg-avatar { background: var(--up-dim); border-color: var(--up-glow); color: var(--up); }
.msg-main { min-width: 0; flex: 1 1 auto; }
.msg-meta {
    display: flex;
    align-items: baseline;
    gap: 8px;
    margin-bottom: 5px;
    font-size: 11px;
    color: var(--text-muted);
}
.msg-meta strong { font-size: 12px; font-weight: 600; color: var(--text-secondary); }
.msg.bot .msg-meta strong { color: var(--up); }

.msg-body {
    background: var(--bg-panel-alt);
    border: 1px solid var(--border-subtle);
    border-radius: var(--r-md);
    padding: 11px 13px;
    font-size: 13px;
    line-height: 1.6;
    color: var(--text-secondary);
    overflow-wrap: anywhere;
}
.msg.bot .msg-body { background: var(--bg-elevated); }

/* Markdown inside messages / review bodies */
.md > *:first-child { margin-top: 0; }
.md > *:last-child  { margin-bottom: 0; }
.md p { margin: 0 0 9px; }
.md h1, .md h2, .md h3, .md h4, .md h5, .md h6 {
    margin: 16px 0 8px;
    color: var(--text);
    font-size: 13px;
    font-weight: 600;
    letter-spacing: -.01em;
}
.md h1 { font-size: 16px; }
.md h2 { font-size: 14.5px; }
.md ul, .md ol { margin: 0 0 9px; padding-left: 20px; }
.md li { margin: 3px 0; }
.md a { color: var(--up); text-decoration: underline; text-underline-offset: 2px; }
.md strong { color: var(--text); font-weight: 600; }
.md em { color: var(--text); font-style: italic; }
.md hr { border: 0; border-top: 1px solid var(--border); margin: 14px 0; }
.md blockquote {
    margin: 0 0 9px;
    padding: 2px 0 2px 12px;
    border-left: 2px solid var(--up-glow);
    color: var(--text-muted);
}
.md code {
    font-family: var(--font-mono);
    font-size: 12px;
    background: var(--bg-input);
    border: 1px solid var(--border);
    border-radius: var(--r-sm);
    padding: 1px 5px;
}
.md pre {
    background: var(--bg-input);
    border: 1px solid var(--border);
    border-radius: var(--r-md);
    padding: 12px;
    overflow-x: auto;
    margin: 0 0 9px;
}
.md pre code { background: none; border: 0; padding: 0; font-size: 12px; line-height: 1.55; }

/* --- Mattermost-flavoured elements -------------------------------------- */
/* The chat pane and digest reader render the same Markdown dialect Mattermost
   does, so these mirror how the channel itself presents them. */

.md .mm-emoji {
    font-size: 1.15em;
    line-height: 1;
    vertical-align: -0.1em;
    font-family: 'Apple Color Emoji', 'Segoe UI Emoji', 'Noto Color Emoji', sans-serif;
}

.md .mm-mention,
.md .mm-channel {
    display: inline-block;
    padding: 0 4px;
    border-radius: var(--r-sm);
    font-weight: 600;
    background: var(--accent-dim);
    color: var(--up);
    white-space: nowrap;
}
.md .mm-channel { background: var(--neutral-dim); color: var(--text-secondary); }

/* Task lists render as real checkboxes, as they do in a Mattermost post. */
.md ul.mm-tasks { list-style: none; padding-left: 2px; }
.md li.mm-task { display: flex; align-items: flex-start; gap: 8px; }
.md .mm-check {
    flex: none;
    width: 15px; height: 15px;
    margin-top: 2px;
    border: 1.5px solid var(--border-strong);
    border-radius: 3px;
    display: inline-grid;
    place-items: center;
    font-size: 10px;
    line-height: 1;
    color: transparent;
}
.md .mm-check.is-done {
    background: var(--up);
    border-color: var(--up);
    color: #000;
    font-weight: 700;
}

/* Fenced blocks show their language, matching Mattermost's code header. */
.md pre { position: relative; }
.md pre[data-lang] { padding-top: 26px; }
.md pre[data-lang]::before {
    content: attr(data-lang);
    position: absolute;
    top: 0; left: 0; right: 0;
    padding: 4px 10px;
    font-family: var(--font-ui);
    font-size: 9.5px;
    font-weight: 600;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--text-muted);
    background: var(--bg-panel-alt);
    border-bottom: 1px solid var(--border);
    border-radius: var(--r-md) var(--r-md) 0 0;
}

.md del { color: var(--text-muted); }

.md .md-table-wrap { overflow-x: auto; margin: 0 0 9px; border: 1px solid var(--border); border-radius: var(--r-md); }
.md table { width: 100%; border-collapse: separate; border-spacing: 0; font-size: 12px; }
.md th {
    background: var(--bg-panel-alt);
    padding: 8px 11px;
    text-align: left;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--text-muted);
    border-bottom: 1px solid var(--border);
    white-space: nowrap;
}
.md td {
    padding: 8px 11px;
    border-bottom: 1px solid var(--border-subtle);
    color: var(--text-secondary);
    vertical-align: top;
}
.md tbody tr:last-child td { border-bottom: 0; }
.md td:first-child { font-family: var(--font-mono); color: var(--text); font-weight: 600; white-space: nowrap; }

/* Composer */
.composer {
    display: flex;
    gap: 10px;
    padding: 14px 18px;
    border-top: 1px solid var(--border-subtle);
    flex: none;
}
.composer .input { flex: 1 1 auto; min-width: 0; }

/* ---------- 14. News ----------------------------------------------------- */
.news-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
    gap: var(--gap);
}

.news-card {
    display: flex;
    flex-direction: column;
    background: var(--bg-panel);
    border: 1px solid var(--border);
    border-radius: var(--r-lg);
    overflow: hidden;
    transition: border-color .14s, transform .14s;
    color: inherit;
    text-decoration: none;
}
.news-card:hover { border-color: var(--border-strong); transform: translateY(-2px); text-decoration: none; }
.news-thumb {
    height: 132px;
    background: var(--bg-input) center/cover no-repeat;
    border-bottom: 1px solid var(--border);
    flex: none;
}
.news-thumb.empty { display: grid; place-items: center; color: var(--text-faint); font-size: 22px; }
.news-content { padding: 14px 15px; display: flex; flex-direction: column; gap: 8px; flex: 1 1 auto; }
.news-title {
    font-size: 13.5px;
    font-weight: 600;
    color: var(--text);
    line-height: 1.4;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.news-summary {
    font-size: 12px;
    color: var(--text-muted);
    line-height: 1.5;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.news-foot {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: auto;
    padding-top: 9px;
    font-size: 11px;
    color: var(--text-faint);
    border-top: 1px solid var(--border-subtle);
    flex-wrap: wrap;
}
.news-foot .tag { font-size: 9.5px; padding: 2px 7px; }

/* ---------- 15. Layout helpers ------------------------------------------- */
.grid { display: grid; gap: var(--gap); }
.grid-2  { grid-template-columns: 1fr 1fr; }
.grid-21 { grid-template-columns: 2fr 1fr; }
.grid-12 { grid-template-columns: 1fr 2fr; }
.grid-31 { grid-template-columns: 3fr 1fr; }
.grid-13 { grid-template-columns: 1fr 3fr; }
.stack { display: flex; flex-direction: column; gap: var(--gap); }
.row { display: flex; align-items: center; gap: 10px; }
.row.wrap { flex-wrap: wrap; }
.mb { margin-bottom: var(--gap); }

.section-title {
    display: flex;
    align-items: center;
    gap: 9px;
    margin: 18px 0 10px;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--text-muted);
}
.section-title::after { content: ''; flex: 1 1 auto; height: 1px; background: var(--border); }

/* ---------- 16. Login ---------------------------------------------------- */
.login-shell {
    min-height: 100vh;
    display: grid;
    place-items: center;
    padding: 24px;
    position: relative;
    z-index: 1;
}
.login-card {
    width: 100%;
    max-width: 380px;
    background: var(--bg-panel);
    border: 1px solid var(--border);
    border-radius: var(--r-xl);
    padding: 36px 32px;
    box-shadow: var(--shadow);
}
.login-card .brand { justify-content: center; margin-bottom: 8px; font-size: 16px; }
.login-card .tagline { text-align: center; color: var(--text-muted); font-size: 13px; margin-bottom: 26px; }
.field { margin-bottom: 14px; }
.field label { display: block; margin-bottom: 6px; }
.field .input { width: 100%; height: 44px; }
.login-card .btn-primary { width: 100%; height: 44px; margin-top: 8px; }
.form-error {
    display: none;
    margin-top: 14px;
    padding: 10px 13px;
    border-radius: var(--r-md);
    background: var(--down-dim);
    border: 1px solid var(--down-glow);
    color: var(--down);
    font-size: 12px;
}
.form-error.show { display: block; }

/* ---------- 17. Toasts --------------------------------------------------- */
.toasts {
    position: fixed;
    right: 20px;
    bottom: 20px;
    z-index: 900;
    display: flex;
    flex-direction: column;
    gap: 10px;
    max-width: 380px;
}
.toast {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 12px 14px;
    border-radius: var(--r-md);
    background: var(--bg-elevated);
    border: 1px solid var(--border-strong);
    box-shadow: var(--shadow);
    font-size: 13px;
    color: var(--text-secondary);
    animation: toast-in .18s ease-out;
}
.toast i { margin-top: 1px; }
.toast.error   { border-color: var(--down-glow); }
.toast.error i { color: var(--down); }
.toast.warn    { border-color: rgba(255,176,32,.4); }
.toast.warn i  { color: var(--warn); }
.toast.ok      { border-color: var(--up-glow); }
.toast.ok i    { color: var(--up); }
@keyframes toast-in { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: none; } }

/* Inline panel-level banner */
.banner {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 11px 18px;
    font-size: 12.5px;
    background: var(--down-dim);
    border-bottom: 1px solid var(--down-glow);
    color: var(--down);
}
.banner.warn { background: var(--warn-dim); border-bottom-color: rgba(255,176,32,.35); color: var(--warn); }

/* ---------- 18. Bot cards ------------------------------------------------ */
.kv {
    display: grid;
    grid-template-columns: auto 1fr;
    gap: 6px 16px;
    align-items: baseline;
}
.kv dt { font-size: 10.5px; letter-spacing: .05em; text-transform: uppercase; color: var(--text-muted); }
.kv dd { font-family: var(--font-mono); font-size: 12px; color: var(--text); text-align: right; }

.stale-mask { opacity: .4; filter: grayscale(.6); transition: opacity .2s; }

/* ---------- 19. Modals ------------------------------------------------- */
.modal-overlay {
    position: fixed; top: 0; left: 0; right: 0; bottom: 0;
    background: rgba(0, 0, 0, 0.7);
    backdrop-filter: blur(4px);
    z-index: 1000;
    display: flex; align-items: center; justify-content: center;
    opacity: 0; pointer-events: none; transition: opacity 0.2s;
}
.modal-overlay.show { opacity: 1; pointer-events: auto; }
.modal {
    background: var(--bg-panel);
    border: 1px solid var(--border-strong);
    border-radius: var(--r-md);
    width: 90vw; max-width: 900px;
    height: 80vh; max-height: 600px;
    display: flex; flex-direction: column;
    box-shadow: 0 10px 40px rgba(0,0,0,0.8);
    transform: translateY(20px); transition: transform 0.2s;
}
.modal-overlay.show .modal { transform: none; }
.modal-head {
    display: flex; align-items: center; justify-content: space-between;
    padding: 16px 20px;
    border-bottom: 1px solid var(--border);
}
.modal-head h2 { margin: 0; font-size: 18px; font-weight: 500; }
.modal-head .sub { color: var(--text-secondary); margin-left: 10px; font-size: 13px; font-family: var(--font-mono); }
.modal-close {
    background: none; border: none; color: var(--text-secondary);
    font-size: 20px; cursor: pointer; padding: 4px;
}
.modal-close:hover { color: var(--text); }
.modal-body { flex: 1; min-height: 0; position: relative; padding: 20px; }

/* ---------- 19b. Inline tile charts ------------------------------------ */

/* The tile that owns an open chart spans the full grid row */
.tile.tile-expanded {
    grid-column: 1 / -1;
    transform: none !important;           /* disable hover lift while expanded */
    background: var(--bg-panel-alt);
    border-color: var(--border-strong);
    z-index: 2;
}

.tile-chart {
    overflow: hidden;
    max-height: 0;
    opacity: 0;
    transition: max-height 0.35s cubic-bezier(.4,0,.2,1),
                opacity 0.3s ease,
                margin-top 0.35s cubic-bezier(.4,0,.2,1);
    margin-top: 0;
    border-top: 1px solid transparent;
}
.tile-chart.tile-chart-open {
    max-height: 440px;
    opacity: 1;
    margin-top: 12px;
    border-top-color: var(--border);
}
.tile-chart-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 8px 4px 6px;
}
.tile-chart-label {
    font-size: 11px;
    font-weight: 500;
    color: var(--text-secondary);
    font-family: var(--font-mono);
    letter-spacing: 0.5px;
    text-transform: uppercase;
}
.tile-chart-close {
    background: none;
    border: none;
    color: var(--text-secondary);
    font-size: 18px;
    cursor: pointer;
    padding: 2px 6px;
    line-height: 1;
    border-radius: var(--r-sm);
    transition: background 0.15s, color 0.15s;
}
.tile-chart-close:hover {
    color: var(--text);
    background: rgba(255,255,255,0.06);
}
.tile-chart-canvas {
    border-radius: var(--r-sm);
    background: rgba(0,0,0,0.18);
    height: 360px;
}

/* ---------- 20. Responsive ----------------------------------------------- */
@media (max-width: 1180px) {
    .grid-21, .grid-12, .grid-31, .grid-13 { grid-template-columns: 1fr; }
}
@media (max-width: 860px) {
    .grid-2 { grid-template-columns: 1fr; }
    .app { padding: 0 14px 40px; }
    .topbar { height: auto; padding: 12px 0; flex-wrap: wrap; gap: 12px; }
    .topbar-meta { width: 100%; justify-content: space-between; }
    .metric .value { font-size: 23px; }
    .news-grid, .tile-grid { grid-template-columns: 1fr 1fr; }
}
@media (max-width: 560px) {
    .news-grid, .tile-grid { grid-template-columns: 1fr; }
    table.data tbody td.hide-sm, table.data thead th.hide-sm { display: none; }
}

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