/* Self-hosted fonts (latin subsets, downloaded from Google Fonts
   2026-08-10; ROADMAP's parked self-host item). Source Sans 3 is one
   variable-weight file covering the 400–600 range the player uses. */
@font-face {
	font-family: 'Source Sans 3';
	font-style: normal;
	font-weight: 400 600;
	font-display: swap;
	src: url(fonts/source-sans-3-latin.woff2) format('woff2');
}
@font-face {
	font-family: 'IBM Plex Mono';
	font-style: normal;
	font-weight: 400;
	font-display: swap;
	src: url(fonts/ibm-plex-mono-400.woff2) format('woff2');
}
@font-face {
	font-family: 'IBM Plex Mono';
	font-style: normal;
	font-weight: 500;
	font-display: swap;
	src: url(fonts/ibm-plex-mono-500.woff2) format('woff2');
}

:root {
	--bg: #1a1a1a;
	--panel: #2d2d2d;
	--text: #e0e0e0;
	--text-subdued: #999;
	--accent: #4a90e2;
	--transition-duration: 0.5s;
	--soft-edge: 40px;
	--current-movement: '';
	--stale-dim-duration: 8s; /* graduated fade-to-placeholder ramp (ROADMAP Phase 10 item 4) — tune against the curdle point */
}

body {
	font-family: 'Source Sans 3', sans-serif;
	background-color: var(--bg);
	color: var(--text);
	margin: 0;
	display: flex;
	flex-direction: column;
	align-items: center;
	min-height: 100vh;
}

main {
	width: 100%;
	max-width: 1200px;
	padding: 20px;
	box-sizing: border-box;
}

.selector-panes {
	background: var(--panel);
	padding: 15px;
	border-radius: 8px;
	margin-bottom: 20px;
	display: grid;
	grid-template-areas: "left center right";
	grid-template-columns: auto 1fr auto;
	row-gap: 15px;
	column-gap: 20px;
}

.pane-left, .pane-center, .pane-right {
	display: flex;
	gap: 15px;
	align-items: center;
}

.pane-left {
	grid-area: left;
}

.pane-center {
	grid-area: center;
	justify-self: center;
	flex-wrap: wrap;
}

.pane-right {
	grid-area: right;
}

/* A long movement title truncates its select instead of breaking the
   layout — this is what makes the one hard breakpoint below acceptable.
   The wrapper divs need min-width: 0 as well: as flex items they refuse
   to shrink below the select's intrinsic width, which would defeat the
   select's max-width. position: relative anchors the armed movement
   select's clone-select stand-in (built and fully inline-styled in
   player.html — deliberately no rule here, so a stale cached copy of
   this file can never break it; field lesson 2026-08-07). */
.pane-center > div {
	min-width: 0;
	position: relative;
}

.selector-panes select {
	min-width: 0;
	max-width: 100%;
}

@media (max-width: 1000px) {
	.selector-panes {
		grid-template-areas:
			"left right"
			"center center";
		grid-template-columns: 1fr auto;
	}

	.pane-center {
		justify-self: stretch;
	}
}

select {
	background: #3d3d3d;
	color: white;
	border: 1px solid #555;
	padding: 8px;
	border-radius: 4px;
	cursor: pointer;
	font-family: 'Source Sans 3', sans-serif;
	min-height: 44px; /* finger-sized, same rows as the buttons (Phase 7) */
}

.system-window {
	width: 100%;
	aspect-ratio: 16 / 9;
	background: white;
	border-radius: 8px;
	overflow: hidden;
	position: relative;
	box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
}

.score-layer {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 100%;
	object-fit: contain;
	background: white;
}

.score-layer.current {
	z-index: 2;
}

.score-layer.incoming {
	z-index: 3;

	-webkit-mask-image: linear-gradient(
		to right,
		black 0%,
		black 48%,
		transparent 52%,
		transparent 100%
	);
	mask-image: linear-gradient(
		to right,
		black 0%,
		black 48%,
		transparent 52%,
		transparent 100%
	);

	-webkit-mask-size: 200% 100%;
	mask-size: 200% 100%;

	-webkit-mask-position: 100% 0;
	mask-position: 100% 0;
}

.score-layer.incoming.wiping {
	-webkit-mask-position: 0% 0;
	mask-position: 0% 0;

	transition:
		-webkit-mask-position var(--transition-duration) linear,
		mask-position var(--transition-duration) linear;
}

