/* AIDSTATION redesign — design tokens + atoms (ported from
   docs/redesign/tokens.css).

   ── Why everything is scoped under `.app` ────────────────────────────
   The live app's static/style.css already ships its own design system on
   :root and on bare class names (.btn, .card, .eyebrow, .wordmark,
   .hairline, .num, .mono) that CURRENT screens use — and the two systems
   disagree (e.g. legacy --ink is oklch(0.16…), here it's 0.13; legacy
   .hairline is an all-sides border, here it's border-top only). A verbatim
   :root/bare-class port would therefore visibly change every existing
   screen. To keep this file INERT until a screen opts in, the whole token
   system + atom set is namespaced under `.app`. Phase 1 applies `class="app"`
   to the new shell's <body>; legacy screens (no .app) are untouched.

   `.screen` (the mockup's artboard frame) is renamed to `.app` here. The
   artboard-only frame constraints (width/height:100%, overflow:hidden) are
   intentionally NOT ported — `.app` becomes the real <body>, which must
   scroll; Phase 1's shell supplies its own flex layout.

   Token-value note: where the redesign and legacy :root differ, the
   redesign value is canonical (it mirrors Brand Guide v3). Inside `.app`
   the redesign value wins by design; outside `.app`, legacy :root is
   unchanged. */

/* ── Tokens (dark mode primary) ──────────────────────────────────── */
.app {
  /* Brand */
  --orange: oklch(0.72 0.18 55);
  --orange-deep: oklch(0.62 0.18 50);
  --orange-soft: oklch(0.86 0.10 60);

  /* Ink (dark) scale */
  --ink:   oklch(0.13 0.005 250);
  --ink-2: oklch(0.18 0.005 250);
  --ink-3: oklch(0.24 0.008 250);
  --ink-4: oklch(0.42 0.010 250);

  /* Paper (light) scale */
  --paper:   oklch(0.98 0.005 80);
  --paper-2: oklch(0.95 0.006 80);
  --paper-3: oklch(0.90 0.008 80);

  /* Semantic — dark mode default for app */
  --bg:       var(--ink);
  --bg-2:     var(--ink-2);
  --bg-3:     var(--ink-3);
  --fg:       var(--paper);
  --fg-2:     color-mix(in oklab, var(--paper) 80%, transparent);
  --fg-3:     color-mix(in oklab, var(--paper) 55%, transparent);
  --fg-4:     color-mix(in oklab, var(--paper) 38%, transparent);
  --hairline: color-mix(in oklab, var(--paper) 10%, transparent);
  --hairline-2: color-mix(in oklab, var(--paper) 6%, transparent);
  --grid:     color-mix(in oklab, var(--paper) 4%, transparent);
  --accent:   var(--orange);
  --accent-2: var(--orange-deep);

  /* Status (kept muted, never neon) */
  --good: oklch(0.72 0.14 145);
  --warn: oklch(0.78 0.14 80);
  --bad:  oklch(0.66 0.18 25);
  --info: oklch(0.70 0.12 230);

  --r-sm: 3px;
  --r-md: 6px;
  --r-lg: 10px;

  --mono: 'JetBrains Mono', ui-monospace, monospace;
  --sans: 'Inter', system-ui, sans-serif;
}

/* Light variant — per-subtree (wrap a region in .light) and the global
   toggle (§28). The toggle class `theme-light` is applied to <html> (the
   documentElement) by a pre-paint bootstrap in base.html's <head>, so the
   theme is correct before first paint (no flash). `.theme-light .app` then
   matches the shell <body class="app"> as a descendant of <html.theme-light>
   and repaints every token; `.app.light` / `.app .light` keep the per-subtree
   wrap (§28 showcase). Inert until both .app and the toggle class exist. */
