/* =============================================================================
   Eyvi.Design - design tokens (EDC v2)
   -----------------------------------------------------------------------------
   The single source of every visual decision. No other stylesheet contains a
   literal colour, font stack, radius, shadow or duration; they use these
   variables. An application adds its own values in css/app-tokens.css, prefixed
   --app-, and never redefines a token declared here.

   PUBLIC AND PRIVATE
   The palette is private: raw EDC values, referenced only by the semantic
   tokens below. Everything else is the public surface applications use.

   WHERE THE VALUES COME FROM
   Palette, semantic mapping and both themes are EDC's v2 design system. Six
   values are Eyvi's own, because EDC's pairs do not all clear WCAG 2.1 AA. Each
   is marked DERIVED with its measured ratio, so nobody "fixes" it back:

     --color-accent          light  #1971A4  EDC's link colour #CEE7F7 is 1.28:1 on white
     --color-focus-ring      light  #2195D8  EDC's is 2.33:1; WCAG 1.4.11 needs 3.0
     --color-warning-text    light  #90621C  EDC has no warningDark; #DEA854 is 2.14:1
     --color-danger-strong          #744040  EDC's danger fails as a fill with white (3.73)
                                             and dark (4.08) text
     --color-text-muted      dark   #989999  EDC's tertiary is 2.85:1 on a dark card
     status subtle backgrounds, dark        EDC defines these for light only

   -----------------------------------------------------------------------------
   BREAKPOINTS - documented here, not variables
   -----------------------------------------------------------------------------
   A custom property in a media query is invalid and never matches, so every
   media query repeats one of these values:

       sm    30rem   480px   large phone
       md    48rem   768px   tablet portrait; below it, record tables become cards
       lg    64rem  1024px   tablet landscape; below it, the shell becomes a drawer
       xl    90rem  1440px   wide desktop

   max-width queries are the default, so the phone layout is the one that
   survives a width nobody anticipated.
   ============================================================================= */

