/*
  PCG Scan — Peterson Corn Genetics brand palette.

  Palette (from the PCG brand sheet):
    Green #028345 · Dark Green #2A5135 · Light Green #70C497
    Blue #007598 · Orange #F68D2B · Warm Gray #8D827A · Warm Gray 1 #D6D1CA

  THEMING
  The theme is selected by a `data-theme` attribute on <html>, set to either
  "light" or "dark". js/theme.js resolves the user's auto/light/dark preference
  to one of those two concrete values and writes the attribute; an inline script
  in index.html does the same before first paint so there is no flash of the
  wrong theme.

  This is deliberately NOT driven by a prefers-color-scheme media query. With a
  media query, supporting an explicit override needs the dark palette written
  twice (once for `@media dark` and again for `[data-theme="dark"]`), and two
  copies of a palette drift. Resolving the system preference in JS keeps one
  definition per token. The app is wholly JS-dependent anyway -- it is a camera
  and a WASM decoder -- so there is no no-JS case to protect.

  Two further rules make this work:

  1. Every colour is a semantic token (--text, --accent, --warn-bg), never a
     raw brand hex used directly in a rule. The brand hexes are the raw
     ingredients; the tokens are what the UI consumes. To retheme, change the
     token block, not the rules below it.

  2. The viewfinder is exempt. --stage-* and --scrim stay dark in BOTH themes
     because that surface is live camera video, not UI: a bright scrim reflects
     off glossy labels, and the guide overlay has to stay legible against
     whatever the camera sees. Camera apps on both platforms do the same.

  Contrast was checked against WCAG AA for normal text. Notably PCG green on
  white is 4.9:1 (passes), but PCG orange on white is 2.4:1 (fails) — which is
  why warnings in light mode use dark text on a pale orange tint and keep the
  orange for the border and icon only.
*/

:root,
:root[data-theme="light"] {
  /* Brand constants — identical in both themes. */
  --pcg-green: #028345;
  --pcg-green-dark: #2a5135;
  --pcg-green-light: #70c497;
  --pcg-blue: #007598;
  --pcg-orange: #f68d2b;
  --pcg-gray: #8d827a;
  --pcg-gray-light: #d6d1ca;
  --pcg-red: #7f2529;

  /* Keeps native form controls, scrollbars and the caret in step with the
     chosen theme rather than always rendering light. */
  color-scheme: light;

  /* ---- light theme (default) ---- */
  --bg: #f7f6f3;
  --surface: #ffffff;
  --surface-2: #f0eeea;
  --border: #dcd8d1;
  /* Contrast-checked against both --bg and --surface at WCAG AA (4.5:1).
     The warm grays straight off the brand sheet (#8D827A, Warm Gray 8) come in
     at 4.05:1 on white and fail, so the muted tiers are darkened here while
     keeping the warm hue. Ratios: text 15.7, dim 6.8, faint 4.95. */
  --text: #1a2620;
  --text-dim: #4a5651;
  --text-faint: #6e675f;

  --accent: var(--pcg-green);
  --accent-strong: var(--pcg-green-dark);
  --accent-ring: rgb(0 0 0 / 0.1);

  --btn-primary-bg: var(--pcg-green);
  --btn-primary-fg: #ffffff;
  --btn-primary-hover: #026e3a;

  --badge-bg: rgb(2 131 69 / 0.1);
  --badge-border: var(--pcg-green);
  --badge-text: var(--pcg-green-dark);

  --info-border: var(--pcg-blue);

  --warn-bg: #fdf2e4;
  --warn-border: var(--pcg-orange);
  --warn-text: #6b3d05;
  --warn-icon-bg: var(--pcg-orange);
  --warn-icon-fg: #2b1400;

  --danger: var(--pcg-red);
  --danger-bg: #fdecea;
  --danger-text: #6e1f22;

  --ctrl-bg: var(--pcg-blue);
  --ctrl-fg: #ffffff;

  /* Viewfinder — deliberately dark in both themes. See note above. */
  --stage-bg: #050806;
  --stage-border: #dcd8d1;
  --stage-text: #cfd8d2;
  --stage-accent: var(--pcg-green-light);
  --scrim: rgb(5 8 6 / 0.45);
  --diag-bg: rgb(5 8 6 / 0.78);

  --font-head: "Prompt", "Segoe UI Semibold", "Trebuchet MS", system-ui, sans-serif;
  --font-body: "Montserrat", "Segoe UI", system-ui, -apple-system, sans-serif;

  --radius: 12px;
  --control-height: 44px;
}

