/* Salotto, Mark 3.
 *
 * The whole design is a token table plus hairlines. No new colours are introduced
 * anywhere below: the accent is spent on exactly five things (the roster dot, the border
 * of your own tile, the microphone meter, the entry button, and the link to your words)
 * and nothing else earns it. Boxes and shadows are not used; a section begins with a 1px
 * --line rule and some air.
 *
 * The responsive story is told in custom properties rather than in duplicated rules: one
 * media query re-points the tokens and every surface follows. --grpLabel, --langGrp,
 * --lblLong and --lblShort are display switches, so a phone drops the group labels and
 * the language select without a second copy of the markup existing anywhere.
 */

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

  --serif: ui-serif, Georgia, "Times New Roman", serif;
  --sans: system-ui, -apple-system, sans-serif;
  --mono: ui-monospace, SFMono-Regular, Menlo, monospace;

  --radius: 10px;

  /* Type scale */
  --h1: 2.5rem;
  --h2: 1.75rem;
  --lead: 1.125rem;
  --cap: 1.5rem;
  --ctl: 0.85rem;

  /* Rhythm */
  --padT: 2.5rem;
  --padX: 2rem;
  --roomPadX: 2rem;
  --secGap: 2.5rem;
  --gap3: 1.25rem;
  --cols3: repeat(3, 1fr);

  /* Face strip */
  --tileW: 7rem;
  --tileH: 5.25rem;

  /* Display switches, read by the control bar */
  --grpLabel: block;
  --langGrp: flex;
  --lblLong: inline;
  --lblShort: none;
}

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

/* 375px is a first-class width, not a fallback. Everything below is a token move. */
@media (max-width: 480px) {
  :root {
    --h1: 1.9rem;
    --h2: 1.4rem;
    --lead: 1rem;
    --cap: 1.4rem;
    --ctl: 0.8rem;
    --padT: 1.5rem;
    --padX: 1.25rem;
    --roomPadX: 1.1rem;
    --secGap: 1.9rem;
    --gap3: 1.1rem;
    --cols3: 1fr;
    --tileW: 4.75rem;
    --tileH: 3.5rem;
    --grpLabel: none;
    --langGrp: none;
    --lblLong: none;
    --lblShort: inline;
  }
}

* { box-sizing: border-box; }

/* Every surface below sets its own display, which outranks the user agent's rule for
   [hidden] and would leave the room and the end screen on screen behind the lobby. The
   attribute is how this page switches surfaces, so it wins here explicitly. */
[hidden] { display: none !important; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font: 16px/1.5 var(--serif);
  -webkit-font-smoothing: antialiased;
}

/* The room is a frame, not a document: the page does not scroll, only the feed does.
   Every other surface is a document and scrolls normally. */
body[data-view="room"] {
  height: 100vh;
  height: 100dvh;
  overflow: hidden;
}
body[data-view="room"] main {
  height: 100%;
  max-width: none;
  padding: 0;
}

main {
  max-width: 46rem;
  margin: 0 auto;
  padding: var(--padT) var(--padX) 3rem;
}

/* Anything reachable by keyboard says so, in both themes. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; scroll-behavior: auto !important; }
}

/* Shared vocabulary ---------------------------------------------------- */

.sheet { display: flex; flex-direction: column; gap: var(--secGap); }

.wordmark { margin: 0; font-size: 1.05rem; letter-spacing: 0.06em; }

h1 { margin: 0; font-weight: 400; font-size: var(--h1); line-height: 1.15; letter-spacing: -0.02em; text-wrap: pretty; }
h1.h2 { font-size: var(--h2); }
h2 { margin: 0; font-weight: 400; font-size: 1.05rem; }

.titles .sub { margin: 0.8rem 0 0; color: var(--muted); text-wrap: pretty; }
.titles .sub.lead { font-size: var(--lead); }

.hint { margin: 0; font-size: 0.85rem; color: var(--muted); text-wrap: pretty; }

