/* ═══════════════════════════════════════════════════════════════════════════
   TUXORA — DESIGN TOKENS

   Three layers, and the order matters:

     1  Primitives      raw ramps and scales. Never referenced by a component.
     2  Semantic tokens the only thing components consume. Roles, not values.
     3  Components      recipes, in app.css.

   A component that reaches past layer 2 is a bug: it breaks dark mode, it
   breaks theming, and it breaks silently.

   Three independent axes drive everything, written on <html> by the shell:

     data-preset    graphite | aqua | steel | amethyst | custom   (the company)
     data-density   comfortable | compact                          (the user)
     data-mode      light | dark                                   (the user)

   Any combination is valid. Aqua compact in dark is as legitimate as steel
   comfortable in light.
   ═══════════════════════════════════════════════════════════════════════════ */


/* ───────────────────────────────────────────────────────────────────────────
   LAYER 1 — PRIMITIVES
   ─────────────────────────────────────────────────────────────────────────── */
:root {
    /* State ramps. Shared across every theme on purpose: "danger" cannot mean a
       different colour depending on the industry. */
    --raw-success-600: #15803D;
    --raw-success-400: #4ADE80;
    --raw-success-050: #E8F5EC;
    --raw-success-950: #0B2F19;
    --raw-warning-600: #B45309;
    --raw-warning-400: #FBBF24;
    --raw-warning-050: #FDF3E3;
    --raw-warning-950: #3A2508;
    --raw-danger-600: #B42318;
    --raw-danger-400: #F87171;
    --raw-danger-050: #FDECEA;
    --raw-danger-950: #3C1210;
    --raw-info-600: #1D4ED8;
    --raw-info-400: #60A5FA;
    --raw-info-050: #E8EFFD;
    --raw-info-950: #111E3E;

    /* Type. System stacks, no web fonts: a receptionist on a bad connection
       should not wait for a font download to read the day's schedule. */
    --font-ui: ui-sans-serif, -apple-system, "Segoe UI Variable Text", "Segoe UI", system-ui, Roboto, sans-serif;
    --font-mono: ui-monospace, "Cascadia Code", "Cascadia Mono", Consolas, "SF Mono", monospace;

    /* Scale. 14px body for the internal app: it is a dense working tool, not a
       reading surface. The public booking portal overrides this to 16. */
    --text-display: 1.75rem;
    --text-h1: 1.375rem;
    --text-h2: 1.125rem;
    --text-h3: 0.9375rem;
    --text-body: 0.875rem;
    --text-small: 0.8125rem;
    --text-caption: 0.75rem;
    --text-label: 0.6875rem;

    --lh-tight: 1.2;
    --lh-snug: 1.4;
    --lh-normal: 1.55;

    /* Spacing, multiples of 4. */
    --sp-1: 4px;
    --sp-2: 8px;
    --sp-3: 12px;
    --sp-4: 16px;
    --sp-5: 20px;
    --sp-6: 24px;
    --sp-8: 32px;
    --sp-10: 40px;
    --sp-12: 48px;

    --ease: cubic-bezier(.2, .7, .3, 1);
}


/* ───────────────────────────────────────────────────────────────────────────
   IDENTITY — theme. Colour and shape. The company's choice: it is their brand.

   Named after minerals, never after industries. A theme called "Clinic" tells
   a workshop owner that its teal is not for them, and there is no reason it
   should not be. The industry belongs in the Vertical Pack.
   ─────────────────────────────────────────────────────────────────────────── */

/* Graphite — near-black, cool neutrals, restrained radius.
   The default. For companies that want the platform to disappear. */
:root,
[data-preset="graphite"] {
    --brand: #1F2933;
    --brand-hover: #0F1720;
    --brand-ink: #FFFFFF;
    --brand-subtle: #EEF1F4;
    --brand-subtle-ink: #1F2933;
    --n0: #FFFFFF;
    --n50: #F7F8F9;
    --n100: #EEF0F2;
    --n200: #E1E4E8;
    --n300: #CBD1D8;
    --n500: #6B7681;
    --n700: #3D464F;
    --n900: #1F2933;
    --n950: #12181D;
    --radius: 6px;
    --radius-sm: 4px;
    --radius-lg: 10px;
}

