:root {
  /*
   * A near-black base with a violet cast rather than a neutral grey.
   *
   * Pure #000 makes every surface above it look like a separate window, and
   * neutral greys next to a purple accent read as dirty. Tinting the whole
   * scale towards the accent is what makes the dark feel deliberate instead of
   * merely unlit.
   */
  /*
   * Paltalk's palette: a light interface with one strong blue.
   *
   * The whole scheme rests on the blue being the only saturated colour. Panels
   * are white, the page behind them is a barely-there grey so those panels read
   * as raised, and every divider is faint - close enough to the background that
   * it separates without drawing a line you notice. Add a second bright colour
   * and the blue stops meaning "this is the thing to press".
   */
  /*
   * Near-black with a magenta-to-violet accent.
   *
   * The reference gets its look from restraint: one gradient, used sparingly,
   * against a background that is almost but not quite black. The surfaces are
   * barely lighter than the page - a few points of luminance - so panels read as
   * edges rather than as boxes, and the accent is the only thing on screen with
   * any saturation. Lighten the greys or add a second bright colour and it turns
   * into an ordinary dark theme.
   */
  /*
   * White, with one pink.
   *
   * The reference gets its calm from restraint: white panels, a page a shade
   * cooler than them so the panels read as raised, and hairline borders. The
   * pink is the only saturated colour, which is what lets it mean "this one".
   *
   * Two pinks, for two jobs: --accent is dark enough to read as text on white
   * (4.6:1), --accent-hot is the brighter one used on fills where the text is
   * white. Using the bright one for text is the usual way a pink theme ends up
   * unreadable.
   */
  --bg: #f6f7f9;
  --surface: #ffffff;
  --surface-2: #f3f4f7;
  --surface-3: #e9ebf0;
  --line: #e6e8ed;
  --line-strong: #d3d7df;
  --text: #16181d;
  --muted: #5f6672;

  /* Gender tints, dark enough to read on white. */
  --male: #1668b0;
  --female: #c2166f;
  --couple: #6f47b8;
  --other: #5c6672;
  --online: #15803d;

  --accent: #e0157a;
  /* Used behind white text as well as for glows, so it has to clear 4.5 itself -
     the brighter pink that looked right on a dark page does not here. */
  --accent-hot: #dd1478;
  --accent-2: #b8156b;
  --accent-deep: #c00f68;
  --accent-soft: #fdeaf3;
  --danger: #d92d43;

  --grad: linear-gradient(135deg, var(--accent-hot) 0%, var(--accent) 55%, var(--accent-2) 100%);

  /* Soft and low. On white a heavy shadow reads as a smudge; these only need to
     lift a panel off the page behind it. */
  --shadow-sm: 0 1px 2px rgba(22, 24, 29, .05);
  --shadow-md: 0 2px 10px rgba(22, 24, 29, .07);
  --shadow-lg: 0 12px 40px rgba(22, 24, 29, .13);
  --glow: 0 4px 18px rgba(224, 21, 122, .16);
  --glow-hot: 0 6px 22px rgba(255, 61, 153, .3);

  --radius: 14px;
  --bar: 56px;
  --shell: 620px;
  /* Landing background. Swap this one line to change the hero image. */

  --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}

* { box-sizing: border-box; }

/* The UA rule for [hidden] is display:none, but any author display rule beats
   it. .screen and .composer both set display, so hidden must be forced here or
   every screen renders at once. */
[hidden] { display: none !important; }

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  font-size: 16px;
  -webkit-font-smoothing: antialiased;
  overscroll-behavior-y: none;
}

body { overflow: hidden; }

input, textarea, select, button { font: inherit; color: inherit; }
button { cursor: pointer; }
a { color: var(--accent); }

.ic {
  width: 22px;
  height: 22px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.9;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex: none;
}

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

.screen {
  position: fixed;
  inset: 0;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  max-width: var(--shell);
  margin: 0 auto;
  border-left: 1px solid var(--line);
  border-right: 1px solid var(--line);
}

.screen--overlay {
  z-index: 20;
  animation: slide-in .18s ease-out;
}

@keyframes slide-in {
  from { transform: translateX(18px); opacity: 0; }
  to { transform: none; opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .screen--overlay { animation: none; }
}

/* ---------- join ---------- */

.screen--join { overflow-y: auto; display: block; }

.join {
  max-width: 420px;
  margin: 0 auto;
  padding: 40px 20px calc(40px + env(safe-area-inset-bottom));
}

.join__head { margin-bottom: 28px; }

.brand {
  font-size: 34px;
  font-weight: 800;
  letter-spacing: -0.03em;
  line-height: 1;
}

.brand span { color: var(--accent); }

.join__lead {
  margin: 10px 0 0;
  color: var(--muted);
  font-size: 15px;
}

.join__note {
  margin: 14px 0 0;
  color: var(--muted);
  font-size: 12.5px;
  text-align: center;
}

.form { display: flex; flex-direction: column; gap: 16px; }

.field { display: flex; flex-direction: column; gap: 7px; }
.field--age { width: 96px; }
.field--grow { flex: 1; }
.row { display: flex; gap: 12px; }

.field__label {
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--muted);
}

.field__label em {
  font-style: normal;
  text-transform: none;
  letter-spacing: 0;
  font-weight: 400;
  opacity: .7;
}

.field input,
.field select,
.field textarea {
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 13px 14px;
  outline: none;
  width: 100%;
  resize: none;
}

.field input:focus,
.field select:focus,
.field textarea:focus {
  border-color: var(--accent);
}

.segment {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 6px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: 5px;
}

.segment__btn {
  background: none;
  border: 0;
  border-radius: 8px;
  padding: 9px 4px;
  font-size: 14px;
  color: var(--muted);
}

.segment__btn.is-active {
  background: var(--surface);
  color: var(--accent);
  font-weight: 700;
  box-shadow: var(--shadow-sm);
}

.photo-pick {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  height: 108px;
  border: 1px dashed var(--line);
  border-radius: 12px;
  background: var(--surface-2);
  color: var(--muted);
  overflow: hidden;
  position: relative;
  cursor: pointer;
}

.photo-pick__hint { display: flex; align-items: center; gap: 8px; font-size: 14px; }
.photo-pick img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

.form__error {
  margin: 0;
  color: var(--danger);
  font-size: 14px;
}

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

.btn {
  border: 1px solid var(--line);
  background: var(--surface-2);
  border-radius: 12px;
  padding: 12px 16px;
  font-weight: 600;
}

