/* Mobile additions for the WebTV chat page.
   Loaded after chat.css so these win on equal specificity. */

@media (max-width: 760px) {

	/* The page itself must never scroll; only the message list does.
	   Without this iOS scrolls the whole document when the keyboard opens
	   and the composer ends up above the fold. */
	html, body {
		overflow: hidden;
		overscroll-behavior: none;
	}

	/* --app-height is written from window.visualViewport by mobile.js, so the
	   layout shrinks to the space the keyboard actually leaves. 100vh does not
	   do this on iOS: it keeps reporting the full screen height. */
	.main-content {
		height: 100dvh;
		height: var(--app-height, 100dvh);
		min-height: 0;
	}

	/* Chat must never be clipped, so when the keyboard is up the header is
	   what gives way. */
	body.kb-open .chat-header { display: none; }

	#chatContent { min-height: 0; }

	#chatMessages {
		-webkit-overflow-scrolling: touch;
		overscroll-behavior: contain;
	}

	/* Keep the composer clear of the home indicator. */
	#chatBar {
		padding-bottom: env(safe-area-inset-bottom, 0);
	}

	/* ---------------- hamburger ---------------- */

	#wtvBurger {
		position: fixed;
		top: calc(env(safe-area-inset-top, 0px) + 8px);
		left: 8px;
		/* The page stacks overlays up to 999999, so 40 left this buried. */
		z-index: 1000000;

		width: 34px;
		height: 34px;
		padding: 0;
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
		gap: 4px;

		/* same palette as the sidebar panel */
		background: linear-gradient(180deg, #3c384e, #1b1b1b);
		border: 1px solid #55506a;
		border-radius: 5px;
		box-shadow: 0 2px 6px rgba(0, 0, 0, 0.5);

		opacity: 0;
		visibility: hidden;
		transition: opacity 400ms ease, visibility 400ms ease;
		-webkit-tap-highlight-color: transparent;
	}

	#wtvBurger.visible {
		opacity: 0.85;
		visibility: visible;
	}

	#wtvBurger span {
		display: block;
		width: 17px;
		height: 2px;
		background: #9a94ad;
		border-radius: 1px;
	}

	#wtvBurger:active { opacity: 1; }
}

/* Pointer-capable large screens keep the normal sidebar. */
@media (min-width: 761px) {
	#wtvBurger { display: none; }
}

/* ==================================================================
   PORTRAIT / PHONE LAYOUT  -  nickname + whisper panels

   The upstream panels are desktop shapes sized entirely in vw, and three
   things defeat ordinary overrides, which is why earlier attempts had no
   visible effect:

     1. .nick-panel.show runs `animation: nickPanelUp .2s forwards`, whose
        final keyframe sets transform: translateY(2vw). An animation fill
        beats a plain declaration, so `transform: none` was ignored.
     2. .nick-panel-submit is position:absolute (top:11.5vw; right:3vw), so
        it never joined any flex row and sat wherever those offsets put it.
     3. .nick-panel-top is height:14vw/max-height:14vw and .nick-panel-input
        is height:0.9vw - fixed vw geometry that collapses on a phone.

   So this block resets geometry explicitly, with !important only where an
   animation fill or absolute positioning has to be beaten. Everything is in
   px: vw units are what made this unreadable on a narrow screen.

   Target shape - a plain /nick box, nothing more:

       [ nickname field ......................... ]
       [  Change  ] [  Clear  ] [ Cancel ]
       now: guest-US-1234

   ================================================================== */

