:root {
  --bg: #0b0d12;
  --card: #141821;
  --card-2: #1b202b;
  --line: #262c39;
  --text: #eef1f6;
  --muted: #8a93a6;
  --accent: #3d8bfd;
  --ok: #22c55e;
  --warn: #f5b301;
  --bad: #ef4444;
  --zone: var(--line);
  --radius: 16px;
  --gap: 10px;
  color-scheme: dark;
}

* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; }
body {
  background: var(--bg);
  color: var(--text);
  font: 15px/1.3 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  -webkit-tap-highlight-color: transparent;
  -webkit-user-select: none;
  user-select: none;
  overscroll-behavior: none;
}
[hidden] { display: none !important; }

button, .primary, input {
  font: inherit;
  color: inherit;
}
button {
  cursor: pointer;
  border: 1px solid var(--line);
  background: var(--card-2);
  border-radius: 12px;
  padding: 10px 14px;
  touch-action: manipulation;
}
button:active { transform: scale(0.97); }
.ghost { background: transparent; }

/* ---- layout ------------------------------------------------------------ */

#app {
  height: 100dvh;
  display: flex;
  flex-direction: column;
  padding: max(8px, env(safe-area-inset-top)) max(10px, env(safe-area-inset-right))
    max(10px, env(safe-area-inset-bottom)) max(10px, env(safe-area-inset-left));
  gap: var(--gap);
}