:root[data-theme="dark"] {
  color-scheme: dark;

  --bg: #0b120e;
  --surface: #141d17;
  --surface-2: #1b2620;
  --border: #2b3830;
  --text: #eef2ef;
  --text-dim: #a8b4ac;
  /* Warm Gray 8 lands at 4.59:1 here — passing but with no margin, so this is
     lifted a step for the same reason as the light theme. */
  --text-faint: #9a8f86;

  /* The mid-tone green is too dark to read on a dark surface; the light tint
     is the accent here, and vice versa in light mode. */
  --accent: var(--pcg-green-light);
  --accent-strong: var(--pcg-green-light);
  --accent-ring: rgb(255 255 255 / 0.08);

  --btn-primary-bg: var(--pcg-green);
  --btn-primary-fg: #ffffff;
  --btn-primary-hover: #039b52;

  --badge-bg: rgb(2 131 69 / 0.18);
  --badge-border: var(--pcg-green);
  --badge-text: var(--pcg-green-light);

  --warn-bg: rgb(246 141 43 / 0.12);
  --warn-text: #ffe0bf;
  --warn-icon-fg: #241000;

  --danger: #ff8a80;
  --danger-bg: rgb(255 138 128 / 0.12);
  --danger-text: #ffd9d4;

  --stage-border: #2b3830;
}

* {
  box-sizing: border-box;
}

html,
body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  -webkit-text-size-adjust: 100%;
}

body {
  display: flex;
  flex-direction: column;
  min-height: 100svh;
  /* Keep content clear of the notch and home indicator on iOS. */
  padding: env(safe-area-inset-top) env(safe-area-inset-right)
    env(safe-area-inset-bottom) env(safe-area-inset-left);
}

main {
  flex: 1;
  width: 100%;
  max-width: 560px;
  margin: 0 auto;
  padding: 0 1rem 1.5rem;
}

/* ---------------------------------------------------------------- topbar -- */

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  width: 100%;
  max-width: 560px;
  margin: 0 auto;
  padding: 0.9rem 1rem;
}

.brand {
  display: flex;
  align-items: center;
  gap: 0.6rem;
}

.brand-mark {
  width: 26px;
  height: 26px;
  border-radius: 7px;
  background: linear-gradient(150deg, var(--pcg-green-light), var(--pcg-green) 55%, var(--pcg-green-dark));
  box-shadow: 0 0 0 1px var(--accent-ring);
}

.brand-text {
  font-family: var(--font-head);
  font-size: 1.15rem;
  letter-spacing: 0.01em;
}

/* Brand rule: "PCG" is set bold at ~85% of the surrounding text size. */
.brand-pcg {
  font-weight: 700;
  font-size: 0.85em;
  color: var(--accent-strong);
}

.brand-app {
  font-weight: 500;
  color: var(--text);
}

.icon-btn {
  font-family: var(--font-body);
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--text-dim);
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0.35rem 0.75rem;
  cursor: pointer;
}

.icon-btn[aria-pressed="true"] {
  /* --accent (mid green) lands at 4.48:1 on the light page background — a hair
     under AA. --accent-strong is the darker green in light mode and the light
     tint in dark mode, so both directions clear it comfortably. */
  color: var(--accent-strong);
  border-color: var(--pcg-green);
}

/* ----------------------------------------------------------------- stage -- */

.stage {
  position: relative;
  aspect-ratio: 3 / 4;
  max-height: 62svh;
  margin: 0 auto;
  overflow: hidden;
  background: var(--stage-bg);
  border: 1px solid var(--stage-border);
  border-radius: var(--radius);
}

.stage video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  /* `cover` is assumed by mapGuideToVideo() in scanner.js — changing this
     without updating that mapping will misalign the scan region. */
  object-fit: cover;
  display: none;
}

.stage.is-scanning video {
  display: block;
}

