:root {
  color-scheme: dark;
  --bg: #121212;
  --surface: #1c1c1c;
  --surface-2: #262626;
  --border: #333333;
  --text: #e8e8e8;
  --muted: #a3a3a3;
  --faint: #737373;
  --accent: #d4d4d4;
  --live: #e5534b;
  --radius: 10px;
  --shadow: 0 12px 36px rgba(0, 0, 0, 0.5);
  --font: Consolas, 'Cascadia Mono', 'Courier New', monospace;
}

* { box-sizing: border-box; }

html, body { height: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 15px;
  line-height: 1.5;
}

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

button {
  cursor: pointer;
  border: 0;
  border-radius: 8px;
  padding: 10px 18px;
  background: var(--accent);
  color: #121212;
  font-weight: 700;
  transition: background 0.15s ease, transform 0.1s ease;
}
button:hover { background: #f0f0f0; }
button:active { transform: translateY(1px); }
button:focus-visible, input:focus-visible, .presence:focus-visible { outline: 2px solid var(--muted); outline-offset: 2px; }

button.ghost {
  background: transparent;
  color: var(--muted);
  border: 1px solid var(--border);
  padding: 6px 14px;
  font-weight: 400;
}
button.ghost:hover { color: var(--text); border-color: var(--faint); background: transparent; }

input {
  width: 100%;
  padding: 10px 12px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
}
input::placeholder { color: var(--faint); }

/* ------------------------------------------------------------ login */

.login-page {
  display: grid;
  place-items: center;
  padding: 24px 16px;
}

.login-card {
  width: 100%;
  max-width: 360px;
  padding: 32px 28px 28px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: var(--shadow);
}

.login-card h1 {
  margin: 0 0 20px;
  font-size: 1.6rem;
  font-weight: 700;
  text-align: center;
}

.login-form { display: grid; gap: 6px; }
.login-form label { font-size: 0.85rem; color: var(--muted); margin-top: 8px; }
.login-form label em { color: var(--faint); }

.login-form label.check {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin-top: 12px;
  cursor: pointer;
  color: var(--text);
  line-height: 1.4;
}
.login-form label.check input {
  width: auto;
  margin: 2px 0 0;
  accent-color: var(--accent);
}

.password-field { position: relative; }
.password-field input { padding-right: 44px; }

.login-form button.eye {
  position: absolute;
  top: 50%;
  right: 6px;
  transform: translateY(-50%);
  display: grid;
  place-items: center;
  margin: 0;
  padding: 6px;
  background: transparent;
  color: var(--faint);
  border-radius: 6px;
}
.login-form button.eye:hover { color: var(--text); background: var(--surface-2); }
.login-form button.eye[hidden] { display: none; }
.eye .eye-closed { display: none; }
.eye[aria-pressed="true"] .eye-open { display: none; }
.eye[aria-pressed="true"] .eye-closed { display: block; }
.login-form button { margin-top: 14px; padding: 12px; }

.error { display: none; margin: 8px 0 0; color: var(--live); font-size: 0.85rem; }
.error.show { display: block; }

/* ------------------------------------------------------------ cam page */

/* The cam page always fits the window exactly: no page scrolling. */
/* Pinned to the visible part of the screen (cam.js sets --app-h/--app-top from the
   visual viewport), so a phone keyboard can't push the camera off the top. */
.cam-page {
  position: fixed;
  left: 0;
  right: 0;
  top: var(--app-top, 0px);
  display: flex;
  flex-direction: column;
  height: 100vh;
  height: var(--app-h, 100dvh);
  overflow: hidden;
}

.topbar {
  position: relative;
  z-index: 10;
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 12px 24px;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
}

.brand { font-size: 1.25rem; font-weight: 700; white-space: nowrap; }

.status { margin-right: auto; margin-left: 12px; }

/* Hover or tap LIVE to see who's here. */
.presence {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  cursor: default;
  border-radius: 8px;
}

.pill {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 3px 11px;
  border-radius: 999px;
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  background: var(--surface-2);
  color: var(--faint);
  border: 1px solid var(--border);
}
.pill .dot { width: 8px; height: 8px; border-radius: 50%; background: currentColor; }
.pill.live { color: var(--text); border-color: var(--faint); }
.pill.live .dot { background: var(--live); animation: pulse 1.8s ease-in-out infinite; }

@keyframes pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(229, 83, 75, 0.6); }
  50% { box-shadow: 0 0 0 6px rgba(229, 83, 75, 0); }
}

