/* kahal.dev design system — the single source of truth.
 *
 * The look is the homelab portal's: green phosphor on near-black, one monospace
 * face, `user@host:~$` prompts and `[tag]` labels. Everything on the site —
 * pages, pieces, static sketches — links this file and uses the tokens below.
 * No raw colours, no inline styles, no one-off spacing: if a value is missing
 * here, add it here. `npm run check:tokens` fails the build on raw colours
 * anywhere else. See DESIGN.md.
 */

/* ---------------------------------------------------------------- tokens */
:root {
	/* palette, as channels so canvas code and alpha washes can reuse them */
	--bg-rgb: 244 241 232;
	--bg-2-rgb: 250 248 241;
	--fg-rgb: 38 46 40;
	--dim-rgb: 104 112 104;
	--hi-rgb: 14 122 64;
	--amber-rgb: 150 88 0;
	--cyan-rgb: 0 104 140;
	--pink-rgb: 168 36 112;
	--red-rgb: 184 44 44;
	--line-rgb: 214 210 196;

	--bg: rgb(var(--bg-rgb));
	--bg-2: rgb(var(--bg-2-rgb));
	--fg: rgb(var(--fg-rgb));
	--dim: rgb(var(--dim-rgb));
	--hi: rgb(var(--hi-rgb));
	--amber: rgb(var(--amber-rgb));
	--cyan: rgb(var(--cyan-rgb));
	--pink: rgb(var(--pink-rgb));
	--red: rgb(var(--red-rgb));
	--line: rgb(var(--line-rgb));

	/* washes and glows: a colour at a fixed strength, never ad hoc */
	--hi-wash: rgb(var(--hi-rgb) / 0.1);
	--hi-select: rgb(var(--hi-rgb) / 0.28);
	--glow-alpha: 0; /* the light theme does not glow; the dark ones set it */
	--hi-glow: rgb(var(--hi-rgb) / var(--glow-alpha));
	--scan-rgb: var(--fg-rgb);
	--scan-alpha: 0.03;
	--scanline: rgb(var(--scan-rgb) / var(--scan-alpha));
	/* the moon: lit side and dark side, whichever way round reads on this background */
	--moon-lit: var(--bg-2);
	--moon-dark: var(--fg);
	--amber-wash: rgb(var(--amber-rgb) / 0.14);
	--red-wash: rgb(var(--red-rgb) / 0.18);

	/* type */
	--mono: ui-monospace, 'SF Mono', Menlo, Consolas, 'DejaVu Sans Mono', monospace;
	--fs-xs: 0.7rem;
	--fs-sm: 0.8rem;
	--fs-base: 15px;
	--lh: 1.6;

	/* space: a 4-step scale in rem, used for every margin and gap */
	--s-1: 0.25rem;
	--s-2: 0.5rem;
	--s-3: 0.75rem;
	--s-4: 1rem;
	--s-5: 1.75rem;
	--s-6: 2.5rem;

	--r: 4px;
	--measure: 46rem;
	--dur: 160ms;
	--ease: cubic-bezier(0.2, 0.7, 0.2, 1);

	color-scheme: light;
}

/* --------------------------------------------------------------- themes */
/* A theme is a set of channel overrides; every token above is derived from them, so nothing
 * else changes. The default (no attribute) is `paper`, the light theme. Roles keep their meaning
 * across themes: --hi acts, --amber names, --cyan links, --pink apps, --red fails. Each palette
 * keeps >= 4.5:1 contrast on its --bg for every role. The list of names, and which is the
 * default, live in theme.js; keep the two in step. */
