/* ==============================================================
   ReactLive Room (Surface edition) — app structure.
   Layout only; every value resolves through ../surface.css tokens.
   Class prefix: room-
   ============================================================== */

.room-app {
  min-height: 100dvh;
  background: var(--rlx-background);
  color: var(--rlx-foreground);
}

/* ── Shared shell padding ─────────────────────────────────────────────── */
.room-live,
.room-join {
  max-width: 1040px;
  margin: 0 auto;
  padding: clamp(16px, 3vw, 28px);
}
.room-live {
  display: flex;
  flex-direction: column;
  gap: var(--rlx-space-4);
  min-height: 100dvh;
}

/* Confirm dialog (stop recording / leave). */
.room-confirm-text {
  margin: 0;
  color: var(--rlx-foreground-muted);
  font-size: 0.9rem;
  line-height: 1.5;
}
.room-confirm-btn { min-width: 96px; }

/* ── Header ───────────────────────────────────────────────────────────── */
.room-head {
  display: flex;
  align-items: center;
  gap: var(--rlx-space-4);
  flex-wrap: wrap;
}
.room-brand {
  display: inline-flex;
  align-items: center;
  gap: var(--rlx-space-2);
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--rlx-foreground);
}
.room-brand svg { color: var(--rlx-primary); }
.room-brand b { color: var(--rlx-primary); }
.room-head-meta {
  display: flex;
  gap: var(--rlx-space-6);
  margin-left: auto;
}
/* "ROOM" label + id on one line (was stacked — wasted vertical space). */
.room-meta-item { display: flex; align-items: baseline; gap: 6px; line-height: 1.25; min-width: 0; }
.room-meta-k {
  font-size: 0.68rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--rlx-foreground-muted);
}
/* Room id can be arbitrarily long — keep it on one line and ellipsize. Generous
   cap on desktop (only very long ids trim); a phone trims tighter (see media). */
.room-meta-v {
  font-size: 0.9rem;
  font-weight: 600;
  max-width: 340px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.room-head-status { display: inline-flex; align-items: center; gap: var(--rlx-space-2); }
.room-rec-pill { font-variant-numeric: tabular-nums; }

/* ── Stage (gallery) ──────────────────────────────────────────────────── */
.room-stage {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: var(--rlx-space-4);
  background: var(--rlx-background-secondary);
  border: var(--rlx-border-width-sm) solid var(--rlx-divider);
  border-radius: var(--rlx-radius-xl);
  padding: var(--rlx-space-5);
}
.room-stage-head { display: flex; align-items: center; gap: var(--rlx-space-3); }
/* Stream-state badge (Starting… / REC) inline with roster count — mobile only. */
.room-stage-status { display: none; margin-left: auto; }
.room-stage-title {
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--rlx-foreground-muted);
}
.room-stage-count { font-size: 0.82rem; color: var(--rlx-foreground-muted); }

.room-grid {
  flex: 1;
  display: grid;
  /* Fixed-footprint participant cards (130px) centered as a group — a single
     card never stretches screen-wide. */
  grid-template-columns: repeat(auto-fit, 130px);
  gap: var(--rlx-space-4);
  align-content: center;
  justify-content: center;
}

/* ── Participant card (audio-only) ────────────────────────────────────────
   Vertical stack: avatar (speaking halo + mic badge) → name → role badge. */
.room-tile {
  box-sizing: border-box;
  width: 130px;
  min-height: 154px;                      /* near-square footprint (was 180, elongated) */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 10px;                              /* avatar zone → text stack */
  padding: 10px var(--rlx-space-3) 22px;  /* extra breathing room below the role badge */
  background: var(--rlx-content1);
  border: var(--rlx-border-width-md) solid var(--rlx-separator-secondary);
  border-radius: var(--rlx-radius-lg);
  box-shadow: var(--rlx-shadow-md);
  transition: border-color 0.18s ease, box-shadow 0.18s ease, transform 0.18s ease;
}
.room-tile--listener { background: var(--rlx-background-tertiary); opacity: 0.9; }
.room-tile--speaking {
  border-color: #22d3ee;
  box-shadow: 0 0 0 1px #22d3ee, var(--rlx-shadow-md);
  transform: translateY(-2px);
}

/* Avatar zone — the ring is sized to the avatar so the halo + badge anchor to it. */
.room-tile-ring {
  position: relative;
  width: 80px;
  height: 80px;
  flex: none;
}
.room-tile-avatar {
  --rlx-avatar-size: 80px;
  border-radius: 50%;
  /* soft inner overlay so an over-exposed photo can't bleed past the circle */
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.05);
}
/* Initials placeholder: keep it soft so it recedes behind the name label below
   (lighter weight + colour, smaller than the kit default of 0.4 × avatar). */
.room-tile-avatar .rlx-avatar-initials {
  font-weight: 500;
  font-size: calc(var(--rlx-avatar-size) * 0.32);
  color: var(--rlx-text-muted);
}

/* Speaking "audio halo": a tight cyan base ring + an outward ping wave. */
.room-tile--speaking .room-tile-avatar {
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.05), 0 0 0 3px #22d3ee;
}
.room-tile-halo {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  pointer-events: none;
}
.room-tile--speaking .room-tile-halo {
  animation: room-halo-ping 1.5s cubic-bezier(0, 0, 0.2, 1) infinite;
}
@keyframes room-halo-ping {
  from { box-shadow: 0 0 0 0 rgba(34, 211, 238, 0.3); }
  to   { box-shadow: 0 0 0 12px rgba(34, 211, 238, 0); }
}

/* Mic-status badge, bottom-right quadrant of the avatar. */
.room-tile-mic {
  position: absolute;
  right: 2px;
  bottom: 2px;
  width: 24px;
  height: 24px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  color: #fff;
  box-shadow: 0 0 0 2px var(--rlx-content1);   /* cut-out ring against the card */
}
.room-tile--muted .room-tile-mic { background: #ef4444; }      /* muted: red mic-off */
.room-tile--listener .room-tile-mic {                          /* listener: neutral */
  background: var(--rlx-foreground-muted);
  color: var(--rlx-content1);
}

/* Text stack: name + stacked role badge. */
.room-tile-meta {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  max-width: 100%;
}
.room-tile-name-text {
  max-width: 100%;
  font-size: 14px;
  font-weight: 600;
  color: var(--rlx-foreground);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.room-tile-role {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 9999px;
  background: #f59e0b;
  color: #422006;
  font-size: 10px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  line-height: 1.4;
}

/* Screen-reader-only status (the card itself is intentionally text-free). */
.room-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  border: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

@media (prefers-reduced-motion: reduce) {
  .room-tile--speaking .room-tile-halo { animation: none; }
}

/* ── Reaction bar ─────────────────────────────────────────────────────────
   The kit's reaction tiles are flex:1 (full-width cards) — tuned for a ~480px
   mobile panel. In this wide room that balloons into boxy stat cards, so scope
   it down into a compact, centered row of pill chips (emoji + count).        */
.room-reactions { width: 100%; display: flex; justify-content: center; align-items: center; }
/* Prevent the kit's reactionbar wrapper from stretching full-width, so the parent flex can truly center it. */
.room-reactions > * { max-width: 100%; }
.room-reactions .rlx-reactionbar-row {
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--rlx-space-2);
  margin-left: auto;
  margin-right: auto;
}
.room-reactions .rlx-reaction {
  flex: 0 0 auto;
  width: auto;
  display: inline-flex;
  align-items: center;
  gap: var(--rlx-space-2);
  grid-template-rows: none;
  padding: 7px 14px;
  border-radius: var(--rlx-radius-full);
  background: var(--rlx-content1);
}
.room-reactions .rlx-reaction-glyph { font-size: 16px; }
.room-reactions .rlx-reaction-count {
  font-size: 0.82rem;
  font-variant-numeric: tabular-nums;
}
/* Labels add height + noise; the emoji already reads. */
.room-reactions .rlx-reaction-label { display: none; }

/* ── Dock ─────────────────────────────────────────────────────────────── */
.room-dock {
  display: flex;
  align-items: center;
  gap: var(--rlx-space-3);
  flex-wrap: wrap;
  padding: var(--rlx-space-3) var(--rlx-space-4);
  background: var(--rlx-content1);
  border: var(--rlx-border-width-sm) solid var(--rlx-divider);
  border-radius: var(--rlx-radius-full);
  box-shadow: var(--rlx-shadow-md);
}
.room-dock-spacer { flex: 1; }
.room-dock-btn--record { font-variant-numeric: tabular-nums; }


/* ── Join view ────────────────────────────────────────────────────────── */
.room-join {
  display: flex;
  flex-direction: column;
  gap: var(--rlx-space-4);
  min-height: 100dvh;
}
.room-join-head { flex: 0 0 auto; }
/* Card sits in its own flexible region so it stays centered without
   overlapping the header above or the footer below. */
.room-join-body {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--rlx-space-5) 0;
}
.room-join-card {
  width: min(460px, 100%);
  /* Light mode: content1 (white) lifts above the off-white page. */
  background: var(--rlx-content1);
  border: var(--rlx-border-width-sm) solid var(--rlx-divider);
  border-radius: var(--rlx-radius-xl);
  box-shadow: var(--rlx-shadow-lg);
  padding: clamp(20px, 4vw, 32px);
}
/* Dark mode: content1 is nearly the page colour, so lift the form to content2
   (a clearly lighter panel) so it separates and reads. */
:root[data-skin='spark'] .room-join-card {
  background: var(--rlx-content2);
}

/* Dark mode call view: the default surfaces all sit within a few % of the page
   (#06080F), so the stage/tiles/dock read as one muddy block. Lift each layer
   into a legible elevation ladder: page < stage(content1) < tiles/dock(content2),
   with listener tiles a step dimmer so they still recede. */
