/* Design tokens — the Variyas brand, from the company website.
 *
 * Until 2 Oct 2026 this was the "Organic" palette from the first design
 * handoff: cream grounds and a terracotta that was every button, every focus
 * ring, every selected chip -- AND the stop colour. The owner approved a
 * redesign that puts Reach in the company's own colours (the design system in
 * the website repo, and the mock-up approved the same day). Stage 1 is this
 * file and the sidebar; the screens follow the tokens.
 *
 * Two layers, deliberately:
 *
 *   1. RAMPS. The primitives: a cool neutral 100-900, the logo's blue
 *      100-900, the terracotta 100-900 (kept, for stop and warnings), the sage
 *      100-900 (kept, for confirmation). These are the only place a hex value
 *      appears, apart from the few literals below that say why they are one.
 *   2. SEMANTICS. Everything the screens actually use (--fg2, --brand, --stop
 *      ...) is defined once, in terms of the ramps.
 *
 * Dark mode redefines ONLY the ramps, with every ramp reversed in weight: a
 * higher step is always further from the ground, so every semantic name keeps
 * its relative weight. That is what the handoff meant by "a full re-tint, not
 * a filter" -- there is no second set of component colours to keep in step.
 *
 * The blue is not a plain reversal of its light self in dark. #036E9C on the
 * dark grounds is about 3:1, too faint for a link, so dark takes the website's
 * own dark blues: #3CC2EA for a fill (with near-black words on it, 8.10:1) and
 * lighter steps for text. White on cyan is 2.48:1 and is never used; cyan is
 * the dark theme's focus ring and nothing else.
 *
 * The theme class goes on <html>, never on an inner wrapper: body-level colour
 * has to resolve against the right set or inherited text comes out invisible.
 *
 * Palette rules:
 *   - blue is the only action colour; terracotta is stop and warning ONLY;
 *     sage confirms. --stop used to BE --brand, so a primary button and a stop
 *     button were the same terracotta -- the split is the point of stage 1
 *   - the outcome colours of a send did not move (see OUTCOME below)
 *   - every button, badge, tag and chip is a pill
 *   - :focus-visible is always 2px --focus at 2px offset, never the browser
 *     default
 */

/* Relative, not rooted. An @import URL resolves against THIS stylesheet, never
 * against the page's <base>, so "/fonts/fonts.css" leaves the mount: under
 * /recruiters it asked for https://host/fonts/fonts.css, which nginx answers
 * with its catch-all 404. No fonts.css meant no IBM Plex Mono anywhere in the
 * app -- and, while it also carried Fraunces, headings silently fell back to
 * Georgia. */
@import url("../fonts/fonts.css");