@media (max-width: 760px) {

	/* The document itself must not scroll. Without this iOS scrolls the layout
	   viewport when an input is focused and carries the chat off-screen; only
	   the message list should ever scroll. */
	html, body {
		position: fixed !important;
		left: 0 !important;
		right: 0 !important;
		top: 0 !important;
		width: 100% !important;
		height: var(--app-height, 100dvh) !important;
		overflow: hidden !important;
		overscroll-behavior: none;
	}

	.main-content {
		height: var(--app-height, 100dvh) !important;
		max-height: var(--app-height, 100dvh) !important;
		min-height: 0 !important;
	}

	/* ---------- shared sheet ---------- */

	.nick-panel,
	.whisper-panel {
		/* Absolute inside <body>, which JS pins to the visual viewport height,
		   rather than fixed with a --kb-height offset. position:fixed measures
		   the layout viewport, which iOS does not shrink for the keyboard, so
		   the sheet was landing at or just below the fold and looked like it
		   had closed the moment the field was tapped. */
		position: absolute !important;
		left: 0 !important;
		right: 0 !important;
		width: auto !important;
		max-width: 100% !important;
		margin: 0 !important;
		bottom: 0 !important;
		transform: none !important;
		animation: none !important;
		height: auto !important;
		min-height: 0 !important;
		max-height: calc(var(--app-height, 100dvh) - 44px);
		overflow-y: auto;
		-webkit-overflow-scrolling: touch;
		border-radius: 10px 10px 0 0;
		box-sizing: border-box !important;
	}

	.nick-panel {
		padding: 12px !important;
	}

	/* ---------- nickname ---------- */

	.nick-panel .nick-panel-top {
		/* Positioning context for .fake-caret, which would otherwise anchor to
		   the panel and float in the middle of it. */
		position: relative !important;
		display: flex !important;
		flex-direction: row !important;
		align-items: center !important;
		height: auto !important;
		max-height: none !important;
		gap: 7px !important;
	}

	.nick-panel .nick-panel-label {
		display: none !important;
	}

	.nick-panel .nick-panel-input {
		flex: 1 1 auto !important;
		width: auto !important;
		min-width: 0 !important;
		max-width: none !important;
		height: auto !important;
		box-sizing: border-box !important;
		margin: 0 !important;
		padding: 8px 9px !important;
		border-width: 2px !important;
		/* 16px or larger stops iOS zooming the page on focus */
		font-size: 16px !important;
		line-height: 1.2 !important;
	}

	/* Out of absolute positioning and into the button row below. */
	.nick-panel .nick-panel-submit {
		position: static !important;
		top: auto !important;
		right: auto !important;
		display: inline-block !important;
		float: none !important;
		flex: 0 0 auto !important;
		width: auto !important;
		max-width: 42% !important;
		margin: 0 !important;
		padding: 6px 10px !important;
		font-size: 12.5px !important;
		line-height: 1.15 !important;
		white-space: nowrap;
		box-sizing: border-box !important;
	}

	/* Change / Clear / Cancel share one row and split the width evenly, so
	   nothing can run past the edge however long the labels are. */
	.nick-panel .nick-panel-bottom {
		display: flex !important;
		flex-direction: row !important;
		flex-wrap: nowrap !important;
		gap: 7px !important;
		justify-content: flex-end !important;
		align-items: stretch !important;
		margin: 7px 0 0 0 !important;
		padding: 0 !important;
		border: 0 !important;
		box-sizing: border-box !important;
	}

	.nick-panel .nick-panel-bottom button {
		flex: 0 0 auto !important;
		width: auto !important;
		min-width: 72px !important;
		max-width: none !important;
		margin: 0 !important;
		padding: 6px 12px !important;
		font-size: 12.5px !important;
		line-height: 1.15 !important;
		white-space: nowrap;
		box-sizing: border-box !important;
	}

	.nick-panel .nick-panel-title {
		font-size: 15px !important;
		margin: 0 0 10px !important;
		text-align: center !important;
	}

	.nick-panel .nick-panel-status {
		position: static !important;
		bottom: auto !important;
		margin: 30px 0 0 0 !important;
		padding: 0 !important;
		font-size: 12px !important;
		line-height: 1.3 !important;
		text-align: left !important;
		border: 0 !important;
		word-break: break-word;
	}

	/* ---------- whisper ---------- */

	/* Reserve a strip so the columns stop covering the close cross. */
	.whisper-panel {
		padding: 42px 12px calc(12px + env(safe-area-inset-bottom, 0px)) !important;
	}

	.whisper-panel .whisper-close {
		top: 6px !important;
		right: 8px !important;
		width: 34px !important;
		height: 34px !important;
		font-size: 22px !important;
		line-height: 34px !important;
		text-align: center;
		color: #ddd !important;
		z-index: 5;
	}

	.whisper-panel .whisper-columns {
		display: flex !important;
		flex-direction: column !important;
		gap: 8px !important;
	}

	.whisper-panel .whisper-column {
		width: 100% !important;
		min-width: 0 !important;
	}

	.whisper-panel .whisper-label {
		font-size: 12.5px !important;
		margin-bottom: 3px !important;
	}

	.whisper-panel .whisper-userlist {
		max-height: 84px !important;
		overflow-y: auto;
		-webkit-overflow-scrolling: touch;
	}

	/* Short private messages; keeps the Whisper button above the keyboard. */
	.whisper-panel .whisper-textarea {
		width: 100% !important;
		box-sizing: border-box !important;
		height: 40px !important;
		min-height: 40px !important;
		max-height: 40px !important;
		font-size: 16px !important;
		line-height: 1.25 !important;
		padding: 6px 8px !important;
		resize: none;
	}

	.whisper-panel .whisper-button-row {
		display: flex !important;
		justify-content: center !important;
		margin-top: 9px !important;
	}

	.whisper-panel .whisper-button-row button {
		width: auto !important;
		min-width: 45% !important;
		padding: 8px 16px !important;
		font-size: 13.5px !important;
		box-sizing: border-box !important;
	}

	/* ---------- keyboard up: shed non-essential rows ---------- */

	body.kb-open .nick-panel {
		padding-top: 9px !important;
	}

	body.kb-open .whisper-panel {
		padding-top: 36px !important;
	}

	body.kb-open .nick-panel .nick-panel-status,
	body.kb-open .whisper-panel .whisper-label {
		display: none !important;
	}

	body.kb-open .whisper-panel .whisper-userlist {
		max-height: 46px !important;
	}

	body.kb-open .whisper-panel .whisper-textarea {
		height: 32px !important;
		min-height: 32px !important;
		max-height: 32px !important;
		padding: 4px 8px !important;
	}
}

