/* Spoqi — random one-to-one video chat. */

/* Theme has three states, and the third one is the default.
   An explicit choice stamps data-theme on <html>; with nothing stamped, the
   operating system decides. So the light palette is defined on bare :root, the
   dark one is defined twice — once for "system says dark and the visitor has
   not overridden it", once for "the visitor chose dark" — and no colour is ever
   declared only inside a media query. The duplication is the price of a toggle
   that can override the system in both directions. */

:root {
  --bg:           #f4f6fb;
  --surface:      #ffffff;
  --raised:       #eaeef7;
  --raised-hover: #dfe5f2;
  --line:         #d8dfee;
  --text:         #10162a;
  --muted:        #57627d;
  --placeholder:  #8a93a8;
  --accent:       #0a7a66;
  --accent-2:     #4f5ce8;
  --on-accent:    #ffffff;
  --danger:       #d33b3b;
  --warn:         #97650b;
  --topbar-bg:    rgba(244, 246, 251, .85);

  /* Video stays on near-black in both themes. The pane is letterbox around
     somebody's camera, and a white surround makes every face look worse. */
  --video-bg:     #05070e;
  --overlay:      rgba(5, 7, 14, .7);

  --radius:       14px;
  --radius-sm:    9px;
  --shadow:       0 12px 34px rgba(16, 22, 42, .14);
  --font:         "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg:           #0b0e18;
    --surface:      #131828;
    --raised:       #1c2338;
    --raised-hover: #232c46;
    --line:         #2a3350;
    --text:         #eef1f8;
    --muted:        #98a2c0;
    --placeholder:  #64708f;
    --accent:       #4de2c2;
    --accent-2:     #6c7bff;
    --on-accent:    #08111f;
    --danger:       #ff6b6b;
    --warn:         #ffcc66;
    --topbar-bg:    rgba(11, 14, 24, .85);
    --shadow:       0 18px 50px rgba(0, 0, 0, .45);
  }
}

:root[data-theme="dark"] {
  --bg:           #0b0e18;
  --surface:      #131828;
  --raised:       #1c2338;
  --raised-hover: #232c46;
  --line:         #2a3350;
  --text:         #eef1f8;
  --muted:        #98a2c0;
  --placeholder:  #64708f;
  --accent:       #4de2c2;
  --accent-2:     #6c7bff;
  --on-accent:    #08111f;
  --danger:       #ff6b6b;
  --warn:         #ffcc66;
  --topbar-bg:    rgba(11, 14, 24, .85);
  --shadow:       0 18px 50px rgba(0, 0, 0, .45);
}

/* Tells the browser which way to paint form controls, scrollbars and the
   spaces the page does not own. */
:root                     { color-scheme: light; }
:root[data-theme="dark"]  { color-scheme: dark; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) { color-scheme: dark; }
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  min-height: 100%;
}

/* The chat has to fit the window exactly: a page that scrolls while somebody
   is on camera means the other person slides out of view whenever a message
   arrives. `dvh` rather than `vh` because mobile browser chrome shrinks and
   grows, and `vh` measures the tallest state — which leaves the controls under
   the address bar for the entire call.

   Only the chat is locked. The landing page and the text pages scroll, because
   they are longer than the window and should be. */
body.in-chat {
  height: 100dvh;
  overflow: hidden;
}

body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 15px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--accent); }

/* ---------------------------------------------------------------- structure */

.app {
  display: flex;
  flex-direction: column;
  min-height: 100%;
}

body.in-chat .app { height: 100dvh; min-height: 0; }
body.in-chat main { min-height: 0; }

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 14px 22px;
  border-bottom: 1px solid var(--line);
  background: var(--topbar-bg);
  backdrop-filter: blur(8px);
  position: sticky;
  top: 0;
  z-index: 20;
}

.brand {
  display: flex;
  align-items: center;
  gap: 10px;
  font-weight: 800;
  font-size: 20px;
  letter-spacing: -.02em;
  color: var(--text);
  text-decoration: none;
}

.brand .dot {
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  box-shadow: 0 0 14px rgba(77, 226, 194, .6);
}

.topbar-right {
  display: flex;
  align-items: center;
  gap: 14px;
}

.theme-toggle {
  appearance: none;
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  padding: 0;
  flex: none;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: var(--raised);
  color: var(--muted);
  cursor: pointer;
  transition: background .15s ease, color .15s ease;
}

