/* Theme tokens — the single source of truth for both themes.
   The charte is sober by construction: neutral greys carry every surface, and a
   single blue is kept for the selected state and for the fill of a control that
   has to be found. There is no second hue and no brand gradient — a surface that
   needs to stand out takes a grey weight, not a colour.
   `:root` is the light theme and stays first; `html[data-theme="dark"]` below
   only redefines colours (never --radius or the three family tokens, which are
   shared) and is switched on by public/js/theme.js, before the first paint. */

:root {
    color-scheme: light;

    /* ---- neutral scale (light theme) ----
       The canvas and the blocks sitting on it share one value, as the charte has
       them: what separates a block from the page is its border, not a tint. */
    --bg-color: #ffffff;
    --panel-color: #ffffff;
    --input-bg: #ffffff;
    --bg-secondary: #f6f6f6;

    /* ---- text ----
       The mock-up's own greys, kept at its values: #707070 carries the text,
       #C2C2C2 the counters, disabled labels and the muted metadata. The mock-up
       also paints the assistant's message body in a third grey of its own
       (#888888), and that text is read: it is painted with --text-color, a
       lighter grey for a text being a level nobody asked for.
       The light theme reads 4.95:1 for #707070 on white and 1.78:1 for #C2C2C2:
       the muted level is far below AA, and it is the charte's value. Legibility
       of the palette belongs to the graphic designer, so the contract below
       records these values instead of refusing them -- the icon, border and
       disabled uses #C2C2C2 was chosen for in the mock-up never needed to be
       read. Where a token's use is *text the user must read* and the mock-up
       paints it #707070, that site belongs on --text-color, not here. */
    --text-color: #707070;
    --text-dim: #c2c2c2;

    /* ---- the one blue ----
       The charte's blue, kept at the mock-up's own value and used everywhere the
       interface turns blue: the fill of a control, a border that becomes active,
       the selected tab, the wash of a selected row, and the text that is blue
       (links, section headings, a selected label). --accent-dim is a lighter
       pass for a border that appears on hover, --accent-hover the shade a link
       takes when it is pointed at. */
    --accent-color: #6ea5dc;
    --accent-dim: #7fb2e2;
    --accent-hover: #2a6fb6;
    --link-color: #6ea5dc;

    /* ---- text drawn on a filled surface (light theme) ----
       --on-accent: on --accent-color; --on-veil: on the dark full-screen veils
       (media preview, loading spinner). */
    --on-accent: #ffffff;
    --on-veil: #ffffff;

    /* ---- borders ----
       Two weights and no more: --border-color outlines a container, and it is
       the stronger of the two, because with the canvas and the panels sharing
       one white it is what draws the plan out. --panel-border-color draws the
       edge of a piece inside a container, inputs included -- a field is a piece,
       not a second kind of edge. */
    --border-color: #c2c2c2;
    --panel-border-color: #d4d4d4;

    /* ---- list-row interaction tints ----
       The wash every clickable row of the left panels shares (session, memory,
       skills): a low-alpha pass of --accent-color, so a row reads as selected
       without the panel gaining a second surface colour. */
    --row-hover-bg: rgba(110, 165, 220, 0.12);
    --row-selected-bg: rgba(110, 165, 220, 0.24);

    /* ---- a row's own ground ----
       The mock-up's `#FBFBFB` ("secondary card fill" in its palette), the one notch
       a session row sits above the panel it is listed in -- which is what makes a
       list read as rows rather than as one block. Measured on the panel's own
       #FFFFFF: the four units are a tint, not a shade, and that is the charte's
       intent. */
    --row-bg: #fbfbfb;

    /* ---- the reader's own surface ----
       The one filled grey of the charte, and two sites: the bubble that carries
       the reader's message, and the button that sends one -- the mock-up paints
       both #8F8F8F, so one token serves the two rather than a second grey nobody
       could tell apart. The ink on it is a token of its own because the pair
       inverts between the themes. Measured in light on that fill: #FFFFFF reads
       3.23:1 -- the charte's value, below AA like its blue, kept as it stands. */
    --user-surface-color: #8f8f8f;
    --on-user-surface: #ffffff;

    /* ---- state colours (light theme) ----
       Semantic, outside the neutral scale: a failure, a warning or a success
       keeps its own hue, because being told apart at a glance is the point. */
    --error-color: #b91c1c;
    --error-bright: #dc2626;
    /* The danger's fill under the pointer: one step further from the surface, the
       move --accent-hover makes for the blue. */
    --error-hover: #991b1b;
    --error-bg: #fdecea;
    --error-text: #b71c1c;
    --warn: #b45309;
    --danger-bg: #fef2f2;
    --danger-text: #b91c1c;
    --danger-border: #fecaca;
    --success-bg: #e8f5e9;
    --success-text: #1b5e20;

    /* ---- shadows, focus ring and veils (light theme) ----
       Calibrated for light surfaces: the dark theme re-tints them, because a
       shadow mixed for a light background is invisible on a dark one. */
    --shadow-xs: 0 1px 3px rgba(0, 0, 0, 0.05);
    --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.08);
    --shadow-lg: 0 12px 28px rgba(0, 0, 0, 0.45);
    --shadow-float: 2px 2px 5px rgba(0, 0, 0, 0.2);
    --shadow-auth: 0 28px 80px rgba(0, 0, 0, 0.14);
    --focus-ring: 0 0 0 3px rgba(110, 165, 220, 0.40);
    --overlay-bg: rgba(20, 20, 20, 0.82);
    --spinner-veil: rgba(0, 0, 0, 0.5);

    --radius: 12px;

    /* ---- families ----
       Three roles, three faces, all served from public/fonts (see fonts.css).
       Lato carries the body. It ships two weights only, 400 and 700 -- plus a 400
       italic -- so every font-weight in the stylesheets is written in one of those
       two values: a 500 or a 600 has no face to land on and the browser would
       silently pick a neighbour. Montserrat dresses a project's group header in the
       tree; Oleo Script the brand name. A face nothing asks for is never
       downloaded, so a family left declared ahead of its zone costs nothing.

       Carlito keeps its faces in fonts.css: it is the metric-compatible counterpart
       of the charte's Calibri, same advance widths, and the charte's own reference
       for the body. Nothing consumes it, so nothing downloads it. */
    --lato: "Lato", sans-serif;
    --montserrat: "Montserrat", sans-serif;
    --oleo: "Oleo Script Swash Caps", cursive;
}

