:root {
  /* ALIEN THEME: UV purple as the primary accent (was gold), toxic green
     as secondary (was ice-blue), a faint green glow on panel borders
     instead of a flat line. Variable NAMES kept identical to what every
     page already references (--gold, --gold-bright, --ice-blue,
     --panel-border) so the new palette applies everywhere at once. */
  --bg-void: #04070a;
  --bg-panel: rgba(14, 22, 20, 0.80);
  --panel-border: rgba(110, 255, 170, 0.28);
  --gold: #b06bff;
  --gold-bright: #d9a8ff;
  --ice-blue: #5dffb0;
  --text-primary: #e4f5ec;
  --text-dim: #8b9a94;
  --green: #4caf7d;
  --red: #d16464;
  --alien-glow: rgba(120, 255, 180, 0.35);
  --mono: "JetBrains Mono", "SFMono-Regular", Consolas, monospace;
  --display: "Cinzel", "Trajan Pro", Georgia, serif;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg-void);
  color: var(--text-primary);
  font-family: var(--mono);
  min-height: 100vh;
}

body::after {
  content: "";
  position: fixed;
  inset: 0;
  background: radial-gradient(ellipse at 50% 15%, rgba(176, 107, 255, 0.10), transparent 55%),
              radial-gradient(ellipse at 50% 100%, rgba(93, 255, 176, 0.07), transparent 60%);
  pointer-events: none;
  z-index: 0;
}

.wrap {
  position: relative;
  z-index: 1;
  max-width: 880px;
  margin: 0 auto;
  padding: 32px 20px 64px;
}

