/* ═══════════════════════════════════════════════════════════════════════════════════════════════
   ORPHEUS — DESIGN TOKENS
   The single place where a colour, a size or a duration is decided. Everything else in the
   interface refers to these by ROLE (--o-surface, --o-ink-2) and never by value, which is the
   only reason two themes are affordable: a theme is this file's second block, not a second app.

   Two themes:
     OBSIDIAN (dark, the default) — a temple at Delphi after dark. Black volcanic glass, gold
                                    lit from within, one cold cyan for anything actually alive.
     MARBLE   (light)             — the same temple at noon. Warm stone, bronze-dark gold, and
                                    every glow replaced by a shadow, because a glow on white is
                                    not a dimmer glow: it is nothing at all.

   RULES FOR ADDING A TOKEN
     1. Name it for its JOB (--o-line-strong), never its appearance (--o-light-grey).
     2. Define it in BOTH themes, in the same order, or the light theme silently inherits a
        value tuned for black and looks broken in a way nobody notices until a user says so.
     3. Effects (glow, bloom, glass) are tokens too. They are the parts that do not survive
        translation, so they need a deliberate light-theme answer, usually a shadow.
   ═══════════════════════════════════════════════════════════════════════════════════════════════ */

/* ── The three voices ──────────────────────────────────────────────────────────────────────────
   Self-hosted; see wwwroot/fonts/README.md for why they are never linked from a CDN.
   font-display: swap — text is readable from the first paint in the fallback, then upgrades.  */

