:root {
  --board-bg: #0c0c0f;
  --cell-bg: #17171b;
  --cell-text: #f5c518;
  --seam: rgba(0, 0, 0, 0.65);
  --panel-bg: #1c1c22;
  /* total width (cell + margin) of one split-flap character cell */
  --flap-w: 27px;
  --row-gap: 0.5rem;
}

* {
  box-sizing: border-box;
}

html, body {
  margin: 0;
  height: 100%;
  background: var(--board-bg);
  color: #eee;
  /* Applies everywhere by inheritance (buttons, header, the message-detail
     overlay, etc.) so the whole board reads consistently — the .flap tiles
     and idle-screen elements no longer need their own override for this. */
  font-family: 'Atkinson Hyperlegible', Arial, sans-serif;
}

#start-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.92);
  z-index: 100;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1rem;
}

#start-overlay button {
  font-size: 1.8rem;
  padding: 1rem 2rem;
  border-radius: 12px;
  border: none;
  background: var(--cell-text);
  color: #111;
  font-weight: 700;
  cursor: pointer;
}

#start-overlay p {
  color: #ccc;
  font-size: 1.1rem;
}

#start-overlay.hidden {
  display: none;
}

.board-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 1rem 2rem;
  border-bottom: 2px solid #2a2a30;
}

.board-header h1 {
  font-size: 2rem;
  margin: 0;
  letter-spacing: 0.05em;
}

.header-right {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  font-size: 1.4rem;
}

#clock {
  font-variant-numeric: tabular-nums;
  color: var(--cell-text);
}

.pill-button {
  background: none;
  border: 1px solid #444;
  border-radius: 999px;
  color: #ccc;
  font-size: 0.95rem;
  padding: 0.3rem 0.9rem;
  cursor: pointer;
}

.pill-button:hover {
  border-color: var(--cell-text);
  color: var(--cell-text);
}

.status {
  font-size: 1rem;
  padding: 0.3rem 0.8rem;
  border-radius: 999px;
}

.status.online {
  background: #1e5c2f;
  color: #b7f7c4;
}

.status.offline {
  background: #5c1e1e;
  color: #f7b7b7;
}

.muted-indicator {
  font-size: 1rem;
  padding: 0.3rem 0.8rem;
  border-radius: 999px;
  background: #3a3420;
  color: #e8d27a;
  font-weight: 700;
}

main {
  padding: 1rem 2rem 2rem;
}

.column-labels {
  display: grid;
  grid-template-columns: calc(8 * var(--flap-w)) calc(1 * var(--flap-w)) calc(16 * var(--flap-w)) 1fr;
  gap: var(--row-gap);
  color: #888;
  font-size: 0.9rem;
  letter-spacing: 0.1em;
  padding: 0 0.25rem 0.5rem;
  border-bottom: 1px solid #2a2a30;
  margin-bottom: 1rem;
}

/* The gap between SENDER and MESSAGE only ever got the grid's normal
   column gap, while TIME-to-SENDER also has a whole blank channel tile
   sitting between them — so despite the same `gap`, TIME-to-SENDER always
   read as the wider space. Stretching the message column's start by that
   same tile width (plus one more row-gap, since the tile itself sits
   between two row-gaps) makes the two gaps actually match. */
.column-labels .col-body {
  margin-left: calc(var(--flap-w) + var(--row-gap));
}

#board {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
}

.row {
  display: grid;
  grid-template-columns: calc(8 * var(--flap-w)) calc(1 * var(--flap-w)) calc(16 * var(--flap-w)) 1fr auto;
  gap: var(--row-gap);
  align-items: start;
}

.row .flap-group:nth-child(4) {
  margin-left: calc(var(--flap-w) + var(--row-gap));
}

/* Read messages dim rather than disappear — reversible, so no scary
   per-message confirmation is needed. "Clear read" removes them in bulk. */
.row.read {
  opacity: 0.35;
}

.row-actions {
  display: flex;
  gap: 0.4rem;
  align-self: center;
}

/* Learning Difficulties boards only: the same category icon shown on the
   idle screen's now/next card (see event-categories.js), sitting in the
   actions strip just left of whatever confirm/ack button the row has. */
.row-icon {
  font-size: 1.8rem;
  line-height: 1;
  align-self: center;
  margin-right: 0.2rem;
}

