/*=== Sort Order ===============================================================
The game's looks: a post office back room (see docs/prototype-plan.md, The look). Dim walls for the page, cream paper
for the cards and the labels, kraft cardboard on a steel sorting table studded with rollers, squat steel machines with
hazard stripes, salmon for the stamps and the red pen, fern for what's done. A slab face like a rubber stamp for the title, the keys and the names on the labels; the
series' mono for the rest. The palette is palette.css's, written from palette.js; it is mapped onto the chassis's
tokens (core/style/base.css) first, so its lobby, cards and keys take it; the shift's screen and the report follow */

:root {
	color-scheme: light;

	--font: "IBM Plex Mono", "Courier New", Courier, monospace;
	--slab: "Alfa Slab One", Georgia, serif; /* The title, the keys, the names on the labels */
	--display-font: var(--slab);
	--display-weight: 400; /* The slab has one weight */

	/* The chassis's tokens */
	--bg: var(--backroom);
	--plate: var(--paper-2);
	--field: var(--paper-3);
	--key: var(--paper-2);
	--border: var(--ink);
	--text: var(--ink);
	--muted: var(--ink-2);
	--accent: var(--slate);
	--accent-text: var(--paper-2);
	--primary-border: var(--ink);
	--select: var(--slate);
	--select-wash: color-mix(in srgb, var(--slate) 16%, transparent);
	--select-text: var(--slate-dark);
	--focus: var(--salmon);
	--shadow-color: var(--shade);
	--radius: 6px;
}

.title_accent {
	color: var(--salmon-dark);
}

.report_title,
.report_verdict,
.shift_day,
.shift_clock {
	font-family: var(--slab);
	font-weight: 400;
}


/*=== The shift's screen =======================================================*/

/* The play area: the shape of a phone, as big as fits, and never stretched. Everything in it is sized in cqw, a
hundredth of its width, so it all scales together. The page's margins shrink while it's up, to give it the room */
#app:has(> #screen_shift:not(.hidden)) {
	padding: calc(6px + var(--safe-top)) calc(6px + var(--safe-right)) calc(6px + var(--safe-bottom)) calc(6px + var(--safe-left));
}

#screen_shift {
	flex: none;
	align-self: center;
	width: min(100%, 430px, calc((100dvh - 12px - var(--safe-top) - var(--safe-bottom)) * 9 / 17));
	aspect-ratio: 9 / 17;
	container-type: size;
	position: relative;
	gap: 6px;
	user-select: none;
	-webkit-user-select: none;
	touch-action: none;
}

.shift_bar {
	display: flex;
	align-items: center;
	gap: 2.5cqw;
	padding-bottom: 1cqw;
	border-bottom: 2px solid var(--ink);
}

.shift_day {
	font-size: 4.6cqw;
}

.shift_clock {
	font-size: 5.6cqw;
	font-variant-numeric: tabular-nums;
	color: var(--ink);
}