:root[data-theme='green'] {
	--bg-rgb: 10 15 11;
	--bg-2-rgb: 15 26 18;
	--fg-rgb: 183 245 196;
	--dim-rgb: 95 138 106;
	--hi-rgb: 90 247 142;
	--amber-rgb: 255 204 102;
	--cyan-rgb: 111 227 255;
	--pink-rgb: 255 138 216;
	--red-rgb: 255 123 123;
	--line-rgb: 27 43 32;
}
:root[data-theme='amber'] {
	--bg-rgb: 16 11 4;
	--bg-2-rgb: 27 19 6;
	--fg-rgb: 255 214 150;
	--dim-rgb: 168 130 72;
	--hi-rgb: 255 176 0;
	--amber-rgb: 255 236 160;
	--cyan-rgb: 140 225 205;
	--pink-rgb: 255 150 120;
	--red-rgb: 255 110 100;
	--line-rgb: 52 36 12;
}
:root[data-theme='ice'] {
	--bg-rgb: 8 12 18;
	--bg-2-rgb: 13 20 30;
	--fg-rgb: 190 220 245;
	--dim-rgb: 104 136 168;
	--hi-rgb: 110 200 255;
	--amber-rgb: 255 214 120;
	--cyan-rgb: 150 240 230;
	--pink-rgb: 200 160 255;
	--red-rgb: 255 130 140;
	--line-rgb: 26 40 58;
}
:root[data-theme='violet'] {
	--bg-rgb: 14 9 20;
	--bg-2-rgb: 22 14 32;
	--fg-rgb: 232 208 255;
	--dim-rgb: 150 120 182;
	--hi-rgb: 200 130 255;
	--amber-rgb: 255 200 110;
	--cyan-rgb: 110 230 255;
	--pink-rgb: 255 130 200;
	--red-rgb: 255 120 130;
	--line-rgb: 44 30 62;
}
/* what every dark theme shares: phosphor glow, scanlines in the accent, a bright moon */
:root[data-theme='green'],
:root[data-theme='amber'],
:root[data-theme='ice'],
:root[data-theme='violet'] {
	color-scheme: dark;
	--glow-alpha: 0.45;
	--scan-rgb: var(--hi-rgb);
	--scan-alpha: 0.035;
	--moon-lit: var(--fg);
	--moon-dark: var(--bg);
}

/* ------------------------------------------------------------------ base */
* {
	box-sizing: border-box;
}
html {
	background: var(--bg);
}
body {
	margin: 0;
	min-height: 100vh;
	color: var(--fg);
	font: var(--fs-base) / var(--lh) var(--mono);
	background:
		repeating-linear-gradient(to bottom, transparent 0 2px, var(--scanline) 2px 3px),
		radial-gradient(ellipse at top, var(--bg-2) 0%, var(--bg) 70%);
	background-attachment: fixed;
}
::selection {
	background: var(--hi-select);
	color: var(--fg);
}
:focus-visible {
	outline: 1px dashed var(--hi);
	outline-offset: 2px;
}
a {
	color: var(--fg);
	text-decoration: none;
}
h1,
h2,
h3,
p,
ul,
ol,
pre {
	margin: 0;
	font: inherit;
}
ul,
ol {
	list-style: none;
	padding: 0;
}
main {
	max-width: var(--measure);
	margin: 0 auto;
	padding: var(--s-5) var(--s-4) var(--s-6);
}
@media (prefers-reduced-motion: reduce) {
	* {
		transition: none !important;
		animation: none !important;
	}
}

/* ------------------------------------------------------------ primitives */
/* colour roles */
.c-fg { color: var(--fg); }
.c-dim { color: var(--dim); }
.c-hi { color: var(--hi); }
.c-amber { color: var(--amber); }
.c-cyan { color: var(--cyan); }
.c-pink { color: var(--pink); }
.c-red { color: var(--red); }

/* the prompt: `user@host:~$ command`, and the output under it */
.ps1 { color: var(--hi); }
.cmd { margin: var(--s-5) 0 var(--s-1); }
.cmd.first { margin-top: 0; }
.cmd.tight { margin-top: var(--s-4); }
.out {
	margin: 0 0 var(--s-1);
	white-space: pre-wrap;
	overflow-wrap: anywhere;
}
.gap { margin-top: var(--s-4); }
.gap-lg { margin-top: var(--s-5); }

.banner {
	margin: 0 0 var(--s-2);
	color: var(--hi);
	line-height: 1.3;
	font-weight: bold;
	text-shadow: 0 0 6px var(--hi-glow);
	overflow-x: auto;
}
.motd { color: var(--dim); margin: 0 0 var(--s-5); }

