/*
 * The room screen, from the RoomDisplay artboard in ba-mobile-design.
 *
 * One visual world and no theme switching: this renders on a projector and an iPad on a
 * stand, never in somebody's browser with a preference. Navy ground, teal for presence,
 * and every digit in the mono face — times and codes are evidence, and they are set like
 * data everywhere else in this product too.
 *
 * Sized to be read from the back row.
 */

:root {
  --navy: #0B1B4D;
  --teal: #0FA47F;
  --ink: #FFFFFF;
  --muted: #7C87A8;
  --dim: #9AA5C8;
  --hair: rgba(255, 255, 255, 0.14);
  --cell: rgba(255, 255, 255, 0.07);
}

* { box-sizing: border-box; }

html, body { height: 100%; }

body {
  margin: 0;
  background: var(--navy);
  color: var(--ink);
  font-family: 'Plus Jakarta Sans', -apple-system, 'Segoe UI', sans-serif;
  -webkit-font-smoothing: antialiased;
  overflow: hidden;
}

/* ── Sign in ─────────────────────────────────────────────────────────────── */

body.signin { display: grid; place-items: center; padding: 24px; overflow: auto; }

.card {
  width: min(420px, 100%);
  display: flex;
  flex-direction: column;
  gap: 14px;
}

/* The lockup is the brand's own white-on-dark one, taken from the landing site.
   Never redraw it: a hand-made stand-in is a second logo that drifts. */
.logo { display: block; height: auto; }

.signin-logo { width: 190px; margin-bottom: 4px; }

.card h1 {
  font-family: 'Sora', sans-serif;
  font-size: 30px; font-weight: 600; letter-spacing: -0.02em; margin: 0;
}

.card .help { margin: 0 0 6px; color: var(--dim); font-size: 14px; line-height: 1.5; }

.card label {
  font-family: 'JetBrains Mono', monospace;
  font-size: 10px; letter-spacing: 0.14em; color: var(--muted);
}

.card input {
  width: 100%;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--hair);
  border-radius: 12px;
  padding: 13px 15px;
  color: var(--ink);
  font: inherit;
  font-size: 15px;
}

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

.card form { display: flex; flex-direction: column; gap: 8px; }
.card form label { margin-top: 8px; }

.card button {
  margin-top: 18px;
  height: 52px;
  border: 0;
  border-radius: 999px;
  background: var(--teal);
  color: var(--navy);
  font: inherit;
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
}

.card .error {
  margin: 0;
  background: rgba(232, 84, 46, 0.14);
  border: 1px solid rgba(232, 84, 46, 0.4);
  border-radius: 12px;
  padding: 12px 14px;
  color: #FFD9CE;
  font-size: 13.5px;
  line-height: 1.5;
}

/* ── The screen ──────────────────────────────────────────────────────────── */

body.stage { position: relative; }

.glow {
  position: absolute; top: -220px; left: 50%; margin-left: -420px;
  width: 840px; height: 840px; border-radius: 999px;
  background: radial-gradient(circle, rgba(15, 164, 127, 0.20) 0%, rgba(15, 164, 127, 0) 62%);
  pointer-events: none;
}

.screen {
  position: relative;
  height: 100%;
  display: flex;
  flex-direction: column;
  padding: clamp(24px, 4vh, 40px) clamp(24px, 5vw, 56px);
  gap: clamp(12px, 2vh, 22px);
}

.top { display: flex; align-items: center; justify-content: space-between; gap: 16px; }

/* Read from the back of the room, so it scales with the screen rather than sitting
   at one size: a projector and an iPad on a stand open the very same page. */
.top .logo { width: clamp(150px, 15vw, 260px); flex-shrink: 0; }

.room {
  font-family: 'JetBrains Mono', monospace;
  font-size: 12px; font-weight: 500; letter-spacing: 0.14em; color: var(--muted);
  text-align: right;
}

.now { display: flex; flex-direction: column; gap: 12px; }