/* ==================================================================
   Header: room name + connection status

   Upstream both are position:absolute - the room name pinned left at 3.5vw
   (about 13px on a phone, and directly under the hamburger) and the status
   pinned top-right. Rearranged below for each orientation.
   ================================================================== */

/* ---------- portrait / phone ----------
   Room name centred in the banner with the status beside it:

        Lobby - Connected
*/
@media (max-width: 760px) {

	.chat-header {
		display: flex !important;
		flex-direction: row !important;
		align-items: center !important;
		justify-content: center !important;
		gap: 7px !important;
		height: auto !important;
		min-height: 46px !important;
		/* Keep clear of the hamburger on the left and stay balanced. */
		padding: 6px 46px !important;
		box-sizing: border-box !important;
	}

	.chat-header .header-text {
		position: static !important;
		margin: 0 !important;
		padding: 0 !important;
		height: auto !important;
		min-height: 0 !important;
		max-width: none !important;
		/* A step up from the 3.5vw original, which read as ~13px here. */
		font-size: 15px !important;
		line-height: 1.2 !important;
		overflow: visible !important;
		white-space: nowrap;
		text-overflow: ellipsis;
	}

	/* The decorative bubble graphic only crowds a narrow banner. */
	.chat-header .header-icon {
		display: none !important;
	}

	.chat-header #connectionStatus {
		position: static !important;
		top: auto !important;
		right: auto !important;
		/* Always smaller than the room name. */
		font-size: 11.5px !important;
		line-height: 1.2 !important;
		white-space: nowrap;
	}

	.chat-header #connectionStatus::before {
		content: "- ";
	}
}

/* ---------- desktop ----------
   Status sits on its own line directly beneath the room name rather than
   away in the top-right corner. */
@media (min-width: 761px) {

	/* Parked at the foot of the sidebar rather than in the banner: present if
	   you look for it, easy to ignore otherwise. Width matches .sidebar (15%)
	   so it centres in that column. Opacity rather than a flat colour, so the
	   green/amber/red state still reads once you do look. */
	.chat-header #connectionStatus {
		position: fixed;
		left: 0;
		right: auto;
		top: auto;
		bottom: 0.7vw;
		width: 15%;
		text-align: center;
		font-size: 0.68rem;
		opacity: 0.38;
		letter-spacing: 0.02em;
		z-index: 3;
		pointer-events: none;
	}
}

/* ---------- sidebar logo ----------
   Centre it in the sidebar column instead of hugging the left edge. */
.sidebar-logo {
	display: block !important;
	align-self: center !important;
	margin-left: auto !important;
	margin-right: auto !important;
}

/* ==================================================================
   Nickname panel close cross - same treatment as the whisper panel's.
   ================================================================== */

.nick-close {
	position: absolute;
	top: 0.5rem;
	right: 0.5rem;
	width: 2.5rem;
	height: 2.5rem;
	background: none;
	border: none;
	color: #aaa;
	font-size: 1.3rem;
	line-height: 1;
	cursor: pointer;
	z-index: 5;
}

.nick-close:hover,
.nick-close:focus {
	color: #fff;
}

@media (max-width: 760px) {

	/* Reserve a strip so the input row cannot ride over the cross, matching
	   how the whisper panel handles it. */
	.nick-panel {
		padding: 38px 12px calc(12px + env(safe-area-inset-bottom, 0px)) !important;
	}

	.nick-panel .nick-close {
		top: 5px !important;
		right: 8px !important;
		width: 34px !important;
		height: 34px !important;
		font-size: 22px !important;
		line-height: 34px !important;
		text-align: center;
		padding: 0 !important;
		color: #ddd !important;
	}

	body.kb-open .nick-panel {
		padding-top: 34px !important;
	}

	/* ---- portrait nickname panel tweaks ---- */

	/* Match the whisper panel's clearance so the cross sits clear of the row
	   below it rather than crowding the input. */
	.nick-panel {
		padding-top: 42px !important;
	}

	.nick-panel .nick-close {
		top: 6px !important;
		right: 8px !important;
	}

	body.kb-open .nick-panel {
		padding-top: 38px !important;
	}

	/* Clear is redundant on a phone - the field is one tap to select and the
	   keyboard has its own delete. Cancel and the cross both dismiss. */
	.nick-panel .nick-panel-bottom button:first-child {
		display: none !important;
	}

	/* A nickname is at most 16 characters; the field does not need the full
	   width of the sheet. */
	.nick-panel .nick-panel-top {
		justify-content: flex-start !important;
	}

	.nick-panel .nick-panel-input {
		flex: 0 1 auto !important;
		width: 58% !important;
		max-width: 58% !important;
	}
}

/* ==================================================================
   Nickname field awaiting input.

   iOS only opens the on-screen keyboard in response to a real gesture, so a
   programmatically focused field can sit there looking inert. This makes it
   unmistakable that a nickname is wanted until the first keystroke.
   ================================================================== */

.nick-panel-input.awaiting-input {
	animation: nickAwait 1.1s ease-in-out infinite;
	caret-color: #ff8800;
}

@keyframes nickAwait {
	0%, 100% { box-shadow: 0 0 0 0 rgba(31, 206, 59, 0.0); }
	50%      { box-shadow: 0 0 0 2px rgba(31, 206, 59, 0.55); }
}

