/**
 * Admin theme token generation.
 *
 * The accent color is the one user-facing knob that recolors the admin's
 * primary affordances (active nav, primary buttons, active tabs, focus rings,
 * selected pills). Rather than let users pick arbitrary colors that fail
 * contrast, we ship a curated set of presets — each with vetted light + dark
 * values — and map the chosen preset to the CSS variables the theme already
 * uses (`--brand`, `--primary`, `--sidebar-primary`, `--ring`).
 *
 * `generateAdminThemeTokens` returns a plain map the client applies via
 * `style.setProperty` on `.actuate-admin`, so an accent change repaints without
 * a reload. A custom color is accepted only if it parses AND meets contrast.
 */
import { contrastRatio, isParseableColor } from './color.js';
const WHITE = '#ffffff';
const NEAR_BLACK = 'oklch(0.205 0 0)';
/**
 * Curated accent presets. Light/dark brand values mirror the existing
 * `theme.css` violet so "purple" is a visual no-op; the others are tuned to the
 * same lightness/chroma envelope so they read as text on cards and as solid
 * fills, and pass the >=3:1 UI-contrast bar against their foreground.
 */
export const ACCENT_PRESETS = {
    purple: {
        name: 'purple',
        label: 'Purple',
        swatch: 'oklch(0.54 0.23 293)',
        light: {
            brand: 'oklch(0.54 0.23 293)',
            brandForeground: WHITE,
            primary: 'oklch(0.54 0.23 293)',
            primaryForeground: WHITE,
            sidebarPrimary: 'oklch(0.54 0.23 293)',
            ring: 'oklch(0.54 0.23 293)',
        },
        dark: {
            brand: 'oklch(0.72 0.18 293)',
            brandForeground: NEAR_BLACK,
            primary: 'oklch(0.72 0.18 293)',
            primaryForeground: NEAR_BLACK,
            sidebarPrimary: 'oklch(0.72 0.18 293)',
            ring: 'oklch(0.72 0.18 293)',
        },
    },
    blue: {
        name: 'blue',
        label: 'Blue',
        swatch: 'oklch(0.55 0.2 256)',
        light: {
            brand: 'oklch(0.55 0.2 256)',
            brandForeground: WHITE,
            primary: 'oklch(0.55 0.2 256)',
            primaryForeground: WHITE,
            sidebarPrimary: 'oklch(0.55 0.2 256)',
            ring: 'oklch(0.55 0.2 256)',
        },
        dark: {
            brand: 'oklch(0.72 0.15 256)',
            brandForeground: NEAR_BLACK,
            primary: 'oklch(0.72 0.15 256)',
            primaryForeground: NEAR_BLACK,
            sidebarPrimary: 'oklch(0.72 0.15 256)',
            ring: 'oklch(0.72 0.15 256)',
        },
    },
    teal: {
        name: 'teal',
        label: 'Teal',
        swatch: 'oklch(0.55 0.12 192)',
        light: {
            brand: 'oklch(0.55 0.12 192)',
            brandForeground: WHITE,
            primary: 'oklch(0.55 0.12 192)',
            primaryForeground: WHITE,
            sidebarPrimary: 'oklch(0.55 0.12 192)',
            ring: 'oklch(0.55 0.12 192)',
        },
        dark: {
            brand: 'oklch(0.74 0.11 192)',
            brandForeground: NEAR_BLACK,
            primary: 'oklch(0.74 0.11 192)',
            primaryForeground: NEAR_BLACK,
            sidebarPrimary: 'oklch(0.74 0.11 192)',
            ring: 'oklch(0.74 0.11 192)',
        },
    },
    pink: {
        name: 'pink',
        label: 'Pink',
        swatch: 'oklch(0.56 0.22 354)',
        light: {
            brand: 'oklch(0.56 0.22 354)',
            brandForeground: WHITE,
            primary: 'oklch(0.56 0.22 354)',
            primaryForeground: WHITE,
            sidebarPrimary: 'oklch(0.56 0.22 354)',
            ring: 'oklch(0.56 0.22 354)',
        },
        dark: {
            brand: 'oklch(0.73 0.17 354)',
            brandForeground: NEAR_BLACK,
            primary: 'oklch(0.73 0.17 354)',
            primaryForeground: NEAR_BLACK,
            sidebarPrimary: 'oklch(0.73 0.17 354)',
            ring: 'oklch(0.73 0.17 354)',
        },
    },
    orange: {
        name: 'orange',
        label: 'Orange',
        swatch: 'oklch(0.62 0.2 41)',
        light: {
            brand: 'oklch(0.55 0.18 41)',
            brandForeground: WHITE,
            primary: 'oklch(0.55 0.18 41)',
            primaryForeground: WHITE,
            sidebarPrimary: 'oklch(0.55 0.18 41)',
            ring: 'oklch(0.55 0.18 41)',
        },
        dark: {
            brand: 'oklch(0.75 0.16 56)',
            brandForeground: NEAR_BLACK,
            primary: 'oklch(0.75 0.16 56)',
            primaryForeground: NEAR_BLACK,
            sidebarPrimary: 'oklch(0.75 0.16 56)',
            ring: 'oklch(0.75 0.16 56)',
        },
    },
};
export const ACCENT_PRESET_LIST = Object.values(ACCENT_PRESETS);
/** Minimum WCAG contrast for a primary fill vs its foreground (UI/large text). */
export const MIN_ACCENT_CONTRAST = 3;
export function isAccentPreset(value) {
    return Object.prototype.hasOwnProperty.call(ACCENT_PRESETS, value);
}
/**
 * Validate an accent value. Presets are always valid (pre-vetted). A custom
 * string must parse AND clear {@link MIN_ACCENT_CONTRAST} against white so
 * white text on the primary button stays legible.
 */
