/* ═══════════════════════════════════════════════════════════════════════════
   WCE ARC — design tokens.

   OURS. Forked, not vendored: nothing imports this from anywhere and there is
   no package to re-pull. It is a port of a system used by another family of
   applications — warm-paper ground, white card surfaces, deep ink headings, one
   accent, a mono eyebrow label, serif display type — rebuilt here as plain CSS.

   Three things were deliberately not carried across:

     - The accent. The source anchors on a colour that is another organisation's
       corporate brand, and ships wordmark rules to match. This is a homeowners'
       association in Wailuku with no connection to it, so wearing that identity
       would be wrong however good it looks. The accent below is this project's
       own. Nothing structural changed with it, so a different accent is the four
       values under "Accent" and nothing else.
     - Every brand-literal colour scale and identifier from the source. Nothing
       here is named after another organisation.
     - Tailwind. The source expresses components as utility classes inside React
       components; this app is server-rendered HTML with no build step, so the
       components are plain CSS in app.css built on these tokens.

   The semantic names (bg, surface, line, head, muted, accent…) describe a ROLE
   rather than a colour, which is what makes the dark theme a swap of values
   rather than a second stylesheet.
   ═══════════════════════════════════════════════════════════════════════════ */

@import url('https://fonts.googleapis.com/css2?family=Noto+Sans:wght@400;500;600;700&family=Noto+Serif:wght@400;500;600&family=Noto+Sans+Mono:wght@400;500&display=swap');