@media (prefers-reduced-motion: reduce) {
	.nick-panel-input.awaiting-input { animation: none; box-shadow: 0 0 0 2px rgba(31,206,59,0.5); }
}

/* ==================================================================
   Fake caret in the nickname field.

   iOS Safari only raises the on-screen keyboard from a genuine user gesture,
   so an auto-opened panel cannot have a real blinking caret until the field
   is tapped. This draws one that blinks anyway, so the field reads as ready
   for input. It disappears the moment the field is genuinely focused or the
   first character is typed, handing over to the real caret.
   ================================================================== */

.fake-caret {
	display: none;
	position: absolute;
	left: 13px;
	top: 50%;
	width: 2px;
	height: 17px;
	margin-top: -8px;
	background: #ff8800;
	pointer-events: none;
	z-index: 4;
	animation: caretBlink 1.06s step-end infinite;
}

@keyframes caretBlink {
	0%, 49%   { opacity: 1; }
	50%, 100% { opacity: 0; }
}

/* Shown whenever the panel is open and the field has not been used yet -
   however the panel was opened. */
.nick-panel.show .nick-panel-input:not(:focus) ~ .fake-caret,
.nick-panel-input.awaiting-input ~ .fake-caret {
	display: block;
}

/* Once something has been typed, the field speaks for itself. */
.nick-panel-input.typed ~ .fake-caret {
	display: none !important;
}

/* Deliberately NOT keyed off :focus. iOS sets :focus from a programmatic
   focus() without opening the keyboard, which hid the caret at exactly the
   moment it was needed. Retire it when the keyboard is genuinely up, or once
   something has been typed. */
body.kb-open .fake-caret {
	display: none !important;
}

@media (prefers-reduced-motion: reduce) {
	.fake-caret { animation: none; opacity: 1; }
}

/* ==================================================================
   Chat bar flush against the keyboard.

   The gap came from two things stacking up: the composer keeps an
   env(safe-area-inset-bottom) pad for the home indicator, which is pointless
   once the keyboard covers that area, and nothing was forcing the column to
   fill exactly the visual-viewport height, so the bar sat at its natural
   position rather than at the bottom.
   ================================================================== */

@media (max-width: 760px) {

	.main-content {
		display: flex !important;
		flex-direction: column !important;
		height: var(--app-height, 100dvh) !important;
		max-height: var(--app-height, 100dvh) !important;
		overflow: hidden !important;
	}

	/* The message list absorbs all spare space, so the bar is pushed to the
	   bottom edge instead of floating above it. */
	#chatContent {
		flex: 1 1 auto !important;
		min-height: 0 !important;
	}

	#chatBar {
		flex: 0 0 auto !important;
		margin-bottom: 0 !important;
		padding-bottom: env(safe-area-inset-bottom, 0px);
	}

	#chatBar .border {
		margin-bottom: 0.15rem !important;
	}

	#chatMessageForm {
		margin-bottom: 0 !important;
	}

	/* Keyboard up: the home indicator is covered, so that reserve is dead
	   space between the composer and the keyboard. */
	body.kb-open #chatBar {
		padding-bottom: 0 !important;
	}
}

/* ==================================================================
   Last chat line getting clipped.

   .chat-message sets font-size:1.3rem with no line-height, so the line box is
   tighter than the glyphs and descenders (g, y, p) were being shaved off at
   the bottom edge of the scroll container. Gives the text room and leaves a
   little clearance under the final message. Applies at every width - this was
   visible on desktop as well as portrait.
   ================================================================== */

.chat-message {
	line-height: 1.35;
	padding-bottom: 1px;
}

#chatMessages {
	padding-bottom: 2.4rem;
}

#chatMessages > *:last-child {
	margin-bottom: 0.55rem;
}

/* The fake caret exists solely because iOS will not raise its keyboard from a
   programmatic focus. On desktop the field focuses normally and shows a real
   caret, so this must never appear there. */
@media (min-width: 761px) {
	.fake-caret {
		display: none !important;
	}
}

/* ==================================================================
   Server text panel - /motd and /rules

   Same WebTV panel treatment as the nickname and whisper sheets: #424242
   body, gold heading, inset bevel. The body scrolls so a long rules file
   stays readable without stretching the panel off-screen.
   ================================================================== */

#serverTextBackdrop {
	display: none;
	position: fixed;
	inset: 0;
	background: #0007;
	z-index: 9997;
}

#serverTextBackdrop.show { display: block; }

#serverTextPanel {
	display: none;
	position: fixed;
	left: 50%;
	top: 50%;
	transform: translate(-50%, -50%);
	width: 46vw;
	max-width: 720px;
	max-height: 72vh;
	padding: 1.4vw 1.6vw;
	box-sizing: border-box;
	flex-direction: column;
	background: #424242;
	color: var(--webtv-gold, #e7ce4a);
	border-radius: 6px;
	box-shadow:
		0.6vw 0.6vw #00000080,
		inset 1px 1px 1px #424242,
		inset 2px 2px 2px 2px #969696,
		inset -1px -1px 1px #424242,
		inset -2px -2px 2px 2px #202020;
	text-shadow: 0.1vw 0.1vw #000;
	z-index: 9998;
}