/* Aqua — teal, cyan-biased neutrals, generous radius. Calm and clean. */
[data-preset="aqua"] {
    --brand: #0E7C86;
    --brand-hover: #0A626A;
    --brand-ink: #FFFFFF;
    --brand-subtle: #E3F3F4;
    --brand-subtle-ink: #08494F;
    --n0: #FFFFFF;
    --n50: #F5FAFA;
    --n100: #EAF2F3;
    --n200: #D9E7E9;
    --n300: #BFD3D6;
    --n500: #63787B;
    --n700: #37494C;
    --n900: #182B2E;
    --n950: #0D1A1C;
    --radius: 12px;
    --radius-sm: 8px;
    --radius-lg: 16px;
}

/* Steel — steel blue, warm neutrals, nearly square corners. Sober, technical.

   Amber would be the obvious colour for an "industrial" theme, and that is
   exactly why it is not here: amber means "attention". Spending it on a
   primary button blunts the one signal read without thinking. */
[data-preset="steel"] {
    --brand: #31708E;
    --brand-hover: #255870;
    --brand-ink: #FFFFFF;
    --brand-subtle: #E7EFF3;
    --brand-subtle-ink: #1C4459;
    --n0: #FFFFFF;
    --n50: #F8F8F6;
    --n100: #F0EFEB;
    --n200: #E3E1DB;
    --n300: #CCC9C0;
    --n500: #726F66;
    --n700: #45433D;
    --n900: #26241F;
    --n950: #161512;
    --radius: 4px;
    --radius-sm: 2px;
    --radius-lg: 6px;
}

/* Amethyst — violet, violet-biased neutrals, rounded. The most expressive. */
[data-preset="amethyst"] {
    --brand: #7048C4;
    --brand-hover: #5A38A3;
    --brand-ink: #FFFFFF;
    --brand-subtle: #F0EAFB;
    --brand-subtle-ink: #442A7A;
    --n0: #FFFFFF;
    --n50: #FAF8FD;
    --n100: #F2EFF7;
    --n200: #E6E1EF;
    --n300: #CFC7DD;
    --n500: #6F6880;
    --n700: #433D52;
    --n900: #231F2E;
    --n950: #15121C;
    --radius: 10px;
    --radius-sm: 6px;
    --radius-lg: 14px;
}

/* Custom — the company picks a hue and everything derives from it, neutrals
   included. That is what makes a custom theme look composed rather than
   bolted on. The hue arrives as --brand-h from the company's settings, and
   BrandHueValidator has already checked it does not collide with a state
   colour. */
[data-preset="custom"] {
    --brand: hsl(var(--brand-h) 62% 38%);
    --brand-hover: hsl(var(--brand-h) 62% 30%);
    --brand-ink: #FFFFFF;
    --brand-subtle: hsl(var(--brand-h) 55% 95%);
    --brand-subtle-ink: hsl(var(--brand-h) 60% 24%);
    --n0: #FFFFFF;
    --n50: hsl(var(--brand-h) 20% 98%);
    --n100: hsl(var(--brand-h) 16% 95%);
    --n200: hsl(var(--brand-h) 14% 90%);
    --n300: hsl(var(--brand-h) 12% 82%);
    --n500: hsl(var(--brand-h) 8% 45%);
    --n700: hsl(var(--brand-h) 10% 27%);
    --n900: hsl(var(--brand-h) 14% 14%);
    --n950: hsl(var(--brand-h) 16% 8%);
    --radius: 8px;
    --radius-sm: 5px;
    --radius-lg: 12px;
}


/* ───────────────────────────────────────────────────────────────────────────
   ERGONOMICS — density. Independent of the theme, and the user's choice.

   Someone entering a hundred work orders a shift wants 32px rows even if their
   company chose Aqua. Someone seeing one patient at a time wants air even if
   their company chose Steel. Tying density to colour forces a choice between
   the brand and being comfortable.
   ─────────────────────────────────────────────────────────────────────────── */
:root,
[data-density="comfortable"] {
    --row-h: 42px;
    --control-h: 38px;
    --pad-x: 16px;
    --section-gap: var(--sp-10);
}

[data-density="compact"] {
    --row-h: 32px;
    --control-h: 30px;
    --pad-x: 10px;
    --section-gap: var(--sp-6);
}