.stage-idle {
  position: absolute;
  inset: auto 1.5rem 1.5rem;
  margin: 0;
  text-align: center;
  font-size: 0.86rem;
  line-height: 1.5;
  color: var(--stage-text);
}

.stage-idle strong {
  color: var(--stage-accent);
  font-weight: 600;
}

.stage.is-scanning .stage-idle {
  display: none;
}

/* Guide box. These offsets MUST match GUIDE in js/scanner.js. */
.guide {
  position: absolute;
  left: 6%;
  right: 6%;
  top: 18%;
  bottom: 18%;
  display: none;
  border-radius: 8px;
  box-shadow: 0 0 0 100vmax var(--scrim);
}

.stage.is-scanning .guide {
  display: block;
}

.corner {
  position: absolute;
  width: 26px;
  height: 26px;
  border: 3px solid var(--stage-accent);
}

.corner.tl { top: -1px; left: -1px; border-right: 0; border-bottom: 0; border-radius: 8px 0 0 0; }
.corner.tr { top: -1px; right: -1px; border-left: 0; border-bottom: 0; border-radius: 0 8px 0 0; }
.corner.bl { bottom: -1px; left: -1px; border-right: 0; border-top: 0; border-radius: 0 0 0 8px; }
.corner.br { bottom: -1px; right: -1px; border-left: 0; border-top: 0; border-radius: 0 0 8px 0; }

.sweep {
  position: absolute;
  left: 6px;
  right: 6px;
  height: 2px;
  background: linear-gradient(90deg, transparent, var(--stage-accent), transparent);
  animation: sweep 2.4s ease-in-out infinite;
}

@keyframes sweep {
  0%, 100% { top: 6px; opacity: 0.25; }
  50% { top: calc(100% - 8px); opacity: 0.9; }
}

@media (prefers-reduced-motion: reduce) {
  .sweep { animation: none; opacity: 0.4; top: 50%; }
}

.diagnostics {
  position: absolute;
  top: 0.5rem;
  left: 0.5rem;
  padding: 0.3rem 0.55rem;
  border-radius: 6px;
  background: var(--diag-bg);
  color: var(--stage-accent);
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.7rem;
  /* app.js joins the diagnostic lines with "\n"; the default would collapse
     those to spaces and run everything together. */
  white-space: pre-line;
  line-height: 1.5;
  max-width: calc(100% - 1rem);
}

/* ---------------------------------------------------------------- status -- */

.status {
  margin: 0.9rem 0 0;
  padding: 0.6rem 0.8rem;
  border-radius: 8px;
  font-size: 0.85rem;
  line-height: 1.45;
  background: var(--surface);
  border-left: 3px solid var(--info-border);
  color: var(--text-dim);
}

.status[data-tone="error"] {
  background: var(--danger-bg);
  border-left-color: var(--danger);
  color: var(--danger-text);
}

/* -------------------------------------------------------------- controls -- */

.controls {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-top: 0.9rem;
}

.btn {
  flex: 1 1 auto;
  min-height: 46px;
  padding: 0.7rem 1.1rem;
  font-family: var(--font-body);
  font-size: 0.92rem;
  font-weight: 600;
  border-radius: 10px;
  border: 1px solid transparent;
  cursor: pointer;
}

.btn:disabled {
  opacity: 0.45;
  cursor: default;
}

.btn-primary {
  background: var(--btn-primary-bg);
  color: var(--btn-primary-fg);
}

.btn-primary:hover:not(:disabled) {
  background: var(--btn-primary-hover);
}

.btn-ghost {
  background: var(--surface);
  border-color: var(--border);
  color: var(--text);
  flex: 0 1 auto;
}

.btn-ghost.is-on {
  border-color: var(--pcg-orange);
  color: var(--warn-text);
  background: var(--warn-bg);
}

.tuning {
  margin-top: 0.7rem;
  display: grid;
  gap: 0.5rem;
}

.control-row {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  font-size: 0.82rem;
  color: var(--text-dim);
}

/* Direct children only — the segmented control's own labels are nested deeper
   and must stay flexible rather than pick up this fixed width. */
.control-row > label,
.control-row > .row-label {
  flex: 0 0 4.5rem;
}

