/* Duck Hunt, 42 Luxembourg.
   A dark arcade cabinet around a Game Boy screen: the page is the cabinet
   (scanlines, quest log), every content panel (.card) is the green screen.
   Jersey 10 for titles, Silkscreen for labels and buttons, IBM Plex Mono
   for reading. The rubber duck yellow is the only loud color. */

@font-face {
	font-family: "Jersey 10";
	src: url("/static/fonts/jersey-10.woff2") format("woff2");
	font-display: swap;
}
@font-face {
	font-family: "Silkscreen";
	src: url("/static/fonts/silkscreen-700.woff2") format("woff2");
	font-weight: 700;
	font-display: swap;
}
@font-face {
	font-family: "Plex Mono";
	src: url("/static/fonts/plex-mono-400.woff2") format("woff2");
	font-weight: 400;
	font-display: swap;
}
@font-face {
	font-family: "Plex Mono";
	src: url("/static/fonts/plex-mono-700.woff2") format("woff2");
	font-weight: 700;
	font-display: swap;
}

:root {
	/* cabinet */
	--cab: #121412;
	--cab-line: #2c332c;
	--cab-text: #e6ebe0;
	--cab-muted: #98a394;
	/* screen: the four greens of the handheld */
	--g0: #e0f0c8;
	--g1: #a8c878;
	--g2: #4a7a3a;
	--g3: #16301a;
	--paper: #f4fae8;
	--band: #d2e6b4;
	--duck: #ffc93c;
	--danger: #b3261e;
	/* game tiles, readable on the dark water */
	--tile-red: #e0564c;
	--tile-green: #7cc35a;
	--tile-blue: #6a9be0;

	--title: "Jersey 10", ui-monospace, monospace;
	--label: "Silkscreen", ui-monospace, monospace;
	--body: "Plex Mono", ui-monospace, "DejaVu Sans Mono", monospace;
	color-scheme: dark;
}

* { box-sizing: border-box; }

html { background: var(--cab); }

body {
	margin: 0;
	min-height: 100vh;
	display: flex;
	flex-direction: column;
	background: var(--cab);
	color: var(--cab-text);
	font: 16px/1.65 var(--body);
	-webkit-tap-highlight-color: transparent;
}
/* faint CRT scanlines over the whole cabinet */
body::after {
	content: "";
	position: fixed;
	inset: 0;
	z-index: 50;
	pointer-events: none;
	background: repeating-linear-gradient(transparent 0 2px, rgba(0, 0, 0, .14) 2px 3px);
}

img { image-rendering: pixelated; }
a { color: var(--duck); text-underline-offset: 3px; }
a:focus-visible, button:focus-visible, input:focus-visible {
	outline: 4px solid var(--duck);
	outline-offset: 3px;
}

/* ---------------------------------------------------------------- top bar */

.top {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	padding: 12px 28px;
	border-bottom: 2px solid var(--cab-line);
}
.logo {
	display: flex;
	align-items: center;
	gap: 12px;
	color: var(--duck);
	font: 34px/1 var(--title);
	text-decoration: none;
	white-space: nowrap;
}
.logo img { width: 36px; height: 36px; }
.player { display: flex; align-items: baseline; gap: 22px; color: var(--cab-muted); white-space: nowrap; }
.player a { color: var(--cab-muted); }
.player a:hover { color: var(--cab-text); }
.player b { color: var(--cab-text); }

/* ---------------------------------------------------------------- page */

.layout {
	flex: 1;
	width: 100%;
	max-width: 1200px;
	margin: 0 auto;
	padding: 40px 28px 64px;
}
body.quest .layout {
	display: grid;
	grid-template-columns: 250px minmax(0, 1fr);
	gap: 44px;
	align-items: start;
}
body.home .layout { max-width: 760px; }
.content { min-width: 0; }