.pill {
  align-self: flex-start;
  display: flex; align-items: center; gap: 12px;
  height: 40px; padding: 0 20px; border-radius: 999px;
  background: rgba(15, 164, 127, 0.16);
  border: 1px solid rgba(15, 164, 127, 0.42);
  font-family: 'JetBrains Mono', monospace;
  font-size: 14px; font-weight: 700; letter-spacing: 0.14em; color: var(--teal);
}
.pill .dot { width: 9px; height: 9px; border-radius: 999px; background: var(--teal); }

.pill.shut {
  background: rgba(255, 255, 255, 0.06);
  border-color: var(--hair);
  color: var(--dim);
}
.pill.shut .dot { background: var(--muted); }

.session { display: flex; align-items: baseline; gap: 20px; flex-wrap: wrap; }

.when { font-family: 'JetBrains Mono', monospace; font-size: 20px; font-weight: 500; color: var(--teal); }

.title {
  font-family: 'Sora', sans-serif;
  font-size: clamp(22px, 3.2vw, 30px); font-weight: 600; letter-spacing: -0.02em;
  line-height: 1.2; margin: 0;
  text-wrap: balance;
}

.people {
  font-family: 'JetBrains Mono', monospace;
  font-size: 15px; color: var(--dim);
  min-height: 1em;
}

.codearea {
  flex-grow: 1;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: clamp(14px, 2.5vh, 26px);
}

.digits { display: flex; align-items: center; gap: clamp(8px, 1.2vw, 18px); }

