/*
 * panel/static/panel.css — GA-008b.
 *
 * The palette, type scale, radii and layout here are LIFTED from the owner's
 * own Grand Dashboard (`nifty_angel_api/Options Selling Systems Dashboard/
 * Grand Dashboard.dc.html`), not invented: same #0d1117 page on #161b22
 * cards with a #2a3140 border, same 13px/1.5 system stack, same 11px
 * uppercase section labels, same 9px card / 6px control / 20px pill radii,
 * same 320px sticky settings column beside a fluid main area. The panel and
 * the dashboard are the same product to the owner, so they read as one.
 *
 * Components the dashboard does not have (tabs, modals, toasts, gauges,
 * skeletons) are derived from those same tokens rather than borrowed from a
 * framework. Nothing here is loaded from a CDN: the production box allows
 * outbound to JM only, so an off-box stylesheet is an unstyled panel in front
 * of the owner at 09:14 (tests/test_panel_ui.py pins this).
 *
 * Motion is 120–200ms and every transition is disabled wholesale under
 * `prefers-reduced-motion` at the bottom of this file.
 */

:root {
  --bg: #0d1117;
  --card: #161b22;
  --bd: #2a3140;
  --ctl: #1c2230;
  --tx: #e6edf3;
  --mut: #8b949e;
  --acc: #2f81f7;
  --link: #58a6ff;
  --link-hover: #79c0ff;
  --grn: #3fb950;
  --red: #f85149;
  --amb: #d29922;
  --pur: #bc8cff;
  --cy: #39c5cf;
  --r-card: 9px;
  --r-ctl: 6px;
  --r-pill: 20px;
  --t-fast: .12s;
  --t-med: .18s;
}

* { box-sizing: border-box; }

html, body { margin: 0; padding: 0; background: var(--bg); }

body {
  font: 13px/1.5 -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  color: var(--tx);
  min-height: 100vh;
}

a { color: var(--link); text-decoration: none; transition: color var(--t-fast) ease; }
a:hover { color: var(--link-hover); text-decoration: underline; }

input, select, button, textarea { font: inherit; }

::-webkit-scrollbar { width: 9px; height: 9px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--bd); border-radius: 5px; }
::-webkit-scrollbar-thumb:hover { background: var(--mut); }

/* ── header ─────────────────────────────────────────────────────────────── */

header.top {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 10px 16px; background: var(--card); border-bottom: 1px solid var(--bd);
  position: sticky; top: 0; z-index: 20;
}
header.top .brand { display: flex; flex-direction: column; gap: 1px; }
header.top h1 { font-size: 15px; margin: 0; font-weight: 600; letter-spacing: .3px; }
header.top h1 span { color: var(--acc); }
header.top .brand .sub { font-size: 11px; color: var(--mut); }
header.top .spacer { flex: 1; }

nav.tabs { display: flex; gap: 2px; flex-wrap: wrap; }
nav.tabs a {
  font-size: 12px; padding: 5px 11px; border-radius: var(--r-pill);
  color: var(--mut); border: 1px solid transparent;
  transition: color var(--t-fast) ease, background var(--t-fast) ease,
              border-color var(--t-fast) ease;
}
nav.tabs a:hover { color: var(--tx); background: var(--ctl); text-decoration: none; }
nav.tabs a.on { color: var(--acc); border-color: var(--acc); background: rgba(47,129,247,.10); }

/* ── the connection pill: the panel's honesty about its own liveness ────── */

.conn {
  font-size: 11px; padding: 3px 9px; border-radius: var(--r-pill);
  background: var(--ctl); border: 1px solid var(--bd); color: var(--mut);
  white-space: nowrap; display: inline-flex; align-items: center; gap: 6px;
  transition: color var(--t-med) ease, border-color var(--t-med) ease;
}
.conn .dot { width: 8px; height: 8px; border-radius: 50%; flex: none; background: var(--mut); }
.conn[data-state="live"]    { color: var(--grn); border-color: rgba(63,185,80,.45); }
.conn[data-state="live"] .dot { background: var(--grn); animation: pulse 2s ease-in-out infinite; }
.conn[data-state="polling"] { color: var(--amb); border-color: rgba(210,153,34,.45); }
.conn[data-state="polling"] .dot { background: var(--amb); }
.conn[data-state="stale"]   { color: var(--amb); border-color: rgba(210,153,34,.45); }
.conn[data-state="stale"] .dot { background: var(--amb); }
.conn[data-state="down"]    { color: var(--red); border-color: rgba(248,81,73,.5); }
.conn[data-state="down"] .dot { background: var(--red); }

@keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: .35; } }

/* ── layout ─────────────────────────────────────────────────────────────── */

