/**
 * THEME TOKENS - Single source of truth for the visual language
 * =============================================================
 *
 * Everything the site looks like is decided here: palette, surfaces, glass,
 * borders, radii, spacing, type and motion. Component stylesheets consume these
 * and should not invent their own values.
 *
 * WHY THIS FILE EXISTS
 * --------------------
 * The theme had drifted into nine near-identical mauves, ten panel backgrounds,
 * five backdrop-filter recipes and six border radii, so no two panels on a page
 * looked like they belonged to the same design. Sixteen hundred !important
 * declarations across forty-six stylesheets were the symptom, not the cause.
 *
 * NAMING
 * ------
 * The `--re-` prefix was already established by theme-color-fix.css; this file
 * keeps it and extends it rather than introducing a competing scheme.
 *
 * ONE IMPORTANT NOTE ON CONTRAST
 * ------------------------------
 * The page background is a dark purple gradient in BOTH themes - the light
 * theme changes panels and accents, not the ground. Foreground colours are
 * therefore light in both themes. This is deliberate; it is what makes the
 * reactive particle background readable.
 *
 * Load order: immediately after Bootstrap, before every component stylesheet.
 */

:root {
    /* ============================================================
       BRAND RAMP
       One ordered scale replacing #826b7d / #5d4b60 / #9b7b8e /
       #6e5771 / #4a3a4d / #c9a0dc / #ba9ebb / #a088a0 / #9d8098 /
       #e5dbe5, which were being used interchangeably.
       ============================================================ */
    --re-brand-900: #221a27;
    --re-brand-800: #2f2434;
    --re-brand-700: #4a3a4d;
    --re-brand-600: #5d4b60;   /* primary fills, buttons */
    --re-brand-500: #6e5771;   /* primary hover */
    --re-brand-400: #826b7d;   /* the signature mauve - accents, icons, rules */
    --re-brand-300: #9d8098;
    --re-brand-200: #ba9ebb;   /* bright accent on dark ground */
    --re-brand-100: #d8c8d6;
    --re-brand-050: #ede6ec;

    /* Raw channels, for building rgba() without hardcoding the hex again. */
    --re-brand-400-rgb: 130, 107, 125;
    --re-brand-600-rgb: 93, 75, 96;
    --re-ink-rgb: 20, 15, 22;

    /* ============================================================
       TEXT
       --bs-body-bg used to be used as a text colour in 567 places.
       It is the PAGE BACKGROUND variable, so it inverted with the
       theme and made half the site invisible in dark mode. These
       are the replacements.
       ============================================================ */
    --re-text-color:   rgba(245, 240, 244, 0.92);
    --re-text-muted:   rgba(245, 240, 244, 0.66);
    --re-text-subtle:  rgba(245, 240, 244, 0.46);
    --re-heading-color: #ffffff;
    --re-accent-color: var(--re-brand-200);

    --re-admin-text:       var(--re-text-color);
    --re-admin-text-muted: var(--re-text-muted);

    /* ============================================================
       SURFACES
       Three steps, not ten. Panels sit on the reactive background,
       so they are tinted darkness rather than opaque boxes.
       ============================================================ */
    --re-surface-sunken: rgba(8, 5, 10, 0.50);                    /* inputs, wells, tags   */
    /*
     * The default panel, and the one token that was still plum.
     *
     * --re-ink-rgb is a fixed near-black purple from before palettes existed,
     * so every panel on the site - the navbar, the header strip, cards, the
     * glass everywhere - kept a warm cast no matter which palette was on. It
     * is subtle at 55% opacity and invisible under Mauve, which is exactly
     * why it survived: it only shows up once the site can be grey or green.
     *
     * Derived from the palette's darkest step instead, same as the ground
     * gradient and the player bar, so all three agree. rgba first as the
     * fallback for browsers without color-mix.
     */
    --re-surface:        rgba(var(--re-ink-rgb), 0.55);           /* the default panel     */
    --re-surface:        color-mix(in srgb, var(--re-brand-900) 55%, transparent);
    /*
     * Declared twice on purpose. The rgba() line is the fallback; the
     * color-mix() line says the same thing but derives from --re-brand-400
     * itself rather than from a list of raw channels, which is what lets it
     * CROSSFADE when a palette changes. A registered custom property can be
     * interpolated; "130, 107, 125" cannot. Browsers without color-mix keep
     * the first declaration and simply snap instead.
     * See assets/css/theme-palettes.css.
     */
    --re-surface-raised: rgba(var(--re-brand-400-rgb), 0.10);     /* alternate / accented  */
    --re-surface-raised: color-mix(in srgb, var(--re-brand-400) 10%, transparent);
    --re-surface-hover:  rgba(var(--re-brand-400-rgb), 0.28);
    --re-surface-hover:  color-mix(in srgb, var(--re-brand-400) 28%, transparent);
    --re-surface-active: rgba(var(--re-brand-400-rgb), 0.38);
    --re-surface-active: color-mix(in srgb, var(--re-brand-400) 38%, transparent);

    /* ============================================================
       GLASS
       Two recipes. Previously there were five, plus eight
       components with no backdrop-filter at all sitting in the
       middle of a glass design.
       ============================================================ */
    --re-glass:        blur(16px) saturate(180%) contrast(110%);
    --re-glass-subtle: blur(10px) saturate(150%);
    --re-noise-opacity: 0.06;

    /* ============================================================
       BORDERS & EDGES
       ============================================================ */
    /* Same pairing as the surfaces above, for the same reason. */
    --re-border:        rgba(var(--re-brand-400-rgb), 0.28);
    --re-border:        color-mix(in srgb, var(--re-brand-400) 28%, transparent);
    --re-border-strong: rgba(var(--re-brand-400-rgb), 0.50);
    --re-border-strong: color-mix(in srgb, var(--re-brand-400) 50%, transparent);
    --re-border-faint:  rgba(var(--re-brand-400-rgb), 0.16);
    --re-border-faint:  color-mix(in srgb, var(--re-brand-400) 16%, transparent);
    --re-rim:           inset 0 1px 0 0 rgba(255, 255, 255, 0.14);

    /* ============================================================
       ELEVATION
       ============================================================ */
    --re-shadow-1: 0 4px 16px rgba(0, 0, 0, 0.35), var(--re-rim);
    --re-shadow-2: 0 10px 32px rgba(0, 0, 0, 0.45), var(--re-rim);
    --re-shadow-hover: 0 14px 40px rgba(0, 0, 0, 0.50),
                       inset 0 1px 0 0 rgba(255, 255, 255, 0.22);

    /* ============================================================
       RADII

       One scale, five steps. Everything else in the codebase - 0.25rem, 1px,
       2px, 3px, 4px, 5px, 8px, 12px, 15%, 16px, 20px, 24px, 40px - has been
       mapped onto it. 50% is kept only where a shape is genuinely circular
       (avatars, icon buttons); vendor stylesheets are left alone.
       ============================================================ */
    --re-radius-xs: 3px;    /* hairline: progress tracks, meters, rules */
    --re-radius-sm: 6px;    /* tags, chips, small controls  */
    --re-radius-md: 10px;   /* buttons, inputs, chrome bars */
    --re-radius-lg: 14px;   /* panels, cards, containers    */
    --re-radius-pill: 999px;

    /* ============================================================
       SPACING - a 4px rhythm
       ============================================================ */
    --re-space-1: 4px;
    --re-space-2: 8px;
    --re-space-3: 12px;
    --re-space-4: 16px;
    --re-space-5: 24px;
    --re-space-6: 32px;
    --re-space-7: 48px;

    /* ============================================================
       TYPE
       Three faces, three jobs:
         display - ThaleahFat, the retro pixel identity. Headings.
         ui      - Silkscreen, 8px uppercase. Chrome, labels, meta.
         body    - Albert Sans. Everything you actually read.
       Albert Sans was named in hundreds of rules but never loaded;
       templates/header.php now pulls it from Google Fonts.
       ============================================================ */
    --re-font-display: 'ThaleahFat', 'Albert Sans', 'Noto Sans JP', sans-serif;
    --re-font-ui:      'Silkscreen', 'Courier New', monospace;
    --re-font-body:    'Albert Sans', 'Noto Sans JP', system-ui, sans-serif;

    --re-size-ui:   8px;      /* the Silkscreen chrome size, site-wide */
    --re-size-xs:   0.78rem;
    --re-size-sm:   0.875rem;
    --re-size-base: 1rem;
    --re-size-lg:   1.25rem;
    --re-size-xl:   1.75rem;
    --re-size-2xl:  2.25rem;
    --re-size-3xl:  3rem;

    --re-tracking-ui: 1px;
    --re-leading-body: 1.7;

    /* ============================================================
       MOTION
       ============================================================ */
    --re-transition: 0.25s ease;
    --re-transition-slow: 0.4s ease;
    --re-lift: translateY(-2px);

    /* ============================================================
       GROUND
       The static gradient the reactive particle layer sits on.
       Kept dark in both themes so the particles stay visible; the
       light theme lifts it rather than inverting it.
       ============================================================ */
    /* ============================================================
       HAIRLINE
       The rules and dividers: section heads, list rows, card edges,
       the footer columns. It lived on `.home` and everything else
       used the literal fallback, which is why every line on every
       other page stayed plum while the palette changed around it.
       ============================================================ */
    --home-rule: rgba(130, 107, 125, 0.22);
    --home-rule: color-mix(in srgb, var(--re-brand-400) 22%, transparent);
    --page-rule: var(--home-rule);

    --re-ground-inner: var(--re-brand-700);
    --re-ground-outer: var(--re-brand-900);
}