.watchers { color: var(--muted); font-size: 0.9rem; white-space: nowrap; }
.me button { white-space: nowrap; }
.watchers span { color: var(--text); font-weight: 700; }

.online {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  min-width: 180px;
  max-width: 280px;
  max-height: 320px;
  overflow-y: auto;
  margin: 0;
  padding: 8px 0;
  list-style: none;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-4px);
  transition: opacity 0.12s ease, transform 0.12s ease, visibility 0.12s;
}
.online::before {
  content: 'Here now';
  display: block;
  padding: 0 14px 6px;
  color: var(--faint);
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.online li { padding: 3px 14px; overflow-wrap: anywhere; }
.online li.incog { color: var(--faint); font-style: italic; }

/* Incognito: no chat (the camera gets the whole width) and no colour picker.
   no-viewers also hides the viewer count and list (everyone incognito except admins). */
.incognito .chat,
.incognito .color-btn,
.incognito .color-panel { display: none; }
.incognito .layout { --chat-width: 0px; --gap: 0px; --chat-min: 0px; }
.no-viewers .watchers,
.no-viewers .online { display: none; }
.online:empty::after { content: 'Nobody yet'; display: block; padding: 3px 14px; color: var(--faint); }

.presence:hover .online,
.presence:focus-within .online {
  opacity: 1;
  visibility: visible;
  transform: none;
}

.me { position: relative; display: flex; align-items: center; gap: 10px; }
.me-name { color: var(--muted); }
.me-name strong { color: var(--text); }
.me form { margin: 0; }

/* .layout is the space under the top bar. The video is sized to the largest 16:9
   box that fits beside the chat; the chat then matches the video's height. */
.layout {
  --chat-width: clamp(240px, 30vw, 360px);
  --gap: 20px;
  flex: 1;
  min-height: 0;
  padding: 20px 24px 24px;
  container-type: size;
}

.row {
  --video-width: min(100cqw - var(--chat-width) - var(--gap), 100cqh * 16 / 9);
  display: grid;
  grid-template-columns: var(--video-width) var(--chat-width);
  justify-content: center;
  align-content: start;
  gap: var(--gap);
}

.stage { min-width: 0; }

.video-wrap {
  position: relative;
  aspect-ratio: 16 / 9;
  background: #000;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow);
}

.video-wrap video { width: 100%; height: 100%; display: block; object-fit: contain; background: #000; }

/* ------------------------------------------------------------ player controls */

/* Shown on hover, on tap (touch), and whenever the video is paused. */
.controls {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 28px 12px 10px;
  background: linear-gradient(transparent, rgba(0, 0, 0, 0.75));
  opacity: 0;
  transition: opacity 0.15s ease;
}
.video-wrap:hover .controls,
.video-wrap.show-controls .controls,
.video-wrap.paused .controls,
.controls:focus-within { opacity: 1; }

.controls button.ctl {
  display: grid;
  place-items: center;
  padding: 6px;
  background: transparent;
  color: var(--text);
  border-radius: 6px;
}
.controls button.ctl:hover { background: rgba(255, 255, 255, 0.12); }

#play .icon-play { display: none; }
#play.paused .icon-play { display: block; }
#play.paused .icon-pause { display: none; }

.scrub-wrap {
  position: relative;
  flex: 1;
  min-width: 60px;
  display: flex;
  align-items: center;
}

.scrub {
  flex: 1;
  width: 100%;
  height: 4px;
  padding: 0;
  margin: 0;
  border: 0;
  accent-color: var(--accent);
  cursor: pointer;
  background: transparent;
}

.behind {
  min-width: 52px;
  text-align: right;
  font-size: 0.85rem;
  color: var(--muted);
  font-variant-numeric: tabular-nums;
}
.behind.at-live { color: var(--text); font-weight: 700; }
.behind.at-live::before {
  content: '';
  display: inline-block;
  width: 7px;
  height: 7px;
  margin-right: 6px;
  border-radius: 50%;
  background: var(--live);
  vertical-align: 1px;
}

/* "live" flag: sits above the right end of the bar, its tail pointing at the live edge. */
.controls .golive {
  position: absolute;
  right: 8px; /* the slider's handle stops half its width short of the end */
  bottom: calc(100% + 10px);
  transform: translateX(50%);
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 3px 9px;
  background: rgba(20, 20, 20, 0.9);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 6px;
  font-size: 0.78rem;
  font-weight: 700;
  text-transform: lowercase;
  box-shadow: none;
  white-space: nowrap;
}
.controls .golive::after {
  content: '';
  position: absolute;
  left: 50%;
  top: 100%;
  transform: translateX(-50%);
  border: 6px solid transparent;
  border-top-color: rgba(20, 20, 20, 0.9);
}
.controls .golive:hover { background: #2a2a2a; }
.controls .golive:hover::after { border-top-color: #2a2a2a; }
.controls .golive[hidden] { display: none; }
.golive-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--live); }

.buffering-spinner {
  position: absolute;
  inset: 0;
  margin: auto;
  width: 36px;
  height: 36px;
  border: 3px solid rgba(255, 255, 255, 0.2);
  border-top-color: var(--text);
  border-radius: 50%;
  animation: spin 0.9s linear infinite;
  pointer-events: none;
  display: none;
}
.video-wrap.buffering .buffering-spinner { display: block; }

@keyframes spin { to { transform: rotate(360deg); } }

.video-wrap:fullscreen { border: 0; border-radius: 0; }

.offline-card {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  gap: 4px;
  text-align: center;
  padding: 16px;
  background: #0b0b0b;
}
.offline-card.hidden { display: none; }
.offline-title { margin: 0; font-size: 1.2rem; }
.offline-sub { margin: 0; color: var(--muted); font-size: 0.9rem; }

/* ------------------------------------------------------------ chat */

/* contain: size stops the chat from sizing the row, so the row takes the video's
   height and the chat stretches to match it exactly. */
.chat {
  contain: size;
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  overflow: hidden;
}

.messages {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  margin: 0;
  padding: 12px 16px;
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 8px;
  scrollbar-color: var(--border) transparent;
}

.msg { overflow-wrap: anywhere; }
.msg .meta { display: flex; align-items: baseline; gap: 8px; }
.msg .name { font-weight: 700; }
.msg .time { color: var(--faint); font-size: 0.75rem; }
.msg .text { margin: 1px 0 0; white-space: pre-wrap; }
.msg.mine .text {
  background: var(--surface-2);
  border-left: 2px solid var(--muted);
  padding: 2px 8px;
  border-radius: 0 6px 6px 0;
  margin-left: -10px;
}
.msg .text.big-emoji { font-size: 2.6rem; line-height: 1.15; }
.msg.mine .text.big-emoji { background: none; border-left: 0; margin-left: 0; padding: 0; }
.msg.system { color: var(--faint); font-size: 0.82rem; font-style: italic; text-align: center; }

.composer { position: relative; display: flex; gap: 8px; padding: 12px; border-top: 1px solid var(--border); }
.composer input { flex: 1; min-width: 0; }

/* Emoji fall back to the system emoji font, since Consolas has none. */
.composer .emoji-btn {
  padding: 6px 9px;
  background: transparent;
  border: 1px solid var(--border);
  font-size: 1.15rem;
  line-height: 1;
  filter: grayscale(0.6);
}
.composer .emoji-btn:hover,
.composer .emoji-btn[aria-expanded="true"] { background: var(--surface-2); filter: none; }

.color-btn {
  display: grid;
  place-items: center;
  align-self: stretch;
  padding: 0 9px;
  background: transparent;
  border: 1px solid var(--border);
}
.color-btn:hover,
.color-btn[aria-expanded="true"] { background: var(--surface-2); }
.color-dot {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--swatch, var(--muted));
  box-shadow: 0 0 0 2px rgba(0, 0, 0, 0.4);
}
.color-btn { --swatch: var(--muted); }

.color-panel {
  position: absolute;
  right: 0;
  top: calc(100% + 8px);
  z-index: 5;
  display: grid;
  grid-template-columns: repeat(6, 32px);
  gap: 8px;
  padding: 10px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.color-panel[hidden] { display: none; }
.color-panel .swatch {
  width: 32px;
  height: 32px;
  padding: 0;
  border-radius: 50%;
  background: var(--swatch);
  border: 2px solid transparent;
}
.color-panel .swatch:hover { background: var(--swatch); transform: scale(1.1); }
.color-panel .swatch[aria-pressed="true"] { border-color: var(--text); box-shadow: 0 0 0 2px var(--surface-2) inset; }
.color-panel .swatch-default {
  grid-column: 1 / -1;
  padding: 6px;
  background: transparent;
  color: var(--muted);
  border: 1px solid var(--border);
  font-weight: 400;
  font-size: 0.85rem;
}
.color-panel .swatch-default:hover { color: var(--text); background: transparent; }
.color-panel .swatch-default[aria-pressed="true"] { border-color: var(--muted); color: var(--text); }

.emoji-panel {
  position: absolute;
  right: 12px;
  bottom: calc(100% + 6px);
  z-index: 5;
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  gap: 2px;
  width: min(320px, calc(100% - 24px));
  max-height: 220px;
  overflow-y: auto;
  padding: 8px;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.emoji-panel[hidden] { display: none; }
.emoji-panel button {
  padding: 4px 0;
  background: transparent;
  font-size: 1.3rem;
  line-height: 1.2;
  border-radius: 6px;
}
.emoji-panel button:hover { background: rgba(255, 255, 255, 0.1); }

.chat-error { margin: 0; padding: 0 14px; color: var(--live); font-size: 0.82rem; }
.chat-error:not(:empty) { padding-bottom: 10px; }

/* ------------------------------------------------------------ small screens */

/* Phones and narrow windows: video on top, chat fills the rest.
   Width only: the on-screen keyboard makes the page shorter than it is wide,
   so an orientation check would wrongly switch to the side-by-side layout. */
@media (max-width: 700px) {
  .layout { --gap: 10px; --chat-min: 190px; padding: 10px; }
  /* Chat is always full width. The video shrinks (centred) only when there isn't
     room for it plus --chat-min of chat, e.g. while the keyboard is open. */
  .row {
    --video-width: min(100cqw, (100cqh - var(--chat-min) - var(--gap)) * 16 / 9);
    height: 100%;
    grid-template-columns: 100%;
    grid-template-rows: auto minmax(0, 1fr);
    align-content: stretch;
  }
  .stage { justify-self: center; width: var(--video-width); }
  .chat { contain: size; }
  .topbar { padding: 8px 12px; gap: 10px; }
  .brand { font-size: 1.05rem; }
  .status { margin-left: 0; }
  .me-name { display: none; }
  .online { left: auto; right: auto; }
  .messages { padding: 10px 12px; }
  .composer { padding: 8px; }
  /* 16px stops iPhones zooming in when you tap the message box. */
  input { font-size: 16px; }
}

/* Small phones: tighten the top bar so it fits on one line. */
@media (max-width: 440px) {
  .topbar { gap: 8px; padding: 8px 10px; }
  .brand { font-size: 1rem; }
  .status .presence { gap: 8px; }
  .pill { padding: 3px 8px; letter-spacing: 0.03em; }
  .me { gap: 6px; }
  .me button.ghost { padding: 5px 9px; }
  .color-btn { padding: 0 7px; }
}

@media (max-width: 370px) {
  .watchers { display: none; }
}

/* Phone with the keyboard open: hide the top bar so the video and chat get the room. */
/* Phone with the keyboard open: camera stays full size, chat shrinks to a small strip
   (latest message or two plus the message box), and the top bar hides to make room.
   .keyboard comes from cam.js, since iPhones don't change the page height for the keyboard. */
@media (max-width: 700px) and (max-height: 500px) {
  .topbar { display: none; }
  .layout { --gap: 6px; --chat-min: 100px; padding: 6px; }
}
@media (max-width: 700px) {
  .keyboard .topbar { display: none; }
  .keyboard .layout { --gap: 6px; --chat-min: 100px; padding: 6px; }
}
