@font-face {
	font-family: "Geist";
	src: url("fonts/geist-latin-wght-normal.woff2") format("woff2");
	font-weight: 100 900;
	font-display: swap;
}
@font-face {
	font-family: "Geist Mono";
	src: url("fonts/geist-mono-latin-wght-normal.woff2") format("woff2");
	font-weight: 400 600;
	font-display: swap;
}

/* The extension's own neutral system (console.css: oklch greys, emerald-400 for "live"), tuned for
   a page that sits in the dark around a lit wall. Colour means state, never decoration. */
:root {
	--wall: #000; /* the wall itself: an LED that is off */
	--letterbox: oklch(0.13 0.004 265); /* the room around it, a shade up so the wall keeps its edge */
	--chrome: oklch(0.16 0.004 265 / 0.9);
	--panel: oklch(0.18 0.004 265);
	--raised: oklch(0.23 0.004 265);
	--line: oklch(1 0 0 / 0.09);
	--line-strong: oklch(1 0 0 / 0.18);
	--hover: oklch(1 0 0 / 0.07);
	--press: oklch(1 0 0 / 0.11);
	--ink: oklch(0.97 0 0);
	--muted: oklch(0.74 0.006 265);
	--faint: oklch(0.56 0.006 265);
	--live: oklch(0.765 0.177 163.223); /* emerald-400, the extension's live dot */
	--warn: oklch(0.82 0.14 75);
	--danger: oklch(0.7 0.18 25);
	--focus: oklch(0.97 0 0 / 0.85);
	--mono: "Geist Mono", ui-monospace, "SF Mono", Menlo, monospace;
	--ease: cubic-bezier(0.16, 1, 0.3, 1);
	--fast: 0.18s;
	--hud-h: 52px;
	--tap: 40px;
	color-scheme: dark;
}
@media (pointer: coarse) {
	:root {
		--tap: 44px;
		--hud-h: 56px;
	}
}

html {
	scrollbar-width: none;
	-ms-overflow-style: none;
}
html::-webkit-scrollbar {
	display: none;
}
html,
body {
	overflow: hidden;
}
:where(*) {
	min-width: 0;
	box-sizing: border-box;
}
/* An element's own display rule must never beat the hidden attribute. */
[hidden] {
	display: none !important;
}
body {
	margin: 0;
	background: var(--letterbox);
	color: var(--ink);
	font: 14px/1.45 "Geist", ui-sans-serif, system-ui, sans-serif;
	-webkit-font-smoothing: antialiased;
	-webkit-tap-highlight-color: transparent;
}
::selection {
	background: oklch(0.765 0.177 163.223 / 0.3);
}
button,
input {
	font: inherit;
	color: inherit;
}
button {
	cursor: pointer;
	background: none;
	border: 0;
	padding: 0;
}
:focus-visible {
	outline: 2px solid var(--focus);
	outline-offset: 2px;
}
.sr-only {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip: rect(0 0 0 0);
	white-space: nowrap;
}
svg {
	width: 18px;
	height: 18px;
	fill: none;
	stroke: currentColor;
	stroke-width: 1.75;
	stroke-linecap: round;
	stroke-linejoin: round;
}

/* ---------- the wall: the whole window, letterboxed to its shape ---------- */

.screen {
	position: fixed;
	inset: 0;
	display: grid;
	place-items: center;
	background: var(--letterbox);
}
.app.is-idle,
.app.is-idle * {
	cursor: none;
}
.stage {
	position: relative;
	/* Its own stacking context: the layers' z-index stays inside, so the swipe surface sits on top. */
	isolation: isolate;
	width: min(100vw, calc(100dvh * var(--aspect, 1.7778)));
	aspect-ratio: var(--aspect, 16 / 9);
	overflow: hidden;
	background: var(--wall);
	/* A bezel: the wall stays an object even when what it shows is dark. */
	box-shadow: 0 0 0 1px var(--line), 0 24px 70px -28px oklch(0 0 0 / 0.9);
}
.layers {
	position: absolute;
	inset: 0;
	transition: filter 0.5s var(--ease), opacity 0.5s var(--ease);
}
/* Offline or silent: what is drawn is the last picture the wall reported, not the wall now. */
.app.is-stale .layers {
	filter: grayscale(0.85) brightness(0.5);
}
.pv-layer {
	position: absolute;
	left: 0;
	top: 50%;
	transform-origin: 50% 50%;
	transition: transform var(--fast) var(--ease), opacity var(--fast) var(--ease);
}
.pv-layer img,
.pv-layer video {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	pointer-events: none;
}
/* Pages and YouTube play live and take clicks, as on a web player. */
.pv-web {
	position: absolute;
	inset: 0;
	overflow: hidden;
}
.pv-web iframe {
	position: absolute;
	top: 0;
	left: 0;
	border: 0;
	transform-origin: 0 0;
	opacity: 0;
	transition: opacity 0.3s var(--ease);
}
.pv-layer.is-live .pv-web iframe {
	opacity: 1;
}
.pv-layer.is-live > :not(.pv-web):not(.pv-tint):not(.pv-defs) {
	visibility: hidden;
}
/* The web player's look (lib/player-look.js): its filter chain on the picture, temperature and tint as
   multiply overlays above it, the SVG filters out of the way. */
