/* AlgoTrade S2 -- dark fintech-dashboard design system.
   Plain CSS (no build step) shared by every page via base.html. */

:root {
  --bg: #0b0f14;
  --bg-elev-1: #10161d;
  --bg-elev-2: #161e27;
  --bg-elev-3: #1c2530;
  --border: #253040;
  --border-soft: #1c2530;

  --text: #e6edf3;
  --text-dim: #8a97a6;
  --text-faint: #5b6672;

  --accent-blue: #3b82f6;
  --accent-blue-dim: #1d4ed8;

  --green: #34d399;
  --green-dim: #059669;
  --red: #f87171;
  --red-dim: #dc2626;
  --amber: #fbbf24;

  --radius: 10px;
  /* 🔴 THE STICKY STACK'S ONE MEASUREMENT. The mode banner, the topbar and the
     sidebar are all `position: sticky`, and until 2026-09-08 all three pinned
     to `top: 0` -- so the moment the operator scrolled, the banner (z-index
     500) sat on top of the topbar's clock row and the sidebar's brand, and
     both looked like they had "scrolled up and stopped". They had not; they
     were underneath. Each one below the banner now offsets by exactly this,
     and the banner is given this as a HARD height so the number cannot drift
     with the font. Change it in one place or not at all. */
  --banner-h: 30px;
  --font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 14px;
  -webkit-font-smoothing: antialiased;
}

/* ---------- numeric formatting: decimals must match the integer's weight/size ---------- */
.num {
  font-family: var(--font-mono);
  font-variant-numeric: tabular-nums;
  font-weight: inherit;
  font-size: inherit;
  letter-spacing: 0.01em;
}
.num.pos { color: var(--green); }
.num.neg { color: var(--red); }
.num.neutral { color: var(--text); }

/* ---------- app shell ---------- */
.app-shell {
  display: flex;
  min-height: 100vh;
}

.sidebar {
  width: 232px;
  flex-shrink: 0;
  background: var(--bg-elev-1);
  border-right: 1px solid var(--border-soft);
  padding: 22px 14px;
  position: sticky;
  /* Below the banner, not underneath it -- see `--banner-h`. The height loses
     the same amount, or the sidebar footer sits below the fold by exactly the
     banner's height and the operator can never scroll to it. */
  top: var(--banner-h);
  height: calc(100vh - var(--banner-h));
  display: flex;
  flex-direction: column;
}

.brand {
  font-weight: 700;
  font-size: 15px;
  letter-spacing: 0.01em;
  color: var(--text);
  padding: 0 10px 26px 10px;
  display: flex;
  align-items: center;
  gap: 9px;
}
.brand .dot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--green);
  box-shadow: 0 0 8px var(--green);
  flex-shrink: 0;
}
.brand-sub {
  display: block;
  font-size: 10px;
  font-weight: 500;
  color: var(--text-faint);
  letter-spacing: 0.04em;
  margin-top: 1px;
}

.nav-section-label {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-faint);
  font-weight: 700;
  padding: 0 10px;
  margin-bottom: 8px;
}

.nav-link {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 12px;
  margin-bottom: 6px;
  border-radius: 8px;
  color: var(--text-dim);
  text-decoration: none;
  font-weight: 500;
  font-size: 13.5px;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
  border: 1px solid transparent;
}
.nav-link svg { flex-shrink: 0; opacity: 0.75; transition: opacity 0.15s; }
.nav-link:hover { background: var(--bg-elev-2); color: var(--text); }
.nav-link:hover svg { opacity: 1; }
.nav-link.active {
  background: linear-gradient(90deg, rgba(59,130,246,0.16), rgba(59,130,246,0.03));
  color: var(--text);
  font-weight: 700;
  border-color: rgba(59,130,246,0.25);
}
.nav-link.active svg { opacity: 1; color: var(--accent-blue); }

.sidebar-footer {
  margin-top: auto;
  padding: 10px;
  font-size: 11px;
  color: var(--text-faint);
  border-top: 1px solid var(--border-soft);
  padding-top: 14px;
}

.main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
}