/* House rule made visible: instructional chrome is bilingual, Italian first with the
   English beneath in the sans, the same shape the caption feed teaches. Vocabulary
   being learned is the only thing that stays Italian alone. */
.chrome-en {
  display: block;
  margin: 0.3rem 0 0;
  font-family: var(--sans);
  font-size: 0.82rem;
  color: var(--muted);
  text-wrap: pretty;
}
span.chrome-en { display: inline; margin: 0; }
.muted { margin: 0; color: var(--muted); text-wrap: pretty; }

/* A section is a hairline and some air. Never a box, never a shadow. */
.ruled { border-top: 1px solid var(--line); padding-top: 1.1rem; }
.narrow { max-width: 36rem; }

code {
  font-family: var(--mono);
  font-size: 0.8rem;
  color: var(--muted);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0.5rem 0.65rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

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

button { cursor: pointer; }
button:hover { border-color: var(--accent); }
button:disabled { opacity: 0.5; cursor: default; }

/* An active toggle is never colour alone: it fills, its border goes to --fg, and its
   word changes to the present tense. Muto, non registro, ferma video. */
button.on {
  background: var(--line);
  border-color: var(--fg);
  color: var(--fg);
}

/* Long labels and short ones live side by side and the tokens choose. */
.lbl-long { display: var(--lblLong); }
.lbl-short { display: var(--lblShort); }

/* A disclosure that reads as a quiet link rather than as a control. */
.quiet > summary,
.regola > summary {
  list-style: none;
  cursor: pointer;
  font-size: 0.85rem;
  color: var(--muted);
  width: fit-content;
}
.quiet > summary::-webkit-details-marker,
.regola > summary::-webkit-details-marker { display: none; }
.pseudo-link,
.regola > summary { border-bottom: 1px solid var(--line); padding-bottom: 1px; }
.quiet > summary:hover .pseudo-link,
.regola > summary:hover { border-color: var(--accent); color: var(--accent); }

/* Lobby ---------------------------------------------------------------- */

.notes { display: flex; flex-direction: column; gap: 1.1rem; }
.note { border-top: 1px solid var(--line); padding-top: 0.85rem; display: flex; flex-direction: column; gap: 0.3rem; }
.note p { margin: 0; color: var(--muted); font-size: 0.95rem; text-wrap: pretty; }

/* One line of preparation for the feed does more for comprehension than any change
   inside the room, so the lobby shows the shape of a caption before anyone joins. */
.preview { display: flex; flex-direction: column; gap: 0.7rem; }
.preview > p { margin: 0; font-size: 0.95rem; text-wrap: pretty; }
.sample { border-left: 1px solid var(--line); padding: 0.15rem 0 0.15rem 0.9rem; }
.sample .it { font-size: 1.25rem; line-height: 1.3; }
.sample .en { font-size: 0.9rem; }

/* The one place --warn appears in the lobby. It is a capability fact, not an alarm. */
.warn {
  margin: 0;
  border-left: 2px solid var(--warn);
  padding: 0.15rem 0 0.15rem 0.8rem;
  color: var(--warn);
  font-size: 0.95rem;
  text-wrap: pretty;
}

form#join { display: flex; flex-direction: column; gap: 1.4rem; padding-top: 1.4rem; }
.field { display: flex; flex-direction: column; gap: 0.4rem; }
.field label { font-size: 1.05rem; }
.field input, .field select {
  font-size: 1.1rem;
  padding: 0.7rem 0.8rem;
  min-height: 44px;
  width: 100%;
}

.submit { display: flex; flex-direction: column; gap: 0.9rem; align-items: flex-start; }
#join-button {
  color: var(--accent);
  border-color: var(--accent);
  font-size: 1.05rem;
  line-height: 1;
  padding: 1rem 1.6rem;
  min-height: 44px;
}
#join-button:hover { background: var(--line); }

/* Before permission is granted this can only say "predefinito", which is exactly why it
   is a line of small type under the button rather than a third question. */
#mic-choice .panel { margin-top: 0.6rem; }
#mic-choice select { min-height: 44px; max-width: 20rem; }

