/**
 * Palette crossfade.
 * ==================
 *
 * A custom property normally cannot be animated. `--re-brand-400: #826b7d`
 * is just a token as far as the browser is concerned - a string it pastes
 * wherever the variable is used - so changing it repaints instantly and the
 * whole site snaps from one palette to the next.
 *
 * @property is what changes that. Registering a property with a `<color>`
 * syntax tells the browser it really is a colour, and a registered property
 * can be interpolated like any other animatable value. Once the ramp is
 * registered, one transition on :root crossfades every single thing that
 * derives from it - the ground gradient, panels, borders, accents, rules,
 * links - without any of them knowing a palette changed.
 *
 * The initial-value on each is Slate, the site's default palette. A browser
 * that has not been given one - no cookie, or the inline block in the head
 * missing - still gets the colours the site is supposed to wear, rather
 * than the mauve that now belongs to the Super Nintendo.
 *
 * Unregistered browsers (anything without @property) ignore these blocks
 * entirely and simply snap between palettes instead of fading. Nothing
 * breaks; the change just arrives all at once.
 */

@property --re-brand-900 { syntax: '<color>'; inherits: true; initial-value: #1c2025; }
@property --re-brand-800 { syntax: '<color>'; inherits: true; initial-value: #262c32; }
@property --re-brand-700 { syntax: '<color>'; inherits: true; initial-value: #3d444a; }
@property --re-brand-600 { syntax: '<color>'; inherits: true; initial-value: #4e555d; }
@property --re-brand-500 { syntax: '<color>'; inherits: true; initial-value: #5b646d; }
@property --re-brand-400 { syntax: '<color>'; inherits: true; initial-value: #6f777f; }
@property --re-brand-300 { syntax: '<color>'; inherits: true; initial-value: #848f99; }
@property --re-brand-200 { syntax: '<color>'; inherits: true; initial-value: #a2acb7; }
@property --re-brand-100 { syntax: '<color>'; inherits: true; initial-value: #cad0d6; }
@property --re-brand-050 { syntax: '<color>'; inherits: true; initial-value: #e7eaec; }

/* The one colour that is not on the ramp: the bright dot in the particle
   field. Registered too, so the canvas can read a fading value rather than a
   stepped one. */
@property --re-particle-pop { syntax: '<color>'; inherits: true; initial-value: #848bb8; }

/* ------------------------------------------------------------------ *
 * The fade itself
 * ------------------------------------------------------------------ */

:root {
    /*
     * One place to change how long a palette takes to arrive. The particle
     * canvas reads this same number out of the computed style so the
     * background and the page finish together rather than drifting apart -
     * see the palette tween in particle-network-interactive.js.
     */
    --re-palette-fade: 900ms;

    transition:
        --re-brand-900 var(--re-palette-fade) ease,
        --re-brand-800 var(--re-palette-fade) ease,
        --re-brand-700 var(--re-palette-fade) ease,
        --re-brand-600 var(--re-palette-fade) ease,
        --re-brand-500 var(--re-palette-fade) ease,
        --re-brand-400 var(--re-palette-fade) ease,
        --re-brand-300 var(--re-palette-fade) ease,
        --re-brand-200 var(--re-palette-fade) ease,
        --re-brand-100 var(--re-palette-fade) ease,
        --re-brand-050 var(--re-palette-fade) ease,
        --re-particle-pop var(--re-palette-fade) ease;
}

/*
 * The ground is painted on <body>, and it is a gradient rather than a flat
 * colour, so it does not inherit the interpolation for free - a gradient is
 * repainted from whatever the variables currently hold. That happens to be
 * exactly what we want: because the variables are themselves mid-transition,
 * the gradient is redrawn every frame with the interpolated values and the
 * ground fades along with everything else.
 */

@media (prefers-reduced-motion: reduce) {
    :root {
        --re-palette-fade: 1ms;
    }
}

/* ------------------------------------------------------------------ *
 * The picker
 * ------------------------------------------------------------------ */

/*
 * Fifteen palettes is taller than a short viewport, so the menu has to
 * scroll - and getting it to was not a one-liner.
 *
 * header-controls-panel.css sets `overflow: hidden !important` on the
 * portaled menu, which is right for the language picker it was written for:
 * five items, no scrolling, and the clip keeps the glass inside the rounded
 * corners. At `.dropdown-menu.header-controls-lang-portal` that scores
 * (0,2,0), so a plain `.palette-menu` at (0,1,0) lost even with !important
 * and the list was simply cut off at the bottom with no way to reach the
 * rest.
 *
 * Matching that specificity - and this file loads afterwards - is what makes
 * it scroll. overflow-x stays hidden so the corners still clip.
 */
.dropdown-menu.palette-menu {
    min-width: 196px;
    padding: 6px;
    max-height: min(70vh, 560px);
    overflow-x: hidden !important;
    overflow-y: auto !important;
    overscroll-behavior: contain;
}

/*
 * A visible scrollbar, because the alternative is a list that looks finished
 * when it is not. Thin and in the palette rather than the browser's default
 * slab, which on a dark glass panel reads as a rendering fault.
 */
.dropdown-menu.palette-menu {
    scrollbar-width: thin;
    scrollbar-color: var(--re-brand-400) transparent;
}

.dropdown-menu.palette-menu::-webkit-scrollbar { width: 8px; }
.dropdown-menu.palette-menu::-webkit-scrollbar-track { background: transparent; }

.dropdown-menu.palette-menu::-webkit-scrollbar-thumb {
    background: var(--re-surface-hover);
    border: 2px solid transparent;
    background-clip: content-box;
    border-radius: 8px;
}

.dropdown-menu.palette-menu::-webkit-scrollbar-thumb:hover {
    background: var(--re-brand-400);
    background-clip: content-box;
}

/* The group heading. Not a menu item - it is not clickable and should not
   look like one. */
.palette-group {
    padding: 10px 8px 4px;
    font-family: var(--re-font-ui);
    letter-spacing: 1px;
    text-transform: uppercase;
    color: var(--re-brand-200);
    opacity: 0.6;
}

.palette-group:not(:first-child) {
    margin-top: 4px;
    border-top: 1px solid var(--re-border-faint);
}

.palette-item {
    display: flex;
    align-items: center;
    gap: 9px;
    width: 100%;
    /* 5px rather than 6: fifteen rows, and the two saved pixels each are a
       whole extra palette visible before the list needs scrolling. */
    padding: 5px 8px;
    border: 1px solid transparent;
    border-radius: var(--re-radius-sm);
    background: none;
    color: var(--re-text-color);
    text-align: left;
    cursor: pointer;
    transition: background var(--re-transition), border-color var(--re-transition);
}

.palette-item:hover,
.palette-item:focus-visible {
    background: var(--re-surface-hover);
    border-color: var(--re-border);
}

.palette-item[aria-current="true"] {
    border-color: var(--re-border-strong);
    background: var(--re-surface-raised);
}

/*
 * The swatch is the palette in miniature - its ground, its accent and its
 * bright step - rather than a single dot. Three colours are what actually
 * distinguish two dark themes from each other; one is not enough to tell
 * Indigo from Cobalt.
 */
.palette-swatch {
    flex: 0 0 auto;
    width: 26px;
    height: 14px;
    border-radius: 3px;
    border: 1px solid var(--re-border-faint);
    background: linear-gradient(
        to right,
        var(--sw-ground) 0 34%,
        var(--sw-accent) 34% 67%,
        var(--sw-bright) 67% 100%);
}

.palette-name {
    display: block;
    font-family: var(--re-font-ui);
    line-height: 1.4;
}

.palette-note {
    display: block;
    font-family: var(--re-font-ui);
    opacity: 0.5;
    line-height: 1.4;
}

/* The follow-the-music switch, sitting under the list. */
.palette-follow {
    display: flex;
    align-items: center;
    gap: 8px;
    margin-top: 6px;
    padding: 8px;
    border-top: 1px solid var(--re-border-faint);
    color: var(--re-text-color);
    font-family: var(--re-font-ui);
    cursor: pointer;
}

.palette-follow input {
    accent-color: var(--re-brand-300);
    margin: 0;
}

/*
 * The trigger sits in the header controls strip beside the language picker
 * and is built to match it exactly - see .header-controls-lang-toggle in
 * header-controls-panel.css. The 34px floor is the mobile tap target the
 * rest of that strip uses.
 */
.header-controls-palette-toggle {
    color: var(--header-controls-fg) !important;
    text-decoration: none;
    padding: 6px 10px;
    background: var(--re-surface-raised);
    border: 1px solid var(--re-border);
    border-radius: var(--re-radius-sm);
    display: inline-flex;
    align-items: center;
    gap: 6px;
    transition: all 0.3s ease;
    cursor: pointer;
}

.header-controls-palette-toggle:hover {
    background: var(--re-surface-hover);
    border-color: var(--re-border-strong);
    color: var(--bs-link-hover-color) !important;
}

@media (max-width: 768px) {
    .header-controls-palette-toggle {
        min-height: 34px;
    }
    /* The name is the first thing to go when the row runs out of width; the
       swatch still says which palette is on. */
    .header-controls-palette-toggle .palette-current-name {
        display: none;
    }
}

@media (min-width: 769px) {
    .header-controls-palette-toggle {
        min-height: 28px;
    }
}
