/* The theme layer: the neutral default, and the tiers a brand overrides.
 *
 * Load order matters and is deliberate. index.html loads Bootstrap FIRST, then
 * this sheet, then default.css and forms.css. Before that fix Bootstrap loaded
 * last and quietly beat forms.css at equal specificity, which is why so many
 * rules there carried !important. Anything added here can assume it outranks
 * Bootstrap on source order alone — do not reintroduce !important to win a
 * fight the load order already settles, because a brand's custom_css then has
 * to escalate too and customisation gets harder the more we use it.
 *
 * THREE TIERS
 *
 *   Tier 1  primitives   The raw values a brand picks: one brand colour, a
 *                        neutral ramp, a radius, a spacing step, a font.
 *                        Defined below. Together they ARE the default theme.
 *   Tier 2  roles        What a value MEANS on a page: accent, surface, ink,
 *                        line, focus. Derived from tier 1.
 *   Tier 3  components   The ~46 --bg-* names that already existed. Each one
 *                        now falls back through tier 2 instead of to a
 *                        hardcoded hex, and still wins when it is set.
 *
 * The tiers are additive, not a migration. Every tier-3 name keeps working
 * exactly as before, so a brand themed against the old flat set renders
 * identically until it opts into the primitives — the tier-1 defaults here are
 * the values those fallbacks already used. A brand that sets only --bg-brand
 * gets buttons, links, pills, toggles and focus rings in one coherent colour.
 */

:root {
	color-scheme: light;

	/* ---------------------------------------------------------------- *
	 * Tier 1 — primitives. A brand theme is mostly just these.
	 * ---------------------------------------------------------------- */

	/* The one colour most brands actually care about. Default is Bootstrap's
	 * blue, so an unthemed page is unchanged. */
	--bg-brand: #0d6efd;
	/* Literal fallbacks for browsers without color-mix; the @supports block
	 * below derives both from --bg-brand so a brand that sets only the one
	 * colour gets hover and pressed states in it rather than in Bootstrap
	 * blue. These two values ARE the derivation applied to the default, so
	 * nothing moves on an unthemed page either way. */
	--bg-brand-hover: #0b5ed7;
	--bg-brand-active: #0a58ca;
	/* Text placed ON the brand colour, so it must contrast with it. */
	--bg-on-brand: #fff;

	/* Neutrals: the page behind everything, the cards on top of it, the text,
	 * and the lines between. Contrast-corrected values, not the historical
	 * greys — those failed WCAG for every brand, themed or not. */
	--bg-canvas: #f8f9fa;
	--bg-surface: #fff;
	--bg-ink: #212529;
	--bg-ink-muted: #6b6265;
	--bg-line: #8f8f8f;
	--bg-line-subtle: #dee2e6;

	/* Shape and rhythm. --bg-radius is the card corner; --bg-radius-control is
	 * the smaller one on buttons and inputs, which reads wrong when it simply
	 * inherits a card's radius. */
	--bg-radius: 5px;
	--bg-radius-control: 0.375rem;
	--bg-space: 25px;
	--bg-shadow: 0 0 10px rgba(0, 0, 0, 0.1);

	/* Typography. --bg-font-url is handled in page-content.ts, not here: a
	 * font has to be fetched before it can be named. */
	--bg-font-body: "Roboto", Arial, Helvetica, sans-serif;
	--bg-font-heading: var(--bg-font-body);

	/* How wide the page is allowed to get. Previously hardcoded in App.vue. */
	--bg-page-max-width: 1024px;

	/* Star ratings keep their own primitive rather than following the accent.
	 * Gold stars are a cross-brand convention and were the previous default,
	 * so following the brand colour here would restyle every existing page.
	 * A brand that wants brand-coloured stars sets --bg-rating to its colour. */
	--bg-rating: #f39c12;

	/* ---------------------------------------------------------------- *
	 * Tier 2 — roles. Derived; a brand can still override any of them.
	 * ---------------------------------------------------------------- */

	--bg-accent: var(--bg-brand);
	--bg-accent-hover: var(--bg-brand-hover);
	--bg-accent-active: var(--bg-brand-active);
	--bg-on-accent: var(--bg-on-brand);

	/* Focus visibility is an accessibility floor, not decoration: it is derived
	 * from the accent so it stays visible on a themed page, and the width is a
	 * token so a brand can thicken it but not silently remove it. */
	--bg-focus-width: 0.25rem;
	--bg-focus-ring: rgba(13, 110, 253, 0.25);

	/* A quiet wash of the accent, for a selected pill or a subtle fill. */
	--bg-accent-subtle: #b3cce8;
}

/* color-mix lets the two derived accents track a brand colour instead of
 * sitting at their blue defaults. Guarded because these pages are public and
 * reached from email clients' in-app browsers, where an unsupported function
 * would drop the declaration and leave a focus ring that never appears. */
@supports (color: color-mix(in srgb, red, blue)) {
	:root {
		/* Bootstrap's own shade steps — 15% toward black for hover, 20% for
		 * pressed — so these reproduce #0b5ed7 and #0a58ca exactly when the
		 * brand colour is the default. A brand that wants different states
		 * still sets the tokens: css_vars are written as inline style on
		 * <html>, which outranks any rule here. Note that --bg-on-brand is
		 * deliberately NOT derived: which of black or white reads on an
		 * arbitrary brand colour is a contrast decision, not a mix. */
		--bg-brand-hover: color-mix(in srgb, var(--bg-brand) 85%, black);
		--bg-brand-active: color-mix(in srgb, var(--bg-brand) 80%, black);

		--bg-focus-ring: color-mix(in srgb, var(--bg-accent) 25%, transparent);
		--bg-accent-subtle: color-mix(in srgb, var(--bg-accent) 30%, white);
	}
}