/* 44px is the tap-target size both platform guidelines call for. It matters
   more than usual here: this is used outdoors, sometimes with gloves on. It
   also keeps every row in the tuning block the same height. */
.control-row select,
.control-row input[type="range"],
.control-row .segmented {
  flex: 1;
  min-width: 0;
  min-height: var(--control-height);
  accent-color: var(--pcg-green);
}

.control-row select {
  padding: 0.4rem 0.5rem;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 8px;
  font-family: var(--font-body);
  font-size: 0.82rem;
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
}

/* Segmented radio group (theme switch). The inputs are visually hidden and the
   labels are the visible control, so the browser still handles selection and
   arrow-key navigation natively. */
.segmented {
  display: flex;
  flex: 1;
  min-width: 0;
  border: 1px solid var(--border);
  border-radius: 8px;
  overflow: hidden;
  background: var(--surface);
}

.segmented label {
  flex: 1 1 0;
  min-width: 0;
  /* Centred via flex rather than padding so --control-height is exact. */
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: var(--control-height);
  padding: 0 0.3rem;
  text-align: center;
  font-size: 0.76rem;
  font-weight: 600;
  color: var(--text-dim);
  cursor: pointer;
  user-select: none;
  white-space: nowrap;
}

.segmented label:not(:first-of-type) {
  border-left: 1px solid var(--border);
}

.segmented input:checked + label {
  background: var(--btn-primary-bg);
  color: var(--btn-primary-fg);
}

/* The input is visually hidden, so the focus ring has to be drawn on the label
   or keyboard focus becomes invisible. */
.segmented input:focus-visible + label {
  outline: 2px solid var(--accent);
  outline-offset: -3px;
}

/* --------------------------------------------------------------- results -- */

.results {
  margin-top: 1.1rem;
}

.multi-note {
  margin: 0 0 0.7rem;
  font-size: 0.82rem;
  color: var(--text-dim);
}

.result {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 0.9rem 1rem 1rem;
  margin-bottom: 0.9rem;
}

.result-head {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  flex-wrap: wrap;
  margin-bottom: 0.85rem;
}

.badge {
  padding: 0.22rem 0.6rem;
  border-radius: 999px;
  background: var(--badge-bg);
  border: 1px solid var(--badge-border);
  color: var(--badge-text);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  white-space: nowrap;
}

.result-kind {
  margin: 0;
  font-family: var(--font-head);
  font-size: 1.02rem;
  font-weight: 600;
}

.warnings {
  display: grid;
  gap: 0.4rem;
  margin-bottom: 0.9rem;
}

.warning {
  display: flex;
  gap: 0.55rem;
  margin: 0;
  padding: 0.5rem 0.65rem;
  border-radius: 8px;
  background: var(--warn-bg);
  border-left: 3px solid var(--warn-border);
  font-size: 0.8rem;
  line-height: 1.45;
  color: var(--warn-text);
}

.warning-icon {
  flex: 0 0 auto;
  width: 1.1rem;
  height: 1.1rem;
  border-radius: 50%;
  background: var(--warn-icon-bg);
  color: var(--warn-icon-fg);
  font-weight: 700;
  font-size: 0.75rem;
  line-height: 1.1rem;
  text-align: center;
}

.fields {
  display: grid;
  grid-template-columns: minmax(7.5rem, 40%) 1fr;
  gap: 0.1rem 0.9rem;
  margin: 0;
  font-size: 0.85rem;
}

.fields dt {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  padding: 0.42rem 0;
  border-top: 1px solid var(--border);
}

.fields dd {
  display: flex;
  flex-direction: column;
  gap: 0.1rem;
  margin: 0;
  padding: 0.42rem 0;
  border-top: 1px solid var(--border);
  min-width: 0;
}

.fields dt:first-of-type,
.fields dd:first-of-type {
  border-top: 0;
}

.field-label {
  color: var(--text-dim);
}

.field-note,
.field-inferred {
  font-size: 0.68rem;
  letter-spacing: 0.02em;
  color: var(--text-faint);
}

.field-inferred {
  color: var(--warn-text);
  cursor: help;
}