/* ---------- sticky header ---------- */
.topbar {
  position: sticky;
  /* Below the banner. Without this the clock row is covered the instant the
     page scrolls -- the banner is sticky too, at `top: 0`, with z-index 500. */
  top: var(--banner-h);
  z-index: 20;
  background: var(--bg-elev-1);
  border-bottom: 1px solid var(--border-soft);
  /* ⚠ `backdrop-filter` DELIBERATELY REMOVED, 2026-09-08. The background above
     is fully opaque, so the blur was never visible -- but it forces this
     sticky element onto its own composited layer, and a composited sticky
     layer under a continuously animating one (the banner's pulse) is a known
     cause of whole-screen black repaints while scrolling or zooming on
     Chrome/Windows, which is what the operator reported. Nothing is lost by
     removing it; if the flashing persists, see the parking-lot entry. */
}

.topbar-row1 {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 20px;
  border-bottom: 1px solid var(--border-soft);
  font-size: 12px;
  color: var(--text-dim);
}
.topbar-row1 .clock {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--text);
  letter-spacing: 0.02em;
}
.market-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 10px;
  border-radius: 999px;
  background: var(--bg-elev-2);
  border: 1px solid var(--border-soft);
}
.market-badge .dot { width: 6px; height: 6px; border-radius: 50%; }
.market-badge.open .dot { background: var(--green); box-shadow: 0 0 6px var(--green); }
.market-badge.closed .dot { background: var(--text-faint); }

.topbar-row2 {
  display: grid;
  grid-template-columns: repeat(4, minmax(140px, 1fr)) auto;
  align-items: center;
  gap: 20px;
  padding: 14px 20px;
}

/* ---------- trading status pill (live/stopped) -- sober, not flashy ---------- */
.status-pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--bg-elev-2);
  font-size: 13px;
  font-weight: 600;
  color: var(--text-dim);
  white-space: nowrap;
  /* Belt and braces (2026-08-10): the labels are deliberately short and the
     detail lives in the title tooltip, but a long one must CLIP rather than
     push into the neighbouring stat card, which is what it did live. */
  max-width: 100%;
  overflow: hidden;
}
.status-pill #status-pill-text {
  overflow: hidden;
  text-overflow: ellipsis;
}
.status-pill-dot { width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0; background: var(--text-faint); }
.status-pill.is-live { color: var(--green); border-color: rgba(52,211,153,0.35); }
.status-pill.is-live .status-pill-dot {
  background: var(--green);
  box-shadow: 0 0 6px var(--green);
  animation: status-pill-pulse 2.2s ease-in-out infinite;
}
.status-pill.is-stopped { color: var(--amber); border-color: rgba(251,191,36,0.3); }
.status-pill.is-stopped .status-pill-dot { background: var(--amber); }
.status-pill.is-alert { color: var(--red); border-color: rgba(248,113,113,0.35); }
.status-pill.is-alert .status-pill-dot { background: var(--red); box-shadow: 0 0 6px var(--red); }
@keyframes status-pill-pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.45; }
}

/* ---------- alert badge (CLOSING/HALTED/DIVERGENCE/FEED*) ----------
   Separate from the phase pill above (2026-08-21) so a diagnostic never
   overwrites "what phase of the day is this" -- hidden entirely unless
   something actually needs attention. */
.alert-badge {
  display: none;
  align-items: center;
  gap: 6px;
  margin-top: 4px;
  font-size: 11px;
  font-weight: 600;
  color: var(--red);
  white-space: nowrap;
  max-width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
}
.alert-badge.show { display: inline-flex; }
.alert-badge-dot {
  width: 6px; height: 6px; border-radius: 50%; flex-shrink: 0;
  background: var(--red); box-shadow: 0 0 6px var(--red);
}
/* PROVISIONAL, NOT WRONG (2026-09-01). Every other state this badge shows means
   something has stopped and will not restart by itself. RECONCILING clears on
   its own, usually within seconds -- so it must not wear the same red as
   UNMANAGED POSITION or DIVERGENCE, or the colour that means "drop everything"
   starts appearing several times a day and stops meaning anything. Amber, and
   it returns to normal the moment the books agree. */
