/* ============================================================================
   tokens.css — the design system.

   Thesis: the interface is monochrome. Colour appears only where it carries
   meaning — a funnel stage, money, a status, a chart series. If something on
   this page is coloured, it means something. That is the whole rule, and it is
   also why the app reads calm at a glance: the eye goes straight to the only
   coloured thing on screen.

   Type has two roles, and both are sans. Figures are set in the interface face
   with tabular numerals — they still align in columns and still never shimmy
   between renders, but they no longer look like terminal output. A monospaced
   slab was carrying "this is data" at the cost of looking like a log file;
   tabular-nums buys the alignment without the costume. The mono face survives
   for what is genuinely code — a config key, a snippet.

   Both stacks are native to the OS: a tool that is open all day should render
   in the face the viewer's system already hints and subpixel-renders best.

   Every colour below is defined at :root and overridden token-for-token in the
   two dark scopes. No component may declare a raw colour.
   ========================================================================== */

:root {
  color-scheme: light;

  /* -- Neutrals. Cool-biased, never a pure grey: each step carries a few
        degrees of blue so the greys sit with the data blue rather than fighting
        it. ------------------------------------------------------------------ */
  --bg:            #f4f5f8;
  --surface:       #ffffff;
  --surface-2:     #fafbfd;
  --surface-3:     #f0f2f6;
  --border:        #e5e8ee;
  --border-strong: #ccd2dd;
  --off:           #e7eaf0;   /* an unlit meter segment */

  --ink:    #0b0d12;
  --ink-2:  #59616f;
  --ink-3:  #868d9a;
  --ink-on: #ffffff;          /* text on an ink-filled surface */

  /* -- Interactive. Primary action is ink, not a hue — the accent slot is
        spent on data instead. Focus is the one place blue touches chrome. --- */
  --action:       #14161b;
  --action-hover: #2b2f38;
  --focus:        #2a78d6;

  /* -- Data. Validated with the data-viz palette validator against #ffffff
        (light) and #131518 (dark). Do not substitute by eye. ---------------- */
  /* One hue per metric, and the same hue everywhere that metric appears. Not
     chosen by eye: run through the data-viz validator against this surface for
     lightness band, chroma floor, colour-vision separation and contrast.

     Four slots, because the chart is heading for four series — what came in,
     what was collected, what was spent, what is left. */
  --series-1: #2a78d6;        /* revenue closed  */
  --series-2: #1baf7a;        /* cash collected  */
  --series-3: #eb6834;        /* ad spend        */
  --series-4: #4a3aa7;        /* profit          */
  --c-booked: #eb6834;
  --c-deals:  #2a78d6;
  --c-rpc:    #1baf7a;

  /* The funnel is ordinal, so it is one hue on a lightness ladder — four blues
     that step, not four different colours competing. */
  --stage-1: #a9cdf3;
  --stage-2: #7db0ec;
  --stage-3: #4f92e2;
  --stage-4: #2a78d6;
  --stage-5: #1b5aa6;

  /* Every goal, everywhere — the line across a bar, the notch on a ring, the
     mark on a meter. Gold, and only ever gold: a goal is not one of the
     metrics, so it gets a colour none of them can take. Deliberately the
     highest-contrast thing on the card, because it is the line you check
     against. 4.7:1 on white, 9.6:1 on the dark surface. */
  --goal:    #9a6b00;
  --goal-bg: #f6efdd;

  /* -- Status. Reserved meanings; never reused as a series colour. ---------- */
  --good:     #06895c;
  --good-bg:  #e4f5ee;
  --warn:     #a56b00;        /* the 24h overdue nudge lives here */
  --warn-bg:  #fdf2dd;
  /* An open task. Blue, not amber: amber already means "this one is late", and
     a queue where every row is amber has no way left to shout. */
  --todo:     #1e5fe0;
  --bad:      #cf3b3b;
  --bad-bg:   #fdecec;

  /* Distance from goal, in four named bands. Two greens differ only in
     lightness because both mean "fine"; amber and crimson are far enough apart
     to survive deuteranopia, which plain orange-vs-red is not. */
  --grade-on:    #06895c;
  --grade-near:  #3aa27c;
  --grade-under: #a56b00;
  --grade-bad:   #cf3b3b;
  --grade-none:  #868d9a;
  --info-bg:  #eef0fc;

  /* -- Elevation. Two levels only; both barely there. ----------------------- */
  --shadow-1: 0 1px 2px rgba(20, 22, 27, .06);
  --shadow-2: 0 8px 28px -6px rgba(20, 22, 27, .16), 0 2px 6px rgba(20, 22, 27, .05);

  /* -- Geometry. Panels are generously rounded; anything carrying a figure
        stays tight, so a number never ends up sitting in a pill. ---------- */
  --r-sm: 7px;
  --r:    12px;
  --r-lg: 16px;
  --rail: 232px;

  /* -- Type ---------------------------------------------------------------- */
  --sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, Roboto, sans-serif;
  --mono: ui-monospace, 'SF Mono', SFMono-Regular, Menlo, 'Cascadia Mono', 'Roboto Mono', monospace;
  /* Figures. The sans face, with the numerals locked to one width. */
  --num:  var(--sans);

  --t-xs:  11px;
  --t-sm:  12px;
  --t-md:  13px;
  --t-lg:  15px;
  --t-xl:  20px;
  --t-2xl: 28px;
  --t-3xl: 38px;

  --ease: cubic-bezier(.32, .72, 0, 1);
}