main { padding: 14px; }
.split { display: grid; grid-template-columns: 320px minmax(0, 1fr); gap: 14px; align-items: start; }
aside.side {
  display: flex; flex-direction: column; gap: 10px;
  position: sticky; top: 78px; max-height: calc(100vh - 92px);
  overflow-y: auto; padding-right: 3px;
}
section.mainCol { display: flex; flex-direction: column; gap: 14px; min-width: 0; }
.row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.grid-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(132px, 1fr)); gap: 10px; }
.grid-wide { display: grid; grid-template-columns: repeat(auto-fit, minmax(430px, 1fr)); gap: 14px; align-items: start; }

@media (max-width: 900px) {
  .split { grid-template-columns: minmax(0, 1fr); }
  aside.side { position: static; max-height: none; }
}

/* ── cards and labels ───────────────────────────────────────────────────── */

.card {
  background: var(--card); border: 1px solid var(--bd);
  border-radius: var(--r-card); padding: 12px;
  animation: rise var(--t-med) ease both;
}
.card.pad { padding: 14px; }
@keyframes rise { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }

.lbl {
  color: var(--mut); font-size: 11px; text-transform: uppercase;
  letter-spacing: .5px; font-weight: 600; margin-bottom: 9px;
}
.sub { font-size: 10.5px; color: var(--mut); line-height: 1.5; }
.note { color: var(--mut); font-size: 11px; line-height: 1.5; }
.hr { border-top: 1px solid var(--bd); margin: 10px 0 8px; }

.stat { background: var(--ctl); border: 1px solid var(--bd); border-radius: 8px; padding: 9px 11px; }
.stat .k { color: var(--mut); font-size: 11px; }
.stat .v { font-size: 18px; font-weight: 700; margin-top: 2px; font-variant-numeric: tabular-nums; }
.big { font-size: 34px; font-weight: 700; line-height: 1.15; letter-spacing: -.5px; font-variant-numeric: tabular-nums; }
.mid { font-size: 20px; font-weight: 700; font-variant-numeric: tabular-nums; }

.ok { color: var(--grn); }
.bad { color: var(--red); font-weight: 600; }
.warn { color: var(--amb); }
.mut { color: var(--mut); }
.acc { color: var(--acc); }
.num { font-variant-numeric: tabular-nums; }

/* Honest empty state: deliberately blank, never a pretty zero. */
.nodata {
  color: var(--mut); font-style: italic; font-size: 12px;
  border: 1px dashed var(--bd); border-radius: 8px;
  padding: 10px 12px; background: rgba(28,34,48,.35);
}
.nodata.inline { border: 0; padding: 0; background: none; display: inline; }

/* ── pills and dots ─────────────────────────────────────────────────────── */

.pill {
  font-size: 11px; padding: 3px 9px; border-radius: var(--r-pill);
  background: var(--ctl); border: 1px solid var(--bd); color: var(--mut);
  white-space: nowrap; display: inline-flex; align-items: center; gap: 5px;
  transition: all var(--t-fast) ease;
}
.pill.good { color: var(--grn); border-color: rgba(63,185,80,.45); }
.pill.bad  { color: var(--red); border-color: rgba(248,81,73,.5); background: rgba(248,81,73,.08); }
.pill.warn { color: var(--amb); border-color: rgba(210,153,34,.45); }
.pill.acc  { color: var(--acc); border-color: rgba(47,129,247,.5); }
a.pill:hover { text-decoration: none; border-color: var(--mut); }
.dot { width: 8px; height: 8px; border-radius: 50%; flex: none; background: var(--mut); }
.dot.good { background: var(--grn); } .dot.bad { background: var(--red); }
.dot.warn { background: var(--amb); } .dot.off { background: var(--bd); }

/* ── controls ───────────────────────────────────────────────────────────── */

