/* ---------------------------------------------------------------------------
   Chartreuse — application shell

   This stylesheet dresses exactly one page: the sign-in page
   (`../templates/login.html`). Everything else the app serves is the wizard,
   which is `/wizard-static/wizard-base.css` plus `./wizard.css` and never
   loads this file.

   Hand-written and dependency-free. It replaces a 10,185-line Tailwind v4 +
   Basecoat artefact whose build could not be run — `package.json` had neither
   the `css` script its source documented nor a `tailwindcss` dependency — so
   the committed output was unreproducible and the page could not be changed.
   Sixteen classes on one page do not need a framework.

   No cascade layers. The old source declared `@layer report, …` so a document
   panel could inject the rendered report's Bootstrap beneath the app's rules;
   that panel belonged to the chat UI and is gone. Nothing embeds report CSS
   in a page now, and this one has no third-party CSS to rank against.

   Palette, radii, shadows and faces are the marketing site's, taken by value
   from the old source and cross-checked against `wizard.css`, which was
   lifted from the same place. Light throughout: cool paper, white cards, deep
   emerald accent, ink on paper.
--------------------------------------------------------------------------- */

/* --- Brand faces ---------------------------------------------------------
   Self-hosted to match the DOMPurify posture — no CDN in the request path.
   Served from /assets, which is where the Theme dataclass mounts `fonts_dir`.
   The woff2 files are vendored from the @fontsource-variable packages of the
   same names; refresh them from there rather than editing in place. */

@font-face {
	font-family: "Hanken Grotesk Variable";
	font-style: normal;
	font-weight: 100 900;
	font-display: swap;
	src: url("/theme/chartreuse/fonts/hanken-grotesk-latin-wght-normal.woff2")
		format("woff2");
}

@font-face {
	font-family: "Schibsted Grotesk Variable";
	font-style: normal;
	font-weight: 400 900;
	font-display: swap;
	src: url("/theme/chartreuse/fonts/schibsted-grotesk-latin-wght-normal.woff2")
		format("woff2");
}

@font-face {
	font-family: "JetBrains Mono Variable";
	font-style: normal;
	font-weight: 100 800;
	font-display: swap;
	src: url("/theme/chartreuse/fonts/jetbrains-mono-latin-wght-normal.woff2")
		format("woff2");
}

/* --- Tokens ------------------------------------------------------------- */

:root {
	--font-sans:
		"Hanken Grotesk Variable", ui-sans-serif, system-ui, -apple-system,
		sans-serif;
	--font-display: "Schibsted Grotesk Variable", var(--font-sans);
	--font-mono: "JetBrains Mono Variable", ui-monospace, "SF Mono", monospace;

	/* The emerald is deepened from the marketing green so it holds contrast
	   against paper. */
	--primary: #10794c;
	--primary-foreground: #ffffff;

	/* Paper is the colour behind the page, white is the reading surface. That
	   distinction is what makes the marketing site read as paper on a desk. */
	--background: #f4f6f3;
	--card: #ffffff;
	--foreground: #131715;

	--border: rgba(19, 23, 21, 0.1);
	--input: rgba(19, 23, 21, 0.17);
	--ring: #10794c;
	/* Read by login.html's `.error-message`. The wizard's equivalent is a
	   shade darker (`--ch-danger: #9c1f25`); this is the shell's own value and
	   is left as it was. */
	--destructive: #b4232a;

	--radius: 0.5rem;

	color-scheme: light;
}

/* --- Base ---------------------------------------------------------------- */

/* The one piece of Tailwind's preflight that is load-bearing here: without it
   `.input`'s `width: 100%` is 100% *plus* its padding and border, and the
   field overhangs the card it sits in. */
*,
*::before,
*::after {
	box-sizing: border-box;
}

body {
	margin: 0;
	font-family: var(--font-sans);
	/* The variable faces carry their own weights; let the browser synthesise
	   none of them or 600 comes out smeared. */
	font-synthesis-weight: none;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	background-color: var(--background);
	color: var(--foreground);
}

h1 {
	font-family: var(--font-display);
	letter-spacing: -0.02em;
	text-wrap: balance;
}

::selection {
	background-color: var(--primary);
	color: var(--primary-foreground);
}