/* Dark tokens are declared twice on purpose: the media query covers the OS
   setting for viewers who never picked a theme, the [data-theme] scope covers
   an explicit choice and must win in both directions. */
@media (prefers-color-scheme: dark) {
  :root:where(:not([data-theme="light"])) {
    color-scheme: dark;

    --bg:            #08090c;
    --surface:       #121419;
    --surface-2:     #171a21;
    --surface-3:     #1e222b;
    --border:        #23272f;
    --border-strong: #333944;
    --off:           #2a2f39;

    --ink:    #f2f4f8;
    --ink-2:  #98a0b0;
    --ink-3:  #666e7d;
    --ink-on: #08090c;

    --action:       #eef0f3;
    --action-hover: #ffffff;
    --focus:        #3987e5;

    --series-1: #3987e5;
    --series-2: #199e70;
    --series-3: #d95926;
    --series-4: #9085e9;
    --c-booked: #d95926;
    --c-deals:  #3987e5;
    --c-rpc:    #199e70;

    --stage-1: #8fc0f2;
    --stage-2: #63a4ea;
    --stage-3: #3987e5;
    --stage-4: #2168bd;
    --stage-5: #17497f;

    --goal:    #e8b33c;
    --goal-bg: #2a2417;

    --good:     #12c98a;
    --good-bg:  #0d2a20;
    --warn:     #ffb020;
    --warn-bg:  #2b210c;
    --todo:     #3d7dff;
    --bad:      #ff5c5c;
    --bad-bg:   #2c1414;

    --grade-on:    #12c98a;
    --grade-near:  #4dd6a3;
    --grade-under: #ffb020;
    --grade-bad:   #ff5c5c;
    --grade-none:  #666e7d;
    --info-bg:  #141a2c;

    --shadow-1: 0 1px 2px rgba(0, 0, 0, .4);
    --shadow-2: 0 10px 34px -8px rgba(0, 0, 0, .7), 0 2px 8px rgba(0, 0, 0, .4);
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;

  --bg:            #08090c;
  --surface:       #121419;
  --surface-2:     #171a21;
  --surface-3:     #1e222b;
  --border:        #23272f;
  --border-strong: #333944;
  --off:           #2a2f39;

  --ink:    #f2f4f8;
  --ink-2:  #98a0b0;
  --ink-3:  #666e7d;
  --ink-on: #08090c;

  --action:       #eef0f3;
  --action-hover: #ffffff;
  --focus:        #3987e5;

  --series-1: #3987e5;
  --series-2: #199e70;
  --series-3: #d95926;
  --series-4: #9085e9;
  --c-booked: #d95926;
  --c-deals:  #3987e5;
  --c-rpc:    #199e70;

  --stage-1: #8fc0f2;
  --stage-2: #63a4ea;
  --stage-3: #3987e5;
  --stage-4: #2168bd;
  --stage-5: #17497f;

  --goal:    #e8b33c;
  --goal-bg: #2a2417;

  --good:     #12c98a;
  --good-bg:  #0d2a20;
  --warn:     #ffb020;
  --warn-bg:  #2b210c;
  --todo:     #3d7dff;
  --bad:      #ff5c5c;
  --bad-bg:   #2c1414;

  --grade-on:    #12c98a;
  --grade-near:  #4dd6a3;
  --grade-under: #ffb020;
  --grade-bad:   #ff5c5c;
  --grade-none:  #666e7d;
  --info-bg:  #141a2c;

  --shadow-1: 0 1px 2px rgba(0, 0, 0, .4);
  --shadow-2: 0 10px 34px -8px rgba(0, 0, 0, .7), 0 2px 8px rgba(0, 0, 0, .4);
}
