/* ══════════════════════════════════════════════════════════════════════════
   Homeground — design tokens

   Three rules hold this together:

   1. **Square.** Nothing is rounded. `--r-full` exists only for shapes that are
      circular by nature — a status dot, a spinner.

   2. **One hue at a time.** Instead of a rainbow palette, each area of the app
      picks a hue and everything inside it — charts, bars, legends, accents —
      is a shade of that one hue. `--c-1` (palest) through `--c-9` (deepest) are
      re-pointed by `[data-hue]`:

          purple   the shell, and anything without an area of its own
          green    GroundUp
          red      ForFun
          blue     ForWork

      A chart never names a colour; it asks for `var(--c-4)` and gets the right
      shade of wherever it is.

   3. **Flat.** No gradients. Borders do the separating, not shadows. Shadows
      survive only where they carry meaning — something floating above the page.

   Light is defined on bare `:root`. Dark redefines the same names under both
   `prefers-color-scheme` (guarded, so an explicit light choice still wins) and
   `[data-theme="dark"]` (so the in-app toggle wins in both directions). No
   colour is ever defined only inside one of those blocks.
   ══════════════════════════════════════════════════════════════════════════ */

:root {
  color-scheme: light;

  /* ── hue ramps ───────────────────────────────────────────────────────────
     Nine steps each, 1 palest to 9 deepest. Deliberately desaturated: these
     are read for hours at a time, and a vivid ramp turns a dense table into
     something you squint at. */

  --purple-1: #f2f0f6;
  --purple-2: #e2ddec;
  --purple-3: #cbc2dc;
  --purple-4: #ada1c7;
  --purple-5: #8e7fae;
  --purple-6: #6f5f95;
  --purple-7: #5a4c7b;
  --purple-8: #453a60;
  --purple-9: #2f2843;

  --green-1: #edf2ee;
  --green-2: #d9e5dd;
  --green-3: #b8cfc2;
  --green-4: #90b4a1;
  --green-5: #66957d;
  --green-6: #416d51;
  --green-7: #365a43;
  --green-8: #2a4634;
  --green-9: #1d3124;

  --red-1: #f8eded;
  --red-2: #efd9d9;
  --red-3: #e0b7b7;
  --red-4: #cd8c8c;
  --red-5: #b76060;
  --red-6: #a03e3e;
  --red-7: #853333;
  --red-8: #692828;
  --red-9: #4c1c1c;

  --blue-1: #ebf1f6;
  --blue-2: #d8e3ee;
  --blue-3: #b7cbde;
  --blue-4: #8dabc8;
  --blue-5: #5f87ac;
  --blue-6: #315e8b;
  --blue-7: #284d72;
  --blue-8: #1e3c59;
  --blue-9: #152a3f;

  /* Neutral ramp, for anything with no area at all. */
  --grey-1: #f3f3f2;
  --grey-2: #e6e5e3;
  --grey-3: #d2d0cd;
  --grey-4: #b3b0ac;
  --grey-5: #93908b;
  --grey-6: #74716c;
  --grey-7: #5d5a56;
  --grey-8: #47443f;
  --grey-9: #302e2a;

  --amber-1: #f6f1e7;
  --amber-2: #ebe0c9;
  --amber-3: #d9c69c;
  --amber-4: #c2a86e;
  --amber-5: #a68949;
  --amber-6: #8a6a2f;
  --amber-7: #715626;
  --amber-8: #58421d;
  --amber-9: #3c2d14;

  --teal-1: #e8f1f0;
  --teal-2: #cfe2e0;
  --teal-3: #a6c8c5;
  --teal-4: #79a9a5;
  --teal-5: #4f8b86;
  --teal-6: #2f6f6b;
  --teal-7: #275c58;
  --teal-8: #1e4845;
  --teal-9: #143130;

  /* ── the active hue ──────────────────────────────────────────────────────
     Purple by default; `[data-hue]` below re-points these. Everything that
     wants "the colour of where I am" uses these, never a ramp directly. */
  --c-1: var(--purple-1);
  --c-2: var(--purple-2);
  --c-3: var(--purple-3);
  --c-4: var(--purple-4);
  --c-5: var(--purple-5);
  --c-6: var(--purple-6);
  --c-7: var(--purple-7);
  --c-8: var(--purple-8);
  --c-9: var(--purple-9);

  /* ── surfaces ────────────────────────────────────────────────────────────
     Warm-tinted greys. A pure grey beside the muted hues above reads cold. */
  --bg:            #f6f5f3;
  --bg-sunk:       #eeece8;
  --surface:       #ffffff;
  --surface-2:     #faf9f7;
  --surface-3:     #f0eeea;
  --surface-hover: #f3f1ed;
  --overlay:       rgb(32 30 27 / 0.42);

  --border:        #dedad3;
  --border-strong: #c6c1b8;
  --border-subtle: #ebe8e2;

  --text:          #1e1c1a;
  --text-muted:    #6a655f;
  --text-subtle:   #8f8a83;
  --text-inverse:  #ffffff;

  /* ── accent ──────────────────────────────────────────────────────────────
     The active hue, given the roles the interface needs. Re-pointed with the
     ramp, so a green page has green buttons without anything being restyled. */
  --accent:        var(--c-6);
  --accent-hover:  var(--c-7);
  --accent-active: var(--c-8);
  --accent-soft:   var(--c-1);
  --accent-border: var(--c-3);
  --accent-text:   var(--c-7);
  --on-accent:     #ffffff;

  /* ── status ──────────────────────────────────────────────────────────────
     Outside the hue system on purpose. "Over budget" and "server down" must
     not change colour depending on which screen you happen to be on. */
  --ok:            #3f6b4a;
  --ok-soft:       #eaf1eb;
  --ok-border:     #c2d6c6;

  --warn:          #8a6320;
  --warn-soft:     #f6f0e4;
  --warn-border:   #ddcda9;

  --danger:        #9b2f34;
  --danger-hover:  #82272b;
  --danger-soft:   #f7eaeb;
  --danger-border: #e0bfc1;

  --info:          #2b5a80;
  --info-soft:     #eaf0f5;
  --info-border:   #bdd0de;

  /* ── chart chrome ────────────────────────────────────────────────────────── */
  --grid-line:     #e9e6e0;
  --axis-text:     #8f8a83;
  --chart-track:   #eae7e1;

  /* ── type ────────────────────────────────────────────────────────────────
     System stack. A webfont would mean either a network dependency the offline
     PWA cannot rely on, or ~200 KB self-hosted for a personal app. */
  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue",
          Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas,
               "Liberation Mono", monospace;

  --fs-xs:   0.6875rem;
  --fs-sm:   0.8125rem;
  --fs-base: 0.9375rem;
  --fs-md:   1.0625rem;
  --fs-lg:   1.375rem;
  --fs-xl:   1.75rem;
  --fs-2xl:  2.25rem;

  --lh-tight: 1.2;
  --lh-snug:  1.4;
  --lh-base:  1.55;

  --fw-normal: 400;
  --fw-medium: 500;
  --fw-semi:   600;
  --fw-bold:   700;

  /* ── space ─────────────────────────────────────────────────────────────── */
  --s-1:  0.25rem;
  --s-2:  0.5rem;
  --s-3:  0.75rem;
  --s-4:  1rem;
  --s-5:  1.25rem;
  --s-6:  1.5rem;
  --s-8:  2rem;
  --s-10: 2.5rem;
  --s-12: 3rem;
  --s-16: 4rem;

  /* ── shape ───────────────────────────────────────────────────────────────
     Everything is square. These stay as named tokens rather than being deleted
     so a component never hard-codes a radius, and so the decision is in one
     place if it is ever revisited. */
  --r-sm:   0;
  --r-md:   0;
  --r-lg:   0;
  --r-xl:   0;
  /* Only for shapes that are circles by nature: status dots, the spinner. */
  --r-full: 999px;

  /* ── elevation ───────────────────────────────────────────────────────────
     Cards do not float — a border separates them. Shadows are kept only for
     things genuinely above the page, where the depth is the message. */
  --shadow-sm: none;
  --shadow-md: 0 1px 2px rgb(32 30 27 / 0.10);
  --shadow-lg: 0 2px 4px rgb(32 30 27 / 0.10), 0 12px 28px rgb(32 30 27 / 0.14);
  --ring: 0 0 0 2px var(--accent);

  /* ── motion ────────────────────────────────────────────────────────────── */
  --t-fast: 100ms;
  --t-base: 160ms;
  --t-slow: 280ms;
  --ease: cubic-bezier(0.32, 0.72, 0, 1);

  /* ── layout ──────────────────────────────────────────────────────────────
     Read by both CSS and JS, so the two never disagree about the shell size. */
  --sidebar-w: 244px;
  --topbar-h: 56px;
  --tabbar-h: 60px;
  --page-max: 1220px;

  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
}