.theme-toggle:hover        { background: var(--raised-hover); color: var(--text); }
.theme-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.theme-toggle svg          { width: 17px; height: 17px; display: block; }

/* The icon shows the mode the button would switch you *to*, which is the
   convention people already read without thinking about it. `data-mode` is
   stamped by theme.js and holds the mode currently in effect — including when
   that mode came from the operating system rather than from a choice. */
.theme-toggle .icon-sun                    { display: none; }
.theme-toggle[data-mode="dark"] .icon-sun  { display: block; }
.theme-toggle[data-mode="dark"] .icon-moon { display: none; }

.status {
  font-size: 13px;
  color: var(--muted);
  display: flex;
  align-items: center;
  gap: 8px;
}

.status .pip {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--muted);
}

.status[data-tone="live"]    .pip { background: var(--accent); box-shadow: 0 0 10px var(--accent); }
.status[data-tone="waiting"] .pip { background: var(--warn);   animation: pulse 1.4s infinite; }
.status[data-tone="bad"]     .pip { background: var(--danger); }

@keyframes pulse { 50% { opacity: .25; } }

main { flex: 1; display: flex; flex-direction: column; }

/* ------------------------------------------------------------------ landing */

.landing {
  flex: 1;
  display: grid;
  place-items: center;
  padding: 48px 22px 64px;
}

.landing-inner { width: 100%; max-width: 620px; text-align: center; }

.landing h1 {
  font-size: clamp(34px, 6vw, 52px);
  line-height: 1.1;
  letter-spacing: -.03em;
  margin: 0 0 14px;
}

.landing h1 .grad {
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.lede { color: var(--muted); font-size: 17px; margin: 0 auto 30px; max-width: 46ch; }

.gate {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 22px;
  text-align: left;
  box-shadow: var(--shadow);
}

.check {
  display: flex;
  align-items: flex-start;
  gap: 11px;
  cursor: pointer;
  font-size: 14px;
  color: var(--muted);
  margin-bottom: 18px;
}

.check input {
  appearance: none;
  flex: none;
  width: 20px;
  height: 20px;
  margin-top: 1px;
  border: 1.5px solid var(--line);
  border-radius: 6px;
  background: var(--raised);
  cursor: pointer;
  position: relative;
}

.check input:checked {
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  border-color: transparent;
}

.check input:checked::after {
  content: "";
  position: absolute;
  inset: 0;
  margin: 4px 0 0 6px;
  width: 5px;
  height: 10px;
  border: solid var(--on-accent);
  border-width: 0 2.5px 2.5px 0;
  transform: rotate(45deg);
}

.check input:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

.rules {
  margin: 18px 0 0;
  padding: 0;
  list-style: none;
  font-size: 13px;
  color: var(--muted);
  display: grid;
  gap: 7px;
}

.rules li { display: flex; gap: 9px; align-items: flex-start; }
.rules li::before { content: "—"; color: var(--accent); flex: none; }

/* ------------------------------------------------------------------ buttons */

.btn {
  appearance: none;
  border: 1px solid transparent;
  border-radius: var(--radius-sm);
  font: inherit;
  font-weight: 650;
  padding: 12px 20px;
  cursor: pointer;
  transition: transform .08s ease, opacity .15s ease, background .15s ease;
  color: var(--on-accent);
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
}

.btn:hover:not(:disabled)  { transform: translateY(-1px); }
.btn:active:not(:disabled) { transform: translateY(0); }
.btn:disabled              { opacity: .4; cursor: not-allowed; }
.btn:focus-visible         { outline: 2px solid var(--accent); outline-offset: 3px; }

.btn-block { width: 100%; font-size: 16px; padding: 14px 20px; }

.btn-ghost {
  background: var(--raised);
  border-color: var(--line);
  color: var(--text);
}
.btn-ghost:hover:not(:disabled) { background: var(--raised-hover); }

.btn-danger { background: var(--danger); color: #fff; }

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

.stage {
  flex: 1;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 330px;
  gap: 14px;
  padding: 14px;
  min-height: 0;
}

.videos {
  display: flex;
  flex-direction: column;
  gap: 12px;
  min-height: 0;
}

/* One grid, three arrangements. The panes keep the same order in the markup in
   every layout, so switching never moves a <video> in the DOM — doing that
   detaches the element and drops the stream mid-chat. */
.panes {
  position: relative;
  flex: 1;
  min-height: 0;
  display: grid;
  gap: 12px;
}

.panes[data-layout="side"]    { grid-template-columns: 1fr 1fr; grid-template-rows: 1fr; }
.panes[data-layout="stacked"] { grid-template-columns: 1fr;     grid-template-rows: 1fr 1fr; }
.panes[data-layout="pip"]     { grid-template-columns: 1fr;     grid-template-rows: 1fr; }

.panes[data-layout="pip"] .pane.local {
  position: absolute;
  right: 14px;
  bottom: 14px;
  width: clamp(120px, 22%, 230px);
  aspect-ratio: 4 / 3;
  height: auto;
  z-index: 5;
  box-shadow: var(--shadow);
}

.pane {
  position: relative;
  min-width: 0;
  min-height: 0;
  background: var(--video-bg);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}

.pane video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  background: var(--video-bg);
}

/* The local preview mirrors, because everybody expects a mirror when they look
   at themselves. The remote one must not — it would flip the stranger's room. */
.pane.local video { transform: scaleX(-1); }

.pane .tag {
  position: absolute;
  left: 10px;
  top: 10px;
  z-index: 3;
  font-size: 11px;
  font-weight: 650;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--muted);
  background: var(--overlay);
  border-radius: 6px;
  padding: 4px 8px;
}

