/* ============================================================
   Tokens: type, colour, reset, page frame.
   Everything nothing else is allowed to redefine. If a colour is wrong,
   it is wrong here. Loaded before app.css.
   ============================================================ */

/* Archivo, latin subset. One variable file covering the whole weight axis —
   Google serves all four of the weights we use from this single URL, so four
   static faces would have been four downloads of the same thing.

   Self-hosted because the Google Fonts @import was the app's only third-party
   request, and the first genuinely offline launch would have fallen back to
   system sans.

   font-display:optional, not swap. swap paints fallback text and then reflows
   to Archivo — a flash of the wrong font on first load. optional gives the
   font a moment and, if it isn't ready, renders fallback for that load only
   and never swaps. From the second load on the service worker has it cached
   and it is instant. Same "never flash, never shift" standard the markup
   data-theme applies to colour. */
@font-face{
  font-family:'Archivo';
  font-style:normal;
  font-weight:100 900;
  font-display:optional;
  src:url('../fonts/archivo-latin-var.woff2') format('woff2');
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,
                U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,
                U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
}

:root{
  --paper:#E9EDEF;
  --surface:#FFFFFF;
  --panel:#FBFCFC;
  --ink:#16242B;
  --ink-2:#5C6E77;
  --ink-3:#8A9AA2;
  --line:#D3DADE;
  --accent:#0E7C6B;
  --accent-soft:#DDEDE9;
  --flag:#B23A2B;
  --warn:#B4761A;
  --on-accent:#FFFFFF;
  --accent-hover:#0A6558;
  --radius:5px;
  --band:#2E8B57;
  color-scheme:light;
  font-synthesis-weight:none;
}

:root[data-theme="dark"]{
  --paper:#0F171B;
  --surface:#18242A;
  --panel:#141F24;
  --ink:#E7EEF0;
  --ink-2:#94A7AF;
  --ink-3:#6D818B;
  --line:#26343A;
  --accent:#3BBBA1;
  --accent-soft:#123630;
  --flag:#E4715A;
  --warn:#E0A34B;
  --on-accent:#0F171B;
  --accent-hover:#55CFB5;
  color-scheme:dark;
}

/* Must stay ahead of app.css. If it drifts after, every padding is zeroed. */
*{box-sizing:border-box;margin:0;padding:0}

/* The `hidden` attribute is only a UA-stylesheet `display:none`, so ANY rule
   that sets display on the element beats it — and .install-card and
   .update-banner both set display:flex. Without this they render regardless
   of `hidden`, as empty boxes. Needed before any component sets display. */
[hidden]{display:none!important}

html{-webkit-text-size-adjust:100%}

body{
  background:var(--paper);
  color:var(--ink);
  font-family:'Archivo','Helvetica Neue',Helvetica,Arial,sans-serif;
  font-size:16px;
  line-height:1.45;
  /* The bottom inset matters once installed: standalone on a phone with a
     home indicator, the last row would otherwise sit under it. */
  padding:0 0 calc(4rem + env(safe-area-inset-bottom));
  -webkit-font-smoothing:antialiased;
}

/* .wrap is defined HERE and nowhere else.
   `padding` is a shorthand, so it resets padding-top to 0 — which is why an
   unqualified `main { padding-top }` (specificity 0,0,1) silently lost to
   `.wrap` (0,1,0). main.wrap (0,1,1) wins on specificity regardless of source
   order. The two rules are one idea, so they stay adjacent: do not add a
   second .wrap rule in app.css, or source order starts deciding and this
   stops being predictable. */
.wrap{max-width:620px;margin:0 auto;padding:0 1rem}
main.wrap{padding-top:1.5rem}

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