/*
	Design tokens for the eOrdering web UI.

	These are the OnBrand Mail portal's tokens (Email Signature Manager, portal/src/theme.ts),
	restated as plain custom properties so a WebForms app with no build step can consume them.
	The portal's own marketing site does the same thing for the same reason, so the three
	surfaces stay in step.

	The palette is stored as space-separated RGB triplets rather than hex. That is what lets
	tailwind.config.js declare its colours as `rgb(var(--stone-0-rgb) / <alpha-value>)` - one
	source of truth, opacity modifiers such as bg-gray-900/80 still work, and a palette change
	needs no `npm run build:css` at all because the compiled stylesheet only ever references
	the variables. The hex-equivalent `--stone-0` forms below are for css/app.css to read.

	Three rules carry the look and are easy to undo by accident:

	  1. --ground is DARKER than --paper in light mode. Cards are sheets of paper on a desk,
	     not panels cut out of a white page. Inverting them makes the whole UI read as generic.

	  2. Shadows are warm - rgba(29, 26, 18, x), not black. Neutral shadows against the warm
	     paper look like dirt. In dark mode they go near-black, because a warm shadow on a cool
	     dark ground reads as a smudge.

	  3. The stone ramp INVERTS between schemes: stone-0 is the lightest surface in light mode
	     and the darkest in dark mode. That is what makes `text-gray-800` and `bg-gray-50`
	     scattered through the .aspx markup flip on their own instead of needing a dark: variant
	     on every one of them. Keep it monotonic or that stops working.

	Iris does NOT invert. It is the brand colour, and a brand that changes hue with the light
	is not a brand. Where iris is used as a background wash it goes through the --accent-*
	roles below, which do flip.
*/