.app.light,
.app .light,
.theme-light .app {
  --bg:       var(--paper);
  --bg-2:     var(--paper-2);
  --bg-3:     var(--paper-3);
  --fg:       var(--ink);
  --fg-2:     var(--ink-2);
  --fg-3:     var(--ink-3);
  --fg-4:     var(--ink-4);
  --hairline: color-mix(in oklab, var(--ink) 12%, transparent);
  --hairline-2: color-mix(in oklab, var(--ink) 6%, transparent);
  --grid:     color-mix(in oklab, var(--ink) 4%, transparent);
}

/* ── App frame (was .screen) ─────────────────────────────────────── */
.app {
  background: var(--bg);
  color: var(--fg);
  font-family: var(--sans);
  font-size: 14px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
.app * { box-sizing: border-box; }
.app a { color: inherit; text-decoration: none; }
.app ul, .app ol { margin: 0; padding: 0; list-style: none; }
/* Legacy base.css colours bare h1–h6 with --ink (a dark token), which is
   invisible on the dark app theme. Re-assert the app foreground so headings
   that don't set their own colour (.wo-title, .page-title, form headings…)
   are legible. */
.app h1, .app h2, .app h3, .app h4, .app h5, .app h6 { color: var(--fg); }

/* ── Reusable atoms ──────────────────────────────────────────────── */
.app .eyebrow {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--fg-3);
  font-weight: 500;
}
.app .eyebrow.accent { color: var(--accent); }
.app .mono { font-family: var(--mono); }
.app .num  { font-variant-numeric: tabular-nums; }

.app .wordmark { display: inline-flex; align-items: baseline; letter-spacing: 0.04em; line-height: 1; }
.app .wordmark .b { font-weight: 800; }
.app .wordmark .r { font-weight: 400; }

.app .btn {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--mono);
  font-size: 11px; letter-spacing: 0.16em; text-transform: uppercase;
  font-weight: 500;
  padding: 9px 14px;
  border-radius: var(--r-sm);
  border: 1px solid transparent;
  cursor: pointer;
  white-space: nowrap;
}
.app .btn-primary { background: var(--accent); color: var(--ink); }
.app .btn-ghost   { background: transparent; color: var(--fg); border-color: var(--hairline); }
.app .btn-text    { background: transparent; color: var(--fg-2); padding: 9px 0; }
/* Outline-secondary inside the .app shell. Without this, it falls through to
   the bare `.btn-outline-secondary` (style.css) whose `--bs-btn-color: var(--ink)`
   is a FIXED dark token — in the default dark theme that paints near-black text
   on the near-black `--bg`, rendering the button invisible (e.g. the "+ Add
   terrain" / "+ Add attempt" buttons on the race form). Use theme-aware tokens
   like the other .app buttons so it stays legible in both themes. */
.app .btn-outline-secondary { background: transparent; color: var(--fg); border-color: var(--hairline); }
.app .btn-outline-secondary:hover { background: var(--fg); color: var(--bg); border-color: var(--fg); }
.app .btn-sm      { font-size: 10px; padding: 6px 10px; }
.app .btn-icon    {
  width: 30px; height: 30px; padding: 0; justify-content: center;
  background: transparent; color: var(--fg-2);
  border: 1px solid var(--hairline); border-radius: var(--r-sm);
}

.app .chip {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--mono);
  font-size: 10px; letter-spacing: 0.16em; text-transform: uppercase;
  padding: 4px 8px;
  border-radius: var(--r-sm);
  border: 1px solid var(--hairline);
  color: var(--fg-2);
  background: transparent;
}
.app .chip.solid { background: var(--bg-2); }
.app .chip.accent { color: var(--accent); border-color: color-mix(in oklab, var(--accent) 40%, transparent); }
.app .chip.good { color: var(--good); border-color: color-mix(in oklab, var(--good) 40%, transparent); }
.app .chip.warn { color: var(--warn); border-color: color-mix(in oklab, var(--warn) 40%, transparent); }
.app .chip.bad  { color: var(--bad);  border-color: color-mix(in oklab, var(--bad) 40%, transparent); }

