/*
 * THE CANONICAL TOKEN SET.
 *
 * One source, and every surface consumes it from here: the console links this file, and
 * website/tokens.css is a byte-identical copy that a test enforces. A colour that changes here
 * changes everywhere, which is the only reason the design language is a system rather than a
 * document describing one.
 *
 * TWO RULES, BOTH ENFORCED BY TESTS RATHER THAN BY GOODWILL - see tests/Hephaisto.Tests/Design/.
 *
 *   1. No colour is written anywhere else. Not in app.css, not in a Razor file, not inline.
 *      Two already escaped before this file existed and broke in light mode for months
 *      without anybody noticing, which is exactly how long a convention lasts when nothing
 *      checks it.
 *
 *   2. Both themes are held to the same contrast bar. Light stopped being "a courtesy" in
 *      v0.4.0: a landing page brings evaluators, and some of them open the console in a bright
 *      room in a meeting about whether to trust it.
 *
 * Still no CDN and no build step. This is a plain stylesheet the pod serves from its own
 * wwwroot, so an egress-free cluster loads it and `tilt live_update` syncs an edit without a
 * rebuild. It is a second file rather than a second ORIGIN - the rule in app.css's header is
 * about the network, not about the file count.
 */

/* ---- the faces ---------------------------------------------------------------------------
 * SELF-HOSTED, and that is the whole constraint. The pod may run in a cluster with no egress,
 * so a webfont from a CDN is a stylesheet that silently falls back to a system stack on exactly
 * the installs that are hardest to debug. These two files are in this repository, served by
 * this pod, and reachable by a browser that can reach nothing else.
 *
 * Latin subsets only - 66KB for both, against roughly 300KB for the full set. This console
 * renders Kubernetes object names, log excerpts and timestamps; the Cyrillic and Greek ranges
 * would be bytes shipped to every operator forever on the chance that one workload is named in
 * them, and the browser falls back per-glyph if that ever happens.
 *
 * Both are variable across 400-700, which is why there is one file per family rather than four.
 * Both are OFL-1.1; the licences ship beside them in fonts/, because shipping a font without
 * its licence is a compliance bug in an AGPL repository and not a tidiness one.
 *
 * font-display: swap - the files are local so the swap window is short, but a console that
 * renders nothing while a font loads is worse than one that reflows once.
 */
@font-face {
    font-family: "Archivo";
    src: url("fonts/archivo-latin.woff2") format("woff2");
    font-weight: 400 700;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
                   U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
                   U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: "JetBrains Mono";
    src: url("fonts/jetbrains-mono-latin.woff2") format("woff2");
    font-weight: 400 700;
    font-style: normal;
    font-display: swap;
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
                   U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
                   U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
    --bg: #131519;
    --bg-raised: #1b1e24;
    --bg-sunken: #0e1013;
    --bg-hover: #23272e;
    --border: #2b3037;
    --border-strong: #3e454e;

    --fg: #e4e1db;
    --fg-dim: #a49d92;
    --fg-faint: #7d7669;

    --accent: #ff8a3d;

    --red: #e33a35;
    --orange: #a85f1e;
    --yellow: #ffd97a;
    --green: #57c7a0;
    --blue: #7fa8d8;
    --purple: #b998e8;
    --cyan: #45bfbf;

    --mono: "JetBrains Mono", ui-monospace, "SF Mono", "Cascadia Mono", Menlo, Consolas, monospace;
    --sans: "Archivo", ui-sans-serif, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;

    --row: 1.55rem;

    /* Text on a --red ground. NOT a fixed near-black: --red is a light pink in dark mode and a
       dark crimson in light, so one literal cannot sit on both. It was a literal for three
       releases and the light-mode error banner was near-black on dark red the whole time. */
    --on-alert: #0a0703;

    /* The reconnect scrim and the dialog it dims for. A scrim darkens in both themes - it is
       not a background, it is an absence of one - but light needs less of it. */
    --scrim: rgb(10 8 6 / 82%);
    --shadow-modal: 0 12px 40px rgb(0 0 0 / 58%);

    /* ---- radius ------------------------------------------------------------------------
       Three values were in use across about twenty declarations - 2px, 3px and 4px - with no
       rule about which went where. Read back off the rules that actually use them: 2px is on
       small or thin things (a step badge, the confidence bar, the meter track), 4px is on large
       containers (the empty state, the investigation panel, the feedback form, the reconnect
       box), and 3px is the default for everything else with a border. Named after the job
       rather than the size, so a direction that squares everything off changes three values
       instead of twenty. */
    --radius-sm: 2px;
    --radius: 3px;
    --radius-lg: 4px;

    /* ---- elevation ---------------------------------------------------------------------
       Two layers, and they are the only two: something pinned over the page (the error banner,
       the reconnect scrim) and something sticky within it (the nav). Written as tokens because
       a raw 1000 in a stylesheet is a number chosen to beat whatever else was on screen at the
       time, and the next one is always higher. */
    --z-sticky: 20;
    --z-overlay: 1000;

    /* ---- type --------------------------------------------------------------------------
       A 13px root, and note that almost every step is BELOW it: this is a dense console and
       most of its text is smaller than the browser default, which is why the scale reads
       downward from --text-root rather than upward from a base.

       Read back off 42 declarations rather than invented. Eight were 0.78rem and seven were
       0.75rem, so the shape was already there; what was missing was names. The one real smell
       it exposed: 0.8rem and 0.82rem were both in use for what is visibly the same role, which
       is what happens when two people pick a number because there is nothing to reach for.
       They are collapsed to one step here, and the visual baselines were the arbiter rather
       than the argument - the difference is 0.26px at this root size and they confirmed it
       renders identically.

       Deliberately NOT renumbered into a neat ratio. That would change the rendering of every
       surface in the console, and it is a decision to make on purpose rather than to smuggle
       in while extracting tokens. */
    --text-2xs: 0.7rem;
    --text-xs: 0.72rem;
    --text-sm: 0.75rem;
    --text-md: 0.78rem;
    --text-lg: 0.8rem;
    --text-xl: 0.85rem;
    --text-root: 1rem;
    --text-2xl: 1.05rem;
    --text-3xl: 1.25rem;
    --text-4xl: 1.35rem;

    /* ---- density -----------------------------------------------------------------------
       The root size is the density lever for the whole console, and it is a one-line lever
       because every length in app.css is already expressed in rem. Forge runs a half-step
       looser than the 13px this shipped with for three releases: more legible at 3am on
       whatever monitor is in the room, at a cost of roughly one incident row per screen.

       THERE IS NO SPACING SCALE, and that is a finding rather than an omission. The paddings
       in app.css are hand-tuned per component - 0.5/0.7, 0.5/0.8, 0.25/0.5, 0.7/0.9, 0.6/0.8 -
       and no ratio joins them. Extracting a scale here would mean INVENTING one and renumbering
       about thirty declarations, which changes the rendering of every surface in the console.
       That is a real improvement and a real decision, and it is not one to make silently while
       moving tokens around. Left for the milestone that can measure it.

       The table cell is the exception, because it IS the density of the product's main screen
       and Forge sets it deliberately rather than inheriting it from the root change. */
    --root-size: 13.5px;
    --cell-y: 0.44rem;
    --cell-x: 0.5rem;
}