.scan-bar {
	position: absolute;
	top: 0;
	bottom: 0;
	left: 0;
	width: 2px;
	background: transparent;
	pointer-events: none;
	z-index: 10;
	opacity: 0;
	transform: translateX(-50%);
	box-shadow: 0 0 4px rgba(74, 144, 226, 0.2);
}

.scan-bar::after {
	content: '';
	position: absolute;
	left: -3px;
	top: 0;
	bottom: 0;
	width: 8px;
	background: transparent;
}

.scan-bar.reset {
	left: 0;
	opacity: 0;
	transition: none;
}

.scan-bar.active {
	left: 100%;
	opacity: 1;
	transition:
		left var(--transition-duration) linear,
		opacity 0.2s;
}

.cue-overlay {
	position: absolute;
	bottom: 10px;
	left: 10px;
	background: rgba(0, 0, 0, 0.7);
	padding: 5px 12px;
	border-radius: 4px;
	/*font-size: 0.9rem;*/
	color: #fff;
	pointer-events: none;
	z-index: 20;
}

.cue-overlay mark {
	font-weight: bold;
	color: darkorange;
	background-color: transparent;
}

.cue-overlay mark.boxed {
	border-color: white;
	border: solid 1px;
	color: white;
	display: inline-block;
	font-weight: normal;
	margin-block: 3pt;
	margin-inline-end: 1ch;
	padding-inline: 3pt;
}



.mute-overlay {
	position: absolute;
	inset: 0;
	background: rgb(0 0 0 / 55%);
	display: flex;
	align-items: center;
	justify-content: center;
	z-index: 25;
	pointer-events: none;
}

.mute-overlay span {
	background: rgba(0, 0, 0, 0.75);
	color: #fff;
	padding: 10px 20px;
	border-radius: 6px;
	font-size: 1.1rem;
	letter-spacing: 0.02em;
}

/* Wait indicators (ROADMAP Phase 5): shared fade discipline for the
   buffering modal, the image chip, and (later) the placeholder.
   Show-delay and minimum-visible timing live in the JS helper
   (makeWaitIndicator); the CSS owns only the fades. Always in the
   DOM so opacity can transition; 'visibility' keeps the hidden state
   out of the accessibility tree. */
.wait-indicator {
	opacity: 0;
	visibility: hidden;
	transition: opacity 0.3s ease, visibility 0s linear 0.3s;
}

.wait-indicator.shown {
	opacity: 1;
	visibility: visible;
	transition: opacity 0.3s ease;
}

/* Buffering modal: shown only when time stops — playback halted by
   starvation or an app-initiated boundary hold. */
.buffering-overlay {
	position: absolute;
	inset: 0;
	background: rgb(0 0 0 / 55%);
	display: flex;
	align-items: center;
	justify-content: center;
	z-index: 30;
	pointer-events: none;
}

.buffering-overlay > span {
	background: rgba(0, 0, 0, 0.75);
	color: #fff;
	padding: 10px 20px;
	border-radius: 6px;
	font-size: 1.1rem;
	letter-spacing: 0.02em;
	display: flex;
	align-items: center;
	gap: 10px;
}

.buffering-spinner {
	width: 18px;
	height: 18px;
	border: 3px solid rgba(255, 255, 255, 0.3);
	border-top-color: #fff;
	border-radius: 50%;
	animation: buffering-spin 1s linear infinite;
}

@keyframes buffering-spin {
	to { transform: rotate(360deg); }
}

/* Slow-link navigation feedback (tester 2026-07-28, round 2): over 3G
   a Home click can produce no visible change for seconds. A gentle
   pulse, deliberately NOT a spinner — spin is the wait-indicators'
   vocabulary ("system busy"), and a spinning Home read as "your
   request is queued behind my other work." The click handler also
   stands the other indicators down and pauses the audio: departure
   acknowledged, everything else quiets. */
a.button.navigating {
	pointer-events: none;
	animation: nav-pulse 1.2s ease-in-out infinite;
}

@keyframes nav-pulse {
	0%, 100% { opacity: 0.7; }
	50% { opacity: 0.3; }
}