.bg-deco {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;
}
.bg-scribble {
  opacity: 0.22;
  fill: none;
}
.bg-radar-sweep {
  transform-origin: 0 0;
  animation: bg-spin-slow 22s linear infinite;
}
.bg-numeral {
  fill: var(--gold);
  font-family: var(--mono);
  font-size: 11px;
  opacity: 0.4;
}
.bg-pulse-dot {
  animation: bg-pulse 3s ease-in-out infinite;
}
.bg-pulse-slow {
  animation: bg-pulse-scale 8s ease-in-out infinite;
}
@keyframes bg-pulse { 0%, 100% { r: 6; opacity: 1; } 50% { r: 9; opacity: 0.5; } }
@keyframes bg-pulse-scale { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.08); } }
.bg-corner-orbit { opacity: 0.5; }
.bg-corner-orbit-tl { animation: bg-drift-a 24s ease-in-out infinite; }
.bg-corner-orbit-tr { animation: bg-drift-b 30s ease-in-out infinite; }
.bg-corner-orbit-bl { animation: bg-drift-b 26s ease-in-out infinite; }
.bg-corner-orbit-br { animation: bg-drift-a 32s ease-in-out infinite; }
@keyframes bg-drift-a { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-10px); } }
@keyframes bg-drift-b { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(10px); } }
.bg-deco-svg {
  position: absolute;
  top: 0; left: 0;
  width: 100%;
  height: 100%;
  opacity: 0.18;
}
.bg-orbit-ring circle { opacity: 0.7; }
.bg-tick-ring {
  transform-origin: 0 0;
  animation: bg-spin-slow 90s linear infinite;
}
.bg-minute-ticks {
  transform-origin: 0 0;
  opacity: 0.5;
  animation: bg-spin-rev 140s linear infinite;
}
.bg-clock-hand-hour {
  transform-origin: 0 0;
  animation: bg-spin-slow 60s linear infinite;
}
.bg-clock-hand-min {
  transform-origin: 0 0;
  animation: bg-spin-slow 20s linear infinite;
}
.bg-clock-hand-sec {
  transform-origin: 0 0;
  animation: bg-spin-slow 6s linear infinite;
}
.bg-orbit-icon-a, .bg-orbit-icon-b, .bg-orbit-icon-c, .bg-orbit-icon-d {
  transform-origin: 0 0;
}
.bg-orbit-icon-a { animation: bg-spin-slow 45s linear infinite; }
.bg-orbit-icon-b { animation: bg-spin-rev 55s linear infinite; }
.bg-orbit-icon-c { animation: bg-spin-slow 32s linear infinite; }
.bg-orbit-icon-d { animation: bg-spin-rev 65s linear infinite; }
.bg-orbit-icon-label {
  fill: var(--text-dim);
  font-family: var(--mono);
  font-size: 7px;
  letter-spacing: 0.05em;
}
.bg-gear { transform-origin: center; }
.bg-gear-a { animation: bg-spin-slow 40s linear infinite; }
.bg-gear-b { animation: bg-spin-rev 30s linear infinite; }
.bg-gear-c { animation: bg-spin-slow 50s linear infinite; }
.bg-gear-d { animation: bg-spin-rev 70s linear infinite; }
.bg-gear-e { animation: bg-spin-slow 45s linear infinite; }
.bg-gear-f { animation: bg-spin-rev 55s linear infinite; }
.bg-gear-g { animation: bg-spin-slow 25s linear infinite; }
.bg-gear-h { animation: bg-spin-rev 80s linear infinite; }
.bg-gear-i { animation: bg-spin-slow 18s linear infinite; }
.bg-gear-j { animation: bg-spin-rev 34s linear infinite; }
.bg-orbit-label {
  fill: var(--gold);
  font-family: var(--mono);
  font-size: 9px;
  letter-spacing: 0.25em;
  text-anchor: middle;
  opacity: 0.6;
}
.bg-orbit-label-small {
  font-size: 7px;
  letter-spacing: 0.15em;
  opacity: 0.35;
}
.bg-deco-dot {
  animation: bg-twinkle 4s ease-in-out infinite;
}
@keyframes bg-twinkle { 0%, 100% { opacity: 0.2; } 50% { opacity: 0.9; } }
@keyframes bg-spin-slow { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
@keyframes bg-spin-rev { from { transform: rotate(360deg); } to { transform: rotate(0deg); } }

.bg-float-col {
  position: absolute;
  bottom: -10%;
  width: 14px;
  writing-mode: vertical-rl;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.3em;
  color: var(--ice-blue);
  opacity: 0.11;
  white-space: nowrap;
  animation: bg-float-up 34s linear infinite;
}
.bg-float-col-1 { left: 3%; animation-duration: 38s; }
.bg-float-col-2 { left: 20%; animation-duration: 46s; animation-delay: -8s; color: var(--gold); }
.bg-float-col-3 { left: 37%; animation-duration: 42s; animation-delay: -20s; }
.bg-float-col-4 { left: 54%; animation-duration: 50s; animation-delay: -14s; color: var(--gold); }
.bg-float-col-5 { left: 70%; animation-duration: 36s; animation-delay: -26s; }
.bg-float-col-6 { left: 85%; animation-duration: 44s; animation-delay: -4s; color: var(--gold); }
.bg-float-col-7 { left: 96%; animation-duration: 40s; animation-delay: -30s; }
@keyframes bg-float-up {
  from { transform: translateY(0); }
  to { transform: translateY(-140vh); }
}

.bg-epoch {
  position: absolute;
  bottom: 10px;
  left: 0; right: 0;
  text-align: center;
  font-family: var(--mono);
  font-size: 9px;
  letter-spacing: 0.15em;
  color: var(--text-dim);
  opacity: 0.35;
}

.site-name {
  font-family: var(--display);
  letter-spacing: 0.14em;
  font-size: 15px;
  color: var(--gold);
  text-align: center;
  text-transform: uppercase;
  cursor: pointer;
  background: none;
  border: none;
  padding: 10px;
  width: 100%;
}
.site-name:hover { color: var(--gold-bright); }

.panel {
  background: var(--bg-panel);
  border: 1px solid var(--panel-border);
  border-radius: 10px;
  padding: 28px;
  margin-top: 20px;
  position: relative;
  overflow: hidden;
  box-shadow: 0 0 22px -8px var(--alien-glow), inset 0 0 30px -20px var(--gold);
}

.panel::before {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 2px;
  background: linear-gradient(90deg, var(--gold-bright), var(--ice-blue));
  opacity: 0.65;
  box-shadow: 0 0 8px 1px var(--alien-glow);
}

@keyframes pulseDot {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.4; transform: scale(0.75); }
}
@keyframes pulseDotRing {
  0% { transform: scale(1); opacity: 0.5; }
  100% { transform: scale(2.6); opacity: 0; }
}
/* A tiny "alien" touch on the live status dot — a soft neon ring expanding
   and fading behind it, same live/pulsing feel as the chart's own dot,
   kept small and subtle per direct request ("tiny tiny bit, not too much"). */
#liveStatusDot { position: relative; }
#liveStatusDot::after {
  content: "";
  position: absolute; inset: 0; border-radius: 50%;
  background: inherit;
  animation: pulseDotRing 1.6s ease-out infinite;
}

.pos { color: var(--green); }
.neg { color: var(--red); }
.mut { color: var(--text-dim); }
.ice { color: var(--ice-blue); }

.center-screen {
  min-height: 80vh;
  display: flex;
  align-items: center;
  justify-content: center;
}