:root {
	/* ===== iris: the primary ramp (does not invert) ===== */
	--iris-0-rgb: 242 240 255;
	--iris-1-rgb: 229 224 255;
	--iris-2-rgb: 205 194 255;
	--iris-3-rgb: 177 158 255;
	--iris-4-rgb: 151 125 255;
	--iris-5-rgb: 132 97 251;
	--iris-6-rgb: 122 82 244;
	--iris-7-rgb: 103 66 224;
	--iris-8-rgb: 86 54 191;
	--iris-9-rgb: 71 44 156;

	--iris-0: rgb(var(--iris-0-rgb));
	--iris-1: rgb(var(--iris-1-rgb));
	--iris-2: rgb(var(--iris-2-rgb));
	--iris-3: rgb(var(--iris-3-rgb));
	--iris-4: rgb(var(--iris-4-rgb));
	--iris-5: rgb(var(--iris-5-rgb));
	--iris-6: rgb(var(--iris-6-rgb));
	--iris-7: rgb(var(--iris-7-rgb));
	--iris-8: rgb(var(--iris-8-rgb));
	--iris-9: rgb(var(--iris-9-rgb));

	/*
		The primary has two jobs and they need different weights once there is a dark scheme.

		--primary FILLS things - buttons, the current pager page - and carries --on-primary as its
		label, so it is picked for contrast against that label. --primary-text DRAWS on the paper:
		links, active icons, the focused input border, the active tab rule. On a dark card the fill
		shade is too dim to read as text, and the text shade is too pale to sit a white label on,
		so one token cannot be both.

		Shade 6 is the lightest step that clears AA against white, which is what makes it the fill
		in both schemes.
	*/
	--primary: var(--iris-6);
	--primary-hover: var(--iris-8);
	--primary-text: var(--iris-6);
	--on-primary: #fdfcf9;
	/* Focus rings and glows only - rgb(var(--primary-rgb) / a). */
	--primary-rgb: var(--iris-6-rgb);

	/* ===== stone: warm neutrals, replacing the usual blue-grey (inverts) ===== */
	--stone-0-rgb: 247 245 241;
	--stone-1-rgb: 239 236 230;
	--stone-2-rgb: 227 223 215;
	--stone-3-rgb: 211 206 196;
	--stone-4-rgb: 184 178 167;
	--stone-5-rgb: 156 150 138;
	--stone-6-rgb: 110 105 96;
	--stone-7-rgb: 86 81 73;
	--stone-8-rgb: 60 57 52;
	--stone-9-rgb: 38 36 33;

	--stone-0: rgb(var(--stone-0-rgb));
	--stone-1: rgb(var(--stone-1-rgb));
	--stone-2: rgb(var(--stone-2-rgb));
	--stone-3: rgb(var(--stone-3-rgb));
	--stone-4: rgb(var(--stone-4-rgb));
	--stone-5: rgb(var(--stone-5-rgb));
	--stone-6: rgb(var(--stone-6-rgb));
	--stone-7: rgb(var(--stone-7-rgb));
	--stone-8: rgb(var(--stone-8-rgb));
	--stone-9: rgb(var(--stone-9-rgb));

	/* ===== surfaces & ink ===== */
	--paper-rgb: 253 252 249;   /* cards, header, modals */
	--paper: rgb(var(--paper-rgb));
	--ground: var(--stone-1);   /* the page behind the paper - deliberately darker */
	--ink-rgb: 29 35 51;
	--ink: rgb(var(--ink-rgb));
	--ink-soft: var(--stone-7);
	--dimmed: var(--stone-6);
	--hairline: var(--stone-2);
	--border: var(--stone-4);   /* input and control borders, a step stronger than hairline */
	--placeholder: var(--stone-5);

	/*
		Surface roles. These exist because hover direction inverts: in light mode a hovered row
		goes darker than the paper, in dark mode it must go lighter. Reaching straight for
		--stone-1 works in light and silently produces an invisible hover in dark, because there
		--stone-1 IS the paper colour.
	*/
	--surface-sunken: var(--stone-0);   /* table headers, input prefixes - recedes in both schemes */
	--surface-hover: var(--stone-1);
	--surface-active: var(--stone-2);

	/*
		Accent roles. Iris itself never inverts, but iris-as-a-background does: --iris-0 is a
		near-white lavender and would glare on a dark card.
	*/
	--accent-wash: var(--iris-0);
	--accent-wash-hover: var(--iris-1);
	--accent-ink: var(--iris-8);
	--accent-border: var(--iris-2);

	/* ===== semantic status colours =====
	   The contract inherited from the portal: red = fail, orange = danger/bypass,
	   yellow = warn/unsaved, green/teal = pass/active, blue = info, stone = neutral.
	   Iris is deliberately absent so the primary never reads as a status. */
	--red: #e03131;
	--red-ink: #c92a2a;
	--red-wash: #fff5f5;
	--red-edge: #ffc9c9;

	--orange: #e8590c;
	/* Deeper than the Mantine orange-8 this started as: on the pale --orange-wash that only
	   reached 3.96:1, which is under AA for the pill text it is meant to carry. */
	--orange-ink: #9a3412;
	--orange-wash: #fff4e6;
	--orange-edge: #ffd8a8;

	/* --yellow-wash is very pale, so the ink has to go a long way down to carry text on it;
	   the amber this started as managed only 3.83:1. It reads on the MFA banner, the SMS
	   warning and the Follow-up pill, all of which are prose rather than decoration. */
	--yellow-ink: #856404;
	--yellow-wash: #fff9db;
	--yellow-edge: #ffe999;

	--green: #2f9e44;
	--green-ink: #287f39;
	--green-wash: #ebfbee;
	--green-edge: #b2f2bb;

	--teal-ink: #087f5a;
	--teal-wash: #e6fcf5;
	--teal-edge: #96f2d7;

	--blue-ink: #1864ab;
	--blue-wash: #e7f5ff;
	--blue-edge: #a5d8ff;

	/* ===== type ===== */
	--font-display: 'Fraunces', Georgia, 'Times New Roman', serif;
	--font-body: 'Schibsted Grotesk', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
	--font-mono: 'JetBrains Mono', ui-monospace, 'Cascadia Code', Consolas, monospace;

	/* Fraunces is a variable face; 560 sits between semibold and bold with a bookish warmth
	   that neither 600 nor 700 has. Headings use this weight everywhere. */
	--display-weight: 560;

	/* ===== warm two-layer shadows ===== */
	--shadow-xs: 0 1px 2px rgba(29, 26, 18, 0.05), 0 1px 1px rgba(29, 26, 18, 0.03);
	--shadow-sm: 0 1px 2px rgba(29, 26, 18, 0.05), 0 6px 14px -4px rgba(29, 26, 18, 0.08);
	--shadow-md: 0 2px 4px rgba(29, 26, 18, 0.05), 0 14px 28px -8px rgba(29, 26, 18, 0.10);
	--shadow-lg: 0 2px 4px rgba(29, 26, 18, 0.06), 0 24px 40px -10px rgba(29, 26, 18, 0.14);
	--shadow-xl: 0 3px 6px rgba(29, 26, 18, 0.07), 0 36px 60px -12px rgba(29, 26, 18, 0.18);

	/* ===== radii ===== */
	--radius-xs: 2px;
	--radius-sm: 4px;
	--radius-md: 8px;   /* the default: buttons, inputs, cards */
	--radius-lg: 16px;  /* modals, hero cards */
	--radius-pill: 999px;

	/* ===== shell geometry (matches the portal's AppShell) ===== */
	--header-h: 56px;
	--nav-w: 240px;

	/* ===== motion ===== */
	--ease-out: cubic-bezier(0.2, 0.6, 0.2, 1);
	--t-fast: 120ms;
	--t-med: 240ms;

	/* ===== the grain =====
	   A 160x160 fractal-noise tile at 5% alpha, inline so it costs no request. This is what
	   keeps the flat background from looking like an unpainted div. Alpha is baked into the
	   tile rather than the colour so one tile serves both schemes. */
	--grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3CfeComponentTransfer%3E%3CfeFuncA type='linear' slope='0.05'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");

	color-scheme: light;
}