/* ───────────────────────────────────────────────────────────────────────────
   LAYER 2 — SEMANTIC TOKENS
   The only thing components touch. A component asks for "raised surface", not
   "grey 50". That is why dark mode reassigns values and touches no component.
   ─────────────────────────────────────────────────────────────────────────── */
:root {
    --surface-page: var(--n50);
    --surface-raised: var(--n0);
    --surface-sunken: var(--n100);
    --surface-hover: var(--n100);

    --ink: var(--n900);
    --ink-secondary: var(--n700);
    --ink-muted: var(--n500);

    --line: var(--n200);
    --line-strong: var(--n300);

    --success: var(--raw-success-600);
    --success-bg: var(--raw-success-050);
    --warning: var(--raw-warning-600);
    --warning-bg: var(--raw-warning-050);
    --danger: var(--raw-danger-600);
    --danger-bg: var(--raw-danger-050);
    --info: var(--raw-info-600);
    --info-bg: var(--raw-info-050);

    --shadow-1: 0 1px 2px rgb(0 0 0 / .06);
    --shadow-2: 0 2px 8px rgb(0 0 0 / .08), 0 1px 2px rgb(0 0 0 / .04);

    color-scheme: light;
}

/* Dark mode. Only tokens are reassigned; no component knows.

   Not an inversion: surfaces rise in luminance with elevation, the opposite of
   light mode, and brand colours lighten so they keep contrast on a dark ground. */
[data-mode="dark"] {
    --surface-page: var(--n950);
    --surface-raised: var(--n900);
    --surface-sunken: #000;
    --surface-hover: var(--n700);

    --ink: var(--n50);
    --ink-secondary: var(--n300);
    --ink-muted: #8C949C;

    --line: var(--n700);
    --line-strong: var(--n500);

    --success: var(--raw-success-400);
    --success-bg: var(--raw-success-950);
    --warning: var(--raw-warning-400);
    --warning-bg: var(--raw-warning-950);
    --danger: var(--raw-danger-400);
    --danger-bg: var(--raw-danger-950);
    --info: var(--raw-info-400);
    --info-bg: var(--raw-info-950);

    --shadow-1: 0 1px 2px rgb(0 0 0 / .5);
    --shadow-2: 0 2px 10px rgb(0 0 0 / .55), 0 1px 2px rgb(0 0 0 / .4);

    color-scheme: dark;
}

[data-mode="dark"][data-preset="graphite"] {
    --brand: #E4E8EC;
    --brand-hover: #FFFFFF;
    --brand-ink: #12181D;
    --brand-subtle: #2A343D;
    --brand-subtle-ink: #E4E8EC;
}

[data-mode="dark"][data-preset="aqua"] {
    --brand: #3FB6BF;
    --brand-hover: #5FCBD3;
    --brand-ink: #06282B;
    --brand-subtle: #123A3E;
    --brand-subtle-ink: #9BDDE2;
}

[data-mode="dark"][data-preset="steel"] {
    --brand: #63A6C4;
    --brand-hover: #83BCD6;
    --brand-ink: #0B222D;
    --brand-subtle: #1D3543;
    --brand-subtle-ink: #A9CFE1;
}

[data-mode="dark"][data-preset="amethyst"] {
    --brand: #A585E0;
    --brand-hover: #BCA1EA;
    --brand-ink: #1B1229;
    --brand-subtle: #2E2440;
    --brand-subtle-ink: #CDB9F0;
}

[data-mode="dark"][data-preset="custom"] {
    --brand: hsl(var(--brand-h) 55% 66%);
    --brand-hover: hsl(var(--brand-h) 55% 76%);
    --brand-ink: hsl(var(--brand-h) 40% 12%);
    --brand-subtle: hsl(var(--brand-h) 25% 22%);
    --brand-subtle-ink: hsl(var(--brand-h) 50% 82%);
    --n50: hsl(var(--brand-h) 12% 96%);
    --n300: hsl(var(--brand-h) 10% 74%);
    --n500: hsl(var(--brand-h) 8% 48%);
    --n700: hsl(var(--brand-h) 12% 26%);
    --n900: hsl(var(--brand-h) 16% 13%);
    --n950: hsl(var(--brand-h) 20% 7%);
}
