:root {
  --bg: #fbfaf7;
  --fg: #1b1a17;
  --muted: #6d6a62;
  --line: #e4e0d7;
  --accent: #7a5c3e;
  --warn: #8a3d2a;
  --radius: 10px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #161513;
    --fg: #ece8e0;
    --muted: #9a958a;
    --line: #2c2a26;
    --accent: #c99a6b;
    --warn: #d98b72;
  }
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font: 16px/1.5 ui-serif, Georgia, "Times New Roman", serif;
  -webkit-font-smoothing: antialiased;
}

main {
  max-width: 46rem;
  margin: 0 auto;
  padding: 2rem 1.25rem 3rem;
}

h1 {
  font-size: 2.5rem;
  margin: 0 0 0.25rem;
  letter-spacing: -0.02em;
}

h2 { font-size: 1.75rem; margin: 0 0 0.25rem; }

.sub { color: var(--muted); margin: 0 0 2rem; }
.muted { color: var(--muted); font-size: 0.9rem; }

.room { font-size: 0.95rem; color: var(--muted); }
.room strong { color: var(--fg); font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }

.share { display: flex; gap: 0.5rem; margin: 0.5rem 0 2rem; }
.share input {
  flex: 1;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.85rem;
}

input, select, button {
  font: inherit;
  color: inherit;
  background: transparent;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0.55rem 0.7rem;
}

button { cursor: pointer; background: transparent; }
button:hover { border-color: var(--accent); }
button.on { border-color: var(--accent); color: var(--accent); }
button.danger:hover { border-color: var(--warn); color: var(--warn); }
button:disabled { opacity: 0.5; cursor: default; }

form#join { display: grid; gap: 1rem; max-width: 22rem; }
form#join label { display: grid; gap: 0.35rem; font-size: 0.9rem; color: var(--muted); }
#join-button {
  border-color: var(--accent);
  color: var(--accent);
  padding: 0.7rem;
  font-size: 1.05rem;
}

/* Said in the lobby because the fear is that joining turns the camera on. There is no
   camera control here on purpose: one would imply exactly that, and before permission
   the device list has no labels worth reading anyway. */
.camera-note { margin-top: 1rem; }

.warn {
  margin-top: 1.5rem;
  padding: 0.75rem 0.9rem;
  border-left: 3px solid var(--warn);
  color: var(--warn);
  font-size: 0.9rem;
}

.promise {
  margin-top: 2.5rem;
  padding-top: 1.25rem;
  border-top: 1px solid var(--line);
  color: var(--muted);
  font-size: 0.9rem;
}

/* Room --------------------------------------------------------------- */

#room header {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  align-items: center;
  justify-content: space-between;
  padding-bottom: 0.75rem;
  border-bottom: 1px solid var(--line);
  font-size: 0.9rem;
}

.dot {
  display: inline-block;
  width: 8px; height: 8px;
  border-radius: 50%;
  background: var(--accent);
  margin-right: 0.45rem;
}

.controls { display: flex; gap: 0.4rem; flex-wrap: wrap; align-items: center; }
.controls button, .controls select { padding: 0.35rem 0.55rem; font-size: 0.85rem; }

/* Device labels run long ("MacBook Pro Microphone (Built-in)"); the row must not. */
#mic-live { max-width: 11rem; text-overflow: ellipsis; }
#cam-live { max-width: 9rem; text-overflow: ellipsis; }

/* Eight controls wrap to three lines on a 375px screen. Tighten the row rather than let
   the header eat the feed. */
.controls { row-gap: 0.35rem; }
@media (max-width: 480px) {
  .controls button, .controls select { font-size: 0.8rem; padding: 0.3rem 0.45rem; }
}

/* The face strip ------------------------------------------------------- */

/* One row that scrolls sideways instead of wrapping, so six people and sixteen people
   cost the feed exactly the same number of pixels. Six 7rem tiles plus gaps is about
   44rem, which fits the 46rem reading column without scrolling at all. */
#stage {
  display: flex;
  gap: 0.5rem;
  overflow-x: auto;
  scroll-snap-type: x proximity;
  padding: 0.75rem 0 0;
}
#stage:empty { display: none; }

.tile {
  position: relative;
  flex: 0 0 auto;
  width: 7rem;
  height: 5.25rem;
  scroll-snap-align: start;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--line);
}

.tile video {
  width: 100%;
  height: 100%;
  /* The camera gives whatever it gives; cover absorbs the aspect mismatch. */
  object-fit: cover;
  display: block;
}

/* The placeholder sits on top and is always present, so a participant with no camera is
   a face-shaped card with their initial rather than a hole in the row. */
.ph {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.75rem;
  color: var(--muted);
  background: var(--line);
}
.tile.live .ph { display: none; }

.tag {
  position: absolute;
  left: 0.3rem;
  bottom: 0.25rem;
  max-width: calc(100% - 0.6rem);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.7rem;
  letter-spacing: 0.06em;
  color: var(--muted);
}
.tile.live .tag {
  color: var(--bg);
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
}

/* Mirroring your own face and not other people's is the convention every video tool
   follows, and the one people notice when it is missing. */
.tile[data-self] { border-color: var(--accent); }
.tile[data-self] video { transform: scaleX(-1); }

@media (max-width: 480px) {
  .tile { width: 4.75rem; height: 3.5rem; }
  .ph { font-size: 1.25rem; }
}

.miclevel {
  width: 5px;
  height: 1.15rem;
  border: 1px solid var(--line);
  border-radius: 3px;
  overflow: hidden;
  display: inline-flex;
  align-items: flex-end;
}
#mic-level {
  width: 100%;
  height: 0%;
  background: var(--accent);
  transition: height 90ms linear;
}

/* Mark 3 buys the face strip out of the feed's height, once, on purpose and as an
   explicit literal rather than a flexible share. Mark 1 and Mark 2 keep min(68vh, 40rem). */
#feed {
  height: min(60vh, 36rem);
  overflow-y: auto;
  padding: 1.5rem 0;
  scroll-behavior: smooth;
}
@media (max-width: 480px) {
  #feed { height: min(52vh, 28rem); }
}

.line { margin-bottom: 1.6rem; }

.who {
  display: block;
  font-size: 0.75rem;
  text-transform: lowercase;
  letter-spacing: 0.08em;
  color: var(--muted);
  margin-bottom: 0.2rem;
}

/* The Italian is the point. It is set large, and the translation sits under it as
   support rather than as an equal. A learner who reads only the English has not had
   the experience this room is for. */
.it {
  margin: 0;
  font-size: 1.5rem;
  line-height: 1.35;
}

.en {
  margin: 0.25rem 0 0;
  font-size: 1rem;
  color: var(--muted);
  font-family: system-ui, -apple-system, sans-serif;
}

.partial { opacity: 0.55; }
.partial .it { font-style: italic; }

#room footer {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  border-top: 1px solid var(--line);
  padding-top: 0.75rem;
  font-size: 0.8rem;
  color: var(--muted);
}

/* Which Mark this is, always on screen. A comparison is worthless if anyone has to
   remember afterwards which build they were in. */
.mark {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  letter-spacing: 0.06em;
}

.downloads { line-height: 2; padding-left: 1.1rem; }
.downloads a { color: var(--accent); }