.pane .placeholder {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 12px;
  text-align: center;
  padding: 24px;
  color: var(--muted);
  font-size: 14px;
}

.spinner {
  width: 30px;
  height: 30px;
  border: 3px solid var(--line);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin .9s linear infinite;
}

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

/* Flagged: the person is shown their own camera blurred, so the warning is
   about something they can see rather than an abstraction. */
.pane.flagged video { filter: blur(22px) saturate(.4); }

.controls {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: center;
  flex: none;
}

.controls .spacer { flex: 1; }

.ctrl-group {
  display: flex;
  gap: 4px;
  padding: 3px;
  background: var(--raised);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}

/* One square icon button, used for every control on this bar. Every one of
   them also carries a title and an aria-label, because an icon on its own is a
   guess — and "which of these turns my camera off" is not a good guess to have
   to make while a stranger is watching. */
.ctrl {
  appearance: none;
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 7px;
  background: none;
  color: var(--muted);
  cursor: pointer;
  transition: background .14s ease, color .14s ease;
}

.ctrl svg { width: 19px; height: 19px; display: block; }
.ctrl:hover:not(:disabled) { background: var(--raised-hover); color: var(--text); }
.ctrl:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.ctrl:disabled { opacity: .35; cursor: not-allowed; }

/* The selected layout, and nothing else on the bar, is filled in. */
.ctrl[aria-current="true"] {
  background: var(--surface);
  border-color: var(--line);
  color: var(--accent);
}

/* A muted mic and a stopped camera are states worth shouting about: somebody
   who cannot hear a reply should be able to see why at a glance. */