/* ================================================================
   LIGHT THEME

   The ground stays dark (see the note at the top), so only the
   panel tints, accent and edges shift - panels lighten and warm
   slightly so the light theme reads as a different mood rather
   than a different site.
   ================================================================ */

[data-bs-theme="light"] {
    /* A lifted, misty version of the same design - frosted white glass on a
       lighter plum ground - rather than a second, unrelated look. The previous
       light theme turned some panels white and left others dark, which is what
       made the two modes feel like different sites. */
    --re-ground-inner: var(--re-brand-500);
    --re-ground-outer: var(--re-brand-800);

    --re-surface-sunken: rgba(34, 26, 39, 0.32);
    --re-surface:        rgba(255, 255, 255, 0.13);
    --re-surface-raised: rgba(255, 255, 255, 0.22);
    --re-surface-hover:  rgba(255, 255, 255, 0.26);
    --re-surface-active: rgba(255, 255, 255, 0.34);

    --re-border:        rgba(255, 255, 255, 0.30);
    --re-border-strong: rgba(255, 255, 255, 0.50);
    --re-border-faint:  rgba(255, 255, 255, 0.18);

    --re-shadow-1: 0 4px 16px rgba(34, 26, 39, 0.28),
                   inset 0 1px 0 0 rgba(255, 255, 255, 0.34);
    --re-shadow-2: 0 10px 32px rgba(34, 26, 39, 0.34),
                   inset 0 1px 0 0 rgba(255, 255, 255, 0.34);

    --re-accent-color: var(--re-brand-050);
}