.alert-badge.is-checking { color: var(--amber, #f59e0b); }
.alert-badge.is-checking .alert-badge-dot {
  background: var(--amber, #f59e0b);
  box-shadow: 0 0 6px var(--amber, #f59e0b);
}

.stat-card { min-width: 0; }
.stat-label {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-faint);
  font-weight: 600;
  margin-bottom: 3px;
}
.stat-value {
  font-family: var(--font-mono);
  font-size: 20px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1.2;
}

.header-actions { display: flex; gap: 10px; }

.btn {
  border: none;
  border-radius: 8px;
  padding: 10px 20px;
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 0.03em;
  cursor: pointer;
  color: #fff;
  transition: transform 0.08s ease, box-shadow 0.15s ease, filter 0.15s ease;
}
.btn:active { transform: translateY(1px); }
.btn:disabled { opacity: 0.4; cursor: not-allowed; filter: grayscale(0.4); }

.btn-start {
  background: linear-gradient(135deg, #34d399, #059669);
  box-shadow: 0 2px 10px rgba(5,150,105,0.35);
}
.btn-start:not(:disabled):hover { filter: brightness(1.08); box-shadow: 0 3px 14px rgba(5,150,105,0.5); }

.btn-kill {
  background: linear-gradient(135deg, #f87171, #dc2626);
  box-shadow: 0 2px 10px rgba(220,38,38,0.35);
}
.btn-kill:not(:disabled):hover { filter: brightness(1.08); box-shadow: 0 3px 14px rgba(220,38,38,0.5); }

/* DISCONNECT: amber, because it is neither routine (green) nor an emergency
   flatten (red). It cuts the broker link and leaves any open position to the
   operator -- a warning, not a stop. */
.btn-warn {
  background: linear-gradient(135deg, #fbbf24, #d97706);
  box-shadow: 0 2px 10px rgba(217,119,6,0.35);
}
.btn-warn:not(:disabled):hover { filter: brightness(1.08); box-shadow: 0 3px 14px rgba(217,119,6,0.5); }

.btn-primary {
  background: linear-gradient(135deg, #60a5fa, #2563eb);
  box-shadow: 0 2px 10px rgba(37,99,235,0.35);
}
.btn-primary:not(:disabled):hover { filter: brightness(1.08); }

.btn-ghost {
  background: var(--bg-elev-3);
  border: 1px solid var(--border);
  color: var(--text-dim);
}
.btn-ghost:hover { color: var(--text); border-color: var(--accent-blue); }

.btn-sm { padding: 6px 12px; font-size: 12px; }

/* ---------- page content ---------- */
.page {
  padding: 24px 28px 48px 28px;
  max-width: 1400px;
}

.page-title {
  font-size: 22px;
  font-weight: 700;
  margin: 0 0 4px 0;
}
.page-subtitle {
  color: var(--text-dim);
  font-size: 13px;
  margin: 0 0 22px 0;
}

.card {
  background: var(--bg-elev-1);
  border: 1px solid var(--border-soft);
  border-radius: var(--radius);
  padding: 18px 20px;
  margin-bottom: 18px;
}
.card-title {
  font-size: 14px;
  font-weight: 700;
  margin: 0 0 12px 0;
  color: var(--text);
}

/* ---------- compact backtest-summary widget grid ---------- */
.summary-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 14px;
}
.summary-cell {
  background: var(--bg-elev-2);
  border: 1px solid var(--border-soft);
  border-radius: 8px;
  padding: 10px 12px;
  min-width: 0;
}
.stat-value-sm {
  font-family: var(--font-mono);
  font-size: 15px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  line-height: 1.35;
}

/* ---------- currency input with a "Rs." prefix chip ---------- */
.input-group { display: flex; }
.input-group .input-prefix {
  display: flex;
  align-items: center;
  background: var(--bg-elev-3);
  border: 1px solid var(--border);
  border-right: none;
  border-radius: 7px 0 0 7px;
  padding: 0 10px;
  color: var(--text-dim);
  font-size: 13px;
  font-family: var(--font-mono);
}
.input-group input { border-radius: 0 7px 7px 0; }

/* ---------- forms ---------- */
input[type=text], input[type=number], input[type=password], input[type=date], select {
  background: var(--bg-elev-2);
  border: 1px solid var(--border);
  border-radius: 7px;
  color: var(--text);
  padding: 8px 10px;
  font-size: 13px;
  font-family: var(--font-sans);
}
input:focus, select:focus {
  outline: none;
  border-color: var(--accent-blue);
  box-shadow: 0 0 0 3px rgba(59,130,246,0.15);
}
label {
  display: block;
  font-size: 12px;
  color: var(--text-dim);
  font-weight: 600;
  margin-bottom: 5px;
}

/* dark-theme date inputs: color-scheme:dark alone makes Chromium draw a
   light-colored native calendar glyph that's visible on this palette --
   layering a filter:invert() on TOP of that (as an earlier pass did)
   re-inverts an already-light icon back to near-black/invisible. */
input[type=date] { color-scheme: dark; }
input[type=date]::-webkit-calendar-picker-indicator { cursor: pointer; border-radius: 4px; }

/* ---------- sticky in-card toolbar (e.g. Backtest's Add row / Run) ---------- */
.toolbar {
  position: sticky;
  top: 0;
  z-index: 5;
  background: var(--bg-elev-1);
  display: flex;
  align-items: flex-start;
  gap: 28px;
  flex-wrap: wrap;
  padding-bottom: 16px;
  margin-bottom: 16px;
  border-bottom: 1px solid var(--border-soft);
}
.toolbar-group { display: flex; flex-direction: column; gap: 6px; }
.toolbar-group-label {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.07em;
  color: var(--text-faint);
  font-weight: 700;
}
.toolbar-group-row { display: flex; gap: 12px; align-items: flex-end; }
.toolbar-divider { width: 1px; align-self: stretch; background: var(--border-soft); }

/* ---------- left/right-labeled toggle switch (e.g. Backtest Mode) ----------
   A segmented button pair read as ambiguous ("which one is pressed?") in
   user testing -- a sliding switch with a label flanking each side reads
   unambiguously as a single left/right binary choice instead. */
.toggle-switch-wrap {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  user-select: none;
}
.toggle-switch-label {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-faint);
  transition: color 0.15s;
}
.toggle-switch-label.active { color: var(--text); }
.toggle-switch {
  position: relative;
  display: inline-block;
  width: 40px;
  height: 22px;
  flex-shrink: 0;
}
.toggle-switch input {
  position: absolute;
  width: 0;
  height: 0;
  opacity: 0;
}
.toggle-switch-track {
  position: absolute;
  inset: 0;
  background: var(--bg-elev-3);
  border: 1px solid var(--border);
  border-radius: 999px;
  transition: background 0.15s, border-color 0.15s;
}
.toggle-switch-thumb {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--text-dim);
  transition: transform 0.15s, background 0.15s;
}
.toggle-switch input:checked + .toggle-switch-track {
  background: var(--accent-blue-dim);
  border-color: var(--accent-blue);
}
.toggle-switch input:checked + .toggle-switch-track .toggle-switch-thumb {
  transform: translateX(18px);
  background: #fff;
}
.toggle-switch input:focus-visible + .toggle-switch-track {
  box-shadow: 0 0 0 3px rgba(59,130,246,0.25);
}

/* ---------- wide 2-column page layout (e.g. Setup) ---------- */
.grid-2 {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 18px;
  align-items: start;
}
@media (max-width: 900px) { .grid-2 { grid-template-columns: 1fr; } }

/* ---------- scrollable activity log ---------- */
.log-area {
  max-height: 280px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
}
.log-area-lg { max-height: 480px; }  /* Live page: the log is the main real estate */
.log-line {
  display: flex;
  gap: 10px;
  padding: 7px 2px;
  border-bottom: 1px solid var(--border-soft);
  font-size: 12.5px;
  line-height: 1.5;
}
.log-line:last-child { border-bottom: none; }
.log-time {
  flex-shrink: 0;
  color: var(--text-faint);
  font-family: var(--font-mono);
  font-size: 11.5px;
  padding-top: 1px;
  width: 68px;
}
.log-area::-webkit-scrollbar { width: 8px; }
.log-area::-webkit-scrollbar-track { background: transparent; }
.log-area::-webkit-scrollbar-thumb { background: var(--border); border-radius: 4px; }
.log-area::-webkit-scrollbar-thumb:hover { background: var(--text-faint); }

/* EVERY OTHER SCROLLER, NOT JUST THE LOG (2026-08-31). The activity log styled
   its own scrollbar and nothing else did, so the Orders table and History drew
   the BROWSER'S DEFAULT -- a white track across a dark page, which is what the
   operator saw and it looks broken rather than merely plain. Same colours as
   the log's, applied once at the root so a new scrolling container inherits
   them instead of having to remember. `scrollbar-color` is the standards
   version (Firefox); the ::-webkit- rules cover Chrome and Edge. */
* {
  scrollbar-color: var(--border) transparent;
  scrollbar-width: thin;
}
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-corner { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--border); border-radius: 4px; }
::-webkit-scrollbar-thumb:hover { background: var(--text-faint); }

/* ---------- tables ---------- */
table.data-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}
table.data-table th {
  text-align: left;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-faint);
  font-weight: 700;
  padding: 8px 12px;
  border-bottom: 1px solid var(--border);
  white-space: nowrap;
}
table.data-table td {
  padding: 9px 12px;
  border-bottom: 1px solid var(--border-soft);
  color: var(--text);
  white-space: nowrap;
}
table.data-table tbody tr:hover { background: var(--bg-elev-2); }
table.data-table tbody tr:nth-child(even) { background: rgba(255,255,255,0.012); }

.badge {
  display: inline-block;
  padding: 2px 9px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.03em;
}
.badge-green { background: rgba(52,211,153,0.15); color: var(--green); }
.badge-red { background: rgba(248,113,113,0.15); color: var(--red); }
.badge-gray { background: rgba(139,151,166,0.15); color: var(--text-dim); }
.badge-blue { background: rgba(59,130,246,0.15); color: var(--accent-blue); }
.badge-amber { background: rgba(251,191,36,0.15); color: var(--amber); }

.divider { height: 1px; background: var(--border-soft); margin: 18px 0; }

.muted { color: var(--text-dim); font-size: 12px; }
.mono { font-family: var(--font-mono); }

.toast-area { min-height: 20px; font-size: 12.5px; margin-top: 8px; }
.toast-ok { color: var(--green); }
.toast-err { color: var(--red); }
.toast-warn { color: var(--amber); }

/* ---------- History page: monthly calendar heatmap ---------- */
.cal-grid {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 6px;
}
.cal-grid-head { margin-bottom: 6px; }
.cal-weekday {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--text-faint);
  font-weight: 700;
  text-align: center;
  padding: 4px 0;
}
.cal-cell {
  min-height: 78px;
  border-radius: 8px;
  border: 1px solid var(--border-soft);
  background: var(--bg-elev-2);
  padding: 8px 10px;
  margin-bottom: 6px;
}
.cal-empty { background: transparent; border-color: transparent; }
.cal-clickable { cursor: pointer; transition: filter 0.12s ease, border-color 0.12s ease; }
.cal-clickable:hover { filter: brightness(1.15); border-color: var(--accent-blue); }
.cal-daynum { font-size: 12px; color: var(--text-faint); font-weight: 600; margin-bottom: 4px; }
.cal-pnl { font-size: 13px; font-weight: 700; }
.cal-trades { font-size: 11px; color: var(--text-faint); margin-top: 1px; }