export function validateAccentColor(value) {
    if (isAccentPreset(value)) {
        const c = contrastRatio(ACCENT_PRESETS[value].light.brand, WHITE);
        return { valid: true, contrast: c };
    }
    if (!isParseableColor(value)) {
        return { valid: false, contrast: 0, reason: 'Not a valid hex or oklch color.' };
    }
    const contrast = contrastRatio(value, WHITE);
    if (contrast < MIN_ACCENT_CONTRAST) {
        return {
            valid: false,
            contrast,
            reason: `Accent color contrast ${contrast.toFixed(2)}:1 is below the ${MIN_ACCENT_CONTRAST}:1 minimum for white text.`,
        };
    }
    return { valid: true, contrast };
}
/**
 * Resolve the accent tokens for a settings value + resolved color mode.
 * Falls back to the purple preset when the stored value is a custom color
 * (custom colors only set `--brand`/`--primary` directly; we keep purple's
 * foreground/ring envelope). Unknown names fall back to purple.
 */
export function generateAdminThemeTokens(settings, resolvedMode) {
    const accent = settings.adminAccentColor;
    if (isAccentPreset(accent)) {
        return ACCENT_PRESETS[accent][resolvedMode];
    }
    // Custom color: drive brand/primary/sidebar/ring from the raw value, keep a
    // sensible foreground for the mode.
    if (isParseableColor(accent)) {
        const foreground = resolvedMode === 'dark' ? NEAR_BLACK : WHITE;
        return {
            brand: accent,
            brandForeground: foreground,
            primary: accent,
            primaryForeground: foreground,
            sidebarPrimary: accent,
            ring: accent,
        };
    }
    return ACCENT_PRESETS.purple[resolvedMode];
}
/** Map accent tokens to the CSS custom properties the theme consumes. */
export function accentTokensToCssVars(tokens) {
    return {
        '--brand': tokens.brand,
        '--brand-foreground': tokens.brandForeground,
        '--primary': tokens.primary,
        '--primary-foreground': tokens.primaryForeground,
        '--sidebar-primary': tokens.sidebarPrimary,
        '--sidebar-primary-foreground': tokens.primaryForeground,
        '--ring': tokens.ring,
    };
}
//# sourceMappingURL=theme-tokens.js.map