/* Light mode was "a courtesy, not the design target" for three releases. It is not any more:
   both themes are contrast-checked and both are photographed by the visual baselines. A
   component is not done until it is correct in both.

   THREE STATES, TWO PALETTES. `:root` above is the dark one and stays the default, so only
   light is written twice - once for an operating system that asked for it, once for a reader
   who asked for it explicitly. The :not([data-theme="dark"]) guard is what makes those two
   compose instead of fight, and it is why there is no [data-theme="dark"] block at all:
   `:root` is already dark, so an explicit dark choice only has to stop the query applying.

   All six combinations, because a theme system that is right in four of them is the usual bug:

     system + dark OS   -> :root                                     dark
     system + light OS  -> query matches, guard passes               light
     dark   + dark OS   -> :root, query does not match               dark
     dark   + light OS  -> query matches, guard REFUSES it           dark
     light  + dark OS   -> query does not match, explicit rule does  light
     light  + light OS  -> both apply, both light                    light

   The two light blocks are identical by assertion rather than by care - DesignTokenTests. */
@media (prefers-color-scheme: light) {
    :root:not([data-theme="dark"]) {
        --bg: #faf8f5;
        --bg-raised: #ffffff;
        --bg-sunken: #f2ede6;
        --bg-hover: #ece5db;
        --border: #e0d9cf;
        --border-strong: #c3b9ab;

        --fg: #1c1a17;
        --fg-dim: #5f5850;
        --fg-faint: #7a7266;

        --accent: #b8500a;
        --red: #8e1a12;
        --orange: #6d420c;
        --yellow: #5c4300;
        --green: #0d6f5a;
        --blue: #2f5c9e;
        --purple: #6d3fb0;
        --cyan: #0e6d78;

        --on-alert: #ffffff;
        --scrim: rgb(28 26 23 / 55%);
        --shadow-modal: 0 12px 40px rgb(60 48 34 / 20%);
    }
}

/* An explicit light choice, which must beat a dark operating system. */
:root[data-theme="light"] {
    --bg: #faf8f5;
    --bg-raised: #ffffff;
    --bg-sunken: #f2ede6;
    --bg-hover: #ece5db;
    --border: #e0d9cf;
    --border-strong: #c3b9ab;

    --fg: #1c1a17;
    --fg-dim: #5f5850;
    --fg-faint: #7a7266;

    --accent: #b8500a;
    --red: #8e1a12;
    --orange: #6d420c;
    --yellow: #5c4300;
    --green: #0d6f5a;
    --blue: #2f5c9e;
    --purple: #6d3fb0;
    --cyan: #0e6d78;

    --on-alert: #ffffff;
    --scrim: rgb(28 26 23 / 55%);
    --shadow-modal: 0 12px 40px rgb(60 48 34 / 20%);
}


/*
 * Deliberately NOT here: a spacing, radius, type or z-index scale. They do not exist yet - the
 * stylesheet hardcodes 2px/3px/4px radii about forty times and every font-size is a literal -
 * and a token with no reader is config that behaves like a comment. They land with their
 * consumers, in the commit that gives them one.
 */