/* quest log, on the cabinet */
.quest { position: sticky; top: 24px; }
.quest h2 { margin: 0 0 14px; font: 30px/1 var(--title); color: var(--cab-muted); }
.quest ol { list-style: none; margin: 0; padding: 0; border-left: 4px solid var(--cab-line); }
.quest li { position: relative; padding: 4px 0 20px 26px; color: var(--cab-muted); }
.quest li::before {
	content: "";
	position: absolute;
	left: -12px;
	top: 10px;
	width: 20px;
	height: 20px;
	background: var(--cab);
	border: 4px solid var(--cab-line);
}
.quest li.done { color: var(--cab-text); }
.quest li.done::before { background: var(--g1); border-color: var(--g1); }
.quest li.now { color: var(--duck); }
.quest li.now::before { background: var(--duck); border-color: var(--duck); }
.quest .day { display: block; font: 700 11px var(--label); letter-spacing: .04em; }
.quest .name { font: 28px/1 var(--title); }
.quest .side {
	margin: 10px 0 0;
	padding: 14px 16px;
	border: 4px dashed var(--cab-line);
	color: var(--cab-muted);
	font-size: 14px;
	line-height: 1.55;
}

.pond {
	position: relative;
	padding: 16px;
	border-top: 2px solid var(--cab-line);
	color: var(--cab-muted);
	font: 700 11px var(--label);
	letter-spacing: .04em;
	text-align: center;
}
.pond p { margin: 0; }
body.home .pond {
	height: 104px;
	padding: 0;
	border: 0;
	background:
		url("/static/sprites/reeds.svg") repeat-x left top / 128px 48px,
		linear-gradient(var(--g3), var(--g3)) left 48px / 100% 100% no-repeat;
}
body.home .pond p { position: absolute; bottom: 14px; width: 100%; color: var(--g1); }

/* ---------------------------------------------------------------- the screen */

.card {
	position: relative;
	margin-bottom: 40px;
	padding: 34px 40px;
	background: var(--g0);
	color: var(--g3);
	border: 4px solid var(--g3);
	box-shadow: 0 0 0 6px var(--cab-line), 10px 10px 0 6px #000;
}
.card a { color: var(--g3); font-weight: 700; }
.center { text-align: center; }

h1, h2 { margin: 0 0 18px; font-family: var(--title); font-weight: 400; line-height: .95; text-wrap: balance; }
.card h1 { font-size: 60px; }
.card h2 { font-size: 36px; }
p { margin: 0 0 14px; }
.card p { max-width: 66ch; }
.card.center p { margin-inline: auto; }

.step { margin-bottom: 6px; font: 700 12px var(--label); letter-spacing: .04em; color: var(--g2); }
.muted, .hint { color: var(--g2); }
.hint { margin-top: 26px; font-size: 15px; }
.error { color: var(--danger); font-weight: 700; }
.ok { color: var(--g2); font-weight: 700; }

.card code {
	padding: 1px 6px;
	background: var(--g1);
	font-family: var(--body);
	font-size: .94em;
}
.card pre {
	margin: 0 0 16px;
	padding: 16px 18px;
	background: var(--g3);
	color: var(--g0);
	font-size: 17px;
	overflow-x: auto;
}
.card pre code { padding: 0; background: none; color: inherit; }

/* subject text sits in a slightly darker band of the screen */
.riddle {
	margin: 20px 0 24px;
	padding: 20px 24px;
	background: var(--band);
	border-left: 6px solid var(--g3);
}
.riddle p:last-child, .riddle ul:last-child, .riddle ol:last-child { margin-bottom: 0; }
.riddle ul, .riddle ol { margin: 0 0 14px; padding-left: 24px; }
.riddle li { margin-bottom: 4px; }

/* ---------------------------------------------------------------- buttons & forms */