.shift_count {
	flex: 1;
	min-width: 0;
	font-size: 3cqw;
	color: var(--ink);
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

.shift_bar .button {
	flex: none;
}

.shift_notice {
	position: absolute;
	inset: auto 0 0;
	z-index: 10;
	margin: 0;
	padding: 1cqw;
	background: var(--paper-2);
	font-size: 3cqw;
	color: var(--salmon-dark);
	text-align: center;
}


/*=== The sorting table ========================================================*/

/* The table fills the rest of the play area: the steel top the parcels slide on, the chute lying across its top edge,
the machines in a row along its bottom. It clips what goes under the chute out of sight; the parcels are drawn over
the machines (one carried onto one is above it) and under the chute */
.table {
	--chute-h: 15cqw;
	--machines-h: 28cqw;
	position: relative;
	flex: 1;
	min-height: 0;
	overflow: hidden;
	background: var(--steel-dark);
	border: 2px solid var(--silver-dark);
}

/* A shelf of soft brushed silver, as Jelly Cleave's tray: lit from above, two faint streaks of light across it, a
darker rim, and short rollers pressed into it in staggered rows: a heavy parcel rides them, and they grip */
.floor {
	position: absolute;
	inset: 0 0 var(--machines-h);
	z-index: 1;
	--roller: radial-gradient(ellipse 1.6cqw 0.45cqw, color-mix(in srgb, var(--silver-dark) 40%, transparent) 0 70%, transparent 100%);
	background-color: var(--silver);
	background-image:
		var(--roller),
		var(--roller),
		linear-gradient(150deg, transparent 30%, var(--sheen) 38%, transparent 46%, transparent 56%, var(--sheen) 60%, transparent 64%),
		repeating-linear-gradient(90deg, transparent 0 0.6cqw, color-mix(in srgb, var(--silver-light) 35%, transparent) 0.6cqw 0.8cqw),
		linear-gradient(180deg, var(--silver-light), var(--silver) 50%, var(--silver-low));
	background-size: 12cqw 6cqw, 12cqw 6cqw, auto, auto, auto;
	background-position: 0 0, 6cqw 3cqw, 0 0, 0 0, 0 0;
	box-shadow: inset 0 0 0 1.2cqw var(--silver-dark), inset 0 0 0 calc(1.2cqw + 1px) var(--silver-light), inset 0 -1cqw 1.5cqw var(--shade);
}

/* A copy of a parcel going into a machine or under the chute: not in the way */
.ghost {
	position: absolute;
	left: 0;
	top: 0;
	z-index: 50;
	pointer-events: none;
}

/* One going under the chute: on the table, over the floor and under the chute */
.ghost_under {
	z-index: 2;
}


/*=== The chute up =============================================================*/

/* A heavy banner across the top of the table, the chute behind it: anything pushed under it goes to the co-worker,
and what they send comes out from under it. Hazard stripes along its bottom edge */
.chute {
	position: absolute;
	inset: 0 0 auto;
	z-index: 3;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	height: var(--chute-h);
	padding-bottom: 2cqw;
	background: linear-gradient(180deg, var(--ink) 0%, var(--steel-dark) 100%);
	color: var(--paper-2);
	box-shadow: 0 1cqw 1.5cqw var(--shade);
	transition: filter var(--snap);
}

.chute::after {
	content: "";
	position: absolute;
	inset: auto 0 0;
	height: 1.6cqw;
	background: repeating-linear-gradient(-45deg, var(--salmon) 0 2cqw, var(--ink) 2cqw 4cqw);
}

.chute_title {
	position: relative;
	font-family: var(--slab);
	font-size: 4.4cqw;
	letter-spacing: 0.3cqw;
}

.chute_title span {
	font-size: 2.6cqw;
	opacity: 0.7;
}

.chute_partner {
	position: relative;
	max-width: 92%;
	font-size: 2.6cqw;
	opacity: 0.8;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}


/*=== Parcels ==================================================================*/

/* The element is where the floor puts it (left and top 0, moved by translate); its body is the look, tilted */
.parcel {
	--pw: 20cqw;
	--ph: 14cqw;
	position: absolute;
	left: 0;
	top: 0;
	width: var(--pw);
	height: var(--ph);
	cursor: grab;
	touch-action: none;
}

.parcel_body {
	position: absolute;
	inset: 0;
	rotate: var(--tilt, 0deg);
	border-radius: 1cqw;
	box-shadow: 0.5cqw 0.8cqw 0 var(--shade);
	transition: rotate 160ms, scale 160ms, box-shadow 160ms;
}

.parcel.carried {
	z-index: 900;
	cursor: grabbing;
}

.parcel.carried .parcel_body {
	rotate: 0deg;
	scale: 1.08;
	box-shadow: 1.5cqw 2.6cqw 3.6cqw var(--shade);
}

/* A box: kraft, a band of tape down the middle where it was sealed */
.parcel.box .parcel_body {
	background:
		linear-gradient(90deg, transparent 43%, var(--kraft-light) 43% 57%, transparent 57%),
		var(--kraft);
	border: 2px solid var(--kraft-dark);
}

.parcel.box.size_0 { --pw: 18cqw; --ph: 13cqw; }
.parcel.box.size_1 { --pw: 20.5cqw; --ph: 14.5cqw; }
.parcel.box.size_2 { --pw: 23cqw; --ph: 16cqw; }

/* Crushed: a dent in the corners, and a crease across */
.parcel.box.crushed .parcel_body {
	clip-path: polygon(0 10%, 16% 0, 58% 7%, 100% 0, 95% 52%, 100% 100%, 42% 93%, 0 100%, 5% 55%);
	background:
		linear-gradient(160deg, transparent 47%, var(--kraft-dark) 48% 50%, transparent 51%),
		linear-gradient(90deg, transparent 43%, var(--kraft-light) 43% 57%, transparent 57%),
		var(--kraft);
}

/* A letter: an envelope, its flap drawn in */
.parcel.letter {
	--pw: 18cqw;
	--ph: 11.5cqw;
}

.parcel.letter .parcel_body {
	background:
		linear-gradient(155deg, transparent 49%, var(--paper-3) 50% 51%, transparent 52%) top left / 50% 60% no-repeat,
		linear-gradient(205deg, transparent 49%, var(--paper-3) 50% 51%, transparent 52%) top right / 50% 60% no-repeat,
		var(--envelope);
	border: 1.5px solid var(--ink-2);
	border-radius: 0.5cqw;
}

/* A mail bag: a sack, a tie at the neck, its tag */
.parcel.bag {
	--pw: 18cqw;
	--ph: 16cqw;
}

.parcel.bag .parcel_body {
	background: var(--slate-light);
	border: 2px solid var(--slate-dark);
	border-radius: 3.5cqw 3.5cqw 40% 40% / 3.5cqw 3.5cqw 30% 30%;
}

.bag_neck {
	position: absolute;
	top: -1.5cqw;
	left: 50%;
	width: 6.5cqw;
	height: 2.5cqw;
	translate: -50% 0;
	background: var(--slate-dark);
	border-radius: 1cqw;
}

.bag_tag {
	position: absolute;
	inset: 3cqw 2cqw auto;
	display: flex;
	flex-direction: column;
	align-items: center;
	padding: 0.6cqw 0.4cqw;
	background: var(--fern-light);
	border: 1.5px solid var(--fern);
	border-radius: 0.8cqw;
	line-height: 1.1;
	text-align: center;
}

.bag_count {
	font-size: 2cqw;
	letter-spacing: 0.1cqw;
}

/* The label: one word, who it's for, sized to fit the smallest parcel's longest name */
.parcel_label {
	position: absolute;
	left: 50%;
	top: 22%;
	translate: -50% 0;
	max-width: 94%;
	padding: 0.5cqw 0.9cqw;
	background: var(--paper-2);
	border: 1px solid var(--ink-2);
	border-radius: 0.5cqw;
	line-height: 1.1;
	pointer-events: none;
}

.parcel.letter .parcel_label {
	top: 34%;
	background: transparent;
	border: none;
}

.label_name {
	display: block;
	font-family: var(--slab);
	font-size: 3cqw;
	white-space: nowrap;
}

.parcel:has(.mark.pen) .label_name {
	text-decoration: underline wavy var(--salmon-dark);
}

/* A letter's round, as a postmark: the letters on one round go in one bag */
.postmark {
	position: absolute;
	left: 1cqw;
	top: 0.8cqw;
	width: 4.4cqw;
	height: 4.4cqw;
	display: grid;
	place-items: center;
	border: 0.5cqw solid var(--round);
	border-radius: 50%;
	color: var(--round);
	font-family: var(--slab);
	font-size: 2.6cqw;
	line-height: 1;
	rotate: -12deg;
}

.round_A { --round: var(--salmon-dark); }
.round_B { --round: var(--fern); }
.round_C { --round: var(--slate); }
.round_D { --round: var(--kraft-dark); }

/* What's been done to it */
.mark {
	position: absolute;
	pointer-events: none;
	font-size: 2cqw;
	line-height: 1;
}

.mark.stamp {
	top: 1cqw;
	right: 0.8cqw;
	width: 3.8cqw;
	height: 4.6cqw;
	display: grid;
	place-items: center;
	background: var(--salmon);
	color: var(--paper-2);
	outline: 0.5cqw dotted var(--paper-2);
	outline-offset: -0.8cqw;
	font-size: 2.3cqw;
}

.mark.weight {
	right: 0.8cqw;
	bottom: 1cqw;
	padding: 0.5cqw 0.8cqw;
	background: var(--paper-2);
	border: 1px solid var(--ink);
	font-weight: 700;
}

.mark.pen {
	left: 1.5cqw;
	bottom: 1cqw;
	color: var(--salmon-dark);
	font-style: italic;
	font-weight: 700;
	font-size: 2.3cqw;
}

.mark.customs {
	left: 50%;
	bottom: 0.8cqw;
	translate: -50% 0;
	padding: 0.5cqw 0.8cqw;
	background: var(--fern);
	color: var(--paper-2);
	font-weight: 700;
	letter-spacing: 0.1cqw;
}

.parcel:has(.mark.weight) .mark.customs {
	left: 38%;
}

.mark.tape {
	left: -1cqw;
	right: -1cqw;
	top: 46%;
	height: 2.8cqw;
	background: var(--tape);
	rotate: -10deg;
	border-top: 1px solid var(--kraft-light);
	border-bottom: 1px solid var(--kraft-light);
}

.mark.returned {
	left: 50%;
	top: 70%;
	translate: -50% -50%;
	rotate: -10deg;
	padding: 0.5cqw 1cqw;
	border: 0.5cqw solid var(--salmon);
	color: var(--salmon);
	background: color-mix(in srgb, var(--paper-2) 55%, transparent);
	font-family: var(--slab);
	font-size: 2.5cqw;
	letter-spacing: 0.2cqw;
	white-space: nowrap;
}


/*=== The machines =============================================================*/

/* Squat steel boxes in a row along the bottom of the table, left to right, the scanner and the shipper wider than the
rest, spaced evenly along it: a hopper mouth along the top with hazard stripes, where a parcel goes in; a riveted name
plate; a display of what's inside, the machine's mark faint behind it; a strip of lights that fill as it works. A
parcel let go on one, or that runs into it hard enough, goes in if it will take it; past the end of the row is wall */
.machines {
	position: absolute;
	inset: auto 0 0;
	z-index: 0;
	display: flex;
	align-items: flex-end;
	justify-content: space-evenly;
	gap: 0.8cqw;
	height: var(--machines-h);
	padding: 0 0.8cqw;
	background: repeating-linear-gradient(-45deg, var(--steel-dark) 0 2cqw, var(--ink) 2cqw 4cqw);
}

.slot {
	--accent: var(--steel-dark);
	position: relative;
	flex: none;
	width: 19cqw;
	height: 100%;
	display: flex;
	flex-direction: column;
	align-items: stretch;
	gap: 0.8cqw;
	padding: 0 1.2cqw 1.2cqw;
	background:
		radial-gradient(circle, var(--steel-dark) 0 0.45cqw, transparent 0.55cqw) 0.9cqw calc(100% - 0.9cqw) / 1cqw 1cqw no-repeat,
		radial-gradient(circle, var(--steel-dark) 0 0.45cqw, transparent 0.55cqw) calc(100% - 0.9cqw) calc(100% - 0.9cqw) / 1cqw 1cqw no-repeat,
		linear-gradient(180deg, var(--steel-light) 0%, var(--steel) 35%, var(--steel) 80%, var(--steel-dark) 100%);
	color: var(--ink);
	border: 0.6cqw solid var(--steel-dark);
	border-bottom: none;
	box-shadow: inset 0 0.5cqw 0 color-mix(in srgb, var(--paper-2) 30%, transparent);
	transition: filter var(--snap);
}

.slot_scanner,
.slot_chute {
	width: 28cqw;
}

.slot_scanner { --accent: var(--slate); }
.slot_chute { --accent: var(--fern); }
.slot_bagger { --accent: var(--kraft-dark); }

/* The hopper: the dark mouth along the top, striped round its lip */
.slot_mouth {
	height: 3.2cqw;
	margin: 0 -1.2cqw;
	background:
		linear-gradient(180deg, var(--ink) 0 55%, transparent 55%),
		repeating-linear-gradient(-45deg, var(--salmon) 0 1.4cqw, var(--ink) 1.4cqw 2.8cqw);
	border-bottom: 0.4cqw solid var(--steel-dark);
}

/* The name plate, its colour the machine's: the scanner slate, the shipper fern */
.slot_plate {
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 0.4cqw 0.4cqw;
	background: var(--accent);
	color: var(--paper-2);
	border: 1px solid var(--steel-dark);
	min-width: 0;
}

.slot_name {
	min-width: 0;
	font-family: var(--slab);
	font-size: 3cqw;
	white-space: nowrap;
	overflow: hidden;
	text-overflow: ellipsis;
}

/* The display: what's inside, in a dark window, the machine's mark big and faint behind it (fainter while it has
something to show) */
.slot_display {
	position: relative;
	flex: 1;
	min-height: 0;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	align-content: center;
	justify-content: center;
	gap: 0.4cqw;
	padding: 0.4cqw;
	background: var(--ink);
	color: var(--fern-light);
	border: 0.4cqw solid var(--steel-dark);
	overflow: hidden;
	font-size: 2.6cqw;
	text-align: center;
}

.slot_display::before {
	content: attr(data-glyph);
	position: absolute;
	inset: 0;
	display: grid;
	place-items: center;
	font-size: 8cqw;
	line-height: 1;
	opacity: 0.4;
	pointer-events: none;
}

.slot_display:has(> :not(.slot_empty))::before {
	opacity: 0.12;
}

.slot_display > * {
	position: relative;
}

.slot_empty {
	opacity: 0.45;
}

.slot_doing {
	font-family: var(--slab);
	font-size: 3cqw;
	white-space: nowrap;
}

.slot.working .slot_doing {
	animation: working 600ms ease-in-out infinite alternate;
}

@keyframes working {
	to { opacity: 0.5; }
}

/* The lights: they fill as the machine works */
.slot_bar {
	height: 1.4cqw;
	background: var(--ink);
	border: 1px solid var(--steel-dark);
}

.slot_fill {
	display: block;
	height: 100%;
	width: calc(var(--progress, 0) * 100%);
	background: repeating-linear-gradient(90deg, var(--fern-light) 0 1.2cqw, transparent 1.2cqw 1.6cqw);
}

/* A letter in the bagger, on its display: drag it back out to the table */
.held {
	padding: 0.2cqw 0.6cqw;
	background: var(--envelope);
	color: var(--ink);
	border-left: 0.8cqw solid var(--round, var(--ink-2));
	cursor: grab;
	touch-action: none;
	white-space: nowrap;
	font-size: 2cqw;
}

.held.carried {
	position: relative;
	z-index: 100;
	cursor: grabbing;
	box-shadow: 0.8cqw 1.2cqw 2cqw var(--shade);
}

.slot_seal {
	padding: 0.3cqw 0;
	background: var(--fern);
	color: var(--paper-2);
	border: 1px solid var(--steel-dark);
	font-family: var(--slab);
	font-size: 2.4cqw;
	cursor: pointer;
}

.slot_seal:disabled {
	opacity: var(--disabled);
	cursor: default;
}


/*=== The readout ==============================================================*/

.readout {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	align-content: center;
	gap: 1cqw 2cqw;
	height: 12cqw;
	padding: 1cqw 2.5cqw;
	background: var(--paper-2);
	border: 2px solid var(--ink-2);
	border-radius: 1.5cqw;
	font-size: 3cqw;
	overflow: hidden;
}

.readout:empty::before {
	content: attr(data-empty);
	color: var(--muted);
	font-size: 2.8cqw;
}

.readout.on {
	animation: readout_in 160ms ease-out both;
}

@keyframes readout_in {
	from { scale: 0.97; opacity: 0.4; }
}

.readout.scan { border-color: var(--slate); }
.readout.shipped { border-color: var(--fern); }
.readout.returned { border-color: var(--salmon); }
.readout.done { border-color: var(--fern); background: var(--fern-light); }

.readout_kind {
	font-family: var(--slab);
	font-size: 3cqw;
	letter-spacing: 0.2cqw;
}

.readout.scan .readout_kind { color: var(--slate); }
.readout.shipped .readout_kind { color: var(--fern); }
.readout.returned .readout_kind { color: var(--salmon-dark); }

.readout_name {
	font-family: var(--slab);
}

.need {
	padding: 0.4cqw 1.6cqw;
	background: var(--slate);
	color: var(--paper-2);
	border-radius: 0.8cqw;
	font-weight: 700;
	text-transform: uppercase;
	font-size: 2.7cqw;
}

.need.bag_need {
	background: var(--fern);
	text-transform: none;
}

.readout_ready {
	padding: 0.4cqw 1.6cqw;
	background: var(--fern);
	color: var(--paper-2);
	border-radius: 0.8cqw;
	font-weight: 700;
}


/*=== The shift report =========================================================*/

.report_title {
	margin: 0;
	font-size: 22px;
}

.report_day {
	margin: 4px 0 0;
	color: var(--muted);
	font-size: 12px;
}

.report_verdict {
	margin: 10px 0;
	font-size: 30px;
	color: var(--fern);
}

.report_verdict.over {
	color: var(--salmon-dark);
}

.report_lines {
	display: grid;
	grid-template-columns: auto 1fr;
	gap: 2px 14px;
	margin: 0 0 14px;
	font-size: 13px;
}

.report_lines dt {
	color: var(--muted);
}

.report_lines dd {
	margin: 0;
	font-weight: 700;
}

.report_deal {
	margin: 0 0 8px;
	font-size: 11px;
	color: var(--muted);
}

.report_list {
	display: flex;
	flex-direction: column;
	gap: 6px;
	max-height: 320px;
	margin: 0 0 12px;
	padding: 0;
	overflow-y: auto;
	list-style: none;
}

.report_parcel {
	display: flex;
	flex-wrap: wrap;
	gap: 2px 6px;
	padding: 6px 8px;
	background: var(--kraft-light);
	border-left: 4px solid var(--kraft-dark);
	border-radius: 3px;
	font-size: 11px;
}

.report_parcel.letter {
	background: var(--envelope);
	border-left-color: var(--ink-2);
}

.report_name {
	flex-basis: 100%;
	font-family: var(--slab);
	font-size: 12px;
}

.report_from {
	flex-basis: 100%;
	color: var(--muted);
	font-size: 10px;
}

.report_needs,
.report_steps {
	display: flex;
	flex-wrap: wrap;
	gap: 3px;
}

.report_steps {
	flex-basis: 100%;
}

.chip {
	padding: 1px 5px;
	background: var(--slate);
	color: var(--paper-2);
	border-radius: 3px;
	font-weight: 700;
}

.chip.quiet {
	background: var(--paper-3);
	color: var(--ink);
}

.step {
	padding: 1px 5px;
	border: 1px solid var(--ink-2);
	border-radius: 3px;
}

.step.wasted {
	text-decoration: line-through;
	color: var(--salmon-dark);
	border-color: var(--salmon);
}

.step.returned {
	color: var(--salmon-dark);
	border-color: var(--salmon);
	font-weight: 700;
}
