/*
 * Chrome, layout, and every board rule.
 *
 * The colours are named here because the stylesheet is where a fixed palette
 * belongs. A block's colour comes from the level rather than from a class, so
 * js/ui/palette.js points --block at one of them per element; gates are picked
 * by name the same way.
 *
 * Board metrics are all calc() off --step, the one number BoardView measures.
 */

:root {
	--bg: #161a21;
	--surface: #1f242e;
	--surface-lit: #262d39;
	--frame-colour: #2f3745;
	--well-colour: #12161d;
	--cell-colour: #212734;
	--wall-colour: #3b4453;

	--ink: #e9eef6;
	--ink-soft: #98a3b5;
	--ink-faint: #5b6474;
	--edge: #333c4b;
	--focus: #8ab4f8;

	--colour-red: #e8534b;
	--colour-blue: #3f8ede;
	--colour-green: #41ab63;
	--colour-yellow: #e5b036;
	--colour-purple: #9a6ede;
	--colour-orange: #ef8a3c;
	--colour-teal: #2fb0aa;
	--colour-pink: #e076ad;

	--radius-control: 12px;
	--radius-card: 20px;

	color-scheme: dark;
}

* {
	box-sizing: border-box;
}

html,
body {
	height: 100%;
	margin: 0;
}

body {
	background: var(--bg);
	color: var(--ink);
	font-family: ui-rounded, "SF Pro Rounded", "Segoe UI Variable Display", system-ui,
		-apple-system, "Helvetica Neue", sans-serif;
	font-size: clamp(0.95rem, 3.4vw, 1.05rem);
	line-height: 1.35;
	/* No rubber-banding and no double-tap zoom: this is a board you tap, not a
	   document you scroll. */
	overscroll-behavior: none;
	touch-action: manipulation;
	-webkit-text-size-adjust: 100%;
}

#app {
	position: relative;
	width: 100%;
	max-width: 30rem;
	height: 100%;
	margin-inline: auto;
}

.screen {
	position: absolute;
	inset: 0;
	display: flex;
	flex-direction: column;
	padding: max(0.75rem, env(safe-area-inset-top)) 0.875rem
		max(0.75rem, env(safe-area-inset-bottom));
}

.screen[hidden] {
	display: none;
}

/* --- Controls ------------------------------------------------------------- */

button {
	min-height: 3rem;
	padding: 0.5rem 1rem;
	border: 1px solid var(--edge);
	border-radius: var(--radius-control);
	background: var(--surface);
	color: var(--ink);
	font: inherit;
	font-weight: 600;
	cursor: pointer;
	-webkit-user-select: none;
	user-select: none;
	transition: background-color 90ms ease-out, border-color 90ms ease-out;
}

button.primary {
	min-height: 3.5rem;
	border-color: transparent;
	background: var(--ink);
	color: var(--bg);
	font-size: 1.05em;
}

button.ghost {
	border-color: transparent;
	background: none;
	color: var(--ink-soft);
	font-weight: 500;
}

/*
 * Chrome only. A board block is a button for what it does -- one press, one move
 * -- and not for how it looks, so the panel background and the press nudge have
 * to be kept off it. Left in, the hover background paints over the block's whole
 * bounding box, which on an L is the hollow as well, and the nudge fights the
 * inline translate the slide is animating.
 */
@media (hover: hover) {
	button:hover:not(:disabled, .block) {
		background: var(--surface-lit);
		border-color: #3f4a5c;
	}

	button.primary:hover:not(:disabled) {
		background: #ffffff;
	}
}

button:active:not(:disabled, .block) {
	translate: 0 1px;
}

button:focus-visible {
	outline: 2px solid var(--focus);
	outline-offset: 2px;
}

button:disabled {
	color: var(--ink-faint);
	cursor: default;
}

/* --- Menu ---------------------------------------------------------------- */

.menu {
	overflow-y: auto;
}

.menu-inner {
	display: flex;
	flex-direction: column;
	gap: 0.7rem;
	width: 100%;
	margin-block: auto;
	padding-block: 1rem;
	text-align: center;
}

.mark {
	width: min(42vw, 9.5rem);
	height: auto;
	margin-inline: auto;
}

