/* Padel pipeline UI — shared tokens.
   Palette is taken from a floodlit padel court at night: the surface is a
   deep blue-green, the glass reads as cool grey, and the only saturated
   thing on court is the ball. So optic yellow is reserved: in this UI it
   ALWAYS means ball or detection, and nothing else is allowed to use it.
   Teams get teal and clay because they must be distinguishable from the
   ball and from each other at a glance. */

:root {
  --ink:        #0B1519;   /* page */
  --court:      #102127;   /* panel */
  --court-hi:   #16303a;   /* raised panel / hover */
  --line:       #E6EDEB;   /* primary text, court lines */
  --muted:      #7794a0;   /* secondary text */
  --faint:      #33505c;   /* borders, rules */
  --ball:       #D8F31E;   /* BALL / DETECTION ONLY */
  --team0:      #45D0C0;
  --team1:      #F4795B;
  --warn:       #F4B95B;
  --ok:         #45D0C0;

  --mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
  --sans: "Archivo", "Helvetica Neue", Arial, sans-serif;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--ink);
  color: var(--line);
  font-family: var(--sans);
  font-size: 14px;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--line); text-decoration: none; }

/* ── header ─────────────────────────────────────────────────────────── */
header {
  display: flex;
  align-items: baseline;
  gap: 28px;
  padding: 18px 24px;
  border-bottom: 1px solid var(--faint);
}

.wordmark {
  font-weight: 700;
  font-size: 15px;
  letter-spacing: -0.02em;
}
.wordmark span { color: var(--ball); }

nav { display: flex; gap: 20px; margin-left: auto; }
nav a {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted);
  padding-bottom: 2px;
  border-bottom: 1px solid transparent;
}
nav a:hover { color: var(--line); }
nav a[aria-current="page"] {
  color: var(--line);
  border-bottom-color: var(--ball);
}

/* ── layout ─────────────────────────────────────────────────────────── */
main { padding: 24px; max-width: 1500px; margin: 0 auto; }

.split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 300px;
  gap: 20px;
  align-items: start;
}

.panel {
  background: var(--court);
  border: 1px solid var(--faint);
  border-radius: 3px;
  padding: 16px;
}

.eyebrow {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 10px;
}

h1 {
  font-size: 26px;
  font-weight: 700;
  letter-spacing: -0.025em;
  margin: 0 0 6px;
}

.lede { color: var(--muted); max-width: 62ch; line-height: 1.55; margin: 0 0 22px; }

/* ── data readouts ──────────────────────────────────────────────────── */
.readout { font-family: var(--mono); font-size: 12px; }

.kv {
  display: flex;
  justify-content: space-between;
  gap: 12px;
  font-family: var(--mono);
  font-size: 12px;
  padding: 5px 0;
  border-bottom: 1px dotted var(--faint);
}
.kv:last-child { border-bottom: 0; }
.kv span:first-child { color: var(--muted); }
.kv span:last-child { font-variant-numeric: tabular-nums; }

.big {
  font-family: var(--mono);
  font-size: 30px;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.03em;
}

