/* Authored CSS entry — web-ui's own additions on top of the vendored
 * design-system bundle. Each import names the cascade layer it joins so
 * the rules sit at the right level of the cascade declared by layers.css.
 *
 * The vendored layers.css defines the layer ordering:
 *   reset, tokens, theme-chrome, base, layouts, components, utilities
 *
 * Authored shell pieces (header, app-shell composition, the left rail)
 * sit in the layouts layer because they are composition primitives owned
 * by this project. The header's classes (.nav-region, .nav-hamburger) are
 * project-owned layout primitives, not competing with vendored component
 * classes, so it belongs in layouts alongside the shell and sidebar. The
 * rail owns its own class names (.rail-nav / .rail-link) and its profile
 * popover uses the vendored data-placement contract for the upward,
 * start-aligned placement rather than a hand-rolled anchor override. The
 * drawer variant is a component variant and sits in the components layer
 * beside the vendored drawer.css.
 */

@import url("components/icons-extended.css") layer(tokens);
/* Authored token extensions — the UI type-role ladder (page title,
 * section heading, item title, meta). Additive names over the vendored
 * role aliases; see the file header. */
@import url("tokens.css") layer(tokens);
@import url("base/appearance.css") layer(base);
@import url("layouts/app-shell.css") layer(layouts);
@import url("layouts/app-header.css") layer(layouts);
@import url("layouts/app-sidebar.css") layer(layouts);
/* Vendored-component gap fills. Imported first among the component sheets:
 * these complete a vendored component's own contract rather than dressing a
 * project surface, so a page sheet can still specialise deliberately. */
@import url("components/button-extensions.css") layer(components);
@import url("components/chip-extensions.css") layer(components);
/* The overflow primitive's own sheet: what a menu of extra actions adds on
 * top of the vendored popover, wherever one is rendered. Beside the button
 * gap-fill because it completes a vendored component the same way. */
@import url("components/overflow-menu.css") layer(components);
/* The in-place row act's own sheet: the trigger, its spinner and the region
 * its result lands in, plus the switch's busy face. Beside the overflow
 * primitive for the same reason. */
@import url("components/row-act.css") layer(components);
/* The checked-by stamp's own sheet: the source it cites is a link inside
 * sentence text, which no page-level sheet can be trusted to remember. */
@import url("components/checked-by.css") layer(components);
/* Shared page grammar. Imported ahead of the chrome and page files so a
 * page-specific sheet can still specialise a surface deliberately; each
 * of these is the one owner of its concern across every route. */
@import url("components/section-heading.css") layer(components);
/* Auth-family surfaces served by the auth-server module (OAuth consent,
 * start-again). The shell classes live in identity-page.css; this sheet
 * owns the consent-specific grouping and row anatomy. */
@import url("components/consent-page.css") layer(components);
@import url("components/page-title.css") layer(components);
@import url("components/page-header.css") layer(components);
@import url("components/empty-state.css") layer(components);
@import url("components/form-column.css") layer(components);
@import url("components/results-toolbar.css") layer(components);

@import url("components/app-topbar.css") layer(components);
@import url("components/detail-action-bar.css") layer(components);
@import url("components/detail-screen.css") layer(components);
@import url("components/app-drawer.css") layer(components);
@import url("components/profile-menu.css") layer(components);
@import url("components/chat-page.css") layer(components);
@import url("components/chat-panel.css") layer(components);
@import url("components/voice-composer.css") layer(components);
@import url("components/library-page.css") layer(components);
/* The Library's draw-a-map page: the ground, the pin, the candidates and the
 * picture that will be filed. Its own sheet because it dresses Leaflet, which
 * no other page loads. */