.lock-card {
  width: 100%;
  max-width: 380px;
  text-align: center;
}

h1.wordmark {
  font-family: var(--display);
  letter-spacing: 0.22em;
  font-size: 28px;
  color: var(--gold-bright);
  text-transform: uppercase;
  margin: 0 0 6px;
  text-shadow: 0 0 12px var(--gold), 0 0 26px var(--alien-glow);
}

.tagline {
  color: var(--text-dim);
  font-size: 12px;
  letter-spacing: 0.08em;
  margin-bottom: 28px;
}

input[type=text], input[type=password], textarea {
  width: 100%;
  background: rgba(5,7,12,0.6);
  border: 1px solid var(--panel-border);
  border-radius: 6px;
  color: var(--text-primary);
  font-family: var(--mono);
  padding: 11px 12px;
  font-size: 14px;
  margin-bottom: 12px;
}
textarea { min-height: 90px; resize: vertical; }
input::placeholder, textarea::placeholder { color: var(--text-dim); }

button.btn {
  width: 100%;
  background: linear-gradient(180deg, var(--gold-bright), var(--gold));
  border: none;
  border-radius: 6px;
  color: #0a0614;
  font-family: var(--mono);
  font-weight: 700;
  letter-spacing: 0.06em;
  padding: 12px;
  font-size: 13px;
  cursor: pointer;
  text-transform: uppercase;
  box-shadow: 0 0 16px -4px var(--gold);
}
button.btn:hover { filter: brightness(1.12); box-shadow: 0 0 22px -2px var(--gold); }
button.btn.ghost {
  background: transparent;
  border: 1px solid var(--panel-border);
  color: var(--ice-blue);
  box-shadow: 0 0 10px -6px var(--alien-glow);
}
button.btn.danger {
  background: transparent;
  border: 1px solid var(--red);
  color: var(--red);
}
button.btn.go {
  background: linear-gradient(180deg, #5dffb0, #22c481);
  border: none;
  color: #04140c;
  box-shadow: 0 0 18px -4px rgba(93,255,176,0.6);
}
button.btn.go:hover { filter: brightness(1.1); }

.flash {
  color: var(--red);
  font-size: 12.5px;
  margin-bottom: 14px;
}
.flash.good { color: var(--green); }
.flash.bad { color: var(--red); }

.row { display: flex; justify-content: space-between; align-items: center; gap: 12px; }
/* MOBILE FIX: a flex item's default min-width is "auto", which lets long
   text overflow the row instead of wrapping — text just silently runs past
   the visible edge, especially on a narrow phone. This lets any text
   directly inside a .row shrink and wrap normally by default; short
   labels/buttons are unaffected since they were never wide enough to hit
   this in the first place. */
.row > span, .row > div, .row > p { min-width: 0; }
.dim { color: var(--text-dim); font-size: 12px; }
.gold { color: var(--gold); }

table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12.5px;
  margin-top: 10px;
  table-layout: fixed;
}
th, td {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
th, td { text-align: left; padding: 8px 6px; border-bottom: 1px solid rgba(198,160,74,0.12); }
th { color: var(--text-dim); font-weight: 500; text-transform: uppercase; letter-spacing: 0.05em; font-size: 10.5px; }

.badge {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 20px;
  font-size: 10.5px;
  letter-spacing: 0.04em;
}
.badge.active { background: rgba(76,175,125,0.15); color: var(--green); }
.badge.expired { background: rgba(209,100,100,0.15); color: var(--red); }

.section-title {
  font-family: var(--display);
  letter-spacing: 0.08em;
  color: var(--gold);
  font-size: 13px;
  text-transform: uppercase;
  margin: 0 0 14px;
}

.divider { height: 1px; background: var(--panel-border); margin: 24px 0; }

a.plain { color: var(--ice-blue); text-decoration: none; font-size: 12.5px; }

/* ---------- Recent trades: cards, not a table ----------
   A five-column table on a phone squeezes the ticker down to unreadable
   fragments like "…UL290015-15", which tells a person nothing about what
   the bot actually did. Each trade gets its own card instead, headed by
   the call in plain words rather than Kalshi's yes/no vocabulary. */
.trade-card {
  display: block;
  padding: 11px 13px;
  margin-bottom: 8px;
  border: 1px solid rgba(198,160,74,0.16);
  border-left: 3px solid var(--text-dim);
  border-radius: 8px;
  background: rgba(5,7,12,0.45);
}
.trade-card.win  { border-left-color: var(--green); }
.trade-card.loss { border-left-color: var(--red); }
.trade-card.open { border-left-color: var(--gold); }

.trade-top {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
}
.trade-call {
  font-size: 13.5px;
  letter-spacing: 0.03em;
  color: var(--text-primary);
}
.trade-call .arrow { font-size: 15px; line-height: 1; }
.trade-call.up   .arrow { color: var(--green); }
.trade-call.down .arrow { color: var(--red); }

.trade-pnl { font-size: 15px; white-space: nowrap; }
.trade-pnl.pos { color: var(--green); }
.trade-pnl.neg { color: var(--red); }
.trade-pnl.flat { color: var(--text-dim); }

.trade-outcome {
  display: inline-block;
  margin-top: 7px;
  padding: 2px 9px;
  border-radius: 20px;
  font-size: 10.5px;
  letter-spacing: 0.04em;
}
.trade-outcome.win  { background: rgba(76,175,125,0.15); color: var(--green); }
.trade-outcome.loss { background: rgba(209,100,100,0.15); color: var(--red); }
.trade-outcome.open { background: rgba(198,160,74,0.15); color: var(--gold); }

/* Facts wrap instead of overflowing — the whole reason the table failed. */
.trade-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 14px;
  margin-top: 8px;
  font-size: 11px;
  color: var(--text-dim);
}
.trade-meta b { color: var(--text-primary); font-weight: 500; }