:root[data-skin='spark'] .room-stage { background: var(--rlx-content1); }
:root[data-skin='spark'] .room-tile { background: var(--rlx-content3); }
:root[data-skin='spark'] .room-tile--listener { background: var(--rlx-content2); }
:root[data-skin='spark'] .room-tile-avatar { box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08); }
:root[data-skin='spark'] .room-tile--speaking .room-tile-avatar { box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08), 0 0 0 3px #22d3ee; }
:root[data-skin='spark'] .room-tile-mic { box-shadow: 0 0 0 2px var(--rlx-content3); }
:root[data-skin='spark'] .room-dock { background: var(--rlx-content2); }
:root[data-skin='spark'] .room-reactions .rlx-reaction { background: var(--rlx-content2); }
.room-join-title { margin: 0 0 4px; font-size: 1.5rem; font-weight: 600; }
.room-join-sub { margin: 0 0 var(--rlx-space-5); color: var(--rlx-foreground-muted); font-size: 0.9rem; }
.room-join-form { display: flex; flex-direction: column; gap: var(--rlx-space-4); }

/* Echo-cancel toggle row — used in join form + in-room Settings modal. */
.room-echo-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--rlx-space-3);
  padding: 10px var(--rlx-space-4);
  background: var(--rlx-content2);
  border: var(--rlx-border-width-sm, 1px) solid var(--rlx-separator-secondary);
  border-radius: var(--rlx-radius-xl);
  box-shadow: var(--rlx-shadow-sm);
  user-select: none;
}
.room-echo-text {
  display: flex;
  align-items: baseline;
  gap: var(--rlx-space-3);
  min-width: 0;
  flex: 1;
}
.room-echo-title {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--rlx-foreground);
  white-space: nowrap;
  flex-shrink: 0;
}
.room-echo-desc {
  font-size: 0.75rem;
  color: var(--rlx-foreground-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.room-foot {
  text-align: center;
  font-size: 0.75rem;
  color: var(--rlx-foreground-muted);
  padding-top: var(--rlx-space-2);
}
.room-foot-link {
  color: var(--rlx-primary);
  text-decoration: none;
}
.room-foot-link:hover { text-decoration: underline; }

/* Narrow screens. */
@media (max-width: 560px) {
  /* Tighter shell so the whole room (incl. the Leave button) fits one screen. */
  .room-live { padding: var(--rlx-space-3); gap: var(--rlx-space-3); }

  .room-head { gap: var(--rlx-space-2); }
  /* Room name sits on its own row, right-aligned. */
  .room-head-meta { margin-left: 0; order: 3; width: 100%; justify-content: flex-end; }
  .room-meta-item { justify-content: flex-end; }
  .room-meta-v { max-width: 60vw; }   /* trim long room ids on a phone */
  .room-head-status { flex-wrap: wrap; }
  /* Stage-head inline badge: show on mobile; header stream + REC pills are redundant
     there (the stage-head badge mirrors them), so hide both to de-crowd the top. */
  .room-stage-status { display: flex; align-items: center; }
  .room-stream-pill,
  .room-head-status .room-rec-pill { display: none; }

  .room-grid {
    grid-template-columns: repeat(auto-fit, 96px);
    column-gap: var(--rlx-space-2);
    row-gap: var(--rlx-space-2);
  }
  .room-stage { padding: var(--rlx-space-2); gap: var(--rlx-space-2); }

  /* Compact participant cards — space is tight on a phone (96×132 footprint). */
  .room-tile { width: 96px; min-height: 116px; padding: 8px var(--rlx-space-2) 14px; gap: 9px; }
  .room-tile-ring { width: 64px; height: 64px; }
  .room-tile-avatar { --rlx-avatar-size: 64px; }
  .room-tile-mic { width: 22px; height: 22px; right: 0; bottom: 0; }
  .room-tile-name-text { font-size: 13px; }
  .room-tile-role { font-size: 9px; padding: 1px 7px; }

  /* ── Two-tier floating controls (mobile) ──────────────────────────────
     Top tier: one floating, glassy reaction capsule (the row IS the pill,
     tiles sit flush inside). Bottom tier: a rounded action bar with a
     low-weight left cluster (Record text-link + dot, Settings) and the
     high-weight Leave pill anchored far-right. */
  .room-reactions { display: flex; justify-content: center; }
  .room-reactions .rlx-reactionbar-row {
    flex-wrap: nowrap;
    gap: 0;
    width: max-content;
    max-width: 100%;
    padding: 4px;
    border-radius: 9999px;
    background: color-mix(in srgb, var(--rlx-content1) 80%, transparent);
    -webkit-backdrop-filter: blur(10px);
    backdrop-filter: blur(10px);
    border: var(--rlx-border-width-sm) solid var(--rlx-separator-secondary);
    box-shadow: var(--rlx-shadow-lg);
  }
  .room-reactions .rlx-reaction {
    min-height: 40px;
    padding: 6px 10px;
    gap: 5px;                       /* tight emoji ↔ count */
    background: transparent;
    border: 0;
    border-radius: 9999px;
  }
  :root[data-skin='spark'] .room-reactions .rlx-reaction { background: transparent; }
  .room-reactions .rlx-reaction:hover,
  .room-reactions .rlx-reaction[data-active='true'] { background: var(--rlx-content2); }

  /* Action bar: single row, left cluster + far-right Leave. */
  .room-dock {
    flex-wrap: nowrap;
    justify-content: flex-start;
    gap: var(--rlx-space-2);
    padding: 8px 12px;
    border-radius: 26px;
  }
  .room-dock-spacer { display: block; flex: 1; order: 98; }
  .room-dock-btn { min-height: 44px; }
  /* Test + Settings go icon-only on a phone so the bar stays to one row. */
  .room-dock-test .rlx-btn-label,
  .room-dock-settings .rlx-btn-label { display: none; }
  .room-dock-test,
  .room-dock-settings { min-width: 0; padding-left: 10px; padding-right: 10px; }

  /* Record — minimal text link with a solid red dot; no filled container.
     min-width:0 + label ellipsis keeps the bar to one row even alongside Mute. */
  .room-dock-btn--record,
  .room-dock-btn--record:hover:not([disabled]) {
    background: transparent;
    color: var(--rlx-foreground);
    border-color: transparent;
    box-shadow: none;
    padding-left: 6px;
  }
  .room-dock-btn--record .rlx-icon { display: none; }
  .room-dock-btn--record::before {
    content: '';
    flex: none;
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--rlx-danger);
  }

  /* Mute — low-weight, icon-only (transparent) to match the left utility cluster.
     Needs (0,2,0) to beat the kit's .rlx-btn--variant-flat.rlx-btn--color-default,
     and min-width:0 to drop the kit's 80px size-md floor that was hogging the bar. */
  .room-dock-mute .rlx-btn-label { display: none; }
  .room-dock-btn.room-dock-mute,
  .room-dock-btn.room-dock-mute:hover:not([disabled]) {
    background: transparent;
    min-width: 0;
    padding-left: 10px;
    padding-right: 10px;
  }

  /* Leave — solid crimson pill, anchored far-right. */
  .room-dock-leave { order: 99; }
  .room-dock-leave,
  .room-dock-leave:hover:not([disabled]) {
    background: var(--rlx-danger);
    color: #fff;
    font-weight: var(--rlx-fw-bold);
    border-color: transparent;
  }

  .room-head-status .rlx-btn { min-width: 40px; min-height: 40px; }
}

/* ── Functional app extras (wired version) ─────────────────────────────── */
.room-join-error {
  margin: 0;
  color: var(--rlx-danger-soft-foreground);
  background: var(--rlx-danger-soft);
  border: var(--rlx-border-width-sm) solid var(--rlx-danger);
  border-radius: var(--rlx-radius-md);
  padding: var(--rlx-space-2) var(--rlx-space-3);
  font-size: 0.85rem;
}

/* --- room banners (mic warning + recording status) ---------------------- */
.room-banner-slot:empty { display: none; }
.room-banner {
  display: flex;
  align-items: center;
  gap: var(--rlx-space-3);
  border-radius: var(--rlx-radius-lg);
  border: var(--rlx-border-width-sm) solid transparent;
  padding: var(--rlx-space-3) var(--rlx-space-4);
  font-size: 0.9rem;
  font-weight: 500;
}
.room-banner-dot {
  flex: 0 0 auto;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: currentColor;
}
.room-banner-text { flex: 1 1 auto; }
.room-banner-btn { flex: 0 0 auto; }

/* recording live — steady red, pulsing dot */
.room-banner--rec {
  color: var(--rlx-danger-soft-foreground);
  background: var(--rlx-danger-soft);
  border-color: var(--rlx-danger);
}
.room-banner--rec .room-banner-dot { animation: room-rec-pulse 1.6s ease-in-out infinite; }
@keyframes room-rec-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }

/* not being heard — the loud, actionable warning */
.room-banner--warn {
  color: var(--rlx-danger-foreground, #fff);
  background: var(--rlx-danger);
  border-color: var(--rlx-danger);
}

/* host call-to-action to start recording */
.room-banner--ready {
  color: var(--rlx-warning-soft-foreground);
  background: var(--rlx-warning-soft);
  border-color: var(--rlx-warning);
}

/* green room (non-host, idle) — neutral, low-key */
.room-banner--muted {
  color: var(--rlx-foreground-muted);
  background: var(--rlx-background-secondary);
  border-color: var(--rlx-divider);
}
.room-banner--muted .room-banner-dot { background: var(--rlx-foreground-muted); }

/* recording saved */
.room-banner--ok {
  color: var(--rlx-success-soft-foreground);
  background: var(--rlx-success-soft);
  border-color: var(--rlx-success);
}

@media (prefers-reduced-motion: reduce) {
  .room-banner--rec .room-banner-dot { animation: none; }
}

/* --- pre-join readiness self-test --------------------------------------- */
.room-readiness { display: flex; flex-direction: column; gap: var(--rlx-space-2); }
/* Join-screen tools row: "Test my setup" + "Audio settings" side by side. */
.room-join-tools { display: flex; gap: var(--rlx-space-3); }
.room-join-tools > * { flex: 1 1 0; min-width: 0; }
@media (max-width: 420px) { .room-join-tools { flex-direction: column; } }
.room-readiness-results {
  display: flex;
  flex-direction: column;
  gap: var(--rlx-space-2);
  padding: var(--rlx-space-3);
  border: var(--rlx-border-width-sm) solid var(--rlx-divider);
  border-radius: var(--rlx-radius-lg);
  background: var(--rlx-background-secondary);
}
.room-check { display: flex; align-items: flex-start; gap: var(--rlx-space-2); }
.room-check-icon {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  margin-top: 1px;
  color: #fff;
}
.room-check--pending .room-check-icon { background: var(--rlx-foreground-muted); }
.room-check--ok .room-check-icon { background: var(--rlx-success); }
.room-check--fail .room-check-icon { background: var(--rlx-danger); }
.room-check--pending .room-check-icon svg { animation: room-spin 1s linear infinite; }
@keyframes room-spin { to { transform: rotate(360deg); } }
.room-check-body { display: flex; flex-direction: column; line-height: 1.25; }
.room-check-label { font-weight: 600; font-size: 0.88rem; }
.room-check-detail { font-size: 0.8rem; color: var(--rlx-foreground-muted); }
.room-check--fail .room-check-detail { color: var(--rlx-danger-soft-foreground); }

.room-meter {
  height: 8px;
  border-radius: 999px;
  background: var(--rlx-content2, var(--rlx-divider));
  overflow: hidden;
  margin: 2px 0 2px 28px;
}
.room-meter-fill {
  height: 100%;
  width: 0%;
  border-radius: 999px;
  background: var(--rlx-success);
  transition: width 60ms linear;
}
.room-meter-fill--hot { background: var(--rlx-warning); }
@media (prefers-reduced-motion: reduce) {
  .room-check--pending .room-check-icon svg { animation: none; }
}
.room-audio-slot:empty { display: none; }
.room-audio-unlock { width: 100%; }

/* Device pickers (mic / speaker) — Surface dropdown, full width in the form. */
.room-device-dd { width: 100%; }
.room-device-dd .rlx-dropdown-trigger { width: 100%; }

/* In-room Audio-settings modal: the Surface modal body is a scroll-clip and the
   inline dropdown opens downward, so the lower Speaker list was clipped at /
   colliding with the Done footer. Scoped to the Speaker field (`.room-dd-up`) so
   the Mic dropdown and the shared kit are untouched: open the Speaker menu UPWARD
   (clear of Done) and cap it with an internal scroll so it stays inside the modal
   body — a long output-device list scrolls instead of overflowing onto Done. */
.room-dd-up .rlx-dropdown-menu {
  top: auto;
  bottom: calc(100% + 6px);
  max-height: 112px;
  overflow-y: auto;
}

/* ==============================================================================
   STUDIO SKIN — dark broadcast look (appended; overrides the base by source order).
   Room-scoped design tokens: dark studio by default, a coherent light studio under
   :root[data-skin='spark-light']. Every rule is `.room-app`-scoped so it wins over the base.
   ============================================================================== */
.room-app {
  --st-bg: #0a0b0e;
  --st-panel: #131519;      /* stage */
  --st-panel-2: #1a1d24;    /* tiles / dock */
  --st-panel-3: #23272f;    /* raised chips */
  --st-border: rgba(255, 255, 255, 0.07);
  --st-border-strong: rgba(255, 255, 255, 0.13);
  --st-text: #eef0f4;
  --st-muted: #9a9da6;
  --st-accent: #ff2d55;
  --st-accent-2: #ff5a5f;
  --st-accent-ink: #fff;
  --st-accent-glow: rgba(255, 45, 85, 0.55);
  --st-speak: #2dd4bf;
  --st-speak-glow: rgba(45, 212, 191, 0.55);
  --st-shadow: 0 10px 34px rgba(0, 0, 0, 0.5);

  background:
    radial-gradient(1100px 560px at 50% -12%, rgba(255, 45, 85, 0.14), transparent 62%),
    radial-gradient(900px 500px at 90% 8%, rgba(45, 212, 191, 0.07), transparent 60%),
    var(--st-bg);
  color: var(--st-text);
  -webkit-font-smoothing: antialiased;
}
:root[data-skin='spark-light'] .room-app {
  --st-bg: #eceef2;
  --st-panel: #ffffff;
  --st-panel-2: #ffffff;
  --st-panel-3: #f4f5f8;
  --st-border: rgba(20, 22, 30, 0.09);
  --st-border-strong: rgba(20, 22, 30, 0.16);
  --st-text: #14161b;
  --st-muted: #6a6d78;
  --st-accent: #e11d48;
  --st-accent-2: #f43f5e;
  --st-accent-glow: rgba(225, 29, 72, 0.30);
  --st-speak: #0d9488;
  --st-speak-glow: rgba(13, 148, 136, 0.30);
  --st-shadow: 0 12px 30px rgba(20, 22, 40, 0.12);
  background:
    radial-gradient(1100px 560px at 50% -12%, rgba(225, 29, 72, 0.08), transparent 62%),
    var(--st-bg);
}

/* ── Header ── */
.room-app .room-brand { color: var(--st-text); letter-spacing: -0.01em; }
.room-app .room-brand svg,
.room-app .room-brand b { color: var(--st-accent); }
.room-app .room-meta-k { color: var(--st-muted); }
.room-app .room-meta-v { color: var(--st-text); }
.room-app .room-rec-pill { box-shadow: 0 0 18px var(--st-accent-glow); }

/* ── Stage ── */
.room-app .room-stage {
  background:
    radial-gradient(560px 320px at 50% 42%, color-mix(in srgb, var(--st-accent) 8%, transparent), transparent 70%),
    var(--st-panel);
  border: 1px solid var(--st-border);
  border-radius: 22px;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.04), var(--st-shadow);
}
.room-app .room-stage-title { color: var(--st-muted); letter-spacing: 0.12em; }
.room-app .room-stage-count { color: var(--st-muted); }

/* ── Participant tile ── */
.room-app .room-tile {
  background: linear-gradient(180deg, color-mix(in srgb, var(--st-panel-2) 100%, transparent), color-mix(in srgb, var(--st-panel-2) 88%, #000));
  border: 1px solid var(--st-border);
  border-radius: 18px;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.28);
}
.room-app .room-tile--listener { background: var(--st-panel); opacity: 0.72; }
.room-app .room-tile--speaking {
  border-color: color-mix(in srgb, var(--st-speak) 55%, transparent);
  box-shadow: 0 0 0 1px var(--st-speak), 0 10px 30px rgba(0, 0, 0, 0.35);
  transform: translateY(-3px);
}
.room-app .room-tile-name-text { color: var(--st-text); }
.room-app .room-tile-avatar .rlx-avatar-initials { color: var(--st-muted); }

/* Avatar rings: host = accent halo, speaking = teal halo + ping. */
.room-app .room-tile-avatar {
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08);
  transition: box-shadow 0.2s ease;
}
.room-app .room-tile--host .room-tile-avatar {
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08), 0 0 0 2px var(--st-accent), 0 0 20px var(--st-accent-glow);
}
.room-app .room-tile--speaking .room-tile-avatar {
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08), 0 0 0 3px var(--st-speak), 0 0 26px var(--st-speak-glow);
}
.room-app .room-tile--speaking .room-tile-halo { animation: st-ping 1.5s cubic-bezier(0, 0, 0.2, 1) infinite; }
@keyframes st-ping {
  from { box-shadow: 0 0 0 0 var(--st-speak-glow); }
  to   { box-shadow: 0 0 0 16px rgba(45, 212, 191, 0); }
}
.room-app .room-tile-mic { box-shadow: 0 0 0 2px var(--st-panel-2); }
.room-app .room-tile--muted .room-tile-mic { background: var(--st-accent); }
.room-app .room-tile-role {
  background: color-mix(in srgb, var(--st-accent) 20%, transparent);
  color: var(--st-accent-2);
  border: 1px solid color-mix(in srgb, var(--st-accent) 40%, transparent);
}

/* Live equalizer — a self-contained pill seated on the avatar's lower edge (centered),
   shown only while speaking. Contained so its bars never collide with the ring or name. */
.room-app .room-tile-eq {
  position: absolute;
  left: 50%;
  bottom: 4px;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 2.5px;
  height: 16px;
  padding: 0 7px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--st-panel) 92%, transparent);
  box-shadow: 0 0 0 1.5px var(--st-panel-2), 0 2px 7px rgba(0, 0, 0, 0.3);
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
  opacity: 0;
  transform: translateX(-50%) scale(0.9);
  transition: opacity 0.18s ease, transform 0.18s ease;
  pointer-events: none;
  z-index: 2;
}
.room-app .room-tile--speaking .room-tile-eq {
  opacity: 1;
  transform: translateX(-50%) scale(1);
}
.room-app .room-tile-eq-bar {
  width: 3px;
  height: 5px;
  border-radius: 2px;
  background: var(--st-speak);
  box-shadow: 0 0 6px var(--st-speak-glow);
}
.room-app .room-tile--speaking .room-tile-eq-bar { animation: st-eq 0.7s ease-in-out infinite; }
.room-app .room-tile-eq-bar:nth-child(1) { animation-delay: -0.1s; }
.room-app .room-tile-eq-bar:nth-child(2) { animation-delay: -0.35s; }
.room-app .room-tile-eq-bar:nth-child(3) { animation-delay: -0.05s; }
.room-app .room-tile-eq-bar:nth-child(4) { animation-delay: -0.25s; }
@keyframes st-eq {
  0%, 100% { height: 4px; }
  50% { height: 11px; }
}

/* ── Dock (floating glass) ── */
.room-app .room-dock {
  background: color-mix(in srgb, var(--st-panel-2) 82%, transparent);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  border: 1px solid var(--st-border-strong);
  border-radius: 999px;
  box-shadow: var(--st-shadow);
}
.room-app .room-dock-btn--record {
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--st-accent) 60%, transparent), 0 0 20px var(--st-accent-glow);
}