.app .card {
  background: var(--bg-2);
  border: 1px solid var(--hairline-2);
  border-radius: var(--r-md);
  /* Bootstrap's .card sets a dark --bs-body-color; re-assert the redesign fg
     so card text relying on inheritance isn't dark-on-dark (invisible). */
  color: var(--fg);
}
.app .card-flush { background: transparent; border: 1px solid var(--hairline); border-radius: var(--r-md); }

.app .hairline { border-top: 1px solid var(--hairline); }
.app .hairline-l { border-left: 1px solid var(--hairline); }

.app .pulse-dot {
  width: 7px; height: 7px; border-radius: 50%; background: var(--accent);
  box-shadow: 0 0 0 0 color-mix(in oklab, var(--accent) 60%, transparent);
}

/* ── Sidebar (desktop chrome) ────────────────────────────────────── */
.app .sidebar {
  width: 232px;
  flex-shrink: 0;
  background: var(--bg);
  border-right: 1px solid var(--hairline-2);
  display: flex; flex-direction: column;
  padding: 18px 0;
  font-size: 13px;
}
.app .sidebar-brand { display: flex; align-items: center; gap: 10px; padding: 0 18px 18px; }
.app .sidebar-brand svg { width: 26px; height: 26px; color: var(--fg); }
.app .sidebar-brand .wordmark { font-size: 14px; color: var(--fg); }
.app .sidebar-section {
  padding: 14px 18px 6px;
  font-family: var(--mono);
  font-size: 9px; letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--fg-4);
}
.app .sidebar-item {
  display: flex; align-items: center; gap: 11px;
  padding: 7px 18px;
  color: var(--fg-2);
  border-left: 2px solid transparent;
  font-weight: 500;
}
.app .sidebar-item .icon { width: 16px; height: 16px; opacity: 0.7; flex-shrink: 0; }
.app .sidebar-item.active {
  color: var(--fg);
  background: color-mix(in oklab, var(--accent) 8%, transparent);
  border-left-color: var(--accent);
}
.app .sidebar-item.active .icon { opacity: 1; color: var(--accent); }
.app .sidebar-item .badge {
  margin-left: auto;
  font-family: var(--mono);
  font-size: 9px;
  background: var(--bg-3);
  padding: 1px 6px;
  border-radius: 999px;
  color: var(--fg-3);
}

.app .sidebar-foot {
  margin-top: auto;
  padding: 14px 18px;
  border-top: 1px solid var(--hairline-2);
  display: flex; align-items: center; gap: 10px;
}
.app .avatar {
  width: 28px; height: 28px; border-radius: 50%;
  background: linear-gradient(135deg, var(--orange), var(--orange-deep));
  color: var(--ink);
  display: grid; place-items: center;
  font-weight: 700; font-size: 11px;
  flex-shrink: 0;
}
.app .avatar.lg { width: 40px; height: 40px; font-size: 14px; }

/* ── Top bar ─────────────────────────────────────────────────────── */
.app .topbar {
  height: 56px;
  padding: 0 28px;
  border-bottom: 1px solid var(--hairline-2);
  display: flex; align-items: center; gap: 16px;
  flex-shrink: 0;
}
.app .topbar .crumbs {
  font-family: var(--mono);
  font-size: 10px; letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--fg-3);
  display: flex; gap: 8px; align-items: center;
}
.app .topbar .crumbs b { color: var(--fg); font-weight: 500; }
.app .topbar .spacer { flex: 1; }
.app .topbar .search {
  display: flex; align-items: center; gap: 8px;
  height: 32px; padding: 0 12px;
  background: var(--bg-2); border: 1px solid var(--hairline-2);
  border-radius: var(--r-sm);
  font-family: var(--mono); font-size: 11px;
  color: var(--fg-3);
  min-width: 240px;
}
.app .topbar .search kbd {
  font-family: var(--mono); font-size: 10px;
  background: var(--bg-3); padding: 1px 5px; border-radius: 2px;
  color: var(--fg-3); margin-left: auto;
}