/* ── controls ───────────────────────────────────────────────────────── */
button, select {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--line);
  background: var(--court-hi);
  border: 1px solid var(--faint);
  border-radius: 2px;
  padding: 7px 12px;
  cursor: pointer;
}
button:hover { border-color: var(--muted); }
button:focus-visible, select:focus-visible {
  outline: 2px solid var(--ball);
  outline-offset: 1px;
}
button.primary { background: var(--ball); color: #0B1519; border-color: var(--ball); font-weight: 600; }
button[disabled] { opacity: 0.35; cursor: default; }

kbd {
  font-family: var(--mono);
  font-size: 10px;
  background: var(--ink);
  border: 1px solid var(--faint);
  border-bottom-width: 2px;
  border-radius: 3px;
  padding: 1px 5px;
  color: var(--muted);
}

/* ── canvas stage ───────────────────────────────────────────────────── */
.stage { position: relative; line-height: 0; }
/* Scoped to the main view only: a bare ".stage canvas" also matches the
   loupe canvas and, at higher specificity than ".loupe", stretches the
   150px magnifier over the whole frame. */
.stage #view { width: 100%; height: auto; cursor: crosshair; border-radius: 2px; }

/* THE SIGNATURE ELEMENT: a 6x loupe pinned to the corner. A padel ball is
   about six pixels across, so clicking it at 1:1 is guesswork. The loupe
   makes the hard part of the job the visible part of the UI. */
.loupe {
  position: absolute;
  top: 10px; right: 10px;
  width: 150px; height: 150px;
  border: 1px solid var(--ball);
  border-radius: 2px;
  background: var(--ink);
  image-rendering: pixelated;
  pointer-events: none;
  box-shadow: 0 6px 24px rgba(0,0,0,0.55);
}
.loupe-tag {
  position: absolute;
  top: 164px; right: 10px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.1em;
  color: var(--ball);
  pointer-events: none;
}

/* ── timeline: one tick per labelled frame ──────────────────────────── */
.timeline {
  position: relative;
  height: 34px;
  margin-top: 12px;
  background: var(--court);
  border: 1px solid var(--faint);
  border-radius: 2px;
  cursor: pointer;
  overflow: hidden;
}
.timeline canvas { width: 100%; height: 100%; display: block; }
.timeline .cursor {
  position: absolute; top: 0; bottom: 0; width: 1px;
  background: var(--line);
  pointer-events: none;
}

/* ── clip list ──────────────────────────────────────────────────────── */
table { width: 100%; border-collapse: collapse; font-family: var(--mono); font-size: 12px; }
th {
  text-align: left;
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 400;
  padding: 8px 10px;
  border-bottom: 1px solid var(--faint);
}
td { padding: 9px 10px; border-bottom: 1px dotted var(--faint); font-variant-numeric: tabular-nums; }
tr:hover td { background: var(--court-hi); }

.bar { height: 3px; background: var(--faint); border-radius: 2px; overflow: hidden; }
.bar i { display: block; height: 100%; background: var(--ball); }

.pill {
  display: inline-block;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  padding: 2px 7px;
  border-radius: 9px;
  border: 1px solid var(--faint);
  color: var(--muted);
}
.pill.on { color: var(--ball); border-color: var(--ball); }
.pill.t0 { color: var(--team0); border-color: var(--team0); }
.pill.t1 { color: var(--team1); border-color: var(--team1); }

.empty {
  padding: 40px 20px;
  text-align: center;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 12px;
  line-height: 1.7;
}

.toast {
  position: fixed; bottom: 20px; left: 50%; transform: translateX(-50%);
  background: var(--court-hi);
  border: 1px solid var(--ball);
  color: var(--line);
  font-family: var(--mono); font-size: 12px;
  padding: 9px 16px; border-radius: 2px;
  opacity: 0; transition: opacity .18s;
}
.toast.show { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}
@media (max-width: 900px) {
  .split { grid-template-columns: 1fr; }
  .loupe { width: 108px; height: 108px; }
  .loupe-tag { top: 122px; }
}

/* ── auth + upload ─────────────────────────────────────────────── */
.who{margin-left:auto;font-size:.8rem;opacity:.75;display:flex;gap:.6rem;align-items:center}
.who span{font-size:.65rem;text-transform:uppercase;letter-spacing:.08em;
  border:1px solid currentColor;border-radius:99px;padding:.1rem .45rem;opacity:.8}
header{display:flex;align-items:center;gap:1.5rem}
.auth{max-width:26rem;margin:3rem auto;padding:0 1rem}
.auth.wide{max-width:46rem}
.auth h1{margin-bottom:1.2rem}
.auth h2{margin:2.2rem 0 .6rem;font-size:1rem;opacity:.8}
.auth label{display:block;margin-bottom:1rem;font-size:.85rem}
.auth input[type=text],.auth input[name=username],.auth input[type=password]{
  display:block;width:100%;margin-top:.35rem;padding:.6rem .7rem;font:inherit;
  border:1px solid #999;border-radius:6px;background:transparent;color:inherit}
.auth button{padding:.6rem 1.4rem;font:inherit;font-weight:600;cursor:pointer;
  border:0;border-radius:6px;background:#e8543f;color:#fff}
.auth button[disabled]{opacity:.55;cursor:progress}
.auth input[type=file]{display:block;margin-bottom:1rem;font:inherit;max-width:100%}
.err{background:#e8543f22;border-left:3px solid #e8543f;padding:.6rem .8rem;
  border-radius:4px;margin-bottom:1rem;font-size:.88rem}
.muted{opacity:.7;font-size:.85rem;line-height:1.5}
.tree{background:#0002;padding:.8rem 1rem;border-radius:6px;font-size:.78rem;
  line-height:1.45;overflow-x:auto}
table.clips{width:100%;border-collapse:collapse;font-size:.82rem}
table.clips th,table.clips td{text-align:left;padding:.35rem .5rem;
  border-bottom:1px solid #8884}
table.clips th{font-size:.7rem;text-transform:uppercase;letter-spacing:.06em;opacity:.6}

/* ── upload progress ───────────────────────────────────────────── */
#prog{margin-top:1rem}
.bar{height:8px;border-radius:99px;background:#8883;overflow:hidden}
.fill{height:100%;width:0;border-radius:99px;background:#e8543f;
  transition:width .18s linear}
/* Bytes are sent; the server is unzipping. Indeterminate, so it stripes. */
.fill.working{width:100%!important;background:repeating-linear-gradient(
  110deg,#e8543f 0 12px,#f3826f 12px 24px);animation:slide 1s linear infinite}
@keyframes slide{to{background-position:48px 0}}
.stats{display:flex;gap:1rem;flex-wrap:wrap;margin:.5rem 0 0}
.stats #pct{font-weight:600;opacity:.9}
button.link{background:none;border:0;padding:0;margin-top:.4rem;color:inherit;
  opacity:.6;font:inherit;font-size:.8rem;text-decoration:underline;cursor:pointer}
button.link:hover{opacity:1}
@media (prefers-reduced-motion:reduce){
  .fill{transition:none}.fill.working{animation:none}}

/* ── shot labeling: player + save bar ──────────────────────────── */
.player{display:flex;align-items:center;gap:10px;margin-top:10px;flex-wrap:wrap}
.player button{min-width:38px;padding:.35rem .6rem;font-size:.9rem;line-height:1}
.player .pp{min-width:44px}
.player input[type=range]{flex:1;min-width:160px;accent-color:#D8F31E;cursor:pointer}
.player .frame{min-width:9ch;color:var(--muted);font-variant-numeric:tabular-nums}
.spd{display:flex;align-items:center;gap:.35rem;font-size:.78rem;color:var(--muted)}
.spd select{padding:.2rem .3rem;font:inherit;font-size:.78rem}

.savebar{display:flex;align-items:center;gap:10px;margin-top:16px;
  padding-top:14px;border-top:1px solid var(--line,#8883);flex-wrap:wrap}
button.save{padding:.55rem 1.1rem;font-weight:600}
button.save kbd{opacity:.6;font-size:.72em;margin-left:.4rem}
.badge{margin-left:auto;font-size:.75rem;padding:.2rem .6rem;border-radius:99px;
  border:1px solid currentColor;white-space:nowrap}
.badge.ok{color:#45D0C0}
.badge.warn{color:#D8F31E}
.badge.auto{color:var(--muted,#7794a0)}
button.linkbtn{background:none;border:0;padding:0;font:inherit;font-size:.78rem;
  color:inherit;opacity:.6;text-decoration:underline;cursor:pointer}
button.linkbtn:hover{opacity:1}
.keys .kv span:first-child{font-family:ui-monospace,monospace;opacity:.75}

/* ── clip lists: group by match, show the rally ─────────────────── */
tr.grouphead td{padding-top:1.1rem;font-size:.72rem;letter-spacing:.09em;
  text-transform:uppercase;opacity:.55;border-bottom:1px solid #8884;
  font-family:ui-monospace,monospace;word-break:break-all}
tr.grouphead .count{float:right;opacity:.7;letter-spacing:.04em}
td.rally{font-family:ui-monospace,monospace}
select optgroup{font-style:normal;font-size:.72rem;letter-spacing:.06em;
  text-transform:uppercase;opacity:.6}
select option{font-family:ui-monospace,monospace;padding:.15rem 0}
