/* Field UI for phone, tablet and PC.
 *
 * Constraints that drove this: gloved/thumb use (44px minimum targets), direct
 * sunlight and dim night shifts (both colour schemes, all pairs >= WCAG 2.2 AA),
 * phones held in landscape on a counter (short-viewport layout), and browsers
 * that would otherwise pull-to-refresh mid-observation and destroy the slot.
 */
:root {
  --t1: #1d4ed8; --t2: #b45309; --t3: #15803d; --t4: #6d28d9;
  /* identical in both schemes: every one clears 4.5:1 against white text */
  --bg: #0f1115; --card: #171a21; --line: #2a303b; --sunk: #0d1016;
  --fg: #e8ecf2; --dim: #9aa4b2; --btn: #222836; --btn-fg: #e8ecf2;
  --ok: #22c55e; --bad: #f87171; --warn: #fbbf24;
  --accent: #7c6cf0; --accent-fg: #0b0d12;
  --pad: 0.9rem;
}
@media (prefers-color-scheme: light) {
  :root {
    --bg: #f4f6f9; --card: #ffffff; --line: #d9dee6; --sunk: #f0f2f6;
    --fg: #14171d; --dim: #59616f; --btn: #eceff4; --btn-fg: #14171d;
    --ok: #15803d; --bad: #b91c1c; --warn: #92610a;
    --accent: #4c3fc4; --accent-fg: #ffffff;
  }
}

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0; background: var(--bg); color: var(--fg);
  font: 16px/1.45 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  /* Stops Android Chrome's pull-to-refresh reloading the page mid-slot. */
  overscroll-behavior-y: contain;
  /* Kills the 300ms tap delay and double-tap zoom without blocking pinch zoom. */
  touch-action: manipulation;
  padding-bottom: calc(2rem + env(safe-area-inset-bottom));
}

/* ATFS brand strip. Sized by WIDTH, not height: the lockup is stacked, so
   fitting it to a line-height collapses the wordmark to a smudge. It sits above
   the sticky header and scrolls away, so it never competes with the tap grid.
   It owns the notch inset; the header keeps its own for when it is stuck. */
.brandbar {
  display: flex; align-items: center;
  background: var(--card); border-bottom: 1px solid var(--line);
  padding: .5rem var(--pad) .4rem;
  padding-top: calc(.5rem + env(safe-area-inset-top));
  padding-left: calc(var(--pad) + env(safe-area-inset-left));
}
.brandbar img { display: block; width: 58px; height: auto; }

header {
  position: sticky; top: 0; z-index: 5; background: var(--card);
  border-bottom: 1px solid var(--line);
  padding: .5rem var(--pad);
  padding-top: calc(.5rem + env(safe-area-inset-top));
  display: flex; align-items: center; gap: .5rem .75rem; flex-wrap: wrap;
}
header h1 { font-size: 1rem; margin: 0; letter-spacing: .04em; color: var(--accent); }
#clock {
  font: 700 1.4rem/1 ui-monospace, "SF Mono", Consolas, monospace;
  margin-left: auto; font-variant-numeric: tabular-nums;
}
.badge {
  font-size: .7rem; padding: .2rem .5rem; border-radius: 99px;
  border: 1px solid var(--line); color: var(--dim);
}
.badge.ok { color: var(--ok); }
.badge.bad { color: #3b2a02; background: var(--warn); font-weight: 700; border-color: transparent; }

main {
  max-width: 860px; margin: 0 auto;
  padding: var(--pad);
  padding-left: calc(var(--pad) + env(safe-area-inset-left));
  padding-right: calc(var(--pad) + env(safe-area-inset-right));
}
.card { background: var(--card); border: 1px solid var(--line); border-radius: 14px; padding: 1rem; }
h2 { margin: 0 0 .8rem; font-size: 1.15rem; }
h3 { margin: 1.2rem 0 .5rem; font-size: .95rem; color: var(--dim); }
h3 small { font-weight: 400; }
.row { display: flex; align-items: center; gap: .6rem; flex-wrap: wrap; }
.row.between { justify-content: space-between; }
.meta { color: var(--dim); font-size: .82rem; margin: -.4rem 0 .9rem; }
.note { color: var(--dim); font-size: .8rem; margin: .4rem 0; }
.hint { color: var(--dim); font-style: normal; font-size: .75rem; }

label { display: block; margin: .55rem 0; font-size: .82rem; color: var(--dim); }
label i { color: var(--bad); font-style: normal; }
label small { display: block; margin-top: .25rem; font-size: .72rem; }
input, select {
  width: 100%; margin-top: .25rem; padding: .7rem .6rem;
  /* 16px exactly — anything smaller makes iOS Safari zoom on focus. */
  font-size: 16px; min-height: 44px;
  background: var(--sunk); color: var(--fg);
  border: 1px solid var(--line); border-radius: 9px;
}
input:focus-visible, select:focus-visible, button:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px;
}
/* min() keeps a 150px minimum from overflowing a 320px-wide phone. */
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr)); gap: 0 .7rem; }
.grid .wide { grid-column: 1 / -1; }
.hidden { display: none; }