.button {
	display: inline-block;
	padding: 12px 22px;
	border: 4px solid var(--g3);
	background: var(--duck);
	color: var(--g3);
	font: 700 14px/1.2 var(--label);
	letter-spacing: .03em;
	text-decoration: none;
	white-space: nowrap;
	cursor: pointer;
	box-shadow: 4px 4px 0 var(--g3);
	touch-action: manipulation;
	transition: transform .08s, box-shadow .08s, background-color .15s;
}
.card a.button { color: var(--g3); }
.button:hover { background: #ffd666; }
.button:active { transform: translate(4px, 4px); box-shadow: none; }
.button.ghost { background: var(--g1); box-shadow: none; }
.button.ghost:hover { background: #bcd88e; }
.button.small { padding: 7px 12px; font-size: 12px; }
.link {
	padding: 0;
	border: 0;
	background: none;
	color: var(--g2);
	font: inherit;
	font-size: 15px;
	text-decoration: underline;
	text-underline-offset: 3px;
	cursor: pointer;
}

.answer { display: flex; gap: 14px; margin-top: 18px; }
.answer input {
	flex: 1;
	min-width: 0;
	padding: 12px 16px;
	border: 4px solid var(--g3);
	background: var(--paper);
	color: var(--g3);
	font: 16px var(--body);
	caret-color: var(--g3);
}
.answer input::placeholder { color: var(--g2); }

/* ---------------------------------------------------------------- title screen */

.title-screen { text-align: center; }
.logo-big {
	margin: 10px 0 6px;
	font-size: clamp(76px, 17vw, 168px);
	line-height: .85;
	color: var(--duck);
	text-shadow: 6px 6px 0 #000;
}
.edition { margin-bottom: 40px; font: 700 13px var(--label); letter-spacing: .05em; color: var(--cab-muted); }
.title-screen .card { max-width: 560px; margin-inline: auto; font-size: 17px; }
.press-start { margin: 24px 0 0; }
.press-start .button { animation: blink 1.4s steps(1) infinite; }
.press-start .button:hover, .press-start .button:focus-visible { animation: none; }
@keyframes blink { 60% { opacity: .55; } }

/* the rubber duck floating on the home pond */
.bobber {
	position: absolute;
	left: 50%;
	top: -6px;
	width: 64px;
	height: 64px;
	margin-left: -32px;
	animation: bob 1.6s steps(2) infinite;
}
@keyframes bob { 50% { transform: translateY(4px); } }

/* ---------------------------------------------------------------- oral & done */

.sprite { width: 64px; height: 64px; margin-bottom: 6px; }
.badge {
	display: inline-block;
	margin: 6px 0 18px;
	padding: 8px 18px;
	background: var(--g3);
	color: var(--duck);
	font: 40px/1 var(--title);
}
.phrase {
	margin: 24px auto;
	padding: 20px 24px;
	max-width: 540px;
	background: var(--duck);
	color: var(--g3);
	border: 4px solid var(--g3);
	box-shadow: 6px 6px 0 var(--g3);
	font: 38px/1.05 var(--title);
}
.phrase.typing::after {
	content: "";
	display: inline-block;
	width: .45em;
	height: .8em;
	margin-left: 4px;
	vertical-align: -.05em;
	background: var(--g3);
	animation: caret .8s steps(1) infinite;
}
@keyframes caret { 50% { opacity: 0; } }
.duck-rain { position: fixed; inset: 0; z-index: 40; overflow: hidden; pointer-events: none; }
.duck-rain img { position: absolute; top: 0; left: 0; width: 40px; height: 40px; will-change: transform; }

/* ---------------------------------------------------------------- exam */

.steps { margin: 0 0 22px; padding-left: 24px; }
.steps li { margin-bottom: 12px; }
.steps pre { margin: 8px 0 0; }
.steps pre code { white-space: pre-wrap; word-break: break-word; }
.steps .button.small { margin-left: 6px; vertical-align: middle; }

/* ---------------------------------------------------------------- admin */

body.wide .card { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; font-size: 15px; }
th, td { padding: 10px; text-align: left; vertical-align: middle; border-bottom: 2px solid var(--g1); }
th { font: 700 11px var(--label); letter-spacing: .04em; color: var(--g2); }
td { font-variant-numeric: tabular-nums; }
tr.claimed td { color: var(--g2); text-decoration: line-through; }
tr.claimed td:last-child { text-decoration: none; }
td form { margin: 0; }
form.inline { display: inline; margin-left: 6px; }
.stage { padding: 2px 8px; font: 700 11px var(--label); background: var(--g1); color: var(--g3); }
.stage.game, .stage.memory { background: var(--duck); }
.stage.exam, .stage.oral { background: var(--g2); color: var(--g0); }
.stage.done { background: var(--g3); color: var(--g0); }

/* ---------------------------------------------------------------- shared game bits */

.game-head, .memory-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; }
.progress { display: flex; gap: 6px; padding-top: 6px; }
.progress span { width: 14px; height: 14px; border: 3px solid var(--g3); background: var(--g0); }
.progress .done { background: var(--g2); }
.progress .current { background: var(--duck); }
.status { min-height: 1.6em; margin: 16px 0 10px; font-weight: 700; text-align: center; }
.status.won { color: var(--g2); }
.status.lost { color: var(--danger); }

.overlay {
	position: fixed;
	inset: 0;
	z-index: 30;
	display: grid;
	place-items: center;
	padding: 16px;
	background: rgba(10, 12, 10, .78);
	overscroll-behavior: contain;
}
.overlay .card { max-width: 460px; width: 100%; margin: 0; text-align: center; }
.big { margin: 0 0 8px; }
.big img { width: 64px; }

/* ---------------------------------------------------------------- logic game */

.game-body {
	display: grid;
	grid-template-columns: minmax(0, 1.25fr) minmax(250px, 1fr);
	gap: 32px;
	margin-top: 10px;
}
.board-wrap { display: flex; flex-direction: column; align-items: center; }
.board {
	position: relative;
	display: grid;
	grid-template-columns: repeat(var(--cols), 1fr);
	grid-template-rows: repeat(var(--rows), 1fr);
	width: min(100%, calc(var(--cols) * 58px));
	aspect-ratio: var(--cols) / var(--rows);
	background:
		radial-gradient(circle at 2px 2px, rgba(224, 240, 200, .12) 1.5px, transparent 2px) 0 0 / 20px 20px,
		var(--g3);
	border: 4px solid var(--g3);
}
.tile { position: relative; margin: 3px; box-shadow: inset 0 -4px 0 rgba(0, 0, 0, .3); transition: background-color .2s; }
.tile.empty { background: transparent; box-shadow: none; }
.tile.red { background: var(--tile-red); }
.tile.green { background: var(--tile-green); }
.tile.blue { background: var(--tile-blue); }
.tile.star::after {
	content: "";
	position: absolute;
	inset: 22%;
	background: url("/static/sprites/star.svg") center / contain no-repeat;
	image-rendering: pixelated;
}
.duck-piece {
	position: absolute;
	top: 0;
	left: 0;
	display: grid;
	place-items: center;
	width: calc(100% / var(--cols));
	height: calc(100% / var(--rows));
	transform: translate(calc(var(--x) * 100%), calc(var(--y) * 100%));
	transition: transform .18s ease-out;
	pointer-events: none;
}
.duck-piece img {
	width: 80%;
	transform: rotate(var(--angle)) scaleY(var(--flip, 1));
	transition: transform .18s ease-out;
	filter: drop-shadow(0 3px 0 rgba(0, 0, 0, .4));
}
.duck-piece.fallen { opacity: .3; }

.controls { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; justify-content: center; }
.speed { display: flex; gap: 8px; align-items: center; color: var(--g2); font: 700 11px var(--label); }
.speed input { width: 90px; accent-color: var(--g3); }

.editor { display: flex; flex-direction: column; gap: 18px; }
.fn { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-bottom: 10px; }
.fn-name { width: 36px; font: 30px/1 var(--title); }
.slot, .op {
	display: inline-grid;
	place-items: center;
	width: 46px;
	height: 46px;
	border: 4px solid var(--g3);
	background: var(--paper);
	color: var(--g3);
	font: 26px/1 var(--title);
	cursor: pointer;
	touch-action: manipulation;
}
/* the pixel icons are drawn light: turn them dark green on the screen */
.slot img, .op img { width: 24px; height: 24px; filter: brightness(0) invert(13%) sepia(30%) saturate(800%) hue-rotate(80deg); }
.op { background: var(--g1); }
.op:hover, .slot:hover { background: #fff; }
.slot.red, .cond.red { background: var(--tile-red); }
.slot.green, .cond.green { background: var(--tile-green); }
.slot.blue, .cond.blue { background: var(--tile-blue); }
.slot.selected { outline: 4px solid var(--duck); outline-offset: 2px; }
.slot.running { box-shadow: 0 0 0 4px var(--duck), 0 0 0 8px var(--g3); }
.paint-red { color: var(--tile-red); }
.paint-green { color: #3d7a22; }
.paint-blue { color: var(--tile-blue); }
.cond.any { color: var(--g2); }
.palette { padding: 16px 18px; background: var(--band); border: 4px solid var(--g3); }
.palette .label { margin: 0 0 10px; font: 700 11px var(--label); letter-spacing: .04em; color: var(--g2); }
.ops { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 14px; }
.ops[hidden], .label[hidden] { display: none; }

/* ---------------------------------------------------------------- memory game */

.round { margin: 0; font: 30px/1 var(--title); }
.pads {
	display: grid;
	grid-template-columns: repeat(var(--grid), 1fr);
	gap: 12px;
	width: min(100%, 380px);
	margin: 18px auto 0;
	padding: 16px;
	background:
		radial-gradient(circle at 2px 2px, rgba(224, 240, 200, .12) 1.5px, transparent 2px) 0 0 / 20px 20px,
		var(--g3);
	border: 4px solid var(--g3);
}
.pad {
	position: relative;
	aspect-ratio: 1;
	border: 0;
	border-radius: 50%;
	background: var(--tile-green);
	box-shadow: inset 0 -5px 0 rgba(0, 0, 0, .3);
	cursor: pointer;
	touch-action: manipulation;
	transition: transform .1s;
}
/* the notch of a lily pad */
.pad::before {
	content: "";
	position: absolute;
	top: 50%;
	right: 6%;
	width: 26%;
	height: 10%;
	background: var(--g3);
	transform: rotate(-25deg);
}
.pad:disabled { cursor: default; }
.pad:not(:disabled):hover { transform: scale(1.05); }
.pad.lit { box-shadow: 0 0 0 4px var(--duck); }
.pad.lit::after {
	content: "";
	position: absolute;
	inset: 12%;
	background: url("/static/sprites/duck.svg") center / contain no-repeat;
	image-rendering: pixelated;
}
.pad.pressed { background: var(--duck); }
#start[hidden] { display: none; }

/* ---------------------------------------------------------------- hidden ducks */

.hints { margin: 18px 0; padding-left: 26px; }
.hints li { margin-bottom: 10px; padding: 10px 14px; background: var(--band); border-left: 6px solid var(--g3); }
.hints li.found { opacity: .65; border-left-color: var(--g1); }
.hints li.found .hint-text { text-decoration: line-through; }
.found-tag { margin-left: 10px; padding: 1px 8px; font: 700 11px var(--label); background: var(--g3); color: var(--g0); }
.tally { font: 30px/1.1 var(--title); }

/* ---------------------------------------------------------------- small screens */

@media (max-width: 860px) {
	.top { padding: 10px 16px; }
	.logo span { display: none; }
	.player { gap: 16px; font-size: 14px; }
	.layout { padding: 22px 16px 48px; }
	body.quest .layout { grid-template-columns: 1fr; gap: 26px; }
	/* the quest log becomes a level path */
	.quest { position: static; }
	.quest h2, .quest .side { display: none; }
	.quest ol { display: flex; gap: 6px; border: 0; overflow-x: auto; }
	.quest li { flex: 1 0 auto; padding: 32px 0 0; text-align: center; }
	.quest li::before { left: 50%; top: 0; margin-left: -12px; }
	.quest .name { font-size: 20px; }
	.card { padding: 22px 18px; box-shadow: 0 0 0 4px var(--cab-line), 6px 6px 0 4px #000; }
	.card h1 { font-size: 44px; }
	.answer { flex-direction: column; }
	.game-body { grid-template-columns: 1fr; }
	.game-head { flex-direction: column; }
	.phrase { font-size: 30px; }
}
@media (max-width: 420px) {
	.player span { display: none; }
}

@media (prefers-reduced-motion: reduce) {
	*, *::before, *::after { animation: none !important; transition: none !important; }
}