:root {
    /* -------------------------------------------------------------------------
       Palette - EDC v2 raw values. PRIVATE: referenced only by semantic tokens.
       ------------------------------------------------------------------------- */

    /* softMarine. A fill that carries dark text, not a text or icon colour. */
    --color-marine: #cee7f7;
    --color-marine-pressed: #bcd3e1;
    --color-marine-strong: #5ab3e6;

    /* rusticStone */
    --color-stone: #d6b890;
    --color-stone-pressed: #b99a71;

    --color-white: #ffffff;
    --color-black: #000000;

    /* EDC's warm-neutral grey ramp. */
    --color-gray-50: #fafafa;
    --color-gray-75: #f8f8f8;
    --color-gray-100: #f5f5f5;
    --color-gray-120: #ebeded;
    --color-gray-160: #e8e8e8;
    --color-gray-180: #d1d2d2;
    --color-gray-200: #dddede;
    --color-gray-240: #c6c7c7;
    --color-gray-300: #afb0b0;
    --color-gray-330: #989999;
    --color-gray-400: #6a6b6b;
    --color-gray-500: #535454;
    --color-gray-600: #464949;
    --color-gray-690: #3b3d3d;
    --color-gray-700: #303232;
    --color-gray-800: #2d2f2f;
    --color-gray-820: #282a2a;
    --color-gray-900: #242626;
    --color-gray-910: #1d2020;
    --color-gray-950: #1a1d1d;
    --color-gray-960: #151717;
    --color-gray-965: #181a1a;
    --color-gray-975: #111313;

    --color-green: #a5ba78;
    --color-green-dark: #4e6b26;
    --color-amber: #dea854;
    --color-red: #ce6464;
    --color-red-dark: #744040;

    /* -------------------------------------------------------------------------
       Semantic - the light theme, and the base set
       -----------------------------------------------------------------------
       EVERY semantic token is defined here. The dark blocks below only
       redefine them; a colour defined solely in a dark block is missing in the
       states that block does not match.
       ------------------------------------------------------------------------- */

    /* Native UI - scrollbars, form controls, the caret - follows the theme. */
    color-scheme: light;

    /* Brand. --color-primary is a fill; --color-accent is the same identity at a
       weight that can carry text. */
    --color-primary: var(--color-marine);
    --color-primary-hover: var(--color-marine-pressed);
    --color-primary-active: var(--color-marine-pressed);
    --color-primary-subtle: #f6fdfe;
    /* Dark text on the pale fill: 11.88:1. White would be 1.28:1. */
    --color-on-primary: var(--color-gray-900);

    /* DERIVED - 5.33:1 on white, 4.54:1 on the deepest light surface. */
    --color-accent: #1971a4;
    --color-accent-hover: #14597f;

    --color-secondary: var(--color-stone);
    --color-secondary-hover: var(--color-stone-pressed);
    --color-on-secondary: var(--color-gray-900);

    /* The stone as text and as a wash, so it can carry meaning as the status
       colours do. DERIVED - 5.60:1 on white, 4.91:1 on the subtle below; the
       stone fill itself is 1.79:1 and is a fill only. */
    --color-secondary-text: #8a5f2a;
    --color-secondary-subtle: #f7efe4;

    /* Surfaces - named by position in the hierarchy, not by appearance.
       Light depth order: root -> page -> container (white) -> inset */
    --color-surface-root: var(--color-gray-50);
    --color-surface-page: var(--color-gray-100);
    --color-surface-container: var(--color-white);
    --color-surface-inset: var(--color-gray-50);
    --color-surface-overlay: var(--color-white);
    --color-surface-contrast: var(--color-gray-200);
    --color-surface-table-header: var(--color-gray-120);
    --color-surface-input: var(--color-white);
    --color-surface-inverse: var(--color-gray-950);

    /* Interaction states: translucent layers over whatever surface is there, so
       one rule serves every button variant and card. See base.css. */
    --color-state-hover: rgb(0 0 0 / 4%);
    --color-state-pressed: rgb(0 0 0 / 8%);
    --color-state-selected: rgb(206 231 247 / 30%);

    --color-overlay: rgb(0 0 0 / 45%);

    --color-text: var(--color-gray-900);
    --color-text-secondary: var(--color-gray-500);
    --color-text-muted: var(--color-gray-400);
    --color-text-inverse: var(--color-white);

    --color-border: var(--color-gray-200);
    --color-border-subtle: var(--color-gray-160);
    --color-border-muted: var(--color-gray-120);
    --color-border-strong: var(--color-gray-300);
    --color-border-outline: var(--color-gray-300);

    --color-link: var(--color-accent);
    --color-link-hover: var(--color-accent-hover);

    /* DERIVED - 3.3:1 on white. WCAG 1.4.11 requires 3.0 for a focus indicator. */
    --color-focus-ring: #2195d8;

    /* Status. Three tokens each, because one colour cannot do all three jobs:
         --color-x          the fill or graphic
         --color-x-text     the same meaning at a weight that passes AA as text
         --color-x-subtle   a background to sit that text on */
    --color-success: var(--color-green);
    --color-success-text: var(--color-green-dark);
    --color-success-subtle: #f8fbe9;

    --color-warning: var(--color-amber);
    /* DERIVED - 5.32:1 on white. */
    --color-warning-text: #90621c;
    --color-warning-subtle: #fdf6dd;

    --color-danger: var(--color-red);
    --color-danger-text: var(--color-red-dark);
    --color-danger-subtle: #fcebe2;
    /* A destructive button fill: white on this is 8.24:1. */
    --color-danger-strong: var(--color-red-dark);

    --color-info: var(--color-marine);
    --color-info-text: var(--color-accent);
    --color-info-subtle: #f6fdfe;

    /* Severity - a four-step scale for scored observations, identical in both
       themes. FILLS ONLY, with --color-on-severity for the text on top. */
    --color-severity-good: #b1c87f;
    --color-severity-minor: #efbf7f;
    --color-severity-moderate: #e48383;
    --color-severity-severe: #d95d5d;
    /* DERIVED - 5.11:1 on the severe step, where --color-text is 4.11:1. */
    --color-on-severity: var(--color-gray-975);

    /* -------------------------------------------------------------------------
       Data visualisation
       -----------------------------------------------------------------------
       Categories: eight muted hues that differ only in hue, because a category
       has no order to encode. Eight at most; a breakdown with more shows the
       largest seven and folds the rest into one "Everything else". Applied
       through the .chart-cat-N classes in base.css. Graphical objects, so
       the bar is 3:1 against the surface, not 4.5:1.

       Scale: five steps of the accent hue for quantities, pale enough that one
       text colour, --color-on-scale, works on every step.
       ------------------------------------------------------------------------- */
    --color-category-1: #1971a4;
    --color-category-2: #4e6b26;
    --color-category-3: #b8792e;
    --color-category-4: #8c4a4a;
    --color-category-5: #4a5f7a;
    --color-category-6: #6b5b8c;
    --color-category-7: #2c7a70;
    --color-category-8: #8a7040;

    --color-scale-1: #eef4f9;
    --color-scale-2: #d3e5f0;
    --color-scale-3: #b0d0e4;
    --color-scale-4: #86b6d5;
    --color-scale-5: #5b9cc4;
    --color-on-scale: var(--color-gray-975);

    /* Application shell. The sidebar sits on surface-root, light in the light theme. */
    --color-sidebar-background: var(--color-surface-root);
    --color-sidebar-text: var(--color-gray-500);
    --color-sidebar-text-active: var(--color-gray-900);
    --color-sidebar-active: var(--color-gray-120);
    --color-sidebar-border: var(--color-border-muted);
    --color-topbar-background: var(--color-surface-container);

    /* -------------------------------------------------------------------------
       Typography
       -----------------------------------------------------------------------
       The system font stack, by decision: it downloads nothing, renders
       natively on every device and never blocks first paint. A custom face is
       adopted only after reading its licence.
       ------------------------------------------------------------------------- */
    --font-family-base: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --font-family-heading: var(--font-family-base);
    --font-family-mono: ui-monospace, SFMono-Regular, "Cascadia Mono", Consolas, "Liberation Mono", monospace;

    --font-size-xs: 0.75rem;    /* 12px */
    --font-size-sm: 0.875rem;   /* 14px */
    --font-size-base: 1rem;     /* 16px - never smaller for body text, which is read on phones, outdoors */
    --font-size-lg: 1.125rem;   /* 18px */
    --font-size-xl: 1.375rem;   /* 22px */
    --font-size-2xl: 1.75rem;   /* 28px */
    --font-size-3xl: 2.25rem;   /* 36px */

    --font-weight-regular: 400;
    --font-weight-medium: 500;
    --font-weight-semibold: 600;
    --font-weight-bold: 700;

    --line-height-tight: 1.2;
    --line-height-base: 1.5;
    --line-height-relaxed: 1.7;

    --letter-spacing-tight: -0.01em;
    --letter-spacing-base: 0;
    --letter-spacing-wide: 0.02em;

    /* -------------------------------------------------------------------------
       Spacing - a 4px scale, a finer superset of EDC's five steps.
       ------------------------------------------------------------------------- */
    --space-0: 0;
    --space-1: 0.25rem;   /* 4px  */
    --space-2: 0.5rem;    /* 8px  */
    --space-3: 0.75rem;   /* 12px */
    --space-4: 1rem;      /* 16px */
    --space-5: 1.5rem;    /* 24px */
    --space-6: 2rem;      /* 32px */
    --space-7: 3rem;      /* 48px */
    --space-8: 4rem;      /* 64px */

    /* -------------------------------------------------------------------------
       Shape - EDC's radius scale.
       ------------------------------------------------------------------------- */
    --radius-none: 0;
    --radius-sm: 0.25rem;
    --radius-md: 0.375rem;
    --radius-lg: 0.5rem;
    --radius-xl: 1rem;
    --radius-full: 9999px;
    --radius-pill: var(--radius-full);

    /* Matches the ring --shadow-focus draws, so an outlined control and a shadowed one look alike. */
    --focus-ring-width: 3px;

    /* The panel a chart or shape sits on - an alias, not a second colour. */
    --color-surface: var(--color-surface-container);

    --border-width: 1px;

    /* -------------------------------------------------------------------------
       Elevation - EDC's shadow tones.
       ------------------------------------------------------------------------- */
    --shadow-none: none;
    --shadow-sm: 0 1px 2px rgb(0 0 0 / 5%);
    --shadow-md: 0 2px 6px rgb(36 38 38 / 11%);
    --shadow-lg: 0 8px 24px rgb(36 38 38 / 20%);
    --shadow-xl: 0 16px 40px rgb(36 38 38 / 30%);
    /* A top highlight plus a drop shadow gives a card an edge, not just a blur. */
    --shadow-container: inset 0 1px 0 rgb(0 0 0 / 6%), 0 2px 8px rgb(0 0 0 / 7%);
    --shadow-focus: 0 0 0 3px var(--color-focus-ring);

    /* -------------------------------------------------------------------------
       Application shell layout
       ------------------------------------------------------------------------- */
    --layout-sidebar-width: 16rem;
    --layout-topbar-height: 3.5rem;
    --layout-content-max-width: 80rem;

    /* Nothing interactive goes below this. */
    --layout-touch-target-min: 2.75rem;

    /* Safe areas, non-zero on devices with a notch because index.html sets viewport-fit=cover. */
    --layout-safe-top: env(safe-area-inset-top, 0px);
    --layout-safe-right: env(safe-area-inset-right, 0px);
    --layout-safe-bottom: env(safe-area-inset-bottom, 0px);
    --layout-safe-left: env(safe-area-inset-left, 0px);

    /* -------------------------------------------------------------------------
       Motion
       ------------------------------------------------------------------------- */
    --motion-duration-fast: 100ms;
    --motion-duration-base: 180ms;
    --motion-duration-slow: 260ms;
    --motion-easing-standard: cubic-bezier(0.2, 0, 0, 1);

    /* -------------------------------------------------------------------------
       Stacking order - declared centrally so z-index is never a guess
       ------------------------------------------------------------------------- */
    --z-sidebar: 100;
    --z-topbar: 200;
    --z-dropdown: 300;
    --z-modal: 400;
    /* Above everything: the skip link and Blazor's unhandled-error bar. */
    --z-top: 500;
}