.read-btn,
.ack-btn {
  background: none;
  border: 1px solid #3a3a42;
  border-radius: 8px;
  font-size: 1.2rem;
  min-width: 2.6rem;
  height: 1.9em;
  cursor: pointer;
}

.ack-btn {
  color: #9a9;
}

/* Testing feedback: the read/unread tick needed to read brighter than the
   muted sage-green it shared with the ack button — a clean white instead. */
.read-btn {
  color: #fff;
}

.read-btn:hover {
  border-color: #7de3b8;
  color: #7de3b8;
}

.ack-btn:hover:not(:disabled) {
  border-color: var(--cell-text);
}

.ack-btn:disabled {
  opacity: 0.6;
  cursor: default;
}

/* Scheduled tasks flap in blue; the Mark done button is deliberately the
   loudest control on the board — it's the one an elderly user must find. */
.row.channel-task .flap {
  color: #6db3f2;
}

.task-done-btn {
  background: #6db3f2;
  border: none;
  border-radius: 8px;
  color: #0c0c0f;
  font-weight: 700;
  font-size: 1rem;
  padding: 0 0.9rem;
  height: 1.9em;
  cursor: pointer;
  white-space: nowrap;
}

.task-done-btn:hover:not(:disabled) {
  filter: brightness(1.2);
}

/* Immediate feedback that a tap registered, applied right on click — before
   the server confirms and the row itself flips to the done state. Reuses
   the same green already used for the eventual "✓ Done" label so the two
   read as one continuous state, not two different colours. */
.task-done-btn.confirmed {
  background: #7de3b8;
  cursor: default;
}

.task-done-label {
  color: #7de3b8;
  font-weight: 700;
  align-self: center;
  white-space: nowrap;
}

.row.task-done {
  opacity: 0.7;
}

#clear-read {
  background: none;
  border: 1px solid #444;
  border-radius: 999px;
  color: #ccc;
  font-size: 0.95rem;
  padding: 0.3rem 0.9rem;
  cursor: pointer;
}

#clear-read:hover {
  border-color: #ff5c5c;
  color: #ff5c5c;
}

.flap-group {
  display: flex;
  flex-wrap: wrap;
  row-gap: 2px;
}

.flap {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: calc(var(--flap-w) - 2px);
  height: 1.9em;
  margin-right: 2px;
  background: var(--cell-bg);
  color: var(--cell-text);
  font-weight: 700;
  font-size: 1.5rem;
  border-radius: 3px;
  overflow: hidden;
  box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.85), 0 1px 0 rgba(255, 255, 255, 0.03);
  perspective: 200px;
}

.flap::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 0;
  right: 0;
  height: 1px;
  background: var(--seam);
  z-index: 2;
}

.flap .char {
  display: inline-block;
}

.flap.flip .char {
  animation: flapFlip 0.22s ease-in;
}

@keyframes flapFlip {
  0% { transform: rotateX(0deg); }
  50% { transform: rotateX(-90deg); }
  51% { transform: rotateX(90deg); }
  100% { transform: rotateX(0deg); }
}

.row.new {
  animation: rowIn 0.4s ease-out;
}

@keyframes rowIn {
  from { opacity: 0; transform: translateY(-6px); }
  to { opacity: 1; transform: translateY(0); }
}

#idle-view {
  display: flex;
  flex-direction: column;
  min-height: calc(100vh - 6rem);
  gap: 1.25rem;
}

#idle-view[hidden] {
  display: none;
}

.idle-top {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6rem;
  /* Top padding cut well below the bottom's: the space above the clock was
     dead air pushing the week-ahead button (LD boards) off the bottom of
     real kiosk screens — see week-ahead-btn-row below. */
  padding: 0.25rem 0.5rem 1.5rem;
}

.idle-clock-block {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.75rem;
}

.idle-clock {
  font-variant-numeric: tabular-nums;
  font-size: 5rem;
  font-weight: 700;
  color: var(--cell-text);
  letter-spacing: 0.05em;
}

.idle-clock-analogue[hidden] {
  display: none;
}

/* 150px, not the original 200px: at 200px the analogue face made this block
   ~110px taller than the digital clock, which was enough on its own to push
   the week-ahead button (LD boards) off the bottom of real kiosk screens
   when someone switched clock styles. Every measurement below is scaled by
   the same 0.75 so the face, ticks and hands stay proportional. */