/* ── Reactions (glass pills) ── */
.room-app .room-reactions .rlx-reaction {
  background: color-mix(in srgb, var(--st-panel-2) 70%, transparent);
  border: 1px solid var(--st-border);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
}
.room-app .room-reactions .rlx-reaction-count { color: var(--st-text); }

/* ── Banners (studio-tinted) ── */
.room-app .room-banner { border-width: 1px; }
.room-app .room-banner--rec {
  color: var(--st-accent-2);
  background: color-mix(in srgb, var(--st-accent) 14%, transparent);
  border-color: color-mix(in srgb, var(--st-accent) 45%, transparent);
}
.room-app .room-banner--warn {
  color: #fff;
  background: var(--st-accent);
  border-color: var(--st-accent);
}
.room-app .room-banner--ready {
  color: var(--st-text);
  background: color-mix(in srgb, #f59e0b 16%, transparent);
  border-color: color-mix(in srgb, #f59e0b 45%, transparent);
}
.room-app .room-banner--muted {
  color: var(--st-muted);
  background: color-mix(in srgb, var(--st-panel-3) 70%, transparent);
  border-color: var(--st-border);
}
.room-app .room-banner--ok {
  color: var(--st-speak);
  background: color-mix(in srgb, var(--st-speak) 14%, transparent);
  border-color: color-mix(in srgb, var(--st-speak) 45%, transparent);
}

/* ── Join view ── */
.room-app .room-join-card {
  background: color-mix(in srgb, var(--st-panel-2) 92%, transparent);
  border: 1px solid var(--st-border-strong);
  border-radius: 22px;
  box-shadow: var(--st-shadow);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}
:root[data-skin='spark'] .room-app .room-join-card { background: var(--st-panel-2); }
.room-app .room-join-title { color: var(--st-text); letter-spacing: -0.01em; }
.room-app .room-join-sub { color: var(--st-muted); }
.room-app .room-echo-row,
.room-app .room-readiness-results {
  background: var(--st-panel-3);
  border-color: var(--st-border);
}
.room-app .room-echo-title,
.room-app .room-check-label { color: var(--st-text); }
.room-app .room-echo-desc,
.room-app .room-check-detail { color: var(--st-muted); }
.room-app .room-meter { background: var(--st-panel); }

/* ── Footer ── */
.room-app .room-foot { color: var(--st-muted); }
.room-app .room-foot-link { color: var(--st-accent-2); }

/* ── Mobile: the record button is a minimal text-link + red dot (no container),
   so drop the studio glow-ring that would otherwise draw a border the dot collides
   with. Keep the record dot in the accent colour. ── */
@media (max-width: 560px) {
  .room-app .room-dock-btn--record,
  .room-app .room-dock-btn--record:hover:not([disabled]) {
    box-shadow: none;
    background: transparent;
    border-color: transparent;
  }
  .room-app .room-dock-btn--record::before { background: var(--st-accent); }
}

/* ==============================================================================
   PROFESSIONAL POLISH — refines the Studio skin toward a business tool (appended,
   overrides by source order). Softer glows, a professional blue accent for identity,
   higher-contrast labels, balanced controls. Red is reserved for recording/destructive.
   ============================================================================== */
.room-app {
  --st-pro: #5b8cff;                    /* professional accent (identity, not red) */
  --st-pro-soft: rgba(91, 140, 255, 0.16);
  --st-accent: #ef4444;                 /* cleaner red than the neon #ff2d55 */
  --st-accent-2: #f87171;
  --st-accent-glow: rgba(239, 68, 68, 0.35);
  /* Ambient glow: subtle + neutral (the red neon read as gaming). */
  background:
    radial-gradient(1050px 540px at 50% -14%, rgba(255, 255, 255, 0.045), transparent 60%),
    var(--st-bg);
}
:root[data-skin='spark-light'] .room-app {
  --st-pro: #2563eb;
  --st-pro-soft: rgba(37, 99, 235, 0.12);
  --st-accent: #dc2626;
  --st-accent-2: #ef4444;
  --st-accent-glow: rgba(220, 38, 38, 0.22);
  background:
    radial-gradient(1050px 540px at 50% -14%, rgba(37, 99, 235, 0.05), transparent 60%),
    var(--st-bg);
}

/* Brand mark → professional blue (was red). */
.room-app .room-brand svg,
.room-app .room-brand b { color: var(--st-pro); }

/* Header: room code truncated in CSS-friendly width + a copy button. */
.room-app .room-meta-item { gap: 6px; }
.room-app .room-meta-v { max-width: none; font-weight: 600; }
.room-app .room-copy-btn {
  min-width: 26px; width: 26px; height: 26px; min-height: 26px; padding: 0;
  opacity: 0.55; color: var(--st-muted);
}
.room-app .room-copy-btn:hover { opacity: 1; color: var(--st-text); }
.room-app .room-rec-pill { box-shadow: none; }  /* drop the neon glow */

/* Higher-contrast stage labels (opacity keeps it theme-aware). */
.room-app .room-stage-title { color: var(--st-text); opacity: 0.8; letter-spacing: 0.1em; }
.room-app .room-stage-count { color: var(--st-text); opacity: 0.6; }
.room-app .room-stage {
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.03), 0 8px 26px rgba(0, 0, 0, 0.35);
  background: var(--st-panel);
}

/* Avatars: professional, not neon. Host = clean blue ring; speaking = teal (softer glow). */
.room-app .room-tile--host .room-tile-avatar {
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08), 0 0 0 2px var(--st-pro);
}
.room-app .room-tile--speaking .room-tile-avatar {
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08), 0 0 0 2px var(--st-speak), 0 0 12px var(--st-speak-glow);
}
@keyframes st-ping {
  from { box-shadow: 0 0 0 0 rgba(45, 212, 191, 0.28); }
  to   { box-shadow: 0 0 0 12px rgba(45, 212, 191, 0); }
}

/* Mic-status badge: clean, centered in its own corner badge, cut out from the tile. */
.room-app .room-tile-mic {
  right: 3px; bottom: 3px; width: 22px; height: 22px;
  box-shadow: 0 0 0 3px var(--st-panel-2);
}
.room-app .room-tile--muted .room-tile-mic { background: var(--st-accent); }

/* HOST tag: lighter, smaller, better letter-spacing, blue-tinted (was heavy red 800). */
.room-app .room-tile-role {
  font-weight: 600;
  font-size: 9px;
  letter-spacing: 0.09em;
  padding: 2px 8px;
  background: var(--st-pro-soft);
  color: var(--st-pro);
  border: 1px solid color-mix(in srgb, var(--st-pro) 32%, transparent);
}

/* Dock: even spacing + uniform controls. */
.room-app .room-dock {
  gap: var(--rlx-space-2);
  padding: 10px var(--rlx-space-3);
  box-shadow: 0 8px 26px rgba(0, 0, 0, 0.4);
}
.room-app .room-dock-btn { min-height: 40px; }

/* Record toggle = a compact icon: red circle (start) / neutral square (stop). Shape is
   drawn in CSS so it never depends on a kit glyph, and "stop" never looks like "start". */
.room-app .room-dock-record {
  width: 40px; min-width: 40px; height: 40px; padding: 0; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center; box-shadow: none;
}
/* idle/live: hide the kit glyph, draw the record dot / stop square in CSS. */
.room-app .room-dock-record:not(.room-dock-record--busy) .rlx-icon,
.room-app .room-dock-record:not(.room-dock-record--busy) svg { display: none; }
/* idle only (not busy, not live) → a red record dot. */
.room-app .room-dock-record:not(.room-dock-record--busy):not(.room-dock-record--live)::before {
  content: ''; width: 13px; height: 13px; border-radius: 50%; background: #fff;
}
/* live → a neutral stop square (rounded button). */
.room-app .room-dock-record--live { border-radius: var(--rlx-radius-md); }
.room-app .room-dock-record--live::before {
  content: ''; width: 12px; height: 12px; border-radius: 2px; background: currentColor;
}
/* starting/stopping: show the real loader glyph, spinning — never a blank button. */
.room-app .room-dock-record--busy svg { animation: room-spin 0.9s linear infinite; }

/* Mute/unmute: the injected mic glyph needs a little space from its label. */
.room-app .room-dock-mute svg { margin-right: 6px; }

/* Leave = secondary dark-red (was bright solid red that stole focus). */
.room-app .room-dock-leave,
.room-app .room-dock-leave:hover:not([disabled]) {
  background: color-mix(in srgb, var(--st-accent) 14%, transparent);
  color: var(--st-accent-2);
  border: 1px solid color-mix(in srgb, var(--st-accent) 32%, transparent);
  box-shadow: none;
  font-weight: 600;
}

/* React: one button + an emoji popover; a picked emoji floats over the stage. */
.room-react { position: relative; display: flex; justify-content: center; }
.room-react-pop {
  position: absolute; bottom: calc(100% + 8px); left: 50%; transform: translateX(-50%);
  display: flex; gap: 4px; padding: 6px;
  background: var(--st-panel-2); border: 1px solid var(--st-border-strong);
  border-radius: 999px; box-shadow: 0 12px 30px rgba(0, 0, 0, 0.45); z-index: 30;
}
.room-react-emoji {
  border: 0; background: transparent; cursor: pointer; font-size: 19px; line-height: 1;
  width: 36px; height: 36px; border-radius: 50%; transition: transform 0.12s ease, background 0.12s ease;
}
.room-react-emoji:hover { background: var(--st-panel-3); transform: scale(1.18); }
.room-react-float {
  position: absolute; bottom: 100%; left: 50%; font-size: 24px; pointer-events: none;
  animation: st-react-float 1.1s ease-out forwards;
}
@keyframes st-react-float {
  0%   { opacity: 0; transform: translate(-50%, 0) scale(0.6); }
  20%  { opacity: 1; transform: translate(-50%, -12px) scale(1.1); }
  100% { opacity: 0; transform: translate(-50%, -90px) scale(1); }
}

/* Dock utility + React buttons: readable in BOTH themes (the kit 'light'/'flat'
   variants wash out on a light background). */