.cal-pos-lo  { background: rgba(52,211,153,0.10); border-color: rgba(52,211,153,0.18); }
.cal-pos-mid { background: rgba(52,211,153,0.20); border-color: rgba(52,211,153,0.32); }
.cal-pos-hi  { background: rgba(52,211,153,0.32); border-color: rgba(52,211,153,0.5); }
.cal-neg-lo  { background: rgba(248,113,113,0.10); border-color: rgba(248,113,113,0.18); }
.cal-neg-mid { background: rgba(248,113,113,0.20); border-color: rgba(248,113,113,0.32); }
.cal-neg-hi  { background: rgba(248,113,113,0.32); border-color: rgba(248,113,113,0.5); }
.cal-neutral { background: var(--bg-elev-3); }

.cal-legend {
  display: flex;
  align-items: center;
  gap: 6px;
  justify-content: flex-end;
  margin-top: 10px;
  font-size: 11px;
  color: var(--text-faint);
  letter-spacing: 0.04em;
}
.cal-legend-dot { width: 10px; height: 10px; border-radius: 3px; display: inline-block; }

dialog.confirm-dialog {
  background: var(--bg-elev-2);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 20px;
  width: 360px;
}
dialog.confirm-dialog::backdrop { background: rgba(0,0,0,0.55); }