.analogue-face {
  position: relative;
  width: 150px;
  height: 150px;
  border-radius: 50%;
  border: 3px solid var(--cell-text);
  background: var(--panel-bg);
}

.analogue-tick-wrap,
.hand-wrap {
  position: absolute;
  inset: 0;
}

.analogue-tick {
  position: absolute;
  top: 8px;
  left: 50%;
  width: 2px;
  height: 9px;
  background: #7d8790;
  transform: translateX(-50%);
}

.analogue-tick-major {
  top: 6px;
  width: 3px;
  height: 14px;
  background: var(--cell-text);
}

.hand {
  position: absolute;
  left: 50%;
  top: 50%;
  border-radius: 4px;
  background: var(--cell-text);
  transform: translate(-50%, -100%);
}

.hand-hour {
  width: 4px;
  height: 40px;
}

.hand-minute {
  width: 3px;
  height: 57px;
}

.hand-second {
  width: 2px;
  height: 63px;
  background: #e0524c;
}

.analogue-center {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--cell-text);
  transform: translate(-50%, -50%);
}

.idle-weather {
  display: flex;
  align-items: center;
  gap: 1rem;
  color: var(--cell-text);
  font-size: 1.2rem;
}

.idle-weather-icon {
  font-size: 3.5rem;
  line-height: 1;
}

.idle-weather-text {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
}

.idle-weather-temp {
  font-size: 2.2rem;
  font-weight: 700;
}

.idle-weather-desc {
  font-size: 1.2rem;
  color: #ccc;
}

.idle-weather-tip {
  font-size: 1.1rem;
  color: #ccc;
  font-style: italic;
  max-width: 32ch;
}

.idle-events {
  align-self: center;
  min-width: 340px;
  max-width: 700px;
  background: var(--panel-bg);
  border: 1px solid #2a2a30;
  border-radius: 12px;
  padding: 1.25rem 1.75rem;
}

.idle-events-title {
  color: #7de3b8;
  font-size: 0.9rem;
  font-weight: 700;
  letter-spacing: 0.15em;
  margin-bottom: 0.75rem;
}

.idle-event {
  display: flex;
  gap: 1.5rem;
  align-items: baseline;
  padding: 0.35rem 0;
  font-size: 1.35rem;
}

.idle-event-time {
  font-weight: 700;
  color: #7de3b8;
  min-width: 5.5ch;
}

.idle-event-title {
  color: #eee;
}

.idle-event-empty {
  color: #888;
  font-style: italic;
}

/* Learning Difficulties boards' idle now/next card — replaces .idle-events
   above (see households.js displayMode; only one of the two is ever shown
   for a given board). NOW is the large, promoted slot; NEXT stays quieter
   with a countdown, matching the elderly Today card's existing green/grey
   hierarchy so the two modes still feel like the same product. */
/* Wraps the events card and the (optional) carer photo panel side by side
   — the carer panel only ever appears when a carer_visit event is active,
   so this row still centers as a whole (via align-self below) when it's
   just the events card on its own, same position as before this existed. */
.idle-schedule-row {
  align-self: center;
  display: flex;
  flex-direction: row;
  align-items: flex-start;
  gap: 1.5rem;
  margin-top: -20px;
}

.idle-schedule {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  min-width: 340px;
  max-width: 700px;
}

/* An explicit display:flex above always beats the browser's own [hidden]
   styling (both are author/UA rules on the same element, and this one
   comes later) — same gotcha called out for .idle-news[hidden] elsewhere
   in this file, needs the same override here. */
.idle-schedule[hidden] {
  display: none;
}

/* Carer photo panel — its own show/hide timing (see app.js
   computeActiveCarer), independent of the NOW/NEXT/AFTER card next to it.
   "Quietly stops showing" is an opacity fade, not an abrupt display:none
   snap, so [hidden] alone can't drive this: JS toggles a .visible class
   ahead of/behind the hidden attribute — see the show/hide handling in
   app.js for why both exist together. */
.idle-carer {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.6rem;
  width: 180px;
  opacity: 0;
  transition: opacity 1.5s ease;
}

.idle-carer.visible {
  opacity: 1;
}

.idle-carer[hidden] {
  display: none;
}