@import url("components/map-draw.css") layer(components);
@import url("components/search-page.css") layer(components);
@import url("components/overview-page.css") layer(components);
@import url("components/coming-up.css") layer(components);
@import url("components/newsroom-calendar.css") layer(components);
@import url("components/newsroom-page.css") layer(components);
@import url("components/alpha-newsroom.css") layer(components);
@import url("components/work-rail.css") layer(components);
@import url("components/list-beside-detail.css") layer(components);
@import url("components/newsroom-workspace.css") layer(components);
@import url("components/newsroom-story-detail.css") layer(components);
@import url("components/picture-stage.css") layer(components);
/* The shaped slot every surface that renders a picture at a fixed shape
 * composes: the newsroom preview's hero and lead, the reader's page. Beside
 * the stage because the two are the picture pair: the stage shows the whole
 * frame, this shows what one shape keeps of it. */
@import url("components/shaped-picture.css") layer(components);
@import url("components/article-settings.css") layer(components);
@import url("components/story-file.css") layer(components);
@import url("components/video-production.css") layer(components);
@import url("components/story-preview.css") layer(components);
@import url("components/settings-page.css") layer(components);
@import url("components/ai-providers.css") layer(components);
@import url("components/models-page.css") layer(components);
@import url("components/distribution-page.css") layer(components);
@import url("components/topics.css") layer(components);
@import url("components/harness-admin.css") layer(components);
@import url("components/harness-authoring.css") layer(components);
@import url("components/workflow-run.css") layer(components);
@import url("components/identity-page.css") layer(components);
@import url("components/command-palette.css") layer(components);
@import url("components/chat-search-dialog.css") layer(components);
@import url("components/combobox.css") layer(components);
@import url("components/text-editor-omni.css") layer(components);
@import url("components/story-body-editor.css") layer(components);
@import url("components/portal-dialog.css") layer(components);
@import url("components/story-activity.css") layer(components);
@import url("components/kinetic-captions.css") layer(components);
@import url("components/video-player-controls.css") layer(components);
@import url("components/caption-preview.css") layer(components);
@import url("components/subject-overlay.css") layer(components);
@import url("components/feedback-canvas.css") layer(components);
@import url("components/toast.css") layer(components);

/* Authored utilities — single-purpose helpers that win over the
 * component-layer element rules by virtue of the later utilities layer. */
@import url("utilities/text-meta.css") layer(utilities);
@import url("utilities/thumbnail-fallback.css") layer(utilities);

/* Authored token aliases — additive only. These join the tokens layer and
 * name new tokens that resolve to vendored primitives/semantic tokens; they
 * never override a vendored token name (DESIGN.md "Extending tokens"). Later
 * parallel work references these; do not edit this file from those lanes. */