@font-face {
    font-family: 'Cinzel';
    font-style: normal;
    font-weight: 400 700;
    font-display: swap;
    src: url('../fonts/cinzel-latin-var.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
                   U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'Space Grotesk';
    font-style: normal;
    font-weight: 300 700;
    font-display: swap;
    src: url('../fonts/spacegrotesk-latin-var.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
                   U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'Chakra Petch';
    font-style: normal;
    font-weight: 500;
    font-display: swap;
    src: url('../fonts/chakrapetch-500-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
                   U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
    font-family: 'Chakra Petch';
    font-style: normal;
    font-weight: 600;
    font-display: swap;
    src: url('../fonts/chakrapetch-600-latin.woff2') format('woff2');
    unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
                   U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ── Scales: the same in both themes ────────────────────────────────────────────────────────── */

:root {
    /* Type. --o-font-data is for NUMBERS ONLY — counts, clocks, the usage ring, badges. Its job
       is to look like the readout on a piece of equipment, and it stops doing that the moment it
       is used for a sentence. */
    --o-font-display: 'Cinzel', 'Times New Roman', Georgia, serif;
    --o-font-ui: 'Space Grotesk', ui-sans-serif, 'Segoe UI', system-ui, -apple-system, sans-serif;
    --o-font-data: 'Chakra Petch', ui-monospace, 'Cascadia Mono', Consolas, monospace;

    /* A 1.2 modular scale from 1rem, rounded to something a person would type. */
    --o-text-2xs: .6875rem;  /*  11px — ring labels, the smallest legal print */
    --o-text-xs:  .75rem;    /*  12px — table captions, meta */
    --o-text-sm:  .8125rem;  /*  13px — secondary text, help */
    --o-text-md:  .9375rem;  /*  15px — body. 15 not 16: the interface is dense */
    --o-text-lg:  1.0625rem; /*  17px — lead paragraphs */
    --o-text-xl:  1.375rem;  /*  22px — card titles */
    --o-text-2xl: 1.75rem;   /*  28px — page titles */
    --o-text-3xl: 2.5rem;    /*  40px — the landing headline */
    --o-text-4xl: 3.75rem;   /*  60px — the landing headline, wide screens */

    --o-tracking-label: .14em;  /* gold small-caps labels read as INSCRIPTION at this tracking */
    --o-tracking-tight: -.015em;

    /* Space — a 4px grid, because every border, gap and inset in the app lands on one. */
    --o-s-1: .25rem;
    --o-s-2: .5rem;
    --o-s-3: .75rem;
    --o-s-4: 1rem;
    --o-s-5: 1.5rem;
    --o-s-6: 2rem;
    --o-s-7: 3rem;
    --o-s-8: 4rem;

    --o-r-xs: 4px;
    --o-r-sm: 7px;
    --o-r: 11px;
    --o-r-lg: 18px;
    --o-r-pill: 999px;

    /* Motion. One ramp for everything that enters (ease-out, decelerating, feels physical) and
       one for state changes. Durations are referenced, never typed, so "calm the whole app down"
       is an edit to four numbers. motion.css zeroes all four under prefers-reduced-motion. */
    --o-t-instant: 90ms;
    --o-t-fast: 150ms;
    --o-t-base: 240ms;
    --o-t-slow: 460ms;
    --o-t-ambient: 40s;          /* the drifting constellation; deliberately far below notice */

    --o-ease: cubic-bezier(.4, 0, .2, 1);
    --o-ease-out: cubic-bezier(.16, 1, .3, 1);   /* overshoot-free settle; the "enter" curve */
    --o-ease-in: cubic-bezier(.55, 0, 1, .45);

    --o-rail: 264px;             /* the navigation rail's width, referenced by the layout and the
                                    backdrop, which has to know where the content starts */
    --o-measure: 68ch;           /* the longest a line of prose is allowed to get */

    --o-z-backdrop: 0;
    --o-z-content: 1;
    --o-z-rail: 20;
    --o-z-overlay: 60;
    --o-z-toast: 80;
}

/* ═══ OBSIDIAN (dark) ══════════════════════════════════════════════════════════════════════════
   Also the :root fallback, so a page that somehow renders before the theme attribute is set is
   dark rather than unstyled-white. Contrast figures in the comments are measured against
   --o-bg and are WCAG 2.1 ratios. */

:root,
[data-bs-theme='dark'] {
    color-scheme: dark;

    /* Grounds, deepest first. The page is --o-bg; things sit ON it in --o-surface. */
    --o-void: #06050A;
    --o-bg: #0A0910;
    --o-bg-raised: #100E18;
    --o-surface: rgba(255, 255, 255, .035);
    --o-surface-2: rgba(255, 255, 255, .06);
    --o-surface-solid: #14121D;
    --o-inset: rgba(0, 0, 0, .35);

    /* Lines. --o-line is structure you should not notice; --o-line-strong is a real division. */
    --o-line: rgba(232, 180, 74, .13);
    --o-line-soft: rgba(255, 255, 255, .07);
    --o-line-strong: rgba(232, 180, 74, .30);

    /* Ink.  ink   17.0:1 — body and headings
             ink-2  7.7:1 — secondary text, still AA at any size
             ink-3  5.1:1 — meta and captions, AA at any size
       There is deliberately no fourth, dimmer step: everything below this is decoration, and
       decoration uses --o-line, not a text colour that some users cannot read. */
    --o-ink: #EDE9F2;
    --o-ink-2: #A39FB0;
    --o-ink-3: #837F94;

    /* Gold — Apollo's metal, and the only brand colour. 10.4:1 as text on --o-bg. */
    --o-gold: #E8B44A;
    --o-gold-soft: #F5D98B;
    --o-gold-deep: #B88A2A;
    --o-gold-ink: #E8B44A;        /* gold used as TEXT; darkens in Marble where gold-on-white fails */
    --o-on-gold: #17120A;         /* what sits on a gold fill — near-black, 9.6:1 on --o-gold */
    --o-gold-wash: rgba(232, 180, 74, .10);
    --o-gold-wash-2: rgba(232, 180, 74, .18);

    /* Gold as a gradient across LIVE TEXT (the wordmark, the gilded half of the headline), via
       background-clip. It needs its own token rather than being built inline from the three gold
       values, because Marble cannot simply swap those: a gradient whose lightest stop is
       --o-gold-soft puts #F0CE7E on cream, which is 1.3:1 and simply not there. */
    --o-gilt: linear-gradient(115deg, var(--o-gold-soft), var(--o-gold) 46%, var(--o-gold-deep));

    /* Status. Warning is ORANGE, not amber: an amber warning beside a gold primary is two
       shades of the same idea, and a person reads them as one. */
    --o-accent: #3FE0D0;          /* cyan — reserved for LIVE: running, connected, counting */
    --o-accent-ink: #3FE0D0;
    --o-success: #34E5A0;
    --o-success-ink: #34E5A0;
    --o-danger: #FF4D5E;
    --o-danger-ink: #FF6B79;
    --o-warning: #FF8A3D;
    --o-warning-ink: #FFA76B;

    /* Effects that do NOT translate between themes — each needs a real Marble answer below. */
    --o-glow-gold: 0 0 24px rgba(232, 180, 74, .30), 0 0 2px rgba(232, 180, 74, .55);
    --o-glow-accent: 0 0 22px rgba(63, 224, 208, .35), 0 0 2px rgba(63, 224, 208, .6);
    --o-glow-inset: inset 0 1px 0 rgba(255, 255, 255, .06);
    --o-shadow-sm: 0 1px 2px rgba(0, 0, 0, .55);
    --o-shadow: 0 8px 28px -10px rgba(0, 0, 0, .8), 0 1px 0 rgba(255, 255, 255, .04) inset;
    --o-shadow-lg: 0 28px 70px -24px rgba(0, 0, 0, .9), 0 1px 0 rgba(255, 255, 255, .05) inset;
    --o-bloom: .55;               /* master opacity for every ambient glow layer */
    --o-glass-blur: 14px;

    /* The meander (Greek key) rule, and the star field. Both are drawn from these two values so
       one edit re-tunes every instance. */
    /* The Spotify usage gauge's four bands (UsageGauges decides which one is in force). They are
       a ring stroke, not text, so the bar is WCAG's 3:1 for non-text — but the yellow still needs
       its own value per theme, because #EAB308 on Marble's cream is 1.75:1 and vanishes. There is
       no gold here on purpose: gold is the brand, and a gauge that turns brand-coloured at half
       full says "good" to everyone who has learned what gold means everywhere else in the app. */
    --o-band-ok: var(--o-success);
    --o-band-half: #EAB308;
    --o-band-most: var(--o-warning);
    --o-band-full: var(--o-danger);

    --o-meander: rgba(232, 180, 74, .38);
    --o-meander-emboss: transparent;   /* engraving is a Marble idea; in the dark it just glows */
    --o-star: rgba(245, 217, 139, .85);
    --o-star-dim: rgba(163, 159, 176, .45);
    --o-vega: #FFF6DE;                 /* Lyra's brightest star, and the hero's focal point */
}

/* ═══ MARBLE (light) ═══════════════════════════════════════════════════════════════════════════
   Not an inversion. Gold at #E8B44A on white is 1.9:1 — illegible — so gold as TEXT becomes
   bronze (--o-gold-ink, 4.8:1) while gold as a SURFACE stays bright metal with near-black on it,
   exactly like a brass plate. Glows become shadows. The meander stops glowing and starts being
   engraved: a dark line with a light one beneath it. */

[data-bs-theme='light'] {
    color-scheme: light;

    --o-void: #EDE8DD;
    --o-bg: #F7F4EE;
    --o-bg-raised: #FFFDF8;
    --o-surface: rgba(255, 253, 248, .75);
    --o-surface-2: rgba(138, 101, 18, .05);
    --o-surface-solid: #FFFDF8;
    --o-inset: rgba(122, 90, 22, .06);

    --o-line: rgba(122, 90, 22, .18);
    --o-line-soft: rgba(26, 20, 8, .09);
    --o-line-strong: rgba(122, 90, 22, .42);

    /* ink 13.9:1 · ink-2 6.1:1 · ink-3 4.6:1 on --o-bg */
    --o-ink: #1E1A14;
    --o-ink-2: #5C5548;
    --o-ink-3: #7A7264;

    --o-gold: #D9A03A;            /* the metal, for fills */
    --o-gold-soft: #F0CE7E;
    --o-gold-deep: #8A6512;
    --o-gold-ink: #8A6512;        /* 4.8:1 — gold-as-text has to be bronze here */
    --o-on-gold: #17120A;
    --o-gold-wash: rgba(184, 138, 42, .10);
    --o-gold-wash-2: rgba(184, 138, 42, .20);

    /* Bronze end to end, and the whole ramp kept dark enough to read on cream: the lightest stop
       measures 3.5:1, which is the AA threshold for large text, and the gilt is only ever used on
       the headline and the wordmark — both well past 18.66px bold. */
    --o-gilt: linear-gradient(115deg, #9C6F14, #8A6512 46%, #6B4E0F);

    --o-accent: #0E9E92;
    --o-accent-ink: #0A7A70;      /* 4.6:1 */
    --o-success: #0F9D63;
    --o-success-ink: #0B7A4C;
    --o-danger: #D92D3E;
    --o-danger-ink: #B8202F;
    --o-warning: #C25A0B;
    --o-warning-ink: #9C4708;

    /* No glow survives a light ground. Every one becomes a shadow with the same NAME, so no
       component has to know which theme it is in. */
    --o-glow-gold: 0 6px 18px -6px rgba(184, 138, 42, .45);
    --o-glow-accent: 0 6px 18px -6px rgba(14, 158, 146, .40);
    --o-glow-inset: inset 0 1px 0 rgba(255, 255, 255, .9);
    --o-shadow-sm: 0 1px 2px rgba(60, 46, 16, .12);
    --o-shadow: 0 10px 26px -14px rgba(60, 46, 16, .35), 0 1px 0 rgba(255, 255, 255, .8) inset;
    --o-shadow-lg: 0 30px 64px -28px rgba(60, 46, 16, .42), 0 1px 0 rgba(255, 255, 255, .9) inset;
    --o-bloom: .22;
    --o-glass-blur: 10px;

    /* 4.5:1 on cream, where the Obsidian yellow measures 1.75:1 and disappears. */
    --o-band-ok: var(--o-success);
    --o-band-half: #A16207;
    --o-band-most: var(--o-warning);
    --o-band-full: var(--o-danger);

    --o-meander: rgba(122, 90, 22, .55);
    --o-meander-emboss: rgba(255, 255, 255, .85);   /* the highlight that makes it look carved */
    --o-star: rgba(122, 90, 22, .55);
    --o-star-dim: rgba(122, 90, 22, .22);
    --o-vega: #8A6512;
}
