/*
    The portal's design tokens, in ONE place (section 6.2 of docs/customer-portal-plan.md).

    Every colour, size and spacing the app uses is named here and nowhere else, for the reason the plan
    gives: charts read their colours from the same tokens, so a series cannot drift from the UI around it.
    A component that needs a value not in this file adds it here, with a reason.

    THE LOOK is PisteOp's back office (`Slalom/docs/design.md`, and its `app.css`, which is the authority
    where the two differ): one white card on a grey desk, nothing on screen darker than the card, four inks
    and no more, neutral greys so the one colour is unmistakably the one colour, Space Grotesk for headings
    and figures over IBM Plex Sans, small caps for labels, pills outlined rather than filled. What does not
    come across is the density - that is an operations tool where more rows beat whitespace, and this is a
    customer meeting the word "imbalance" for the first time, on a phone, under D21's 44 px targets.

    THE ONE COLOUR is EFS's red rather than PisteOp's plum. The logo's own #E84421 measures 3.98:1 on white,
    too light to be a link or to carry a white button label, so it stays in the mark and the accent is that
    red deepened to #B23018 (6.31:1) - which is the job plum's 6.78:1 was doing.

    Light and dark are both defined (D21 asks for both), and `body` carries an explicit background - a page
    that inherits the user agent's white renders dark text on white inside a dark shell on exactly the
    devices most customers hold.
*/

:root {
    /* ---- brand. One colour, and state does NOT ride on it: see --portal-state-* below. */
    --portal-brand: #b23018;
    --portal-brand-deep: #8f2714;
    --portal-brand-tint: #fdefea;
    --portal-brand-contrast: #ffffff;

    /* ---- surfaces. The desk is the only thing darker than the card, and nothing else on screen is. */
    --portal-desk: #dce0e0;
    --portal-background: var(--portal-desk);
    --portal-surface: #ffffff;
    --portal-sunk: #fafbfb;

    /* Three weights of line, because they do different jobs: --portal-border bounds a thing,
       --portal-border-soft separates rows inside one, --portal-rule divides regions of the shell. */
    --portal-border: #e2e6e6;
    --portal-border-soft: #f1f4f4;
    --portal-rule: #ecefef;

    /* A control's own edge, which --portal-border cannot serve: a field on a white card has no other
       boundary, so WCAG 1.4.11 asks 3:1 of it and --portal-border reads 1.31:1. */
    --portal-control-border: #848d9c;

    /* ---- ink. Four steps, no more. */
    --portal-text: #1a2226;
    --portal-text-2: #3e4a4f;
    --portal-text-muted: #5e6b70;
    --portal-text-faint: #8a9599;
    --portal-text-on-brand: #ffffff;

    /* ---- type. Space Grotesk carries headings and every figure; IBM Plex Sans carries the rest. Both
            fall back to the system stack, so a device that cannot reach Google Fonts still reads. */
    --portal-font: "IBM Plex Sans", system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
    --portal-font-figure: "Space Grotesk", var(--portal-font);

    /* One step per role; a page needing a size between two of these has too many levels on it. */
    --portal-text-xs: 0.6875rem;
    --portal-text-sm: 0.8125rem;
    --portal-text-base: 0.875rem;
    --portal-text-lg: 1.0625rem;
    --portal-text-xl: 1.5rem;

    /* The small-caps label, which is one treatment rather than a size: a run of letters at this tracking
       reads as a label and never as a sentence. */
    --portal-label-size: 0.625rem;
    --portal-label-tracking: 0.11em;

    /* ---- spacing, on a 4 px grid */
    --portal-space-1: 0.25rem;
    --portal-space-2: 0.5rem;
    --portal-space-3: 0.75rem;
    --portal-space-4: 1rem;
    --portal-space-6: 1.5rem;
    --portal-space-8: 2rem;

    /* ---- the 16 px side gutter D15 names, and the one-column width the layout is designed at */
    --portal-gutter: 1rem;
    --portal-column: 36rem;

    /* What a page may widen to when it has a second column beside its first, the site diagram and its
       detail panel (§10.6). Not the default: 36rem is a reading measure, and a page of text set to this
       would be a worse page. A page opts in per block with .portal-wide. */
    --portal-wide: 68rem;

    /* The rail's width on a desktop, where it exists. Below --portal-rail-at it is a top bar instead. */
    --portal-rail: 14.75rem;
    --portal-rail-at: 56rem;

    /* The two things along the bottom of the card - the person in the rail and the week beside it - are one
       band across its foot, so they are one height rather than two that nearly agree. */
    --portal-foot: 4.75rem;

    --portal-radius-card: 18px;
    --portal-radius: 14px;
    --portal-radius-control: 9px;
    --portal-radius-sm: 6px;

    --portal-elevation: 0 1px 2px rgba(26, 34, 38, 0.06), 0 16px 44px rgba(26, 34, 38, 0.09);

    --portal-focus: var(--portal-brand);

    /*
        The site diagram's two directions. NOT the brand and not a state colour: the accent is red, which on
        a diagram would read as an alarm, and the five figure states already own their palette. Blue and
        green rather than red and green, and they differ in LIGHTNESS as well as hue (#15537d is darker than
        #2b7a5b), because that is what someone who cannot separate the two hues reads them by - with the
        arrow head and the word beside the figure saying it a third and fourth time (D21).
    */
    --portal-flow-in: #15537d;
    --portal-flow-out: #2b7a5b;
    --portal-flow-idle: var(--portal-text-muted);
    --portal-flow-unknown: var(--portal-text-muted);

    /* The connectors that are structure rather than flow: a bracket is the sum of several children and has
       no one direction, so it is drawn quiet and never moves. */
    --portal-flow-bracket: #cdd5d8;


    /*
        The state a figure carries (D18). One per FigureState.

        These are OUTLINES, not fills, which is PisteOp's rule - in a list a row of coloured pills is louder
        than its data - and they deliberately avoid red altogether, because red is now the brand. A state
        that borrowed the accent would read as an alarm on a settled figure and would sit on top of the one
        colour the page uses for every action. So the five differ by LIGHTNESS and by border, and the word
        inside each is what actually carries the meaning (D21).
    */
    --portal-state-ground: var(--portal-surface);
    --portal-state-border: var(--portal-border);
    --portal-state-ink: var(--portal-text-2);

    --portal-state-held-ground: var(--portal-sunk);
    --portal-state-held-ink: var(--portal-text-muted);

    --portal-state-faint-ink: var(--portal-text-faint);

    /* The one state that keeps a hue, because "we have no reading" is a caution somebody should act on and
       a grey pill in a grey list is not read. Amber rather than red, for the reason above. */
    --portal-state-caution-ground: #fdf6e6;
    --portal-state-caution-border: #c9a227;
    --portal-state-caution-ink: #7a5600;

    /* ---- chart series, in the order a chart takes them.
            RESTATED IN C# as Components/PortalChartPalette.cs, because a chart option is built in C# and
            handed to the renderer as data - it cannot read a custom property without going back through the
            DOM on every render. Portal.Web.Tests.ChartPaletteTests parses this file and fails if the two
            sides stop agreeing, which is the half of "a series cannot drift from the UI" (§6.2) that can be
            held automatically. Edit them here; the test names the other side. */
    --portal-series-1: #3a8fc4;
    --portal-series-2: #c9742c;
    --portal-series-3: #4a9a4f;
    --portal-series-4: #8f6ac0;
    --portal-series-5: #c04a6d;
    --portal-series-6: #6d8494;
}