.btn--primary {
  background: linear-gradient(135deg, var(--accent) 0%, #5a0bd8 100%);
  border-color: transparent;
  color: #fff;
  font-weight: 700;
}
.btn--primary:hover { box-shadow: 0 6px 18px rgba(29, 161, 228, .32); }
.btn--primary:disabled { opacity: .55; }
.btn--block { width: 100%; }
.btn--ghost { background: none; }
.btn--sm { padding: 8px 12px; font-size: 13px; }
/* Needs its own fill: white text with no background of its own was invisible
   the moment the page went light. */
.btn--danger { background: #d60e6c; border-color: transparent; color: #fff; }
.btn--danger:hover { background: #c93a50; }

/* ---------- tabs ---------- */

.tabs {
  display: flex;
  height: var(--bar);
  border-bottom: 1px solid var(--line);
  background: var(--surface);
  flex: none;
}

.tab {
  flex: 1;
  background: none;
  border: 0;
  border-bottom: 2px solid transparent;
  color: var(--muted);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-size: 14px;
  position: relative;
}

.tab.is-active { color: var(--accent); border-bottom-color: var(--accent); font-weight: 650; }
.tab span { display: none; }

@media (min-width: 420px) {
  .tab span { display: inline; }
}

.badge {
  position: absolute;
  top: 9px;
  left: 50%;
  margin-left: 4px;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 9px;
  background: var(--accent);
  color: #fff;
  font-size: 11px;
  font-style: normal;
  font-weight: 700;
  line-height: 18px;
  text-align: center;
}

/* ---------- panes ---------- */

/* main column holds the header, tabs, ad slot and the scrolling panes */
.main {
  flex: 1;
  min-width: 0;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

/* only this part scrolls, so the ad slot stays pinned under the menu */
.panes { flex: 1; min-height: 0; position: relative; }

.pane {
  display: none;
  position: absolute;
  inset: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}

.pane.is-active { display: block; }

/* ---------- advertising ---------- */

.adslot {
  flex: none;
  border-bottom: 1px solid var(--line);
  background: var(--surface);
  overflow: hidden;
  display: block;
}

.adslot iframe {
  border: 0;
  display: block;
  width: 100%;
  margin: 0 auto;
  max-width: 970px;
}

/* ---------- desktop sidebar ---------- */

.sidebar { display: none; }

@media (min-width: 900px) {
  /* Wider than before: the two-column room needs the room, and 1180px left the
     cams squeezed once the 250px sidebar had taken its share. */
  #view-app { max-width: 1700px; flex-direction: row; }

  .sidebar {
    display: flex;
    flex-direction: column;
    width: 250px;
    flex: none;
    border-right: 1px solid var(--line);
    background: var(--surface);
    padding: 16px 12px;
  }

  /* the in-column header and tab bar are the mobile chrome; hide on desktop */
  .main > .topbar,
  .main > .tabs { display: none; }

  .sidebar__brand {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 6px 8px 16px;
    gap: 8px;
  }

  .sidenav { display: flex; flex-direction: column; gap: 4px; }

  .sidenav__item {
    display: flex;
    align-items: center;
    gap: 13px;
    padding: 12px 14px;
    border: 0;
    border-radius: 11px;
    background: none;
    color: var(--muted);
    font-size: 15.5px;
    font-weight: 600;
    text-align: left;
    position: relative;
  }

  .sidenav__item:hover { background: var(--surface-2); color: var(--accent); }
  .sidenav__item.is-active {
    background: linear-gradient(135deg, var(--accent) 0%, #5f1ab8 100%);
    color: #fff;
  }
  .sidenav__item .ic { width: 21px; height: 21px; }

  .badge--inline {
    position: static;
    margin-left: auto;
    top: auto;
    left: auto;
  }

  .sidebar__banner {
    margin-top: auto;
    padding-top: 16px;
    display: flex;
    justify-content: center;
  }

  .sidebar__banner iframe { border: 0; display: block; width: 100%; max-width: 300px; }
}

@media (min-width: 900px) {
  /* Overlays (profile, chat, snap) sit over the main column, not the whole
     window, so the sidebar stays put and visible.

     The app box is centered at up to 1180px. Its left edge is at
     max(0px, (100vw - 1180px) / 2); the main column starts 250px past that. */
  .screen--overlay, .screen--snap {
    max-width: none;
    margin: 0;
    left: calc(max(0px, (100vw - 1180px) / 2) + 250px);
    right: max(0px, (100vw - 1180px) / 2);
    border-right: 1px solid var(--line);
  }
}

.toolbar {
  position: sticky;
  top: 0;
  z-index: 5;
  background: var(--bg);
  padding: 12px 14px 10px;
  border-bottom: 1px solid var(--line);
}

.toolbar__top {
  display: flex;
  align-items: center;
  gap: 10px;
}

.toolbar__search-btn {
  flex: none;
  width: 38px;
  height: 38px;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--muted);
  display: flex;
  align-items: center;
  justify-content: center;
}

.toolbar__search-btn.is-active { background: var(--accent); border-color: var(--accent); color: #fff; }

.search {
  display: flex;
  align-items: center;
  gap: 9px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 11px;
  padding: 0 12px;
  color: var(--muted);
  margin-top: 10px;
}

.search input {
  flex: 1;
  background: none;
  border: 0;
  outline: none;
  padding: 11px 0;
  color: var(--text);
}

.search__clear {
  flex: none;
  background: none;
  border: 0;
  color: var(--muted);
  display: flex;
  align-items: center;
  padding: 4px;
}

.chips { display: flex; gap: 7px; overflow-x: auto; scrollbar-width: none; flex: 1; min-width: 0; }
.chips::-webkit-scrollbar { display: none; }

.chip {
  flex: none;
  background: var(--surface-2);
  border: 1px solid var(--line);
  color: var(--muted);
  border-radius: 999px;
  padding: 7px 13px;
  font-size: 13.5px;
}

.chip:hover { border-color: var(--line-strong); color: var(--text); }
.chip.is-active {
  background: linear-gradient(135deg, #8f0f4b 0%, #d60e6c 100%);
  color: #fff;
  border-color: transparent;
  font-weight: 600;
  box-shadow: 0 2px 8px rgba(29, 161, 228, .24);
}

/* ---------- lists ---------- */

.list { padding: 10px 12px 16px; display: flex; flex-direction: column; gap: 8px; }

.row-item {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 11px 13px;
  width: 100%;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 15px;
  text-align: left;
  box-shadow: var(--shadow-sm);
  /*! transition: transform .13s ease, box-shadow .13s ease, border-color .13s ease; */
}

.row-item:hover {
  border-color: var(--accent);
  box-shadow: var(--shadow-md);
  transform: translateY(-1px);
}
.row-item:active { transform: none; box-shadow: var(--shadow-sm); }

/* A row that just arrived over the socket slides in, so the list visibly
   reacts instead of silently growing. */
.row-item--enter, .tile--enter { animation: row-in .34s cubic-bezier(.22, 1, .36, 1); }

@keyframes row-in {
  from { opacity: 0; transform: translateY(-8px) scale(.98); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .row-item--enter, .tile--enter { animation: none; }
}

/* ---------- bottom navigation ---------- */

/* The main column is a flex column, so a nav placed last simply sits at the
   bottom; no fixed positioning and therefore no overlap with the scroll area. */
.tabs--bottom {
  border-bottom: 0;
  border-top: 1px solid var(--line);
  height: auto;
  padding-bottom: env(safe-area-inset-bottom);
  /*! box-shadow: 0 -2px 14px rgba(0, 0, 0, .45); */
}

.tabs--bottom .tab {
  flex-direction: column;
  gap: 3px;
  height: 60px;
  border-bottom: 0;
  border-top: 2px solid transparent;
  font-size: 11.5px;
}

.tabs--bottom .tab .ic { width: 23px; height: 23px; }
.tabs--bottom .tab.is-active { border-top-color: var(--accent); }

/* badge sits on the icon rather than beside the label */
.tabs--bottom .badge { top: 6px; left: 50%; margin-left: 3px; }

/* ---------- profile button in the top bar ---------- */

.topbar__me {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 3px 9px 3px 3px;
  border: 1px solid transparent;
  border-radius: 999px;
  background: none;
  color: var(--muted);
  font-size: 13px;
  font-weight: 600;
  flex: none;
}

.topbar__me:hover { background: var(--surface-2); }

.topbar__me.is-active {
  background: var(--accent-soft);
  border-color: var(--accent);
  color: var(--accent);
}

.topbar__me .avatar { width: 32px; height: 32px; font-size: 13px; box-shadow: none; }
.topbar__melabel { white-space: nowrap; }

@media (max-width: 400px) { .topbar__melabel { display: none; } }


/* ---------- live cams ---------- */

.cams {
  border-bottom: 1px solid var(--line);
  background: linear-gradient(180deg, var(--surface-2) 0%, var(--surface) 100%);
  padding: 12px 14px 14px;
}

/* "Live now 0/12" kop verwijderd; #cams-count blijft in de DOM voor app.js.
   De strip komt hierdoor hoger en er is meer ruimte voor de chatroom. */
.cams__head { display: none; }

.cams__title {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  font-size: 16px;
  font-weight: 750;
  letter-spacing: -0.015em;
}

.cams__pulse {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: #e8203f;
  box-shadow: 0 0 8px rgba(232, 32, 63, .7);
  animation: live-pulse 1.8s ease-in-out infinite;
}

@media (prefers-reduced-motion: reduce) { .cams__pulse { animation: none; } }

.cams__count { color: var(--muted); font-weight: 600; font-size: 13.5px; }

/* Five slots side by side, scrollable on a narrow phone. */
.cams__strip {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(84px, 1fr);
  gap: 7px;
  overflow-x: auto;
  scrollbar-width: none;
  padding-bottom: 2px;
}

.cams__strip::-webkit-scrollbar { display: none; }

.cam {
  position: relative;
  z-index: 0;
  isolation: isolate;
  /* Square keeps the strip short so the expanded player gets the room. */
  aspect-ratio: 1 / 1;
  border-radius: 12px;
  overflow: hidden;
  background: #14101a;
  border: 1px solid var(--line);
  padding: 0;
  min-width: 0;
}

.cam__video { position: absolute; inset: 0; background: #14101a; }
.cam__video video { width: 100%; height: 100%; object-fit: cover; display: block; }

/* The still that stands in for a live stream in the strip. */
.cam__thumb {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  /* Cross-fade on refresh, so a new frame does not land as a visible jolt every
     ten seconds across ten tiles at once. */
  transition: opacity .25s ease;
}

.cam__badge {
  position: absolute;
  top: 6px;
  left: 6px;
  z-index: 1;
  font-size: 9.5px;
  font-weight: 800;
  letter-spacing: .06em;
  color: #fff;
  background: #f90f9e;
  padding: 2px 6px;
  border-radius: 4px;
}

.cam__you {
  position: absolute;
  top: 6px;
  right: 6px;
  z-index: 1;
  font-size: 9.5px;
  font-weight: 800;
  letter-spacing: .04em;
  color: #14101a;
  background: #fff;
  padding: 2px 6px;
  border-radius: 4px;
}

.cam__eyes {
  position: absolute;
  top: 6px;
  right: 6px;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 3px;
  padding: 2px 6px 2px 5px;
  border-radius: 999px;
  background: rgba(0, 0, 0, .55);
  backdrop-filter: blur(4px);
  color: #fff;
  font-size: 10.5px;
  font-weight: 700;
}

.cam__eyes .ic { width: 12px; height: 12px; }

.cam__name {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1;
  padding: 14px 6px 5px;
  font-size: 11.5px;
  font-weight: 700;
  color: #fff;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  background: linear-gradient(to top, rgba(0, 0, 0, .82), transparent);
  text-shadow: 0 1px 3px rgba(0, 0, 0, .6);
}

.cam__name i { font-style: normal; font-weight: 400; opacity: .85; }

.cam.is-mine { border-color: var(--accent); box-shadow: 0 0 0 2px var(--accent); }

/* an empty slot invites you to take it */
.cam--free {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  background: var(--surface-2);
  border: 1.5px dashed var(--line-strong);
  color: var(--muted);
  font-size: 10.5px;
  font-weight: 600;
}

.cam--free .ic { width: 19px; height: 19px; }
.cam--free:hover { border-color: var(--accent); color: var(--accent); background: var(--surface-2); }

.cams__note {
  margin: 10px 0 0;
  font-size: 13px;
  color: var(--danger);
}

@media (min-width: 900px) {
  .cams { padding: 16px 18px 18px; }
  /* Ten tiles across would be postage stamps; let them keep a floor and scroll. */
  .cams__strip { grid-auto-columns: minmax(96px, 1fr); }
}





/* the strip stays visible but reads as inactive while we wait for a seat */
.cams__strip.is-dimmed { opacity: .45; pointer-events: none; }

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

.modal {
  position: fixed;
  inset: 0;
  z-index: 80;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 20px;
}

.modal__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, .68);
  backdrop-filter: blur(4px);
  animation: fade-in .16s ease-out;
}

.modal__card {
  position: relative;
  width: 100%;
  max-width: 380px;
  background: var(--surface);
  border-radius: 20px;
  padding: 26px 24px 22px;
  text-align: center;
  box-shadow: 0 24px 60px rgba(40, 8, 26, .34);
  animation: modal-in .2s cubic-bezier(.22, 1, .36, 1);
}

@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes modal-in {
  from { opacity: 0; transform: translateY(14px) scale(.97); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) {
  .modal__backdrop, .modal__card { animation: none; }
}

.modal__icon {
  width: 56px;
  height: 56px;
  margin: 0 auto 14px;
  border-radius: 50%;
  background: var(--accent-soft);
  color: var(--accent);
  display: flex;
  align-items: center;
  justify-content: center;
}

.modal__icon .ic { width: 27px; height: 27px; }

.modal__title {
  margin: 0 0 8px;
  font-size: 20px;
  font-weight: 750;
  letter-spacing: -0.02em;
}

.modal__text {
  margin: 0 0 16px;
  font-size: 14.5px;
  line-height: 1.55;
  color: var(--muted);
}

.modal__text b { color: var(--text); font-weight: 700; }

.modal__card--ask { text-align: left; }
.modal__card--ask .modal__icon { margin-left: 0; }
.modal__card--ask .modal__title { text-align: left; }

.modal__icon--danger { background: rgba(232, 69, 91, .12); color: var(--danger); }

.modal__actions {
  display: flex;
  gap: 10px;
  margin-top: 4px;
}

/* The confirming action sits on the right, where the thumb lands last, so a
   destructive one is not the first thing hit by accident. */
.modal__actions .btn { flex: 1; }

.modal__card--ask .field { margin-bottom: 16px; }

.modal__card--ask textarea {
  width: 100%;
  resize: vertical;
  min-height: 78px;
}

.modal__wait {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  margin-bottom: 18px;
  padding: 9px 12px;
  border-radius: 10px;
  background: var(--surface-2);
  font-size: 13px;
  font-weight: 600;
  color: var(--muted);
}

.modal__wait i {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--accent);
  animation: live-pulse 1.4s ease-in-out infinite;
}

@media (prefers-reduced-motion: reduce) { .modal__wait i { animation: none; } }

/* the strip stays visible but reads as inactive while we wait for a seat */

/* ---- expanded cam ---- */

/*
 * The expanded cam sits above the slots, everywhere.
 *
 * Done with flex order rather than by moving the element, because the markup
 * order is what a screen reader and keyboard follow: the strip is the list you
 * choose from, and the player is what that choice produced. Visually the player
 * wants to be first - it is the thing being watched, and having it below the
 * grid pushed it under the fold on a phone the moment the grid had more than a
 * few tiles.
 */
.cams {
  display: flex;
  flex-direction: column;
}

/* The player is a full-screen overlay, so it is out of the flow and this order
   rule has nothing to act on. Kept as a note rather than a rule: leaving a
   declaration that does nothing invites someone to reason from it later. */
.cams .cams__strip { order: 1; }
.cams .cams__count { order: 2; }

/*
 * The stage is capped in height, not just given a ratio.
 *
 * A 3:4 box on a phone is around 500px tall. Stacked under the strip and above
 * the chat that overflows the pane, and because the pane clips, what gets cut is
 * the bottom of the player - exactly where the name and viewer count sit. The
 * cap keeps the whole player on screen; the video letterboxes inside it, so the
 * full picture is still visible whatever shape the box ends up.
 */
.cambig__stage {
  position: relative;
  z-index: 1;
  flex: none;
  width: 100%;
  max-width: 640px;
  max-height: 52vh;
  aspect-ratio: 3 / 4;
  border-radius: 18px;
  border: 0;
  overflow: hidden;
  background: #07050a;
  box-shadow: var(--shadow-lg);
}

/* Landscape phones have almost no vertical room, so give the player less of it
   and let the chat keep its share. */
@media (max-height: 520px) {
  .cambig__stage { max-height: 62vh; }
}

.cambig__video { position: absolute; inset: 0; }
.cambig__video video { width: 100%; height: 100%; object-fit: contain; display: block; background: #14101a; }
.cambig__video audio { display: none; }

.cambig__badge {
  position: absolute;
  top: 10px;
  left: 10px;
  z-index: 1;
  font-size: 10.5px;
  font-weight: 800;
  letter-spacing: .06em;
  color: #fff;
  background: #f90f9e;
  padding: 3px 8px;
  border-radius: 5px;
}

.cambig__controls {
  position: absolute;
  top: 8px;
  right: 8px;
  z-index: 1;
  display: flex;
  gap: 8px;
}

.cambig__btn {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: 0;
  background: rgba(20, 16, 26, .62);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  backdrop-filter: blur(6px);
  transition: background .12s ease;
}

.cambig__btn .ic { width: 21px; height: 21px; }
.cambig__btn:hover { background: rgba(20, 16, 26, .85); }
.cambig__btn.is-on { background: var(--accent); }

.cambig__foot {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1;
  padding: 22px 12px 10px;
  background: linear-gradient(to top, rgba(0, 0, 0, .8), transparent);
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 10px;
  min-width: 0;
}

.cambig__watching {
  flex: none;
  display: flex;
  align-items: center;
  gap: 5px;
  padding: 4px 10px;
  border-radius: 999px;
  background: rgba(255, 255, 255, .18);
  backdrop-filter: blur(6px);
  color: #fff;
  font-size: 12.5px;
  font-weight: 700;
  text-shadow: 0 1px 3px rgba(0, 0, 0, .5);
}

.cambig__watching .ic { width: 14px; height: 14px; }

.cambig__who {
  border: 0;
  background: none;
  padding: 0;
  color: #fff;
  font-size: 16px;
  font-weight: 700;
  display: flex;
  align-items: baseline;
  gap: 8px;
  min-width: 0;
  overflow: hidden;
  text-shadow: 0 1px 3px rgba(0, 0, 0, .6);
}

/* On a narrow screen the name gives way before the count does: knowing how many
   people are watching is the part you cannot get anywhere else on this screen. */
.cambig__who > span:first-child,
.cambig__who { white-space: nowrap; text-overflow: ellipsis; }

.cambig__who i { font-style: normal; font-weight: 400; opacity: .85; }

.cambig__link {
  font-size: 12.5px;
  font-weight: 600;
  color: #ffc4dc;
  border-bottom: 1px solid rgba(255, 196, 220, .5);
}

/* the strip cam currently expanded */
.cam.is-open { box-shadow: 0 0 0 2.5px var(--accent); }

@media (max-width: 380px) {
  .cambig__link { display: none; }
  .cambig__who { font-size: 15px; }
}

@media (min-width: 900px) {
  .cambig__stage { aspect-ratio: 16 / 9; max-height: 540px; margin: 0 auto; }
}

/* ---------- public chatroom ---------- */

/* The room pane is a column: cams keep their natural height at the top and the
   chat takes whatever is left, so the composer sits on the bottom edge rather
   than being pushed off screen by a tall strip. */



/* Whatever the cams take, the chat keeps enough to stay usable: a log you can
   read a couple of lines in, plus the composer. */
/* The banner sits inside .room and takes its own height, so the floor has to
   cover both it and a usable log; otherwise adding the banner quietly ate the
   conversation. */

.room {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

.room__log {
  flex: 1;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 12px 12px 6px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  overscroll-behavior: contain;
}

.rmsg {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  padding: 5px 6px;
  border-radius: 10px;
  cursor: pointer;
}

.rmsg:hover { background: var(--surface-2); }

.rmsg--enter { animation: bubble-in .2s cubic-bezier(.22, 1, .36, 1); }
@media (prefers-reduced-motion: reduce) { .rmsg--enter { animation: none; } }

/* Deliberately small: in a busy room the avatars are decoration, the words are
   the content, and 40px portraits would push half the messages off screen. */
.rmsg__av {
  flex: none;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  overflow: hidden;
  background: var(--surface-3);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 700;
  color: var(--muted);
  margin-top: 1px;
}

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

.rmsg__main { min-width: 0; flex: 1; }

.rmsg__head {
  display: flex;
  align-items: baseline;
  gap: 7px;
  margin-bottom: 1px;
}

.rmsg__name {
  font-size: 14px;
  font-weight: 700;
  letter-spacing: -0.01em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.rmsg__time {
  flex: none;
  font-style: normal;
  font-size: 11px;
  color: var(--muted);
  opacity: .8;
}

.rmsg__body {
  display: block;
  font-size: 15px;
  line-height: 1.45;
  color: var(--text);
  word-wrap: break-word;
  overflow-wrap: anywhere;
}

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

.rmsg__gif {
  display: block;
  margin-top: 4px;
  max-width: 220px;
  width: 100%;
  border-radius: 12px;
  background: var(--surface-3);
}

.rmsg.is-mine .rmsg__body { color: #00e7ff; }

.room__note {
  margin: 0 12px 6px;
  padding: 8px 12px;
  border-radius: 10px;
  background: var(--accent-soft);
  border: 1px solid var(--accent);
  color: var(--accent);
  font-size: 13px;
}

.room__composer {
  flex: none;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
  border-top: 1px solid var(--line);
  background: var(--surface);
}

.room__composer input {
  flex: 1;
  min-width: 0;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 11px 16px;
  color: var(--text);
  font-size: 15px;
  outline: none;
}

.room__composer input:focus { border-color: var(--accent); }

.room__gif {
  flex: none;
  height: 40px;
  padding: 0 12px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--muted);
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .04em;
}

.room__gif:hover { border-color: var(--accent); color: var(--accent); }

.room__send {
  flex: none;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  border: 0;
  background: linear-gradient(135deg, var(--accent) 0%, #00ff58 100%);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 3px 10px rgba(29, 161, 228, .28);
}

.room__send .ic { width: 19px; height: 19px; }

/* ---- GIF picker ---- */

.gifs {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 3;
  max-height: 62%;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border-top: 1px solid var(--line);
  border-radius: 16px 16px 0 0;
  box-shadow: 0 -10px 30px rgba(0, 0, 0, .5);
}

.gifs__bar {
  flex: none;
  display: flex;
  gap: 8px;
  padding: 10px 12px;
  border-bottom: 1px solid var(--line);
}

.gifs__bar input {
  flex: 1;
  min-width: 0;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 9px 14px;
  color: var(--text);
  outline: none;
}

.gifs__close {
  flex: none;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: 0;
  background: var(--surface-2);
  color: var(--muted);
  display: flex;
  align-items: center;
  justify-content: center;
}

.gifs__grid {
  flex: 1;
  overflow-y: auto;
  padding: 10px;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
}

@media (min-width: 620px) { .gifs__grid { grid-template-columns: repeat(5, 1fr); } }

.gifs__item {
  padding: 0;
  border: 0;
  border-radius: 10px;
  overflow: hidden;
  background: var(--surface-3);
  aspect-ratio: 1 / 1;
}

.gifs__item img { width: 100%; height: 100%; object-fit: cover; display: block; }
.gifs__item:hover { outline: 2px solid var(--accent); }

.gifs__msg {
  grid-column: 1 / -1;
  padding: 26px 10px;
  text-align: center;
  color: var(--muted);
  font-size: 14px;
}

/* system notices in the room */
.rsys {
  align-self: center;
  max-width: 90%;
  margin: 4px 0;
  padding: 4px 12px;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--muted);
  font-size: 12.5px;
  text-align: center;
}

/* ---------- admin panel ---------- */

.me__section--admin { border-top: 2px solid var(--accent); }

.admin__head {
  margin: 12px 0 6px;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--muted);
}

.admin__row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 10px;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--surface-2);
  margin-bottom: 6px;
}

.admin__slot {
  flex: none;
  width: 24px;
  height: 24px;
  border-radius: 7px;
  background: var(--surface-3);
  color: var(--muted);
  font-size: 12px;
  font-weight: 800;
  display: flex;
  align-items: center;
  justify-content: center;
}

.admin__who { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.admin__who b { font-size: 14.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.admin__who i { font-style: normal; font-size: 12px; color: var(--muted); }

.admin__acts { flex: none; display: flex; gap: 6px; }

.admin__msg {
  padding: 12px 10px;
  color: var(--muted);
  font-size: 13.5px;
}

/* ---------- people rows ---------- */

/* Full-bleed rows with hairline separators: no cards, no shadows. */
.list--rows {
  display: block;
  padding: 0;
}

.list--rows .empty { padding: 40px 20px; }

.srow {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 0 12px 0 0;
  border-bottom: 1px solid var(--line);
  background: var(--surface);
}

.srow:last-child { border-bottom: 0; }
.srow:hover { background: var(--surface); }

/* the whole left area opens the profile */
.srow__open {
  display: flex;
  align-items: center;
  gap: 13px;
  flex: 1;
  min-width: 0;
  padding: 12px 4px 12px 16px;
  border: 0;
  background: none;
  text-align: left;
}

.srow__avatar {
  position: relative;
  flex: none;
  width: 62px;
  height: 62px;
  border-radius: 50%;
  overflow: hidden;
  background: var(--surface-3);
  display: flex;
  align-items: center;
  justify-content: center;
}

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

.srow__initial {
  font-size: 24px;
  font-weight: 800;
  color: var(--accent);
}

/* Ring for people who are online. A box-shadow paints outside the element, so
   the avatar can keep clipping its image while still showing the ring. */
.srow__avatar.is-online {
  box-shadow: 0 0 0 2px var(--bg), 0 0 0 4.5px #e70379;
}

.srow__dot {
  position: absolute;
  right: 9px;
  bottom: 7px;
  width: 10px;
  height: 10px;
  background: #3ddc4e;
  border: 2.5px solid var(--bg);
}

.srow__main { min-width: 0; display: flex; flex-direction: column; gap: 2px; }

.srow__top {
  display: flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
}

/* Gender colour comes from the .g-* class the row adds; this is only the
   fallback for anyone without one. */
.srow__name {
  font-size: 19px;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  min-width: 0;
}

.srow__age { flex: none; font-size: 15px; color: var(--muted); font-weight: 500; }

.srow__sub {
  font-size: 14.5px;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* the action on the right, mirroring the camera button in the reference */
.srow__act {
  flex: none;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  border: 0;
  background: none;
  color: var(--text);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background .12s ease, color .12s ease;
}

.srow__act .ic { width: 25px; height: 25px; stroke-width: 1.9; }
.srow__act:hover { background: var(--accent); color: #fff; }
.srow__act:active { transform: scale(.94); }

.srow--enter { animation: row-in .34s cubic-bezier(.22, 1, .36, 1); }
@media (prefers-reduced-motion: reduce) { .srow--enter { animation: none; } }

.avatar {
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: var(--surface-3);
  flex: none;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  font-size: 19px;
  color: var(--muted);
  overflow: hidden;
  box-shadow: 0 0 0 2px var(--line);
}

/* subtle glow ring when online */
.row-item .avatar:has(.dot.is-online),
.avatar.is-online-ring {
  box-shadow: 0 0 0 2px rgba(23, 191, 95, .5);
}

.avatar img { width: 100%; height: 100%; object-fit: cover; }
.avatar--sm { width: 34px; height: 34px; font-size: 14px; box-shadow: none; }
.avatar--lg { width: 100%; height: auto; aspect-ratio: 1; border-radius: 18px; font-size: 48px; box-shadow: none; }

.dot {
  position: absolute;
  right: -1px;
  bottom: -1px;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: #cfc6cd;
  border: 3px solid var(--bg);
}

.dot.is-online {
  background: var(--online);
  box-shadow: 0 0 6px rgba(23, 191, 95, .55);
}
.avatar--sm .dot { width: 10px; height: 10px; border-width: 2px; }

.row-item__main { flex: 1; min-width: 0; }

.row-item__name {
  font-weight: 650;
  font-size: 16.5px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  letter-spacing: -0.01em;
  min-width: 0;
  flex-shrink: 1;
}

.g-male { color: var(--male); }
.g-female { color: var(--female); }
.g-couple { color: var(--couple); }
.g-other { color: var(--other); }

/* envelope icon before the avatar */
.row-item__env {
  flex: none;
  width: 22px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--muted);
  opacity: .7;
}
.row-item__env .ic { width: 19px; height: 19px; }

/* name + age + New badge on one line */
.row-item__top {
  display: flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
}

.row-item__age {
  color: var(--muted);
  font-size: 14px;
  font-weight: 400;
  flex: none;
}

.tag-new {
  flex: none;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: #fff;
  background: linear-gradient(100deg, var(--accent), #ff6aa4);
  padding: 2px 7px;
  border-radius: 999px;
  box-shadow: 0 1px 6px rgba(255, 45, 122, .4);
}

.row-item__sub {
  color: var(--muted);
  font-size: 13.5px;
  margin-top: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}

/* country in its own right-aligned column */
.row-item__country {
  flex: none;
  max-width: 34%;
  color: var(--muted);
  font-size: 13px;
  text-align: right;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  padding-left: 8px;
}

.row-item__side { text-align: right; flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: 5px; }
.row-item__time { color: var(--muted); font-size: 12px; }

.pill {
  min-width: 20px;
  height: 20px;
  padding: 0 6px;
  border-radius: 10px;
  background: var(--accent);
  color: #fff;
  font-size: 11.5px;
  font-weight: 700;
  line-height: 20px;
  text-align: center;
}

.list-end { padding: 18px; text-align: center; color: var(--muted); font-size: 13.5px; }

.empty { padding: 60px 26px; text-align: center; color: var(--muted); }
.empty strong { display: block; color: var(--text); font-size: 17px; margin-bottom: 6px; }

/* ---------- bar ---------- */

.bar {
  display: flex;
  align-items: center;
  gap: 4px;
  height: var(--bar);
  padding: 0 6px;
  border-bottom: 1px solid var(--line);
  background: var(--surface);
  flex: none;
}

.bar__btn {
  width: 42px;
  height: 42px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: 0;
  border-radius: 10px;
  color: var(--text);
}

.bar__title { font-weight: 600; font-size: 16px; }
.bar__spacer { flex: 1; }

.bar__peer {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 10px;
  background: none;
  border: 0;
  min-width: 0;
  padding: 0 4px;
  text-align: left;
}

.bar__peerinfo { min-width: 0; }
.bar__peername { display: block; font-weight: 600; font-size: 15.5px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.bar__peerstate { display: block; font-size: 12px; color: var(--muted); }
.bar__peerstate.is-online { color: var(--online); }

/* ---------- profile layout ---------- */

.profile__grid { display: block; }

/* gallery */

.gallery { margin-bottom: 14px; }

.gallery__hero {
  width: 100%;
  aspect-ratio: 4 / 5;
  border-radius: 18px;
  overflow: hidden;
  background: var(--surface-3);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-md);
}

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

.gallery__hero--empty {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 54px;
  font-weight: 800;
  color: var(--accent);
  background: linear-gradient(160deg, var(--surface-2), var(--surface-3));
}

.gallery__thumbs { display: flex; gap: 8px; margin-top: 8px; }

.gallery__thumb {
  width: 62px;
  height: 62px;
  padding: 0;
  border-radius: 12px;
  overflow: hidden;
  border: 2px solid transparent;
  background: var(--surface-2);
  flex: none;
  transition: border-color .12s ease;
}

.gallery__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.gallery__thumb.is-active { border-color: var(--accent); }
.gallery__thumb:hover { border-color: var(--line-strong); }

/* fact list */

.profile__site {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 16px;
  padding: 10px 14px;
  border-radius: 12px;
  background: var(--accent-soft);
  border: 1px solid var(--accent);
  color: var(--accent-deep);
  font-size: 14.5px;
  font-weight: 650;
  max-width: 100%;
  text-decoration: none;
  transition: background .12s ease, color .12s ease;
}

.profile__site:hover { background: var(--accent); color: #fff; }
.profile__site .ic { width: 17px; height: 17px; flex: none; }
.profile__site span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.field__hint {
  display: block;
  margin-top: 5px;
  font-size: 12.5px;
  color: var(--muted);
}

.profile__h {
  margin: 22px 0 10px;
  font-size: 17px;
  font-weight: 750;
  letter-spacing: -0.015em;
}

.facts {
  margin: 18px 0 0;
  padding: 0;
  display: grid;
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: 14px;
  overflow: hidden;
}

.fact {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 14px;
  background: var(--surface);
  padding: 11px 14px;
}

.fact dt { color: var(--muted); font-size: 13.5px; }
.fact dd { margin: 0; font-weight: 600; font-size: 14.5px; text-align: right; }

/* suggestions sidebar */

.profile__side { margin-top: 22px; }

.sidecard {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 18px;
  padding: 14px;
  box-shadow: var(--shadow-sm);
}

.sidecard__title {
  margin: 2px 4px 10px;
  font-size: 15.5px;
  font-weight: 750;
  letter-spacing: -0.015em;
}

.suggest {
  display: flex;
  align-items: center;
  gap: 11px;
  width: 100%;
  padding: 8px;
  border: 0;
  border-radius: 12px;
  background: none;
  text-align: left;
  transition: background .12s ease;
}

.suggest:hover { background: var(--surface-2); }
.suggest .avatar { width: 42px; height: 42px; font-size: 16px; }
.suggest__main { min-width: 0; display: flex; flex-direction: column; }

.suggest__name {
  font-weight: 650;
  font-size: 14.5px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.suggest__name i { font-style: normal; font-weight: 400; color: var(--muted); }

.suggest__place {
  font-size: 12.5px;
  color: var(--muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Three columns once there is room: gallery, details, suggestions. */
@media (min-width: 900px) {
  .profile { padding: 24px 24px 40px; }

  .profile__grid {
    display: grid;
    grid-template-columns: 262px minmax(0, 1fr) 236px;
    gap: 24px;
    align-items: start;
    max-width: 1160px;
    margin: 0 auto;
  }

  .profile__left { position: sticky; top: 0; }
  .profile__side { margin-top: 0; position: sticky; top: 0; }

  .profile__name { font-size: 34px; }
  .facts { margin-top: 22px; }
}

/* Between tablet and desktop, drop the sidebar under the details. */
@media (min-width: 700px) and (max-width: 899px) {
  .profile__grid {
    display: grid;
    grid-template-columns: 260px minmax(0, 1fr);
    gap: 26px;
    align-items: start;
  }
  .profile__side { grid-column: 1 / -1; }
}


/* ---------- profile ---------- */

.profile { flex: 1; overflow-y: auto; padding: 18px 16px calc(28px + env(safe-area-inset-bottom)); }
.profile__photo { margin-bottom: 16px; }

.profile__namerow {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-top: 4px;
}

.profile__name {
  font-size: 28px;
  font-weight: 800;
  letter-spacing: -0.025em;
  line-height: 1.05;
}

/* premium sheen on the name */
.profile__name.g-male   { background: linear-gradient(100deg, var(--male) 0%, #9cd4ff 100%); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; }
.profile__name.g-female { background: linear-gradient(100deg, var(--female) 0%, #ffb0d4 100%); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; }
.profile__name.g-couple { background: linear-gradient(100deg, var(--couple) 0%, #d9b8ff 100%); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; }
.profile__name.g-other  { background: linear-gradient(100deg, #6b7684 0%, #9aa5b3 100%); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; }

/* online badge next to the name */
.profile__live {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  flex: none;
  padding: 4px 10px 4px 8px;
  border-radius: 999px;
  background: rgb(11, 11, 11);
  border: 1px solid rgb(22, 21, 21);
  color: #d60e6c;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .02em;
  text-transform: uppercase;
}

.profile__live i {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #fff9fc;
  box-shadow: 0 0 6px rgb(214, 14, 108);
  animation: live-pulse 1.8s ease-in-out infinite;
}

@keyframes live-pulse { 0%,100% { opacity: 1; } 50% { opacity: .35; } }
@media (prefers-reduced-motion: reduce) { .profile__live i { animation: none; } }

.profile__meta {
  color: var(--muted);
  margin-top: 8px;
  font-size: 14.5px;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.profile__meta b { color: var(--text); font-weight: 600; }

.profile__bio {
  margin-top: 18px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 14px 16px;
  line-height: 1.55;
}

.profile__bio-text {
  white-space: pre-wrap;
  word-break: break-word;
  overflow-wrap: anywhere;
}

/* Long bios are capped at five lines so they never dominate the screen or push
   the action buttons out of reach. The toggle appears only when clamping
   actually hides something. */
.profile__bio.is-clamped .profile__bio-text {
  display: -webkit-box;
  -webkit-line-clamp: 5;
  line-clamp: 5;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.profile__bio-toggle {
  margin-top: 8px;
  padding: 0;
  border: 0;
  background: none;
  color: var(--accent);
  font-size: 13.5px;
  font-weight: 600;
}

.profile__actions { display: flex; gap: 10px; margin-top: 18px; }
.profile__actions .btn { flex: 1; display: flex; align-items: center; justify-content: center; gap: 8px; }

/* ---------- me ---------- */

.me { padding: 18px 16px calc(28px + env(safe-area-inset-bottom)); }
.me__section { margin-top: 22px; }
.me__title { font-size: 12.5px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); font-weight: 600; margin-bottom: 10px; }
.me__actions { display: flex; flex-direction: column; gap: 10px; }
.me__actions .btn { display: flex; align-items: center; justify-content: center; gap: 8px; }
.me__token { font-family: ui-monospace, Menlo, Consolas, monospace; font-size: 12px; color: var(--muted); word-break: break-all; background: var(--surface-2); border: 1px solid var(--line); border-radius: 10px; padding: 10px 12px; }

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

.screen--chat { background: var(--bg); }

.thread {
  flex: 1;
  overflow-y: auto;
  padding: 16px 12px 10px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  -webkit-overflow-scrolling: touch;
  background: var(--surface);
}

.thread__more { text-align: center; padding: 6px 0 14px; }

.bubble {
  max-width: 78%;
  padding: 9px 13px 8px;
  border-radius: 18px;
  line-height: 1.45;
  word-wrap: break-word;
  overflow-wrap: anywhere;
  white-space: pre-wrap;
  font-size: 15.3px;
  position: relative;
  animation: bubble-in .22s cubic-bezier(.22, 1, .36, 1);
}

@keyframes bubble-in {
  from { opacity: 0; transform: translateY(6px) scale(.98); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) { .bubble { animation: none; } }

/* Incoming is a plain card, outgoing carries the brand gradient. The tail is
   only drawn on the last bubble of a run, so a burst of messages reads as one
   block instead of a row of identical speech balloons. */
.bubble--in {
  align-self: flex-start;
  background: var(--surface);
  color: var(--text);
  border-bottom-left-radius: 18px;
}

.bubble--out {
  align-self: flex-end;
  background: linear-gradient(135deg, var(--accent) 0%, #45b6ef 100%);
  border-color: transparent;
  color: #fff;
  border-bottom-right-radius: 18px;
  box-shadow: 0 2px 8px rgba(29, 161, 228, .22);
}

.bubble--in.is-tail  { border-bottom-left-radius: 6px; }
.bubble--out.is-tail { border-bottom-right-radius: 6px; }

/* extra breathing room where the speaker changes */
.bubble.is-first { margin-top: 10px; }

.bubble__time {
  float: right;
  margin: 7px 0 -2px 12px;
  font-size: 10.5px;
  font-weight: 500;
  color: var(--muted);
  line-height: 1;
  opacity: .85;
}

.bubble--out .bubble__time { color: rgba(255, 255, 255, .85); }


/* photo message */
.bubble--photo { padding: 0; overflow: hidden; border-radius: 14px; }

.snapcard {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 12px 14px;
  min-width: 190px;
  background: none;
  border: 0;
  color: inherit;
  text-align: left;
  width: 100%;
}

.snapcard__icon {
  width: 34px;
  height: 34px;
  border-radius: 10px;
  background: rgba(255, 45, 122, .16);
  color: var(--accent);
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
}

.snapcard__label { font-size: 14.5px; font-weight: 600; }
.snapcard__sub { font-size: 12px; color: var(--muted); margin-top: 2px; }
.snapcard.is-spent .snapcard__icon { background: var(--surface-3); color: var(--muted); }
.snapcard.is-spent .snapcard__label { color: var(--muted); font-weight: 500; }

.day {
  align-self: center;
  color: var(--muted);
  font-size: 11.5px;
  font-weight: 650;
  letter-spacing: .01em;
  background: var(--surface-3);
  border-radius: 999px;
  padding: 5px 13px;
  margin: 16px 0 8px;
}

.composer {
  display: flex;
  align-items: flex-end;
  gap: 9px;
  padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
  border-top: 1px solid var(--line);
  background: var(--surface);
  flex: none;
}

.composer textarea {
  flex: 1;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-radius: 20px;
  padding: 11px 15px;
  max-height: 130px;
  outline: none;
  resize: none;
  line-height: 1.4;
}

.composer textarea:focus { border-color: var(--accent); }

.composer__send {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 0;
  background: var(--accent);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
}

.composer__blocked {
  margin: 0;
  padding: 14px 16px calc(14px + env(safe-area-inset-bottom));
  border-top: 1px solid var(--line);
  background: var(--surface);
  color: var(--muted);
  font-size: 14px;
  text-align: center;
}

/* ---------- toast ---------- */

.toast {
  position: fixed;
  left: 50%;
  bottom: 26px;
  transform: translateX(-50%);
  z-index: 60;
  background: var(--surface-3);
  border: 1px solid var(--line);
  color: var(--text);
  padding: 11px 17px;
  border-radius: 999px;
  font-size: 14px;
  max-width: 88vw;
  text-align: center;
}

/* ---------- focus ---------- */

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


/* ---------- wordmark ---------- */

.wordmark { display: flex; align-items: center; gap: 9px; }

/* The mark carries its own gradient fill, so it needs no colour from here. */
.logo-mark { width: 27px; height: 27px; flex: none; }

.wordmark__text {
  font-size: 19.5px;
  font-weight: 800;
  letter-spacing: -0.03em;
  color: var(--text);
}

/* second half of the name in brand pink */
.wordmark__text i { font-style: normal; color: #d60e6c; font-weight: 800; }

.wordmark--lg .logo-mark { width: 40px; height: 40px; }
.wordmark--lg .wordmark__text { font-size: 30px; }

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: 52px;
  padding: 0 14px;
  border-bottom: 1px solid var(--line);
  background: var(--surface);
  flex: none;
}

.topbar__count { font-size: 12.5px; color: var(--muted); }
.topbar__count b { color: var(--online); font-weight: 600; }

/* rechterkant van de mobiele header: online-teller + Go live-knop */
.topbar__right { display: flex; align-items: center; gap: 10px; }

.topbar__golive {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  white-space: nowrap;
  border-radius: 999px;
}
.topbar__golive .ic { width: 16px; height: 16px; }

/* op erg smalle schermen alleen het camera-icoon tonen */
@media (max-width: 360px) {
  .topbar__golive span { display: none; }
  .topbar__golive { padding: 8px; }
}

/* Go live-knop bovenaan de desktop-sidebar */
.sidebar__golive {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  margin: 0 0 12px;
}
.sidebar__golive .ic { width: 18px; height: 18px; }

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

.screen--auth { overflow-y: auto; display: block; padding: 0; border: 0; max-width: none; }

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

/* hero */

.hero {
  position: relative;
  isolation: isolate;
  color: #fff;
  padding: 44px 24px 48px;
  overflow: hidden;
  background-color: #1a0a12;
  background-image: var(--hero-image);
  background-size: cover;
  background-position: center;
}

/*
 * Two layers over the photo: a warm tint so the brand pink carries through, and
 * a darker vignette so white text stays readable wherever the image is bright.
 * Without these the headline disappears against light parts of the picture.
 */
.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(180deg, rgba(6, 6, 6, 0.98) 0%, rgba(236, 107, 221, 0.02) 40%, rgba(27, 30, 28, 0) 100%), linear-gradient(115deg, rgb(0, 0, 0) 0%, rgba(0, 0, 0, 0.13) 55%, rgba(17, 17, 17, 0.8) 100%);
}

.hero__inner {
  max-width: 620px;
  margin: 0 auto;
  position: relative;
  z-index: 1;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.hero__brand { margin-bottom: 30px; }

.hero__brand .logo-mark {
  background: #fff;
  border-radius: 9px;
  padding: 4px;
  width: 34px;
  height: 34px;
  box-shadow: 0 4px 14px rgba(120, 20, 70, .35);
}

.hero__brand .wordmark__text { color: #fff; }
.hero__brand .wordmark__text i { color: rgba(255, 255, 255, .82); }

/* the online pill sits above the headline, as a live signal */
.hero__count {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  background: rgba(255, 255, 255, .13);
  border: 1px solid rgba(255, 255, 255, .28);
  backdrop-filter: blur(8px);
  border-radius: 999px;
  padding: 7px 16px;
  font-size: 14px;
  font-weight: 600;
  margin-bottom: 22px;
}

.hero__count b { color: #fff; font-weight: 800; }

.hero__dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: #2ee06a;
  box-shadow: 0 0 0 3px rgba(46, 224, 106, .28);
}

.hero__title {
  margin: 0 0 18px;
  font-weight: 800;
  letter-spacing: -0.035em;
  line-height: 1.06;
  font-size: clamp(34px, 8.5vw, 58px);
  text-shadow: 0 2px 20px rgba(0, 0, 0, .35);
}

.hero__accent {
  background: linear-gradient(100deg, #af7aff 0%, #d2b4ff 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
}

.hero__lead {
  margin: 0 0 26px;
  max-width: 520px;
  font-size: 16px;
  line-height: 1.6;
  color: rgba(255, 255, 255, .88);
  text-shadow: 0 1px 12px rgba(0, 0, 0, .45);
}

.hero__feats {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 9px;
}

.hero__feats li {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 13.5px;
  font-weight: 600;
  background: rgba(255, 255, 255, .12);
  border: 1px solid rgba(255, 255, 255, .2);
  backdrop-filter: blur(6px);
  border-radius: 999px;
  padding: 7px 13px;
}

.hero__check { width: 15px; height: 15px; color: #955ff5; stroke-width: 3; }
.hero__lock { width: 14px; height: 14px; color: #ffd0e4; }

/* login card */


/*
 * The card is a card at every width.
 *
 * These styles were inside a min-width: 860px query, so on a phone the form sat
 * bare on the page with no edge, no padding and nothing separating it from the
 * hero above - which reads as a broken layout rather than a deliberate one. A
 * sign-in form is the one place a visitor has to trust, so it should look
 * built.
 */

/*
 * The landing page's two-column rule lives with the rest of the auth styling
 * further down. An older copy sat here, left over from the dark theme, and it
 * carried a near-black panel with an 18px backdrop blur - which on a light page
 * painted a dark, blurred sheet over whatever was behind it. Two rules for one
 * layout is one rule too many; this is the one that went.
 */


.segment--2 { grid-template-columns: repeat(2, 1fr); margin-bottom: 20px; }

.field__pw { position: relative; display: block; }
.field__pw input { padding-right: 46px; }

.field__reveal {
  position: absolute;
  right: 4px;
  top: 50%;
  transform: translateY(-50%);
  width: 38px;
  height: 38px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: none;
  border: 0;
  color: var(--muted);
}

/* ---------- photo slots ---------- */

.slots { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }

.slot {
  position: relative;
  aspect-ratio: 1;
  border: 1px dashed var(--line);
  border-radius: 12px;
  background: var(--surface-2);
  color: var(--muted);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  cursor: pointer;
}

.slot img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.slot__hint { display: flex; align-items: center; justify-content: center; }

.slot__drop {
  position: absolute;
  right: 6px;
  top: 6px;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 0;
  background: rgba(0, 0, 0, .62);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 2;
}

.slot__drop .ic { width: 16px; height: 16px; }

/* profile photo pair */



/* ---------- composer attach ---------- */

.composer__attach {
  width: 40px;
  height: 44px;
  border: 0;
  background: none;
  color: var(--muted);
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
}

/* ---------- photo viewer ---------- */

.screen--snap { z-index: 40; background: #000; }
.bar--snap { background: transparent; border-bottom: 0; }
.snap__warn { font-size: 12px; color: var(--muted); padding-right: 10px; }

.snap__stage {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 8px 8px calc(24px + env(safe-area-inset-bottom));
  min-height: 0;
}

.snap__stage img { max-width: 100%; max-height: 100%; object-fit: contain; border-radius: 12px; }

/* ---------- inbox row action ---------- */

.row-item__del {
  width: 34px;
  height: 34px;
  border-radius: 9px;
  border: 0;
  background: none;
  color: var(--muted);
  display: flex;
  align-items: center;
  justify-content: center;
  flex: none;
}

.row-item__del .ic { width: 18px; height: 18px; }
/* Fallback behind a still: shown until the first frame arrives, and left in
   place if a refresh fails, so a tile is never a black hole. */
.cam__poster {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--surface-3);
  color: var(--muted);
  font-size: 22px;
  font-weight: 800;
}

.cam__poster--letter { object-fit: unset; }

/* The still sits over the fallback and fades in once it has actually loaded. */
.cam__thumb {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity .25s ease;
}

.cam__thumb.is-loaded { opacity: 1; }


/* ============ landing, voice and the capacity door ============ */

/* ---- hero ---- */

.hero { position: relative; isolation: isolate; overflow: hidden; }

/* A wall of faces behind the copy. Heavily dimmed: it is texture, not content,
   and legible white text over portraits needs the picture pushed right back. */

@media (min-width: 700px) { .hero__faces { grid-template-columns: repeat(8, 1fr); } }

.hero__faces img { width: 100%; height: 100%; object-fit: cover; display: block; aspect-ratio: 1; }


.hero__cta:hover { background: #3ea520; transform: translateY(-1px); }
.hero__cta:active { transform: none; }






/* ---- capacity door ---- */

.screen--full { overflow-y: auto; display: block; padding: 0; max-width: none; border: 0; }

.full {
  max-width: 460px;
  margin: 0 auto;
  padding: 54px 22px calc(40px + env(safe-area-inset-bottom));
  text-align: center;
}

.full__mark { width: 54px; height: 54px; margin: 0 auto 22px; color: var(--accent); }
.full__mark .logo-mark { width: 100%; height: 100%; }

.full__title { margin: 0 0 14px; font-size: 27px; font-weight: 800; letter-spacing: -0.025em; }
.full__text { margin: 0 0 14px; font-size: 15.5px; line-height: 1.6; color: var(--muted); }

.full__meter { margin: 24px 0 20px; }

.full__bar {
  height: 9px;
  border-radius: 999px;
  background: var(--surface-3);
  overflow: hidden;
  margin-bottom: 8px;
}

.full__bar span {
  display: block;
  height: 100%;
  width: 100%;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--accent), #45b6ef);
}

.full__count { font-size: 13px; color: var(--muted); }
.full__count b { color: var(--text); }

.full__support {
  margin: 20px 0 0;
  font-size: 13px;
  line-height: 1.55;
  color: var(--muted);
}

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

.voice {
  flex: none;
  display: flex;
  align-items: stretch;
  gap: 8px;
  padding: 8px 10px;
  border-bottom: 1px solid var(--line);
  background: var(--surface);
}

.voice__seats {
  flex: 1;
  min-width: 0;
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  gap: 6px;
}

.vseat {
  display: flex;
  align-items: center;
  gap: 7px;
  min-width: 0;
  padding: 5px 7px;
  border-radius: 999px;
  background: var(--surface-2);
  border: 1px solid var(--line);
}

.vseat--free {
  justify-content: center;
  border-style: dashed;
  color: var(--muted);
}

.vseat__empty { font-size: 11.5px; font-weight: 600; }

.vseat__av {
  position: relative;
  flex: none;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  overflow: hidden;
  background: var(--surface-3);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 700;
  color: var(--muted);
}

.vseat__av img { width: 100%; height: 100%; object-fit: cover; }

/* The ring pulses only while this person is actually speaking, so a glance at
   the bar answers "who is talking" without reading any names. */
.vseat__wave {
  position: absolute;
  inset: -3px;
  border-radius: 50%;
  border: 2px solid transparent;
  pointer-events: none;
}

.vseat.is-talking .vseat__wave {
  border-color: var(--online);
  animation: vwave 1.1s ease-out infinite;
}

@keyframes vwave {
  0%   { transform: scale(.9); opacity: 1; }
  100% { transform: scale(1.25); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .vseat.is-talking .vseat__wave { animation: none; opacity: 1; }
}

.vseat__name {
  flex: 1;
  min-width: 0;
  font-size: 12.5px;
  font-weight: 700;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.vseat__you {
  flex: none;
  font-size: 9.5px;
  font-weight: 800;
  letter-spacing: .04em;
  color: var(--accent);
}

.vseat__mute {
  flex: none;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 0;
  background: none;
  color: var(--muted);
  display: flex;
  align-items: center;
  justify-content: center;
}

.vseat__mute .ic { width: 15px; height: 15px; }
.vseat__mute:hover { color: var(--accent); }

/* A muted speaker stays visible and still shows as talking; only the sound is
   gone, so the bar never lies about who is in the conversation. */
.vseat.is-muted { opacity: .58; }
.vseat.is-muted .vseat__mute { color: var(--danger); }
.vseat.is-mine { border-color: var(--accent); }

.voice__mic {
  flex: none;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 0 14px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--text);
  font-size: 13px;
  font-weight: 700;
}

.voice__mic .ic { width: 17px; height: 17px; }
.voice__mic:disabled { opacity: .45; }

.voice__mic.is-on {
  background: linear-gradient(135deg, var(--accent), #45b6ef);
  border-color: transparent;
  color: #fff;
}

.voice__note {
  margin: 0;
  padding: 8px 12px;
  font-size: 13px;
  color: var(--danger);
  background: var(--surface-2);
  border-bottom: 1px solid var(--line);
}


/* ---- master mute for the voice channel ---- */

.voice__all {
  flex: none;
  width: 38px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--muted);
  display: flex;
  align-items: center;
  justify-content: center;
}

.voice__all .ic { width: 17px; height: 17px; }
.voice__all:hover { color: var(--text); }

.voice__all.is-off {
  background: var(--danger);
  border-color: transparent;
  color: #fff;
}

/* The seats stay readable while the channel is silenced - you can still see who
   is talking, which is the whole reason the indicator is server-driven. */
.voice.is-allmuted .voice__seats { opacity: .55; }

/* ---------- install prompt ---------- */

.install {
  position: fixed;
  left: 12px;
  right: 12px;
  bottom: calc(12px + env(safe-area-inset-bottom));
  z-index: 70;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 14px;
  border-radius: 16px;
  background: var(--surface);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-lg);
  animation: install-in .25s cubic-bezier(.22, 1, .36, 1);
}

@keyframes install-in {
  from { opacity: 0; transform: translateY(14px); }
  to   { opacity: 1; transform: none; }
}

@media (prefers-reduced-motion: reduce) { .install { animation: none; } }

/* Above the bottom nav on a phone, and out of the way of the thumb on a wide
   screen where it would otherwise stretch across the whole window. */
@media (min-width: 620px) {
  .install { left: auto; right: 18px; max-width: 380px; }
}

.install__icon { width: 42px; height: 42px; border-radius: 10px; flex: none; }

.install__text { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.install__text strong { font-size: 14.5px; }
.install__text span { font-size: 12.5px; color: var(--muted); line-height: 1.35; }

.install__close {
  flex: none;
  width: 28px;
  height: 28px;
  border: 0;
  border-radius: 50%;
  background: none;
  color: var(--muted);
  display: flex;
  align-items: center;
  justify-content: center;
}

.install__close .ic { width: 15px; height: 15px; }

/* The banner after it has turned into instructions: taller, and the text is now
   the point rather than a subtitle under a button. */
.install.is-steps { align-items: flex-start; }
.install.is-steps .install__text span { font-size: 13.5px; color: var(--text); }
.install.is-steps .install__text span b { color: var(--accent); }

/* ---------- room welcome ---------- */

.rintro {
  align-self: stretch;
  margin: 4px 2px 12px;
  padding: 14px 16px;
  border-radius: 14px;
  background: var(--surface-2);
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
}

.rintro strong {
  display: block;
  margin-bottom: 5px;
  font-size: 15.5px;
  font-weight: 750;
  letter-spacing: -0.015em;
  color: var(--text);
}

.rintro span {
  display: block;
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--muted);
}

/* The invitation reads as the point, the rules as the condition. */
.rintro__cta { margin-top: 4px; color: var(--accent); font-weight: 600; }


/* Shown in the expanded player when a stream does not arrive. Black tells the
   viewer nothing; this at least says whether to wait or move on. */
.cambig__msg {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  text-align: center;
  font-size: 14px;
  line-height: 1.55;
  color: rgba(255, 255, 255, .82);
  background: #14101a;
}

/* ---------- photos in the room ---------- */

.room__photo {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--muted);
  cursor: pointer;
}

.room__photo:hover { border-color: var(--accent); color: var(--accent); }
.room__photo .ic { width: 18px; height: 18px; }

/* While uploading. The button stays put and pulses rather than being swapped for
   a spinner, so the composer does not reflow mid-send. */
.room__photo.is-busy { opacity: .5; pointer-events: none; animation: live-pulse 1.1s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) { .room__photo.is-busy { animation: none; } }

.rmsg__photo {
  display: block;
  margin-top: 4px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 12px;
  overflow: hidden;
  background: var(--surface-3);
  cursor: zoom-in;

  /* Big enough to see what it is, small enough that three in a row do not push
     the conversation off the screen. The aspect ratio is set inline per photo,
     so tall and wide ones both fit this box without cropping. */
  width: 100%;
  max-width: 230px;
  max-height: 300px;
}

.rmsg__photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.rmsg__photo:hover { border-color: var(--accent); }

/* ---------- lightbox ---------- */

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 90;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(0, 0, 0, .88);
  backdrop-filter: blur(6px);
  animation: fade-in .15s ease-out;
}

@media (prefers-reduced-motion: reduce) { .lightbox { animation: none; } }

.lightbox__frame {
  margin: 0;
  max-width: 100%;
  max-height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}

/*
 * Fit the window, never exceed the photo.
 *
 * Two caps, and both matter. Without the viewport limits a tall photo runs off
 * the screen and has to be scrolled; without max-width/height in its own pixels
 * a small photo is stretched to fill the screen and turns to mush. Whichever
 * limit is smaller wins, so every photo is shown as large as is useful and no
 * larger.
 */
.lightbox img {
  max-width: min(100%, 1100px);
  max-height: min(82vh, 1100px);
  width: auto;
  height: auto;
  border-radius: 12px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, .6);
  cursor: default;
}

.lightbox figcaption {
  font-size: 13px;
  color: rgba(255, 255, 255, .7);
}

.lightbox__close {
  position: absolute;
  top: calc(14px + env(safe-area-inset-top));
  right: 14px;
  width: 42px;
  height: 42px;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, .14);
  color: #fff;
  display: flex;
  align-items: center;
  justify-content: center;
}

.lightbox__close .ic { width: 20px; height: 20px; }
.lightbox__close:hover { background: rgba(255, 255, 255, .24); }

/* Links in messages. The break rule matters: a long address in a narrow bubble
   would otherwise stretch the bubble past the edge of the screen. */
.rmsg__body a,
.bubble a {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 2px;
  word-break: break-word;
  overflow-wrap: anywhere;
}

.bubble--out a { color: #fff; text-decoration-color: rgba(255, 255, 255, .6); }

/* The greeter's picture in the moderation panel. */
.admin__slot--pic { width: 34px; height: 34px; border-radius: 50%; overflow: hidden; padding: 0; }
.admin__slot--pic img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ---------- sponsor banner above the chat ---------- */

.roomad {
  flex: none;
  display: flex;
  justify-content: center;
  align-items: center;
  overflow: hidden;
  background: var(--surface-2);
  border-bottom: 1px solid var(--line);

  /* Height is set from script to match the scaled banner, because the banner is
     a fixed 468x60 and the space it needs depends on how far it had to shrink.
     This is the fallback for the moment before that runs. */
  height: 62px;
}

/*
 * The banner is a fixed pixel size from a third party, so it cannot be made
 * responsive - it can only be scaled. Transform keeps it sharp and preserves
 * every click target in proportion, where squashing the iframe would just crop
 * it.
 */
.roomad__fit {
  width: 468px;
  height: 60px;
  flex: none;
  transform-origin: center center;
  transform: scale(var(--ad-scale, 1));
}

.roomad iframe {
  display: block;
  width: 468px;
  height: 60px;
  border: 0;
}

/* Nothing to show - a blocked or failed banner should not leave a gap. */
.roomad.is-empty { display: none; }

/* ============ desktop: cams left, chat right ============ */

@media (min-width: 1000px) {
  /*
   * Two columns instead of a stack.
   *
   * On a wide screen the stacked layout wastes most of the width and leaves the
   * cams as a thin strip with the conversation pushed far below the fold. Side
   * by side, the cams get the room to be watched and the chat stays in view
   * while you watch - which is the whole point of having both.
   *
   * The pane owns the height and neither column scrolls as a whole; only the
   * cam area and the message log scroll, so the composer and the banner stay
   * where they are.
   */
  

  /* The strip becomes a wall. Ten tiles in a row would be postage stamps, so
     they wrap into as many columns as the width allows. */

  /* The expanded cam takes the left column rather than floating over the page,
     so the grid stays visible underneath and switching cams is one click. */
  /* The player is an overlay on desktop too - see the block further down - so
     nothing here should try to place it inside the column. */

  .voice { border-left: 0; }
}

/* Wider still: give the chat a little more room rather than stretching the
   cams beyond a comfortable size. */
@media (min-width: 1500px) {
}


/* ============ expanded cam: fullscreen on mobile, modal on desktop ============ */

/*
 * Watching gets the whole screen.
 *
 * In the flow the player competed with the grid and the chat for height, which
 * on a phone left it a band in the middle of a busy page. Lifting it out means
 * the stream is the only thing on screen, which is what someone who tapped a cam
 * asked for. The close button returns them exactly where they were - nothing
 * else changes, and no history entry is spent.
 */
/*
 * The expanded cam: stream on top, chat below, exactly like a battle.
 *
 * This was a centring overlay - one item in the middle of the screen - and a
 * chat panel cannot take a width inside that, which is why it ended up floating
 * beside the video instead of sitting under it. A column with the two children
 * stretched is the arrangement the design actually calls for.
 */
.cambig {
  position: fixed;
  inset: 0;
  z-index: 85;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  gap: 12px;
  background: var(--bg);
  margin: 0;
  padding: 12px 12px calc(12px + env(safe-area-inset-bottom));
  animation: fade-in .16s ease-out;
  overflow: hidden;
}

@media (prefers-reduced-motion: reduce) { .cambig { animation: none; } }

/* The blurred still behind the video. Scaled up past the edges so the blur has
   nothing to fade into, and dimmed so it never competes with the stream. */
.cambig__wash {
  position: absolute;
  inset: 0;
  z-index: 0;
  background-size: cover;
  background-position: center;
  filter: blur(34px) brightness(.45) saturate(1.2);
  transform: scale(1.15);
  pointer-events: none;
}

.cambig__wash:empty { background-color: #07050a; }

/*
 * Portrait by default, because that is what a phone camera produces and what a
 * phone screen wants. The video is contained rather than cropped, so nothing is
 * cut off; the blurred wash fills whatever is left.
 */
/*
 * Removed: a second .cambig__stage from when the player was a full-screen
 * overlay.
 *
 * It set overflow: visible, and the blurred fill inside the stage is
 * position: absolute with inset: 0 - so with nothing clipping it, the blur
 * spilled out over the whole page. That is what greyed out the cam grid. It also
 * overrode the height, the ratio and the corners, because a later rule for the
 * same selector wins whatever the earlier one says.
 *
 * The definition that survives is the one above, near the other player styles.
 */

.cambig__video video { object-fit: contain; background: transparent; }

/* Controls clear of the notch and the home indicator. */
.cambig__controls {
  top: calc(10px + env(safe-area-inset-top));
  right: calc(10px + env(safe-area-inset-right));
  z-index: 3;
}

.cambig__foot {
  padding-bottom: calc(14px + env(safe-area-inset-bottom));
  z-index: 3;
}

.cambig__badge { top: calc(12px + env(safe-area-inset-top)); z-index: 3; }

.cambig__btn {
  width: 42px;
  height: 42px;
  background: rgba(0, 0, 0, .5);
  backdrop-filter: blur(8px);
}

/*
 * Removed: the desktop rules from when the player was a window over the site.
 *
 * They put `backdrop-filter: blur(10px)` and a near-black fill on .cambig, which
 * blurs everything *behind* the element - and .cambig is fixed across the whole
 * viewport, so the page underneath it was greyed out and unreadable. That is
 * what hid the cam grid. The same block also redefined the stage and hid the
 * blurred fill, overriding the current layout further down the file.
 *
 * The player is now a section with the stream and its chat side by side; those
 * rules live with the rest of the player styles.
 */

/* A landscape phone has no vertical room for a 9:16 box. */
/* A landscape phone has little height, so give the stream more of it and let
   the chat scroll below rather than squeezing both. */
@media (max-width: 999px) and (orientation: landscape) {
  .cambig__stage { max-height: 72vh; aspect-ratio: 16 / 10; }
}

/* Nothing behind the overlay should scroll while it is open. */
body.is-camopen { overflow: hidden; }

/* ============ chrome ============ */

/*
 * The top bar carries the gradient, thinly.
 *
 * In the reference the brand colour appears as a strip and then almost nowhere
 * else. That is what keeps it feeling expensive rather than loud: the eye reads
 * one accent, so the accent means something.
 */
.topbar {
  background: var(--surface);
  border-bottom: 1px solid var(--line);
  position: relative;
}

.topbar::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 2px;
  background: var(--grad);
  opacity: .9;
}

.topbar__count b { color: #d60e6c; }

/* Selected tab: the gradient as a mark under the label rather than a filled
   block, which on a dark page would read as a hole. */
.tab.is-active,
.sidenav__item.is-active {
  color: var(--text);
  background: none;
  position: relative;
}

.tab.is-active .ic,
.sidenav__item.is-active .ic { color: var(--accent); }

.tab.is-active::after {
  content: "";
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  bottom: 6px;
  width: 22px;
  height: 3px;
  border-radius: 999px;
  background: var(--grad);
}

.sidenav__item.is-active {
  background: var(--surface-2);
  border-radius: 10px;
  box-shadow: inset 2px 0 0 var(--accent);
}

.srow:hover,
.row-item:hover,
.rmsg:hover { background: var(--surface-2); }

/* Inputs are wells cut into the page, not raised cards. */
.room__composer input,
.gifs__bar input,
.field input,
.field select,
.field textarea {
  background: var(--surface-2);
  border: 1px solid var(--line);
  color: var(--text);
}

.room__composer input:focus,
.field input:focus,
.field textarea:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(212, 60, 224, .16);
  outline: none;
}

.rmsg__body { color: var(--text); }
.bubble--in { background: var(--surface-2); border-color: var(--line); }
.thread, .room__log { background: var(--bg); }

/* Anything that was the primary action now carries the gradient. */
.btn--primary,
.room__send,
.voice__mic.is-on,
.cams__go {
  background: var(--grad);
  border-color: transparent;
  color: #fff;
}

.btn--primary:hover { box-shadow: var(--glow-hot); }

.bubble--out {
  background: var(--grad);
  box-shadow: 0 2px 14px rgba(212, 60, 224, .22);
}

/* The admin search box. Full width because a name is the only thing going in
   it, and a narrow field would just make long names awkward to check. */
.admin__find { margin-bottom: 10px; }

.admin__find input {
  width: 100%;
  padding: 10px 14px;
  border-radius: 10px;
  border: 1px solid var(--line-strong);
  background: var(--surface-2);
  color: var(--text);
  font-size: 14.5px;
  outline: none;
}

.admin__find input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

/* Two actions per row on a phone would overflow, so they wrap under the name
   rather than squeezing the name out. */
@media (max-width: 420px) {
  .admin__row { flex-wrap: wrap; }
  .admin__acts { width: 100%; justify-content: flex-end; }
}


/* ============ landing ============ */

.hero { position: relative; isolation: isolate; overflow: hidden; background: var(--bg); }

/*
 * The dot field. Two layers at different scales so it does not read as a
 * regular grid, faded out towards the centre so the copy always sits on plain
 * black - the moment text crosses a pattern it gets harder to read, however
 * faint the pattern is.
 */
.hero__dots {
  position: absolute;
  inset: 0;
  z-index: -2;
  background-image:
    radial-gradient(rgba(212, 60, 224, .30) 1px, transparent 1px),
    radial-gradient(rgba(124, 77, 255, .18) 1px, transparent 1px);
  background-size: 22px 22px, 38px 38px;
  background-position: 0 0, 11px 11px;
  -webkit-mask-image: radial-gradient(ellipse 70% 60% at 50% 45%, transparent 35%, #000 100%);
  mask-image: radial-gradient(ellipse 70% 60% at 50% 45%, transparent 35%, #000 100%);
}

/* A single soft bloom behind the headline, which is where the reference's
   colour actually comes from. */
.hero__glow {
  position: absolute;
  z-index: -1;
  left: 50%;
  top: 12%;
  width: min(760px, 120vw);
  height: 420px;
  transform: translateX(-50%);
  background: radial-gradient(ellipse at center, rgba(212, 60, 224, .22) 0%, rgba(124, 77, 255, .10) 45%, transparent 70%);
  pointer-events: none;
}

.hero__strip {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  flex-wrap: wrap;
  padding: 9px 16px;
  background: var(--grad);
  color: #fff;
  font-size: 13px;
  text-decoration: none;
  text-align: center;
}

.hero__strip .ic { width: 15px; height: 15px; }
.hero__strip b { font-weight: 750; }

.hero__strip-cta {
  padding: 3px 12px;
  border-radius: 999px;
  background: rgba(0, 0, 0, .28);
  font-weight: 700;
  font-size: 12.5px;
}

.hero__inner {
  position: relative;
  max-width: 780px;
  margin: 0 auto;
  padding: 40px 20px calc(48px + env(safe-area-inset-bottom));
  text-align: center;
}

.hero__brand { justify-content: center; margin-bottom: 34px; }

.hero__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 7px 16px;
  margin-bottom: 20px;
  border-radius: 999px;
  border: 1px solid var(--line-strong);
  background: var(--surface);
  color: var(--muted);
  font-size: 13px;
  font-weight: 600;
}

.hero__eyebrow .ic { width: 14px; height: 14px; color: var(--accent-hot); }

.hero__title {
  margin: 0 0 18px;
  font-size: clamp(30px, 7vw, 52px);
  line-height: 1.12;
  font-weight: 800;
  letter-spacing: -0.035em;
}

/* The one place the gradient touches type. Used on a single word, because a
   whole headline in gradient stops being emphasis and becomes decoration. */
.hero__grad {
  background: var(--grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.hero__lead {
  margin: 0 auto 28px;
  max-width: 520px;
  font-size: 15.5px;
  line-height: 1.65;
  color: var(--muted);
}

.hero__cta {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 15px 34px;
  border-radius: 999px;
  background: var(--grad);
  color: #fff;
  font-size: 16px;
  font-weight: 750;
  text-decoration: none;
  box-shadow: var(--glow-hot);
  transition: transform .12s ease, box-shadow .12s ease;
}

.hero__cta:hover { transform: translateY(-1px); box-shadow: 0 10px 34px rgba(255, 47, 179, .5); }
.hero__cta:active { transform: none; }
.hero__cta span { font-size: 19px; line-height: 1; }

@media (prefers-reduced-motion: reduce) { .hero__cta { transition: none; } }

.hero__trust {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  margin: 18px 0 0;
  font-size: 13.5px;
  color: var(--muted);
}

.hero__trust .ic { width: 15px; height: 15px; color: var(--online); }
.hero__trust b { color: var(--text); }

.hero__feats {
  list-style: none;
  margin: 26px 0 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 10px;
}

.hero__feats li {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 9px 16px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--surface);
  font-size: 13px;
  color: var(--muted);
}

.hero__feats .ic { width: 14px; height: 14px; color: var(--accent); }

.hero__cards {
  display: grid;
  grid-template-columns: 1fr;
  gap: 12px;
  margin: 38px 0 0;
  text-align: left;
}

@media (min-width: 720px) { .hero__cards { grid-template-columns: repeat(3, 1fr); } }

.hcard {
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 0;
  padding: 14px;
  border-radius: 16px;
  border: 1px solid var(--line);
  background: var(--surface);
}

.hcard__face {
  width: 46px;
  height: 46px;
  flex: none;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid var(--accent);
}

.hcard figcaption { min-width: 0; }
.hcard b { display: block; font-size: 14px; margin-bottom: 2px; }
.hcard span { font-size: 12.5px; line-height: 1.45; color: var(--muted); }

.hcard--stat { justify-content: center; text-align: center; flex-direction: column; gap: 2px; }

.hcard__num {
  font-size: 30px;
  font-weight: 800;
  letter-spacing: -0.03em;
  background: var(--grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

.hero__sub { margin: 30px 0 0; font-size: 12.5px; color: var(--muted); }

/* ---------- password reveal ---------- */

.pw { position: relative; display: block; }

/* The field gets room on the right so the eye never sits over the text - at a
   long password the caret would otherwise run underneath it. */
.pw input { width: 100%; padding-right: 46px; }

.pw__eye {
  position: absolute;
  top: 50%;
  right: 6px;
  transform: translateY(-50%);
  width: 34px;
  height: 34px;
  border: 0;
  border-radius: 8px;
  background: none;
  color: var(--muted);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
}

.pw__eye .ic { width: 18px; height: 18px; }
.pw__eye:hover { color: var(--text); }
.pw__eye.is-on { color: var(--accent); }


/* ============ cams tab ============ */

/*
 * The grid is the first thing, and the only thing.
 *
 * Splitting it from the chat is what makes it work: on one screen the strip had
 * to stay short so the conversation had room, which meant ten tiles the size of
 * postage stamps. Alone, each tile can be big enough to see a face, which is the
 * decision the grid exists to support.
 */
#pane-cams { display: none; flex-direction: column; overflow-y: auto; }
#pane-cams.is-active { display: flex; }

#pane-cams .cams { flex: none; }

#pane-cams .cams__strip {
  display: grid;
  grid-auto-flow: row;
  grid-auto-columns: unset;
  grid-template-columns: repeat(2, 1fr);
  gap: 10px;
  overflow: visible;
}

/* Portrait tiles, because a phone camera produces portrait and a face fills the
   frame better than it does in a wide box. */
#pane-cams .cam { aspect-ratio: 3 / 4; }

@media (min-width: 560px) { #pane-cams .cams__strip { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 900px) { #pane-cams .cams__strip { grid-template-columns: repeat(4, 1fr); } }
@media (min-width: 1300px) { #pane-cams .cams__strip { grid-template-columns: repeat(5, 1fr); } }

/* The name sits over the photo, as in the reference, with a scrim so it stays
   readable whatever the picture behind it is doing. */
#pane-cams .cam__name {
  padding: 22px 10px 9px;
  font-size: 13.5px;
  background: linear-gradient(to top, rgba(0, 0, 0, .85), transparent);
}

/* ============ chat tab ============ */

#pane-chat { display: none; flex-direction: column; overflow: hidden; }
#pane-chat.is-active { display: flex; }
#pane-chat .voice { flex: none; }
#pane-chat .room { flex: 1; min-height: 0; }

/*
 * Six tabs where there were four.
 *
 * The tap area is what must not shrink - a target under about 44px is one people
 * miss - so the label gives way instead, and disappears entirely on the
 * narrowest phones where even that is not enough.
 */
.tabs--bottom .tab { min-width: 0; padding-left: 2px; padding-right: 2px; }
.tabs--bottom .tab span { font-size: 9.5px; letter-spacing: -0.01em; }

@media (max-width: 400px) {
  /* On the narrowest phones the labels stop fitting at all; the icons carry it,
     and the active tab keeps its underline so position is still readable. */
  .tabs--bottom .tab span { display: none; }
}

/* ---------- sign in / create account ---------- */

/*
 * Space between the fields.
 *
 * The form had no rhythm of its own, so every label sat right under the field
 * above it and the whole thing read as one block. A form is a list of decisions,
 * and it is easier to work through when each one is visibly separate.
 */
.form { display: flex; flex-direction: column; gap: 16px; }

.form .field input,
.form .field select,
.form .field textarea {
  width: 100%;
  padding: 12px 14px;
  border-radius: 12px;
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--text);
  font-size: 16px;   /* below 16px iOS zooms the page on focus */
  outline: none;
}

.form .field input:focus,
.form .field select:focus,
.form .field textarea:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(212, 60, 224, .16);
}

.field__label em {
  font-style: normal;
  font-weight: 500;
  text-transform: none;
  letter-spacing: 0;
  color: var(--muted);
  opacity: .8;
}

/*
 * Four options across is 70px each on a small phone, which is too narrow for
 * "Couple" and far too narrow to tap confidently. Two rows of two gives every
 * option room and keeps the group scannable.
 */
@media (max-width: 400px) {
  .segment { grid-template-columns: repeat(2, 1fr); }
  #auth-switch.segment--2 { grid-template-columns: repeat(2, 1fr); }
}

/* Age and country side by side only when age has room to stay legible. */
@media (max-width: 340px) {
  .row { flex-direction: column; }
  .field--age { width: 100%; }
}

.segment__btn.is-active {
  background: var(--grad);
  color: #fff;
  font-weight: 650;
}

/* The switch between the two forms is the first choice on the card, so it reads
   heavier than the options inside them. */
#auth-switch { margin-bottom: 20px; }
#auth-switch .segment__btn { padding: 11px 6px; font-size: 14.5px; font-weight: 600; }


.form__error {
  margin: 0;
  padding: 10px 12px;
  border-radius: 10px;
  background: rgba(255, 77, 104, .12);
  border: 1px solid rgba(255, 77, 104, .3);
  color: var(--danger);
  font-size: 13.5px;
}

/* The submit button is the point of the card; give it presence. */
.form .btn--block { padding: 14px; font-size: 15.5px; font-weight: 700; }

/* ---------- go live / stop ---------- */

/*
 * When you are broadcasting the button becomes red.
 *
 * It carried the brand gradient in both states, so the one control that turns
 * your camera off looked exactly like the one that turns it on. Colour is what
 * makes that readable at a glance, which matters most on a phone where the
 * strip may not even be on screen.
 */
#cams-go.is-live,
#cams-go-m.is-live {
  background: var(--danger);
  border-color: transparent;
  color: #fff;
  box-shadow: 0 3px 14px rgba(255, 77, 104, .35);
}

#cams-go.is-live:hover,
#cams-go-m.is-live:hover { background: #e03e57; }

/* A live dot on the mobile twin, so it reads as a state and not just a button. */
#cams-go-m.is-live::before {
  content: "";
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: #fff;
  margin-right: 2px;
  animation: live-pulse 1.4s ease-in-out infinite;
}

@media (prefers-reduced-motion: reduce) {
  #cams-go-m.is-live::before { animation: none; }
}

/* On a narrow header the label goes and the icon carries it - but only when
   idle. While live the word "Stop" stays, because that is the moment someone
   needs to be certain what the button does. */
@media (max-width: 400px) {
  .topbar__golive span { display: none; }
  .topbar__golive.is-live span { display: inline; }
}

/* ---------- sign-up form: use the width when there is width ---------- */

/*
 * The card grows on a tablet before the two-column landing kicks in.
 *
 * Between a phone and the split layout the form sat at 420px in the middle of a
 * 700px screen, which reads as an unfinished page rather than a considered one.
 */

/*
 * Fields that belong together sit together.
 *
 * A sign-up form asks for eight things, and stacking every one full width makes
 * a column long enough that the submit button falls off the screen - so people
 * scroll past half of it without reading. Pairing the short answers roughly
 * halves the height and makes the grouping obvious: identity, then details.
 */
@media (min-width: 480px) {
  .form--register .form__pair {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 14px;
  }
}

.form__pair { display: flex; flex-direction: column; gap: 16px; }

/* The photo slots read as a pair of tiles rather than two loose squares. */
.slots { display: flex; gap: 10px; }
.slots .slot { flex: 1; aspect-ratio: 1; max-width: 140px; }

/* A little more air around the two segmented pickers, which are the densest
   things on the card. */
#reg-gender { gap: 6px; }
#reg-gender .segment__btn { padding: 10px 4px; font-size: 13.5px; }

/* ============ PK battles ============ */

#pane-pk { display: none; flex-direction: column; overflow-y: auto; }
#pane-pk.is-active { display: flex; }

.pk { padding: 14px; }

.pk__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 14px;
}

.pk__title { margin: 0; font-size: 19px; font-weight: 800; letter-spacing: -0.02em; }
.pk__note { margin: 0 0 12px; font-size: 13.5px; color: var(--danger); }

.pk__list { display: grid; grid-template-columns: 1fr; gap: 12px; }
@media (min-width: 720px) { .pk__list { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1200px) { .pk__list { grid-template-columns: repeat(3, 1fr); } }

.pkcard {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 16px 14px;
  border-radius: 16px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--text);
  text-align: center;
  cursor: pointer;
  position: relative;
  overflow: hidden;
}

.pkcard:hover { border-color: var(--accent); }

.pkcard--free { border-style: dashed; color: var(--muted); }
.pkcard__free { display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 10px 0; }
.pkcard__free .ic { width: 22px; height: 22px; color: var(--accent); }
.pkcard__free b { font-size: 14.5px; color: var(--text); }
.pkcard__free i { font-style: normal; font-size: 12.5px; }

/* The two faces with the clash between them - the shape of the thing, before
   any words. */
.pkcard__faces { display: flex; align-items: center; gap: 10px; }

.pkcard__face {
  width: 60px;
  height: 60px;
  border-radius: 50%;
  overflow: hidden;
  background: var(--surface-3);
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px solid var(--line-strong);
}

.pkcard__face img { width: 100%; height: 100%; object-fit: cover; }
.pkcard__face i { font-style: normal; font-weight: 700; color: var(--muted); }
.pkcard__wait { opacity: .5; }

.pkcard__vs {
  font-size: 12px;
  font-weight: 900;
  letter-spacing: .06em;
  padding: 3px 8px;
  border-radius: 6px;
  background: var(--grad);
  color: #fff;
}

.pkcard__names { display: flex; align-items: center; gap: 7px; font-size: 13.5px; }
.pkcard__names i { font-style: normal; color: var(--muted); font-size: 11.5px; }

/* One bar, two claims on it: the whole state of the battle in one line. */
.pkcard__bar {
  display: block;
  width: 100%;
  height: 5px;
  border-radius: 999px;
  background: var(--accent-2);
  overflow: hidden;
}

.pkcard__bar i { display: block; height: 100%; background: var(--accent-hot); }

.pkcard__live {
  position: absolute;
  top: 10px;
  right: 10px;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: .08em;
  padding: 3px 7px;
  border-radius: 5px;
  background: var(--danger);
  color: #fff;
}

.pkcard__pending { font-size: 12px; color: var(--muted); }

/* ---------- the battle, open ---------- */

.screen--pk { display: flex; flex-direction: column; background: var(--bg); }
.bar--pk { flex: none; }

/* Same shell as the expanded cam: video on top, a white panel below, both
   centred and capped to the same width so the two screens are one design. */
.pkroom {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 12px 12px calc(12px + env(safe-area-inset-bottom));
  background: var(--bg);
}

/*
 * Two halves, edge to edge.
 *
 * Portrait on a phone means side by side gives each person a tall narrow strip,
 * which is the shape a phone camera produces - so they fill it rather than
 * being letterboxed, and the split reads as one picture cut down the middle.
 */
.pkstage {
  position: relative;
  flex: none;
  display: grid;
  grid-template-columns: 1fr 1fr;
  /*
   * A lit seam between the two sides.
   *
   * The gap was a grey hairline, which read as a rendering artefact. Making it
   * the brand pink turns the division into the point: this is a contest, and the
   * line is where the two halves meet.
   */
  gap: 3px;
  background: linear-gradient(180deg, var(--accent-hot), var(--accent), var(--accent-2));
  /*
   * Taller than wide overall, because each half is a portrait.
   *
   * Two 16:10 halves give each person a letterbox they do not fill; a 4:5 stage
   * splits into two tall panes that match what a phone camera produces, so faces
   * fill the frame instead of floating in the middle of it.
   */
  aspect-ratio: 5 / 5;
  width: 100%;
  max-width: 640px;
  max-height: 52vh;
  border-radius: 18px;
  overflow: hidden;
  box-shadow: var(--shadow-lg);
}

.pkside { position: relative; overflow: hidden; background: #0a0810; }
.pkside__video { position: absolute; inset: 0; }
.pkside__video video { width: 100%; height: 100%; object-fit: cover; display: block; }

.pkside__poster { width: 100%; height: 100%; object-fit: cover; display: block; opacity: .5; }

.pkside__poster--letter {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 40px;
  font-weight: 800;
  color: var(--muted);
}

.pkside__empty {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  text-align: center;
  font-size: 13px;
  color: var(--muted);
}

.pkside__who {
  position: absolute;
  left: 8px;
  bottom: 8px;
  z-index: 2;
  max-width: calc(100% - 16px);
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 4px 11px 4px 4px;
  border: 0;
  border-radius: 999px;
  background: rgba(0, 0, 0, .58);
  backdrop-filter: blur(8px);
  cursor: pointer;
}

.pkside__who:hover { background: rgba(0, 0, 0, .78); }

.pkside__avatar {
  width: 26px;
  height: 26px;
  flex: none;
  border-radius: 50%;
  overflow: hidden;
  background: var(--surface-3);
  display: flex;
  align-items: center;
  justify-content: center;
}

.pkside__avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.pkside__avatar i { font-style: normal; font-size: 11px; font-weight: 700; color: var(--muted); }

.pkside__name {
  font-size: 12.5px;
  font-weight: 650;
  color: #fff;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The gender tint reads on the name itself; against a dark scrim it needs to
   stay light enough to be legible, so it tints rather than replaces. */
.pkside__name.g-female { color: #ffc2ea; }
.pkside__name.g-male { color: #b8dcff; }
.pkside__name.g-couple { color: #dcc8ff; }

/* The score bar sits across the seam, which is where the contest actually is. */
.pkbar {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  z-index: 3;
  display: flex;
  height: 22px;
  font-size: 11px;
}

.pkbar__host { background: linear-gradient(90deg, var(--accent-hot), #ff6fc4); transition: width .4s ease; }
.pkbar__guest { background: linear-gradient(90deg, #6f8dff, var(--accent-2)); transition: width .4s ease; flex: 1; }

@media (prefers-reduced-motion: reduce) {
  .pkbar__host, .pkbar__guest { transition: none; }
}

.pkbar__num {
  position: absolute;
  top: 3px;
  font-size: 11.5px;
  font-weight: 800;
  color: #fff;
  text-shadow: 0 1px 2px rgba(0, 0, 0, .5);
}

.pkbar__num--host { left: 10px; }
.pkbar__num--guest { right: 10px; }

.pkstage__vs {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  z-index: 3;
  font-size: 15px;
  font-weight: 900;
  letter-spacing: .08em;
  padding: 5px 11px;
  border-radius: 8px;
  background: rgba(0, 0, 0, .55);
  backdrop-filter: blur(8px);
  color: #fff;
  pointer-events: none;
}

/* ---------- the battle's own chat ---------- */

.pkchat {
  flex: 1;
  min-height: 0;
  width: 100%;
  max-width: 640px;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 18px;
  overflow: hidden;
}

.pkchat__log {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 7px;
}

.pkmsg { font-size: 14px; line-height: 1.45; }
.pkmsg b { font-weight: 700; margin-right: 6px; }
.pkmsg span { color: var(--text); word-break: break-word; }

.pkchat__composer {
  flex: none;
  display: flex;
  gap: 8px;
  padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
  border-top: 1px solid var(--line);
  background: var(--surface);
}

.pkchat__composer input {
  flex: 1;
  min-width: 0;
  padding: 11px 14px;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--surface-2);
  color: var(--text);
  font-size: 16px;
  outline: none;
}

.pkchat__composer input:focus { border-color: var(--accent); }

/*
 * On a wide screen the chat moves beside the stage rather than under it, so the
 * video can be large and the conversation still visible - the same reasoning as
 * the cams tab, and the layout the reference uses.
 */
/*
 * The battle stacks too, at every width.
 *
 * Side by side looked efficient and read badly: two portrait halves plus a chat
 * column left all three narrow, and the arrangement changed shape halfway up the
 * range so the same screen behaved differently on a laptop and a monitor. Below
 * the stage, the video keeps its proportions and the conversation sits with it -
 * the same as a cam, which is the point.
 */
/* Same arrangement as an expanded cam: the two halves fill the left, the chat is
   a column on the right. */
@media (min-width: 1000px) {
  .pkroom {
    flex-direction: row;
    align-items: stretch;
    justify-content: center;
    gap: 0;
    padding: 0;
  }

  /* Same reasoning as a single cam: the pair keeps its shape and is sized by
     the height, so the two people stay large whatever the window does. */
  .pkroom__left {
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
  }

  .pkstage {
    flex: none;
    width: auto;
    height: 100%;
    max-width: 100%;
    max-height: none;
    aspect-ratio: 5 / 5;
    border-radius: 16px;
  }

  .pkchat {
    flex: none;
    width: clamp(320px, 26vw, 420px);
    max-width: none;
    height: 100%;
    border: 0;
    border-left: 1px solid var(--line);
    border-radius: 0;
  }

  .pkchat__composer { background: var(--surface-2); }

  /* Bigger type on a bigger screen: the score is the thing being watched. */
  .pkbar { height: 30px; }
  .pkbar__num { top: 6px; font-size: 14px; }
  .pkbar__num--host { left: 16px; }
  .pkbar__num--guest { right: 16px; }
  .pkstage__vs { font-size: 19px; padding: 7px 15px; }
  .pkside__who { left: 14px; bottom: 14px; padding: 5px 15px 5px 5px; gap: 9px; }
  .pkside__avatar { width: 34px; height: 34px; }
  .pkside__name { font-size: 14.5px; }
}

@media (min-width: 1600px) {
  .pkchat { width: clamp(380px, 24vw, 460px); }
}

/* Your own half is mirrored, the way a front camera looks in every other app -
   an unmirrored self-view reads as wrong even though it is technically right. */
.pkside__video video.is-self { transform: scaleX(-1); }

/* ---------- battle list on a wide screen ---------- */

@media (min-width: 900px) {
  .pk { padding: 24px 28px; max-width: 1400px; margin: 0 auto; width: 100%; }
  .pk__title { font-size: 24px; }
  .pk__head { margin-bottom: 20px; }

  .pk__list { gap: 18px; }

  /*
   * The card earns more room: bigger faces, and the clash between them reads as
   * the point rather than as a label. At this size the two portraits are what
   * someone is choosing between, so they should be the largest thing on it.
   */
  .pkcard { padding: 22px 18px; gap: 14px; border-radius: 20px; }
  .pkcard__face { width: 84px; height: 84px; }
  .pkcard__faces { gap: 14px; }
  .pkcard__vs { font-size: 13px; padding: 4px 10px; }
  .pkcard__names { font-size: 15px; }
  .pkcard__bar { height: 7px; }

  /* A quiet lift on hover, so the grid feels like a set of choices rather than
     a table. */
  .pkcard { transition: transform .14s ease, border-color .14s ease, box-shadow .14s ease; }
  .pkcard:hover { transform: translateY(-2px); box-shadow: var(--glow); }
}

@media (prefers-reduced-motion: reduce) {
  .pkcard { transition: none; }
  .pkcard:hover { transform: none; }
}

/* ---------- inviting from the battle ---------- */

/*
 * The empty half is the button. A separate control elsewhere would mean leaving
 * the battle to look for someone, which is the whole thing being fixed.
 */
.pkside__invite {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 16px;
  border: 0;
  background: linear-gradient(160deg, rgba(212, 60, 224, .14), rgba(124, 77, 255, .10));
  color: var(--text);
  cursor: pointer;
  text-align: center;
}

.pkside__invite::after {
  content: "";
  position: absolute;
  inset: 10px;
  border: 2px dashed var(--line-strong);
  border-radius: 14px;
  pointer-events: none;
}

.pkside__invite:hover::after { border-color: var(--accent); }
.pkside__invite .ic { width: 26px; height: 26px; color: var(--accent); }
.pkside__invite b { font-size: 14.5px; font-weight: 700; }
.pkside__invite i { font-style: normal; font-size: 12px; color: var(--muted); }

/* The picker itself: a list, scrollable, with the whole row as the target. */
.modal__card--list { max-width: 460px; }

.pkpick {
  max-height: min(52vh, 420px);
  overflow-y: auto;
  margin: 4px 0 14px;
  border-radius: 12px;
  border: 1px solid var(--line);
}

.pkpick__msg { padding: 22px 16px; text-align: center; font-size: 13.5px; color: var(--muted); }

.pkpick__row {
  display: flex;
  align-items: center;
  gap: 11px;
  width: 100%;
  padding: 10px 12px;
  border: 0;
  border-bottom: 1px solid var(--line);
  background: none;
  color: var(--text);
  text-align: left;
  cursor: pointer;
}

.pkpick__row:last-child { border-bottom: 0; }
.pkpick__row:hover { background: var(--surface-2); }

.pkpick__face {
  width: 42px;
  height: 42px;
  flex: none;
  border-radius: 50%;
  overflow: hidden;
  background: var(--surface-3);
  display: flex;
  align-items: center;
  justify-content: center;
}

.pkpick__face img { width: 100%; height: 100%; object-fit: cover; }
.pkpick__face i { font-style: normal; font-weight: 700; color: var(--muted); font-size: 15px; }

.pkpick__who { flex: 1; min-width: 0; }
.pkpick__who b { display: block; font-size: 14.5px; }
.pkpick__who i { font-style: normal; font-size: 12px; color: var(--muted); }

.pkpick__vip {
  flex: none;
  padding: 2px 7px;
  border-radius: 5px;
  background: var(--grad);
  color: #fff;
  font-size: 10px;
  font-weight: 800;
  letter-spacing: .05em;
}

.pkpick__go {
  flex: none;
  padding: 6px 13px;
  border-radius: 999px;
  background: var(--surface-3);
  font-size: 12.5px;
  font-weight: 700;
  color: var(--accent);
}

.pkpick__row:hover .pkpick__go { background: var(--grad); color: #fff; }

/* Hearts over the opening of a battle. Tiled so the field covers any stage size
   without stretching the artwork, and never in the way of a tap. */
.pkhearts {
  position: absolute;
  inset: 0;
  z-index: 4;
  pointer-events: none;
  background-image: url("/img/hearts.gif");
  background-repeat: repeat;
  background-size: 180px auto;
  opacity: .75;
  mix-blend-mode: screen;
}

/* Smaller tiles on a phone: at 180px only two or three hearts fit across the
   stage, which reads as a texture rather than as hearts flying. */
@media (max-width: 600px) {
  .pkhearts { background-size: 110px auto; }
  .pkfire { height: 30%; }
}

@media (prefers-reduced-motion: reduce) { .pkhearts { display: none; } }

/*
 * The wrappers are only a desktop device: they exist to centre the stream in its
 * own half. Stacked, they must not add a layer that eats height, so they simply
 * pass their child through.
 */
.cambig__left,
.pkroom__left {
  display: contents;
}

@media (min-width: 1000px) {
  .cambig__left,
  .pkroom__left { display: flex; }
}

/* ---------- battle effects ---------- */

/*
 * The seam again, drawn over the top with a glow.
 *
 * The gap alone gives the colour but not the light; a second element can bloom
 * outwards without pushing the halves apart, which a border on either side
 * would.
 */
.pkstage::after {
  content: "";
  position: absolute;
  left: 50%;
  top: 0;
  bottom: 0;
  width: 3px;
  transform: translateX(-50%);
  z-index: 3;
  background: linear-gradient(180deg, var(--accent-hot), var(--accent), var(--accent-2));
  box-shadow: 0 0 14px rgba(255, 47, 179, .8), 0 0 34px rgba(212, 60, 224, .45);
  pointer-events: none;
}

/* A run of flame along the bottom, over both halves. Anchored to the bottom
   edge so it burns up from the floor rather than floating. */
.pkfire {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 34%;
  z-index: 4;
  pointer-events: none;
  background-image: url("/img/fire.gif");
  background-repeat: repeat-x;
  background-position: bottom center;
  background-size: auto 100%;
  /* The source has a white field behind the flame; screen drops it and keeps
     the colour, which is cheaper than re-cutting the artwork. */
  mix-blend-mode: screen;
  opacity: .9;
  animation: fx-in .4s ease-out;
}

@keyframes fx-in { from { opacity: 0; } to { opacity: .9; } }

@media (prefers-reduced-motion: reduce) {
  .pkfire { display: none; }
}

/* Tipping either side. Placed top-inward so it never covers a face or the name
   badge at the bottom. */
.pktip {
  position: absolute;
  top: 10px;
  z-index: 5;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 13px;
  border-radius: 999px;
  background: linear-gradient(135deg, #ffb020 0%, #ff8a2b 100%);
  color: #fff;
  font-size: 12.5px;
  font-weight: 800;
  text-decoration: none;
  box-shadow: 0 3px 12px rgba(255, 138, 43, .4);
}

.pktip:hover { filter: brightness(1.07); }
.pktip .ic { width: 14px; height: 14px; }
.pktip--host { left: 10px; }
.pktip--guest { right: 10px; }

@media (max-width: 380px) {
  .pktip span { display: none; }
  .pktip { padding: 7px 9px; }
}

/* Sound is blocked until a tap - say so instead of being silently mute. */
.pksound {
  position: absolute;
  left: 50%;
  bottom: 14%;
  transform: translateX(-50%);
  z-index: 6;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 18px;
  border: 0;
  border-radius: 999px;
  background: rgba(0, 0, 0, .78);
  backdrop-filter: blur(8px);
  color: #fff;
  font-size: 13.5px;
  font-weight: 700;
  cursor: pointer;
  box-shadow: 0 4px 18px rgba(0, 0, 0, .5);
}

.pksound .ic { width: 17px; height: 17px; }
.pksound:hover { background: rgba(0, 0, 0, .9); }

/* ============ light chrome ============ */

/*
 * The top bar is white with a hairline, not a coloured band.
 *
 * In the reference the chrome disappears and the content carries the colour;
 * a filled bar at the top would be the loudest thing on a page whose point is
 * the photographs below it.
 */
.topbar {
  background: var(--surface);
  border-bottom: 1px solid var(--line);
}

.topbar::after { display: none; }
.topbar .wordmark__text, .topbar__count { color: var(--text); }
.topbar__count b { color: var(--online); }
.topbar .ic { color: var(--text); }
.topbar .logo-mark path, .topbar .logo-mark circle { fill: url(#lg-brand); }

/*
 * The sidebar: a quiet list, with the current item marked by a filled row and a
 * pink rule rather than by colour alone - colour alone fails for anyone who
 * cannot separate the two hues.
 */
.sidebar {
  background: var(--surface);
  border-right: 1px solid var(--line);
}

.sidenav__item {
  color: var(--muted);
  font-weight: 550;
  border-radius: 10px;
}

.sidenav__item .ic { color: var(--muted); }
.sidenav__item:hover { background: var(--surface-2); color: var(--text); }
.sidenav__item:hover .ic { color: var(--text); }

.sidenav__item.is-active {
  background: var(--surface-2);
  color: var(--text);
  font-weight: 700;
  box-shadow: inset 3px 0 0 var(--accent);
}

.sidenav__item.is-active .ic { color: var(--accent); }

/* Bottom tabs follow the same rule: filled, plus the pink mark. */
.tabs--bottom { background: var(--surface); border-top: 1px solid var(--line); }
.tab { color: var(--muted); }
.tab .ic { color: var(--muted); }
.tab.is-active { color: var(--text); }
.tab.is-active .ic { color: var(--accent); }
.tab.is-active::after { background: var(--accent); }

/* Rows lift with a wash of the page grey, keeping pink for actions only. */
.srow:hover, .row-item:hover, .rmsg:hover { background: var(--surface-2); }

.thread, .room__log { background: var(--bg); }
.bubble--in { background: var(--surface); border-color: var(--line); }

/* Inputs are wells on a white page, so they need a visible edge. */
.room__composer input,
.gifs__bar input,
.field input,
.field select,
.field textarea,
.pkchat__composer input {
  background: var(--surface);
  border: 1px solid var(--line-strong);
  color: var(--text);
}

.room__composer input:focus,
.field input:focus,
.field textarea:focus,
.pkchat__composer input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
  outline: none;
}

.room__composer, .pkchat__composer { background: var(--surface); border-top-color: var(--line); }

/* The cam and battle panels keep a dark stage - video belongs on black - but
   everything around them is light. */
.cams { background: var(--surface); border-bottom: 1px solid var(--line); }
.pk { background: transparent; }
.pkchat__log { background: var(--surface); }
.pkmsg span { color: var(--text); }


/* ============ sign in / create account ============ */

/*
 * The panel sits over the landing page rather than under it.
 *
 * Stacked below a hero, the form was something you scrolled to and the page had
 * no obvious purpose; brought forward it is the first thing you can act on,
 * which is what a page whose job is signing people up should offer.
 */
.auth {
  position: relative;
  z-index: 2;
  display: flex;
  justify-content: center;
  align-items: flex-start;
  padding: 0 16px calc(28px + env(safe-area-inset-bottom));
  margin-top: -28px;
}

.auth__card {
  width: 100%;
  max-width: 520px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 22px;
  padding: 26px 22px 28px;
  box-shadow: var(--shadow-lg);
}

.auth__head { text-align: center; margin-bottom: 20px; }
.auth__brand { justify-content: center; margin-bottom: 8px; }
.auth__tag { margin: 0; font-size: 13.5px; color: var(--muted); }

/* The switch between the two forms is the first decision on the card, so it
   reads as a control rather than as two links. */
#auth-switch {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4px;
  padding: 4px;
  margin-bottom: 20px;
  border-radius: 999px;
  background: var(--surface-2);
  border: 1px solid var(--line);
}

#auth-switch .segment__btn {
  padding: 10px 8px;
  border: 0;
  border-radius: 999px;
  background: none;
  color: var(--muted);
  font-size: 14.5px;
  font-weight: 650;
  cursor: pointer;
}

#auth-switch .segment__btn.is-active {
  background: var(--grad);
  color: #fff;
  box-shadow: var(--glow);
}

/* Fields: generous targets, and 16px text so iOS does not zoom on focus. */
.form { display: flex; flex-direction: column; gap: 15px; }

.form .field input,
.form .field select,
.form .field textarea {
  width: 100%;
  padding: 13px 15px;
  border-radius: 12px;
  font-size: 16px;
}

.field__label {
  display: block;
  margin-bottom: 6px;
  font-size: 12.5px;
  font-weight: 650;
  color: var(--text);
}

.field__label em { font-style: normal; font-weight: 500; color: var(--muted); }

.form .btn--block {
  padding: 15px;
  font-size: 15.5px;
  font-weight: 750;
  border-radius: 12px;
  background: var(--grad);
  border-color: transparent;
  color: #fff;
}

.form .btn--block:hover { box-shadow: var(--glow-hot); }

.form__error {
  margin: 0;
  padding: 11px 13px;
  border-radius: 10px;
  background: #fdecef;
  border: 1px solid #f6c9d1;
  color: var(--danger);
  font-size: 13.5px;
}

.auth__note { margin: 2px 0 0; text-align: center; font-size: 12.5px; color: var(--muted); }

/* Four choices across is too narrow to read or hit on a small phone. */
@media (max-width: 420px) {
  #reg-gender { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 360px) {
  .row { flex-direction: column; }
  .field--age { width: 100%; }
}

/* Room to breathe once there is room to give. */
@media (min-width: 620px) {
  .auth { padding-bottom: 44px; margin-top: -40px; }
  .auth__card { max-width: 560px; padding: 34px 34px 36px; }
}

/*
 * Side by side on a wide screen: the pitch on the left, the form on the right,
 * with the form given real width rather than a column of its own.
 */
@media (min-width: 1040px) {
  .landing { flex-direction: row; align-items: center; min-height: 100vh; }
  .hero { flex: 1; display: flex; align-items: center; padding: 48px; }
  .hero__inner { max-width: 560px; text-align: left; }
  .hero__brand { justify-content: flex-start; }
  .hero__feats, .hero__trust { justify-content: flex-start; }

  .auth {
    flex: none;
    width: clamp(480px, 36vw, 620px);
    align-items: center;
    margin-top: 0;
    padding: 40px;
  }

  .auth__card { max-width: none; }
}

/* ============ a cam's own chat ============ */

/*
 * Below the stream on a phone, beside it once there is width.
 *
 * The audience belongs to the stream it is watching, so it sits with it rather
 * than in a separate place you have to navigate to - which is what made the old
 * single room feel like shouting into a hall.
 */
.camchat {
  flex: 1;
  min-height: 0;
  width: 100%;
  max-width: 640px;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 18px;
  overflow: hidden;
}

.camchat__log {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 7px;
}

.cmsg { font-size: 14px; line-height: 1.45; }
.cmsg b { font-weight: 700; margin-right: 6px; cursor: pointer; }
.cmsg b:hover { text-decoration: underline; }
.cmsg span { color: var(--text); word-break: break-word; }

.camchat__composer {
  flex: none;
  display: flex;
  gap: 8px;
  padding: 10px 12px calc(10px + env(safe-area-inset-bottom));
  border-top: 1px solid var(--line);
  background: var(--surface);
}

.camchat__composer input {
  flex: 1;
  min-width: 0;
  padding: 11px 14px;
  border-radius: 999px;
  font-size: 16px;
}

/* In the expanded player the stage is capped so the conversation below it is
   reachable without scrolling past the video. */
.cambig .cambig__stage { flex: none; }

@media (max-width: 999px) {
  .cambig__stage { max-height: 52vh; }
}

/*
 * Desktop: stream on the left, chat down the right, both full height.
 *
 * A wide window has height to spare and width to fill, so stacking wastes both -
 * the video ends up short and the chat gets a strip at the bottom. Side by side,
 * the stream is as tall as the window allows and the conversation is a column
 * you can actually follow, which is how every cam site is laid out because it is
 * what the shape of a monitor wants.
 *
 * On a phone the stacked arrangement stays: there is no width to divide.
 */
@media (min-width: 1000px) {
  .cambig {
    flex-direction: row;
    align-items: stretch;
    justify-content: center;
    gap: 0;
    padding: 0;
  }

  /*
   * The stream keeps its shape and is sized by the height available.
   *
   * Letting it fill the column was the mistake: the column is landscape, a
   * phone camera is portrait, and `object-fit: contain` then draws a small
   * video in the middle of a large box - with the blurred fill taking
   * everything around it. The wider the window, the more of the screen was
   * blur and the less was the person. Deriving the width from the height
   * instead means the picture grows with the window and the fill stays a
   * margin.
   */
  .cambig__left {
    flex: 1;
    min-width: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 16px;
  }

  .cambig__stage {
    flex: none;
    width: auto;
    height: 100%;
    max-width: 100%;
    max-height: none;
    aspect-ratio: 3 / 4;
    border-radius: 16px;
  }

  .camchat {
    flex: none;
    width: clamp(320px, 26vw, 420px);
    max-width: none;
    height: 100%;
    border: 0;
    border-left: 1px solid var(--line);
    border-radius: 0;
  }
}

@media (min-width: 1600px) {
  .camchat { width: clamp(380px, 24vw, 460px); }
}

/* ============ Diamond ============ */

/*
 * The badge. Sized to the text it sits beside rather than to a fixed pixel
 * count, so it stays in proportion wherever names are rendered.
 */
.dbadge {
  width: 1em;
  height: 1em;
  margin-right: 4px;
  vertical-align: -0.12em;
  color: var(--accent);
  flex: none;
}

.profile__name .dbadge,
.bar__peername .dbadge { width: .9em; height: .9em; }

.modal__icon--diamond { color: var(--accent); }

.diamond__price {
  margin: 6px 0 2px;
  text-align: center;
  font-size: 15px;
  color: var(--muted);
}

.diamond__price b {
  font-size: 26px;
  font-weight: 800;
  letter-spacing: -0.02em;
  background: var(--grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

#diamond-buy { text-decoration: none; display: inline-flex; align-items: center; justify-content: center; }