.cell {
  width: clamp(64px, 8.5vw, 112px);
  height: clamp(88px, 17vh, 152px);
  border-radius: 16px;
  background: var(--cell);
  border: 1px solid var(--hair);
  display: flex; align-items: center; justify-content: center;
  font-family: 'JetBrains Mono', monospace;
  font-size: clamp(48px, 7vw, 92px);
  font-weight: 500;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.cell.gapbefore { margin-left: clamp(10px, 1.6vw, 24px); }

.cell.turn { animation: turn 260ms ease-out; }

@keyframes turn {
  from { opacity: 0.25; transform: translateY(-6px); }
  to { opacity: 1; transform: none; }
}

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

.instruction {
  margin: 0;
  font-size: clamp(15px, 1.7vw, 22px);
  color: var(--dim);
  text-align: center;
}

.bottom { display: flex; align-items: center; justify-content: space-between; gap: 24px; }

.countdown {
  display: flex; align-items: center; gap: 18px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 15px; letter-spacing: 0.08em; color: var(--dim);
}

#ring { transition: stroke-dashoffset 250ms linear; }

.tally { display: flex; align-items: baseline; gap: 12px; }

.count {
  font-family: 'Sora', sans-serif;
  font-size: 44px; font-weight: 600; line-height: 1; letter-spacing: -0.03em; color: var(--teal);
}

.countlabel {
  font-family: 'JetBrains Mono', monospace;
  font-size: 12px; letter-spacing: 0.14em; color: var(--muted);
}

/*
 * Out of touch with the server. The codes are already here and stay correct, so the screen
 * keeps working — this only says that what is ON may be out of date. Deliberately quiet:
 * nobody in the back row needs to read it, and the person who does will come and look.
 */
body.stale .room::after {
  content: ' · OFFLINE';
  color: #DCA53F;
}

/* ── The printed fallback ────────────────────────────────────────────────── */

@media print {
  body { background: #FFFFFF; color: #000000; overflow: visible; }
  .glow, .codearea, .bottom, .pill { display: none; }
}

/*
 * The way back off the screen.
 *
 * The screen carries the code and nothing else, because it goes on a projector in front of
 * a room — but it is also opened on the phone of whoever set it up, and twice now there was
 * no way back from there. So: shown on load so it is discoverable, faded after a few seconds
 * so it is not furniture, and brought back by any touch, mouse move or key.
 */
.wayback {
  /* Top centre: the four corners already hold the lockup, the room name, the countdown
     and the tally, and a transient control has no business overlapping any of them. */
  position: fixed;
  top: calc(14px + env(safe-area-inset-top, 0px));
  left: 50%;
  transform: translateX(-50%);
  z-index: 10;
  display: inline-flex;
  align-items: center;
  padding: 10px 16px;
  border-radius: 999px;
  background: rgba(6, 14, 40, 0.72);
  border: 1px solid var(--hair);
  color: var(--ink);
  text-decoration: none;
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  transition: opacity 500ms ease;
}

.wayback.faded { opacity: 0; pointer-events: none; }

/* Keyboard focus always wins: a control nobody can tab to is a control that is not there. */
.wayback:focus-visible {
  opacity: 1;
  pointer-events: auto;
  outline: 2px solid var(--teal);
  outline-offset: 2px;
}

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

/* ── The gatekeeper's own page ───────────────────────────────────────────── */
/*
 * Held in one hand, in a room, by somebody who is also watching a speaker. So: few
 * things on screen, one obvious action, and targets big enough to hit without looking.
 * Same navy as the screen on the wall, because it is the same job and the same account.
 */

body.keeper { overflow: auto; }

.sheetpage {
  max-width: 560px;
  margin: 0 auto;
  padding: 28px 20px 56px;
  display: flex;
  flex-direction: column;
  gap: 22px;
}

.khead { display: flex; align-items: center; justify-content: space-between; gap: 16px; }
.khead .logo { width: 150px; }

.block { display: flex; flex-direction: column; gap: 10px; }

.ey {
  font-family: 'JetBrains Mono', monospace;
  font-size: 10px; font-weight: 700; letter-spacing: 0.16em; color: var(--muted);
}
.ey.teal { color: var(--teal); }

.ktitle {
  font-family: 'Sora', sans-serif;
  font-size: 26px; font-weight: 600; letter-spacing: -0.02em; line-height: 1.15;
  margin: 0; text-wrap: balance;
}

.kmeta { margin: 0; font-family: 'JetBrains Mono', monospace; font-size: 12px; color: var(--dim); }
.kcount { margin: 6px 0 4px; font-size: 15px; color: var(--ink); }
.kcount strong { font-family: 'JetBrains Mono', monospace; font-size: 22px; color: var(--teal); }

.hint { margin: 0; font-size: 13px; color: var(--dim); line-height: 1.5; }
.hint a { color: var(--teal); }

/* A thumb, in a room, not looking down. Nothing here is smaller than 52px. */
.btn {
  width: 100%;
  min-height: 56px;
  border: 0;
  border-radius: 999px;
  font: inherit;
  font-size: 16px;
  font-weight: 600;
  cursor: pointer;
  margin-top: 6px;
}
.btn.start { background: var(--teal); color: var(--navy); }
.btn.stop { background: #E8542E; color: #FFFFFF; }

/* Stopping is a two-step now, so the first step is a link rather than a submit. An anchor
   has no intrinsic box, so it takes the button's height and centring explicitly. */
a.btn {
  display: flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  text-decoration: none;
}

/* The second ask. It says what stopping costs, on the page rather than in a browser
   dialog a thumb dismisses without reading (Rosa, 2026-09-24). */
.confirm {
  margin-top: 10px;
  padding: 16px;
  border-radius: 18px;
  background: rgba(232, 84, 46, 0.09);
  border: 1.5px solid rgba(232, 84, 46, 0.45);
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.confirm .ctitle { margin: 0; font-size: 17px; font-weight: 600; color: var(--ink); }
.confirm .cwhy { margin: 0; font-size: 14px; line-height: 1.45; color: var(--ink); }
.confirm .cwhy strong { font-weight: 600; color: #E8542E; }
.crow { display: flex; gap: 8px; margin-top: 6px; }
.crow form { flex: 1; }
.crow .btn { margin-top: 0; }
.btn.cancel {
  flex: 1;
  background: transparent;
  border: 1.5px solid var(--hair);
  color: var(--ink);
}

.correct { margin-top: 18px; display: flex; flex-direction: column; gap: 8px; }
.nudges { display: flex; gap: 8px; }
.nudges form { flex: 1; }
.btn.nudge {
  min-height: 52px;
  background: transparent;
  border: 1.5px solid var(--hair);
  color: var(--ink);
  font-family: 'JetBrains Mono', monospace;
  font-size: 13px;
  margin-top: 0;
}

.klist { list-style: none; margin: 0; padding: 0; }
.klist li {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  padding: 14px 0; border-bottom: 1px solid var(--hair);
}
.klist li:first-child { border-top: 1px solid var(--hair); }
.lt { font-size: 15px; font-weight: 500; }
.lm { font-family: 'JetBrains Mono', monospace; font-size: 11px; color: var(--muted); margin-top: 3px; }

/* inline-flex, so a chip centres its own text rather than letting it ride the top of a
   box some taller neighbour stretched (Rosa, 2026-09-25). */
.chip {
  display: inline-flex;
  align-items: center;
  font-family: 'JetBrains Mono', monospace;
  font-size: 9px; font-weight: 700; letter-spacing: 0.12em;
  padding: 5px 9px; border-radius: 6px; white-space: nowrap; flex-shrink: 0;
}
.chip.done { background: rgba(255, 255, 255, 0.08); color: var(--muted); }
.chip.now { background: var(--teal); color: var(--navy); }
.chip.later { border: 1px solid var(--hair); color: var(--muted); }

/* SCOPED TO THE PARAGRAPH deliberately. As a bare `.done` this collided with the roster's
   `.chip.done` — the small "OUT 19:44" pill — because it is declared later in the file and
   sets the properties `.chip.done` does not: padding, font-size, border-radius. So a row
   grew a pill half again as large the moment somebody was checked out, and only then.
   Found by Rosa on the desk, 2026-09-24. Same shape as `.people` colliding with the room
   screen's speakers line in September; the rule in CLAUDE.md about cascade collisions is
   there because of this exact family. */
p.done {
  margin: 0;
  background: rgba(15, 164, 127, 0.14);
  border: 1px solid rgba(15, 164, 127, 0.4);
  border-radius: 12px;
  padding: 12px 14px;
  color: #CFEFE4;
  font-size: 13.5px;
  line-height: 1.5;
}

/* ── The timings report ──────────────────────────────────────────────────── */

.sheetpage.wide { max-width: 860px; }

.tablewrap { overflow-x: auto; }

table.report { width: 100%; border-collapse: collapse; font-size: 14px; }
table.report th {
  text-align: left;
  font-family: 'JetBrains Mono', monospace;
  font-size: 10px; font-weight: 700; letter-spacing: 0.14em; color: var(--muted);
  padding: 0 14px 10px 0; border-bottom: 1px solid var(--hair); white-space: nowrap;
}
table.report td {
  padding: 13px 14px 13px 0;
  border-bottom: 1px solid var(--hair);
  vertical-align: top;
}
table.report .s-title { font-weight: 500; min-width: 10ch; }
table.report .mono { font-family: 'JetBrains Mono', monospace; font-variant-numeric: tabular-nums; white-space: nowrap; }
table.report .dim { color: var(--dim); }
table.report .sub { color: var(--muted); font-size: 11px; }
table.report .warn { color: #DCA53F; }

/* Marked, not alarming: a session running late is ordinary, and the point of the
   design is that it costs nobody their credit. */
table.report tr.notable td { background: rgba(220, 165, 63, 0.07); }

/* ── The desk: where signing in lands ────────────────────────────────────── */
/*
 * The screen deliberately does not navigate — it goes on a projector in front of a room,
 * so it carries the code and nothing else. This is the page that links to everything,
 * and the one to bookmark on the device in your hand.
 */

.live {
  font-family: 'JetBrains Mono', monospace;
  font-size: 10px; font-weight: 700; letter-spacing: 0.14em;
  color: var(--navy); background: var(--teal);
  padding: 3px 7px; border-radius: 5px; margin-right: 6px;
}

.choices { display: flex; flex-direction: column; gap: 12px; }

.choice {
  display: flex; flex-direction: column; gap: 5px;
  padding: 18px 20px;
  border: 1px solid var(--hair);
  border-radius: 16px;
  text-decoration: none;
  color: var(--ink);
  background: rgba(255, 255, 255, 0.03);
}
.choice:hover, .choice:focus-visible { border-color: var(--teal); background: rgba(15, 164, 127, 0.08); }
.choice:focus-visible { outline: 2px solid var(--teal); outline-offset: 2px; }

.ch-t { font-family: 'Sora', sans-serif; font-size: 18px; font-weight: 600; letter-spacing: -0.015em; }
.ch-s { font-size: 13px; line-height: 1.5; color: var(--dim); }

/* ── The desk: finding a person and recording them by hand ───────────────── */

/*
 * The way back, in the header rather than at the foot of the page.
 *
 * The screen's way back is a chip that fades, because the screen is furniture in front of
 * an audience. These pages are the opposite: held in a hand, read top to bottom, and the
 * person using one is navigating. A link at the bottom of a long roster is not a way back,
 * which is how the rooms list became unreachable once a desk had been bookmarked.
 */
.crumb {
  display: inline-flex; align-items: center;
  padding: 10px 14px 10px 0;
  color: var(--dim);
  text-decoration: none;
  font-family: 'JetBrains Mono', monospace;
  font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.crumb:hover, .crumb:focus-visible { color: var(--teal); }
.crumb:focus-visible { outline: 2px solid var(--teal); outline-offset: 2px; border-radius: 6px; }

/* The header holds the crumb first and the lockup second on these pages, so the way back
   sits where a thumb already is and the mark stays where it is on every other page. */
.khead .crumb + .logo { margin-left: auto; }

.find { display: flex; gap: 8px; align-items: stretch; }
.find input {
  flex: 1; min-width: 0;
  background: var(--cell);
  border: 1.5px solid var(--hair);
  border-radius: 12px;
  padding: 0 14px;
  min-height: 56px;
  color: var(--ink);
  font: inherit; font-size: 16px; /* 16px or iOS zooms the page on focus */
}
.find input::placeholder { color: var(--muted); }
.find input:focus-visible { outline: 2px solid var(--teal); outline-offset: 1px; }
.btn.find-go { width: auto; padding: 0 22px; margin-top: 0; background: var(--teal); color: var(--navy); }

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* Not `.people`: the room screen already owns that name for its speakers line, and
   it sets a mono face that this list silently inherited. */
.roster { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 10px; }

.person {
  display: flex; flex-direction: column; gap: 12px;
  padding: 16px 18px;
  border: 1px solid var(--hair);
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.03);
}

.p-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
/* align-items CENTRE, not the default stretch: a button beside them is taller than a chip,
   and stretching made every pill that button's height with its text at the top. */
.p-chips { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 6px; }

/* Said apart from the teal of a code that was typed. Weaker evidence has to look
   weaker everywhere it is read, not only in the export. */
.chip.hand { border: 1px solid rgba(232, 84, 46, 0.55); color: #F0A48C; }
/* Registered, no badge collected. Said rather than left as the absence of a pill. */
.chip.pale { border: 1px solid var(--hair); color: var(--muted); }
/* Late is information, not an accusation: amber rather than the red of a fault, and never
   the teal that means presence. */
.chip.late { border: 1px solid rgba(232, 168, 46, 0.5); color: #E8B45E; }

.p-actions { display: flex; flex-direction: column; gap: 8px; }

.btn.small {
  min-height: 52px; margin-top: 0;
  background: transparent;
  border: 1.5px solid var(--hair);
  color: var(--ink);
  font-size: 15px;
}
.btn.small.undo { color: var(--dim); }
.btn.small.go { background: var(--teal); color: var(--navy); border-color: var(--teal); }

/* A summary styled as a button: it opens the reason, so it must not look like the
   thing that records it — the record is the button underneath, after a sentence. */
dialog.sheet label {
  font-family: 'JetBrains Mono', monospace;
  font-size: 10px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--dim);
}
dialog.sheet input[type="text"] {
  background: var(--cell);
  border: 1.5px solid var(--hair);
  border-radius: 12px;
  padding: 0 14px; min-height: 52px;
  color: var(--ink);
  font: inherit; font-size: 16px;
}
dialog.sheet input[type="text"]::placeholder { color: var(--muted); }
dialog.sheet input[type="text"]:focus-visible { outline: 2px solid var(--teal); outline-offset: 1px; }

@media (max-width: 460px) {
  .p-head { flex-direction: column; gap: 8px; }
  .p-chips { justify-content: flex-start; }
}

/* ── The day, in the order it happens ────────────────────────────────────── */
/*
 * Replaces a single "next to start" card. That card was driven by a QUEUE — the first
 * session nobody had started — and a queue gets stuck: one missed session sat at the front
 * of it all day and the obvious button offered a talk that had finished hours ago.
 *
 * No pinned header (Rosa, 2026-09-24): the list is short enough for a room's day, and a
 * panel that is always on screen eats the phone it is held on.
 */
.day { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 8px; }

.slot {
  border: 1px solid var(--hair);
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.03);
  overflow: hidden;
}

.slot-head {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 14px 16px;
  color: var(--ink);
  text-decoration: none;
}
a.slot-head:hover, a.slot-head:focus-visible { background: rgba(15, 164, 127, 0.08); }
a.slot-head:focus-visible { outline: 2px solid var(--teal); outline-offset: -2px; }

/* The one the buttons act on. */
.slot.chosen { border-color: var(--teal); background: rgba(15, 164, 127, 0.06); }

/* Needs nothing from anybody: a break, or anything worth no credit. Set BACK rather than
   hidden, because "where are we in the day" is the question this list answers.
 *
 * It used to be `opacity: 0.55` and `0.45` on the whole row, and that made the list barely
 * readable unless a session was live (Rosa, 2026-09-24). Opacity is the wrong instrument
 * here on two counts: it fades the STATE CHIP along with everything else, so the one word
 * telling you where the day is — ENDED, NEVER STARTED — went with it; and at 0.45 the meta
 * line's #7C87A8 on the navy ground falls to about 1.6:1, which is not a contrast ratio,
 * it is a rumour.
 *
 * Colour does the same job and stays legible: the title steps back from white to --dim
 * (about 5:1 on this ground), the row's fill flattens, and the chip keeps its full
 * strength because it is the part you are scanning for. */
.slot.idle .lt,
.slot.past .lt { color: var(--dim); font-weight: 400; }
.slot.idle,
.slot.past { background: rgba(255, 255, 255, 0.015); }
/* The state word stays readable on a row that is over — it is what the row is FOR. */
.slot.past .chip.done,
.slot.idle .chip.done { color: var(--dim); }

.slot-body { padding: 0 16px 16px; display: flex; flex-direction: column; gap: 4px; }

.hint.warn { color: #F0A48C; }

/* ── The register as a list, not a search result (Rosa, 2026-09-24) ──
   It used to show nothing until somebody typed. A desk works DOWN a register, and a list
   you can only reach by guessing a spelling cannot tell somebody who is not registered
   from somebody whose name you typed wrong. The search narrows it now rather than
   summoning it, so the page needs a count, a few facts per person, and a pager. */

.rcount {
  margin: 14px 0 2px;
  font-size: 13px;
  color: var(--dim);
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  align-items: baseline;
}
.rcount strong {
  font-family: 'JetBrains Mono', monospace;
  font-size: 15px;
  color: var(--ink);
}
.rcount .rof { font-family: 'JetBrains Mono', monospace; font-size: 12px; }

.p-who { min-width: 0; }

/* Enough to tell two people with the same surname apart, without becoming a table. */
.p-facts { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 7px; }
.fact {
  font-family: 'JetBrains Mono', monospace;
  font-size: 10.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: 5px;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--hair);
  color: var(--dim);
  white-space: nowrap;
}
/* Somebody attending remotely is not missing from the room. Marked, because checking them
   in by hand at the door would be a false record. */
.fact.online {
  color: #7FB2FF;
  border-color: rgba(127, 178, 255, 0.45);
  background: rgba(127, 178, 255, 0.10);
}

.find-clear {
  width: auto;
  padding: 0 18px;
  margin-top: 0;
  background: transparent;
  border: 1.5px solid var(--hair);
  color: var(--dim);
  display: flex;
  align-items: center;
  text-decoration: none;
}

.pager {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-top: 18px;
}
.pager .btn.small { width: auto; padding: 0 16px; margin-top: 0; text-decoration: none; }
.pager .btn.small.disabled { opacity: 0.35; pointer-events: none; }
.pnum {
  font-family: 'JetBrains Mono', monospace;
  font-size: 12px;
  color: var(--dim);
  white-space: nowrap;
}


/* ── The register, laid out as a list to work down (Rosa, 2026-09-24) ──
   It was a stack of tall cards with full-width buttons, which is right for one search
   result on a phone and wrong for a register somebody reads top to bottom. Wider, tighter,
   and the actions sit at the end of the row rather than across it. */

.sheetpage.register { max-width: 1040px; }

.register .roster { gap: 6px; }

.register .person {
  padding: 9px 14px;
  gap: 8px;
  border-radius: 12px;
}

/* Who, then what is true of them, then what can be done — on one line. */
.register .p-row {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
}
.register .p-head { flex: 1 1 340px; align-items: center; gap: 16px; }
.register .p-who { flex: 1 1 auto; }
.register .p-chips { justify-content: flex-end; flex: 0 1 auto; }
.register .p-facts { margin-top: 4px; }
.register .lt { font-size: 16px; }
.register .lm { font-size: 12.5px; }

/* Actions end the row; they are not the row. */
.register .p-actions {
  flex: 0 0 auto;
  flex-direction: row;
  align-items: flex-start;
  gap: 8px;
  flex-wrap: wrap;
}
.register .p-actions .btn.small {
  width: auto;
  min-height: 38px;
  padding: 0 14px;
  font-size: 13.5px;
  white-space: nowrap;
}
/* The reason still needs room to be typed in, so the form keeps its own width. */
.register dialog.sheet input[type="text"] { min-height: 42px; font-size: 15px; }

@media (max-width: 720px) {
  /* A phone in a hand: back to a stack, and the actions go full width again because a
     thumb needs the target more than the page needs the density. */
  .register .p-row { align-items: flex-start; }
  .register .p-actions { flex: 1 1 100%; }
  .register .p-actions .btn.small { width: 100%; }
}

/* The reason, chosen rather than typed (Rosa, 2026-09-24). A blank box at a door gets the
   same four words forty times; a choice can be counted, which is the anomaly report the
   design asks for. "Other" keeps the sentence where it is actually worth something. */
/* Scoped to the dialog, which is where these controls now live. They were scoped to the
   inline <details> that used to hold them, so when the markup moved the styling stayed
   behind and the dropdown rendered as a raw white control (Rosa, 2026-09-25). */
dialog.sheet select {
  background: var(--cell);
  border: 1.5px solid var(--hair);
  border-radius: 12px;
  padding: 0 12px;
  min-height: 42px;
  color: var(--ink);
  font: inherit;
  font-size: 15px;
  width: 100%;
  appearance: none;
  background-image: linear-gradient(45deg, transparent 50%, var(--dim) 50%),
                    linear-gradient(135deg, var(--dim) 50%, transparent 50%);
  background-position: calc(100% - 18px) 50%, calc(100% - 13px) 50%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat;
  padding-right: 34px;
}
dialog.sheet select:focus-visible { outline: 2px solid var(--teal); outline-offset: 1px; }
dialog.sheet select:invalid { color: var(--muted); }
dialog.sheet .other { display: flex; flex-direction: column; gap: 8px; }
dialog.sheet .other[hidden] { display: none; }

/* ---------------------------------------------------------------------------
   The register, folded around the person (Rosa, 2026-09-25).

   The page's subject is a PERSON, so their day lives inside their own row and
   stays out of the way until somebody opens it. It replaced a switcher above
   the list, which made the SESSION the subject: to see whether somebody was in
   the keynote you first had to put the whole page into keynote mode.
   --------------------------------------------------------------------------- */
.register .pfold > summary {
  cursor: pointer;
  list-style: none;
}
.register .pfold > summary::-webkit-details-marker { display: none; }

/* A chevron, so a row reads as something that opens before anybody taps it. */
.register .pfold > summary::after {
  content: "";
  flex: 0 0 auto;
  width: 8px;
  height: 8px;
  margin-left: 4px;
  border-right: 2px solid var(--muted);
  border-bottom: 2px solid var(--muted);
  transform: rotate(45deg);
  transition: transform 120ms ease;
}
.register .pfold[open] > summary::after { transform: rotate(-135deg); }
.register .pfold > summary:focus-visible { outline: 2px solid var(--teal); outline-offset: 3px; }

.register .pbody {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--hair);
}

.sessions { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 6px; }

.sess {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 9px 12px;
  border: 1px solid var(--hair);
  border-radius: 10px;
}
/* Still inside is the one state a desk is scanning for. */
.sess.in { border-color: rgba(15, 164, 127, 0.55); }

/* The name leads; what the room did with it sits out at the right, on the same line —
   one row instead of three, and the states line up down the list. Everything below starts
   at the name's own edge, so the eye has one left margin to follow (Rosa, 2026-09-25). */
.s-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.s-head .lt { min-width: 0; flex: 1 1 auto; }
.fact.live { color: var(--teal); border-color: rgba(15, 164, 127, 0.55); }

/* Both windows: what the programme printed, and what the room actually did. A record
   showing only one cannot be checked against the other, and the REAL pair is the one
   somebody is reading for, so it gets the brighter ink (Rosa, 2026-09-24). */
.s-times {
  display: flex;
  flex-wrap: wrap;
  gap: 2px 16px;
  margin: 0;
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 13px;
  color: var(--muted);
}
.s-times .real { color: var(--ink); }
.tlab {
  margin-right: 6px;
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  opacity: 0.8;
}
.s-none { margin: 0; font-size: 13px; color: var(--dim); }

/* Every visit, oldest first — not only the newest. Somebody in and out twice looked
   identical to somebody in once, and weaker evidence should never be invisible. */
.visits { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 5px; }
/* When it happened, and — kept apart — how it came to be recorded. By hand is weaker
   evidence and must not read as one more timing pill. */
.visits li {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 6px 16px;
}
.v-when, .v-how { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.v-how { justify-content: flex-end; }
/* Typed by the attendee: stated, not left as an absence. Two visits that differ only in
   how they were recorded looked identical when one of them showed nothing. */
.chip.typed { border: 1px solid var(--hair); color: var(--muted); }
.chip.open { background: rgba(15, 164, 127, 0.18); color: var(--teal); }
.vmins {
  font-family: "JetBrains Mono", ui-monospace, monospace;
  font-size: 12.5px;
  color: var(--muted);
}
.vwhy { font-size: 12.5px; color: var(--dim); }

.sess .btn.small { align-self: flex-start; }

/* The by-hand confirmation, in the page rather than a browser confirm(): unstyled,
   weak on a phone, and invisible to the automation that walks this screen. */
dialog.sheet {
  width: min(460px, calc(100vw - 32px));
  border: 1px solid var(--hair);
  border-radius: 16px;
  background: var(--navy);
  color: var(--ink);
  padding: 20px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.5);
}
dialog.sheet::backdrop { background: rgba(6, 12, 28, 0.66); }
dialog.sheet form { display: flex; flex-direction: column; gap: 10px; }
.dtitle { margin: 0; font-family: Sora, system-ui, sans-serif; font-size: 18px; }
.dwho { margin: 0; color: var(--muted); font-size: 14px; }
.dbtns { display: flex; gap: 8px; justify-content: flex-end; margin-top: 4px; }


/* The conference check-in's own actions, among the chips on the closed row, so they have
   to be chip-sized rather than the full-width control .btn is by default. */
.register .p-chips .btn.small.arrive {
  width: auto;
  min-height: 30px;
  padding: 0 12px;
  font-size: 12.5px;
  white-space: nowrap;
}

.btn.ghost { background: transparent; border: 1px solid var(--hair); color: var(--muted); }

@media (max-width: 720px) {
  .s-head { align-items: flex-start; }
  .sess .btn.small { align-self: stretch; width: 100%; }
  .dbtns { flex-direction: column-reverse; }
  .dbtns .btn { width: 100%; }
}