/* ---------- Win rate + P&L ---------- */
.stat-block { flex: 1; min-width: 0; }

.wl-bar {
  display: flex;
  height: 6px;
  border-radius: 3px;
  overflow: hidden;
  margin-top: 6px;
  background: rgba(255,255,255,0.06);
}
.wl-bar .wins   { background: var(--green); }
.wl-bar .losses { background: var(--red); }

.stat-big { font-size: 17px; letter-spacing: 0.02em; }
.stat-big.pos { color: var(--green); }
.stat-big.neg { color: var(--red); }
.stat-sub { font-size: 10.5px; color: var(--text-dim); margin-top: 3px; }

@media (max-width: 520px) {
  .trade-call { font-size: 12.5px; }
  .trade-pnl  { font-size: 14px; }
  .trade-meta { font-size: 10.5px; gap: 3px 11px; }
  .stat-big   { font-size: 15px; }
  .row.stats-row { flex-wrap: wrap; gap: 14px; }
  .row.stats-row .stat-block { flex: 1 1 44%; }
}

/* ── SITE-WIDE MOBILE PASS ──
   Applies everywhere theme.css is loaded (dashboard, owner panel, lock,
   login) rather than one page at a time, since the same handful of layout
   assumptions (a header row that never wraps, fixed generous padding,
   14px form inputs) were causing cramped or overflowing pages across all
   of them, not just the dashboard. */
@media (max-width: 600px) {
  .wrap { padding: 20px 14px 48px; }
  .panel { padding: 18px 16px; margin-top: 14px; }
  /* .row is used for every page header (title + back-link) and several
     inline forms — on a phone these need to wrap instead of squeezing or
     overflowing the viewport horizontally. */
  .row { flex-wrap: wrap; gap: 8px; }
  /* iOS Safari zooms the whole page in when a focused input's font-size is
     under 16px — a well-known mobile annoyance that makes every form on the
     site feel broken the first time someone taps into it. */
  input[type=text], input[type=password], input[type=number],
  input[type=email], textarea, select { font-size: 16px; }
  button.btn { padding: 13px; font-size: 13px; }
  /* Any table not already given its own .scroll wrapper still gets one, so
     a wide table pushes the page into horizontal scroll instead of forcing
     the WHOLE layout wider than the phone screen. */
  table { display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; }
}

/* ROUNDED CORNERS ON CHART ALERT BOXES. Plotly.js doesn't expose a native
   "corner radius" option in its annotation config — the background box is
   always a flat SVG <rect>. This targets that rect directly (a stable,
   long-standing part of Plotly's internal rendering: annotations render as
   <g class="annotation"> containing a <rect class="bg">) and rounds it via
   the CSS rx/ry properties modern browsers support on SVG shapes. */
#priceChart .annotation .bg { rx: 6px; ry: 6px; }

/* Live indicator on a code card — shows at a glance that someone is
   actively using that code, which is what removed the need for a separate
   Active Sessions panel. */
.live-dot {
  display: inline-block; width: 8px; height: 8px; border-radius: 50%;
  background: var(--green); margin-left: 6px; vertical-align: middle;
  box-shadow: 0 0 6px 1px rgba(61,220,132,0.55);
  animation: pulseDot 1.6s ease-in-out infinite;
}