/* Blank-ledger placeholder: shown when the score window holds nothing
   valid to sing from (cold load, or a held image from a different
   movement than the audio). Opaque backing so an invalid stale image
   never shows through. Below every indicator and overlay; above the
   score layers.
   Dark treatment (user design, round 2 2026-07-28): pure white is
   reserved for real music. The placeholder is a recessed, dimmed slot
   — "the system wants to put your music here" — and the score's
   arrival reads as a brightening. Values from the user's DevTools
   mockup; the canonical SVG stays screen-agnostic grey, dimmed here
   at the presentation layer. */
.score-placeholder {
	position: absolute;
	inset: 0;
	background: #333333;
	z-index: 15;
	pointer-events: none;
}

.score-placeholder img {
	width: 100%;
	height: 100%;
	object-fit: contain;
	filter: brightness(0.5);
}

/* Graduated fade-to-placeholder (ROADMAP Phase 10 item 4): when the
   held image is VALID but the display is lagging the audio, the show
   transition stretches to a long ease-in — the whole-layer opacity ramp
   makes the opaque backing semi-transparent on the way up, so the stale
   SVG visibly dims toward the placeholder: recognizable while "where I
   was" still matters, gone as it stops mattering. ease-in keeps the
   first seconds nearly crisp (the "friendly little challenge" window)
   and accelerates as staleness curdles. The opaque-backing guarantee
   (invalid stale images never show through) only ever mattered fully
   shown, which still holds — invalid content keeps the quick cover via
   the base rule. Scoped to .graduated.shown so the fade-OUT always
   falls back to the base 0.3 s: the score's arrival stays a prompt
   brightening no matter how deep the dim had gotten. */
.score-placeholder.graduated.shown {
	transition: opacity var(--stale-dim-duration) ease-in;
}

/* Image chip: the score window lagging the audio while music keeps
   playing. Peripheral by design — never dims or obscures music
   someone may be singing from (cue captions own the bottom-left). */
.image-chip {
	position: absolute;
	top: 10px;
	right: 10px;
	display: flex;
	align-items: center;
	gap: 7px;
	background: rgba(0, 0, 0, 0.7);
	color: #fff;
	padding: 5px 12px;
	border-radius: 4px;
	font-size: 0.9rem;
	pointer-events: none;
	z-index: 20;
}

.image-chip .buffering-spinner {
	width: 12px;
	height: 12px;
	border-width: 2px;
}

.controls {
	background: var(--panel);
	margin-top: 10px;
	padding: 5px 20px 20px 20px;
	border-radius: 0 0 8px 8px;
	display: flex;
	flex-direction: column;
	gap: 15px;
}

.timeline-container {
	display: grid;
	grid-template-rows: auto auto;
	row-gap: 8px;
	width: 100%;
}

/* Finger-scrubbable timeline (Phase 7): appearance: none resets native
   track rendering in both engines, so track AND thumb are restyled for
   both vendor pseudo-elements. The 44 px input height is the touch hit
   area — transparent padding around a slim 6 px track, not visual bulk.
   WebKit positions the thumb at the track's top edge, hence the
   negative margin-top ((6 − 28) / 2) to center it; Firefox centers on
   its own. margin: 0 keeps the ends aligned with the time labels.

   Page-turn / cue markers (user design, 2026-08-08): the input's own
   track pseudos are TRANSPARENT (they still size and position the
   thumb); the visible bar and the markers are drawn by the
   .timeline-bed layer underneath. The native input is atomic — track
   and thumb paint as one — so this underlay is the only way markers
   can sit above the bar yet under the thumb: navigate to a marker and
   the blue dot covers it exactly (the guiding principle: markers live
   precisely where paused next/prev and Cue± land the dot). */
.timeline-track {
	position: relative;
}

.timeline-container input[type='range'] {
	width: 100%;
	cursor: pointer;
	appearance: none;
	-webkit-appearance: none;
	background: transparent;
	height: 44px;
	margin: 0;
	padding: 0;
	position: relative; /* paints above the bed */
	display: block; /* inline-level inputs add baseline descender space
	                   to the wrapper's line box, making it taller than
	                   44px — which silently breaks the bed's top: 50%
	                   centering against the thumb (field-tuned as a
	                   44.7% kludge before this was diagnosed) */
}

.timeline-container input[type='range']::-webkit-slider-runnable-track {
	height: 6px;
	background: transparent;
	border-radius: 3px;
}

.timeline-container input[type='range']::-webkit-slider-thumb {
	-webkit-appearance: none;
	width: 28px;
	height: 28px;
	margin-top: -11px;
	border: none;
	border-radius: 50%;
	background: var(--accent);
}