:focus-visible {
	outline: 2px solid var(--ring);
	outline-offset: 2px;
	border-radius: 3px;
}

/* --- Brand lockup -------------------------------------------------------- */

.app-header {
	display: flex;
	align-items: center;
	gap: 0.7rem;
}

.app-header__mark {
	width: 1.4rem;
	height: 1.4rem;
	flex-shrink: 0;
}

.app-header__wordmark {
	font-family: var(--font-display);
	font-size: 0.95rem;
	font-weight: 600;
	letter-spacing: -0.01em;
	color: var(--foreground);
}

/* Mono is the tool's utility voice — service names, labels, thresholds.
   Prose stays in Hanken. */
.app-header__service {
	font-family: var(--font-mono);
	font-size: 0.68rem;
	font-weight: 500;
	letter-spacing: 0.18em;
	text-transform: uppercase;
	color: var(--primary);
	padding-left: 0.7rem;
	margin-left: 0.1rem;
	border-left: 1px solid var(--border);
}

/* --- Components ---------------------------------------------------------- */

.card {
	display: flex;
	flex-direction: column;
	gap: 1.5rem;
	padding-block: 1.5rem;
	/* One step softer than the controls inside it, so the card reads as the
	   container rather than as another control. */
	border-radius: calc(var(--radius) + 4px);
	background-color: var(--card);
	color: var(--foreground);
	font-size: 0.875rem;
	line-height: 1.43;
	box-shadow:
		0 0 0 1px var(--border),
		0 1px 2px rgba(19, 23, 21, 0.05);
	overflow: hidden;
}

.label {
	font-size: 0.875rem;
	font-weight: 500;
	line-height: 1;
	color: var(--foreground);
	user-select: none;
}

.input {
	width: 100%;
	min-width: 0;
	height: 2.25rem;
	padding-inline: 0.75rem;
	font: inherit;
	font-size: 0.875rem;
	color: var(--foreground);
	background-color: var(--card);
	border: 1px solid var(--input);
	border-radius: calc(var(--radius) - 2px);
	box-shadow: 0 1px 2px rgba(19, 23, 21, 0.04);
	outline: none;
}

/* A wider ring than the global :focus-visible, because on a form control the
   focus state is the only affordance telling you where you are typing. */
.input:focus-visible {
	outline: none;
	border-color: var(--ring);
	box-shadow: 0 0 0 3px rgba(16, 121, 76, 0.35);
}

.btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	flex-shrink: 0;
	height: 2.25rem;
	padding-inline: 0.75rem;
	font: inherit;
	font-size: 0.875rem;
	font-weight: 500;
	white-space: nowrap;
	color: var(--primary-foreground);
	background-color: var(--primary);
	border: 1px solid transparent;
	border-radius: calc(var(--radius) - 2px);
	cursor: pointer;
	user-select: none;
	transition:
		background-color 0.15s ease,
		translate 0.15s ease;
}

.btn:hover {
	background-color: #0c6440;
}

/* A press moves the button rather than only shading it, which survives a
   colour-blind or high-contrast rendering of the hover state. */
.btn:active {
	translate: 0 1px;
}

.btn:disabled {
	pointer-events: none;
	opacity: 0.5;
}

/* --- Sign in ------------------------------------------------------------- */

.signin {
	min-height: 100vh;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 1.5rem;
}

.signin__card {
	width: 100%;
	max-width: 24rem;
}

.signin__brand {
	margin-bottom: 1.5rem;
}

.signin__panel {
	padding-inline: 1.5rem;
}

.signin__title {
	font-size: 1.25rem;
	font-weight: 600;
	margin: 0;
}

.signin__label {
	display: block;
	margin-bottom: 0.4rem;
}

.signin__input {
	margin-bottom: 1rem;
}

.signin__submit {
	width: 100%;
}

/* Emitted by app/auth.py as `<p class="error-message">…</p>` on a wrong
   password or a throttle lockout; absent otherwise. */
.error-message {
	color: var(--destructive);
	font-size: 0.85rem;
	margin: 0 0 0.75rem;
}

/* The button's fade and press are the only motion on the page, so the
   preference is honoured by naming them rather than by a blanket `*` reset
   with `!important`. */
@media (prefers-reduced-motion: reduce) {
	.btn {
		transition: none;
	}
}
