/* ═══════════════════════════════════════════════════════════════════
   pquote — Cool Neutral base layer
   ───────────────────────────────────────────────────────────────────
   Shared tokens + primitives for every page. Ported from pzip.ai's
   Cool Neutral system (zipper/ZIPPER-BUILD-SPEC.md is the source of
   truth). Only the surface is shared — pquote keeps its own page
   skeletons, per the workspace rule against reusing a layout twice.

   Load this BEFORE any page stylesheet. A page must not declare its
   own :root token block; if it does, it will shadow these and the two
   identities drift apart again, which is the whole problem this file
   exists to end.
   ═══════════════════════════════════════════════════════════════════ */

:root {
  /* Ground — neutral, so the one accent is free to mean "action". */
  --bg:        #F1F3F4;
  --surface:   #FFFFFF;
  --surface-2: #F8F9FA;

  --text:  #1F2125;   /* 14.5:1 on --bg      */
  --muted: #474B4F;   /* 8.8:1  on --surface */

  /* THE TWO-TOKEN RULE — these are NOT interchangeable.
     --rule is decorative and is allowed to vanish in direct sunlight.
     --border marks anything the user touches: inputs, buttons, row
     hit-targets. Never put --rule on a hit target, and never use
     either as a status mark. */
  --rule:   #DADCE0;  /* 1.4:1 — decorative dividers ONLY  */
  --border: #A9AEB3;  /* 2.2:1 — interactive borders ONLY  */

  /* Exactly ONE accent hue. Semantic colours below are status and
     never get promoted to a second accent. */
  --accent:       #3A5E30;  /* 7.4:1 on --surface */
  --accent-hover: #2E4E24;
  --accent-pale:  #E6F0E0;

  --red:   #B3261E;  --red-pale:   #FCEEEE;
  --amber: #8A6E20;  --amber-pale: #FBF3DF;
  --green: #2A5020;  --green-pale: #E6F4EA;

  --radius:    14px;
  --radius-sm: 8px;
  --pill:      999px;

  /* Panels get elevation, not outlines. */
  --shadow-1: 0 1px 2px rgba(31,33,37,.08), 0 4px 16px rgba(31,33,37,.06);
  --shadow-2: 0 10px 40px rgba(31,33,37,.16);

  /* One sans. DM Mono is for numerals that line up in columns and
     nothing else — there is no serif role in this system. */
  --sans: 'Nunito', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --mono: 'DM Mono', ui-monospace, 'SFMono-Regular', monospace;

  --tap: 44px;   /* gloved-hand floor on every control */
}

/* ═══ RESET ═══ */
*, *::before, *::after { box-sizing: border-box; }

html {
  /* Set here, not only on body, so nothing can fall back to the UA serif. */
  font-family: var(--sans);
  -webkit-text-size-adjust: 100%;
  /* Deliberately no overflow-x/max-width here — on iOS Safari those
     kill the page's vertical scroll when they land on <html>. */
}

/* Form controls do NOT inherit font-family — the UA sheet hands them Arial.
   Without this, any <button> that isn't .btn silently renders its label in
   Arial instead of Nunito. Found on /voice's .mic-btn. */
button, input, select, textarea { font-family: inherit; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4, h5, h6 {
  font-family: var(--sans);   /* no serif role exists */
  color: var(--text);
  line-height: 1.2;
  margin: 0 0 .5em;
}

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

img, svg, video { max-width: 100%; }

/* Load-bearing: many JS-toggled elements depend on this existing
   exactly once. Without it, state changes apply but nothing moves. */
.hidden { display: none !important; }

/* ═══ NUMERALS ═══
   Mono is reserved for figures that stack in a column, and always with
   tabular-nums so digits don't jitter as values change. */
.num, .tabular {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
}

/* ═══ BUTTONS ═══
   Full pills, sentence case. Never uppercase mono. */
.btn,
.btn-primary,
.btn-secondary,
.btn-danger {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: var(--tap);
  padding: 11px 20px;
  border-radius: var(--pill);
  font-family: var(--sans);
  font-size: 15px;
  font-weight: 600;
  line-height: 1.2;
  cursor: pointer;
  border: 1px solid transparent;
  transition: background .15s, border-color .15s, color .15s;
}

.btn-primary {
  background: var(--accent);
  border-color: var(--accent);
  color: #fff;
}
.btn-primary:hover:not(:disabled) {
  background: var(--accent-hover);
  border-color: var(--accent-hover);
}

.btn-secondary {
  background: var(--surface);
  border-color: var(--border);   /* interactive — --rule would be wrong */
  color: var(--text);
}
.btn-secondary:hover:not(:disabled) {
  background: var(--surface-2);
  border-color: var(--accent);
  color: var(--accent);
}

/* Tertiary action — carries no chrome of its own, so it can sit inline
   inside a sentence ("No account? Create one") without reading as a
   third button weight. Still a 44px pill: it is a hit target. */
.btn-ghost {
  background: transparent;
  border-color: transparent;
  color: var(--accent);
  padding: 11px 14px;
}
.btn-ghost:hover:not(:disabled) { background: var(--accent-pale); }

.btn-danger {
  background: var(--red-pale);
  border-color: transparent;
  color: var(--red);
}
.btn-danger:hover:not(:disabled) { background: var(--red); color: #fff; }

.btn:disabled,
.btn-primary:disabled,
.btn-secondary:disabled,
.btn-danger:disabled { opacity: .5; cursor: not-allowed; }

:where(button, a, input, select, textarea):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ═══ FORM CONTROLS ═══ */
input[type="text"], input[type="email"], input[type="password"],
input[type="number"], input[type="search"], input[type="tel"],
input[type="url"], input[type="date"], select, textarea {
  width: 100%;
  min-height: var(--tap);
  padding: 11px 14px;
  border: 1px solid var(--border);   /* the user touches it */
  border-radius: var(--radius-sm);
  background: var(--surface);
  color: var(--text);
  font-family: var(--sans);
  font-size: 16px;   /* below 16px iOS Safari zooms the viewport on focus */
  outline: none;
  transition: border-color .15s, box-shadow .15s;
}
input:focus, select:focus, textarea:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-pale);
}
textarea { min-height: 96px; resize: vertical; line-height: 1.5; }