/*
    Dark is the system's choice, guarded so an explicit data-theme="light" wins - the same shape the
    dashboard uses, so a theme switch can be added later without restating every token.

    PisteOp has no dark mode at all; this is the same language read on a dark ground, and the one value it
    cannot simply invert is the accent. #b23018 on a dark card is 1.9:1, so dark takes a lighter red -
    #e8654a, 5.08:1 as text - and a filled button then carries NEAR-BLACK rather than white, because white
    on that red is 3.29:1 and the near-black is 5.61:1.
*/
@media (prefers-color-scheme: dark) {
    :root:not([data-theme="light"]) {
        --portal-brand: #e8654a;
        --portal-brand-deep: #f08b77;
        --portal-brand-tint: #2a1a15;
        --portal-brand-contrast: #141413;

        --portal-desk: #0e1214;
        --portal-surface: #181f22;
        --portal-sunk: #141a1d;

        --portal-border: #2a3337;
        --portal-border-soft: #222a2e;
        --portal-rule: #242c30;
        --portal-control-border: #6a787e;

        --portal-text: #e8edef;
        --portal-text-2: #c3ccd0;
        --portal-text-muted: #a8b2b7;
        --portal-text-faint: #8e9a9f;
        --portal-text-on-brand: #141413;

        --portal-elevation: none;


        /* Both directions lightened for a dark ground: #15537d measures 2.0:1 on the dark card and #2b7a5b
           3.0:1, and these are text as well as line. The lightness gap between them is kept. */
        --portal-flow-in: #74b6e6;
        --portal-flow-out: #58c79b;
        --portal-flow-bracket: #364246;

        --portal-state-caution-ground: #2b2415;
        --portal-state-caution-border: #a3851f;
        --portal-state-caution-ink: #e0c164;

        /* The SERIES colours are deliberately not restated: they are one set for both schemes, because C#
           holds the only copy a chart can reach (PortalChartPalette) and it cannot know which scheme the
           device is in without asking the DOM on every render. They are mid-tone for that reason - each
           clears 3:1 against the light surface and against this one, which is WCAG 1.4.11's bar for a
           graphical object. */
    }
}

:root[data-theme="dark"] {
    --portal-brand: #e8654a;
    --portal-brand-deep: #f08b77;
    --portal-brand-tint: #2a1a15;
    --portal-brand-contrast: #141413;

    --portal-desk: #0e1214;
    --portal-surface: #181f22;
    --portal-sunk: #141a1d;

    --portal-border: #2a3337;
    --portal-border-soft: #222a2e;
    --portal-rule: #242c30;
    --portal-control-border: #6a787e;

    --portal-text: #e8edef;
    --portal-text-2: #c3ccd0;
    --portal-text-muted: #a8b2b7;
    --portal-text-faint: #8e9a9f;
    --portal-text-on-brand: #141413;

    --portal-elevation: none;


    /* Both directions lightened for a dark ground: #15537d measures 2.0:1 on the dark card and #2b7a5b
       3.0:1, and these are text as well as line. The lightness gap between them is kept. */
    --portal-flow-in: #74b6e6;
    --portal-flow-out: #58c79b;
    --portal-flow-bracket: #364246;

    /* As in the media query above, and for the same reasons. */
    --portal-state-caution-ground: #2b2415;
    --portal-state-caution-border: #a3851f;
    --portal-state-caution-ink: #e0c164;
}