/* Page body */
.app .page { flex: 1; overflow: hidden; display: flex; flex-direction: column; }
.app .page-body { padding: 28px; overflow: auto; flex: 1; }
.app .page-title { font-size: 28px; font-weight: 700; letter-spacing: -0.02em; margin: 0; }
.app .page-sub { font-size: 14px; color: var(--fg-3); margin: 4px 0 0; }

/* Grids.
   Zero Bootstrap's grid gutter on our flex rows: its .row sets negative side
   margins and its `.row > *` adds horizontal padding (both via --bs-gutter-x),
   which leak into these redesign rows and throw spacing off / overhang the
   container. Neutralising the variable kills both at once while preserving the
   `flex-wrap: wrap` the layout relies on for mobile column stacking. */
.app .row { display: flex; gap: 16px; --bs-gutter-x: 0; }
.app .col { flex: 1; min-width: 0; }
.app .stack { display: flex; flex-direction: column; gap: 16px; }

/* Below the shell breakpoint, every row collapses to a single stacked column.
   Made explicit (flex-basis: 100%) rather than leaning on flex-wrap heuristics,
   so main+rail layouts stack cleanly instead of cramming side by side. */
@media (max-width: 859.98px) {
  .app .row { flex-wrap: wrap; }
  .app .row > * { flex-basis: 100%; }
}

/* ── Mobile chrome ───────────────────────────────────────────────── */
.app .statusbar {
  height: 44px; padding: 0 22px;
  display: flex; align-items: center; justify-content: space-between;
  font-family: var(--mono); font-size: 13px; font-weight: 600;
  color: var(--fg);
  flex-shrink: 0;
}
.app .statusbar .right { display: flex; gap: 6px; align-items: center; opacity: 0.85; }

.app .appbar {
  height: 52px;
  padding: 0 16px;
  display: flex; align-items: center; gap: 12px;
  border-bottom: 1px solid var(--hairline-2);
  flex-shrink: 0;
}
.app .appbar .title { font-size: 17px; font-weight: 600; letter-spacing: -0.01em; }

.app .tabbar {
  height: 78px;
  padding: 8px 0 22px;
  border-top: 1px solid var(--hairline-2);
  display: grid; grid-template-columns: repeat(5, 1fr);
  background: var(--bg);
  flex-shrink: 0;
}
.app .tabbar .tab {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  color: var(--fg-3);
  font-family: var(--mono); font-size: 9px; letter-spacing: 0.14em; text-transform: uppercase;
}
.app .tabbar .tab svg { width: 22px; height: 22px; }
.app .tabbar .tab.active { color: var(--accent); }
.app .tabbar .tab.fab {
  position: relative;
}
.app .tabbar .tab.fab .fab-btn {
  width: 46px; height: 46px;
  background: var(--accent); color: var(--ink);
  border-radius: 50%;
  display: grid; place-items: center;
  margin-top: -10px;
  box-shadow: 0 8px 24px -4px color-mix(in oklab, var(--accent) 40%, transparent);
}

/* ── Misc atoms used inside screens ──────────────────────────────── */
.app .kv { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; }
.app .kv .k { font-family: var(--mono); font-size: 10px; letter-spacing: 0.18em; text-transform: uppercase; color: var(--fg-3); }
.app .kv .v { font-weight: 600; font-variant-numeric: tabular-nums; }