button {
  font: inherit; font-weight: 600; padding: .7rem 1rem; min-height: 44px;
  border-radius: 10px; border: 1px solid var(--line);
  background: var(--btn); color: var(--btn-fg); cursor: pointer;
}
button.primary { background: var(--accent); border-color: var(--accent); color: var(--accent-fg); }
button.big { width: 100%; padding: 1rem; font-size: 1.05rem; margin-top: .8rem; }
button.ghost { background: transparent; color: var(--dim); }
button.tiny { padding: .25rem .55rem; min-height: 0; font-size: .75rem; margin-left: .35rem; }
button.danger { color: var(--bad); border-color: var(--bad); }
button[disabled] { opacity: .55; cursor: default; }
button:not([disabled]):active { transform: translateY(1px); }

/* stopwatch */
.taps { display: grid; gap: .6rem; margin: .4rem 0 .8rem;
        grid-template-columns: repeat(auto-fit, minmax(min(104px, 100%), 1fr)); }
.taps-2 { grid-template-columns: repeat(2, 1fr); }
.taps-3 { grid-template-columns: repeat(3, 1fr); }
.taps-4 { grid-template-columns: repeat(4, 1fr); }
.tap {
  min-height: 116px; border: none; color: #fff; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: .25rem; font-size: .8rem;
  position: relative; text-align: center; line-height: 1.2;
}
.tap b { font-size: 1.9rem; line-height: 1; }
.tap1 { background: var(--t1); } .tap2 { background: var(--t2); }
.tap3 { background: var(--t3); } .tap4 { background: var(--t4); }
.tap .q {
  position: absolute; top: .45rem; right: .55rem; background: rgba(0,0,0,.5);
  border-radius: 99px; min-width: 1.5rem; padding: .1rem .35rem; font-size: .8rem;
}
.counts { margin-left: auto; color: var(--dim); font-size: .82rem; }
.rem { font-size: .8rem; color: var(--dim); font-variant-numeric: tabular-nums; }
.rem.warn { color: var(--warn); } .rem.over { color: var(--bad); font-weight: 700; }
.carry { color: var(--warn); }

.tracks { display: flex; flex-direction: column; gap: .3rem; margin: .5rem 0; }
.track { font: .78rem/1.6 ui-monospace, Consolas, monospace; display: flex; gap: .4rem; flex-wrap: wrap; }
.track span { padding: .1rem .4rem; border-radius: 6px; background: var(--sunk); }
.track span.off { opacity: .5; }
details.log { margin: .5rem 0; color: var(--dim); font-size: .8rem; }
summary { cursor: pointer; padding: .5rem 0; min-height: 44px; display: flex; align-items: center; }

.closer { border-top: 1px solid var(--line); margin-top: 1rem; padding-top: .9rem; display: grid; gap: .5rem; }
/* Why the export button is dead. Sits directly above it, because a disabled
   button with no stated reason reads as a broken app, not as a refusal. */
.blocked {
  grid-column: 1 / -1; margin: 0;
  padding: .75rem .8rem; border-radius: 9px;
  background: var(--sunk); border: 1px solid var(--bad);
  font-size: .85rem; line-height: 1.55;
}
.blocked p { margin: 0 0 .6rem; }
.blocked button { width: 100%; }
.blocked .small { margin: .6rem 0 0; font-size: .78rem; color: var(--dim); }
.resume { margin-top: 1rem; padding: .8rem; border: 1px dashed var(--line); border-radius: 10px; font-size: .85rem; }
.dest {
  margin-top: 1rem; padding: .7rem .8rem; border-radius: 10px;
  background: var(--sunk); border: 1px solid var(--line); font-size: .82rem; color: var(--dim);
}
.dest b { color: var(--fg); }
.ok-line { margin-top: .4rem; color: var(--ok); }

table.counts { width: 100%; border-collapse: collapse; font-size: .85rem; }
table.counts th, table.counts td { text-align: left; padding: .4rem .5rem; border-bottom: 1px solid var(--line); }
table.counts td.n { text-align: right; font-variant-numeric: tabular-nums; }