/* Dark themes.
 *
 * Set by page-content.ts from the brand's colour_scheme, as data-bs-theme on
 * <html> so Bootstrap's own dark styles switch with ours rather than against
 * them. Only the neutrals move: the brand colour is the brand colour in either
 * scheme, and a brand that needs a different accent in the dark sets one.
 */
[data-bs-theme="dark"] {
	color-scheme: dark;

	--bg-canvas: #121417;
	--bg-surface: #1c1f23;
	--bg-ink: #e9ecef;
	--bg-ink-muted: #adb5bd;
	--bg-line: #6c757d;
	--bg-line-subtle: #343a40;
	--bg-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
}

@supports (color: color-mix(in srgb, red, blue)) {
	[data-bs-theme="dark"] {
		/* Mixing toward white on a dark page produces a wash that glares. */
		--bg-accent-subtle: color-mix(in srgb, var(--bg-accent) 30%, black);
	}
}

/* -------------------------------------------------------------------- *
 * Bootstrap mapping.
 *
 * Bootstrap 5.3 builds its components from --bs-* custom properties, but
 * setting --bs-primary at :root does NOT repaint them: that variable is
 * published for reuse, and the components compile their colours from Sass.
 * Rebuilding Sass per brand is not available to us at runtime, so the
 * supported path is this one — map brand tokens onto the --bs-* properties
 * the components genuinely read.
 *
 * These are the root-level ones, which reach Bootstrap's own components
 * (inputs, alerts, cards, shadows, tables) for free. Component-level maps
 * that need a selector live with their component in default.css/forms.css.
 * -------------------------------------------------------------------- */
:root {
	--bs-body-bg: var(--bg-page-background, var(--bg-canvas));
	--bs-body-color: var(--bg-page-text, var(--bg-ink));
	--bs-body-font-family: var(--bg-page-font-family, var(--bg-font-body));

	--bs-border-color: var(--bg-surface-border, var(--bg-line-subtle));
	--bs-border-radius: var(--bg-radius-control);
	--bs-box-shadow: var(--bg-shadow);

	--bs-link-color: var(--bg-link-color, var(--bg-accent));
	--bs-link-hover-color: var(--bg-link-hover-color, var(--bg-accent-hover));

	--bs-focus-ring-color: var(--bg-focus-ring);
	--bs-focus-ring-width: var(--bg-focus-width);

	/* Published for anything that reads it, and so a brand's custom_css can
	 * use rgba(var(--bs-primary-rgb), …) the way Bootstrap's docs describe.
	 * Setting this does not restyle components — see the note above. */
	--bs-primary: var(--bg-accent);
}

/* -------------------------------------------------------------------- *
 * Form controls.
 *
 * These pages ARE forms, and until now not one input carried a brand token:
 * every brand got Bootstrap's blue focus ring and blue checkboxes. Bootstrap
 * compiles the focus and checked colours from Sass rather than exposing them
 * as variables, so they need real declarations here. We load after Bootstrap,
 * so plain specificity is enough and none of this needs !important.
 * -------------------------------------------------------------------- */

.form-control,
.form-select {
	background-color: var(--bg-input-background, var(--bg-surface));
	color: var(--bg-input-text, var(--bg-ink));
	border-color: var(--bg-input-border, var(--bg-line-subtle));
	border-radius: var(--bg-input-radius, var(--bg-radius-control));
}

.form-control:focus,
.form-select:focus {
	background-color: var(--bg-input-background, var(--bg-surface));
	color: var(--bg-input-text, var(--bg-ink));
	border-color: var(--bg-input-border-focus, var(--bg-accent));
	box-shadow: 0 0 0 var(--bg-focus-width) var(--bg-focus-ring);
}

.form-control::placeholder {
	color: var(--bg-input-placeholder, var(--bg-ink-muted));
}

.form-label,
.col-form-label {
	color: var(--bg-input-label, var(--bg-surface-text, inherit));
}

.form-text {
	color: var(--bg-page-muted, var(--bg-ink-muted));
}

.form-check-input {
	background-color: var(--bg-input-background, var(--bg-surface));
	border-color: var(--bg-input-border, var(--bg-line));
}

.form-check-input:checked {
	background-color: var(--bg-accent);
	border-color: var(--bg-accent);
}

.form-check-input:focus {
	border-color: var(--bg-input-border-focus, var(--bg-accent));
	box-shadow: 0 0 0 var(--bg-focus-width) var(--bg-focus-ring);
}

/* Keyboard focus anywhere else on the page. Bootstrap only paints its own
 * components; an authored link inside a brand's HTML gets nothing without it. */
:focus-visible {
	outline-color: var(--bg-focus-outline, var(--bg-accent));
}

/* -------------------------------------------------------------------- *
 * Alerts. Eleven of them across the app, none previously themeable.
 *
 * The variant colours stay semantic — a red error is red on every brand,
 * because recolouring failure to match a logo is how a brand ends up with a
 * green error message. Only the shape and the neutral variant follow the theme.
 * -------------------------------------------------------------------- */
.alert {
	--bs-alert-border-radius: var(--bg-alert-radius, var(--bg-radius));
}

.alert-primary {
	--bs-alert-bg: var(--bg-alert-primary-background, var(--bg-accent-subtle));
	--bs-alert-color: var(--bg-alert-primary-text, var(--bg-ink));
	--bs-alert-border-color: var(--bg-alert-primary-border, transparent);
}