.htmx-indicator { opacity: 0; transition: opacity 150ms ease-in; }
.htmx-request.htmx-indicator, .htmx-request .htmx-indicator { opacity: 1; }

/* --- Login page (webapp/templates/login.html) -- standalone, no sidebar --- */
.login-page {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background-image:
    linear-gradient(rgba(52,211,153,0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(52,211,153,0.05) 1px, transparent 1px);
  background-size: 42px 42px;
  background-position: center top;
}
.login-topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18px 28px;
  border-bottom: 1px solid var(--border-soft);
  background: rgba(11,15,20,0.6);
}
.login-brand { display: flex; align-items: center; gap: 12px; }
.login-brand-icon {
  width: 38px; height: 38px;
  border-radius: 9px;
  background: linear-gradient(135deg, var(--green) 0%, var(--green-dim) 100%);
  display: flex; align-items: center; justify-content: center;
  color: #04140d;
  flex-shrink: 0;
}
.login-brand-name { font-weight: 700; font-size: 15px; letter-spacing: 0.02em; }
.login-brand-sub { font-size: 10.5px; color: var(--text-faint); letter-spacing: 0.08em; margin-top: 1px; }
.login-topbar-right { display: flex; align-items: center; gap: 16px; }
.login-clock { font-family: var(--font-mono); font-size: 13px; color: var(--text-dim); text-align: right; line-height: 1.3; }
.login-clock .time { color: var(--text); font-weight: 600; letter-spacing: 0.02em; }

