/* Shared tokens and primitives. Page-specific styles live in each page's <style>. */
:root {
  /*
   * Declared, not assumed. Without this a browser in dark mode applies its own
   * dark chrome to form controls while every fill here stays light, which is
   * the one failure mode worse than having no dark appearance at all. The dark
   * palette is below.
   */
  color-scheme: light;
  --paper: #FBFAF7;      /* the page */
  --surface: #ffffff;    /* raised: a panel, a card, a field */
  --ink: #1B1A17;
  /*
   * Text that sits ON a filled colour rather than on the page.
   *
   * Separate tokens because the fill and its text do not move together between
   * appearances. --ink is near-black in light and near-white in dark, so
   * `background: var(--ink); color: #fff` is a perfectly readable button in
   * light and an invisible one in dark — which is the exact failure
   * dark-mode.md describes as "dark text on a dark background".
   */
  --on-accent: #ffffff;  /* on --stamp */
  --on-ink: #ffffff;     /* on --ink */
  --on-danger: #ffffff;  /* on --danger */
  --on-free: #ffffff;    /* on --ochre-ink, the "this one is free" chip */
  --stamp: #4B3FCC;      /* primary action, filled cups */
  --stamp-ink: #231C7A;
  --stamp-wash: #EFEEFF;
  --ochre: #C08A1E;      /* rewards */
  --ochre-ink: #5A4008;
  --ochre-wash: #FBF2DC;
  --hair: #DFDAD0;       /* dividers and hairlines: decorative, no contrast floor */
  /*
   * The edge of something you can type in or press.
   *
   * Separate from --hair on purpose. An input is #fff on a --paper page —
   * 1.04:1 — so its border is the only thing that says a control is there, and
   * WCAG 1.4.11 (the standard Apple's own accessibility page cites) wants 3:1
   * for a boundary that identifies a control. --hair is 1.39:1 on white.
   * #8A8275 is 3.80:1 on white and 3.64:1 on paper, so it holds on both.
   *
   * Not applied to --hair globally: most of its 39 uses in the dashboard are
   * table rules and section dividers, where 3:1 is not required and darkening
   * them would coarsen the page for nothing.
   */
  --edge: #8A8275;
  /*
   * Hebrew beside all-caps Latin.
   *
   * `text-transform: uppercase` does nothing to Hebrew — it has no case — so a
   * micro-label that reads as confident small caps in English renders smaller
   * and lighter in Hebrew. Apple's right-to-left guidance is to raise the RTL
   * size "by about 2 points" to rebalance it.
   *
   * 1.5px, not 2pt (2.67px): Apple's figure is calibrated against 17pt body
   * text, and these labels are 11-13px, where a full 2pt is a 20% jump that
   * would re-wrap the rows they sit in. Scaled deliberately; worth a look on a
   * real device.
   */
  --he-caps-bump: 1.5px;
  --sunken: #F3F0EA;
  --muted: #6B655C;
  --danger: #B3261E;
  --danger-edge: #C9756E;  /* a destructive outline has to be findable: 3.36:1 on white */
  --danger-wash: #FDF3F2;
  --ok: #1E6B3A;
  --ok-wash: #EAF6EE;
  --radius: 10px;
  --display: 'Bricolage Grotesque', system-ui, sans-serif;
  --text: Inter, system-ui, -apple-system, 'Segoe UI', sans-serif;
}

* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0; background: var(--paper); color: var(--ink);
  font: 400 15px/1.5 var(--text);
}
[hidden] { display: none !important; }
a { color: var(--stamp); }
h1, h2, h3 { font-family: var(--display); letter-spacing: -.02em; line-height: 1.1; }