#serverTextPanel.show { display: flex; }

#serverTextTitle {
	flex: 0 0 auto;
	font-size: 1.5vw;
	font-weight: 600;
	margin-bottom: 0.7vw;
	letter-spacing: 0.02em;
}

#serverTextBody {
	flex: 1 1 auto;
	min-height: 0;
	overflow-y: auto;
	-webkit-overflow-scrolling: touch;
	background: #161616;
	border-width: 0.25vw;
	border-style: solid;
	border-color: #222 #888 #888 #222;
	padding: 0.7vw 0.9vw;
	color: var(--webtv-green, #1fce3b);
	font-family: var(--standard-font), monospace;
	font-size: 1.05vw;
	line-height: 1.45;
	white-space: pre-wrap;
	word-wrap: break-word;
	overflow-wrap: break-word;
	text-shadow: none;
	scrollbar-width: thin;
	scrollbar-color: #1fce3b #148726;
}

#serverTextButtons {
	flex: 0 0 auto;
	display: flex;
	justify-content: flex-end;
	margin-top: 0.9vw;
}

#serverTextClose {
	position: absolute;
	top: 0.4rem;
	right: 0.5rem;
	width: 2.2rem;
	height: 2.2rem;
	background: none;
	border: none;
	color: #aaa;
	font-size: 1.25rem;
	line-height: 1;
	cursor: pointer;
	z-index: 5;
}

#serverTextClose:hover,
#serverTextClose:focus { color: #fff; }

/* ---------------- portrait ---------------- */

@media (max-width: 760px) {

	#serverTextPanel {
		left: 0 !important;
		right: 0 !important;
		top: auto !important;
		bottom: 0 !important;
		transform: none !important;
		width: auto !important;
		max-width: none !important;
		/* Sits inside <body>, which is pinned to the visual viewport, so it
		   clears the on-screen keyboard without any offset arithmetic. */
		position: absolute !important;
		max-height: calc(var(--app-height, 100dvh) - 40px) !important;
		border-radius: 10px 10px 0 0;
		padding: 38px 12px calc(12px + env(safe-area-inset-bottom, 0px)) !important;
	}

	#serverTextTitle {
		font-size: 15px !important;
		margin-bottom: 7px !important;
	}

	#serverTextBody {
		font-size: 12.5px !important;
		line-height: 1.4 !important;
		border-width: 2px !important;
		padding: 7px 8px !important;
	}

	#serverTextButtons {
		margin-top: 9px !important;
		justify-content: center !important;
	}

	#serverTextButtons button {
		min-width: 50% !important;
		padding: 8px 16px !important;
		font-size: 13.5px !important;
	}

	#serverTextClose {
		top: 5px !important;
		right: 8px !important;
		width: 34px !important;
		height: 34px !important;
		font-size: 22px !important;
		line-height: 34px !important;
		text-align: center;
		color: #ddd !important;
	}
}

/* ==================================================================
   Room list panel

   Colours and column widths follow the original WebTV channellistformat
   template in /wtv/rooms.html: room name in lightblue, description and user
   count in lightgreen, on the #191919 body the old page used, with the count
   right-aligned in a narrow final column.
   ================================================================== */

#roomListBackdrop {
	display: none;
	position: fixed;
	inset: 0;
	background: #0007;
	z-index: 9997;
}

#roomListBackdrop.show { display: block; }

#roomListPanel {
	display: none;
	position: fixed;
	left: 11vw;
	top: auto;
	bottom: 4vw;
	transform: none;
	width: 78vw;
	max-width: none;
	height: 33vw;
	min-height: 200px;
	max-height: calc(100vh - 6vw);
	padding: 2vw 3.4vw 2.4vw 3.5vw;
	box-sizing: border-box;
	flex-direction: column;
	background: #424242;
	color: var(--webtv-gold, #e7ce4a);
	border-radius: 6px;
	box-shadow:
		0.6vw 0.6vw #00000080,
		inset 1px 1px 1px #424242,
		inset 2px 2px 2px 2px #969696,
		inset -1px -1px 1px #424242,
		inset -2px -2px 2px 2px #202020;
	text-shadow: 0.1vw 0.1vw #000;
	z-index: 9998;
}

#roomListPanel.show { display: flex; }

#roomListTitle {
	flex: 0 0 auto;
	text-align: center;
	font-size: 2vw;
	font-weight: 600;
	margin-bottom: 1vw;
}

#roomListHead {
	flex: 0 0 auto;
	display: flex;
	gap: 0.6vw;
	padding: 0 1vw 0.4vw;
	font-size: 1.3vw;
	opacity: 0.75;
	border-bottom: 1px solid #5a5a5a;
	margin-bottom: 0.3vw;
}

#roomListBody {
	flex: 1 1 auto;
	min-height: 0;
	overflow-y: auto;
	-webkit-overflow-scrolling: touch;
	background: #191919;
	border-width: 0.25vw;
	border-style: solid;
	border-color: #222 #888 #888 #222;
	padding: 0.4vw 0;
	scrollbar-width: thin;
	scrollbar-color: #1fce3b #148726;
	text-shadow: none;
}