.room-app .room-dock-test,
.room-app .room-dock-settings { color: var(--st-text); }
.room-app .room-react-btn {
  color: var(--st-text);
  background: var(--st-panel-2);
  border: 1px solid var(--st-border-strong);
}

@media (max-width: 560px) { .room-app .room-dock-mute svg { margin-right: 0; } }

/* ==============================================================================
   REVIEW-3 POLISH — resolve dual recording controls, balance the dock, contrast,
   empty-state. Appended last (wins by source order).
   ============================================================================== */

/* 1 · Dock = 3 zones: mic (left) · record (dead-center) · settings+leave (right). */
.room-app .room-dock {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: var(--rlx-space-2);
}
.room-app .room-dock-zone { display: flex; align-items: center; gap: var(--rlx-space-2); min-width: 0; }
.room-app .room-dock-left { justify-self: start; }
.room-app .room-dock-center { justify-self: center; }
.room-app .room-dock-right { justify-self: end; }

/* 2 · Microphone = the prominent primary control on the left (blue pill when live). */
.room-app .room-dock-mute {
  min-height: 46px; padding: 0 20px; border-radius: 999px; font-weight: 600;
}
.room-app .room-dock-mute:not(.room-dock-mute--off) {
  background: var(--st-pro-soft);
  color: var(--st-pro);
  border: 1px solid color-mix(in srgb, var(--st-pro) 35%, transparent);
}
.room-app .room-dock-mute:not(.room-dock-mute--off) svg { color: var(--st-pro); }

/* 3 · Record = dead-center. idle = HOLLOW GRAY circle (does NOT look active, so it never
   competes with the banner CTA); live = a red stop; busy = a spinner. */
.room-app .room-dock-record {
  width: 52px; min-width: 52px; height: 52px; padding: 0; border-radius: 50%;
  display: inline-flex; align-items: center; justify-content: center;
  background: transparent;
  border: 2px solid var(--st-border-strong);
  box-shadow: none;
  transition: border-color 0.15s ease, background 0.15s ease;
}
.room-app .room-dock-record:not(.room-dock-record--busy) .rlx-icon,
.room-app .room-dock-record:not(.room-dock-record--busy) svg { display: none; }
/* idle → a gray record dot inside the hollow ring. */
.room-app .room-dock-record:not(.room-dock-record--busy):not(.room-dock-record--live)::before {
  content: ''; width: 16px; height: 16px; border-radius: 50%; background: var(--st-muted);
  transition: background 0.15s ease;
}
.room-app .room-dock-record:not(.room-dock-record--live):hover:not([disabled]) {
  border-color: color-mix(in srgb, var(--st-accent) 55%, transparent);
}
.room-app .room-dock-record:not(.room-dock-record--busy):not(.room-dock-record--live):hover:not([disabled])::before {
  background: var(--st-accent);
}
/* live → a solid red button with a white stop square. */
.room-app .room-dock-record--live {
  background: var(--st-accent);
  border-color: var(--st-accent);
  border-radius: var(--rlx-radius-lg);
}
.room-app .room-dock-record--live::before {
  content: ''; width: 16px; height: 16px; border-radius: 3px; background: #fff;
}
/* busy → show + spin the loader glyph. */
.room-app .room-dock-record--busy svg { display: inline-flex; animation: room-spin 0.9s linear infinite; color: var(--st-muted); }

/* 4 · Banner ✕ dismiss. */
.room-app .room-banner-close {
  margin-left: 4px; min-width: 26px; width: 26px; height: 26px; padding: 0;
  font-size: 14px; line-height: 1; opacity: 0.7;
}
.room-app .room-banner-close:hover { opacity: 1; }

