body {
  --color-text: var(--color-black);
  /* Dirty-cream ground + mid-deep green. A muted, slightly greyed sand (not a
     bright near-white) so the light theme is easy on the eyes. The green reads
     clearly as green for links/text on it, AND is dark enough that the cream
     on-accent text punches out of the button fill. --theme-bg-muted (this minus
     10% L) is the sand highlight reused by both the dropdown and calendar hover. */
  --color-background: #e8e1cd;
  --color-accent: #0e7a4a;
  --color-warn: var(--color-red);
  --color-saved: var(--color-raspberry);

  --border-width: 2px;
  --tag-border-width: 1px;
  --calendar-border-width: 1px;
  /* Structural rules / hairlines are NEUTRAL, not green. Green is reserved for
     interaction (links, focus, active, primary actions), state (today, selected),
     and follows — so it reads as a signal, not as the default border colour.
     A foreground-derived tint adapts to both themes automatically. */
  --border-color: color-mix(in srgb, var(--theme-fg-color) 22%, transparent);
  /* A more emphatic neutral for prominent CONTENT dividers (date headings, the
     calendar weekday rule, the day drawer frame) — visible as structure without
     reaching for the interactive green. */
  --rule-color: color-mix(in srgb, var(--theme-fg-color) 45%, transparent);
  /* The focus indicator: the one place we deliberately spend green on chrome. */
  --focus-ring: var(--theme-accent-color);

  --theme-bg-color: var(--color-background);
  --theme-fg-color: var(--color-text);
  --theme-accent-color: var(--color-accent);
  --theme-warn-color: var(--color-warn);
  --theme-saved-color: var(--color-saved);
  /* Text/glyphs painted ON the accent fill (primary buttons, badges, the today
     badge, checked-box ticks, chips). The on-accent colour matches the page
     background — the "punched out" look — and stays legible in both themes
     because each pairs a light ground with a dark-enough green (cream on green in
     light, dark plum on the brighter green in dark). */
  --theme-on-accent: var(--color-background);
  /* +24 (was +30) lifts secondary text contrast against the saturated grounds
     without letting muted info compete with primary text. */
  --theme-fg-muted: hsl(from var(--theme-fg-color) h s calc(l + 24));
  --theme-bg-muted: hsl(from var(--theme-bg-color) h s calc(l - 10));
  /* The today badge's fill. In light it deliberately MATCHES --theme-bg-muted so
     the pill melts into the cell's hover/selected wash (a nice "absorbed on hover"
     effect). Dark overrides this with a stronger lift — there the badge must stay
     visible, since +5 on the near-black plum leaves it lost on a hovered cell. */
  --theme-bg-emphasis: hsl(from var(--theme-bg-color) h s calc(l - 10));
  --theme-accent-muted: hsl(from var(--theme-accent-color) h calc(s - 60) calc(l + 15));
  /* An interactive field's resting underline. More present than a structural
     hairline (--border-color, 22%) so an empty input reads as fillable rather
     than blending into the ground — the login/settings fields were near-invisible
     at 22% on the saturated grounds. Derived from fg so it adapts to both themes. */
  --field-border-color: color-mix(in srgb, var(--theme-fg-color) 40%, transparent);
  /* The calendar grid: visible enough to read as a grid on the saturated pink,
     still lighter than a content rule. (22% washed out against the rose ground.) */
  --calendar-border-color: color-mix(in srgb, var(--theme-fg-color) 30%, transparent);

  color-scheme: light;
  background-color: var(--theme-bg-color);
  color: var(--theme-fg-color);
  transition: background-color 0.2s ease, color 0.2s ease;
}

/* Dark theme. The toggle (theme_controller.js) resolves the user's
   system/light/dark preference to a concrete light|dark value and sets it on
   <html data-theme>, so we only need a single dark override here — the muted
   tokens are recomputed in the opposite direction from light. */
html[data-theme="dark"] body {
  /* Soft, faintly warm off-white rather than near-#fff: pure white halates
     against the dark plum ground and reads as harsh. */
  --color-text: #d4ced3;
  --color-background: #17131a;
  /* Slightly calmer green and raspberry so links/hearts read as accents
     instead of glowing against the dark field. */
  --color-accent: #38c08a;
  --color-warn: #f0837a;
  --color-saved: #ec6f98;

  /* On the brighter dark-theme green, the dark plum ground reads far better than
     white (which glares). */
  --theme-on-accent: var(--color-background);

  /* Muted recalcs run opposite to light: dim the bright fg, lift the dark bg.
     -20 keeps secondary text comfortably readable against the dark ground. */
  --theme-fg-muted: hsl(from var(--theme-fg-color) h s calc(l - 20));
  --theme-bg-muted: hsl(from var(--theme-bg-color) h s calc(l + 5));
  /* The muted wash only lifts +5 here (calm hairlines/hovers on the near-black
     plum), which left the today badge nearly invisible — and gone entirely on a
     hovered/selected cell, since those use the muted wash too. +10 reads as a
     clear dark-sand chip on base AND hovered cells without glowing. */
  --theme-bg-emphasis: hsl(from var(--theme-bg-color) h s calc(l + 10));
  --theme-accent-muted: hsl(from var(--theme-accent-color) h calc(s - 35) calc(l - 12));

  color-scheme: dark;
}

/* Typed text is foreground, not green — green is an interaction signal, not the
   default text colour for a passive field. The accent now appears on a field
   only when it's focused (see the field underline rules). */
input {
  color: var(--theme-fg-color);
}