.rl-row {
	display: flex;
	gap: 0.6vw;
	align-items: baseline;
	padding: 0.4vw 1vw;
	cursor: pointer;
	font-size: 1.4vw;
	line-height: 1.35;
}

.rl-row:hover,
.rl-row:focus {
	background: #243024;
	outline: none;
}

/* Proportions taken from the original template: 129 / 211 / 60 px. */
.rl-room {
	flex: 0 0 26%;
	min-width: 0;
	color: #189cd6;
	font-weight: 600;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.rl-topic {
	flex: 1 1 auto;
	min-width: 0;
	color: #44cc55;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}

.rl-count {
	flex: 0 0 12%;
	text-align: right;
	color: #44cc55;
}

.rl-empty {
	padding: 1vw;
	color: #44cc55;
	font-size: 1.4vw;
}

#roomListButtons {
	flex: 0 0 auto;
	display: flex;
	justify-content: flex-end;
	margin-top: 1.2vw;
}

#roomListButtons button {
	font-size: 1.5vw;
}

#roomListClose {
	position: absolute;
	top: 0.4rem;
	right: 0.5rem;
	width: 2.2rem;
	height: 2.2rem;
	background: none;
	border: none;
	color: #aaa;
	font-size: 1.25rem;
	line-height: 1;
	cursor: pointer;
	z-index: 5;
}

#roomListClose:hover,
#roomListClose:focus { color: #fff; }

/* ---------------- portrait ---------------- */

@media (max-width: 760px) {

	#roomListPanel {
		position: absolute !important;
		height: auto !important;
		min-height: 0 !important;
		left: 0 !important;
		right: 0 !important;
		top: auto !important;
		bottom: 0 !important;
		transform: none !important;
		width: auto !important;
		max-width: none !important;
		max-height: calc(var(--app-height, 100dvh) - 40px) !important;
		border-radius: 10px 10px 0 0;
		padding: 38px 12px calc(12px + env(safe-area-inset-bottom, 0px)) !important;
	}

	#roomListTitle { font-size: 15px !important; margin-bottom: 7px !important; }

	#roomListHead {
		font-size: 11px !important;
		gap: 8px !important;
		padding: 0 8px 4px !important;
	}

	#roomListBody { border-width: 2px !important; }

	.rl-row {
		font-size: 13px !important;
		gap: 8px !important;
		padding: 7px 8px !important;
	}

	/* Room names get more of a narrow screen; the topic is the first thing
	   that can afford to be clipped. */
	.rl-room { flex: 0 0 34% !important; }
	.rl-count { flex: 0 0 14% !important; }
	.rl-empty { font-size: 13px !important; padding: 10px !important; }

	#roomListButtons { margin-top: 9px !important; justify-content: center !important; }
	#roomListButtons button { min-width: 50% !important; padding: 8px 16px !important; font-size: 13.5px !important; }

	#roomListClose {
		top: 5px !important;
		right: 8px !important;
		width: 34px !important;
		height: 34px !important;
		font-size: 22px !important;
		line-height: 34px !important;
		text-align: center;
		color: #ddd !important;
	}
}

/* ==================================================================
   Status doubles as the Reconnect control.

   Sitting idle at the foot of the sidebar, the status line was pure
   decoration. Hovering it now swaps the label for a bold gold "Reconnect",
   matching the gold used on the whisper and nickname panels, and clicking it
   reconnects. The sidebar's old Reconnect slot became Room List.

   The element keeps the "clickable" class so main.js still draws the WebTV
   selection box around it on hover, exactly like the sidebar links.
   ================================================================== */

#connectionStatus {
	cursor: pointer;
	pointer-events: auto !important;
}

#connectionStatusAction {
	display: none;
	color: var(--webtv-gold, #e7ce4a);
	font-weight: 700;
}

#connectionStatus:hover #connectionStatusText,
#connectionStatus:focus #connectionStatusText {
	display: none;
}

#connectionStatus:hover #connectionStatusAction,
#connectionStatus:focus #connectionStatusAction {
	display: inline;
}

/* Full strength on hover - it is an action at that point, not background. */
#connectionStatus:hover,
#connectionStatus:focus {
	opacity: 1 !important;
}

/* Room list column headings in the same gold as the panel text, rather than
   the dimmed variant they started with. */
#roomListHead {
	color: var(--webtv-gold, #e7ce4a);
	opacity: 1;
}

/* ==================================================================
   Desktop nickname panel.

   Standardized on the Go to panel's footprint: 78vw wide, 33vw tall,
   anchored near the bottom. The label sits left with the field running
   long to its right, exactly like the Room name row; Clear/Cancel pin
   bottom-left and Change Nickname bottom-right.

   Portrait is untouched by this block.
   ================================================================== */