label { display: block; font-size: .88rem; color: var(--muted); margin: 0 0 .3rem; }
input, select, textarea {
  width: 100%; padding: .7rem .8rem; font: inherit; color: var(--ink);
  background: var(--surface); border: 1.5px solid var(--edge); border-radius: 8px;
}
textarea { resize: vertical; min-height: 6rem; }
input:focus, select:focus, textarea:focus, button:focus-visible {
  outline: 2px solid var(--stamp); outline-offset: 1px; border-color: var(--stamp);
}
input[type=checkbox], input[type=radio] { width: auto; accent-color: var(--stamp); }
.field { margin-bottom: 1rem; }
.hint { font-size: .82rem; color: var(--muted); margin-top: .3rem; }

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .4rem;
  padding: .75rem 1.1rem; font: 500 1rem var(--text); border-radius: 8px;
  border: 1.5px solid transparent; cursor: pointer; text-decoration: none;
}
.btn-primary { background: var(--stamp); color: var(--on-accent); }
.btn-primary:hover { background: var(--stamp-ink); }
.btn-dark { background: var(--ink); color: var(--on-ink); }
.btn-dark:hover { background: var(--stamp); }
.btn-secondary { background: var(--surface); color: var(--ink); border-color: var(--edge); }
.btn-secondary:hover { border-color: var(--ink); }
.btn-ghost { background: transparent; color: var(--muted); border-color: var(--edge); }
.btn-danger { background: var(--surface); color: var(--danger); border-color: var(--danger-edge); }
.btn:disabled { opacity: .5; cursor: default; }
.btn-block { width: 100%; }

.msg { padding: .7rem .85rem; border-radius: 8px; font-size: .92rem; }
.msg-ok { background: var(--ok-wash); color: var(--ok); }
.msg-bad { background: var(--danger-wash); color: var(--danger); }
.msg-info { background: var(--stamp-wash); color: var(--stamp-ink); }

/* The card mechanic: a row of tapered cups. */
.cups { display: flex; flex-wrap: wrap; gap: 6px; align-items: flex-end; }
.cup {
  width: 22px; height: 29px; border: 2px solid var(--ink);
  border-radius: 2px 2px 7px 7px; clip-path: polygon(0 0, 100% 0, 86% 100%, 14% 100%);
}
.cup.on { background: var(--stamp); border-color: var(--stamp); }
.cups.lg .cup { width: 32px; height: 42px; border-width: 2.5px; }
.cups.sm .cup { width: 9px; height: 12px; border-width: 1.5px; border-radius: 1px 1px 3px 3px; }
.cups.sm { gap: 3px; flex-wrap: nowrap; }

.tag {
  display: inline-block; font-size: .75rem; padding: 1px 8px; border-radius: 99px;
  border: 1px solid var(--hair); color: var(--muted); white-space: nowrap;
}
.tag-reward { border-color: var(--ochre); color: var(--ochre-ink); background: var(--ochre-wash); }
.tag-stamp { border-color: var(--stamp); color: var(--stamp-ink); background: var(--stamp-wash); }
.tag-bad { border-color: #EBC5C1; color: var(--danger); background: var(--danger-wash); }

table { width: 100%; border-collapse: collapse; font-size: .92rem; }
th { text-align: left; font-weight: 500; color: var(--muted); padding: 8px 10px; border-bottom: 1px solid var(--hair); white-space: nowrap; }
td { padding: 9px 10px; border-bottom: 1px solid var(--sunken); vertical-align: middle; }
.num { font-variant-numeric: tabular-nums; text-align: right; }
.table-wrap { overflow-x: auto; }
.empty { padding: 28px 16px; color: var(--muted); text-align: center; }

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; }
}

/*
 * Touch targets. A finger needs about 44px; a mouse does not, and widening
 * everything for the mouse would only spread the interface out. So the
 * minimum applies on small screens and on any coarse pointer, and the
 * desktop layouts stay as tight as they were drawn.
 */
@media (max-width: 40rem), (pointer: coarse) {
  .btn { min-height: 44px; }
  input[type=checkbox], input[type=radio] { width: 24px; height: 24px; }
  .lang-switch button { min-height: 44px; padding-inline: .85rem; }
  /*
   * Safari zooms the whole page when a focused field is under 16px, and then
   * leaves it zoomed — the page is suddenly wider than the screen and the rest
   * of the form is off to one side. Body text is 15px and fields inherit it, so
   * every field on every form did this. 16px only where a finger is the
   * pointer; the desktop type scale is untouched.
   */
  input, select, textarea { font-size: 16px; }
}