/* ══ hue contexts ═════════════════════════════════════════════════════════
   Set `data-hue` on any element and everything inside it — charts, buttons,
   progress bars, chips — becomes that hue. The book pages set it from the
   book's own `hue` column, so a fourth book added later gets this for free. */

[data-hue="purple"] {
  --c-1: var(--purple-1); --c-2: var(--purple-2); --c-3: var(--purple-3);
  --c-4: var(--purple-4); --c-5: var(--purple-5); --c-6: var(--purple-6);
  --c-7: var(--purple-7); --c-8: var(--purple-8); --c-9: var(--purple-9);
}
[data-hue="green"] {
  --c-1: var(--green-1); --c-2: var(--green-2); --c-3: var(--green-3);
  --c-4: var(--green-4); --c-5: var(--green-5); --c-6: var(--green-6);
  --c-7: var(--green-7); --c-8: var(--green-8); --c-9: var(--green-9);
}
[data-hue="red"] {
  --c-1: var(--red-1); --c-2: var(--red-2); --c-3: var(--red-3);
  --c-4: var(--red-4); --c-5: var(--red-5); --c-6: var(--red-6);
  --c-7: var(--red-7); --c-8: var(--red-8); --c-9: var(--red-9);
}
[data-hue="blue"] {
  --c-1: var(--blue-1); --c-2: var(--blue-2); --c-3: var(--blue-3);
  --c-4: var(--blue-4); --c-5: var(--blue-5); --c-6: var(--blue-6);
  --c-7: var(--blue-7); --c-8: var(--blue-8); --c-9: var(--blue-9);
}
[data-hue="grey"] {
  --c-1: var(--grey-1); --c-2: var(--grey-2); --c-3: var(--grey-3);
  --c-4: var(--grey-4); --c-5: var(--grey-5); --c-6: var(--grey-6);
  --c-7: var(--grey-7); --c-8: var(--grey-8); --c-9: var(--grey-9);
}
[data-hue="amber"] {
  --c-1: var(--amber-1); --c-2: var(--amber-2); --c-3: var(--amber-3);
  --c-4: var(--amber-4); --c-5: var(--amber-5); --c-6: var(--amber-6);
  --c-7: var(--amber-7); --c-8: var(--amber-8); --c-9: var(--amber-9);
}
[data-hue="teal"] {
  --c-1: var(--teal-1); --c-2: var(--teal-2); --c-3: var(--teal-3);
  --c-4: var(--teal-4); --c-5: var(--teal-5); --c-6: var(--teal-6);
  --c-7: var(--teal-7); --c-8: var(--teal-8); --c-9: var(--teal-9);
}