.share { display: flex; flex-direction: column; gap: 0.5rem; }
.share-row { display: flex; flex-wrap: wrap; gap: 0.5rem; align-items: center; }
.share-row code { flex: 1; min-width: 12rem; }
#copy { font-size: 0.85rem; padding: 0.5rem 0.8rem; min-height: 44px; }

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

#room {
  height: 100%;
  display: flex;
  flex-direction: column;
  gap: 0.7rem;
  padding: 1rem var(--roomPadX) 0.8rem;
  /* A no-op at the 1000px the artboards were drawn at, and a guard against 2500px-wide
     caption lines on a large monitor. */
  max-width: 72rem;
  margin: 0 auto;
}

#room header {
  flex: none;
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  border-bottom: 1px solid var(--line);
  padding-bottom: 0.55rem;
}

.roster {
  margin: 0;
  font-size: 0.9rem;
  display: flex;
  align-items: baseline;
  gap: 0.45rem;
  flex-wrap: wrap;
  min-width: 0;
}

.dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accent);
  display: inline-block;
  transform: translateY(-1px);
}

/* Somebody else's paused captions are meaningful information delivered as a word, not
   as a glyph nobody was taught. */
.roster .sep-dot { color: var(--muted); }
.roster .not-recording { font-size: 0.78rem; color: var(--muted); }

.leave {
  flex: none;
  font-size: var(--ctl);
  color: var(--muted);
  padding: 0.4rem 0.7rem;
}
.leave:hover { color: var(--warn); border-color: var(--warn); }

/* 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. */
#stage {
  flex: none;
  display: flex;
  gap: 0.5rem;
  overflow-x: auto;
  scroll-snap-type: x proximity;
  padding-bottom: 0.15rem;
}
#stage:empty { display: none; }

.tile {
  position: relative;
  flex: none;
  width: var(--tileW);
  height: var(--tileH);
  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. Camera-off and
   camera-never-started render identically on purpose. */
.ph {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.4rem;
  color: var(--muted);
  background: var(--line);
}
.tile.live .ph { display: none; }

.tag {
  position: absolute;
  left: 0.35rem;
  bottom: 0.28rem;
  max-width: calc(100% - 0.7rem);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  font-size: 0.7rem;
}
.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) {
  .ph { font-size: 1.25rem; }
}

/* The feed ------------------------------------------------------------- */

#feed {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 1.15rem;
  padding-right: 0.3rem;
  scroll-behavior: smooth;
}

.alone {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0.85rem;
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  align-items: flex-start;
}
.alone-title { margin: 0; font-size: 1.05rem; }
.alone code { font-size: 0.75rem; padding: 0.4rem 0.55rem; }

.no-asr {
  margin: 0;
  border: 1px solid var(--warn);
  border-radius: var(--radius);
  padding: 0.7rem 0.85rem;
  color: var(--warn);
  font-size: 0.95rem;
  text-wrap: pretty;
}

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

/* The Italian is the point. It is set large in the serif, and the translation sits under
   it as support rather than as an equal. A learner who reads only the translation has
   not had the experience this room is for. */
.it {
  margin: 0;
  font-size: var(--cap);
  line-height: 1.35;
  text-wrap: pretty;
}

.en {
  margin: 0.15rem 0 0;
  font-family: var(--sans);
  font-size: 1rem;
  line-height: 1.4;
  color: var(--muted);
  text-wrap: pretty;
}

/* Partials must never read as finals, or the feed looks like it is stuttering. */
.partial { opacity: 0.55; }
.partial .it { font-style: italic; }

/* The state line ------------------------------------------------------- */

.state-line {
  margin: 0;
  flex: none;
  font-size: 0.9rem;
  color: var(--muted);
  border-top: 1px solid var(--line);
  padding-top: 0.6rem;
}
/* The clause that is currently true of you is the one in full contrast. */
.state-line strong { font-weight: inherit; color: var(--fg); }
.state-line.trouble { color: var(--warn); border-top-color: var(--warn); }