/*
 * The notch and the home indicator, as tokens.
 *
 * env() is only meaningful once the viewport says viewport-fit=cover, and it
 * resolves to zero on anything that has no inset — so these are safe to add to
 * any edge. The @supports guard is not decoration: in an engine without env()
 * the whole declaration is invalid at computed-value time, and a bare fallback
 * in the custom property would not survive to be used.
 */
:root { --sa-t: 0px; --sa-r: 0px; --sa-b: 0px; --sa-l: 0px; }
@supports (top: env(safe-area-inset-top)) {
  :root {
    --sa-t: env(safe-area-inset-top);
    --sa-r: env(safe-area-inset-right);
    --sa-b: env(safe-area-inset-bottom);
    --sa-l: env(safe-area-inset-left);
  }
}

/* Language switch (business-facing pages). Small, quiet, always reachable. */
.lang-switch { display: inline-flex; gap: 2px; padding: 2px; border: 1px solid var(--hair); border-radius: 999px; background: var(--surface); }
.lang-switch button {
  padding: .25rem .6rem; font: 500 .82rem var(--text); color: var(--muted);
  background: transparent; border: 0; border-radius: 999px; cursor: pointer;
}
.lang-switch button.on { background: var(--ink); color: var(--on-ink); }
.lang-switch button:focus-visible { outline: 2px solid var(--stamp); outline-offset: 1px; }

/* Right-to-left pages: keep one-directional utilities honest. */
[dir="rtl"] .num { text-align: left; }

/*
 * The dark appearance.
 *
 * Opted into per page with <html class="adaptive">, not applied globally, and
 * that is deliberate. base.css is shared by the marketing page and by the
 * scanner: the marketing page commits to one light look with its own
 * hard-coded colours, and the scanner is permanently dark already (which
 * dark-mode.md explicitly allows: "In rare cases, consider using only a dark
 * appearance"). Swapping tokens underneath either would half-convert it, which
 * is worse than not converting it at all.
 *
 * The relationship between the three surfaces inverts rather than translating:
 * in light, raised is brighter than the page; in dark, raised is brighter and
 * recessed is darker still. These are not inversions of their light
 * counterparts — dark-mode.md: "while many colors are inverted, some are not."
 *
 * Every pair here is computed, not eyeballed. Body text clears Apple's 7:1
 * aspiration for custom colours (15.9:1 on the page, 14.5:1 on a panel), the
 * 13px hints clear 4.5:1 (7.3:1 and 6.7:1), and --edge clears the 3:1 the
 * control boundary needs (3.4:1 on the page, 3.1:1 on a panel).
 */
html.adaptive { color-scheme: light dark; }

@media (prefers-color-scheme: dark) {
  html.adaptive {
    --paper: #171614;
    --surface: #211F1C;
    /* Below the page in dark, above it in light: "recessed" is a direction,
       not a brightness. */
    --sunken: #100F0E;
    --ink: #F3F0EA;
    --muted: #ABA49A;
    --hair: #343229;
    --edge: #78726A;
    /* The accent brightens so it still reads on a dark page; the text on it
       therefore has to darken, which is what --on-accent is for. */
    --stamp: #9B92FF;
    --stamp-ink: #CFC9FF;
    --stamp-wash: #241F4D;
    --on-accent: #14122B;
    --on-ink: #171614;
    /* Both fills brighten in dark, so both texts darken with them. */
    --on-danger: #2B0F0C;
    --on-free: #2B2008;
    --ochre: #E0A93A;
    --ochre-ink: #F0CE7E;
    --ochre-wash: #3A2C0C;
    --danger: #F08A82;
    --danger-wash: #3A1613;
    --danger-edge: #C9756E;
    --ok: #6FD08C;
    --ok-wash: #13301D;
  }
}