/* ══ dark ═════════════════════════════════════════════════════════════════
   Not an inversion. The ramps are rebuilt so shade 1 stays the quiet end and
   shade 9 the loud one, but both sit legibly on a dark ground — a light tint
   that works on white is invisible on charcoal. */

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;

    --purple-1: #262137; --purple-2: #322b48; --purple-3: #42395e;
    --purple-4: #554a77; --purple-5: #6d6091; --purple-6: #8878ac;
    --purple-7: #a394c4; --purple-8: #bfb3d8; --purple-9: #dbd3ec;

    --green-1: #1a2b21; --green-2: #23392c; --green-3: #2f4c3b;
    --green-4: #3f634d; --green-5: #547d63; --green-6: #6e9a7c;
    --green-7: #8db698; --green-8: #b0cfb8; --green-9: #d3e6d8;

    --red-1: #2e1a1b; --red-2: #3e2223; --red-3: #532e2f;
    --red-4: #6d3c3d; --red-5: #8c4e4f; --red-6: #ab6465;
    --red-7: #c4837f; --red-8: #d9a6a2; --red-9: #edcac7;

    --blue-1: #17242f; --blue-2: #1f313f; --blue-3: #2a4255;
    --blue-4: #38566f; --blue-5: #4a6f8d; --blue-6: #618cab;
    --blue-7: #82a8c3; --blue-8: #a8c4d8; --blue-9: #cee0ec;

    --grey-1: #232220; --grey-2: #2e2d2a; --grey-3: #3d3b37;
    --grey-4: #504e49; --grey-5: #6a6760; --grey-6: #86827a;
    --grey-7: #a29e95; --grey-8: #c0bcb3; --grey-9: #ded9d1;

    --amber-1: #2c2416; --amber-2: #3b301d; --amber-3: #4e4027;
    --amber-4: #665336; --amber-5: #856d47; --amber-6: #a68a5e;
    --amber-7: #c4a87d; --amber-8: #dbc6a2; --amber-9: #eddfc8;

    --teal-1: #16292a; --teal-2: #1d3839; --teal-3: #274a4b;
    --teal-4: #336161; --teal-5: #457f7d; --teal-6: #5c9d99;
    --teal-7: #7dbab5; --teal-8: #a5d3ce; --teal-9: #cbe8e5;

    --bg:            #131211;
    --bg-sunk:       #0c0b0a;
    --surface:       #1b1a18;
    --surface-2:     #201f1c;
    --surface-3:     #282622;
    --surface-hover: #262420;
    --overlay:       rgb(0 0 0 / 0.62);

    --border:        #322f2b;
    --border-strong: #454139;
    --border-subtle: #262421;

    --text:          #ebe8e3;
    --text-muted:    #9c968d;
    --text-subtle:   #77716a;
    --text-inverse:  #131211;

    --on-accent:     #12100e;

    --ok:            #7fb28c;
    --ok-soft:       #16241a;
    --ok-border:     #2c4432;

    --warn:          #cfa757;
    --warn-soft:     #2a2113;
    --warn-border:   #4b3c1e;

    --danger:        #d08286;
    --danger-hover:  #e0a0a3;
    --danger-soft:   #2c1618;
    --danger-border: #52292c;

    --info:          #7ba7c8;
    --info-soft:     #16232d;
    --info-border:   #2c4457;

    --grid-line:     #2a2724;
    --axis-text:     #77716a;
    --chart-track:   #282622;

    --shadow-sm: none;
    --shadow-md: 0 1px 2px rgb(0 0 0 / 0.5);
    --shadow-lg: 0 2px 4px rgb(0 0 0 / 0.5), 0 12px 28px rgb(0 0 0 / 0.45);
  }
}