/* The control bar ------------------------------------------------------ */

/* Four groups, each labelled with the job it does, separated by hairlines. Eight
   controls that accumulated one at a time now answer four questions. */
.bar {
  flex: none;
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.7rem;
}

.group { display: flex; flex-direction: column; gap: 0.3rem; }
.grp-lang { display: var(--langGrp); flex-direction: column; }
.grp-items { display: flex; align-items: center; gap: 0.45rem; }

.grp-label {
  display: var(--grpLabel);
  font-size: 0.68rem;
  letter-spacing: 0.1em;
  color: var(--muted);
}

.sep { width: 1px; align-self: stretch; background: var(--line); }
.sep-lang { display: var(--langGrp); }

.bar button, .bar select {
  font-size: var(--ctl);
  padding: 0.5rem 0.75rem;
  min-height: 44px;
}
.bar select { padding: 0.5rem 0.55rem; }

/* The single instrument that separates a dead microphone from a network problem. */
.miclevel {
  width: 3.5rem;
  height: 5px;
  border-radius: 3px;
  background: var(--line);
  overflow: hidden;
  display: inline-block;
}
#mic-level {
  display: block;
  width: 0%;
  height: 100%;
  background: var(--accent);
  transition: width 90ms linear;
}

.regola { margin-left: auto; align-self: flex-end; }
/* Open, it takes a row of its own rather than shoving the groups sideways. The details
   stays in block layout on purpose: Chrome wraps everything after the summary in a
   ::details-content box, and making the details a flex container leaves that wrapper
   shrink-to-fit, so the panel comes out the width of its contents instead of the row. */
.regola[open] { flex: 1 0 100%; margin-left: 0; }
.regola > summary { font-size: var(--ctl); margin-left: auto; }
.regola .panel {
  width: 100%;
  display: flex;
  flex-wrap: wrap;
  gap: 0.7rem 1.2rem;
  margin-top: 0.7rem;
  padding-top: 0.7rem;
  border-top: 1px solid var(--line);
  /* On a phone the language select moves in here, where its group label is worth
     showing again. */
  --grpLabel: block;
}
.picker { display: flex; flex-direction: column; gap: 0.3rem; font-size: 0.68rem; letter-spacing: 0.1em; color: var(--muted); }
/* Device labels run long ("MacBook Pro Microphone (Built-in)"); the row must not. */
.picker select { max-width: 13rem; text-overflow: ellipsis; }

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

/* Which build a participant is in, always on screen. A comparison between sessions is
   worthless if nobody can say afterwards which build they were in. */
.mark {
  margin: 0;
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.04em;
  color: var(--muted);
}

/* End screen ----------------------------------------------------------- */

.yours { display: flex; flex-direction: column; gap: 1.1rem; }
#samples { display: flex; flex-direction: column; gap: 1.1rem; }
.said .at { margin: 0 0 0.12rem; font-size: 0.75rem; letter-spacing: 0.08em; color: var(--muted); }
.said .text { margin: 0; font-size: 1.25rem; line-height: 1.35; text-wrap: pretty; }
#sample-count { margin-top: 0.2rem; font-size: 0.95rem; }

.read-all {
  font-size: 1.05rem;
  color: var(--accent);
  text-decoration: none;
  border-bottom: 1px solid var(--line);
  align-self: flex-start;
  padding-bottom: 2px;
}
.read-all:hover { border-color: var(--accent); }

.files { display: flex; flex-direction: column; gap: 0.7rem; }
.file-row { display: flex; flex-wrap: wrap; gap: 0.5rem 1.2rem; }
.file-row a {
  font-family: var(--mono);
  font-size: 0.8rem;
  color: var(--muted);
  text-decoration: none;
  border-bottom: 1px solid var(--line);
  padding-bottom: 2px;
}
.file-row a:hover { color: var(--accent); border-color: var(--accent); }

#done footer {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 1rem;
  padding-top: 1rem;
}
#done footer .hint { font-size: 0.9rem; }