.timeline-container input[type='range']::-moz-range-track {
	height: 6px;
	background: transparent;
	border-radius: 3px;
}

.timeline-container input[type='range']::-moz-range-thumb {
	width: 28px;
	height: 28px;
	border: none;
	border-radius: 50%;
	background: var(--accent);
}

/* The visible track bar, drawn by the bed. Markers are its children,
   positioned by player.html at calc(14px + fraction × (100% − 28px)) —
   the thumb-CENTER travel mapping (28 px thumb, half inset each end),
   so a marker's center is exactly where the dot's center rests.
   Marker geometry below = the user's field-tuned design (2026-08-08).
   Cues append after page turns, so where they coincide the cue wins. */
.timeline-bed {
	position: absolute;
	left: 0;
	right: 0;
	top: 50%;
	height: 6px;
	transform: translateY(-50%);
	background: #555;
	border-radius: 3px;
	pointer-events: none;
}

/* Page turns read as GAPS cut into the bar (user tuning superseded
   the original dash look): full bar height, painted in the panel
   color so the bar appears interrupted — and the print palette's
   --panel override keeps the gap illusion working on paper too. */
.timeline-bed .page-turn {
	position: absolute;
	top: 50%;
	transform: translate(-50%, -50%);
	width: 3px;
	height: 6px;
	background: var(--panel);
}

/* Cue lozenge. Base rule = the rotated-square diamond — the fallback
   every browser renders. Where corner-shape is supported (Chromium
   139+, 2025), the user's tuned shape upgrades it to a taller scooped
   lozenge (concave-pointed, DAW-style). */
.timeline-bed .cue-mark {
	position: absolute;
	top: 50%;
	transform: translate(-50%, -50%) rotate(45deg);
	width: 6px;
	height: 6px;
	background: darkorange;
}

@supports (corner-shape: scoop) {
	.timeline-bed .cue-mark {
		transform: translate(-50%, -50%);
		width: 9px;
		height: 14px;
		corner-shape: scoop;
		border-radius: 90% / 87%;
	}
}

.timeline-labels {
	display: grid;
	grid-template-columns: auto 1fr auto;
	align-items: center;
	width: 100%;
}

.button-group {
	display: flex;
	justify-content: center;
	justify-content: left;
	gap: 10px;
	flex-wrap: wrap;
}

/* Playback-control legibility (user design, 2026-08-08; mockup in
   design/DESIGN-TEST-*.png): the transport symbols were too small to
   read comfortably, but the button BOXES are exactly right (Phase 7
   touch targets, layout flexes across every viewport) and must not
   move a pixel. Mechanism: the real label still renders — transparent
   — so it sizes the box precisely as before, and the visible ink is
   painted over it by the ::after at an independent size. font-size on
   the ::after is therefore a pure legibility knob that CANNOT affect
   layout. The ink text comes from data-label, which player.html keeps
   in sync with textContent (init seed + setButtonLabel), so screen
   readers and layout stay on the real text. Sizes are hand-tuned, not
   uniform, deliberately: words self-identify by shape and need only a
   nudge; punctuation-derived symbols (« |« » »|) render optically far
   smaller than their nominal size and need roughly double to reach
   parity. */
.button-group button {
	position: relative;
	color: transparent;
}

.button-group button::after {
	content: attr(data-label);
	position: absolute;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	color: white;
	pointer-events: none;
	white-space: nowrap;
}

#prevMvmt::after,
#prevSystem::after,
#nextSystem::after,
#nextMvmt::after {
	font-size: 20pt;
}

#restartSystem::after,
#muteBtn::after {
	font-size: 14pt;
}

#playBtn::after,
#prevCue::after,
#nextCue::after {
	font-size: 12pt;
}

button, a.button {
	background: #444;
	color: white;
	border: none;
	padding: 10px 15px;
	border-radius: 4px;
	cursor: pointer;
	transition: background 0.2s;
	min-width: 44px;
	min-height: 44px; /* 44 px touch minimum (Phase 7); buttons center their labels natively */
	font-family: 'Source Sans 3', sans-serif;
}

a.button {
	/* inline-flex (not inline-block) so the label stays vertically
	   centered under the 44 px minimum height */
	display: inline-flex;
	align-items: center;
	justify-content: center;
	box-sizing: border-box;
	text-align: center;
	text-decoration: none;
	font-size: 13.3333px; /* match the UA default button font-size */
}