/* =============================================================================
   Dark theme - EDC v2 dark tokens
   -----------------------------------------------------------------------------
   Only semantic tokens are redefined. Three states, two blocks:

     1. device preference, nothing on <html>  -> the media query
     2. explicit "dark"                        -> [data-theme="dark"]
     3. explicit "light" on a dark device      -> neither applies

   The media query is guarded with :not([data-theme="light"]) so an explicit
   light choice beats a dark device, and the attribute block repeats the values
   so an explicit dark choice beats a light one.

   THE TWO BLOCKS MUST STAY IDENTICAL. A test asserts it.
   ============================================================================= */

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

        /* The pale marine already carries dark text and, at 13.25:1 on the page
           surface, works as accent text too. */
        --color-accent: var(--color-marine);
        --color-accent-hover: var(--color-white);

        --color-surface-root: var(--color-gray-975);
        --color-surface-page: var(--color-gray-950);
        --color-surface-container: var(--color-gray-900);
        --color-surface-inset: var(--color-gray-820);
        --color-surface-overlay: var(--color-gray-800);
        --color-surface-contrast: var(--color-gray-600);
        --color-surface-table-header: var(--color-gray-700);
        --color-surface-input: var(--color-gray-965);
        --color-surface-inverse: var(--color-white);

        --color-state-hover: rgb(255 255 255 / 6%);
        --color-state-pressed: rgb(255 255 255 / 10%);
        --color-state-selected: rgb(206 231 247 / 15%);

        --color-overlay: rgb(0 0 0 / 60%);

        --color-text: var(--color-gray-50);
        --color-text-secondary: var(--color-gray-300);
        /* DERIVED - EDC's tertiary (#6A6B6B) is 2.85:1 on a dark card. */
        --color-text-muted: var(--color-gray-330);
        --color-text-inverse: var(--color-gray-900);

        --color-border: var(--color-gray-690);
        --color-border-subtle: var(--color-gray-700);
        --color-border-muted: var(--color-gray-800);
        --color-border-strong: var(--color-gray-600);
        --color-border-outline: var(--color-gray-600);

        --color-focus-ring: var(--color-marine);

        /* The fill tones clear AA as text on dark, so no darkened variants. */
        --color-success-text: var(--color-green);
        --color-warning-text: var(--color-amber);
        --color-danger-text: var(--color-red);
        --color-info-text: var(--color-marine);
        --color-secondary-text: var(--color-stone);

        /* DERIVED - translucent tints, so they sit correctly on any dark surface. */
        --color-success-subtle: rgb(165 186 120 / 16%);
        --color-warning-subtle: rgb(222 168 84 / 16%);
        --color-danger-subtle: rgb(206 100 100 / 18%);
        --color-info-subtle: rgb(206 231 247 / 14%);
        --color-primary-subtle: rgb(206 231 247 / 14%);
        --color-secondary-subtle: rgb(214 184 144 / 18%);

        --color-sidebar-background: var(--color-surface-root);
        --color-sidebar-text: var(--color-gray-300);
        --color-sidebar-text-active: var(--color-gray-50);
        --color-sidebar-active: var(--color-gray-820);
        --color-sidebar-border: var(--color-gray-800);
        --color-topbar-background: var(--color-surface-container);

        --shadow-sm: 0 1px 2px rgb(0 0 0 / 30%);
        --shadow-md: 0 2px 8px rgb(0 0 0 / 40%);
        --shadow-lg: 0 10px 28px rgb(0 0 0 / 50%);
        --shadow-xl: 0 18px 44px rgb(0 0 0 / 60%);
        --shadow-container: inset 0 1px 0 rgb(255 255 255 / 8%), 0 2px 8px rgb(0 0 0 / 40%);

        /* The same eight identities, lifted off a dark ground, in the same order. */
        --color-category-1: #5aa8d6;
        --color-category-2: #9dbd6a;
        --color-category-3: #e0a558;
        --color-category-4: #d18585;
        --color-category-5: #8aa2c4;
        --color-category-6: #a794c9;
        --color-category-7: #5fb5a8;
        --color-category-8: #c7ab72;

        /* The scale inverts; still five steps and one text colour. */
        --color-scale-1: #1a2830;
        --color-scale-2: #22394a;
        --color-scale-3: #2b4d63;
        --color-scale-4: #35637f;
        --color-scale-5: #40799b;
        --color-on-scale: var(--color-gray-50);
    }
}

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

    --color-accent: var(--color-marine);
    --color-accent-hover: var(--color-white);

    --color-surface-root: var(--color-gray-975);
    --color-surface-page: var(--color-gray-950);
    --color-surface-container: var(--color-gray-900);
    --color-surface-inset: var(--color-gray-820);
    --color-surface-overlay: var(--color-gray-800);
    --color-surface-contrast: var(--color-gray-600);
    --color-surface-table-header: var(--color-gray-700);
    --color-surface-input: var(--color-gray-965);
    --color-surface-inverse: var(--color-white);

    --color-state-hover: rgb(255 255 255 / 6%);
    --color-state-pressed: rgb(255 255 255 / 10%);
    --color-state-selected: rgb(206 231 247 / 15%);

    --color-overlay: rgb(0 0 0 / 60%);

    --color-text: var(--color-gray-50);
    --color-text-secondary: var(--color-gray-300);
    --color-text-muted: var(--color-gray-330);
    --color-text-inverse: var(--color-gray-900);

    --color-border: var(--color-gray-690);
    --color-border-subtle: var(--color-gray-700);
    --color-border-muted: var(--color-gray-800);
    --color-border-strong: var(--color-gray-600);
    --color-border-outline: var(--color-gray-600);

    --color-focus-ring: var(--color-marine);

    --color-success-text: var(--color-green);
    --color-warning-text: var(--color-amber);
    --color-danger-text: var(--color-red);
    --color-info-text: var(--color-marine);
    --color-secondary-text: var(--color-stone);

    --color-success-subtle: rgb(165 186 120 / 16%);
    --color-warning-subtle: rgb(222 168 84 / 16%);
    --color-danger-subtle: rgb(206 100 100 / 18%);
    --color-info-subtle: rgb(206 231 247 / 14%);
    --color-primary-subtle: rgb(206 231 247 / 14%);
    --color-secondary-subtle: rgb(214 184 144 / 18%);

    --color-sidebar-background: var(--color-surface-root);
    --color-sidebar-text: var(--color-gray-300);
    --color-sidebar-text-active: var(--color-gray-50);
    --color-sidebar-active: var(--color-gray-820);
    --color-sidebar-border: var(--color-gray-800);
    --color-topbar-background: var(--color-surface-container);

    --shadow-sm: 0 1px 2px rgb(0 0 0 / 30%);
    --shadow-md: 0 2px 8px rgb(0 0 0 / 40%);
    --shadow-lg: 0 10px 28px rgb(0 0 0 / 50%);
    --shadow-xl: 0 18px 44px rgb(0 0 0 / 60%);
    --shadow-container: inset 0 1px 0 rgb(255 255 255 / 8%), 0 2px 8px rgb(0 0 0 / 40%);

    --color-category-1: #5aa8d6;
    --color-category-2: #9dbd6a;
    --color-category-3: #e0a558;
    --color-category-4: #d18585;
    --color-category-5: #8aa2c4;
    --color-category-6: #a794c9;
    --color-category-7: #5fb5a8;
    --color-category-8: #c7ab72;

    --color-scale-1: #1a2830;
    --color-scale-2: #22394a;
    --color-scale-3: #2b4d63;
    --color-scale-4: #35637f;
    --color-scale-5: #40799b;
    --color-on-scale: var(--color-gray-50);
}