.idle-carer-photo {
  width: 180px;
  height: 180px;
  border-radius: 50%;
  object-fit: cover;
  border: 3px solid #7de3b8;
}

.idle-carer-name {
  color: #eee;
  font-size: 1.3rem;
  font-weight: 700;
  text-align: center;
}

.ld-slot {
  display: flex;
  align-items: center;
  gap: 1rem;
  background: var(--panel-bg);
  border: 1px solid #2a2a30;
  border-radius: 12px;
}

.ld-slot[hidden] {
  display: none;
}

.ld-now {
  padding: 1.5rem 2rem;
  border-color: #7de3b8;
  background: rgba(125, 227, 184, 0.08);
}

.ld-next {
  padding: 0.9rem 1.5rem;
  opacity: 0.85;
}

/* AFTER reuses .ld-next's look (quiet, secondary) but a touch quieter
   still, so the eye reads NOW > NEXT > AFTER at a glance. */
.ld-after {
  opacity: 0.65;
}

.ld-tag {
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.15em;
  color: #7de3b8;
  align-self: flex-start;
}

.ld-next .ld-tag {
  color: #888;
}

.ld-icon {
  font-size: 2.4rem;
  line-height: 1;
}

.ld-next .ld-icon {
  font-size: 1.6rem;
}

.ld-title {
  color: #eee;
  font-size: 1.6rem;
  font-weight: 700;
}

.ld-next .ld-title {
  font-size: 1.15rem;
  font-weight: 400;
}

.ld-countdown {
  color: #888;
  font-size: 1rem;
  margin-left: auto;
}

.ld-empty {
  color: #888;
  font-style: italic;
  text-align: center;
}

/* "Rest of the week" button — opt-in per household, Learning Difficulties
   boards only (see households.js weekAheadEnabled). Sits directly under the
   NOW/NEXT/AFTER card, so it reads as "look further ahead" rather than a
   generic nav control. Bigger than the header's .pill-button controls
   (clock style, idle screen toggle) since this needs to be an easy, obvious
   tap target from a distance. */
.week-ahead-btn-row {
  align-self: center;
}

.week-ahead-btn {
  font-size: 1.2rem;
  padding: 0.7rem 1.6rem;
}

.week-ahead-btn[hidden] {
  display: none;
}

/* Broadcast notices (warden/office messages to many boards) flap in a soft
   violet — distinct from personal amber messages and green reminders. */
.row.channel-broadcast .flap {
  color: #c9a6f5;
}

/* Calendar reminders flap in green so they stand out from amber messages. */
.row.channel-calendar .flap {
  color: #7de3b8;
}

/* Alerts (# prefix or a device reporting level "alert") flap in red and
   pulse briefly. Declared after the channel colours so alert wins. */
.row.alert .flap {
  color: #ff5c5c;
}

.row.alert.new {
  animation: rowIn 0.4s ease-out, alertPulse 1.2s ease-in-out 3;
}

@keyframes alertPulse {
  0%, 100% { filter: brightness(1); }
  50% { filter: brightness(1.6); }
}

.idle-news[hidden] {
  display: none;
}

.idle-news {
  margin-top: auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem 2rem;
  padding: 1rem 0.5rem;
  border-top: 2px solid #2a2a30;
  color: var(--cell-text);
}

.idle-news-item {
  font-size: 1.2rem;
  background: none;
  border: none;
  color: var(--cell-text);
  font-family: inherit;
  padding: 0;
  cursor: pointer;
  text-align: left;
}

.idle-news-item:hover {
  text-decoration: underline;
}

.idle-news-item:not(:last-child)::after {
  content: '•';
  margin-left: 2rem;
  color: #555;
  text-decoration: none;
  display: inline-block;
}

#story-overlay,
#message-overlay,
#confirm-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.85);
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
}

#story-overlay[hidden],
#message-overlay[hidden],
#confirm-overlay[hidden] {
  display: none;
}

/* "Rest of the week" full-screen view — deliberately covers everything
   underneath (the clock, carer photo, NOW/NEXT/AFTER card) rather than
   sitting as a centered card like the other overlays above: the whole
   point is a run of near-full-screen day-cards the reader swipes through,
   clearly separate from "today". z-index above the other overlays since,
   unlike them, it's opened directly from the idle screen rather than from
   inside another overlay. */