.ctrl[aria-pressed="true"] {
  background: var(--danger);
  color: #fff;
}
.ctrl[aria-pressed="true"]:hover { background: var(--danger); color: #fff; }

.ctrl .off { display: none; }
.ctrl[aria-pressed="true"] .on  { display: none; }
.ctrl[aria-pressed="true"] .off { display: block; }

.btn-icon {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 9px 16px;
}
.btn-icon svg { width: 18px; height: 18px; }

.chat {
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  min-height: 0;
  overflow: hidden;
}

.chat-log {
  flex: 1;
  overflow-y: auto;
  padding: 14px;
  display: flex;
  flex-direction: column;
  gap: 9px;
  scrollbar-width: thin;
}

.msg {
  max-width: 88%;
  padding: 8px 12px;
  border-radius: 12px;
  font-size: 14px;
  word-break: break-word;
  white-space: pre-wrap;
}

.msg.them { background: var(--raised); align-self: flex-start; border-bottom-left-radius: 4px; }
.msg.you  { background: linear-gradient(135deg, var(--accent), var(--accent-2)); color: var(--on-accent); align-self: flex-end; border-bottom-right-radius: 4px; }

.msg.system {
  align-self: center;
  background: none;
  color: var(--muted);
  font-size: 12.5px;
  text-align: center;
  max-width: 100%;
  padding: 4px 0;
}

.typing { font-size: 12px; color: var(--muted); padding: 0 14px 6px; height: 18px; }

.chat-form {
  display: flex;
  gap: 8px;
  padding: 12px;
  border-top: 1px solid var(--line);
}

.chat-form input {
  flex: 1;
  min-width: 0;
  background: var(--raised);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  color: var(--text);
  font: inherit;
  padding: 10px 12px;
}

.chat-form input::placeholder { color: var(--placeholder); }
.chat-form input:focus { outline: none; border-color: var(--accent); }
.chat-form input:disabled { opacity: .5; }

/* -------------------------------------------------------------------- alerts */

.banner {
  border-radius: var(--radius-sm);
  padding: 11px 14px;
  font-size: 14px;
  font-weight: 600;
}

.banner.warn   { background: rgba(255, 204, 102, .14); color: var(--warn);   border: 1px solid rgba(255, 204, 102, .35); }
.banner.danger { background: rgba(255, 107, 107, .14); color: var(--danger); border: 1px solid rgba(255, 107, 107, .35); }

.notice {
  max-width: 520px;
  margin: 0 auto;
  text-align: center;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 34px 28px;
  box-shadow: var(--shadow);
}

.notice h2 { margin: 0 0 10px; font-size: 24px; letter-spacing: -.02em; }
.notice p  { color: var(--muted); margin: 0 0 20px; }
.notice.bad h2 { color: var(--danger); }

/* ------------------------------------------------------------------- footer */

.site-footer {
  border-top: 1px solid var(--line);
  padding: 26px 22px;
  text-align: center;
  color: var(--muted);
  font-size: 13px;
}

.site-footer nav { display: flex; gap: 18px; justify-content: center; flex-wrap: wrap; margin-bottom: 10px; }
.site-footer a { color: var(--muted); text-decoration: none; }
.site-footer a:hover { color: var(--text); }

.hidden { display: none !important; }

/* ------------------------------------------------------------ country badge */

.tag-country {
  margin-left: 7px;
  padding-left: 7px;
  border-left: 1px solid rgba(255, 255, 255, .22);
  font-weight: 600;
  letter-spacing: .04em;
}

.tag-country .flag {
  /* Flags are emoji, and emoji ignore the surrounding letter-spacing badly
     enough to look detached from the name without this. */
  margin-right: 5px;
  letter-spacing: 0;
  font-style: normal;
}

/* ------------------------------------------------------------------- modal */

.modal {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  place-items: center;
  padding: 20px;
  background: rgba(4, 6, 12, .62);
  backdrop-filter: blur(3px);
  overflow-y: auto;
}

.modal-card {
  width: 100%;
  max-width: 380px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 20px;
}

.modal-card h2 {
  margin: 0 0 14px;
  font-size: 19px;
  letter-spacing: -.01em;
}

.report-shot {
  position: relative;
  aspect-ratio: 4 / 3;
  background: var(--video-bg);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  overflow: hidden;
  margin-bottom: 10px;
}

.report-shot img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.report-shot-empty {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  color: var(--muted);
  font-size: 13px;
}

.report-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 16px;
}

.report-which {
  font-size: 13px;
  color: var(--muted);
  text-align: center;
  flex: 1;
}

.report-label {
  display: block;
  font-size: 13px;
  color: var(--muted);
  margin-bottom: 6px;
}

#report-reason {
  width: 100%;
  font: inherit;
  color: var(--text);
  background: var(--raised);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  margin-bottom: 18px;
}

#report-reason:focus { outline: none; border-color: var(--accent); }

.modal-actions {
  display: flex;
  gap: 9px;
  justify-content: flex-end;
}

.prose { max-width: 720px; margin: 0 auto; padding: 46px 22px 60px; }
.prose h1 { letter-spacing: -.02em; }
.prose h2 { margin-top: 34px; letter-spacing: -.01em; }
.prose p, .prose li { color: var(--muted); }

/* ------------------------------------------------------------------ responsive */

@media (max-width: 900px) {
  /* The chat drops under the video and both share the window. `minmax(0, …)`
     on the first row matters: a grid row defaults to min-content, which a
     video happily blows past, and the page would scroll — the one thing the
     chat must never do. */
  .stage {
    grid-template-columns: 1fr;
    grid-template-rows: minmax(0, 1.15fr) minmax(0, 1fr);
    padding: 10px;
    gap: 10px;
  }
  .panes[data-layout="pip"] .pane.local { right: 10px; bottom: 10px; }
  .controls { gap: 6px; }
  .ctrl { width: 34px; height: 34px; }
  .btn-icon span { display: none; }
  .btn-icon { padding: 9px 12px; }
}