:root {
  /* Every colour is declared twice on purpose. The first is a plain value, the
     second uses light-dark(); a browser that does not understand the function
     drops the second line at parse time and keeps the first, so an old device
     gets the light theme rather than an unstyled page. The pair is adjacent so
     the two cannot drift.

     Which half light-dark() picks is decided by `color-scheme`, and the forcing
     rules below set that per choice. That is the whole mechanism: no duplicated
     block of dark values, and no media query to keep in step. */

  /* --- Ground and structure ---------------------------------------------- */
  --bg:            #fbfaf8;
  --bg:            light-dark(#fbfaf8, #0b1520);   /* warm paper / deep ground */
  --surface:       #ffffff;
  --surface:       light-dark(#ffffff, #111e2b);   /* cards sit on the ground */
  --sunk:          #eef1f5;
  --sunk:          light-dark(#eef1f5, #16232f);   /* wells: table heads */
  --line:          #e6ebf1;
  --line:          light-dark(#e6ebf1, rgba(255, 255, 255, .10));
  --line-strong:   #cbd5e1;
  --line-strong:   light-dark(#cbd5e1, rgba(255, 255, 255, .18));

  /* --- Ink ---------------------------------------------------------------- */
  --head:          #10202f;
  --head:          light-dark(#10202f, #f1f5f9);
  --body:          #1a2530;
  --body:          light-dark(#1a2530, #d9e3ec);
  --ink:           #10202f;
  --ink:           light-dark(#10202f, #eaf1f8);
  --muted:         #566572;
  --muted:         light-dark(#566572, #a2b2c0);   /* 5.75:1 light, 7.77:1 dark */
  /* Labels, table heads, item numbers. Solved against --sunk, the darkest ground
     it ever sits on and so the binding constraint: 4.84:1 there clears AA
     everywhere. The system this was forked from uses a lighter value that does
     NOT clear AA on paper, despite its file saying it does. */
  --faint:         #5c6b78;
  --faint:         light-dark(#5c6b78, #8495a3);
  --on-accent:     #ffffff;
  --on-accent:     light-dark(#ffffff, #07182a);

  /* --- Accent -------------------------------------------------------------
     Blue, and this project's own. Deliberately not the source's #0060AE, which
     is another organisation's corporate colour; this is a deeper, quieter blue
     that suits warm paper. The ink ramp above is tinted to match it — a blue
     accent against green-black text reads as two systems on one page. Change
     these four and the app changes; if the ink stops agreeing with them, retune
     head/body/ink/muted/faint at the same lightness and measure again. */
  --accent:              #1a5289;
  --accent:              light-dark(#1a5289, #6fb0e8);
  --accent-ink:          #14416e;
  --accent-ink:          light-dark(#14416e, #93c6f0);   /* accent as TEXT */
  --accent-tint:         #e8eef6;
  --accent-tint:         light-dark(#e8eef6, rgba(111, 176, 232, .16));
  --accent-tint-border:  #cddced;
  --accent-tint-border:  light-dark(#cddced, rgba(111, 176, 232, .34));

  /* --- Status ------------------------------------------------------------- */
  --success:  #1f7a4d;
  --success:  light-dark(#1f7a4d, #4fb07f);
  --warning:  #8a5a00;
  --warning:  light-dark(#8a5a00, #d6a04a);
  --danger:   #a8322a;
  --danger:   light-dark(#a8322a, #e08279);

  /* --- Type --------------------------------------------------------------- */
  --serif: 'Noto Serif', Georgia, serif;
  --sans:  'Noto Sans', system-ui, -apple-system, sans-serif;
  --mono:  'Noto Sans Mono', ui-monospace, 'SFMono-Regular', monospace;

  --t-eyebrow: 11px;   /* mono, uppercase, wide tracking */
  --t-index:   12px;   /* mono data, counts */
  --t-small:   13px;
  --t-body-s:  14px;
  --t-body:    15px;
  --t-lede:    17px;
  --t-h3:      20px;
  --t-h2:      clamp(22px, 2.4vw, 26px);
  --t-h1:      clamp(28px, 4vw, 34px);

  /* --- Space (4px base) --------------------------------------------------- */
  --s-1: 4px;  --s-2: 8px;  --s-3: 12px; --s-4: 16px; --s-5: 20px;
  --s-6: 24px; --s-7: 32px; --s-8: 40px; --s-9: 56px; --s-10: 80px;

  /* --- Geometry ----------------------------------------------------------- */
  --r-sm: 6px; --r: 8px; --r-md: 12px; --r-lg: 14px; --r-xl: 20px;
  /* A shadow has two layers and light-dark() takes two arguments, both separated
     by commas, so the function cannot wrap the whole value without ambiguity.
     The COLOUR flips instead and the geometry stays put, which is the part that
     actually differs: a shadow on a dark ground has to be darker and deeper to
     read at all. */
  --shadow-near: rgba(16, 32, 47, .05);
  --shadow-near: light-dark(rgba(16, 32, 47, .05), rgba(0, 0, 0, .35));
  --shadow-far:  rgba(16, 32, 47, .18);
  --shadow-far:  light-dark(rgba(16, 32, 47, .18), rgba(0, 0, 0, .6));
  --shadow-card: 0 1px 2px var(--shadow-near), 0 8px 24px -16px var(--shadow-far);
  --shadow-lift: 0 2px 4px var(--shadow-near), 0 24px 48px -24px var(--shadow-far);

  /* --- Measure ------------------------------------------------------------ */
  --column:      780px;   /* a reading column: forms, records */
  --column-wide: 1080px;  /* tables that need the room */
  --margin: 24px;
  --nav-h: 60px;
}

/* The theme, and how a person chooses it.
 *
 * `color-scheme` is what light-dark() above reads, so these three rules are the
 * entire switch. No stored copy of the palette, nothing to keep in step.
 *
 *   no attribute  follow the operating system (the default)
 *   light / dark  the person chose, and `only` stops the OS overriding them
 *
 * The attribute is written into the HTML by the server from a cookie, so the
 * first paint is already correct. A script that applied it afterwards would
 * flash the wrong theme on every page load. See src/lib/theme.js. */
:root                    { color-scheme: light dark; }
:root[data-theme="light"] { color-scheme: only light; }
:root[data-theme="dark"]  { color-scheme: only dark; }

@media (max-width: 880px) { :root { --margin: 20px; --nav-h: 56px; } }
@media (max-width: 480px) { :root { --margin: 16px; } }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001ms !important; transition-duration: .001ms !important; }
}