@media (min-width: 761px) {

	.nick-panel {
		width: 78vw !important;
		left: 11vw !important;
		/* The slide-up animation parks the panel at translateY(2vw), so 6vw
		   here nets out to the same 4vw clearance the Go to panel uses. */
		bottom: 6vw !important;
		height: 33vw !important;
		min-height: 200px !important;
		padding: 0 !important;
		box-sizing: border-box !important;
	}

	/* Nickname: [_________________________] on one row, like Room name. */
	.nick-panel .nick-panel-top {
		flex-wrap: nowrap !important;
		align-content: center !important;
		align-items: center !important;
		height: auto !important;
		max-height: none !important;
		gap: 1.1vw !important;
		margin: 2.6vw 3.4vw 0 3.5vw !important;
	}

	.nick-panel .nick-panel-label {
		flex: 0 0 auto !important;
		width: auto !important;
	}

	.nick-panel .nick-panel-input {
		flex: 1 1 auto !important;
		width: auto !important;
		max-width: none !important;
		min-width: 0 !important;
	}

	/* Current-nickname line sits under the field, in the open grey space,
	   starting where the field starts rather than at the label. */
	.nick-panel .nick-panel-status {
		position: static !important;
		bottom: auto !important;
		margin: 2vw 3.4vw 0 12.8vw !important;
		font-size: 1.4vw !important;
	}

	/* Change Nickname bottom-right, level with Clear/Cancel bottom-left. */
	.nick-panel .nick-panel-submit {
		top: auto !important;
		bottom: 3.2vw !important;
		right: 3.4vw !important;
		font-size: 1.5vw !important;
	}

	.nick-panel .nick-panel-bottom {
		position: absolute !important;
		left: 3.5vw !important;
		bottom: 3.2vw !important;
		margin: 0 !important;
		padding: 0 !important;
		border: 0 !important;
		gap: 1.1vw !important;
	}

	.nick-panel .nick-panel-bottom button {
		font-size: 1.5vw !important;
	}
}

/* ==================================================================
   Header notice strip (desktop).

   NickServ's registration hint and the Global random news arrive as NOTICEs
   and used to be written into the conversation, above the topic, where they
   stayed forever. They now stack under the room name and fade out after 9s.
   Portrait keeps them in the chat log - there is no room for a strip there.
   ================================================================== */

#headerNotice {
	display: none;
}

@media (min-width: 761px) {

	/* Anchored to the bottom of the header rather than measured down from its
	   top, so it always clears the room name whatever the header height works
	   out to. Lines stack upward from there. */
	#headerNotice {
		display: flex;
		flex-direction: column;
		justify-content: flex-end;
		gap: 0.1vw;
		position: absolute;
		left: 2vw;
		right: 17vw;
		bottom: 0.5vw;
		z-index: 1;
		pointer-events: none;
	}

	.header-notice-line {
		font-size: 0.95vw;
		line-height: 1.35;
		color: #eaf5ea;
		text-shadow: 0.06vw 0.06vw #000;
		white-space: nowrap;
		overflow: hidden;
		text-overflow: ellipsis;
		opacity: 0;
		/* Slow, unhurried fade in both directions. */
		transition: opacity 1500ms ease;
	}

	/* Deliberately faint - present if you look, easy to ignore otherwise. */
	.header-notice-line.show {
		opacity: 0.42;
	}
}

/* Wider Done button - a little breathing room either side of the word. */
#roomListDone {
	padding-left: 1.6rem;
	padding-right: 1.6rem;
}

/* Room list column headings share one colour. The heading cells reuse the row
   classes, so Room was picking up the blue used for actual room links while
   Description and Here took the green. Only the links should be blue. */
#roomListHead .rl-room,
#roomListHead .rl-topic,
#roomListHead .rl-count {
	color: #44cc55;
}


/* Room list: the two buttons were touching. */
#roomListButtons {
	gap: 1.4vw;
}

/* Join and part lines are status, not speech - italic like the other status
   messages. The upstream comment on these rules literally says "no italics",
   which set them apart from every other notice in the log. */
.chat-message.join,
.chat-message.part,
.chat-message.quit,
.chat-message.join .message,
.chat-message.part .message,
.chat-message.quit .message {
	font-style: italic;
}

/* Masks the room key without making it a password field, so no password
   manager offers to fill or save it. */
.masked-input {
	-webkit-text-security: disc;
	text-security: disc;
}

/* Kicks are status lines too. */
.chat-message.kick,
.chat-message.kick .message {
	font-style: italic;
}
/* ==================================================================
   "Go to" panel - join a room by name.

   Laid out to match the classic WebTV "Create a new chat room" dialog:
   a wide panel with a centered title, a Room name field beside a
   right-aligned label column, open grey space where the topic box sat,
   and a bottom-right strip holding the password checkbox and the Join
   Room button. Ticking the box reveals a Password field (the +k channel
   key) under Room name, the same length as the Room name field.
   ================================================================== */

#gotoBackdrop {
	display: none;
	position: fixed;
	inset: 0;
	background: #0006;
	z-index: 9997;
}

#gotoBackdrop.show { display: block; }