.app .stat-card {
  padding: 18px; border-radius: var(--r-md);
  background: var(--bg-2); border: 1px solid var(--hairline-2);
  display: flex; flex-direction: column; gap: 8px;
}
.app .stat-card .k { font-family: var(--mono); font-size: 10px; letter-spacing: 0.22em; text-transform: uppercase; color: var(--fg-3); }
.app .stat-card .v { font-size: 28px; font-weight: 700; letter-spacing: -0.02em; font-variant-numeric: tabular-nums; line-height: 1; }
.app .stat-card .u { font-size: 12px; color: var(--fg-3); font-weight: 400; margin-left: 4px; }
.app .stat-card .delta { font-family: var(--mono); font-size: 10px; letter-spacing: 0.14em; }
.app .stat-card.hi { background: var(--accent); color: var(--ink); border-color: transparent; }
.app .stat-card.hi .k, .app .stat-card.hi .u { color: color-mix(in oklab, var(--ink) 65%, transparent); }
.app .stat-card.hi .delta { color: color-mix(in oklab, var(--ink) 80%, transparent); }

/* Bar/sparkline helpers (pure CSS / SVG) */
.app .spark { width: 100%; height: 56px; display: block; }
.app .bars { display: flex; align-items: flex-end; gap: 4px; height: 64px; }
.app .bars span { flex: 1; background: var(--fg-4); border-radius: 1px; }
.app .bars span.hi { background: var(--accent); }

/* ── Plan generation · letter-tumble animation ───────────────────
   Used by Phase 3 plan-gen (cup-pour). Harmless until then. Keyframes
   are global by nature; the elements that consume them live under .app. */
@keyframes letterTumble {
  0%        { opacity: 0; transform: translate(calc(-50% + var(--px, 0px)), -60px) rotate(0deg)   scale(1);    }
  0.05%     { opacity: 1; transform: translate(calc(-50% + var(--px, 0px)), -60px) rotate(0deg)   scale(1);    }
  0.5%      { opacity: 1; transform: translate(calc(-50% + var(--px, 0px)), -60px) rotate(0deg)   scale(1);    }
  0.85%     { opacity: 1; transform: translate(calc(-50% + var(--px, 0px) * 0.55), -30px) rotate(-5deg) scale(1); }
  1.7%      { opacity: 1; transform: translate(calc(-50% + var(--x, 0px) * 1.25), 60px) rotate(calc(var(--r, 0deg) * 0.5)) scale(0.97); }
  2.5%      { opacity: 1; transform: translate(calc(-50% + var(--x, 0px)), var(--y, 150px)) rotate(var(--r, 0deg)) scale(0.92); }
  2.9%      { opacity: 1; transform: translate(calc(-50% + var(--x, 0px)), var(--y, 150px)) rotate(var(--r, 0deg)) scale(0.92); }
  3.05%     { opacity: 1; transform: translate(calc(-50% + var(--x, 0px) * 0.5), calc(var(--y, 150px) - 100px)) rotate(calc(var(--r, 0deg) - 20deg)) scale(0.92); }
  3.3%      { opacity: 1; transform: translate(calc(-50% + var(--x, 0px) * 0.15), calc(var(--y, 150px) - 350px)) rotate(calc(var(--r, 0deg) - 50deg)) scale(0.85); }
  3.55%     { opacity: 0.5; transform: translate(-50%, calc(var(--y, 150px) - 650px)) rotate(-110deg) scale(0.6); }
  3.75%     { opacity: 0; transform: translate(-50%, calc(var(--y, 150px) - 950px)) rotate(-200deg) scale(0.3); }
  4%        { opacity: 0; transform: translate(calc(-50% + var(--px, 0px)), -60px) rotate(0deg) scale(1); }
  100%      { opacity: 0; transform: translate(calc(-50% + var(--px, 0px)), -60px) rotate(0deg) scale(1); }
}
@keyframes cupTipping {
  0%, 65%   { transform: translateX(-50%) rotate(0deg); }
  72%       { transform: translateX(-50%) rotate(60deg); }
  76%, 92%  { transform: translateX(-50%) rotate(108deg); }
  98%       { transform: translateX(-50%) rotate(20deg); }
  100%      { transform: translateX(-50%) rotate(0deg); }
}