input[type=text], input[type=password], input[type=number], input[type=date], select {
  background: var(--ctl); color: var(--tx); border: 1px solid var(--bd);
  border-radius: var(--r-ctl); padding: 5px 8px; max-width: 100%;
  transition: border-color var(--t-fast) ease, box-shadow var(--t-fast) ease;
}
input:hover, select:hover { border-color: var(--mut); }
input:focus, select:focus, button:focus-visible {
  outline: none; border-color: var(--acc); box-shadow: 0 0 0 2px rgba(47,129,247,.25);
}
input:disabled, input[readonly] { color: var(--mut); background: #171d2a; cursor: not-allowed; }
input.invalid { border-color: var(--red); box-shadow: 0 0 0 2px rgba(248,81,73,.2); }

button, input[type=submit] {
  background: var(--ctl); color: var(--tx); border: 1px solid var(--bd);
  border-radius: var(--r-ctl); padding: 5px 10px; cursor: pointer;
  transition: background var(--t-fast) ease, border-color var(--t-fast) ease,
              transform var(--t-fast) ease, color var(--t-fast) ease;
}
button:hover, input[type=submit]:hover { border-color: var(--mut); background: #222a3a; }
button:active, input[type=submit]:active { transform: translateY(1px); }
button.primary { border-color: rgba(47,129,247,.6); color: var(--acc); }
button.primary:hover { background: rgba(47,129,247,.12); }
button.good { border-color: rgba(63,185,80,.5); color: var(--grn); }
button.good:hover { background: rgba(63,185,80,.12); }
button.danger { border-color: rgba(248,81,73,.6); color: var(--red); }
button.danger:hover { background: rgba(248,81,73,.12); }
button:disabled { opacity: .45; cursor: not-allowed; transform: none; }

/* Pill toggle, 34x18 track and a 14px knob — the dashboard's own control. */
.toggle { width: 34px; height: 18px; border-radius: 9px; position: relative; cursor: pointer;
          flex: none; background: var(--bd); border: 0; padding: 0;
          transition: background var(--t-med) ease; }
.toggle .knob { position: absolute; top: 2px; left: 2px; width: 14px; height: 14px;
                border-radius: 50%; background: var(--tx); transition: left .15s ease; }
.toggle[aria-checked="true"] { background: var(--acc); }
.toggle[aria-checked="true"] .knob { left: 18px; }
.toggle:disabled { opacity: .5; cursor: not-allowed; }

.frow { display: grid; grid-template-columns: 1fr 118px; gap: 8px; align-items: center; margin: 6px 0; }
.frow label { color: var(--mut); font-size: 12px; line-height: 1.25; }
.frow input, .frow select { width: 100%; min-width: 0; }
.frow .unit { color: var(--mut); font-size: 10.5px; }
.frow.wide { grid-template-columns: 1fr 160px; }

/* ── tables ─────────────────────────────────────────────────────────────── */

table { width: 100%; border-collapse: collapse; font-size: 12px; }
th {
  padding: 5px 8px; text-align: left; border-bottom: 1px solid var(--bd);
  color: var(--mut); font-weight: 600; white-space: nowrap;
  position: sticky; top: 0; background: var(--card); z-index: 1;
}
td { padding: 5px 8px; border-bottom: 1px solid var(--bd); }
td.num, th.num { text-align: right; font-variant-numeric: tabular-nums; }
tbody tr { transition: background var(--t-fast) ease; }
tbody tr:hover { background: rgba(28,34,48,.55); }
.scroll { max-height: 420px; overflow: auto; border: 1px solid var(--bd); border-radius: 8px; }
.scroll table th { background: var(--card); }
tr.locked td { background: rgba(28,34,48,.5); color: var(--mut); }

/* ── settings groups ────────────────────────────────────────────────────── */

.field-group { border: 1px solid var(--bd); border-radius: 8px; background: var(--ctl); margin-bottom: 10px; }
.field-group > summary {
  list-style: none; cursor: pointer; padding: 9px 11px;
  display: flex; align-items: center; gap: 8px;
  color: var(--mut); font-size: 11px; text-transform: uppercase;
  letter-spacing: .5px; font-weight: 600;
  transition: color var(--t-fast) ease;
}
.field-group > summary::-webkit-details-marker { display: none; }
.field-group > summary:hover { color: var(--tx); }
.field-group > summary .caret { transition: transform var(--t-med) ease; display: inline-block; }
.field-group[open] > summary .caret { transform: rotate(90deg); }
.field-group > summary .count { margin-left: auto; text-transform: none; letter-spacing: 0;
                                font-weight: 500; opacity: .75; }
.field-group .body { padding: 0 11px 11px; animation: rise var(--t-med) ease both; }
.field-group .body > .note { margin-bottom: 8px; }

.field { display: grid; grid-template-columns: 1fr 132px 46px; gap: 8px;
         align-items: center; margin: 7px 0; padding: 2px 0; border-radius: 4px; }
.field > label { color: var(--mut); font-size: 12px; line-height: 1.25; }
.field .unit { color: var(--mut); font-size: 10.5px; }
.field .lock { font-size: 10px; color: var(--amb); }
.field.is-locked > label { color: var(--mut); opacity: .8; }
.field.is-changed > label { color: var(--tx); }
.field.is-changed > label::before {
  content: ""; display: inline-block; width: 5px; height: 5px; border-radius: 50%;
  background: var(--acc); margin-right: 6px; vertical-align: middle;
}
.field .locked-val { color: var(--mut); font-variant-numeric: tabular-nums;
                     background: #171d2a; border: 1px solid var(--bd);
                     border-radius: var(--r-ctl); padding: 5px 8px; }

/* ── gauges and charts (hand-drawn SVG, no chart library) ───────────────── */

.gauge { display: flex; align-items: center; gap: 10px; margin: 7px 0; }
.gauge .track { flex: 1; height: 6px; border-radius: 3px; background: var(--bd); overflow: hidden; }
.gauge .fill { height: 100%; border-radius: 3px; width: 0;
               transition: width var(--t-med) ease, background var(--t-med) ease; }
.gauge .fill.good { background: var(--grn); }
.gauge .fill.warn { background: var(--amb); }
.gauge .fill.bad  { background: var(--red); }
.gauge .cap { font-size: 11px; color: var(--mut); white-space: nowrap; font-variant-numeric: tabular-nums; }
.gauge .name { width: 54px; font-size: 11px; color: var(--mut); }

.spark { width: 100%; height: 64px; display: block; overflow: visible; }
.bar-row { display: grid; grid-template-columns: 92px 1fr 92px; gap: 8px; align-items: center; margin: 5px 0; font-size: 12px; }
.bar-row .track { height: 8px; background: var(--bd); border-radius: 4px; overflow: hidden; }
.bar-row .fill { height: 100%; transition: width var(--t-med) ease; }

/* ── value transitions: a number that changes must be seen changing ─────── */

[data-bind] { transition: color var(--t-med) ease; }
@keyframes flashUp   { 0% { background: rgba(63,185,80,.28); } 100% { background: transparent; } }
@keyframes flashDown { 0% { background: rgba(248,81,73,.28); } 100% { background: transparent; } }
.flash-up   { animation: flashUp .6s ease-out; border-radius: 4px; }
.flash-down { animation: flashDown .6s ease-out; border-radius: 4px; }

/* Skeleton shimmer, shown only until the first snapshot lands. */
.skel { background: linear-gradient(90deg, var(--ctl) 25%, #232b3b 37%, var(--ctl) 63%);
        background-size: 400% 100%; animation: shimmer 1.3s ease infinite;
        border-radius: 4px; color: transparent !important; display: inline-block; min-width: 60px; }
@keyframes shimmer { 0% { background-position: 100% 50%; } 100% { background-position: 0 50%; } }

/* ── flashes, toasts, modal ─────────────────────────────────────────────── */

.flash { background: rgba(210,153,34,.10); border: 1px solid var(--amb); color: var(--amb);
         padding: 8px 11px; margin-bottom: 10px; border-radius: 8px; font-size: 12px; }
.flash.bad { background: rgba(248,81,73,.10); border-color: var(--red); color: var(--red); }

#toasts { position: fixed; right: 14px; bottom: 14px; z-index: 60;
          display: flex; flex-direction: column; gap: 8px; max-width: 340px; }
.toast { background: var(--card); border: 1px solid var(--bd); border-radius: 8px;
         padding: 9px 11px; font-size: 12px; color: var(--tx);
         box-shadow: 0 6px 20px rgba(0,0,0,.45); animation: rise var(--t-med) ease both; }
.toast.bad { border-color: var(--red); color: var(--red); }

.modal-back { position: fixed; inset: 0; background: rgba(6,9,14,.72); z-index: 50;
              display: flex; align-items: center; justify-content: center; padding: 16px;
              animation: fade var(--t-med) ease both; }
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }
.modal { background: var(--card); border: 1px solid var(--bd); border-radius: var(--r-card);
         padding: 14px; width: 420px; max-width: 100%; animation: rise var(--t-med) ease both; }
.modal h2 { font-size: 14px; margin: 0 0 6px; font-weight: 600; }
.modal .phrase { font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
                 background: var(--ctl); border: 1px solid var(--bd); border-radius: var(--r-ctl);
                 padding: 6px 8px; margin: 8px 0; color: var(--amb); user-select: all; }
.modal input[type=text] { width: 100%; }
.modal .actions { display: flex; gap: 8px; justify-content: flex-end; margin-top: 12px; }

/* JS replaces every inline confirm box with the modal; without JS the inline
   box stays and the same POST still works. The panel must never need JS to
   be operable — plan §9's HALT is not allowed to depend on a script loading. */
body.js .confirm-inline { display: none; }

/* ── login ──────────────────────────────────────────────────────────────── */

.login-wrap { min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 16px; }
.login-wrap .card { width: 360px; max-width: 100%; padding: 18px; }

/* ── motion off ─────────────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
}

/* The sparkline holder shimmers only until the first snapshot draws it; the
   rest of the page is server-rendered, so it needs no skeleton at all. */
.spark-holder { min-height: 64px; border-radius: 6px; }
.spark-holder.skel svg { visibility: hidden; }
