*, *::before, *::after { box-sizing: border-box; }

/*
 * The page does not rubber-band, and it does not pull to refresh. The game is a
 * board on a table: a drag that runs past the end of the page and springs the
 * whole thing back reads as a fault, and a downward drag that reloads mid-game
 * is worse. Scrolling itself is untouched — the chat is deliberately below the
 * fold — this refuses only the overscroll past either end.
 *
 * It has to be on the root, since that is the element whose used value the
 * viewport takes; body is here because Chrome will read it there too. iOS Safari
 * honours it from 16, and 15 still bounces: the only way to stop that one is to
 * pin the body and rebuild the scrolling by hand, which is not worth a bounce.
 */
html, body { overscroll-behavior: none; }

body {
	margin: 0;
	background: var(--surface);
	color: var(--ink);
	font: var(--step-0)/1.5 var(--font);
	/* Stops iOS bumping the text size up when the phone is turned sideways. */
	-webkit-text-size-adjust: 100%;
	/* The board is tapped constantly; the browser's double-tap-to-zoom delay
	   would make every placement feel sluggish. */
	touch-action: manipulation;
}

h1, h2, h3, p, ul, ol { margin: 0; }
ul, ol { padding: 0; list-style: none; }

button {
	font: inherit;
	color: inherit;
	background: none;
	border: 0;
	cursor: pointer;
	/*
	 * No borrowed tap flash. A mobile browser paints its own translucent cyan over
	 * whatever a finger touches, which on a cream tile reads as the tile having
	 * turned a different colour. Every button here says for itself that it has
	 * been pressed — a tile lifts, a square lights up.
	 */
	-webkit-tap-highlight-color: transparent;
}

button:disabled { cursor: default; }

input, select {
	font: inherit;
	color: inherit;
}

/*
 * Nothing on this page is text to be selected, and what is typed into a field is
 * the exception rather than the rule.
 *
 * Every gesture here is a drag or a tap — a tile onto a square, a tile along the
 * rack, a double-tap for a close-up, a letter pressed over and over on the code
 * pad — and a press a browser does not otherwise recognise is answered by
 * starting a selection: the tile that will not move because the letter under it
 * is being highlighted instead, and the blue smear left across half the board
 * behind it. So this is one refusal over the whole page. Declared on each thing
 * that turned out to need it, it is a rule that is only ever as complete as the
 * last fault somebody noticed.
 *
 * The fields have to say so for themselves rather than being left to the cascade.
 * A WebKit reached by an ancestor's `none` puts the caret out of reach of a tap
 * inside the field, which on the dictionary's search box is a panel that cannot
 * be typed into.
 *
 * What it gives up is copying a word's meaning out of the panel that prints it,
 * and copying the room code. The code is read out or handed over as a link, which
 * is what Share link beside it is for, and it could not be copied usefully in any
 * case: the code is one tile a letter and the tiles are flex items, so each is
 * blockified and a selection over the row serialises as five lines rather than as
 * a code. Making it selectable means laying that row out as inline-blocks first.
 */
body {
	user-select: none;
	-webkit-user-select: none;
}

input {
	user-select: text;
	-webkit-user-select: text;
}

/* Visible focus everywhere, since the board is fully keyboard navigable. */
:focus-visible {
	outline: 3px solid var(--accent);
	outline-offset: 2px;
}

[hidden] { display: none !important; }
