/* ---------------------------------------------------------------- fonts */
/* Both SIL OFL (see static/vendor/fonts/OFL.txt), Latin subset. Served locally so they work offline.
   Antonio: display face. Tall and condensed, the LCARS look; big counters fit a phone.
   Atkinson Hyperlegible Next: text face, drawn for legibility. */
@font-face {
  font-family: 'Antonio';
  font-style: normal;
  font-display: swap;
  font-weight: 100 700;
  src: url(/static/vendor/fonts/antonio.woff2) format('woff2');
}
/* Text: Atkinson's letters with Antonio's digits would be too narrow; keep Atkinson whole. */
@font-face {
  font-family: 'Text';
  font-style: normal;
  font-display: swap;
  font-weight: 200 800;
  src: url(/static/vendor/fonts/atkinson-hyperlegible-next.woff2) format('woff2');
}

/* ---------------------------------------------------------------- tokens */
/* LCARS, but practical: a black screen framed by rounded bars in soft orange, lilac and
   periwinkle; labels in tall capitals. The light theme keeps the frame on warm paper.
   Each state brings its own colour as --c (set inline by the scripts); everything that
   belongs to a state is drawn in it. */
:root {
  color-scheme: light;
  --bg: #f3efe7;
  --surface: #fffcf6;
  --surface-2: #e7e1d5;
  --surface-3: #d6cebf;
  --text: #1b1712;
  --text-2: #4b4338;
  --muted: #847b6e;
  --line: #ddd5c7;
  --grid: #e4ddd0;
  --axis: #b5ab9b;
  --accent: #ff9900;
  --accent-ink: #a85a00; /* the accent as text on the page */
  --danger: #c0362c;
  --hatch: rgba(27, 23, 18, .08);
  --on-c: #000; /* text on a solid frame or state colour: all of them are light */

  /* Frame colours. */
  --frame-1: #ff9900;
  --frame-2: #cc99cc;
  --frame-3: #9999ff;
  --frame-4: #ffcc99;
  --frame-dim: 45%; /* how much colour a frame block keeps when it isn't the current one */

  --rest-mix: 26%; /* state buttons at rest */
  --ink-mix: 55%; /* a state's colour as text: mixed with black so it reads on paper */
  --tl-tint: 42%;

  --tabbar-h: 46px;
  --display: 'Antonio', 'Arial Narrow', sans-serif;
  --text-font: 'Text', system-ui, sans-serif;
  --pad: 16px; /* side gutter on the phone */
  --r: 999px; /* pill ends */
  font-family: var(--text-font);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --bg: #000;
    --surface: #0f0e12;
    --surface-2: #1d1b22;
    --surface-3: #2c2933;
    --text: #f5ecdc;
    --text-2: #c8bfae;
    --muted: #8a8276;
    --line: #26232b;
    --grid: #1c1a20;
    --axis: #48434f;
    --accent-ink: #ff9900;
    --danger: #ff6655;
    --hatch: rgba(245, 236, 220, .07);
    --frame-dim: 38%;
    --rest-mix: 20%;
    --ink-mix: 100%;
    --tl-tint: 30%;
  }
}
:root[data-theme="dark"] {
  color-scheme: dark;
  --bg: #000; --surface: #0f0e12; --surface-2: #1d1b22; --surface-3: #2c2933;
  --text: #f5ecdc; --text-2: #c8bfae; --muted: #8a8276; --line: #26232b; --grid: #1c1a20; --axis: #48434f;
  --accent-ink: #ff9900; --danger: #ff6655; --hatch: rgba(245, 236, 220, .07);
  --frame-dim: 38%; --rest-mix: 20%; --ink-mix: 100%; --tl-tint: 30%;
}

/* ---------------------------------------------------------------- base */
* { box-sizing: border-box; }
html, body { margin: 0; height: 100%; }
body {
  background: var(--bg);
  color: var(--text);
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
  -webkit-text-size-adjust: 100%;
  overscroll-behavior: none;
}
body.sheet-open { overflow: hidden; }
button {
  font: inherit; color: inherit; background: none; border: 0; border-radius: 0; padding: 0; cursor: pointer;
  touch-action: manipulation; user-select: none; -webkit-user-select: none;
}
button:disabled { cursor: default; }
:focus-visible { outline: 2px solid var(--frame-3); outline-offset: 2px; }
h1, h2, h3, h4 { margin: 0; font-family: var(--display); font-weight: 600; text-transform: uppercase; letter-spacing: .03em; }
.icon { width: 22px; height: 22px; flex: none; }
.muted { color: var(--muted); }

/* Pinned to the visible viewport rather than sized with 100vh/100dvh: some Android
   browsers count the area behind the system navigation bar in those units (or don't
   support dvh), which pushed the tab bar off screen. Only <main> scrolls. */
html, body { overflow: hidden; overscroll-behavior: none; }
#app {
  position: fixed; inset: 0;
  display: flex; flex-direction: column;
  max-width: 560px; margin: 0 auto;
}

/* Top bar: ( FLUX ━━━━━━━━━━━━ ) [status] (+) */
.topbar {
  display: flex; align-items: center; gap: 6px;
  padding: calc(env(safe-area-inset-top) + 10px) var(--pad) 8px;
}
.topbar h1, .login h1 {
  flex: 1; min-width: 0;
  display: flex; align-items: center; gap: 8px;
  font-size: 24px; font-weight: 600; letter-spacing: .1em; line-height: 1; color: var(--accent-ink);
}
.topbar h1::before, .topbar h1::after {
  content: ""; height: 16px; background: var(--frame-2); flex: none;
}
.topbar h1::before { width: 18px; border-radius: var(--r) 0 0 var(--r); }
.topbar h1::after { flex: 1; min-width: 12px; border-radius: 0 var(--r) var(--r) 0; }
.brand-icon { display: none; width: 34px; height: 34px; }
.add-state {
  width: 52px; height: 32px; border-radius: var(--r); background: var(--frame-3); color: var(--on-c);
}
.add-state .icon { width: 20px; height: 20px; }
.offline {
  flex: none; font-family: var(--display); text-transform: uppercase; letter-spacing: .05em;
  font-size: 14px; font-weight: 600; color: var(--on-c); background: var(--danger);
  padding: 5px 12px; border-radius: var(--r);
}
.offline.pending { background: var(--frame-4); }
main {
  flex: 1; overflow-y: auto; -webkit-overflow-scrolling: touch;
  padding: 4px var(--pad) var(--pad);
}
.loading, .empty { color: var(--muted); padding: 40px 0; }