/*
	Dark mode. Set by SiteTailwind.Master's pre-paint script from localStorage('orm.colorScheme')
	before first paint, so the page never flashes light before flipping.

	The stone ramp is the ESM portal's ink-slate scale in reverse, which lands almost exactly on
	that app's own dark semantics: --dimmed, --border and --placeholder come out at its dark-2,
	dark-4 and dark-3 respectively without being special-cased.
*/
[data-theme="dark"] {
	--stone-0-rgb: 25 28 46;     /* darkest surface - was the lightest */
	--stone-1-rgb: 32 36 58;
	--stone-2-rgb: 43 48 69;
	--stone-3-rgb: 54 60 82;
	--stone-4-rgb: 69 75 99;
	--stone-5-rgb: 102 108 133;
	--stone-6-rgb: 142 147 173;
	--stone-7-rgb: 179 183 204;
	--stone-8-rgb: 205 208 224;
	--stone-9-rgb: 230 232 240;  /* lightest text - was the darkest */

	--paper-rgb: 32 36 58;
	--ground: var(--stone-0);
	--ink-rgb: 205 208 224;

	/*
		The fill stays on shade 6. Shade 5 is the obvious choice for a dark scheme and is what
		the portal uses, but a white label on it only reaches 3.95:1 - under AA - and no
		foreground fixes that, because near-black on iris-5 is worse still. Hover goes deeper
		rather than lighter for the same reason.

		The text weight is where dark mode actually needs the lighter shade: iris-6 on a dark
		card is about 3.4:1, so links and active icons move to iris-3 at roughly 7:1.
	*/
	--primary-hover: var(--iris-7);
	--primary-text: var(--iris-3);
	/* Rings read better bright against a dark ground than the fill shade does. */
	--primary-rgb: var(--iris-4-rgb);

	/* --hairline would otherwise land on the paper colour and disappear. */
	--hairline: var(--stone-2);
	--border: var(--stone-4);

	--surface-sunken: var(--stone-0);
	--surface-hover: var(--stone-2);   /* lighter than paper, not darker */
	--surface-active: var(--stone-3);

	/* iris-6 mixed into the paper at 18% and 28%; the raw iris-0/1 washes would glare. */
	--accent-wash: #302c5b;
	--accent-wash-hover: #39316e;
	--accent-ink: var(--iris-3);
	--accent-border: var(--iris-7);

	/* Status washes re-struck for a dark ground. Same contract, same order. */
	--red-ink: #ff8787;
	--red-wash: #2e1c22;
	--red-edge: #5c2b33;

	--orange-ink: #ffa94d;
	--orange-wash: #33241a;
	--orange-edge: #6b452a;

	--yellow-ink: #ffd43b;
	--yellow-wash: #2f2a17;
	--yellow-edge: #5f5327;

	--green-ink: #69db7c;
	--green-wash: #1a2b1f;
	--green-edge: #2f5738;

	--teal-ink: #38d9a9;
	--teal-wash: #122b28;
	--teal-edge: #1f544c;

	--blue-ink: #74c0fc;
	--blue-wash: #17242f;
	--blue-edge: #2a4a63;

	/* Near-black and deeper: a warm shadow over a cool dark ground reads as a smudge. */
	--shadow-xs: 0 1px 2px rgba(0, 0, 0, 0.30), 0 1px 1px rgba(0, 0, 0, 0.22);
	--shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.32), 0 6px 14px -4px rgba(0, 0, 0, 0.40);
	--shadow-md: 0 2px 4px rgba(0, 0, 0, 0.34), 0 14px 28px -8px rgba(0, 0, 0, 0.46);
	--shadow-lg: 0 2px 4px rgba(0, 0, 0, 0.36), 0 24px 40px -10px rgba(0, 0, 0, 0.52);
	--shadow-xl: 0 3px 6px rgba(0, 0, 0, 0.40), 0 36px 60px -12px rgba(0, 0, 0, 0.60);

	color-scheme: dark;
}