.login-center {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 40px 20px;
}
.login-card {
  width: 100%;
  max-width: 420px;
  background: var(--bg-elev-1);
  border: 1px solid var(--border);
  border-radius: 16px;
  padding: 36px 32px 28px;
  box-shadow: 0 20px 60px rgba(0,0,0,0.4);
}
.login-card h1 {
  margin: 0 0 6px;
  font-size: 22px;
  text-align: center;
}
.login-card .login-subtitle {
  text-align: center;
  color: var(--text-dim);
  font-size: 13px;
  margin: 0 0 28px;
}
.login-field { margin-bottom: 20px; }
.login-field label {
  display: block;
  font-size: 11px;
  letter-spacing: 0.08em;
  color: var(--text-faint);
  margin-bottom: 8px;
}
.login-field-box {
  display: flex;
  align-items: center;
  gap: 10px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px 14px;
  color: var(--text-dim);
}
.login-field-box svg { flex-shrink: 0; opacity: 0.75; }
.login-field-box.mono { font-family: var(--font-mono); font-size: 14px; }
.btn-authenticate {
  width: 100%;
  display: flex; align-items: center; justify-content: center; gap: 8px;
  background: linear-gradient(135deg, var(--green) 0%, #6ee7b7 100%);
  color: #04140d;
  border: none;
  border-radius: 8px;
  padding: 14px 18px;
  font-size: 13.5px;
  font-weight: 700;
  letter-spacing: 0.04em;
  cursor: pointer;
  margin-top: 4px;
}
.btn-authenticate:not(:disabled):hover { filter: brightness(1.06); }
.btn-authenticate:disabled { opacity: 0.6; cursor: default; }
.login-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-top: 1px solid var(--border-soft);
  margin-top: 24px;
  padding-top: 16px;
  font-size: 10.5px;
  letter-spacing: 0.05em;
  color: var(--text-faint);
}
.login-footer .ok { color: var(--green); }
.login-status { margin-top: 16px; text-align: center; font-size: 13px; min-height: 18px; }

/* Password visibility toggle + sign-in spinner (login page) */
.pw-wrap { position: relative; display: block; }
.pw-toggle {
  position: absolute;
  right: 6px;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: none;
  padding: 6px;
  border-radius: 6px;
  color: var(--text-faint);
  cursor: pointer;
}
.pw-toggle:hover { color: var(--text-dim); }
.signin-spinner {
  display: none;
  width: 15px;
  height: 15px;
  border-radius: 50%;
  border: 2px solid rgba(4, 20, 13, 0.25);
  border-top-color: #04140d;
  animation: signin-spin 0.7s linear infinite;
}
@keyframes signin-spin { to { transform: rotate(360deg); } }
.btn-authenticate.htmx-request .signin-arrow,
form.htmx-request .signin-arrow { display: none; }
.btn-authenticate.htmx-request .signin-spinner,
form.htmx-request .signin-spinner { display: block; }