.goto-panel {
	display: none;
	position: fixed;
	left: 11vw;
	bottom: 4vw;
	width: 78vw;
	height: 33vw;
	min-height: 200px;
	padding: 0;
	box-sizing: border-box;
	background: #424242;
	color: var(--webtv-gold, #e7ce4a);
	border-radius: 0.5vw;
	box-shadow:
		0 0.6vw 0 #0008,
		inset 0.1vw 0.1vw 0.1vw #4e4e4e,
		inset 0.2vw 0.2vw 0.2vw 0.2vw #969696,
		inset -0.1vw -0.1vw 0.1vw #4e4e4e,
		inset -0.2vw -0.2vw 0.2vw 0.2vw #202020;
	text-shadow: 0.15vw 0.15vw #000;
	z-index: 9998;
}

.goto-panel.show { display: block; }

.goto-title {
	margin-top: 2.8vw;
	text-align: center;
	font-size: 2vw;
	color: var(--webtv-gold, #e7ce4a);
	text-shadow: 0.15vw 0.15vw #000;
}

/* Label column + field rows. Insets copied from the reference dialog:
   the field's right edge lines up with the Join Room button below it. */
.goto-row {
	display: flex;
	align-items: center;
	margin: 0 3.4vw 0 3.5vw;
}

.goto-top { margin-top: 3.4vw; }

.goto-label {
	flex: 0 0 12vw;
	text-align: right;
	margin-right: 1.1vw;
	color: var(--webtv-gold, #e7ce4a);
	font-size: 1.75vw;
	text-shadow: 0.15vw 0.15vw #000;
}

.goto-input {
	flex: 1 1 auto;
	min-width: 0;
	box-sizing: border-box;
	padding: 0.35vw 0.6vw;
	border-width: 0.35vw;
	border-style: solid;
	border-color: #222 #888 #888 #222;
	background: #161616;
	color: #ffc343;
	caret-color: #ff8800;
	font-size: 1.4vw;
	font-family: var(--standard-font);
}

/* Password reveals under Room name; Name only appears for locked rooms. */
.goto-keyrow,
.goto-namerow { display: none; }

.goto-keyrow.show,
.goto-namerow.show {
	display: flex;
	margin-top: 1.8vw;
}

/* Bottom-right strip: [x] Use a password for this room.  [Join Room] */
.goto-bottom {
	position: absolute;
	right: 3.4vw;
	bottom: 3.2vw;
	display: flex;
	align-items: center;
	gap: 1.1vw;
}

.wtv-check {
	display: flex;
	align-items: center;
	gap: 0.8vw;
	cursor: pointer;
	font-size: 1.75vw;
	color: var(--webtv-gold, #e7ce4a);
	user-select: none;
}

.wtv-check input[type=checkbox] {
	flex: 0 0 auto;
	margin: 0;
}

.goto-bottom button { font-size: 1.5vw; }

.goto-close {
	position: absolute;
	top: 0.4rem;
	right: 0.5rem;
	width: 2.2rem;
	height: 2.2rem;
	background: none;
	border: none;
	color: #aaa;
	font-size: 1.25rem;
	line-height: 1;
	cursor: pointer;
	z-index: 5;
}

.goto-close:hover,
.goto-close:focus { color: #fff; }

/* ---------------- portrait ---------------- */

@media (max-width: 760px) {

	.goto-panel {
		/* Absolute inside <body>, which JS pins to the visual viewport, so the
		   sheet rides above the on-screen keyboard - the same approach the
		   nickname and whisper panels use. */
		position: absolute !important;
		left: 0 !important;
		right: 0 !important;
		bottom: 0 !important;
		width: auto !important;
		height: auto !important;
		min-height: 0 !important;
		max-width: none !important;
		transform: none !important;
		max-height: calc(var(--app-height, 100dvh) - 40px);
		overflow-y: auto;
		-webkit-overflow-scrolling: touch;
		border-radius: 10px 10px 0 0;
		padding: 38px 12px calc(12px + env(safe-area-inset-bottom, 0px)) !important;
	}

	.goto-title {
		margin-top: 0;
		font-size: 16px;
	}

	/* Stacked layout: label above its field, full-width fields. */
	.goto-row {
		display: block;
		margin: 0;
	}

	.goto-top { margin-top: 12px; }

	.goto-label {
		display: block;
		text-align: left;
		font-size: 14px !important;
		margin: 0 0 5px;
	}

	.goto-input {
		display: block;
		width: 100% !important;
		/* 16px or larger stops iOS zooming the page on focus */
		font-size: 16px !important;
		padding: 8px 9px !important;
		border-width: 2px !important;
	}

	.goto-keyrow.show,
	.goto-namerow.show {
		display: block;
		margin-top: 10px;
	}

	.wtv-check {
		font-size: 13.5px !important;
		gap: 9px !important;
	}

	.goto-bottom {
		position: static;
		justify-content: space-between;
		gap: 9px !important;
		margin-top: 14px !important;
	}

	.goto-bottom button {
		flex: 0 0 auto !important;
		min-width: 0 !important;
		padding: 9px 12px !important;
		font-size: 13.5px !important;
	}

	.goto-close {
		top: 5px !important;
		right: 8px !important;
		width: 34px !important;
		height: 34px !important;
		font-size: 22px !important;
		line-height: 34px !important;
		text-align: center;
		color: #ddd !important;
	}

	body.kb-open .goto-panel { padding-top: 34px !important; }
}