button:hover, a.button:hover {
	background: var(--accent);
}

button:disabled {
	opacity: 0.3;
	cursor: not-allowed;
}

button#playBtn {
	width: 11ch; /* wide enough fixed-width so switching between “play”/“pause” doesn’t mess with layout */
}

.time-display {
	color: var(--text-subdued);
	font-family: 'IBM Plex Mono', monospace;
	font-size: 0.875rem;
	line-height: 0.1;
}

#currentTime {
	justify-self: start;
	padding-inline-start: 0.5ch;
}

#duration {
	justify-self: end;
}

.system-counter {
	font-family: 'IBM Plex Mono', monospace;
	font-size: 0.85rem;
	color: var(--text-subdued);
	align-self: center;
	min-width: 110px;
	text-align: left;
}

.system-counter::before {
	display: block;
	content: var(--current-movement);
}

@media (orientation: landscape) and (max-height: 500px) {
	main {
		padding: 8px;
	}

	.system-window {
		max-height: 58vh;
	}

	.selector-panes {
		padding: 8px;
		margin-bottom: 8px;
		gap: 8px;
	}

	.controls {
		padding: 10px;
		gap: 8px;
	}
}

.help-backdrop {
	position: fixed;
	inset: 0;
	background: rgba(0, 0, 0, 0.6);
	z-index: 100;
}

.help-content {
	position: fixed;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%);
	background: var(--panel);
	padding: 24px;
	border-radius: 8px;
	z-index: 101;
	width: min(560px, calc(100vw - 32px));
	max-height: calc(100dvh - 24px);
	overflow-y: auto;
	box-sizing: border-box;
	color: var(--text);
}

.help-content h3 {
	margin-top: 0;
}

.help-content kbd {
	background: #555;
	padding: 2px 8px;
	border-radius: 3px;
	font-family: 'IBM Plex Mono', monospace;
	font-size: 0.9rem;
}

.help-content td {
	padding: 4px 12px;
}

.help-hint {
	color: var(--text-subdued);
	font-size: 0.9rem;
	margin: 8px 0;
}

.help-hint kbd {
	white-space: nowrap;
}

.help-actions {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 8px;
	margin-block: 12px;
}

@media (max-width: 480px) {
	.help-actions {
		grid-template-columns: 1fr;
	}
}

.help-action {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 12px;
	text-align: left;
}

.help-action kbd {
	white-space: nowrap;
}

#closeHelp {
	background: oklch(0.56 0.11 253.87);
}

#closeHelp:hover {
	background: oklch(0.65 0.11 253.87);
}

.mute-toggle.muted {
	background: #8a3d3d;
}
/**********************************************************************/
/**********************************************************************/
/* COLD-LOAD NOTICE (ROADMAP Phase 10 item 5)                         */
/**********************************************************************/
/* Paints with the first paint (this stylesheet is render-blocking, so
   once anything paints, these rules are live) and is removed by the
   first real surface: logon gate, app, or the no-score message. The
   animation-delay is the anti-flash edge — a load that finishes
   sooner never shows anything, same principle as the wait
   indicators' show-delay. */
.load-notice {
	position: fixed;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	color: var(--text-subdued);
	font-size: 1.2rem;
	letter-spacing: 1px;
	opacity: 0;
	animation: load-notice-in 0.6s ease 0.3s forwards;
	pointer-events: none;
}

@keyframes load-notice-in {
	to { opacity: 1; }
}

/* DEPARTURE NOTICE (ROADMAP Phase 12) — the cold-load notice's mirror
   image, shown by the departure protocol. Opaque backing (it covers a
   live player, not an empty page) and above everything, help dialog
   included. Same anti-flash edge: the fade-in delay means a departure
   that commits quickly never shows anything. pointer-events: none so
   a canceled navigation leaves the app fully operable beneath it (any
   interaction then stands the notice down; see player.html). */
.depart-notice {
	position: fixed;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	background: var(--bg);
	color: var(--text-subdued);
	font-size: 1.2rem;
	letter-spacing: 1px;
	z-index: 200;
	opacity: 0;
	animation: load-notice-in 0.6s ease 0.3s forwards;
	pointer-events: none;
}

/**********************************************************************/
/* LOGON SUPPORT                                                      */
/**********************************************************************/
main {
	display: none;
}

.logon-card {
	background: var(--panel);
	padding: 28px;
	border-radius: 8px;
	max-width: 420px;
	margin: 80px auto;
}