#week-ahead-overlay {
  position: fixed;
  inset: 0;
  background: #0c0c0f;
  z-index: 55;
  display: flex;
  flex-direction: column;
}

#week-ahead-overlay[hidden] {
  display: none;
}

#week-ahead-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  padding: 1.5rem 2rem;
  border-bottom: 2px solid #2a2a30;
}

#week-ahead-title {
  color: #c33;
  font-weight: 700;
  font-size: 1.4rem;
  letter-spacing: 0.1em;
}

#week-ahead-subtitle {
  color: #888;
  font-weight: 400;
  font-size: 1rem;
  letter-spacing: normal;
  text-transform: none;
}

/* Sized like #message-close, not the smaller #story-close — this needs to
   be effortless to hit, not a quiet secondary action. */
#week-ahead-close {
  flex-shrink: 0;
  padding: 0.9rem 2.2rem;
  border-radius: 10px;
  border: none;
  background: var(--cell-text);
  color: #111;
  font-weight: 700;
  font-size: 1.1rem;
  cursor: pointer;
}

.week-ahead-strip {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  gap: 1.5rem;
  padding: 1.5rem 2rem 2rem;
  flex: 1;
}

.week-ahead-card {
  flex: 0 0 57vw;
  scroll-snap-align: center;
  min-height: 70vh;
  background: var(--panel-bg);
  border: 1px solid #2a2a30;
  border-radius: 16px;
  padding: 2rem;
  display: flex;
  flex-direction: column;
  gap: 1rem;
}

.week-ahead-day-name {
  color: #7de3b8;
  font-size: 2rem;
  font-weight: 700;
  margin-bottom: 0.5rem;
}

.week-ahead-event-icon {
  font-size: 1.4rem;
  line-height: 1;
}

.week-ahead-empty {
  margin: auto;
  color: #888;
  font-style: italic;
  font-size: 1.4rem;
  text-align: center;
}

#story-card,
#message-card,
#confirm-card {
  background: var(--panel-bg);
  border: 2px solid #3a3a42;
  border-radius: 14px;
  max-width: 700px;
  width: 100%;
  padding: 2rem 2.5rem;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.7);
  animation: storyIn 0.25s ease-out;
}

/* Testing feedback: the row-detail popup specifically needed to read
   bigger than the news/confirm popups it shares CSS with — a wider card
   plus its own (larger) text-size rule below, kept separate from the
   shared #story-*/#confirm-* sizing so those two are unaffected. */
#message-card {
  max-width: 860px;
  padding: 2.5rem 3rem;
}

#message-body {
  display: flex;
  align-items: stretch;
  gap: 2rem;
}

#message-text {
  flex: 1;
  min-width: 0;
}

/* Learning Difficulties boards only: the same category icon as the idle
   card and the row itself (see event-categories.js), shown as a large tile
   next to the message text rather than inline with it — this popup is
   read at a distance, so the icon earns its own space. */
#message-icon-tile {
  flex-shrink: 0;
  width: 10rem;
  display: flex;
  align-items: center;
  justify-content: center;
}

#message-icon-tile[hidden] {
  display: none;
}

#message-icon {
  font-size: 4.5rem;
  line-height: 1;
}

@keyframes storyIn {
  from { opacity: 0; transform: translateY(14px) scale(0.98); }
  to { opacity: 1; transform: translateY(0) scale(1); }
}

/* Every piece of text in this popup — the small kicker label down to the
   close button — is deliberately the SAME size, not a heading/body/caption
   hierarchy: nothing in here should read as "less important, so smaller". */
#story-kicker,
#story-title,
#confirm-title,
#story-description,
#story-close,
#confirm-ok,
#confirm-cancel {
  font-size: 1.4rem;
}

/* The row-detail popup follows the same "everything one size" rule as the
   others above, just a bigger size — testing feedback was specifically
   that this popup (not the news/confirm ones) needed to read bigger. */
#message-kicker,
#message-title,
#message-description,
#message-close {
  font-size: 1.75rem;
}

#story-kicker,
#message-kicker {
  color: #c33;
  font-weight: 700;
  letter-spacing: 0.15em;
  margin-bottom: 0.75rem;
}

#story-title,
#message-title,
#confirm-title {
  margin: 0 0 1.5rem;
  line-height: 1.35;
  color: var(--cell-text);
}