/* ==========================================================================
   LIVE APP additions (session 7)
   ========================================================================== */

/* Mode banner -- always visible, never dismissible. An operator must never
   have to wonder whether this portal can spend real money. */
.mode-banner {
  position: sticky;
  top: 0;
  z-index: 500;
  /* A HARD height, because two other sticky elements offset themselves by it.
     Centred by flex rather than by padding so the text stays put whatever the
     font resolves to -- a banner that grows by two pixels would otherwise
     re-open the exact overlap this fixes. */
  height: var(--banner-h);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 16px;
  /* ⚠ IT MUST NOT WRAP, and that is a consequence of the fixed height, not a
     style choice. Two other sticky elements offset themselves by exactly
     `--banner-h`; a second line would overflow the box rather than push them
     down, and the text would spill across the topbar. Found by code review.
     The banner shrinks instead -- it is the one line on the page that must
     stay readable at any width, so it is never clipped or ellipsised. */
  white-space: nowrap;
  font-size: clamp(8px, 2.4vw, 12px);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  text-align: center;
  border-bottom: 1px solid rgba(0, 0, 0, 0.25);
}
.mode-banner.is-shadow {
  background: #1f2937;
  color: #9ca3af;
}
/* Broker link cut: amber, matching the DISCONNECT button that causes it. NOT
   red and not pulsing -- nothing is being risked here; the numbers have simply
   stopped moving, and reusing the live banner's alarm would blunt it. */
.mode-banner.is-warn {
  background: #78350f;
  color: #fef3c7;
}

/* Deliberately loud. This is the one state where a mistake costs money. */
.mode-banner.is-live {
  background: #7f1d1d;
  color: #fee2e2;
  animation: liveBannerPulse 2.5s ease-in-out infinite;
}
@keyframes liveBannerPulse {
  0%, 100% { background: #7f1d1d; }
  50%      { background: #991b1b; }
}
.mode-banner #mode-banner-detail,
.mode-banner #mode-banner-session {
  font-weight: 500;
  text-transform: none;
  letter-spacing: 0;
  opacity: 0.85;
}
/* The session line is a separate span from the detail one so the server and
   the tick each own exactly one of them (see base.html). Its separator lives
   here rather than in either painter's string, so an empty span adds nothing. */
.mode-banner #mode-banner-session:not(:empty)::before { content: " — "; }
@media (prefers-reduced-motion: reduce) {
  .mode-banner.is-live { animation: none; }
}

/* Orders panel */
.orders-panel { margin-top: 18px; }
.orders-table { width: 100%; border-collapse: collapse; font-size: 12px; }
.orders-table th,
.orders-table td {
  padding: 6px 8px;
  text-align: left;
  border-bottom: 1px solid rgba(148, 163, 184, 0.18);
  white-space: nowrap;
}
.orders-table th {
  font-weight: 600;
  text-transform: uppercase;
  font-size: 10px;
  letter-spacing: 0.05em;
  opacity: 0.7;
}
.orders-table td.num { text-align: right; font-variant-numeric: tabular-nums; }
.orders-empty { padding: 14px 8px; font-size: 12px; opacity: 0.65; }

/* Status chips. Colour carries meaning, but the text always states it too --
   never rely on colour alone to tell an operator an order was rejected. */
.ord-status {
  display: inline-block;
  padding: 1px 7px;
  border-radius: 10px;
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.04em;
}
.ord-status.s-new       { background: #374151; color: #d1d5db; }
.ord-status.s-submitted { background: #1e3a5f; color: #bfdbfe; }
.ord-status.s-partial   { background: #78350f; color: #fde68a; }
.ord-status.s-filled    { background: #14532d; color: #bbf7d0; }
.ord-status.s-uncertain { background: #7c2d12; color: #fed7aa; }
.ord-status.s-rejected,
.ord-status.s-abandoned { background: #7f1d1d; color: #fecaca; }
.ord-status.s-cancelled { background: #334155; color: #cbd5e1; }
.ord-error { font-size: 11px; opacity: 0.8; white-space: normal; }

.brand-ver { display:block; font-size:10px; letter-spacing:.04em;
  opacity:.55; font-family:ui-monospace,SFMono-Regular,Menlo,monospace;
  margin-top:2px; }