.warns { display: flex; flex-direction: column; gap: .3rem; font-size: .82rem; max-height: 40vh; overflow: auto; }
.warns > div { padding: .4rem .55rem; border-radius: 8px; background: var(--sunk); border-left: 3px solid var(--line); }
/* Severity is carried by a WORD as well as the border colour. Red/amber/green
   is the exact triple deuteranopia collapses, and "will not export" vs "worth a
   look" is the difference between a shift landing and a shift being lost — too
   important to encode in hue alone (WCAG 2.2 AA, 1.4.1). Done here rather than
   in markup so the review screen and the admin console both get it from the one
   place they already share. Labels match the counts in the heading above. */
.warns > div::before {
  display: inline-block; margin-right: .4rem;
  font-size: .68rem; font-weight: 700; letter-spacing: .04em;
}
.warns .error { border-left-color: var(--bad); }
.warns .error::before { content: 'BLOCKING'; color: var(--bad); }
.warns .warn { border-left-color: var(--warn); }
.warns .warn::before { content: 'ADVISORY'; color: var(--warn); }
.warns .ok { border-left-color: var(--ok); color: var(--ok); }
.warns .ok::before { content: 'OK'; }
.bad { color: var(--bad); }

.toast {
  position: fixed; left: 50%; z-index: 10;
  bottom: calc(1rem + env(safe-area-inset-bottom));
  transform: translate(-50%, 200%);
  background: var(--fg); color: var(--bg);
  padding: .7rem 1rem; border-radius: 10px; font-size: .85rem;
  max-width: min(90vw, 30rem); transition: transform .22s ease;
  box-shadow: 0 8px 30px rgba(0,0,0,.35);
}
.toast.show { transform: translate(-50%, 0); }

/* ---- phone, portrait ------------------------------------------------------ */
@media (max-width: 480px) {
  :root { --pad: 0.6rem; }
  .card { padding: .8rem; border-radius: 12px; }
  .brandbar img { width: 52px; }
  header h1 { font-size: .85rem; }
  #clock { font-size: 1.25rem; }
  /* Tap buttons stay on one row even at 320px — splitting them across rows
     moves a button under the thumb mid-observation. */
  .taps { gap: .35rem; }
  .tap { min-height: 104px; font-size: .68rem; padding: .3rem .15rem; }
  .tap b { font-size: 1.5rem; }
  .taps-4 .tap { font-size: .6rem; padding: .3rem .1rem; }
  .taps-4 .tap b { font-size: 1.3rem; }
}

/* ---- tablet and PC -------------------------------------------------------- */
@media (min-width: 700px) {
  main { max-width: 980px; padding: 1.25rem; }
  .tap { min-height: 132px; font-size: .85rem; }
  .tap b { font-size: 2.1rem; }
  /* Both counts side by side, then the actions across the full width. */
  .closer { grid-template-columns: 1fr 1fr; align-items: end; }
  .closer .note, .closer button { grid-column: 1 / -1; }
}
@media (min-width: 900px) {
  .closer button.primary { grid-column: 1; }
  .closer button.ghost { grid-column: 2; }
  .closer button.big { grid-column: 1 / -1; }
}

/* ---- short viewport (phone/tablet in landscape) --------------------------
   Declared last on purpose: it must beat the min-width blocks above, because a
   844x390 phone in landscape matches both and height is the binding limit. */
@media (max-height: 500px) and (orientation: landscape) {
  .brandbar { padding-block: .25rem; }
  .brandbar img { width: 38px; }
  header { position: static; padding-block: .3rem; }
  #clock { font-size: 1.1rem; }
  .card { padding: .6rem; }
  h2 { font-size: 1rem; margin-bottom: .4rem; }
  .meta { margin-bottom: .5rem; }
  .tap { min-height: 76px; }
  .tap b { font-size: 1.4rem; }
  .tracks, details.log { max-height: 22vh; overflow: auto; }
  .closer { grid-template-columns: 1fr 1fr; align-items: end; }
  .closer .note, .closer button.primary { grid-column: 1 / -1; }
}

/* Base state first: the media query below must be able to override it. */
.kbdhint { display: none; color: var(--dim); font-size: .75rem; }

/* Pointer-based devices get hover affordances and the keyboard-shortcut hint;
   touch devices must not, or the hover state sticks after a tap. */
@media (hover: hover) and (pointer: fine) {
  button:not([disabled]):hover { filter: brightness(1.12); }
  .kbdhint { display: inline; }
}

@media (prefers-reduced-motion: reduce) { * { transition: none !important; animation: none !important; } }
@media (prefers-contrast: more) {
  :root { --line: currentColor; }
  .badge, .dest, .warns > div { border-width: 2px; }
}