/* 5 · Metadata contrast — readable gray on both themes. */
.room-app .room-stage-title,
.room-app .room-stage-count { color: #9ca3af; opacity: 1; }
:root[data-skin='spark-light'] .room-app .room-stage-title,
:root[data-skin='spark-light'] .room-app .room-stage-count { color: #5b616e; }

/* 6 · HOST tag — solid blue capsule + white text (was near-invisible blue-on-dark). */
.room-app .room-tile-role {
  background: var(--st-pro);
  color: #fff;
  border: none;
  font-weight: 700;
}

/* 7 · Empty-state — center the roster + a "waiting" hint with an animated wave. */
.room-app .room-stage-content {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 22px;
}
.room-app .room-grid { flex: 0 0 auto; }
.room-waiting {
  display: flex; flex-direction: column; align-items: center; gap: 12px;
  color: #9ca3af;
}
.room-waiting[hidden] { display: none; }
:root[data-skin='spark-light'] .room-waiting { color: #6b7280; }
.room-waiting-wave { display: flex; align-items: flex-end; gap: 4px; height: 26px; }
.room-waiting-bar {
  width: 4px; height: 35%; border-radius: 2px;
  background: color-mix(in srgb, var(--st-pro) 60%, transparent);
  animation: room-wave 1.15s ease-in-out infinite;
}
.room-waiting-bar:nth-child(1) { animation-delay: -0.5s; }
.room-waiting-bar:nth-child(2) { animation-delay: -0.3s; }
.room-waiting-bar:nth-child(3) { animation-delay: -0.7s; }
.room-waiting-bar:nth-child(4) { animation-delay: -0.2s; }
.room-waiting-bar:nth-child(5) { animation-delay: -0.4s; }
@keyframes room-wave { 0%, 100% { height: 22%; } 50% { height: 100%; } }
.room-waiting[data-tone='recording'] { color: var(--rlx-foreground-muted, #9ca3af); }
.room-waiting[data-tone='recording'] .room-waiting-bar { background: var(--rlx-danger, #ef4444); }
.room-waiting--still .room-waiting-bar { animation: none; height: 35%; }
.room-waiting-text { margin: 0; font-size: 0.9rem; letter-spacing: 0.01em; }
@media (prefers-reduced-motion: reduce) { .room-waiting-bar { animation: none; } }

/* ==============================================================================
   REVIEW-4 POLISH — visible "Starting…" spinner, tidy toolbar, minimal reaction bar.
   ============================================================================== */

/* 1 · CRITICAL — the record button's starting/stopping spinner was near-black on a dark
   bar (invisible). Make it AMBER + clearly spinning, matching the "• Starting…" badge. */
.room-app .room-dock-record--busy {
  border-color: color-mix(in srgb, #f59e0b 60%, transparent);
  background: color-mix(in srgb, #f59e0b 12%, transparent);
}
.room-app .room-dock-record--busy svg {
  display: inline-flex;
  width: 24px; height: 24px;
  color: #f59e0b;
  animation: room-spin 0.8s linear infinite;
}

/* 2 · Toolbar tidy — the mic is a clean neutral control (not a loud blue circle);
   the right group (settings + leave) sits together with even spacing. */
.room-app .room-dock-mute:not(.room-dock-mute--off) {
  background: var(--st-panel-3);
  color: var(--st-text);
  border: 1px solid var(--st-border-strong);
}
.room-app .room-dock-mute:not(.room-dock-mute--off) svg { color: var(--st-text); }
.room-app .room-dock-left,
.room-app .room-dock-right { gap: var(--rlx-space-2); }

/* 3 · Reaction bar — ONE flat translucent bar (not five outlined bubbles); a pill only
   gets a solid highlight when it's active (count > 0 / selected). */
.room-app .room-reactions .rlx-reactionbar-row {
  display: inline-flex;
  flex-wrap: nowrap;
  width: max-content;
  max-width: 100%;
  gap: 2px;
  padding: 4px 6px;
  background: color-mix(in srgb, var(--st-panel-2) 55%, transparent);
  border: 1px solid var(--st-border);
  border-radius: 999px;
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  box-shadow: none;
}
.room-app .room-reactions .rlx-reaction,
:root[data-skin='spark'] .room-app .room-reactions .rlx-reaction {
  background: transparent;
  border: none;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}
.room-app .room-reactions .rlx-reaction:hover {
  background: color-mix(in srgb, var(--st-text) 8%, transparent);
}
.room-app .room-reactions .rlx-reaction[data-active='true'] {
  background: var(--st-pro-soft);
  color: var(--st-pro);
}

/* ==============================================================================
   REVIEW-5 — narrow the dock (no empty canyon) + a clearly-visible idle placeholder.
   ============================================================================== */
/* Cluster the controls centrally instead of stretching edge-to-edge on wide screens. */
.room-app .room-dock {
  max-width: 640px;
  margin-left: auto;
  margin-right: auto;
}
/* Idle record = a clearly-visible STATIC gray placeholder (amber shows only while
   starting/stopping; live is the red square). */
.room-app .room-dock-record:not(.room-dock-record--busy):not(.room-dock-record--live) {
  border-color: color-mix(in srgb, var(--st-muted) 70%, transparent);
}

/* ==============================================================================
   REVIEW-6 — mobile micro-polish: symmetric toolbar spacing + compact reaction bar.
   ============================================================================== */
@media (max-width: 560px) {
  /* All four controls (mic · record · settings · leave) evenly, symmetrically spaced.
     display:contents flattens the 3 zone wrappers so the buttons are direct flex items. */
  .room-app .room-dock {
    display: flex;
    justify-content: space-between;
    align-items: center;
    max-width: none;
    gap: 8px;
    padding: 10px 16px; /* consistent edge padding so mic/leave don't hug the edges */
  }
  .room-app .room-dock-zone { display: contents; }

  /* Compact reaction bar to match the refined bottom controls. */
  .room-app .room-reactions .rlx-reactionbar-row { padding: 3px 5px; }
  .room-app .room-reactions .rlx-reaction { padding: 5px 8px; gap: 3px; min-height: 34px; }
  .room-app .room-reactions .rlx-reaction-glyph { font-size: 14px; }
  .room-app .room-reactions .rlx-reaction-count { font-size: 0.72rem; }
}

/* ==============================================================================
   REVIEW-8 — desktop toolbar proportions, equal button weights, bigger reactions.
   ============================================================================== */
@media (min-width: 561px) {
  /* A tighter, deliberate pill: hug the controls with even gaps + center on screen
     (was a wide bar with controls spread to the edges → disconnected). */
  .room-app .room-dock {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 16px;
    width: max-content;
    max-width: 672px;
    margin-left: auto;
    margin-right: auto;
    padding: 10px 20px;
  }
  .room-app .room-dock-zone { display: contents; }

  /* Bigger, more prominent reaction bar on the wide desktop canvas. */
  .room-app .room-reactions .rlx-reactionbar-row { padding: 6px 8px; gap: 4px; }
  .room-app .room-reactions .rlx-reaction { padding: 8px 15px; }
  .room-app .room-reactions .rlx-reaction-glyph { font-size: 18px; }
  .room-app .room-reactions .rlx-reaction-count { font-size: 0.9rem; }
}

/* Equal button weights — Mute + Settings share the SAME subtle capsule (bg-white/5);
   Leave keeps its distinct translucent-red style. */
.room-app .room-dock-mute:not(.room-dock-mute--off),
.room-app .room-dock-settings {
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid var(--st-border);
  color: var(--st-text);
}
.room-app .room-dock-mute:not(.room-dock-mute--off) svg,
.room-app .room-dock-settings svg { color: var(--st-text); }
:root[data-skin='spark-light'] .room-app .room-dock-mute:not(.room-dock-mute--off),
:root[data-skin='spark-light'] .room-app .room-dock-settings {
  background: rgba(20, 22, 30, 0.05);
}

/* ==============================================================================
   REVIEW-9 — active-state transition polish + responsive participant grid.
   ============================================================================== */

/* 1 · Active state — pulsing REC badge, smooth record-icon morph, banner fade-in. */
.room-app .room-rec-pill { animation: rec-pulse 1.9s ease-in-out infinite; }
@keyframes rec-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0.5); }
  70%  { box-shadow: 0 0 0 6px rgba(239, 68, 68, 0); }
  100% { box-shadow: 0 0 0 0 rgba(239, 68, 68, 0); }
}
/* gray dot ⇆ red stop-square morphs smoothly (border-radius/size/colour). */
.room-app .room-dock-record,
.room-app .room-dock-record::before { transition: all 0.22s ease; }
/* banner fades in on state change (fade-out is inherent as the slot empties). */
.room-banner { animation: banner-in 0.24s ease; }
@keyframes banner-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }

/* 2 · Responsive participant grid — balanced columns by count (--cols set in onRoster). */
@media (min-width: 561px) {
  .room-app .room-grid { grid-template-columns: repeat(var(--cols, 1), 130px); }
}
/* Many participants → the stage content scrolls rather than pushing the dock off-screen. */
.room-app .room-stage-content { overflow-y: auto; min-height: 0; }

@media (prefers-reduced-motion: reduce) {
  .room-app .room-rec-pill { animation: none; }
  .room-banner { animation: none; }
}

/* ==============================================================================
   RECORDING-CONFIG — venue-layout option cards in the start modal (modals mount on
   document.body, so these use kit tokens, not .room-app studio tokens), plus the
   floating shared_mic "I'm speaking" claim control above the dock.
   ============================================================================== */
.room-mode-cards { display: flex; flex-direction: column; gap: var(--rlx-space-3); margin-top: var(--rlx-space-3); }
.room-mode-card {
  display: block;
  width: 100%;
  text-align: left;
  padding: 12px 14px;
  font: inherit;
  color: inherit;
  cursor: pointer;
  background: var(--rlx-content2);
  border: 1px solid var(--rlx-divider);
  border-radius: var(--rlx-radius-lg);
  transition: border-color 0.15s ease, background 0.15s ease, box-shadow 0.15s ease;
}
.room-mode-card:hover { border-color: var(--rlx-default-400); }
.room-mode-card[data-selected='true'] {
  border-color: var(--rlx-primary);
  background: rgb(var(--rlx-primary-rgb) / 0.08);
  box-shadow: 0 0 0 1px var(--rlx-primary);
}
.room-mode-card-head { display: flex; align-items: center; gap: 8px; }
.room-mode-card-icon { font-size: 15px; line-height: 1; }
.room-mode-card-title { font-weight: 600; font-size: var(--rlx-fs-small); color: var(--rlx-foreground); }
.room-mode-card-desc {
  margin: 6px 0 0;
  font-size: var(--rlx-fs-tiny);
  line-height: 1.45;
  color: var(--rlx-text-sub);
}
.room-mode-fineprint {
  margin: var(--rlx-space-3) 0 0;
  font-size: var(--rlx-fs-tiny);
  line-height: 1.45;
  color: var(--rlx-text-muted);
}

/* Self identification — "which tile is me?" was genuinely unanswerable. The local
   tile gets a subtle blue ring + a YOU chip beside the name; the header additionally
   carries "You · identity · role". */
.room-app .room-tile--self .room-tile-avatar {
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08), 0 0 0 2px color-mix(in srgb, var(--st-pro) 55%, transparent);
}
.room-app .room-tile--self.room-tile--speaking .room-tile-avatar {
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.08), 0 0 0 2px var(--st-speak), 0 0 12px var(--st-speak-glow);
}
.room-app .room-tile-you {
  font-weight: 700;
  font-size: 9px;
  letter-spacing: 0.09em;
  padding: 2px 7px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.1);
  color: var(--st-text);
  border: 1px solid var(--st-border-strong);
}
:root[data-skin='spark-light'] .room-app .room-tile-you {
  background: rgba(20, 22, 30, 0.07);
}

/* Claim slot: floats the tap centered just above the dock, never blocking tiles. */
.room-app .room-claim-slot { display: flex; justify-content: center; }
.room-app .room-claim-slot:empty { display: none; }
.room-app .room-claim-btn {
  border-radius: 999px;
  min-height: 44px;
  padding: 0 22px;
  font-weight: 600;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
}

/* ==============================================================================
   REVIEW-10 — join-screen polish: unselected role-chip contrast + symmetric
   secondary anchors (Test my setup / Audio settings).
   ============================================================================== */

/* Unselected role chips: the kit's flat/default surface sits nearly on top of the
   studio card, and its label can fall below readable contrast on the dark join
   card. Give idle chips the dock's subtle capsule treatment with an explicit
   readable gray label; the selected chip keeps the kit's solid primary fill. */
.room-app .rlx-chip-group .rlx-btn--variant-flat.rlx-btn--color-default {
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid var(--st-border);
  color: #9ca3af;
}
.room-app .rlx-chip-group .rlx-btn--variant-flat.rlx-btn--color-default:hover:not([disabled]) {
  background: rgba(255, 255, 255, 0.09);
  color: var(--st-text);
}
:root[data-skin='spark-light'] .room-app .rlx-chip-group .rlx-btn--variant-flat.rlx-btn--color-default {
  background: rgba(20, 22, 30, 0.05);
  color: #5b616e;
}
:root[data-skin='spark-light'] .room-app .rlx-chip-group .rlx-btn--variant-flat.rlx-btn--color-default:hover:not([disabled]) {
  background: rgba(20, 22, 30, 0.09);
  color: var(--st-text);
}

/* Secondary anchors above the CTA: fullWidth buttons left-align their label
   (.rlx-btn--full spreads content), which reads lopsided when the two sit side
   by side. Center icon + label so they act as symmetric anchors. */
.room-app .room-readiness-trigger.rlx-btn--full { justify-content: center; }
.room-app .room-readiness-trigger.rlx-btn--full .rlx-btn-label {
  margin-right: 0;
  flex: 0 0 auto;
}

/* ─── v2 Part 4: capture source + operator desk panel ─────────────────────── */
.room-source-field { gap: var(--rlx-space-2); }
.room-source-chips { flex-wrap: wrap; }
.room-source-desc,
.room-source-note {
  margin: 0;
  font-size: 0.8rem;
  line-height: 1.35;
  color: var(--rlx-foreground-muted);
}
.room-source-field[hidden] { display: none; }
/* Echo toggle locked off for a line feed: visibly inert, still explains why. */
.room-echo-row--locked { opacity: 0.6; }
.room-echo-row--locked .rlx-switch,
.room-echo-row--locked [role='switch'] { pointer-events: none; }
/* Built-in inputs under a line feed: greyed, still selectable (the checklist turns red). */
.room-dd-option--discouraged .rlx-dropdown-option-label {
  color: var(--rlx-foreground-muted);
  text-decoration: line-through;
  text-decoration-color: color-mix(in srgb, var(--rlx-foreground-muted) 55%, transparent);
}

.room-operator {
  display: flex;
  flex-direction: column;
  gap: var(--rlx-space-3);
  background: var(--rlx-background-secondary);
  border: var(--rlx-border-width-sm) solid var(--rlx-divider);
  border-radius: var(--rlx-radius-xl);
  padding: var(--rlx-space-4) var(--rlx-space-5);
}
.room-operator-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--rlx-space-3);
}
.room-operator-title { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.room-operator-sub {
  font-size: 0.8rem;
  color: var(--rlx-foreground-muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.room-op-badge { flex: 0 0 auto; }
.room-op-badge--live .rlx-pill-dot,
.room-op-badge--armed .rlx-pill-dot { animation: room-op-pulse 1.4s ease-in-out infinite; }
@keyframes room-op-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.35; } }
.room-operator-meter { margin: 0; height: 10px; }
.room-operator-checks { display: flex; flex-direction: column; gap: var(--rlx-space-2); }
.room-operator-caption {
  margin: 0;
  font-size: 0.82rem;
  color: var(--rlx-foreground-muted);
  font-style: italic;
}
@media (max-width: 560px) {
  .room-operator { padding: var(--rlx-space-3) var(--rlx-space-4); }
}
.room-operator-schedule {
  margin: 0;
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.82rem;
  color: var(--rlx-foreground-muted);
}

/* v2 3.8 — plain-English state line + quick-fixes drawer; 3.6 — local copy line */
.room-operator-state { margin: 0; font-size: 0.9rem; color: var(--rlx-fg-muted, #9aa3b5); }
.room-operator-tools { display: flex; gap: var(--rlx-space-2); flex-wrap: wrap; }
.room-fix { border: 1px solid var(--rlx-border, #2a2f3d); border-radius: 10px; padding: 10px 12px; margin-bottom: 8px; }
.room-fix--relevant { border-color: var(--rlx-warning, #f5a623); }
.room-fix h4 { margin: 0 0 2px; font-size: 0.95rem; }
.room-fix .room-fix-sym { margin: 0 0 6px; color: var(--rlx-fg-muted, #9aa3b5); font-size: 0.85rem; }
.room-fix ol { margin: 0; padding-left: 18px; font-size: 0.9rem; }
.room-fix .room-fix-link { margin-top: 4px; font-size: 0.75rem; color: var(--rlx-fg-muted, #9aa3b5); font-family: ui-monospace, Menlo, monospace; }
.room-localcopy { margin: 0; font-size: 0.85rem; color: var(--rlx-fg-muted, #9aa3b5); }
.room-leave-list { margin: 8px 0 0; padding-left: 18px; font-size: 0.9rem; color: var(--rlx-fg-muted, #9aa3b5); }

/* v2 3.7 — desk channel plan */
.room-desk-row { display: flex; align-items: center; gap: 10px; margin: 6px 0; } .room-desk-ch { min-width: 90px; color: var(--rlx-fg-muted, #9aa3b5); }

/* AUX board (Nov 2026) — warn check state, console-style dB meter, the line check */
.room-check--warn .room-check-icon { background: var(--rlx-warning); }
.room-check--warn .room-check-detail { color: var(--rlx-warning-soft-foreground, var(--rlx-warning)); }
.room-dbmeter { display: flex; flex-direction: column; gap: 2px; }
.room-dbmeter-row { display: flex; align-items: center; gap: 8px; }
.room-dbmeter-name { flex: 0 0 38px; font-size: 0.78rem; color: var(--rlx-foreground-muted); font-variant-numeric: tabular-nums; }
.room-dbmeter-bar {
  position: relative;
  flex: 1 1 auto;
  height: 12px;
  border-radius: 3px;
  overflow: hidden;
  /* −60…−12 green · −12…−3 amber · −3…0 red (dbToPercent: −12 = 80 %, −3 = 95 %) */
  background: linear-gradient(90deg, var(--rlx-success) 0 80%, var(--rlx-warning) 80% 95%, var(--rlx-danger) 95% 100%);
}
.room-dbmeter-cover {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 100%;
  background: var(--st-panel, var(--rlx-content2, #1d2027));
}
.room-dbmeter-hold { position: absolute; top: 0; bottom: 0; width: 2px; margin-left: -1px; background: var(--st-text, #fff); opacity: 0.85; }
.room-dbmeter-readout { flex: 0 0 52px; text-align: right; font-size: 0.78rem; font-variant-numeric: tabular-nums; color: var(--rlx-foreground-muted); }
.room-dbmeter-clip {
  flex: 0 0 auto;
  font-size: 0.65rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  padding: 1px 5px;
  border-radius: 4px;
  color: var(--rlx-foreground-muted);
  border: 1px solid var(--st-border-strong, var(--rlx-divider));
}
.room-dbmeter-clip--on { background: var(--rlx-danger); border-color: var(--rlx-danger); color: #fff; }
.room-dbmeter-scale { position: relative; height: 12px; margin-right: 94px; font-size: 0.62rem; color: var(--rlx-foreground-muted); font-variant-numeric: tabular-nums; }
.room-dbmeter-scale span { position: absolute; transform: translateX(-50%); }
.room-dbmeter-scale span:last-child { transform: translateX(-100%); }
.room-dbmeter--off { opacity: 0.45; }
.room-linecheck-meters { display: flex; flex-direction: column; gap: 6px; }
.room-linecheck-status { margin: 0; font-size: 0.85rem; color: var(--rlx-foreground-muted); }
.room-linecheck-status:empty { display: none; }
.room-linecheck-verdict { margin: 6px 0 0; font-size: 0.88rem; font-weight: 600; }
.room-linecheck-verdict--good { color: var(--rlx-success); }
.room-linecheck-verdict--quiet,
.room-linecheck-verdict--hot { color: var(--rlx-warning); }
.room-linecheck-verdict--clipping,
.room-linecheck-verdict--silent { color: var(--rlx-danger); }
.room-linecheck-suggest { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; font-size: 0.85rem; margin-top: 6px; }
.room-linecheck-suggest:empty { display: none; }
.room-line-summary { margin: 0; font-size: 0.82rem; color: var(--rlx-foreground-muted); }

/* ==============================================================================
   SPARK — reactlive-surface v10.09 (public/surface/KIT_VERSION.txt). The studio
   tokens read the product skin (colors.css --rlc-*, resolved by skin.js on
   data-skin) instead of their own hex, so the room is the same graphite / Spark
   Light as every other ReactLive app. Same specificity as the skin blocks above,
   later in the file, so this wins in both modes.
   ============================================================================== */
:root[data-skin] .room-app {
  --st-bg: var(--rlc-bg-canvas);
  --st-panel: var(--rlc-bg-panel);
  --st-panel-2: var(--rlc-bg-control);
  --st-panel-3: var(--rlc-bg-raised);
  --st-border: var(--rlc-border-panel);
  --st-border-strong: var(--rlc-border-strong);
  --st-text: var(--rlc-text);
  --st-muted: var(--rlc-text-sub);
  --st-pro: var(--rlx-accent);
  --st-pro-soft: color-mix(in srgb, var(--rlx-accent) 16%, transparent);
  --st-accent: var(--rlx-danger);
  --st-accent-2: var(--rlx-danger);
  background: var(--st-bg);
}

/* The ReactLive lockup (orb + wordmark, resources/reactlive-logo*.webp; the skin picks the
   white- or dark-text file through surface.css .rl-lockup) + the app name beside it. */
.room-brand { display: flex; align-items: center; gap: 10px; }
.room-brand .rl-lockup { height: 26px; width: auto; }
.room-brand-app {
  padding-left: 10px;
  border-left: 1px solid var(--st-border-strong, var(--rlx-divider));
  font-weight: 600;
  font-size: 0.95rem;
  color: var(--st-muted, var(--rlx-foreground-muted));
  letter-spacing: -0.01em;
}
@media (max-width: 560px) {
  .room-brand .rl-lockup { height: 20px; }
  .room-brand-app { display: none; }
}
/* Join-screen tools (Line check / Audio settings) keep a visible control fill on both skins. */
:root[data-skin] .room-app .room-readiness-trigger { background: var(--st-panel-3); }
:root[data-skin] .room-app .room-readiness-trigger:hover:not([disabled]) { background: var(--rlc-bg-hover, var(--st-panel-3)); }
/* Quick fixes: who the desk calls */
.room-contact { display: flex; flex-direction: column; gap: 8px; }
.room-contact h4 { margin: 0; }
.room-contact .room-fix-sym { margin: 0; }
.room-contact-actions { display: flex; gap: 8px; flex-wrap: wrap; }

/* Join card by role (owner, 31 Oct): a header line, one device row, one action, the rest folded away */
.room-join-meta { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-size: 0.82rem; color: var(--st-muted, var(--rlx-foreground-muted)); margin-bottom: 2px; }
.room-join-meta-text { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.room-join-notyou,
.room-devrow-action { background: none; border: 0; padding: 0; font: inherit; font-size: 0.82rem; color: var(--rlx-accent, var(--rlx-primary)); cursor: pointer; white-space: nowrap; }
.room-join-notyou:hover,
.room-devrow-action:hover { text-decoration: underline; }
.room-join-manual { display: flex; flex-direction: column; gap: var(--rlx-space-3); padding: var(--rlx-space-3); border: 1px dashed var(--st-border-strong, var(--rlx-divider)); border-radius: var(--rlx-radius-lg); }
.room-join-role { display: flex; flex-direction: column; gap: var(--rlx-space-3); }
.room-devrow { display: flex; align-items: center; gap: 10px; min-height: 40px; padding: 8px 12px; border-radius: var(--rlx-radius-md, 10px); background: var(--st-panel-3, var(--rlx-content2)); border: 1px solid var(--st-border, var(--rlx-divider)); }
.room-devrow-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 0.9rem; }
.room-devrow-meter { flex: 0 0 64px; height: 6px; border-radius: 3px; overflow: hidden; background: var(--st-panel, var(--rlx-content1)); }
.room-devrow-fill { display: block; height: 100%; width: 0%; background: var(--rlx-success); transition: width 60ms linear; }
.room-more { border-top: 1px solid var(--st-border, var(--rlx-divider)); padding-top: var(--rlx-space-2); }
.room-more > summary { cursor: pointer; font-size: 0.85rem; color: var(--st-muted, var(--rlx-foreground-muted)); list-style: none; display: flex; align-items: center; gap: 6px; }
.room-more > summary::-webkit-details-marker { display: none; }
.room-more > summary::before { content: '▸'; font-size: 0.75rem; transition: transform 120ms ease; }
.room-more[open] > summary::before { transform: rotate(90deg); }
.room-more-body { display: flex; flex-direction: column; gap: var(--rlx-space-3); padding-top: var(--rlx-space-3); }
@media (prefers-reduced-motion: reduce) { .room-more > summary::before { transition: none; } }
/* the hidden attribute always wins over a component's own display (as in the capture app) */
.room-app [hidden] { display: none !important; }
@media (max-width: 420px) { .room-devrow-meter { flex-basis: 36px; } }

/* Desk panel, simplified (owner, 31 Oct): one top line, a strip of ticks, only problems spelled out */
.room-op-top { display: flex; align-items: center; gap: 12px; }
.room-op-top .room-op-badge { flex: 0 0 auto; }
.room-op-what { display: flex; flex-direction: column; gap: 2px; min-width: 0; flex: 1 1 auto; }
.room-op-state { font-weight: 600; font-size: 0.95rem; color: var(--st-text, var(--rlx-foreground)); }
.room-op-sub { font-size: 0.8rem; color: var(--st-muted, var(--rlx-foreground-muted)); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.room-op-primary { flex: 0 0 auto; }
.room-op-strip {
  display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap;
  width: 100%; padding: 8px 12px; border-radius: var(--rlx-radius-md, 10px); cursor: pointer; text-align: left;
  font: inherit; color: inherit; background: var(--st-panel-3, var(--rlx-content2)); border: 1px solid var(--st-border, var(--rlx-divider));
}
.room-op-strip:hover { border-color: var(--st-border-strong, var(--rlx-divider)); }
.room-op-strip--fail { border-color: var(--rlx-danger); }
.room-op-strip--warn { border-color: var(--rlx-warning); }
.room-op-verdict { font-size: 0.88rem; font-weight: 600; }
.room-op-strip--ok .room-op-verdict { color: var(--rlx-success); }
.room-op-strip--fail .room-op-verdict { color: var(--rlx-danger); }
.room-op-strip--warn .room-op-verdict { color: var(--rlx-warning); }
.room-op-strip--pending .room-op-verdict { color: var(--st-muted, var(--rlx-foreground-muted)); }
.room-op-ticks { display: flex; gap: 10px; flex-wrap: wrap; }
.room-op-tick { display: inline-flex; align-items: center; gap: 5px; font-size: 0.78rem; color: var(--st-muted, var(--rlx-foreground-muted)); }
.room-op-tick-dot { width: 8px; height: 8px; border-radius: 50%; background: var(--rlx-foreground-muted); }
.room-op-tick--ok .room-op-tick-dot { background: var(--rlx-success); }
.room-op-tick--warn .room-op-tick-dot { background: var(--rlx-warning); }
.room-op-tick--fail .room-op-tick-dot { background: var(--rlx-danger); }
.room-op-tick--pending .room-op-tick-dot { background: transparent; box-shadow: inset 0 0 0 1.5px var(--rlx-foreground-muted); }
.room-op-more { border-top: 0; padding-top: 0; margin-left: auto; }
.room-op-more > .room-more-body { padding-top: var(--rlx-space-2); }
.room-operator-tools { align-items: flex-start; }
@media (max-width: 560px) {
  .room-op-top { flex-wrap: wrap; }
  .room-op-primary { width: 100%; }
}

/* Desk confidence (1 Nov, after Snapsight's Operator): one big status word, the sound check's heard
   words, and the "before you walk away" cards */
.room-op-word {
  display: flex; align-items: center; gap: 14px;
  font-size: clamp(1.5rem, 4.5vw, 2.25rem); font-weight: 700; line-height: 1.1; letter-spacing: -0.01em;
  color: var(--st-text, var(--rlx-foreground));
}
.room-op-word-dot { width: 0.42em; height: 0.42em; border-radius: 50%; flex: 0 0 auto; background: var(--rlx-foreground-muted); }
.room-op-word--green { color: var(--rlx-success); }
.room-op-word--green .room-op-word-dot { background: var(--rlx-success); }
.room-op-word--amber { color: var(--rlx-warning); }
.room-op-word--amber .room-op-word-dot { background: var(--rlx-warning); animation: room-op-pulse 1.4s ease-in-out infinite; }
.room-op-word--red { color: var(--rlx-danger); }
.room-op-word--red .room-op-word-dot { background: var(--rlx-danger); animation: room-op-pulse 1.4s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) { .room-op-word-dot { animation: none !important; } }

.room-sc {
  display: flex; flex-direction: column; gap: 6px; padding: 12px 14px; border-radius: var(--rlx-radius-md, 10px);
  background: var(--st-panel-3, var(--rlx-content2)); border: 1px solid var(--st-border, var(--rlx-divider));
}
.room-sc p { margin: 0; }
.room-sc-title { display: flex; align-items: center; gap: 8px; font-weight: 700; font-size: 1rem; }
.room-sc-text { font-size: 0.85rem; color: var(--st-muted, var(--rlx-foreground-muted)); }
.room-sc--passed { border-color: var(--rlx-success); }
.room-sc--passed .room-sc-title { color: var(--rlx-success); }
.room-sc--no_signal, .room-sc--no_words { border-color: var(--rlx-warning); }
.room-sc--no_signal .room-sc-title, .room-sc--no_words .room-sc-title { color: var(--rlx-warning); }
.room-sc-heard { margin: 2px 0 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 4px; }
.room-sc-heard li { font-size: 0.95rem; color: var(--st-text, var(--rlx-foreground)); }

.room-walk { display: flex; flex-direction: column; gap: 8px; }
.room-walk-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.room-walk-title { font-weight: 700; font-size: 0.95rem; }
.room-walk-count { font-size: 0.8rem; color: var(--st-muted, var(--rlx-foreground-muted)); font-variant-numeric: tabular-nums; }
.room-walk-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.room-walk-card {
  display: flex; align-items: flex-start; gap: 10px; padding: 10px 12px; min-height: 64px; text-align: left; cursor: pointer;
  font: inherit; color: inherit; border-radius: var(--rlx-radius-md, 10px);
  background: var(--st-panel-3, var(--rlx-content2)); border: 1px solid var(--st-border, var(--rlx-divider));
}
.room-walk-card:hover { border-color: var(--st-border-strong, var(--rlx-divider)); }
.room-walk-card:focus-visible { outline: 2px solid var(--rlx-primary); outline-offset: 2px; }
.room-walk-card > svg { flex: 0 0 auto; margin-top: 1px; color: var(--st-muted, var(--rlx-foreground-muted)); }
.room-walk-card--done { border-color: var(--rlx-success); }
.room-walk-card--done > svg { color: var(--rlx-success); }
.room-walk-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.room-walk-card-title { font-weight: 600; font-size: 0.88rem; }
.room-walk-card-hint { font-size: 0.78rem; color: var(--st-muted, var(--rlx-foreground-muted)); }
.room-walk-ready {
  display: flex; align-items: center; gap: 8px; width: 100%; padding: 8px 12px; cursor: pointer; text-align: left;
  font: inherit; font-size: 0.88rem; font-weight: 600; color: var(--rlx-success);
  background: transparent; border: 1px solid var(--rlx-success); border-radius: var(--rlx-radius-md, 10px);
}
@media (max-width: 560px) { .room-walk-grid { grid-template-columns: 1fr; } }

/* Record page by role (owner, 1 Nov): the link decides — link header, no picker, "Use your personal
   link", and the quiet "Last heard" for the AV desk and the host */
.room-join-link { display: flex; justify-content: flex-start; align-items: center; gap: 8px; flex-wrap: wrap; font-size: 0.82rem; color: var(--st-muted, var(--rlx-foreground-muted)); }
.room-join-link-label { font-weight: 600; }
.room-join-role-chip { flex: 0 0 auto; }
.room-join-link-room { font-family: var(--rlx-font-mono, ui-monospace, monospace); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.room-join-wrong { margin: 0; font-size: 0.8rem; text-align: center; color: var(--st-muted, var(--rlx-foreground-muted)); }

.room-nolink { text-align: center; align-items: center; }
.room-nolink-icon { font-size: 2.2rem; line-height: 1; margin-bottom: 4px; }
.room-nolink .room-join-sub { max-width: 34ch; margin-left: auto; margin-right: auto; }
.room-nolink-captions { display: inline-block; margin-top: 8px; font-weight: 600; color: var(--rlx-primary); text-decoration: none; }
.room-nolink-captions:hover { text-decoration: underline; }
.room-seat-actions { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; margin-top: 12px; }

.room-heard { display: flex; flex-direction: column; gap: 1px; min-height: 0; }
.room-heard-label { font-size: 0.72rem; font-weight: 600; letter-spacing: 0.02em; color: var(--st-muted, var(--rlx-foreground-muted)); }
.room-heard--stalled .room-heard-label { color: var(--rlx-danger); }
.room-heard-line {
  margin: 0; font-size: 0.82rem; font-style: italic; line-height: 1.35;
  color: var(--st-text, var(--rlx-foreground));
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.room-heard-line--1 { opacity: 1; }
.room-heard-line--2 { opacity: 0.66; }
.room-heard-line--3 { opacity: 0.42; }
.room-heard-slot:empty { display: none; }
.room-heard-slot { padding: 0 var(--rlx-space-2, 8px); }

/* Sound-check result, quiet (1 Nov: the owner's "just give a sense it works" for captions in the room):
   no box — a small coloured status line, a one-line hint until it passes, the heard words in the
   "Last heard" italic, newest brightest */
.room-sc { gap: 2px; padding: 0; background: transparent; border: 0; border-radius: 0; }
.room-sc-title { font-size: 0.82rem; gap: 6px; }
.room-sc-title svg { width: 14px; height: 14px; }
.room-sc-text { font-size: 0.76rem; }
.room-sc--passed .room-sc-text { display: none; }
.room-sc-heard { gap: 1px; margin: 0; }
.room-sc-heard li { font-size: 0.82rem; font-style: italic; line-height: 1.35; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.room-sc-heard li:nth-last-child(2) { opacity: 0.66; }
.room-sc-heard li:nth-last-child(3) { opacity: 0.42; }

/* AV desk laptop self-check (1 Nov): one line, tap for every check */
.room-laptop { font-size: 0.82rem; }
.room-laptop > summary { cursor: pointer; list-style: none; color: var(--st-muted, var(--rlx-foreground-muted)); }
.room-laptop > summary::-webkit-details-marker { display: none; }
.room-laptop--ok > summary { color: var(--rlx-success); }
.room-laptop--warn > summary { color: var(--rlx-warning); }
.room-laptop--fail > summary { color: var(--rlx-danger); }
.room-laptop-list { margin: 6px 0 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 3px; }
.room-laptop-item { color: var(--st-muted, var(--rlx-foreground-muted)); }
.room-laptop-item--warn { color: var(--rlx-warning); }
.room-laptop-item--fail { color: var(--rlx-danger); }