/* ---- dark theme ----
   Only colours: every token below is consumed by the same rules as its light
   counterpart, so no stylesheet has to know which theme is active.
   The scale is the light one inverted -- the same three greys, the same one
   blue -- and the borders are lifted, because a hairline that reads on white
   disappears on a near-black surface.
   Contrast (checked by tests/front/test_theme_tokens.py): 4.5:1 on the main
   text, links and accent; 3:1 on dimmer text, borders and meaningful icons; and
   never worse than the light-theme ratio for a given pair. */
html[data-theme="dark"] {
    color-scheme: dark;

    /* Neutral scale: the surfaces keep the blue-tinted greys the app already
       used at night -- they read cooler than a pure neutral, and they cost
       nothing in contrast, being darker than the light theme's counterparts.
       The canvas stays deeper than the panels, which is what the light theme
       cannot do (white is its floor). The soft fill sits one notch above the
       canvas so the composer bar and a hovered control still read as a band,
       and the field stays the lightest surface of the four. */
    --bg-color: #0f131b;
    --panel-color: #171d29;
    --input-bg: #1c232f;
    --bg-secondary: #12171f;

    /* Text */
    --text-color: #e6e6e6;
    --text-dim: #b4b4b4;

    /* The one blue, raised so it reads on a dark surface: --on-accent stays a
       near-black, which is what keeps a label legible on a light-blue fill. */
    --accent-color: #7fb0dd;
    --accent-dim: #6a9bc9;
    --accent-hover: #a8cff0;
    --link-color: #8dbde8;
    --on-accent: #10151b;
    --on-veil: #f4f6fa;

    /* Borders: the container's edge is the stronger one here too. */
    --border-color: rgba(255, 255, 255, 0.46);
    --panel-border-color: rgba(255, 255, 255, 0.38);

    /* List-row interaction tints */
    --row-hover-bg: rgba(127, 176, 221, 0.14);
    --row-selected-bg: rgba(127, 176, 221, 0.22);

    /* A row's own ground: one notch above the panel, as the light theme's #FBFBFB is
       one notch under its white -- the light theme cannot go brighter, so here the
       row lifts instead of sinking, and it still reads as a row. */
    --row-bg: #1b222e;

    /* The reader's own surface: lighter than the panel it sits on, so the block
       still reads as a block on a dark page. */
    --user-surface-color: #3d4450;
    --on-user-surface: #f2f4f8;

    /* State colours: light-theme values are calibrated for light surfaces and
       would be unreadable here, so each one is re-tinted for dark surfaces. */
    --error-color: #ff8f8f;
    --error-bright: #ff6b6b;
    --error-hover: #ffadad;
    --error-bg: #3a1c22;
    --error-text: #ffb4b4;
    --warn: #f5b544;
    --danger-bg: #3a1c22;
    --danger-text: #ffb4b4;
    --danger-border: #8a3a44;
    --success-bg: #14301f;
    --success-text: #8ce9a8;
    /* Shadows, focus ring and veils */
    --shadow-xs: 0 1px 3px rgba(0, 0, 0, 0.45);
    --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.5);
    --shadow-lg: 0 12px 28px rgba(0, 0, 0, 0.6);
    --shadow-float: 2px 2px 5px rgba(0, 0, 0, 0.5);
    --shadow-auth: 0 28px 80px rgba(0, 0, 0, 0.55);
    --focus-ring: 0 0 0 3px rgba(127, 176, 221, 0.35);
    --overlay-bg: rgba(0, 0, 0, 0.78);
    --spinner-veil: rgba(0, 0, 0, 0.6);
}
