/*
 * Omega design system — token layer.
 *
 * Loads after style.css so these :root declarations win. Both are equal specificity,
 * so order is the only thing deciding it: see App.razor.
 *
 * TOKENS ONLY. No component rules, no element selectors. Components live in
 * omega-design-system.css or in the owning component's .razor.css.
 *
 * The primitive ramps and scales below are additive — nothing referenced them before
 * this file existed, so adding them cannot change a rendered pixel. The legacy aliases
 * at the bottom are the part that can, and they are held byte-identical to the values
 * they replaced in style.css, with one deliberate exception noted inline.
 */

:root {
    /* ---------------------------------------------------------------------
     * Primitives — brand
     *
     * Teal, navy and coral are locked brand colours. The ramp steps absorb the
     * eight stray greens and five stray corals found across the codebase:
     * #2f8a80 and #2f8279 were rounding errors on 600; #286760 and #245b55 were
     * real hover/active states and become 700 and 800; #0f6f72 and #17616a were
     * cyan drift and now resolve to 700 and 800 respectively.
     *
     * Several steps here have no consumer -- teal-50/100/200/400, coral-50/200/ink.
     * They stay. A ramp is a designed set and its usefulness is that any step is
     * there when a component needs one; a ramp with holes punched in it for tidiness
     * is worse than one with spare steps. This is the single exception to the rule
     * that a token either gains a consumer or is deleted.
     *
     * The coral ramp does have a real gap, though: nothing sits between 500 and 700.
     * Button hover states need it -- see the #f16d48 note in StyleConventionTests.
     * ------------------------------------------------------------------ */
    --omega-teal-50: #F2F9F8;
    --omega-teal-100: #ECF7F6;
    --omega-teal-200: #D6E9E6;
    --omega-teal-400: #5C9B94;
    --omega-teal-600: #307B74;
    --omega-teal-700: #286760;
    --omega-teal-800: #245B55;
    --omega-teal-900: #1B4541;
    --omega-teal-rgb: 48, 123, 116;

    --omega-navy-800: #0E2B56;
    --omega-navy-rgb: 14, 43, 86;

    --omega-coral-50: #FEF1EB;
    --omega-coral-200: #FFD4C7;
    --omega-coral-500: #FE7D58;
    /* The hover step. Not a new colour: #F16D48 was already written out by hand on every
       coral button, and it sits 2.4 Lab units from the perceptual midpoint of 500 and 700,
       so it is the step the ramp was missing rather than one invented to fill the hole.
       Like its neighbours it is a fill, not a text colour -- white on it is 2.99:1, where
       500 is 2.53 and 700 is 3.72. Text on coral uses --omega-coral-ink. */
    --omega-coral-600: #F16D48;
    --omega-coral-700: #DB5D3B;
    /* The only coral that carries text. 6.38:1 on white; coral-500 is 2.53:1 and fails AA. */
    --omega-coral-ink: #A8391B;

    /* ---------------------------------------------------------------------
     * Primitives — ink, surfaces, borders
     * ------------------------------------------------------------------ */
    --omega-ink: #030911;
    --omega-text: #333333;
    --omega-text-muted: #626B76;
    /* Solid white for text on a filled brand or navy surface. Distinct from
     * --omega-text-on-dark below, which is 88% and is for secondary copy on those
     * same surfaces -- the two are different jobs, not two spellings of one. */
    --omega-text-on-inverse: #FFFFFF;
    --omega-text-on-dark: rgba(255, 255, 255, 0.88);

    --omega-surface-page: #FFFFFF;
    --omega-surface-neutral: #F2F4F7;
    --omega-surface-mint: #ECF7F6;
    --omega-surface-peach: #FEF1EB;
    /*
     * No --omega-surface-inverse. It held the same value as --omega-navy-800 and had no
     * consumers, while .omega-surface-inverse -- a class of the same name, doing the
     * actual work -- is live in site.css. Two names for one colour, one of which was a
     * near-miss for an existing class, is a trap rather than a token.
     */

    --omega-border: #E6EAF0;
    /* Unused. Same value as teal-200, and the two are not obviously distinguishable
       by name at the call site -- decide which survives before either gains a user. */
    --omega-border-strong: #D6E9E6;

    /* ---------------------------------------------------------------------
     * Status — one set for the whole product. The admin workspace already had
     * these; the public side had invented #a52828 for form errors instead.
     *
     * info-ink and info-bg have no consumer because the product has no
     * informational state yet -- only success, warning and danger are used. They
     * are kept so the set is complete when one arrives, rather than being
     * invented ad hoc at that point.
     * ------------------------------------------------------------------ */
    --omega-success-ink: #16764A;
    --omega-success-bg: #E9F8F0;
    --omega-warning-ink: #A65B00;
    --omega-warning-bg: #FFF3DF;
    --omega-danger-ink: #B42318;
    --omega-danger-bg: #FFF0EE;
    --omega-info-ink: #0E2B56;
    --omega-info-bg: #F2F4F7;

    /* ---------------------------------------------------------------------
     * Typography
     *
     * text-h1, text-display, text-lead and tracking-display are the hero title
     * sizes and have no consumer yet: the ~40 hand-tuned clamp() expressions the
     * heroes use are the last step of this migration and the most visible change
     * in it, so they ship on their own rather than riding along with a cleanup.
     *
     * Two gaps found by trying to use this scale rather than by reading it.
     * There is nothing between h4 (18px) and h3 (24.8px), and twelve declarations
     * sit in that hole at 20 to 22.4px. And above h3 there is no fixed step at
     * all -- h2 and display are both clamps -- so fixed sizes of 32, 40, 48 and
     * 80px have nowhere to go. Both need a design decision.
     * ------------------------------------------------------------------ */
    --omega-font-body: "Roboto", "Segoe UI", Arial, sans-serif;
    --omega-font-heading: "Raleway", "Roboto", "Segoe UI", Arial, sans-serif;

    /*
     * Capped at 3rem, and the story of that number is worth keeping.
     *
     * It was first fitted to the median of the 19 per-page hero clamps -- 4.25rem at the
     * top end. That was the wrong thing to fit to. Those rules had never rendered (see the
     * note in omega-design-system.css), so their values were an intention nobody had ever
     * seen on a page, not a design anyone had approved.
     *
     * What that missed is that almost every hero is a two-column grid: the title sits in a
     * ~532px column at 1440px, not the full 1300px. At 4.25rem, 14 of 23 page titles wrapped
     * to three lines and 16 pages wrapped worse than they had before. 3rem puts that back to
     * 7 of 23 -- what it was under the Bootstrap default -- while keeping the tighter leading
     * and a slightly larger size than the 45px that was rendering by accident.
     *
     * If the heroes ever give the title its own container, sizing on cqi instead of vw is the
     * better answer: it makes the title respond to the column rather than the window.
     * container-type on the grid cell itself does not work -- it collapses the track to zero.
     */
    --omega-text-display: clamp(2.15rem, 0.55rem + 4.1vw, 3rem);
    /*
     * Unused. It fits the admin editor and blog article headers -- a family that spans
     * 26px to 80px and needs consolidating on its own terms, not as part of the public
     * hero work. Left declared so that job has a target.
     */
    --omega-text-h1: clamp(2.1rem, 1.5rem + 2.4vw, 3.2rem);
    --omega-text-h2: clamp(1.75rem, 1.35rem + 1.6vw, 2.5rem);
    --omega-text-h3: 1.55rem;
    --omega-text-h4: 1.125rem;
    /*
     * The heading size between a section title and a small one: card titles, sub-section
     * headings, menu headings, form legends. Six rules were sitting at 20.8 or 21.6px with
     * nothing to reach for, because h3 at 24.8px is a SECTION heading and cards want less.
     *
     * A role name rather than a level, deliberately. Numerically it belongs between h3 and
     * h4, where there is no level to call it; and making h4 this size and pushing 18px down
     * to an h5 would move 20 existing declarations to fix a naming gap on six. The scale
     * already mixes role names -- eyebrow, lead, body, small -- so this fits how it reads.
     */
    --omega-text-subheading: 1.35rem;
    /*
     * Left at the design document's value, unlike display. The hero leads it would replace
     * are LIVE -- those elements sit in each page's own markup and so carry that page's
     * scope attribute -- so retuning this resizes real text by -31% to +29%. It goes with
     * the change that switches the titles on, where it can be looked at.
     */
    --omega-text-lead: clamp(1.05rem, 1rem + 0.3vw, 1.2rem);
    --omega-text-body: 1rem;
    --omega-text-small: 0.875rem;
    --omega-text-eyebrow: 0.75rem;

    --omega-leading-tight: 1.04;
    --omega-leading-heading: 1.16;
    --omega-leading-snug: 1.25;
    --omega-leading-body: 1.65;

    --omega-tracking-display: -0.02em;
    /* Unused, and no literal to absorb: not one heading in the codebase sets
       letter-spacing at all. Adopting it would be adding tightening where there is
       none, which is a type decision rather than a migration. */
    --omega-tracking-heading: -0.015em;
    --omega-tracking-eyebrow: 0.10em;

    /* ---------------------------------------------------------------------
     * Icons.
     *
     * font-size does two unrelated jobs here. It sizes text, and it sizes the icon
     * fonts and decorative shapes. Every type step in this migration had to exclude
     * the second kind by hand, because an icon tied to the type scale shrinks whenever
     * body copy does -- a relationship nobody asked for and nobody would notice until
     * it fired.
     *
     * 34 declarations were sizing glyphs across 20 distinct values, from 8.8px to 80px,
     * with no token among them. These steps come from those measured clusters rather
     * than from a formula, which is why md is 1.35rem and not something rounder: 1.35rem
     * was the single most common glyph size in the codebase.
     * ------------------------------------------------------------------ */
    --omega-icon-xs: 0.75rem;
    --omega-icon-sm: 1rem;
    --omega-icon-md: 1.35rem;
    --omega-icon-lg: 2rem;
    --omega-icon-xl: 2.5rem;
    --omega-icon-display: 5rem;

    /* ---------------------------------------------------------------------
     * Spacing — one scale for section rhythm, card padding and stack gaps.
     *
     * The admin workspace's --admin-space-1..5 are the same five values as
     * steps 2..6 here, not steps 1..5: that scale starts at .5rem where this
     * one starts at .25rem. They are defined in terms of these in
     * admin-design-system.css, so the two cannot drift, but the numbering does
     * not line up and reading --admin-space-3 as --omega-space-3 is wrong.
     * ------------------------------------------------------------------ */
    --omega-space-1: 0.25rem;
    --omega-space-2: 0.5rem;
    --omega-space-3: 0.75rem;
    --omega-space-4: 1rem;
    --omega-space-5: 1.25rem;
    --omega-space-6: 1.5rem;
    --omega-space-7: 2rem;
    --omega-space-8: 2.5rem;
    --omega-space-9: 3rem;
    --omega-space-10: 4rem;
    --omega-space-11: 5rem;

    /* Section rhythm. The slope is steeper than the card and hero clamps because
       a section break has to read as a break at a glance, from across the room,
       where card padding only has to separate a card from its own contents.
       96px a side on a wide desktop gives the 192px gutter between sections that
       the heading scale needs; the 56px floor keeps a phone from feeling padded
       out. Both ends govern directly, so no breakpoint override is needed. */
    --omega-section-y: clamp(3.5rem, 2.25rem + 5vw, 6rem);
    --omega-section-y-compact: clamp(2.25rem, 1.75rem + 2.5vw, 3.75rem);
    --omega-card-padding: clamp(1.35rem, 1rem + 1.4vw, 1.75rem);

    /* Public form fields. 48px keeps every control at the tap minimum, and the gap is
       the within-group rhythm; the between-group step stays on the spacing scale. */
    --omega-field-min-height: 48px;
    --omega-field-gap: 0.75rem;
    /* An alias for space-6 with no consumer. Kept because the name says "the gap
       between items in a vertical stack" where the number does not, and a stack
       component is the obvious next thing to build; delete it if that never comes. */
    --omega-stack-gap: var(--omega-space-6);

    /* ---------------------------------------------------------------------
     * Radius — lg is what every card actually renders today; the token layer
     * simply never had a name for it.
     * ------------------------------------------------------------------ */
    --omega-radius-xs: 4px;
    --omega-radius-sm: 8px;
    --omega-radius-md: 12px;
    --omega-radius-lg: 20px;
    --omega-radius-pill: 999px;

    /* ---------------------------------------------------------------------
     * Elevation.
     *
     * card and soft now carry the design system values. They were held at the
     * theme's originals while the token layer landed, so that step could claim to
     * be visually neutral; adopting them is a deliberate change to every card.
     * ------------------------------------------------------------------ */
    --omega-shadow-panel: 0 18px 50px rgba(14, 43, 86, 0.16);
    --omega-shadow-raised: 0 20px 42px rgba(14, 43, 86, 0.10);

    /* ---------------------------------------------------------------------
     * Motion — declared here, applied in the motion-contract step.
     *
     * slow, entrance and both easings have no consumer, and adopting them is not
     * a cleanup. The codebase uses the `ease` keyword 115 times; replacing that
     * with ease-standard changes the shape of every transition on the site, which
     * is a motion design decision rather than a token migration. Left for whoever
     * takes that decision.
     * ------------------------------------------------------------------ */
    --omega-duration-fast: 140ms;
    --omega-duration-base: 200ms;
    --omega-duration-slow: 320ms;
    --omega-duration-entrance: 520ms;

    /* Ambient continuous motion, currently only the client logo wall's drift.
       Deliberately outside the four-step scale above: that scale sizes state
       changes, and this is a loop that never resolves. Slow enough to read as
       drift rather than as a carousel.

       Not overridden in the reduced-motion block below, and it does not need to
       be: the animation that consumes it is declared only inside
       `@media (prefers-reduced-motion: no-preference)`, so under reduced motion
       there is no animation for a shortened duration to act on. */
    --omega-duration-drift: 52s;

    --omega-ease-standard: cubic-bezier(.2, 0, 0, 1);
    --omega-ease-exit: cubic-bezier(.4, 0, 1, 1);
    /* The one overshooting curve, for the playful children's components only. It exists as
       a token so the spring is a shared decision rather than a per-file literal. */
    --omega-ease-spring: cubic-bezier(.34, 1.56, .64, 1);

    /* ---------------------------------------------------------------------
     * Focus — one ring for the whole site.
     *
     * The design system draws this as a two-colour box-shadow (white inner,
     * navy outer) so it reads on any background. This implements it as an
     * outline instead, for two reasons: box-shadow is dropped entirely in
     * Windows forced-colors mode, and it would replace the existing shadow on
     * every focusable card. An outline cannot be clipped by an ancestor's
     * overflow, does not affect layout, and is drawn in forced-colors mode.
     *
     * Contrast on dark surfaces is handled by overriding the colour rather
     * than by a second ring: see --omega-focus-ring-color below.
     * ------------------------------------------------------------------ */
    --omega-focus-ring-width: 3px;
    --omega-focus-ring-offset: 2px;
    --omega-focus-ring-color: var(--omega-navy-800);
    --omega-focus-ring-color-inverse: #FFFFFF;

    /* ---------------------------------------------------------------------
     * Layout — the header heights replace calc(65svh - 116px), where 116 was an
     * undeclared guess that is wrong at every breakpoint by a different amount.
     * ------------------------------------------------------------------ */
    /*
     * container-max and gutter have no consumers and are not adopted here. Using them
     * means taking page width off Bootstrap's .container, which is 1320px at xxl against
     * this 1480px -- a 160px widening of every page. That is a layout change, not token
     * adoption, so it waits for a decision rather than arriving as a side effect.
     */
    --omega-container-max: 1480px;
    --omega-gutter: clamp(1rem, 4vw, 2rem);
    --omega-header-height: 65px;
    /* Unused: the hero height calcs that consume --omega-header-height are outside any
       media query, so they take the desktop value at every width. Wiring the mobile
       number in means adding a breakpoint to those rules, which changes mobile hero
       heights by 3px -- small, but a change, and not one this step is making. */
    --omega-header-height-mobile: 62px;
    --omega-topbar-height: 40px;

    /*
     * The breakpoint tokens that used to live here are gone. They cannot work.
     *
     * Custom properties are not valid in a media query's feature value:
     * @media (max-width: var(--omega-bp-md)) is invalid, the whole query is dropped, and
     * every rule inside it silently never applies. This is not a browser gap -- media
     * conditions are evaluated before custom-property substitution -- and there is no
     * @custom-media support and no build step in this repo to preprocess it.
     *
     * The values did not match the usage either. The 101 media queries here are
     * desktop-first Bootstrap max-widths (767.98px x41, 991.98px x23, 575.98px x19,
     * 1199.98px x18) while the tokens were mobile-first min-width integers, and
     * 768px is not 767.98px.
     *
     * Leaving five tokens that look usable and are not is worse than having none, so
     * this comment is what replaces them.
     */

    /* =====================================================================
     * Legacy aliases.
     *
     * Every name below already existed in style.css and is consumed across the
     * codebase. Each resolves byte-identically to the value it replaced, so
     * this file can land without moving anything — with one exception, marked.
     *
     * These are deleted once every consumer has been migrated to the primitives
     * above. Until then a missed reference keeps working rather than silently
     * falling back to inherit.
     * ================================================================== */

    /*
     * CHANGED, deliberately — WCAG 2.2 AA. Was #69727D, which gives 4.90:1 on
     * white but only 4.49:1 on the mint surface, where a lot of secondary copy
     * actually sits. It passed review because it was only ever checked against
     * white. #626B76 gives 5.42:1 on white and 4.96:1 on mint, so it passes on
     * every surface in the system. This is the one value in this file that
     * moves pixels, and the snapshot diff shows exactly where.
     */

    /*
     * NOT yet pointed at the ramp. The design system replaces peach with
     * coral-50 (#FEF1EB), a visibly lighter tint than today's #FCDDD4. That is
     * a design change, not a token cleanup, so it lands with the section
     * surfaces rather than here.
     */

    /* Legacy elevation — see the note under Elevation above. */
    --omega-shadow-card: 0 12px 30px rgba(14, 43, 86, 0.05);
    --omega-shadow-soft: 0 10px 30px rgba(14, 43, 86, 0.04);
    --omega-shadow-menu: 5px 3px 46px rgba(0, 0, 0, 0.07);
}

@media (prefers-reduced-motion: reduce) {
    :root {
        --omega-duration-fast: 1ms;
        --omega-duration-base: 1ms;
        --omega-duration-slow: 1ms;
        --omega-duration-entrance: 1ms;
    }
}