.logon-card h2 {
	margin-top: 0;
	text-align: center;
}

.logon-card label {
	display: block;
	margin-bottom: 6px;
	font-size: 0.9rem;
}

.logon-card input[type="text"],
.logon-card input[type="password"] {
	width: 100%;
	padding: 8px;
	border-radius: 4px;
	border: 1px solid #555;
	background: #3d3d3d;
	color: white;
	box-sizing: border-box;
	font-family: monospace;
	margin-bottom: 12px;
}

.logon-card .checkbox-row {
	display: flex;
	align-items: center;
	gap: 8px;
	margin-bottom: 16px;
	cursor: pointer;
}

.logon-card .checkbox-row input {
	margin: 0;
}

.logon-card button {
	color: white;
	border: none;
	padding: 10px 24px;
	border-radius: 4px;
	cursor: pointer;
	font-size: 1rem;
}

.logon-card button.logon-agree {background: var(--accent);}
.logon-card button:hover {background: #50b7f5}
.logon-card button.logon-cancel:hover {background: red}

.auth-error {
	color: #e57373;
	font-size: 0.9rem;
	min-height: 1.4em;
	margin-bottom: 8px;
}

/**********************************************************************/
/* PRINTING                                                           */
/**********************************************************************/
@media print {
	:root {
		--bg: #ffffff;
		--panel: #f5f5f5;
		--text: #000000;
		--accent: #000000;
	}

	/* Force browsers to print background colors/tints */
	* {
		-webkit-print-color-adjust: exact;
		print-color-adjust: exact;
	}

	body {
		background: var(--bg);
		color: var(--text);
		/*font-size: 11pt;*/
	}

	#signOut {
		display: none;
	}

	/* Convert shadow panels to bordered boxes */
	.selector-panes,
	.controls {
		background: var(--panel);
		border: 1px solid #ccc;
		box-shadow: none;
	}

	.selector-panes button,
	.selector-panes a.button {display: none;}

	/* Override hardcoded dark form controls */
	.checkbox-row,
	.logon-card button.logon-agree,
	.logon-card button.logon-cancel {
		display: none;
	}

	#authCode,
	#authOk,
	select,
	button {
		background: #ffffff;
		color: #000000;
		border: 1px solid #999;
	}

	/* The slider bar is drawn by the bed layer (the input's own track
	   is transparent); lighten it here like the other form controls
	   (thumb follows --accent → black). Markers keep printing — they
	   are part of the timeline's meaning. The page-turn gaps need no
	   print rule: they paint in var(--panel), which this block's :root
	   override flips to the print panel color, so the bar still reads
	   as interrupted on paper. */
	.timeline-bed {
		background: #ccc;
	}

	button:hover {
		background: #e0e0e0; /* Subtle gray instead of blue accent */
	}

	/* The transport buttons' real text is transparent (legibility ink
	   rides in the ::after, white for the screen theme) — on white
	   print buttons the ink must turn black or the labels vanish. */
	.button-group button::after {
		color: #000000;
	}

	button:disabled {
		opacity: 0.5;
	}

	/* Clean score viewport - no shadow, crisp border */
	.system-window {
		box-shadow: none;
		border: 1px solid #000;
	}

	/* Hide animated elements that freeze awkwardly (and the dark
	   placeholder slot, which would print as a filled box) */
	.scan-bar,
	.mute-overlay,
	.buffering-overlay,
	.image-chip,
	.score-placeholder,
	.load-notice,
	.depart-notice {
		display: none;
	}

	/* Convert dark overlay to bordered callout */
	.cue-overlay {
		background: #ffffff;
		color: #000000;
		border: 1px solid #000;
		box-shadow: none;
	}

	.cue-overlay mark {
		color: #000000;
		background: transparent;
		font-weight: bold;
		text-decoration: underline;
	}
	.cue-overlay mark.boxed {
		color: black;
		border-color: black;
		text-decoration: none;
	}

	/* Data readouts */
	.time-display,
	.system-counter {
		color: var(--text);
	}

	/* Help dialog as static info box */
	.help-backdrop {
		background: rgba(255, 255, 255, 0.95);
	}

	.help-content {
		background: var(--panel);
		color: var(--text);
		border: 1px solid #000;
		box-shadow: none;
	}

	.help-content kbd {
		background: #e8e8e8;
		color: #000000;
		border: 1px solid #bbb;
	}
}