.bar {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.brand { font-weight: 800; letter-spacing: 0.12em; margin-right: 6px; }
.spacer { flex: 1; }

.chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  border-radius: 999px;
  padding: 8px 14px;
  max-width: 42vw;
}
.chip-label { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dot { width: 10px; height: 10px; border-radius: 50%; background: var(--muted); flex: none; }
.chip[data-state="on"] .dot { background: var(--ok); }
.chip[data-state="busy"] .dot { background: var(--warn); animation: pulse 1s infinite alternate; }
.chip[data-state="error"] .dot { background: var(--bad); }
@keyframes pulse { to { opacity: 0.3; } }

.ftp { color: var(--muted); display: inline-flex; align-items: center; gap: 6px; }
.ftp input {
  width: 4.5em;
  background: var(--card-2);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 8px;
  text-align: center;
  -webkit-user-select: text;
  user-select: text;
}

.banner {
  background: color-mix(in srgb, var(--warn) 18%, var(--card));
  border: 1px solid color-mix(in srgb, var(--warn) 50%, transparent);
  border-radius: 12px;
  padding: 8px 12px;
}

.dash {
  flex: 1;
  min-height: 0;
  display: grid;
  gap: var(--gap);
  grid-template-columns: repeat(6, minmax(0, 1fr));
  grid-template-rows: 3fr 2fr 1.4fr auto;
}

.card {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 10px 14px;
  display: flex;
  flex-direction: column;
  min-height: 0;
  min-width: 0;
}
.card h2, .details h3 {
  margin: 0;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
}
.card .value {
  flex: 1;
  min-height: 0;
  container-type: size;
  display: flex;
  align-items: center;
  justify-content: center;
}
.card .value span {
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  font-size: min(80cqh, 24cqw);
  letter-spacing: -0.02em;
}
.card .sub { text-align: center; color: var(--muted); font-size: 13px; min-height: 1.3em; }

.power { grid-column: span 4; border-width: 2px; border-color: var(--zone); }
.power .value span { color: var(--zone-text, var(--text)); }
.control { grid-column: span 2; border-color: var(--zone, var(--line)); }
.control .value span { font-size: min(80cqh, 30cqw); color: var(--zone-text, var(--text)); }
.small { grid-column: span 2; }
.graph { grid-column: 1 / -1; }
.graph canvas { flex: 1; min-height: 0; width: 100%; display: block; margin-top: 4px; }

.modes, .steps {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 6px;
  margin-top: 8px;
}
.modes button { padding: 10px 4px; font-weight: 600; }
.modes button[aria-pressed="true"] { background: var(--accent); border-color: var(--accent); color: #fff; }
.steps button { padding: 12px 4px; font-weight: 700; font-size: 18px; }
.steps button.big { font-size: 26px; padding: 8px 4px; }
.steps button:disabled { opacity: 0.35; }

.stats {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: repeat(8, minmax(0, 1fr));
  gap: var(--gap);
}
.stat {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 8px 6px;
  text-align: center;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.stat span { color: var(--muted); font-size: 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.stat b { font-size: 18px; font-variant-numeric: tabular-nums; white-space: nowrap; }

@media (orientation: portrait) {
  .dash { grid-template-rows: 3fr 3fr 1.6fr 1.6fr auto; }
  .power, .control { grid-column: 1 / -1; }
  .control { display: grid; grid-template-columns: 1fr 1fr; grid-template-rows: auto 1fr auto; column-gap: 14px; }
  .control h2 { grid-column: 1 / -1; }
  .control .value { grid-column: 1; grid-row: 2; }
  .control .sub { grid-column: 1; grid-row: 3; }
  .control .modes { grid-column: 2; grid-row: 2; align-self: center; grid-template-columns: repeat(2, 1fr); }
  .control .steps { grid-column: 2; grid-row: 3; }
  .stats { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
@media (max-width: 700px) {
  .stats { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .chip { max-width: 60vw; }
}

/* ---- details drawer ---------------------------------------------------- */

.details {
  position: fixed;
  inset: 0;
  background: rgb(0 0 0 / 0.55);
  display: flex;
  justify-content: flex-end;
  z-index: 10;
}
.details-inner {
  width: min(520px, 100%);
  height: 100%;
  background: var(--card);
  border-left: 1px solid var(--line);
  padding: max(16px, env(safe-area-inset-top)) 16px 16px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  -webkit-user-select: text;
  user-select: text;
}
.details dl { display: grid; grid-template-columns: auto 1fr; gap: 4px 12px; margin: 8px 0 0; }
.details dt { color: var(--muted); }
.details dd { margin: 0; word-break: break-word; }
.log-wrap { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.log {
  flex: 1;
  overflow: auto;
  margin: 8px 0 0;
  padding: 0;
  list-style: none;
  font: 13px/1.45 ui-monospace, SFMono-Regular, Menlo, monospace;
}
.log time { color: var(--muted); margin-right: 8px; }
.log .ok { color: var(--ok); }
.log .warn { color: var(--warn); }
.log .bad { color: var(--bad); }
.log .info { color: #67c6e8; }
.close { align-self: flex-end; }

.toast {
  position: fixed;
  left: 50%;
  bottom: max(20px, env(safe-area-inset-bottom));
  transform: translateX(-50%);
  background: var(--card-2);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 10px 16px;
  max-width: 90vw;
  z-index: 20;
  box-shadow: 0 10px 30px rgb(0 0 0 / 0.4);
}
.toast.bad { border-color: var(--bad); }
.toast.warn { border-color: var(--warn); }

/* ---- unsupported browser ------------------------------------------------- */

.gate {
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: 24px 16px;
}
.gate-card {
  width: min(460px, 100%);
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 20px;
  padding: 28px 24px;
  text-align: center;
  display: flex;
  flex-direction: column;
  gap: 12px;
  align-items: stretch;
}
.gate-icon img { border-radius: 18px; }
.gate h1 { margin: 4px 0 0; font-size: 22px; }
.gate p { margin: 0; color: var(--muted); }
.primary {
  display: block;
  background: var(--accent);
  color: #fff;
  text-decoration: none;
  font-weight: 700;
  border-radius: 12px;
  padding: 14px;
}
.gate-url {
  font: 13px ui-monospace, SFMono-Regular, Menlo, monospace;
  color: var(--text) !important;
  background: var(--card-2);
  border-radius: 10px;
  padding: 10px;
  word-break: break-all;
  -webkit-user-select: all;
  user-select: all;
}
.card .value span.empty { color: var(--line); font-weight: 600; font-size: min(40cqh, 14cqw); }

/* Phones, and portrait tablets shorter than ~1050px (an 8" Fire tablet in Silk): there isn't room to fit everything
   on one screen, so the page scrolls and each card is as tall as its content (otherwise the control card's buttons
   spill over the cards below). */
@media (max-width: 600px), (max-height: 600px), (orientation: portrait) and (max-height: 1050px) {
  #app { height: auto; min-height: 100dvh; }
  .dash { flex: none; grid-template-rows: none; grid-auto-rows: auto; }
  .card { min-height: auto; }
  .card .value { flex: none; height: 72px; }
  .card .value span { font-size: min(80cqh, 30cqw); }
  .power .value { height: clamp(110px, 26vh, 200px); }
  .control { display: flex; }
  .control .value { height: clamp(80px, 16vh, 140px); }
  .control .modes { grid-template-columns: repeat(4, 1fr); align-self: stretch; }
  .graph canvas { flex: none; height: 120px; }
  .stat b { font-size: 15px; }
}
@media (max-height: 600px) and (min-width: 601px) {
  /* Phone in landscape: power and control side by side, 3 small cards below. */
  .power { grid-column: span 3; }
  .control { grid-column: span 3; }
}

.reconnect {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  background: color-mix(in srgb, var(--accent) 14%, var(--card));
  border-color: color-mix(in srgb, var(--accent) 45%, transparent);
}
.reconnect span { flex: 1 1 220px; }
.primary-btn { background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 700; }
.reconnect .ghost { padding: 8px 12px; }

/* Zwift Ride button icons under the on-screen controls' labels (app.js controllerBadges). */
.modes button, .steps button {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
}
.steps button { padding: 8px 4px; }
.steps button.big { font-size: 22px; padding: 6px 4px; }
.pad-icon { width: 18px; height: 18px; flex: none; pointer-events: none; }
.face {
  display: grid;
  place-items: center;
  border: 1.5px solid currentColor;
  border-radius: 50%;
  font-size: 10px;
  font-weight: 800;
  line-height: 1;
  opacity: 0.8;
}
.dpad rect { fill: currentColor; opacity: 0.22; }
.dpad rect.on { fill: var(--accent); opacity: 1; }
.steps button:disabled .pad-icon { opacity: 0.6; }

/* Wherever the one-screen layout is used, the control card is never shorter than its buttons: on a size that doesn't
   fit, the page scrolls a little instead of clipping them. */
.control { min-height: min-content; }