/* a listing row: [tag] label ........ trailing */
.ls a {
	display: flex;
	gap: 1ch;
	padding: 0.15rem 0.5ch;
	border-left: 2px solid transparent;
}
.ls a:hover,
.ls a:focus-visible {
	background: var(--hi-wash);
	border-left-color: var(--hi);
	outline: none;
}
.ls a:hover .label::after,
.ls a:focus-visible .label::after {
	content: ' \2192';
	color: var(--hi);
}
.tag { flex: 0 0 10ch; }
.label { min-width: 0; overflow-wrap: anywhere; }
.hc { margin-left: auto; flex: none; white-space: nowrap; color: var(--dim); }
.t-game { color: var(--cyan); }
.t-art { color: var(--amber); }
.t-app { color: var(--pink); }
.t-link { color: var(--dim); }

.legend {
	color: var(--dim);
	margin-top: var(--s-6);
	border-top: 1px dashed var(--line);
	padding-top: var(--s-4);
}
.legend a { color: var(--cyan); }

/* input line */
.prompt { display: flex; gap: 1ch; margin: var(--s-5) 0 0; }
.prompt.first { margin-top: 0; }
.prompt label { flex: none; }
.prompt input {
	flex: 1;
	min-width: 0;
	padding: 0;
	border: 0;
	outline: 0;
	background: transparent;
	color: var(--fg);
	font: inherit;
	caret-color: var(--hi);
}
.prompt input::placeholder { color: var(--dim); opacity: 0.7; }

/* navigation */
.crumbs { display: flex; flex-wrap: wrap; gap: 0 1.5ch; margin: 0 0 var(--s-5); }
.crumbs a { color: var(--dim); }
.crumbs a:hover,
.crumbs a[aria-current='page'] { color: var(--hi); }
.crumbs .cycle { margin-left: auto; }

/* controls: `[x] option` toggles and `$ command` buttons */
.opt {
	font: inherit;
	color: var(--dim);
	background: none;
	border: 0;
	padding: 0;
	cursor: pointer;
}
.opt::before { content: '[ ] '; }
.opt[aria-pressed='true'] { color: var(--hi); }
.opt[aria-pressed='true']::before { content: '[x] '; }
.opt:hover:not(:disabled),
.opt:focus-visible { color: var(--fg); }
.run {
	font: inherit;
	color: var(--hi);
	background: none;
	border: 0;
	padding: 0;
	cursor: pointer;
}
.run::before { content: '$ '; color: var(--dim); }
.run:hover:not(:disabled) { text-shadow: 0 0 6px var(--hi-glow); }
.opt:disabled,
.run:disabled { opacity: 0.5; cursor: default; }
.row { display: flex; flex-wrap: wrap; gap: 0 2.5ch; }

/* a control that cycles through values: `theme: green` */
.cycle {
	font: inherit;
	color: var(--dim);
	background: none;
	border: 0;
	padding: 0;
	cursor: pointer;
}
.cycle b { color: var(--hi); font-weight: normal; }
.cycle:hover,
.cycle:focus-visible { color: var(--fg); }

/* an external link inside running text: cyan, the link role, with a dotted underline */
.ext {
	color: var(--cyan);
	text-decoration: underline dotted;
	text-underline-offset: 3px;
}
.ext:hover,
.ext:focus-visible { text-decoration-style: solid; }

/* a chip: one small highlighted fact, e.g. `CI 20 → 5 min` */
.chip {
	display: inline-block;
	padding: 0 var(--s-2);
	border: 1px solid var(--line);
	border-radius: var(--r);
	background: var(--amber-wash);
	color: var(--amber);
	font-size: var(--fs-sm);
	white-space: nowrap;
}

/* a bordered surface, for pieces that need a frame */
.frame { border: 1px solid var(--line); border-radius: var(--r); background: var(--bg-2); }
.pick { border-left: 2px solid transparent; }
.pick:hover,
.pick[aria-current='true'] { background: var(--hi-wash); border-left-color: var(--hi); }

/* print: always the paper palette on white, without the chrome */
@media print {
	:root,
	:root[data-theme] {
		--bg-rgb: 255 255 255;
		--bg-2-rgb: 255 255 255;
		--fg-rgb: 38 46 40;
		--dim-rgb: 104 112 104;
		--hi-rgb: 14 122 64;
		--amber-rgb: 150 88 0;
		--glow-alpha: 0;
		--scan-alpha: 0;
		color-scheme: light;
	}
	.no-print,
	.crumbs { display: none !important; }
	:root { --fs-base: 11px; }
	body { background: var(--bg); }
	main { max-width: none; padding: 0; }
}