:root {
  /* --- ramps: light (the website's light theme) --- */
  /* Cool greys tuned to the blue. 200 is the site's `tint`, 300 its `line`,
     700 its `muted`, 800 its `ink-2`, 900 its `ink`. 500 is the darkest grey
     that is still decoration, and the lightest that holds 3:1 as the edge of
     a field on --raised (3.15:1) -- which is what --control-line uses it for. */
  --color-neutral-100: #f7fafc;
  --color-neutral-200: #f2f7fa;
  --color-neutral-300: #dde5ea;
  --color-neutral-400: #b4c3cb;
  --color-neutral-500: #7b8e99;
  --color-neutral-600: #6b7c86;
  --color-neutral-700: #5d6d76;
  --color-neutral-800: #44545d;
  --color-neutral-900: #16242c;

  /* The logo's blue. 600 is the logo (#036E9C, white on it 5.65:1), 700 the
     website's hover (`blue-dark`, 9.03:1), 800 the navy of its hero. 100 and
     200 are washes for a selected or picked row; 300 and 400 are edges. */
  --color-blue-100: #f2f7fa;
  --color-blue-200: #e1eff6;
  --color-blue-300: #c4dfec;
  --color-blue-400: #7fbcd9;
  --color-blue-500: #2f8fbf;
  --color-blue-600: #036e9c;
  --color-blue-700: #024e70;
  --color-blue-800: #01344d;
  --color-blue-900: #0b2531;

  /* Terracotta. Unchanged, and now spoken for: --stop, --cooling, the
     outcome colours and the warning notes. Nothing that means "do this" may
     use it. */
  --color-accent-100: #fff2eb;
  --color-accent-200: #ffe1d0;
  --color-accent-300: #ffc6a5;
  --color-accent-400: #f6a06b;
  --color-accent-500: #d67f48;
  --color-accent-600: #b2622d;
  --color-accent-700: #8c491a;
  --color-accent-800: #643312;
  --color-accent-900: #402310;

  --color-accent-2-100: #f0fae1;
  --color-accent-2-200: #e1eecc;
  --color-accent-2-300: #ccdbb2;
  --color-accent-2-400: #aebf92;
  --color-accent-2-500: #8fa073;
  --color-accent-2-600: #728157;
  --color-accent-2-700: #56633f;
  --color-accent-2-800: #3d472b;
  --color-accent-2-900: #272e1b;

  /* The two warm greys the outcome charts were drawn in: away and silent.
     The neutral ramp went cool underneath them, and "outcome colours stay
     exactly as they are" -- a chart read last week has to mean the same thing
     this week -- so they keep their Organic values under a name that says
     what they are for. Nothing else may use these. */
  --color-warm-200: #eee7db;
  --color-warm-400: #c0b6a5;

  /* White grounds, a hairline between them. The ground and the card are the
     same white, as on the website: a card is drawn by its --line border. */
  --color-bg:      #ffffff;
  --color-surface: #ffffff;
  --color-text:    #16242c;
  --color-accent-2:#7a8a5e;
  --color-divider: #dde5ea;
  --divider-ink:   #16242c;      /* what --line-soft and --line-strong mix from */
  --color-on-accent: #ffffff;    /* words on a blue or terracotta fill */
  --color-focus:   #036e9c;      /* blue: cyan on white is 2.48:1 */

  /* --- radii, shadows, spacing --- */
  --radius-sm: 8px;
  --radius-md: 16px;
  --radius-lg: 28px;
  --radius-pill: 999px;

  --shadow-sm: 0 1px 2px rgb(22 36 44 / 8%), 0 2px 6px rgb(22 36 44 / 8%);
  --shadow-md: 0 2px 4px rgb(22 36 44 / 8%), 0 6px 18px rgb(22 36 44 / 14%);
  --shadow-lg: 0 12px 32px rgb(22 36 44 / 18%);


  /* Header height. Declared here so the stylesheet stands on its own; app.js
     measures the real topbar and overrides it, because the header wraps to two
     rows below ~800px and anything pinned under it needs the true value. */
  --topbar-h: 74px;

  /* --- type scale ---
     Was 24 hand-typed sizes with eleven between 10px and 15px, including
     six half-pixel values -- the signature of sizes chosen by nudging.
     Half-pixels also round inconsistently inside line boxes. */
  /* Shifted up one notch at the small end, and the floor for PROSE is
     --text-base. 11 and 12 were carrying clauses, not labels: the main copy of
     every card, the body of a reply, the explanation under a setup row. An
     uppercase micro-label is what --text-xs is for; a sentence is not. */
  --text-xs:       12px;   /* uppercase micro-labels ONLY -- never a sentence */
  --text-sm:       13px;   /* metadata, timestamps, counts */
  --text-base:     14px;   /* body copy. The smallest a sentence may use. */
  --text-md:       15px;
  --text-lg:       17px;
  --text-xl:       20px;
  --display-sm:    25px;
  --display-md:    28px;
  --display-lg:    32px;
  --display-xl:    40px;
  --display-2xl:   46px;

  /* A 1.1x scaling of a 4px scale gave 4.4 / 8.8 / 13.2 / 17.6 / 26.4 / 35.2 --
     fractional pixels put element edges on half-pixels, and grep says these were
     used exactly 0 times in app.css. Reset to a plain 4px scale. */
  /* The app's measure. The chrome and the page share it, so the campaign
     name in the header sits directly above the page's first word. 1560, not
     1240: the busiest screens are a list pane beside a detail pane, and 1240
     was squeezing two panes into the width of one document. The prose blocks
     keep their own `max-width: NNch`, which is what holds text readable. */
  --shell-max: 1560px;
  --shell-gutter: 48px;          /* == --space-7, declared before the scale */

  --space-1: 4px;   --space-2: 8px;   --space-3: 12px;
  --space-4: 16px;  --space-5: 24px;  --space-6: 32px;
  --space-7: 48px;

  /* --- type ---
     The website's type (2 Oct 2026): variyasinc.com is system fonts only,
     and the design system names one family, `sans`, for headings and text
     alike. Copied from the website's site.css --font; keep the two equal.
     The serif used to carry the hierarchy on its own, and Fraunces shipped a
     single SemiBold face, so every heading rendered at 600 whatever it asked
     for. A system sans has every weight, so a heading now holds its place by
     --weight-heading (the website's 700) and size, and nothing else. */
  --font-heading: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-ui:      -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --weight-heading: 700;
  /* Self-hosted, and the one face left in fonts.css: the figures in every
     table are tabular, and the system sans is not a monospace. */
  --font-mono:    "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  --dur-micro: 120ms;
  --dur-base:  220ms;
  --ease:      cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* --- ramps: dark. Reversed in weight, so every semantic name below keeps it.
   The grounds and greys are the website's dark theme: bg #0b171d, surface
   #11222a, ink #e7eff3, ink-2 #bccbd3, muted #9aadb7, line #23404c. The blue
   washes (100, 200) are lifted further than a mirror of light would put
   them: the first build's #0E2630 was 1.04:1 against the sidebar, so the
   selected row was marked by its bar and nothing else. 1.35:1 now. The two
   blocks below are the same declarations -- one for the OS setting, one for
   the toggle -- and must be edited together. --- */
@media (prefers-color-scheme: dark) {
  :root:not(.light):not([data-theme="light"]) {
    --color-neutral-100: #0e1d24;
    --color-neutral-200: #182c35;
    --color-neutral-300: #23404c;
    --color-neutral-400: #3d5a68;
    --color-neutral-500: #6a8593;
    --color-neutral-600: #8197a3;
    --color-neutral-700: #9aadb7;
    --color-neutral-800: #bccbd3;
    --color-neutral-900: #e7eff3;

    --color-blue-100: #163a49;
    --color-blue-200: #1c4a5c;
    --color-blue-300: #2b6278;
    --color-blue-400: #3a87a8;
    --color-blue-500: #2fa8d6;
    --color-blue-600: #3cc2ea;
    --color-blue-700: #86daf3;
    --color-blue-800: #a3e2f7;
    --color-blue-900: #dff3fb;

    --color-accent-100: #402310;
    --color-accent-200: #643312;
    --color-accent-300: #8c491a;
    --color-accent-400: #b2622d;
    --color-accent-500: #d67f48;
    --color-accent-600: #f6a06b;
    --color-accent-700: #ffc6a5;
    --color-accent-800: #ffe1d0;
    --color-accent-900: #fff2eb;

    --color-accent-2-100: #272e1b;
    --color-accent-2-200: #3d472b;
    --color-accent-2-300: #56633f;
    --color-accent-2-400: #728157;
    --color-accent-2-500: #8fa073;
    --color-accent-2-600: #aebf92;
    --color-accent-2-700: #ccdbb2;
    --color-accent-2-800: #e1eecc;
    --color-accent-2-900: #f0fae1;

    --color-warm-200: #544e42;
    --color-warm-400: #82796a;

    --color-bg:      #0b171d;
    --color-surface: #11222a;
    --color-text:    #e7eff3;
    --color-accent-2:#aebf92;
    --color-divider: #23404c;
    --divider-ink:   #e7eff3;
    --color-on-accent: #04202b;  /* the fills turn light in dark, so the words go dark */
    --color-focus:   #06b2e2;    /* cyan, 6.59:1 on the surface: a mark, never a fill */

    --shadow-sm: 0 1px 2px rgb(0 0 0 / 34%);
    --shadow-md: 0 3px 10px rgb(0 0 0 / 40%);
    --shadow-lg: 0 12px 32px rgb(0 0 0 / 50%);
  }
}

.dark, [data-theme="dark"] {
  --color-neutral-100: #0e1d24;
  --color-neutral-200: #182c35;
  --color-neutral-300: #23404c;
  --color-neutral-400: #3d5a68;
  --color-neutral-500: #6a8593;
  --color-neutral-600: #8197a3;
  --color-neutral-700: #9aadb7;
  --color-neutral-800: #bccbd3;
  --color-neutral-900: #e7eff3;

  --color-blue-100: #163a49;
  --color-blue-200: #1c4a5c;
  --color-blue-300: #2b6278;
  --color-blue-400: #3a87a8;
  --color-blue-500: #2fa8d6;
  --color-blue-600: #3cc2ea;
  --color-blue-700: #86daf3;
  --color-blue-800: #a3e2f7;
  --color-blue-900: #dff3fb;

  --color-accent-100: #402310;
  --color-accent-200: #643312;
  --color-accent-300: #8c491a;
  --color-accent-400: #b2622d;
  --color-accent-500: #d67f48;
  --color-accent-600: #f6a06b;
  --color-accent-700: #ffc6a5;
  --color-accent-800: #ffe1d0;
  --color-accent-900: #fff2eb;

  --color-accent-2-100: #272e1b;
  --color-accent-2-200: #3d472b;
  --color-accent-2-300: #56633f;
  --color-accent-2-400: #728157;
  --color-accent-2-500: #8fa073;
  --color-accent-2-600: #aebf92;
  --color-accent-2-700: #ccdbb2;
  --color-accent-2-800: #e1eecc;
  --color-accent-2-900: #f0fae1;

  --color-warm-200: #544e42;
  --color-warm-400: #82796a;

  --color-bg:      #0b171d;
  --color-surface: #11222a;
  --color-text:    #e7eff3;
  --color-accent-2:#aebf92;
  --color-divider: #23404c;
  --divider-ink:   #e7eff3;
  --color-on-accent: #04202b;
  --color-focus:   #06b2e2;

  --shadow-sm: 0 1px 2px rgb(0 0 0 / 34%);
  --shadow-md: 0 3px 10px rgb(0 0 0 / 40%);
  --shadow-lg: 0 12px 32px rgb(0 0 0 / 50%);
}

/* =====================================================================
 * SEMANTICS — defined once, in terms of the ramps above. Nothing below
 * repeats a hex value, so dark mode needs no second copy of any of it.
 * ===================================================================== */
:root, .dark, .light, [data-theme] {
  /* grounds. White on white in light, as on the website: a card is drawn by
     its border, not by a darker page under it. */
  --desk:         var(--color-neutral-300);
  --canvas:       var(--color-bg);
  --panel:        var(--color-surface);
  --raised:       var(--color-neutral-200);   /* light: #f2f7fa, the site's tint */
  --chrome:       var(--color-surface);
  --sidebar:      var(--color-surface);
  --chip:         var(--color-neutral-100);
  --inset:        var(--color-neutral-900);
  --inset-fg:     var(--color-neutral-300);
  --inset-fg2:    var(--color-neutral-500);

  /* THE LOG PANEL. Dark in both themes: a terminal reads as a terminal.
     That was the intent here before, written as a comment over
     `--inset: var(--color-neutral-900)` — and the dark ramp reverses that
     step to the lightest one, so the panel turned pale while the inks written
     for a dark ground stayed put. `.ll-bounce` reported a failed delivery at
     1.38:1, on the screen somebody watches while 250 emails go out.
     Literals, not ramp steps, because a ramp step is exactly what moved.
     The ground is the website's footer navy; the bounce and reply inks are
     the ones the log always used, so a line still means what it meant. */
  --log-ground:   #0f2530;   /* the website's foot-bg                */
  --log-fg:       #c8d6dd;   /* body                          10.63:1 */
  --log-head:     #e4f4fb;   /*                               14.03:1 */
  --log-bounce:   #ffc6a5;   /*                               10.45:1 */
  --log-reply:    #ccdbb2;   /*                               10.80:1 */
  --log-quiet:    #c8d6dd;   /*                               10.63:1 */
  --log-muted:    #9fb3bd;   /*                                7.27:1 */

  /* THE SIDEBAR'S COUNT BADGE: solid blue, white figures, the same in both
     themes -- the design system's rule, and the mock-up's. Literals for the
     reason the log panel's are: the ramps reverse in dark, so the blue step
     dark enough under white in light is a pale one in dark, and white on
     that would fail. 5.65:1 in both themes. A count is never drawn in the
     selected row's colours, so "5 waiting" and "you are here" cannot be
     mistaken for each other. */
  --badge-fill:   #036e9c;
  --badge-ink:    #ffffff;

  /* rules */
  --line:         var(--color-divider);
  --line-soft:    color-mix(in srgb, var(--divider-ink) 8%, transparent);
  --line-strong:  color-mix(in srgb, var(--divider-ink) 26%, transparent);
  --track:        var(--color-neutral-300);
  --track-strong: var(--color-neutral-400);
  --disabled:     var(--color-neutral-400);
  --dot:          var(--color-neutral-400);
  /* The edge of something you type into. --line is a hairline, 1.28:1, and
     decoration; a field whose only boundary is its edge needs 3:1 (WCAG
     1.4.11). 3.15:1 on --raised, which is the field's own ground. */
  --control-line: var(--color-neutral-500);

  /* text */
  /* Four roles, four steps that all pass. --fg2 and --fg3 were the same
     token, and --fg4 -- documented as "never words" -- was carrying words in
     a dozen places at roughly 3.6:1 on the card ground, which fails AA.
     A micro-label needs MORE contrast than body copy, not less: its visual
     step comes from letter-spacing and uppercase, not from fading it out. */
  --fg1:          var(--color-text);
  --fg2:          var(--color-neutral-800);
  --fg3:          var(--color-neutral-700);
  --fg4:          var(--color-neutral-700);
  /* NOT text. Rules, dots, disabled marks -- what --fg4 was being misused as. */
  --fg-decor:     var(--color-neutral-500);

  /* header */
  --header:           var(--color-surface);
  --header-fg:        var(--color-text);
  /* The header sat on a darker cream than the cards, and this was the worst
     contrast in the app at roughly 3.2:1. White now, and 8.67:1. */
  --header-sub:       var(--color-neutral-800);
  --header-chip:      var(--color-neutral-200);
  --header-chip-line: var(--color-divider);

  /* THE ACTION COLOUR: the logo's blue, and nothing that means "stop" may use
     it. --brand fills a primary button and colours a link; --brand-deep is
     its hover and the bar on a selected row; --brand-fg is blue words on a
     blue wash; --brand-ink the strongest of those, on --brand-tint. */
  --brand:      var(--color-blue-600);
  --brand-deep: var(--color-blue-700);
  --brand-fg:   var(--color-blue-700);
  --brand-ink:  var(--color-blue-800);
  --brand-wash: var(--color-blue-100);   /* the selected nav row, a picked row */
  --brand-tint: var(--color-blue-200);   /* a pressed chip */
  --brand-line: var(--color-blue-300);
  --brand-line-strong: var(--color-blue-400);
  --on-accent:  var(--color-on-accent);
  --focus:      var(--color-focus);

  --brand-a09: color-mix(in srgb, var(--color-blue-600) 8%,  transparent);
  --brand-a10: color-mix(in srgb, var(--color-blue-600) 10%, transparent);
  --brand-a12: color-mix(in srgb, var(--color-blue-600) 12%, transparent);
  --brand-a13: color-mix(in srgb, var(--color-blue-600) 15%, transparent);
  --brand-a22: color-mix(in srgb, var(--color-blue-600) 22%, transparent);
  --brand-a30: color-mix(in srgb, var(--color-blue-600) 30%, transparent);

  /* status. Sage confirms, terracotta refuses - the handoff's own rule. */
  --sent:          var(--color-accent-2-600);
  --sent-fg:       var(--color-accent-2-700);
  --sent-tint:     var(--color-accent-2-100);

  /* Warming, pacing, "watch": the terracotta that is not yet a stop. Its
     words are the 700 step, the same as --stop-fg: the 600 measured 4.09:1 on
     its own tint, and a warning nobody can read is not one. The fill and the
     dot (500) are what tell it from a stop, and the word always says which. */
  --cooling:       var(--color-accent-500);
  --cooling-fg:    var(--color-accent-700);
  --cooling-tint:  var(--color-accent-100);
  --cooling-tint2: var(--color-accent-200);
  --cooling-wash:  var(--color-accent-100);

  /* The [?...?] clause: a third thing a token can be, alongside "filled from
     the list" and "one wording per contact". It needed its own colour because
     its consequence is different -- the clause disappears rather than the send
     being refused -- and reusing the sage of a variant said the wrong thing. */
  --opt-tint:      var(--color-accent-2-200);
  --opt-fg:        var(--color-accent-2-800);

  /* OUTCOME of a send, which is not the same thing as its STATE. Collapsing
     the two is how the old ring ended up with two terracottas nobody could
     tell apart. --stop, --sent and --cooling below carry state; these five
     are the whole palette of the outcome charts, and those charts may use no
     other colour. NONE OF THEM MOVED when the brand went blue (2 Oct 2026),
     and none is blue or cyan, so an outcome can never read as a link.

     Light against dark inside the terracotta family carries how bad it is:
     bounced is the deep step and asked-to-stop is obviously lighter, because
     neither address will be reached again but only one of them is a fault.
     The sage is reserved for replies and appears nowhere else on the screen --
     it is the only thing anybody opens the dashboard hoping to see.

     Three of these are very pale against the card by design: measured on 5
     September, stopped is 1.27 against the surface in light and silent is
     1.03, which is the card colour to the pixel. That is deliberate -- silence
     should not shout -- and it is why every segment drawn in them carries a
     hairline outline and every legend row carries its word. Colour alone
     never says what an outcome was. (On the white card silent is now 1.23:1:
     still quiet, still outlined.) */
  --outcome-replied: var(--color-accent-2-700);
  --outcome-bounced: var(--color-accent-700);
  --outcome-stopped: var(--color-accent-300);
  --outcome-away:    var(--color-warm-400);
  --outcome-silent:  var(--color-warm-200);

  /* STOP, and only stop: the Emergency stop, a refusal, a failed check, a
     warning note. The 700 step, not the base: white on it is 6.81:1, where
     the old --stop (#c67139) carried white at 3.3:1 -- and was the brand. */
  --stop:          var(--color-accent-700);
  --stop-fg:       var(--color-accent-700);
  --stop-tint:     var(--color-accent-200);
  --stop-wash:     var(--color-accent-100);

  --idle:          var(--color-neutral-500);

  /* shadows, under the names the screens already use */
  --shadow-card:   var(--shadow-sm);
  --shadow-window: var(--shadow-lg);
}