.menu h1 {
	margin: 0;
	font-size: clamp(2rem, 9vw, 2.5rem);
	font-weight: 700;
	letter-spacing: -0.01em;
}

.subtitle {
	margin: 0 0 0.4rem;
	color: var(--ink-soft);
	text-wrap: balance;
}

.section-title {
	margin: 0.6rem 0 0;
	color: var(--ink-soft);
	font-size: 0.85em;
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
}

/* Three ways onto the ladder, three across a phone. */
.difficulty {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 0.4rem;
}

.difficulty button {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 0.1rem;
	padding: 0.5rem 0.375rem;
}

/* Inherits its colour, so it follows the button through hover and press. */
.difficulty .level {
	font-size: 0.8em;
	line-height: 1.2;
	opacity: 0.85;
}

/* --- Game screen --------------------------------------------------------- */

.game {
	gap: 0.5rem;
}

.header-row {
	display: flex;
	align-items: center;
	gap: 0.5rem;
}

.header-row .ghost {
	min-height: 2.5rem;
	padding-inline: 0.5rem;
	margin-left: -0.5rem;
}

.level-name {
	flex: 1;
	overflow: hidden;
	font-weight: 600;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.moves {
	color: var(--ink-soft);
	font-variant-numeric: tabular-nums;
}

.board-area {
	display: grid;
	flex: 1;
	min-height: 0;
	place-items: center;
}

.bottom-bar {
	display: flex;
	flex-direction: column;
	gap: 0.4rem;
}

.progress {
	display: flex;
	justify-content: center;
	gap: 0.7rem;
	margin: 0;
	color: var(--ink-soft);
	text-align: center;
	font-variant-numeric: tabular-nums;
}

.status {
	min-height: 2.4em;
	margin: 0;
	color: var(--colour-yellow);
	text-align: center;
	text-wrap: pretty;
	font-size: 0.85em;
}

.toolbar {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 0.5rem;
}

/* --- The board ----------------------------------------------------------- */

.board {
	--pad: calc(var(--step) * 0.05);
	--tile-radius: calc(var(--step) * 0.2);
	position: relative;
	box-sizing: content-box;
	width: calc(var(--cols) * var(--step));
	height: calc(var(--rows) * var(--step));
	border: var(--frame) solid var(--frame-colour);
	border-radius: calc(var(--frame) + var(--tile-radius));
	background: var(--well-colour);
	-webkit-user-select: none;
	user-select: none;
	-webkit-tap-highlight-color: transparent;
	/* iOS raises a selection callout on a long press, and a long press here is
	   just a slow tap. */
	-webkit-touch-callout: none;
}

.grid {
	position: absolute;
	inset: 0;
	display: grid;
	grid-template-columns: repeat(var(--cols), var(--step));
	grid-template-rows: repeat(var(--rows), var(--step));
}

.cell {
	position: relative;
}

.cell::before {
	content: "";
	position: absolute;
	inset: var(--pad);
	border-radius: var(--tile-radius);
	background: var(--cell-colour);
}

.cell.is-wall::before {
	background: var(--wall-colour);
	background-image: repeating-linear-gradient(
		45deg,
		rgb(0 0 0 / 22%) 0 3px,
		transparent 3px 7px
	);
}

/*
 * The frame is drawn under the blocks, so an escaping block crosses it on the
 * way out. The gates sit above, which makes the block pass through the mouth
 * rather than over it.
 */
.gates {
	position: absolute;
	inset: calc(-1 * var(--frame));
	z-index: 3;
	pointer-events: none;
}

.gate {
	position: absolute;
	background: var(--gate);
	box-shadow: inset 0 0 0 1px rgb(0 0 0 / 20%);
}

.gate.side-up {
	border-radius: calc(var(--frame) * 0.4) calc(var(--frame) * 0.4) 0 0;
}

.gate.side-down {
	border-radius: 0 0 calc(var(--frame) * 0.4) calc(var(--frame) * 0.4);
}

.gate.side-left {
	border-radius: calc(var(--frame) * 0.4) 0 0 calc(var(--frame) * 0.4);
}

.gate.side-right {
	border-radius: 0 calc(var(--frame) * 0.4) calc(var(--frame) * 0.4) 0;
}

.blocks {
	position: absolute;
	inset: 0;
	z-index: 2;
}

/*
 * The button is the block's bounding box, so for an L or a T it covers squares
 * the block does not stand on. Only the tiles take the pointer, which leaves the
 * hollow open: a block parked in it can be tapped, and passing over it is not
 * hovering the L. The button still knows it is being hovered or pressed, because
 * both states propagate up from the tile that took the pointer.
 */
.block {
	pointer-events: none;
	position: absolute;
	left: calc(var(--col) * var(--step));
	top: calc(var(--row) * var(--step));
	width: calc(var(--w) * var(--step));
	height: calc(var(--h) * var(--step));
	min-height: 0;
	padding: 0;
	border: 0;
	border-radius: 0;
	background: none;
	transition-property: translate, opacity;
	transition-timing-function: cubic-bezier(0.32, 0.72, 0.3, 1);
	transition-duration: 0ms;
}

/* A block that has left the board is still in the DOM until its exit finishes. */
.block:disabled .tile {
	pointer-events: none;
}

.block:focus-visible {
	outline: 2px solid var(--focus);
	outline-offset: 1px;
}

/*
 * One element per cell. A side shared with another cell of the same block gets
 * no inset, so neighbouring tiles meet and the block reads as one piece.
 *
 * Flat colour, because the tile is the unit that gets painted but the block is
 * what the eye reads. Any shading across a tile restarts at every cell, so a
 * block shows a seam wherever two of its cells meet, and an L shows the ramp
 * running two different ways either side of its corner.
 */
.tile {
	pointer-events: auto;
	position: absolute;
	left: calc(var(--c) * var(--step) + var(--pl));
	top: calc(var(--r) * var(--step) + var(--pt));
	width: calc(var(--step) - var(--pl) - var(--pr));
	height: calc(var(--step) - var(--pt) - var(--pb));
	background: var(--block);
}

.arrow {
	position: absolute;
	left: calc(var(--c) * var(--step) + var(--step) * 0.5);
	top: calc(var(--r) * var(--step) + var(--step) * 0.5);
	width: calc(var(--step) * 0.42);
	height: calc(var(--step) * 0.42);
	translate: -50% -50%;
	fill: rgb(255 255 255 / 88%);
	pointer-events: none;
}

@media (hover: hover) {
	.block:hover .tile {
		filter: brightness(1.12);
	}
}

.block:active .tile {
	filter: brightness(0.94);
}

/* A block with nowhere to go says so rather than doing nothing. */
@keyframes nudge {
	0%,
	100% {
		rotate: 0deg;
	}

	25% {
		rotate: -1.8deg;
	}

	60% {
		rotate: 1.8deg;
	}

	85% {
		rotate: -0.7deg;
	}
}

.block.is-stuck {
	animation: nudge 230ms ease-in-out;
}

/* --- Overlays ------------------------------------------------------------ */

.overlay {
	position: absolute;
	inset: 0;
	z-index: 4;
	display: grid;
	place-items: center;
	padding: 1.25rem;
	background: rgb(12 15 20 / 72%);
}

.overlay[hidden] {
	display: none;
}

.card {
	display: flex;
	flex-direction: column;
	gap: 0.75rem;
	width: 100%;
	padding: 1.75rem;
	border: 1px solid var(--edge);
	border-radius: var(--radius-card);
	background: var(--surface);
	text-align: center;
}

.card h2 {
	margin: 0;
	font-size: clamp(1.6rem, 7vw, 2.1rem);
	font-weight: 700;
}

/* The board is still being found, so there is nothing behind this to look at. */
#finding-panel .card {
	max-width: 20rem;
}

#finding-detail {
	margin: 0;
}

#result-detail {
	margin: 0 0 0.5rem;
	color: var(--ink-soft);
	font-variant-numeric: tabular-nums;
}

#next-button[hidden] {
	display: none;
}

@media (prefers-reduced-motion: reduce) {
	button,
	.block {
		transition: none;
	}

	.block.is-stuck {
		animation: none;
	}
}