#story-description,
#message-description {
  margin: 0 0 1.5rem;
  line-height: 1.5;
  color: #ddd;
  white-space: pre-wrap;
}

#story-actions,
#message-actions,
#confirm-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 1rem;
}

/* Mirrors the row's own task/visit/ack buttons (see appendActionButtons in
   app.js) inside the bigger popup, so "Mark done" / "Confirm arrived" /
   thumbs-up are reachable without closing the popup first — sized up to
   match the rest of this popup's larger text. */
#message-action-buttons {
  display: flex;
  gap: 1rem;
}

#message-action-buttons .task-done-btn {
  font-size: 1.3rem;
  padding: 0.7rem 1.4rem;
  min-width: 3.2rem;
  height: auto;
}

/* The popup's thumbs-up needed to be a real tap target, not the same quiet
   outline it uses inline in the row — filled and sized to match (or beat)
   the "Mark done" button so it reads as the obvious, prominent action. */
#message-action-buttons .ack-btn {
  background: #7de3b8;
  border: none;
  color: #0c0c0f;
  font-weight: 700;
  font-size: 1.5rem;
  padding: 0.9rem 1.8rem;
  min-width: 4.5rem;
  height: auto;
  border-radius: 10px;
  line-height: 1;
  white-space: nowrap;
}

#message-action-buttons .ack-btn:hover:not(:disabled) {
  filter: brightness(1.15);
  border-color: transparent;
}

#message-action-buttons .ack-btn:disabled {
  background: #4a5c53;
  color: #ccc;
}

#message-action-buttons .task-done-label {
  font-size: 1.3rem;
}

#story-close,
#confirm-ok {
  padding: 0.6rem 1.6rem;
  border-radius: 8px;
  border: none;
  background: var(--cell-text);
  color: #111;
  font-weight: 700;
  cursor: pointer;
}

#message-close {
  padding: 0.9rem 2.2rem;
  border-radius: 10px;
  border: none;
  background: var(--cell-text);
  color: #111;
  font-weight: 700;
  cursor: pointer;
}

#confirm-cancel {
  padding: 0.6rem 1.6rem;
  border-radius: 8px;
  border: 2px solid #3a3a42;
  background: none;
  color: #ccc;
  font-weight: 700;
  cursor: pointer;
}

#confirm-cancel:hover {
  border-color: #666;
  color: #fff;
}

.row.expandable {
  cursor: pointer;
}

#test-panel {
  position: fixed;
  bottom: 1rem;
  right: 1rem;
  background: var(--panel-bg);
  border-radius: 10px;
  padding: 0.75rem 1rem;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5);
  max-width: 320px;
}

/* #test-toggle {
  background: none;
  border: none;
  color: #ccc;
  font-size: 1rem;
  cursor: pointer;
  padding: 0;
} */

#test-form {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  margin-top: 0.75rem;
}

#test-form label {
  display: flex;
  flex-direction: column;
  font-size: 0.85rem;
  color: #aaa;
  gap: 0.2rem;
}

#test-form input,
#test-form select {
  padding: 0.4rem;
  border-radius: 6px;
  border: 1px solid #444;
  background: #111;
  color: #eee;
}

#test-form button {
  padding: 0.5rem;
  border-radius: 6px;
  border: none;
  background: var(--cell-text);
  color: #111;
  font-weight: 700;
  cursor: pointer;
}

/* Below this width, the desktop preview lengths (CHANNEL 10 / FROM 16 /
   BODY 32 character-tiles) don't fit a single line on a tablet screen. The
   design intent is every row stays on ONE line — truncation-with-"…" plus
   the row's existing tap-to-expand (see the `expandable` class in app.js)
   is how a too-long sender/message is meant to be read, not a wrapped
   second line. So app.js hands out shorter preview lengths below this same
   breakpoint (see COMPACT_LENS) and this block just shrinks the tile size
   and the column widths to match — the grid stays a single row throughout. */
@media (max-width: 1400px) {
  :root {
    --flap-w: 19px;
    --row-gap: 0.35rem;
  }
  .flap {
    height: 1.5em;
    font-size: 1.3rem;
  }
  .column-labels {
    display: none;
  }
  .row {
    grid-template-columns: calc(8 * var(--flap-w)) calc(1 * var(--flap-w)) calc(10 * var(--flap-w)) 1fr auto;
    gap: var(--row-gap);
  }
}