label, .flabel {
  display: block;
  font-size: 13px;
  font-weight: 600;
  color: var(--muted);
  margin-bottom: 6px;
}

/* ═══ SURFACES ═══
   Cards carry elevation, never a border. */
.card, .panel {
  background: var(--surface);
  border-radius: var(--radius);
  box-shadow: var(--shadow-1);
  padding: 18px;
}
.modal, .popover {
  background: var(--surface);
  border-radius: var(--radius);
  box-shadow: var(--shadow-2);
}

/* Decorative separator — safe to use --rule here because nothing is
   clickable on it. */
.divider { height: 1px; background: var(--rule); border: 0; margin: 16px 0; }

/* ═══ TABLES ═══
   Hairline rows, not boxed grids. */
table { width: 100%; border-collapse: collapse; }
th, td {
  padding: 12px 10px;
  text-align: left;
  border-bottom: 1px solid var(--rule);
}
th {
  font-size: 12px;
  font-weight: 700;
  color: var(--muted);
  letter-spacing: .02em;
}
td.num, th.num, td.amount {
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  text-align: right;
}

/* ═══ BADGES ═══
   Borderless pills. Status is carried by TEXT COLOUR — pale fills wash
   out in sunlight, coloured text survives. Never encode status by fill
   alone, and never add a border back. */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 4px 11px;
  border: 0;
  border-radius: var(--pill);
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 600;
  line-height: 1.4;
  white-space: nowrap;
}
.badge-accent  { color: var(--accent); background: var(--accent-pale); }
.badge-success { color: var(--green);  background: var(--green-pale); }
.badge-warn    { color: var(--amber);  background: var(--amber-pale); }
.badge-error   { color: var(--red);    background: var(--red-pale); }
.badge-neutral { color: var(--muted);  background: var(--surface-2); }

/* ═══ TOAST ═══
   Styling lives here; behaviour lives in /js/toast.js. */
#toast {
  position: fixed;
  left: 50%;
  bottom: calc(24px + env(safe-area-inset-bottom, 0px));
  transform: translate(-50%, 12px);
  z-index: 9999;
  display: flex;
  align-items: center;
  gap: 10px;
  max-width: min(92vw, 460px);
  padding: 13px 20px;
  border-radius: var(--pill);
  background: var(--text);
  color: var(--surface);
  font-family: var(--sans);
  font-size: 15px;
  font-weight: 600;
  box-shadow: var(--shadow-2);
  opacity: 0;
  pointer-events: none;
  transition: opacity .22s ease, transform .22s ease;
}
#toast.show { opacity: 1; transform: translate(-50%, 0); pointer-events: auto; }
#toast.toast-ok    { background: var(--green); }
#toast.toast-error { background: var(--red); }
#toast button {
  min-height: 32px;              /* inside an already-tappable toast */
  padding: 5px 14px;
  border: 0;
  border-radius: var(--pill);
  background: rgba(255,255,255,.18);
  color: inherit;
  font-family: var(--sans);
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
}
#toast button:hover { background: rgba(255,255,255,.3); }

/* ═══ DESKTOP ═══
   Mobile-first: base rules above are the phone. Overrides start here. */
@media (min-width: 769px) {
  .card, .panel { padding: 22px; }
}