/* ================================================================
   BOOTSTRAP BRIDGE

   Bootstrap components read --bs-* variables. Point the ones that
   matter at the brand ramp so buttons, links, badges and focus
   rings inherit the theme instead of shipping Bootstrap blue and
   needing a 400-line override file to undo it.

   --bs-body-bg is deliberately NOT redefined here: it is a real
   background variable that Bootstrap uses for cards, modals,
   dropdowns and form controls. The 567 places that misused it as a
   text colour were corrected at the source instead.
   ================================================================ */

:root,
[data-bs-theme="dark"],
[data-bs-theme="light"] {
    --bs-primary: var(--re-brand-600);
    --bs-primary-rgb: var(--re-brand-600-rgb);
    --bs-secondary: var(--re-brand-400);

    --bs-link-color: var(--re-brand-400);
    --bs-link-hover-color: var(--re-brand-200);
    --bs-link-color-rgb: var(--re-brand-400-rgb);

    --bs-border-color: var(--re-border);
    --bs-emphasis-color: var(--re-heading-color);
    --bs-secondary-color: var(--re-text-muted);
    --bs-heading-color: var(--re-heading-color);

    --bs-focus-ring-color: rgba(var(--re-brand-400-rgb), 0.45);
    --bs-focus-ring-width: 2px;
}

/* ================================================================
   SHARED PRIMITIVES

   The glass panel treatment is one recipe applied through a single
   class so panels cannot drift apart again. Component stylesheets
   compose with this rather than re-declaring blur + noise + rim.
   ================================================================ */

.re-panel,
.re-panel-raised,
.re-panel-sunken {
    position: relative;
    border-radius: var(--re-radius-lg);
    border: 1px solid var(--re-border);
    backdrop-filter: var(--re-glass);
    -webkit-backdrop-filter: var(--re-glass);
    box-shadow: var(--re-shadow-1);
    color: var(--re-text-color);
}

.re-panel        { background: var(--re-surface); }
.re-panel-raised { background: var(--re-surface-raised); box-shadow: var(--re-shadow-2); }
.re-panel-sunken { background: var(--re-surface-sunken); box-shadow: none; }

/* Fine noise, so glass reads as a material rather than a flat tint. */
.re-noise::before {
    content: '';
    position: absolute;
    inset: 0;
    border-radius: inherit;
    pointer-events: none;
    z-index: 0;
    opacity: var(--re-noise-opacity);
    background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 400 400' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='reNoise'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='4.5' numOctaves='5' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23reNoise)'/%3E%3C/svg%3E");
}

/* Content has to clear the noise layer. */
.re-noise > * {
    position: relative;
    z-index: 1;
}

/* One focus treatment for the whole site. */
.re-focusable:focus-visible,
a:focus-visible,
button:focus-visible,
[role="button"]:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
    outline: 2px solid var(--re-brand-200);
    outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
    :root {
        --re-transition: 0s;
        --re-transition-slow: 0s;
        --re-lift: none;
    }
}