.pv-layer > :not(.pv-tint):not(.pv-defs) {
	filter: var(--pv-filter, none);
}
.pv-tint {
	position: absolute;
	inset: 0;
	mix-blend-mode: multiply;
	pointer-events: none;
}
.pv-defs {
	position: absolute;
	width: 0;
	height: 0;
	overflow: hidden;
}
/* Identify (flashBorder): v7 IdentifyFlash, a border that grows and shrinks over everything. */
.identify-flash {
	position: absolute;
	inset: 0;
	z-index: 3000;
	pointer-events: none;
	animation: identify-flash var(--flash-ms, 2000ms) ease-in-out forwards;
}
@keyframes identify-flash {
	0%,
	100% {
		box-shadow: inset 0 0 0 0 var(--flash-color);
	}
	50% {
		box-shadow: inset 0 0 0 clamp(5px, 1vw, 10px) var(--flash-color);
	}
}
.pv-stand-in {
	display: grid;
	place-content: center;
	justify-items: center;
	gap: 4px;
	width: 100%;
	height: 100%;
	padding: 6%;
	background: linear-gradient(160deg, var(--raised), var(--letterbox) 70%);
	color: var(--muted);
	font-size: clamp(11px, 1.4cqi, 18px);
	text-align: center;
	container-type: inline-size;
}
.pv-stand-in b {
	color: var(--ink);
	font-weight: 500;
	max-width: 100%;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.stage-note {
	position: absolute;
	inset: 0;
	display: grid;
	place-items: center;
	margin: 0;
	color: var(--faint);
	font-size: 14px;
}
.veil {
	position: absolute;
	inset: 0;
	display: grid;
	place-items: center;
	background: oklch(0 0 0 / 0.72);
	color: var(--warn);
	font-weight: 500;
	letter-spacing: 0.02em;
}

/* What the wall is doing right now when it isn't simply live: pinned at the foot, never fades with
   the header, because a shadow that hides how fresh it is misleads. */
.wall-state {
	position: fixed;
	left: 50%;
	bottom: max(16px, env(safe-area-inset-bottom));
	z-index: 4;
	display: flex;
	align-items: center;
	gap: 8px;
	max-width: calc(100vw - 32px);
	padding: 7px 14px 7px 12px;
	border-radius: 999px;
	background: var(--chrome);
	box-shadow: 0 0 0 1px var(--line), 0 10px 30px -12px oklch(0 0 0 / 0.8);
	color: var(--muted);
	font-size: 13px;
	transform: translateX(-50%);
	white-space: nowrap;
	animation: rise 0.4s var(--ease) both;
}
.wall-state span:last-child {
	overflow: hidden;
	text-overflow: ellipsis;
}
.wall-state b {
	color: var(--ink);
	font-weight: 500;
}
@keyframes rise {
	from {
		opacity: 0;
		transform: translate(-50%, 6px);
	}
}

/* Phones held upright with a wide wall: the room under the wall says what is on it. */
.now-caption {
	display: none;
}
@media (pointer: coarse) and (orientation: portrait) {
	.now-caption {
		position: fixed;
		left: 0;
		right: 0;
		top: calc(50% + (100vw / var(--aspect, 1.7778)) / 2 + 18px);
		display: grid;
		gap: 2px;
		padding: 0 20px;
		margin: 0;
		text-align: center;
		pointer-events: none;
	}
	.app.no-wall .now-caption,
	.app.is-moving .now-caption {
		display: none;
	}
	.now-caption b {
		font-weight: 500;
		font-size: 15px;
		overflow: hidden;
		text-overflow: ellipsis;
		white-space: nowrap;
	}
	.now-caption span {
		color: var(--muted);
		font-size: 13px;
		overflow: hidden;
		text-overflow: ellipsis;
		white-space: nowrap;
	}
	.now-caption span:empty {
		display: none;
	}
}

/* Swiping between walls (phones, Move off): a transparent surface over the wall catches horizontal
   swipes; the stage follows the finger, then slides out and the next wall slides in. */
.swipe-layer {
	display: none;
}
@media (pointer: coarse) {
	.swipe-layer {
		display: block;
		position: fixed;
		inset: 0;
		z-index: 1;
		touch-action: none;
	}
	.app.is-moving .swipe-layer,
	.app.no-wall .swipe-layer {
		display: none;
	}
}
.stage.is-swiping {
	transition: none;
}
.stage.is-sliding {
	transition: transform var(--fast) var(--ease), opacity var(--fast) var(--ease);
}

/* Move mode: the extension's preview. Layers take the pointer (pages stop taking clicks), the
   selected one is outlined, and nothing hides while you work. */
.stage:focus {
	outline: none;
}
.app.is-moving .pv-web iframe {
	pointer-events: none;
}
.app.is-moving .pv-layer {
	cursor: grab;
	touch-action: none;
}
.app.is-moving .stage {
	touch-action: none;
	user-select: none;
	-webkit-user-select: none;
	box-shadow: 0 0 0 1px var(--line-strong), 0 24px 70px -28px oklch(0 0 0 / 0.9);
}
.app.is-moving .pv-layer.is-dragging {
	cursor: grabbing;
	transition: none;
}
.app.is-moving .pv-layer.is-selected::after {
	content: "";
	position: absolute;
	inset: 0;
	border: 2px solid oklch(1 0 0 / 0.6);
	box-shadow: 0 0 0 1px oklch(0 0 0 / 0.4);
	pointer-events: none;
}
.app.is-moving .pv-layer.is-selected.is-locked::after {
	border-style: dashed;
	border-color: var(--warn);
}

/* ---------- the header: the wall picker, and three tools ---------- */

.hud {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	z-index: 5;
	display: flex;
	align-items: center;
	gap: 8px;
	height: calc(var(--hud-h) + env(safe-area-inset-top));
	padding: env(safe-area-inset-top) max(8px, env(safe-area-inset-right)) 0 max(8px, env(safe-area-inset-left));
	background: var(--chrome);
	box-shadow: 0 1px 0 var(--line);
	transition: opacity 0.4s var(--ease), transform 0.4s var(--ease);
}
.app.is-idle .hud {
	opacity: 0;
	transform: translateY(-6px);
	pointer-events: none;
}
.combo {
	position: relative;
	flex: 1 1 auto;
	display: flex;
}
.hud-tools {
	display: flex;
	flex: none;
	gap: 4px;
}
.tool-btn {
	display: grid;
	place-items: center;
	width: var(--tap);
	height: var(--tap);
	border-radius: 10px;
	color: var(--muted);
	touch-action: manipulation;
	transition: background-color var(--fast) var(--ease), color var(--fast) var(--ease), transform 0.12s var(--ease);
}
.tool-btn:active {
	transform: scale(0.94);
	background: var(--press);
}
/* Move is armed: it changes a real wall, so it reads as switched on, not as a hover. */
#moveBtn[aria-pressed="true"] {
	background: var(--ink);
	color: var(--letterbox);
}
.pill {
	display: flex;
	align-items: center;
	gap: 9px;
	max-width: min(460px, 100%);
	height: var(--tap);
	padding: 0 10px 0 12px;
	border-radius: 10px;
	touch-action: manipulation;
	transition: background-color var(--fast) var(--ease), box-shadow var(--fast) var(--ease);
}
.pill[aria-expanded="true"] {
	background: var(--hover);
	box-shadow: inset 0 0 0 1px var(--line-strong);
}
@media (hover: hover) {
	.tool-btn:hover {
		background: var(--hover);
		color: var(--ink);
	}
	#moveBtn[aria-pressed="true"]:hover {
		background: var(--ink);
		color: var(--letterbox);
	}
	.pill:hover {
		background: var(--hover);
	}
}
.pill-value {
	flex: none;
	font-family: var(--mono);
	font-size: 13px;
	font-weight: 500;
	letter-spacing: 0.01em;
	white-space: nowrap;
}
.pill-value.is-placeholder {
	font-family: inherit;
	font-weight: 400;
	letter-spacing: 0;
	color: var(--muted);
}
.pill-name {
	color: var(--muted);
	font-size: 13px;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.pill-name:empty {
	display: none;
}
/* The direct WebRTC link: a quiet fact, not a badge competing with the wall's name. */
.link-badge {
	flex: none;
	display: inline-flex;
	align-items: center;
	gap: 3px;
	color: var(--faint);
	font-size: 11px;
	letter-spacing: 0.02em;
}
.chev {
	flex: none;
	width: 16px;
	height: 16px;
	color: var(--faint);
	transition: transform var(--fast) var(--ease);
}
.pill[aria-expanded="true"] .chev {
	transform: rotate(180deg);
}

/* Status dots: live is emerald, asleep amber, offline a hollow ring (the normal state of most walls,
   so it must not read as an alarm), not heard from yet a faint dot. */
.dot {
	flex: none;
	width: 8px;
	height: 8px;
	border-radius: 50%;
	background: var(--faint);
	opacity: 0.6;
}
.dot[data-status="online"] {
	background: var(--live);
	opacity: 1;
	box-shadow: 0 0 0 3px oklch(0.765 0.177 163.223 / 0.18);
}
.dot[data-status="asleep"] {
	background: var(--warn);
	opacity: 1;
}
.dot[data-status="offline"] {
	background: transparent;
	box-shadow: inset 0 0 0 1.5px var(--faint);
	opacity: 1;
}

/* An outside tap closes the panel. */
.scrim {
	position: fixed;
	inset: 0;
	z-index: 1;
}
.combo-panel {
	position: absolute;
	top: calc(100% + 8px);
	left: 0;
	z-index: 2;
	display: flex;
	flex-direction: column;
	width: min(360px, calc(100vw - 16px));
	max-height: min(70dvh, 480px);
	overflow: hidden;
	border-radius: 14px;
	background: var(--panel);
	box-shadow: 0 0 0 1px var(--line), 0 24px 48px -16px oklch(0 0 0 / 0.75);
	touch-action: manipulation;
	transform-origin: top left;
	animation: drop 0.22s var(--ease) both;
}
@keyframes drop {
	from {
		opacity: 0;
		transform: translateY(-4px) scale(0.985);
	}
}
.combo-entry {
	flex: none;
	padding: 8px;
	box-shadow: 0 1px 0 var(--line);
}
.field {
	width: 100%;
	height: var(--tap);
	padding: 0 12px;
	border-radius: 10px;
	border: 0;
	background: var(--letterbox);
	box-shadow: inset 0 0 0 1px var(--line);
	outline: none;
	font-family: var(--mono);
	font-size: 13px;
	letter-spacing: 0.01em;
	transition: box-shadow var(--fast) var(--ease);
}
.field::placeholder {
	color: var(--muted);
	font-family: "Geist", ui-sans-serif, system-ui, sans-serif;
	letter-spacing: 0;
}
.field:focus-visible,
.field:focus {
	box-shadow: inset 0 0 0 1px var(--line-strong), 0 0 0 2px var(--focus);
}
.use-row {
	display: flex;
	gap: 6px;
	width: 100%;
	margin-top: 6px;
	padding: 8px 10px;
	border-radius: 8px;
	color: var(--muted);
	font-size: 13px;
	text-align: left;
}
.use-row span {
	color: var(--ink);
	font-family: var(--mono);
}
.combo-list {
	flex: 1;
	min-height: 0;
	margin: 0;
	padding: 4px;
	list-style: none;
	overflow: auto;
	scrollbar-width: thin;
	scrollbar-color: var(--raised) transparent;
}
.combo-list button {
	display: flex;
	align-items: center;
	gap: 10px;
	width: 100%;
	min-height: var(--tap);
	padding: 8px 10px;
	border-radius: 8px;
	text-align: left;
	color: var(--ink);
	font-size: 13px;
	touch-action: manipulation;
}
.combo-list button.is-active,
.use-row.is-active {
	background: var(--hover);
}
@media (hover: hover) {
	.combo-list button:hover,
	.use-row:hover {
		background: var(--hover);
	}
}
.combo-list button[aria-selected="true"] {
	background: var(--press);
}
.combo-list button[aria-selected="true"] .row-name::after {
	content: "  ·  following";
	color: var(--faint);
	font-size: 12px;
}
.row-name {
	flex: 1;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.row-name.is-id {
	font-family: var(--mono);
}
.row-id {
	flex: none;
	color: var(--faint);
	font-family: var(--mono);
	font-size: 12px;
}
.combo-empty {
	padding: 16px 12px;
	color: var(--muted);
	font-size: 13px;
	text-align: center;
}
.combo-foot {
	flex: none;
	display: flex;
	align-items: center;
	padding: 4px;
	box-shadow: 0 -1px 0 var(--line);
}
.foot-user {
	margin-left: auto;
	max-width: 220px;
	height: 34px;
	padding: 0 10px;
	border-radius: 8px;
	color: var(--faint);
	font-size: 12px;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
@media (hover: hover) {
	.foot-user:hover {
		background: var(--hover);
		color: var(--ink);
	}
}
#soundBtn .i-on,
#soundBtn[aria-pressed="true"] .i-off {
	display: none;
}
#soundBtn[aria-pressed="true"] .i-on {
	display: block;
}

/* ---------- sign in ---------- */

.panel {
	position: fixed;
	inset: 0;
	z-index: 10;
	display: grid;
	place-items: center;
	padding: 16px;
	background: radial-gradient(120% 80% at 50% 0%, oklch(0.2 0.006 265), var(--letterbox) 60%);
}
.card {
	display: grid;
	justify-items: center;
	gap: 10px;
	width: min(360px, 100%);
	padding: 32px 28px 28px;
	border-radius: 20px;
	background: var(--panel);
	box-shadow: 0 0 0 1px var(--line), 0 30px 60px -24px oklch(0 0 0 / 0.8);
	text-align: center;
}
.card img {
	margin-bottom: 6px;
}
.card h1 {
	margin: 0;
	font-size: 20px;
	font-weight: 600;
	letter-spacing: -0.02em;
	text-wrap: balance;
}
.card p {
	margin: 0 0 10px;
	color: var(--muted);
	text-wrap: pretty;
}
.btn {
	width: 100%;
	height: 44px;
	border-radius: 12px;
	font-weight: 500;
	transition: background-color var(--fast) var(--ease), transform 0.12s var(--ease);
}
.btn-primary {
	background: var(--ink);
	color: var(--letterbox);
}
@media (hover: hover) {
	.btn-primary:hover {
		background: #fff;
	}
}
.btn:active {
	transform: scale(0.98);
}
.note {
	margin: 4px 0 0;
	font-size: 12px;
}
.note:empty {
	display: none;
}
.note a {
	color: var(--ink);
	text-underline-offset: 3px;
}
.toast {
	position: fixed;
	left: 50%;
	bottom: max(64px, calc(env(safe-area-inset-bottom) + 56px));
	z-index: 20;
	max-width: calc(100vw - 32px);
	padding: 9px 16px;
	border-radius: 12px;
	background: var(--raised);
	box-shadow: 0 0 0 1px var(--line), 0 14px 34px -14px oklch(0 0 0 / 0.85);
	font-size: 13px;
	text-align: center;
	transform: translateX(-50%);
	animation: rise 0.3s var(--ease) both;
}
.toast[data-tone="error"] {
	color: var(--danger);
}
.toast b {
	font-weight: 500;
}
.toast .muted {
	color: var(--muted);
}

/* ---------- reduced motion: state still changes, it just doesn't travel ---------- */

@media (prefers-reduced-motion: reduce) {
	.hud,
	.app.is-idle .hud {
		transform: none;
	}
	.stage.is-sliding,
	.pv-layer {
		transition-property: opacity;
	}
	.combo-panel,
	.wall-state,
	.toast {
		animation: none;
	}
	.tool-btn:active,
	.btn:active {
		transform: none;
	}
}