.field-value {
  font-weight: 500;
  overflow-wrap: anywhere;
}

.field-raw {
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.7rem;
  color: var(--text-faint);
}

.field-link {
  color: var(--accent);
  overflow-wrap: anywhere;
}

/* ----------------------------------------------------------- raw payload -- */

.raw {
  margin-top: 1rem;
  border-top: 1px solid var(--border);
  padding-top: 0.7rem;
}

.raw summary {
  cursor: pointer;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--text-dim);
}

.raw-meta {
  display: grid;
  grid-template-columns: minmax(8rem, 45%) 1fr;
  gap: 0.15rem 0.9rem;
  margin: 0.7rem 0;
  font-size: 0.76rem;
  color: var(--text-dim);
}

.raw-meta dt {
  color: var(--text-faint);
}

.raw-meta dd {
  margin: 0;
  overflow-wrap: anywhere;
}

.raw-text {
  margin: 0;
  padding: 0.6rem 0.7rem;
  background: var(--surface-2);
  border-radius: 8px;
  font-family: ui-monospace, "Cascadia Mono", Consolas, monospace;
  font-size: 0.74rem;
  line-height: 1.6;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
}

/* Control characters shown as named tokens rather than invisible bytes. */
.ctrl {
  display: inline-block;
  margin: 0 1px;
  padding: 0 3px;
  border-radius: 3px;
  background: var(--ctrl-bg);
  color: var(--ctrl-fg);
  font-size: 0.66rem;
  vertical-align: 1px;
}

/* --------------------------------------------------------------- history -- */

.history {
  margin-top: 1.6rem;
  border-top: 1px solid var(--border);
  padding-top: 0.9rem;
}

.history-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.6rem;
  flex-wrap: wrap;
}

.history-head h2 {
  margin: 0;
  font-family: var(--font-head);
  font-size: 0.95rem;
  font-weight: 600;
  display: flex;
  align-items: center;
  gap: 0.45rem;
}

.history-count {
  min-width: 1.6rem;
  padding: 0.1rem 0.4rem;
  border-radius: 999px;
  background: var(--badge-bg);
  border: 1px solid var(--badge-border);
  color: var(--badge-text);
  font-family: var(--font-body);
  font-size: 0.72rem;
  font-weight: 600;
  text-align: center;
}

.history-actions {
  display: flex;
  gap: 0.4rem;
}

/* Narrower than the main action buttons: these are secondary, and the row has
   to survive a 320px screen alongside the heading. */
.history-actions .btn {
  min-height: 38px;
  padding: 0.45rem 0.7rem;
  font-size: 0.78rem;
}

.history-note {
  margin: 0.55rem 0 0;
  font-size: 0.72rem;
  line-height: 1.5;
  color: var(--text-faint);
}

.history-list {
  list-style: none;
  margin: 0.7rem 0 0;
  padding: 0;
  display: grid;
  gap: 0.35rem;
}

.history-row {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 0.15rem 0.6rem;
  width: 100%;
  min-height: var(--control-height);
  padding: 0.5rem 0.65rem;
  text-align: left;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 9px;
  font-family: var(--font-body);
  color: var(--text);
  cursor: pointer;
}

.history-row:hover {
  border-color: var(--pcg-green);
}

.history-time {
  font-size: 0.7rem;
  color: var(--text-faint);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}

.history-format {
  font-size: 0.7rem;
  font-weight: 600;
  color: var(--accent);
  white-space: nowrap;
}

.history-summary {
  grid-column: 1 / -1;
  font-size: 0.82rem;
  overflow-wrap: anywhere;
  /* Two lines is enough to identify a scan without the list becoming a wall. */
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.history-row.is-viewing {
  border-color: var(--pcg-green);
  background: var(--badge-bg);
}

.result-source {
  margin: 0 0 0.7rem;
  font-size: 0.74rem;
  color: var(--text-faint);
}

/* ---------------------------------------------------------------- footer -- */

.footer {
  padding: 0.9rem 1rem calc(0.9rem + env(safe-area-inset-bottom));
  text-align: center;
}

.footer p {
  margin: 0;
  font-size: 0.72rem;
  line-height: 1.5;
  color: var(--text-faint);
}