/* Tabs: a segmented LCARS bar along the bottom. The current one lights up. */
.tabbar {
  display: flex; gap: 4px; background: var(--bg);
  padding: 6px var(--pad) calc(env(safe-area-inset-bottom) + 8px);
}
.tabbar button {
  --c: var(--frame-2);
  flex: 1; height: var(--tabbar-h); min-width: 0;
  display: flex; align-items: flex-end; justify-content: flex-end; padding: 0 10px 5px;
  font-family: var(--display); font-size: 17px; font-weight: 500; text-transform: uppercase; letter-spacing: .05em;
  color: var(--text);
  background: color-mix(in srgb, var(--c) var(--frame-dim), var(--bg));
  transition: background .15s;
}
.tabbar button:nth-child(2) { --c: var(--frame-3); }
.tabbar button:nth-child(3) { --c: var(--frame-4); }
.tabbar button:nth-child(4) { --c: var(--frame-2); }
.tabbar button:first-child { border-radius: var(--r) 0 0 var(--r); }
.tabbar button:last-child { border-radius: 0 var(--r) var(--r) 0; }
.tabbar button.on { --c: var(--frame-1); background: var(--c); color: var(--on-c); font-weight: 700; }

/* Swatches: a small pill in the state's colour (--c). */
.dot { display: inline-block; width: 18px; height: 10px; border-radius: var(--r); flex: none; background: var(--c, var(--muted)); }
.dot.total { background: var(--text); }
.dot.gap { background: repeating-linear-gradient(-45deg, var(--axis) 0 2px, transparent 2px 4px); box-shadow: inset 0 0 0 1px var(--axis); }

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 48px; padding: 0 20px; border-radius: var(--r);
  background: var(--surface-2); color: var(--text);
  font-family: var(--display); font-weight: 600; font-size: 18px; text-transform: uppercase; letter-spacing: .05em;
}
.btn:active { background: var(--surface-3); }
.btn.small { min-height: 36px; padding: 0 14px; font-size: 15px; }
.btn.wide { width: 100%; }
.btn.primary { background: var(--frame-1); color: var(--on-c); }
.btn.primary:active { filter: brightness(.92); }
.btn.danger { color: var(--danger); background: transparent; box-shadow: inset 0 0 0 2px var(--danger); }
.btn.danger.armed { background: var(--danger); color: #fff; box-shadow: none; }
.btn:disabled { opacity: .45; }
.link { color: var(--text); font-weight: 700; font-size: 14px; padding: 6px 4px; text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1.5px; }
.link.danger { color: var(--danger); }
.icon-btn { width: 44px; height: 44px; display: grid; place-items: center; color: var(--text); border-radius: var(--r); }
.icon-btn:active { background: var(--surface-2); }
.icon-btn:disabled { opacity: .3; }
.toast.error {
  margin: 8px 0; padding: 10px 14px; border-radius: 0 var(--r) var(--r) 0; border-left: 8px solid var(--danger);
  background: color-mix(in srgb, var(--danger) 12%, transparent);
  color: var(--danger); font-size: 14px; font-weight: 600;
}
.legend { display: flex; flex-wrap: wrap; gap: 6px 16px; font-size: 13px; color: var(--text-2); padding: 8px 0 0; }
.legend span { display: inline-flex; align-items: center; gap: 6px; }

/* ---------------------------------------------------------------- now view */
.view-now { padding-bottom: 0; }
.now { display: flex; flex-direction: column; min-height: 100%; }
.cards { display: flex; flex-direction: column; padding-top: 4px; }
/* The counter sits in an LCARS elbow in the colour of what is running; grey when stopped. */
.card {
  --c: var(--muted);
  position: relative; display: block; width: 100%; text-align: left;
  padding: 8px 4px 12px 16px;
  border-left: 14px solid var(--c); border-top: 10px solid var(--c); border-top-left-radius: 36px;
  transition: border-color .3s;
}
.card-label {
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
  font-family: var(--display); font-size: 22px; font-weight: 600; text-transform: uppercase; letter-spacing: .06em;
  color: color-mix(in srgb, var(--c) var(--ink-mix), #000); line-height: 1.1;
}
.card.idle .card-label { color: var(--text-2); }
.card-edit { width: 18px; height: 18px; color: var(--muted); }
.counter {
  font-family: var(--display); font-weight: 600;
  /* Shrinks on short screens too, so Now fits without scrolling (svh: the viewport with all browser bars shown). */
  font-size: clamp(64px, min(26vw, 16svh - 20px), 124px); line-height: .95;
  font-variant-numeric: tabular-nums; margin: 4px 0 6px; white-space: nowrap;
}
.counter .unit {
  font-family: var(--text-font);
  font-size: .18em; font-weight: 700; color: var(--text-2);
  margin: 0 .7em 0 .25em;
}
.counter .unit:last-child { margin-right: 0; }
/* Seconds: smaller, so a counter with hours still fits a phone. */
.counter .num.sec { font-size: .56em; color: var(--text-2); }
.counter .num.sec + .unit { font-size: .16em; }
.counter.muted { color: var(--muted); }
.card-sub { font-size: 15px; color: var(--text-2); line-height: 1.35; font-variant-numeric: tabular-nums; }

/* One button per state, in a grid that takes whatever height the counter leaves (up to a cap),
   so Now never scrolls with a handful of states. Rounded on the outer ends, like LCARS panels. */
.modes {
  position: relative; flex: 1 1 0; max-height: 360px; min-height: 0;
  display: grid; grid-template-columns: 1fr 1fr; grid-auto-rows: minmax(64px, 1fr); gap: 4px;
  margin: auto 0 0; padding: 18px 0 10px;
}
.modes.many { grid-template-columns: repeat(3, 1fr); max-height: 440px; grid-auto-rows: minmax(56px, 1fr); }
.modes .empty { grid-column: 1 / -1; text-align: center; }
/* Floats just above the buttons (over the counter), so nothing shifts under a finger. */
.undo-toast {
  position: absolute; left: 0; right: 0; bottom: calc(100% - 16px); z-index: 3;
  display: flex; align-items: center; gap: 12px; padding: 5px 5px 5px 20px;
  overflow: hidden; border-radius: var(--r);
  background: var(--frame-4); color: var(--on-c);
  font-size: 15px; animation: undo-in .18s ease-out;
}
.undo-text { flex: 1; min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.undo-btn {
  min-height: 38px; padding: 0 18px; border-radius: var(--r);
  font-family: var(--display); font-weight: 700; font-size: 16px; text-transform: uppercase; letter-spacing: .06em;
  background: var(--on-c); color: var(--frame-4);
}
.undo-btn:active { filter: brightness(1.4); }
.undo-bar {
  position: absolute; left: 20px; right: 20px; bottom: 0; height: 3px;
  background: var(--frame-1); transform-origin: left; animation: undo-time 6s linear forwards;
}
@keyframes undo-in { from { opacity: 0; transform: translateY(6px); } }
@keyframes undo-time { to { transform: scaleX(0); } }
.mode {
  --c: var(--frame-3);
  position: relative; min-width: 0;
  display: flex; flex-direction: column; justify-content: flex-end; align-items: flex-end;
  padding: 10px 18px 10px;
  background: color-mix(in srgb, var(--c) var(--rest-mix), var(--bg));
  border-radius: 6px;
  text-align: right;
  transition: background .15s, color .15s;
}
.mode:nth-child(odd of .mode) { border-radius: 32px 6px 6px 32px; }
.mode:nth-child(even of .mode) { border-radius: 6px 32px 32px 6px; }
.modes.many .mode { border-radius: 22px; }
.mode:active { filter: brightness(.9); }
.mode-label {
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-family: var(--display); font-weight: 600; font-size: 28px; line-height: 1.05;
  text-transform: uppercase; letter-spacing: .05em;
  color: color-mix(in srgb, var(--c) var(--ink-mix), #000);
}
.modes.many .mode-label { font-size: 21px; }
.mode-hint {
  position: absolute; top: 12px; left: 22px; right: 14px; text-align: left;
  font-size: 13px; font-weight: 700; color: var(--text-2); font-variant-numeric: tabular-nums;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.modes.many .mode-hint { left: 14px; top: 8px; font-size: 12px; }
.mode.on { background: var(--c); }
.mode.on :is(.mode-label, .mode-hint) { color: var(--on-c); }
/* A blinking light on the running one, the way LCARS panels show what is live. */
.mode.on::after {
  content: ""; position: absolute; right: 18px; top: 14px; width: 10px; height: 10px; border-radius: 50%;
  background: var(--on-c); animation: blink 1.6s steps(1) infinite;
}
.modes.many .mode.on::after { top: 9px; right: 12px; }
@keyframes blink { 50% { opacity: .15; } }

/* ---------------------------------------------------------------- editor sheet */
.sheet-backdrop {
  position: fixed; inset: 0; z-index: 10;
  background: rgba(0, 0, 0, .55);
  display: flex; align-items: flex-end; justify-content: center;
  animation: fade .15s ease-out;
}
/* Framed by an elbow along its top and left edge. */
.sheet {
  width: 100%; max-width: 560px; max-height: 92dvh;
  display: flex; flex-direction: column;
  background: var(--surface);
  border-top: 10px solid var(--frame-2); border-left: 12px solid var(--frame-2); border-top-left-radius: 34px;
  padding: 2px var(--pad) calc(env(safe-area-inset-bottom) + 12px) 14px;
  animation: up .18s ease-out;
}
@keyframes fade { from { opacity: 0; } }
@keyframes up { from { transform: translateY(32px); opacity: .6; } }
.sheet-grip { width: 40px; height: 5px; border-radius: var(--r); background: var(--surface-3); margin: 6px auto 8px; }
.sheet-title { display: flex; align-items: baseline; gap: 10px; padding-bottom: 10px; min-width: 0; }
.sheet-title h2 { font-size: 30px; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sheet-title .dot { width: 30px; height: 16px; align-self: center; }
.sheet-sum { font-family: var(--display); font-weight: 600; font-size: 22px; color: var(--text-2); font-variant-numeric: tabular-nums; white-space: nowrap; }
.sheet-body { overflow-y: auto; display: flex; flex-direction: column; padding-bottom: 8px; }
.sheet-error { color: var(--danger); font-size: 14px; font-weight: 600; padding: 6px 0; }
.sheet-hint { margin: 0; padding: 8px 0; font-size: 14px; color: var(--text-2); line-height: 1.4; }
.sheet-sub { padding: 14px 0 8px; font-size: 13px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: .06em; }
.sheet-body .add-row { margin: 0; }
.sheet-actions { display: flex; gap: 8px; padding-top: 12px; border-top: 1px solid var(--line); }
.sheet-actions .btn { min-height: 52px; white-space: nowrap; padding: 0 16px; }
.sheet-actions .btn.primary { flex: 1; }
.gap-range { margin: 0; font-size: 16px; color: var(--text-2); font-variant-numeric: tabular-nums; }

/* Text fields: name of a state, the confirm word. */
.field { display: flex; flex-direction: column; gap: 6px; padding: 4px 0 12px; }
.text, .confirm-input {
  font: inherit; font-size: 18px; min-height: 50px; padding: 0 18px; width: 100%;
  border: 0; border-radius: var(--r); background: var(--surface-2); color: var(--text);
  box-shadow: inset 0 0 0 1.5px var(--axis);
}
.text:focus, .confirm-input:focus { outline: none; box-shadow: inset 0 0 0 2px var(--frame-3); }

/* Colour swatches for a state. */
.swatches { display: grid; grid-template-columns: repeat(6, 1fr); gap: 8px; padding: 4px 0 8px; }
.swatch {
  height: 40px; border-radius: var(--r); background: var(--c);
  transition: transform .1s;
}
.swatch.on { box-shadow: 0 0 0 3px var(--surface), 0 0 0 5px var(--text); }
.swatch:active { transform: scale(.94); }

/* A time field: a ruled row, not a box. */
.tf { border-top: 1px solid var(--line); padding: 10px 0 12px; }
.tf-head { display: flex; align-items: baseline; gap: 10px; }
.tf-label { font-family: var(--display); font-weight: 600; font-size: 16px; text-transform: uppercase; letter-spacing: .06em; color: var(--text-2); }
.tf-date { font-size: 14px; color: var(--muted); flex: 1; }
.tf-time {
  position: relative; display: block; text-align: center;
  font-family: var(--display); font-size: 48px; font-weight: 600;
  font-variant-numeric: tabular-nums; line-height: 1.1; padding: 2px 0 6px;
}
.tf-time input {
  position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; font-size: 16px;
  -webkit-appearance: none; appearance: none;
}
.steps { display: grid; grid-template-columns: repeat(6, 1fr); gap: 6px; }
.step {
  min-height: 46px; border-radius: var(--r); background: var(--surface-2);
  font-weight: 800; font-size: 16px; font-variant-numeric: tabular-nums;
}
.step:active { background: var(--surface-3); }
.step:disabled { opacity: .35; }
button.tf-time { width: 100%; }
/* Editor time: −5 −1 [time] +1 +5 on one row. */
.tf-row { display: grid; grid-template-columns: 1fr 1fr auto 1fr 1fr; align-items: center; gap: 6px; padding-top: 6px; }
.tf-row .tf-time { font-size: 42px; padding: 0 6px; }
.tf-row .step { min-width: 0; min-height: 50px; }
.tf-row .step:first-child { border-radius: var(--r) 6px 6px var(--r); }
.tf-row .step:last-child { border-radius: 6px var(--r) var(--r) 6px; }

/* Wheel date/time picker (static/js/picker.js, iPhone only). */
.picker-backdrop {
  position: fixed; inset: 0; z-index: 15; background: rgba(0, 0, 0, .45);
  display: flex; align-items: flex-end; justify-content: center; animation: fade .15s ease-out;
}
.picker {
  width: 100%; max-width: 440px; display: flex; flex-direction: column; gap: 6px;
  padding: 0 8px calc(env(safe-area-inset-bottom) + 8px); animation: up .18s ease-out;
}
.picker-card { background: var(--surface); overflow: hidden; border-radius: 22px; }
.picker-card:first-child { border-top: 8px solid var(--frame-2); }
.picker-title { font-family: var(--display); font-size: 16px; font-weight: 600; text-transform: uppercase; letter-spacing: .06em; color: var(--text-2); padding: 12px 18px 4px; }
.wheels {
  position: relative; display: grid; grid-template-columns: 1.7fr 1fr 1fr; padding: 0 12px;
  -webkit-mask-image: linear-gradient(transparent, #000 30%, #000 70%, transparent);
  mask-image: linear-gradient(transparent, #000 30%, #000 70%, transparent);
}
.wheel-band {
  position: absolute; left: 8px; right: 8px; top: 80px; height: 40px; pointer-events: none;
  border-radius: var(--r); background: color-mix(in srgb, var(--frame-3) 22%, transparent);
}
.wheel {
  position: relative; height: 200px; overflow-y: scroll; scroll-snap-type: y mandatory;
  overscroll-behavior: contain; scrollbar-width: none; outline: none;
}
.wheel::-webkit-scrollbar { display: none; }
.wheel-item {
  height: 40px; line-height: 40px; scroll-snap-align: center; text-align: center;
  font-size: 21px; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; cursor: default;
}
.wheel.days .wheel-item { text-align: right; padding-right: 14px; }
.wheel-item.on { color: var(--text); font-weight: 700; }
.picker-btn {
  display: block; width: 100%; min-height: 56px;
  font-family: var(--display); font-size: 20px; font-weight: 600; text-transform: uppercase; letter-spacing: .06em;
}
.picker-btn.primary { background: var(--frame-1); color: var(--on-c); }
.picker-card.picker-btn { color: var(--text-2); }
.picker-btn:not(.primary):active { background: var(--surface-2); }
.tf-ongoing { display: flex; align-items: center; justify-content: space-between; padding-top: 8px; }
.pill {
  padding: 6px 14px; border-radius: var(--r);
  font-family: var(--display); font-weight: 600; font-size: 15px; text-transform: uppercase; letter-spacing: .06em;
}
.pill.live { background: var(--frame-1); color: var(--on-c); }
.pill.live::before {
  content: ""; display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: currentColor;
  margin-right: 8px; vertical-align: 2px; animation: blink 1.6s steps(1) infinite;
}

/* ---------------------------------------------------------------- segmented controls */
/* Week/Day, the stats period, the theme and state chips: LCARS pills; the chosen one lit. */
.seg-ctl, .theme-pick { display: flex; gap: 3px; }
.chips { display: flex; gap: 6px; }
.seg-ctl button, .chip, .theme-pick button {
  min-height: 40px; padding: 0 16px;
  font-family: var(--display); font-weight: 600; font-size: 16px; text-transform: uppercase; letter-spacing: .05em;
  color: var(--text-2); background: var(--surface-2); white-space: nowrap;
}
.seg-ctl button:first-child, .theme-pick button:first-child { border-radius: var(--r) 4px 4px var(--r); }
.seg-ctl button:last-child, .theme-pick button:last-child { border-radius: 4px var(--r) var(--r) 4px; }
.seg-ctl button.on, .theme-pick button.on { background: var(--frame-1); color: var(--on-c); }
.chip { --c: var(--frame-3); border-radius: var(--r); }
.chip.on { background: var(--c); color: var(--on-c); }
/* State chips: tinted in their own colour. */
.state-chips { flex-wrap: wrap; padding: 2px 0 10px; }
.state-chips .chip {
  text-transform: none; letter-spacing: 0; font-family: var(--text-font); font-weight: 700; font-size: 15px;
  background: color-mix(in srgb, var(--c) var(--rest-mix), var(--surface));
  color: color-mix(in srgb, var(--c) var(--ink-mix), #000);
}
.state-chips .chip.on { background: var(--c); color: var(--on-c); }

/* ---------------------------------------------------------------- history */
.toolbar { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding-top: 4px; }
.navbar { display: flex; align-items: center; justify-content: space-between; padding: 8px 0 6px; margin: 0 -10px; }
.navbar h2 { font-size: 28px; flex: 1; text-align: center; }

.week { --hour: 24px; user-select: none; }
.week-head { display: grid; grid-template-columns: 22px repeat(7, 1fr); gap: 3px; position: sticky; top: -4px; background: var(--bg); z-index: 2; padding: 4px 0; }
.wd { display: flex; flex-direction: column; align-items: center; padding: 4px 0; font-size: 11px; color: var(--muted); border-radius: 10px; }
.wd b { font-family: var(--display); font-size: 20px; font-weight: 600; color: var(--text); }
.wd.today { background: var(--frame-1); color: var(--on-c); }
.wd.today b { color: var(--on-c); }
.week-body { display: grid; grid-template-columns: 22px repeat(7, 1fr); gap: 3px; height: calc(24 * var(--hour)); }
.hours { position: relative; }
.hours span { position: absolute; right: 3px; transform: translateY(-50%); font-size: 10px; color: var(--muted); font-variant-numeric: tabular-nums; }
.wcol {
  position: relative; background: var(--surface); border-radius: 4px;
  background-image: repeating-linear-gradient(to bottom, transparent 0 calc(3 * var(--hour) - 1px), var(--grid) calc(3 * var(--hour) - 1px) calc(3 * var(--hour)));
}
.blk { position: absolute; left: 2px; right: 2px; min-height: 3px; border-radius: 3px; background: var(--c, var(--muted)); }
.blk::after { content: ""; position: absolute; inset: -4px -2px; }
.blk.open { border-bottom: 2px dashed var(--bg); }
.now-line { position: absolute; left: -2px; right: -2px; height: 2px; background: var(--frame-1); pointer-events: none; }

/* Day totals: tracked, then the states with the most time. */
.day-sum { display: grid; grid-template-columns: repeat(auto-fit, minmax(68px, 1fr)); margin: 4px 0 12px; gap: 4px; }
.day-sum div {
  padding: 6px 10px 8px; display: flex; flex-direction: column; gap: 1px; min-width: 0;
  background: color-mix(in srgb, var(--c, var(--text)) 10%, var(--surface));
  border-left: 6px solid var(--c, var(--text)); border-radius: 0 14px 14px 0;
}
.day-sum b { font-family: var(--display); font-weight: 600; font-size: 20px; line-height: 1.1; white-space: nowrap; }
.day-sum small { font-size: 12px; color: var(--text-2); order: 2; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.day-sum .dot { display: none; }
.add-row { display: grid; grid-template-columns: 1fr; gap: 8px; margin: 14px 0 4px; }
.add-row .icon { width: 18px; height: 18px; }
.history.day .navbar { position: sticky; top: -4px; z-index: 5; background: var(--bg); }

/* Day timeline (static/js/timeline.js). --pph = px per hour (zoom); --y/--h = position in px,
   set by the script (the hour scale stretches where short blocks were given room). */
.tl-wrap { display: grid; padding: 12px 0 20px; }
.tl-wrap > * { grid-area: 1 / 1; }
.tl {
  --gutter: 44px;
  --stick: 44px; /* where block labels stop under the sticky day header */
  position: relative; /* height set inline */
  touch-action: pan-y; user-select: none; -webkit-user-select: none;
}
.tl-hour { position: absolute; left: var(--gutter); right: 0; top: var(--y); border-top: 1px solid var(--grid); }
.tl-hour span {
  position: absolute; right: calc(100% + 6px); top: 0; transform: translateY(-50%);
  font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap;
}
.tl[data-every="2"] .tl-hour:not(.h2) span, .tl[data-every="3"] .tl-hour:not(.h3) span { visibility: hidden; }

/* An entry: a bar in its state's colour, with a solid cap on the left. */
.tl-blk {
  --c: var(--muted);
  position: absolute; left: calc(var(--gutter) + 4px); right: 0;
  top: calc(var(--y) + 1px); height: calc(var(--h) - 2px); /* --y, --h from timeline.js */
  container-type: size; display: flex; align-items: center; overflow: clip;
  padding: 0 12px; text-align: left; color: var(--text); font: inherit;
  background: color-mix(in srgb, var(--c) var(--tl-tint), var(--surface));
  border-left: 8px solid var(--c); border-radius: 8px 4px 4px 8px;
}
.tl-blk[hidden] { display: none; }
/* Untracked: nothing recorded, so it's hatched rather than filled. */
.tl-blk.gap {
  background: repeating-linear-gradient(-45deg, transparent 0 6px, var(--hatch) 6px 7.5px);
  border-left: 0; color: var(--muted);
}
.tl-blk.open { border-bottom: 2px dashed var(--c); }
.tl-blk:active { filter: brightness(0.96); }
.tl-txt { display: flex; flex-direction: column; gap: 2px; width: 100%; min-width: 0; }
.tl-line { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; font-size: 14px; line-height: 16px; }
.tl-line b { font-weight: 800; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tl-blk.gap .tl-line b { font-weight: 500; }
.tl-blk.gap :is(.tl-dur, .tl-sub) { color: var(--muted); }
.tl-dur { flex: none; font-size: 13px; font-weight: 700; color: color-mix(in srgb, currentColor 72%, transparent); font-variant-numeric: tabular-nums; }
.tl-sub { font-size: 12px; line-height: 14px; color: color-mix(in srgb, currentColor 72%, transparent); font-variant-numeric: tabular-nums; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
@container (height < 18px) { .tl-txt { display: none; } }
@container (height < 36px) { .tl-sub { display: none; } }
@container (height < 24px) { .tl-line { font-size: 12px; line-height: 14px; } .tl-dur { font-size: 11px; } }
/* Tall blocks: label at the top, and it stays in view while the block scrolls by. */
@container (height >= 56px) { .tl-txt { align-self: flex-start; position: sticky; top: var(--stick); padding: 8px 0; } }

.tl-now { position: absolute; left: var(--gutter); right: 0; top: calc(var(--y) - 1px); height: 2px; background: var(--frame-1); z-index: 2; pointer-events: none; }
.tl-now span {
  position: absolute; right: calc(100% - 4px); top: 50%; transform: translateY(-50%);
  background: var(--frame-1); color: var(--on-c); font-size: 10px; font-weight: 800; padding: 2px 5px;
  border-radius: var(--r) 0 0 var(--r); font-variant-numeric: tabular-nums;
}
/* Add an entry after the last one: just below the now line. */
.tl-add { position: absolute; left: calc(var(--gutter) + 4px); top: calc(var(--y) + 10px); z-index: 3; display: flex; gap: 8px; }
.tl-add .btn { background: var(--surface-2); box-shadow: 0 0 0 3px var(--bg); }
.tl-add .icon { width: 16px; height: 16px; }
.tl-empty { position: absolute; left: var(--gutter); right: 0; top: calc(var(--pph) * 7.5); margin: 0; text-align: center; color: var(--muted); }
.tl-zoom {
  align-self: end; justify-self: end; position: sticky; bottom: 12px; z-index: 4;
  display: flex; flex-direction: column; gap: 4px; margin-right: 6px;
}
.tl-zoom .icon-btn { background: var(--frame-3); color: var(--on-c); width: 48px; }
.tl-zoom .icon-btn:first-child { border-radius: 22px 22px 4px 4px; }
.tl-zoom .icon-btn:last-child { border-radius: 4px 4px 22px 22px; }

/* ---------------------------------------------------------------- stats */
.chips:not(.state-chips) { overflow-x: auto; padding: 1.5px; }
.chip { flex: none; }
.custom-range { display: flex; gap: 8px; margin-top: 10px; }
.custom-range label { flex: 1; display: flex; flex-direction: column; font-size: 13px; font-weight: 700; color: var(--text-2); gap: 4px; }
.custom-range input {
  font: inherit; font-size: 16px; padding: 8px 14px; border: 0; border-radius: var(--r);
  background: var(--surface-2); color: var(--text); min-height: 44px; width: 100%;
}
.period-note { font-size: 14px; color: var(--text-2); margin: 10px 0 0; }
/* Sections open with an LCARS header bar: ( TITLE ━━━━━━━━━ ). */
.stats section, .settings section { --sec: var(--frame-2); margin-top: 28px; }
.stats section:nth-of-type(4n + 2), .settings section:nth-of-type(4n + 2) { --sec: var(--frame-3); }
.stats section:nth-of-type(4n + 3), .settings section:nth-of-type(4n + 3) { --sec: var(--frame-4); }
.stats section:nth-of-type(4n), .settings section:nth-of-type(4n) { --sec: var(--frame-1); }
.stats h3, .settings h3 {
  display: flex; align-items: center; gap: 10px;
  font-size: 26px; line-height: 1; margin-bottom: 14px; color: var(--text);
}
.stats h3::before, .stats h3::after, .settings h3::before, .settings h3::after {
  content: ""; height: 18px; background: var(--sec); flex: none;
}
.stats h3::before, .settings h3::before { width: 22px; border-radius: var(--r) 0 0 var(--r); }
.stats h3::after, .settings h3::after { flex: 1; border-radius: 0 var(--r) var(--r) 0; }
.stats h4 { font-size: 16px; font-weight: 600; color: var(--text-2); margin: 22px 0 8px; letter-spacing: .06em; }
.tiles { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.tile {
  --c: var(--frame-3);
  padding: 8px 12px 10px; min-width: 0;
  border-left: 8px solid var(--c); border-radius: 0 16px 16px 0;
  background: color-mix(in srgb, var(--c) 9%, var(--surface));
}
.tile-label { font-size: 13px; font-weight: 700; color: var(--text-2); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tile-value { font-family: var(--display); font-size: 30px; font-weight: 600; line-height: 1.05; margin: 4px 0 3px; font-variant-numeric: tabular-nums; }
.tile-sub { font-size: 13px; color: var(--muted); line-height: 1.3; }

.chart svg { display: block; width: 100%; height: auto; overflow: visible; }
.chart .grid { stroke: var(--grid); stroke-width: 1; }
.chart .axis { stroke: var(--axis); stroke-width: 1.5; }
.chart .tick { fill: var(--muted); font-size: 10px; font-variant-numeric: tabular-nums; }
.chart .hit { fill: transparent; cursor: pointer; }
.chart .dim .mark { opacity: .3; }
.chart .cursor { fill: none; stroke: var(--text); stroke-width: 1.5; }
.chart .avg-bg { fill: var(--surface-2); }
.mark { fill: var(--c, var(--muted)); background: var(--c, var(--muted)); }
.mark.gap { background: repeating-linear-gradient(-45deg, transparent 0 4px, var(--hatch) 4px 6px), var(--surface-2); }
.readout { font-size: 14px; color: var(--text-2); padding: 8px 0 0; min-height: 28px; }

.split-bar { display: flex; gap: 2px; height: 30px; border-radius: var(--r); overflow: hidden; }
.split-bar .mark { min-width: 2px; }
.split-table, .daily { width: 100%; border-collapse: collapse; font-size: 15px; font-variant-numeric: tabular-nums; }
.split-table { margin-top: 12px; }
.split-table th, .daily th { font-size: 12px; font-weight: 700; color: var(--muted); text-align: right; padding: 4px 4px; white-space: nowrap; }
.daily th .dot { width: 10px; height: 6px; margin-right: 4px; vertical-align: 1px; }
.split-table td, .daily td { text-align: right; padding: 7px 4px; border-top: 1px solid var(--line); white-space: nowrap; }
.split-table th:first-child, .split-table td:first-child, .daily th:first-child, .daily td:first-child { text-align: left; padding-left: 0; }
.split-table th:last-child, .split-table td:last-child, .daily th:last-child, .daily td:last-child { padding-right: 0; }
.split-table td:first-child { white-space: normal; }
.split-table td:first-child .dot { margin-right: 10px; vertical-align: 0; }
.split-table tr.sum td { color: var(--text-2); }
.split-table tr.sum:first-of-type td, .split-table tr:not(.sum) + tr.sum td { border-top: 2px solid var(--axis); }
.table-wrap { overflow-x: auto; }
.footnote { font-size: 12px; color: var(--muted); margin: 8px 0 2px; }

/* ---------------------------------------------------------------- iOS status bar */
/* The installed app uses black-translucent, which always draws white status-bar
   text; give it a dark band to sit on in light mode. Height is 0 outside iOS PWAs. */
:root { --statusbar: #1b1712; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) { --statusbar: #000; } }
:root[data-theme="dark"] { --statusbar: #000; }
body::before {
  content: ""; position: fixed; top: 0; left: 0; right: 0; z-index: 20;
  height: env(safe-area-inset-top); background: var(--statusbar);
}

/* ---------------------------------------------------------------- settings */
.settings section:first-child { margin-top: 8px; }
.theme-pick button {
  flex: 1; min-width: 0; padding: 0 2px; min-height: 76px;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 6px;
  font-size: 15px;
}
.theme-pick button .icon { width: 24px; height: 24px; }
.schedule { display: flex; flex-direction: column; margin-top: 12px; }
.schedule-row, .setting-row {
  display: flex; align-items: center; gap: 12px; min-height: 58px;
  border-bottom: 1px solid var(--line); font-weight: 700; color: var(--text-2);
}
.schedule-row:first-child, .setting-row { border-top: 1px solid var(--line); }
.schedule-row span, .setting-row > span { flex: 1; }
.schedule-row input {
  font: inherit; font-family: var(--display); font-size: 24px; font-weight: 600;
  font-variant-numeric: tabular-nums; color: var(--text);
  min-height: 44px; padding: 0 14px; border: 0; border-radius: var(--r); background: var(--surface-2);
}
.setting-desc { font-size: 14px; color: var(--text-2); line-height: 1.45; margin: 10px 0; max-width: 60ch; }
.setting-ok { font-size: 14px; color: var(--text); margin: 0 0 10px; }

/* States: one row each; the name opens its editor, the arrows reorder. */
.state-list { list-style: none; margin: 0 0 10px; padding: 0; display: flex; flex-direction: column; gap: 4px; }
.state-row { display: flex; align-items: center; gap: 2px; }
.state-name {
  flex: 1; min-width: 0; min-height: 50px; display: flex; align-items: center; gap: 12px; padding: 0 14px 0 0;
  background: color-mix(in srgb, var(--c) var(--rest-mix), var(--bg)); border-radius: var(--r) 6px 6px var(--r);
  font-weight: 700; font-size: 16px; text-align: left;
}
.state-name .dot { width: 34px; height: 50px; border-radius: var(--r) 0 0 var(--r); }
.state-name span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.state-edit { width: 16px; height: 16px; color: var(--muted); }
.state-list.archived .state-name { background: var(--surface-2); color: var(--text-2); }
.state-list.archived .dot { opacity: .5; }
.archived-toggle { display: block; margin: 10px 0 4px; }

.account { display: flex; align-items: center; gap: 12px; padding: 6px 0; }
.account-pic { width: 40px; height: 40px; border-radius: 50%; flex: none; background: var(--surface-2); }
.account-who { flex: 1; min-width: 0; display: flex; flex-direction: column; font-size: 14px; color: var(--text-2); }
.account-who b { font-size: 16px; color: var(--text); }
.account-who span { overflow: hidden; text-overflow: ellipsis; }

/* ---------------------------------------------------------------- login */
.login {
  flex: 1; grid-area: 1 / 1 / -1 / -1; /* fills #app, whether it's the phone column or the desktop grid */
  display: flex; flex-direction: column; justify-content: flex-end; overflow-y: auto;
  padding: calc(env(safe-area-inset-top) + 24px) 24px calc(env(safe-area-inset-bottom) + 48px);
}
.login-card {
  width: 100%; max-width: 400px; padding: 18px 0 0 20px;
  border-left: 16px solid var(--frame-1); border-top: 12px solid var(--frame-1); border-top-left-radius: 44px;
  display: flex; flex-direction: column; align-items: flex-start; gap: 12px;
}
.login-icon { width: 72px; height: 72px; }
.login h1 { font-size: 32px; flex: none; }
.login-text { color: var(--text-2); font-size: 16px; margin: 0 0 8px; }
.login-google { min-height: 44px; }
.login-note { font-size: 13px; color: var(--muted); }
.confirm-box { border: 2px solid var(--danger); border-radius: 20px; padding: 14px 16px; }
.confirm-box p { margin: 0 0 12px; line-height: 1.4; }
.confirm-label { display: flex; flex-direction: column; gap: 8px; font-size: 14px; color: var(--text-2); }
.confirm-actions { display: flex; gap: 8px; margin-top: 12px; }
.confirm-actions .btn { flex: 1; min-height: 52px; }


/* ---------------------------------------------------------------- desktop */
@media (hover: hover) {
  .card:hover .card-edit { color: var(--text); }
  .mode:not(.on):hover { filter: brightness(1.12); }
  .btn:hover, .step:hover, :is(.seg-ctl button, .chip, .theme-pick button):not(.on):hover { filter: brightness(1.1); }
  .btn:disabled:hover { filter: none; }
  .icon-btn:hover { background: var(--surface-2); }
  .add-state:hover, .tl-zoom .icon-btn:hover { background: var(--frame-3); filter: brightness(1.1); }
  .tabbar button:not(.on):hover { background: color-mix(in srgb, var(--c) 65%, var(--bg)); }
  .state-name:hover, .swatch:hover { filter: brightness(1.1); }
  .blk:hover { filter: brightness(1.12); }
  .tl-blk:hover { filter: brightness(1.06); }
}

@media (min-width: 900px) {
  /* LCARS sidebar on the left: an elbow at the top (brand), the nav as a column of blocks,
     a filler block running down to a rounded foot. Content on the right. */
  #app {
    max-width: none; margin: 0;
    display: grid; grid-template-columns: 200px minmax(0, 1fr); grid-template-rows: auto 1fr;
    grid-template-areas: "head main" "nav main";
    padding-left: 16px;
  }
  .topbar {
    --frame: var(--frame-3);
    grid-area: head; position: relative; z-index: 6;
    flex-direction: column; align-items: flex-end; justify-content: flex-end; gap: 10px;
    min-height: 132px; margin-top: 16px; padding: 18px 14px 10px;
    background: var(--frame); border-top-left-radius: 64px 54px;
  }
  /* The elbow's arm along the top of the content, with the inner curve under it. */
  .topbar::before {
    content: ""; position: absolute; left: 100%; top: 0; height: 22px;
    width: calc(100vw - 200px - 16px - 24px); background: var(--frame);
    border-radius: 0 var(--r) var(--r) 0;
    box-shadow: 0 -16px 0 var(--bg); /* hide what scrolls past above the arm */
  }
  .topbar::after {
    content: ""; position: absolute; left: 100%; top: 22px; width: 28px; height: 28px;
    background: radial-gradient(circle at 100% 100%, transparent 27.5px, var(--frame) 28px);
  }
  .topbar h1 { flex: none; color: var(--on-c); font-size: 26px; flex-direction: column; align-items: flex-end; gap: 10px; }
  .topbar h1::before, .topbar h1::after { display: none; }
  .brand-icon { display: block; width: 40px; height: 40px; }
  .add-state { background: var(--on-c); color: var(--frame-3); }
  .tabbar {
    grid-area: nav; flex-direction: column; gap: 4px; padding: 4px 0 16px;
  }
  .tabbar::after {
    content: ""; flex: 1; min-height: 40px; background: var(--frame-2); border-radius: 0 0 0 54px;
  }
  .tabbar button, .tabbar button:first-child, .tabbar button:last-child {
    flex: none; height: 60px; padding: 0 14px 6px; border-radius: 0; font-size: 20px;
  }
  main, main.view-now { grid-area: main; padding: 64px 36px 36px 28px; }

  /* Now: live panel stays put while the history scrolls beside it. */
  .dash {
    display: grid; grid-template-columns: minmax(340px, 460px) minmax(0, 1fr); gap: 40px;
    align-items: start; max-width: 1480px;
  }
  .dash-now { position: sticky; top: 0; }
  .dash .now { min-height: calc(100dvh - 110px); }
  .dash .modes { padding-top: 24px; }
  .dash .counter { font-size: 124px; } /* the dash column scrolls with the page; no need to shrink */
  .week-head, .history.day .navbar { top: -24px; } /* just under the arm */
  .tl { --stick: 24px; }
  .week { --hour: max(22px, calc((100dvh - 290px) / 24)); }
  .view-history .history, .view-settings .settings { max-width: 760px; }

  /* Editor opens as a centred dialog instead of a bottom sheet. */
  .sheet-backdrop { align-items: center; }
  .sheet { max-height: 88dvh; padding-bottom: 16px; border-bottom-left-radius: 34px; border-bottom: 10px solid var(--frame-2); }
  .sheet-grip { display: none; }
  .sheet-title { padding-top: 12px; }
}

@media (min-width: 1100px) {
  /* Stats: two columns. */
  .stats {
    display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 40px;
    align-items: start; max-width: 1480px;
  }
  .stats > :not(section) { grid-column: 1 / -1; }
  .stats .chips { justify-self: start; }
  .stats .s-daily { grid-column: 1 / -1; }
}

/* ---------------------------------------------------------------- state change sweep
   See static/js/transitions.js. Over everything, never catches taps.
   Two bars in the new state's colour sweep across from opposite sides with its name
   between them, hold, then sweep on out. Stopping plays the same in grey. */
.fx-layer { position: fixed; inset: 0; z-index: 30; pointer-events: none; overflow: hidden; }
.fx { position: absolute; inset: 0; }
.fx-sweep {
  display: flex; flex-direction: column; justify-content: center; gap: 14px;
  background: radial-gradient(ellipse 80% 40% at 50% 50%, color-mix(in srgb, var(--c) 18%, transparent), transparent 75%);
  animation: fx-veil 1.8s ease-in-out forwards;
}
.fx-bar { height: 20px; width: 78%; background: var(--c); }
.fx-bar.top { align-self: flex-start; border-radius: 0 var(--r) var(--r) 0; animation: fx-from-left 1.8s cubic-bezier(.5, 0, .2, 1) forwards; }
.fx-bar.bottom { align-self: flex-end; border-radius: var(--r) 0 0 var(--r); animation: fx-from-right 1.8s cubic-bezier(.5, 0, .2, 1) forwards; }
.fx-label {
  text-align: center; padding: 0 24px;
  font-family: var(--display); font-weight: 600; text-transform: uppercase;
  font-size: clamp(44px, 14vmin, 120px); line-height: 1; color: var(--c);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  text-shadow: 0 0 24px var(--bg);
  animation: fx-label 1.8s ease-out forwards;
}
.fx-sweep.stop .fx-label { color: var(--text-2); }
@keyframes fx-veil { 0%, 100% { opacity: 0; } 20%, 70% { opacity: 1; } }
@keyframes fx-from-left {
  0% { clip-path: inset(0 100% 0 0); }
  28%, 68% { clip-path: inset(0 0 0 0); }
  100% { clip-path: inset(0 0 0 100%); }
}
@keyframes fx-from-right {
  0% { clip-path: inset(0 0 0 100%); }
  28%, 68% { clip-path: inset(0 0 0 0); }
  100% { clip-path: inset(0 100% 0 0); }
}
@keyframes fx-label {
  0%, 12% { opacity: 0; letter-spacing: .4em; }
  34% { opacity: 1; letter-spacing: .08em; }
  40% { opacity: .4; }
  46%, 72% { opacity: 1; letter-spacing: .08em; }
  100% { opacity: 0; letter-spacing: .08em; }
}

@media (prefers-reduced-motion: reduce) {
  .fx-layer { display: none; }
  .undo-toast { animation: none; }
  .mode.on::after, .pill.live::before { animation: none; }
}