/* The explicit dark choice, which must beat a light system preference. */
:root[data-theme="dark"] {
  color-scheme: dark;

  --purple-1: #262137; --purple-2: #322b48; --purple-3: #42395e;
  --purple-4: #554a77; --purple-5: #6d6091; --purple-6: #8878ac;
  --purple-7: #a394c4; --purple-8: #bfb3d8; --purple-9: #dbd3ec;

  --green-1: #1a2b21; --green-2: #23392c; --green-3: #2f4c3b;
  --green-4: #3f634d; --green-5: #547d63; --green-6: #6e9a7c;
  --green-7: #8db698; --green-8: #b0cfb8; --green-9: #d3e6d8;

  --red-1: #2e1a1b; --red-2: #3e2223; --red-3: #532e2f;
  --red-4: #6d3c3d; --red-5: #8c4e4f; --red-6: #ab6465;
  --red-7: #c4837f; --red-8: #d9a6a2; --red-9: #edcac7;

  --blue-1: #17242f; --blue-2: #1f313f; --blue-3: #2a4255;
  --blue-4: #38566f; --blue-5: #4a6f8d; --blue-6: #618cab;
  --blue-7: #82a8c3; --blue-8: #a8c4d8; --blue-9: #cee0ec;

  --grey-1: #232220; --grey-2: #2e2d2a; --grey-3: #3d3b37;
  --grey-4: #504e49; --grey-5: #6a6760; --grey-6: #86827a;
  --grey-7: #a29e95; --grey-8: #c0bcb3; --grey-9: #ded9d1;

    --amber-1: #2c2416; --amber-2: #3b301d; --amber-3: #4e4027;
    --amber-4: #665336; --amber-5: #856d47; --amber-6: #a68a5e;
    --amber-7: #c4a87d; --amber-8: #dbc6a2; --amber-9: #eddfc8;

    --teal-1: #16292a; --teal-2: #1d3839; --teal-3: #274a4b;
    --teal-4: #336161; --teal-5: #457f7d; --teal-6: #5c9d99;
    --teal-7: #7dbab5; --teal-8: #a5d3ce; --teal-9: #cbe8e5;

  --bg:            #131211;
  --bg-sunk:       #0c0b0a;
  --surface:       #1b1a18;
  --surface-2:     #201f1c;
  --surface-3:     #282622;
  --surface-hover: #262420;
  --overlay:       rgb(0 0 0 / 0.62);

  --border:        #322f2b;
  --border-strong: #454139;
  --border-subtle: #262421;

  --text:          #ebe8e3;
  --text-muted:    #9c968d;
  --text-subtle:   #77716a;
  --text-inverse:  #131211;

  --on-accent:     #12100e;

  --ok:            #7fb28c;
  --ok-soft:       #16241a;
  --ok-border:     #2c4432;

  --warn:          #cfa757;
  --warn-soft:     #2a2113;
  --warn-border:   #4b3c1e;

  --danger:        #d08286;
  --danger-hover:  #e0a0a3;
  --danger-soft:   #2c1618;
  --danger-border: #52292c;

  --info:          #7ba7c8;
  --info-soft:     #16232d;
  --info-border:   #2c4457;

  --grid-line:     #2a2724;
  --axis-text:     #77716a;
  --chart-track:   #282622;

  --shadow-sm: none;
  --shadow-md: 0 1px 2px rgb(0 0 0 / 0.5);
  --shadow-lg: 0 2px 4px rgb(0 0 0 / 0.5), 0 12px 28px rgb(0 0 0 / 0.45);
}