@layer tokens {
    :root {
        /* Caption kinetic palette (video fix-forward C1/C2).
         * FIXED across light/dark by design: already-spoken words must stay
         * black in dark mode, so these alias raw gray/brand primitives, not
         * theme text tokens (which flip with appearance). Only the current
         * word follows the brand. */
        /* Fixed like the other three, and for the same reason. This word used
         * to follow the brand, which reads as the exception the paragraph above
         * describes; it was really the bug. The backing below is --gray-2, a
         * fixed light grey in every appearance and every preset, and a
         * theme-following ink cannot be safe on it in any grade: measured on the
         * rendered backing, the brand-following value bottoms out at 1.20:1
         * (amber palette, dark) and never clears the floor under a preset that
         * pins dark surfaces, in either appearance, because those presets pin an
         * ink meant for a dark ground. Neither the action family's text grade nor
         * pinning the caption line to a light colour-scheme fixes that: both
         * still follow the preset. --blue-9 is the ramp step the action family's
         * text grade and the link colour both resolve to at the bare default, so
         * the caption is unchanged there, and being a raw primitive it holds
         * 5.13:1 on the backing in every configuration. */
        --caption-word-current: var(--blue-9);         /* fixed, text-grade on the backing */
        --caption-word-spoken: var(--gray-9);          /* near-black, fixed */
        --caption-word-pending: var(--gray-4);         /* light grey, fixed */
        --caption-backing: var(--gray-2);              /* grey backing, fixed */

        /* Closed-caption palette. Deliberately NOT the kinetic house style:
         * closed captions are the traditional broadcast/OTT artefact and must
         * read as one, so this is the familiar white on a translucent dark
         * strip. FIXED across light/dark for the same reason the kinetic
         * palette is: captions sit over video frames, not over the app's
         * surfaces, so they must not flip with the appearance setting. */
        --caption-closed-text: var(--gray-0);
        --caption-closed-backing: color-mix(in srgb, var(--gray-12) 75%, transparent);

        /* Subject-detection box palette (video fix-forward B5).
         * Three theme-aware, hue-distinct kinds mapped to existing semantic
         * status tokens (each is light-dark() in the vendored layer, so the
         * boxes adapt to appearance). Blue / amber / green are separated on
         * the hue wheel for at-a-glance distinction; red (--color-error) is
         * deliberately avoided because red on a video monitor reads as a
         * recording/error signal. */
        --subject-person: var(--color-info);    /* blue */
        --subject-face: var(--color-warning);   /* amber/yellow */
        --subject-object: var(--color-success); /* green */

        /* Review-note marks: the words a note was written about, marked in
         * the copy under review.
         *
         * Amber, and deliberately not blue. Blue is already spoken for three
         * times over on this surface — the focus ring, the link colour, and
         * the transient [data-recently-changed] wash that says someone else
         * just altered a field — and a mark has to be none of those at a
         * glance. Amber is also what a reader expects annotated text to look
         * like, which is the whole point.
         *
         * A HIGHLIGHT TINTS THE GROUND AND KEEPS THE PAGE'S INK. That is what
         * a highlighter does to a page, and it is the rule these tokens now
         * follow, after two earlier tries that did not. Naming a fixed
         * surface/text pair from the warning family made the words unreadable
         * in dark. Mixing amber into the PRIMITIVE --gray-0 and painting the
         * full-strength fill's on-colour over that dilution then read at
         * 2.13:1 the moment the operator chrome changed preset, because an
         * on-colour is a promise about the undiluted fill and about nothing
         * else. Marked words are copy, so they take the copy's own ink and
         * carry its legibility wherever the preset goes; only the ground
         * moves.
         *
         * The mix is measured, not chosen by eye. Read off the rendered page:
         * editorial-ai 11.29:1 light and 8.78:1 dark, modern 13.59:1 light
         * and 8.12:1 dark. Swept across every theme preset the design system
         * ships, in both appearances, 25% is the highest tint that keeps all
         * of them clear of the 4.5:1 floor — the thinnest is neumorphism in
         * dark at 4.66:1, and by 30% it has fallen through. So 25% is a
         * ceiling on how much tint the ink can carry, not a round number.
         *
         * Nothing here says "warning": the family is borrowed for its hue,
         * and the names say what they are for. */
        --note-mark-surface: color-mix(in srgb, var(--color-warning) 25%, var(--color-surface));
        /* The words in a mark and the rule under them are the copy's words,
         * so they take the copy's ink. The ring drawn round an active mark is
         * painted outside the mark, on the copy's own ground, so it takes the
         * same ink and lands at the page's full contrast. */
        --note-mark-ink: var(--color-text);
        /* Being pointed at is the one place the undiluted warning fill is
         * painted, so it is also the one place the design system's on-amber
         * pair is the right ink. */
        --note-mark-active-surface: var(--color-warning);
        --note-mark-active-ink: var(--color-on-warning);
        /* The ring drawn round a note's card when its words are being pointed
         * at. It sits on the card's own surface, not on amber, so it is the
         * amber itself rather than the ink. */
        --note-mark-signal: var(--color-warning);

        /* A note read on the words rather than in the rail reads at the width
         * it would have had in the rail, so the same note is the same shape
         * whichever posture the reviewer is in. */
        --note-mark-popover-width: 21rem;
    }
}
