@font-face {
  font-family: 'Atkinson Hyperlegible Next';
  src: url('/vendor/fonts/atkinson-400.woff2') format('woff2');
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: 'Atkinson Hyperlegible Next';
  src: url('/vendor/fonts/atkinson-700.woff2') format('woff2');
  font-weight: 700;
  font-display: swap;
}

:root {
  --caption-size: 30px;
  --font: 'Atkinson Hyperlegible Next', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --ease: cubic-bezier(0.2, 0, 0, 1);
  /* Caption appearance: display.js overrides these from the Display panel. */
  --cap-font: var(--font);
  --cap-weight: 400;
  --cap-leading: 1.34;
  --cap-tracking: 0em;
  --cap-color: var(--text);
  --cap-box: transparent;
  --cap-edge: none;
  --earlier-opacity: 1;
}

/* Themes are plain attribute selectors, so any element can carry one: the theme tiles in the
   Display panel preview themselves this way. Dark is also the default for the whole page. */
:root,
[data-theme='dark'] {
  color-scheme: dark;
  /* Neutrals lean slightly blue so surfaces read as one family rather than flat greys. */
  --bg: #0e1015;
  --surface: #15181e;
  --surface-2: #1e222a;
  --surface-3: #282d37;
  --line: #2a2e38;
  /* Text-field outlines: at least 3:1 against both the field and the surface around it. */
  --field-border: #6c7280;
  --text: #f2f4f8;
  --text-2: #abb1bd;
  --interim: #9ba1ad;
  --accent: #8fb0ff;
  --accent-hover: #a7c1ff;
  --accent-ink: #0a1433;
  --ok: #5fdc96;
  --warn: #ffc94d;
  --danger: #ff8a8a;
  --local: #8fb0ff;
  --demo: #c9a2ff;
  --reply-bg: #22304f;
  --reply-text: #eef3ff;
  /* How strongly a speaker or status color tints its pill. */
  --tint: 16%;
  --tint-hover: 26%;
  /* Shadow rings stand in for borders on buttons and cards, so they sit well on any surface. */
  --ring: 0 0 0 1px rgb(255 255 255 / 0.08);
  --ring-hover: 0 0 0 1px rgb(255 255 255 / 0.13);
  --shadow-lg: 0 0 0 1px rgb(255 255 255 / 0.06), 0 24px 70px rgb(0 0 0 / 0.55);
  --backdrop: rgb(4 6 10 / 0.66);
  /* Speaker colors: labels and the bar beside each caption. */
  --spk-0: #abb1bd;
  --spk-1: #ffd54a;
  --spk-2: #6fd3ff;
  --spk-3: #ff8fc7;
  --spk-4: #8be58b;
  --spk-5: #ffae66;
  --spk-6: #c3a6ff;
}

/* Softer than Dark: a mid-grey page for less glare in bright rooms. */
[data-theme='dim'] {
  --bg: #1f2127;
  --surface: #26292f;
  --surface-2: #2f333a;
  --surface-3: #393d45;
  --line: #353941;
  --field-border: #7a808c;
  --text: #e3e5ea;
  --text-2: #aeb3bd;
  --interim: #9ea3ad;
  --accent: #9db8f5;
  --accent-hover: #b4c9f8;
  --accent-ink: #111a33;
  --local: #9db8f5;
  --reply-bg: #2c3a57;
  --reply-text: #eef2fb;
}

/* Status, speaker and shadow colors shared by every light-background theme. */
[data-theme='light'],
[data-theme='paper'],
[data-theme='custom'][data-mode='light'] {
  color-scheme: light;
  --ok: #157a3f;
  --warn: #9a6200;
  --danger: #c0262d;
  --demo: #6b3fc0;
  --tint: 11%;
  --tint-hover: 18%;
  --ring: 0 0 0 1px rgb(0 0 0 / 0.07), 0 1px 2px -1px rgb(0 0 0 / 0.06), 0 2px 4px 0 rgb(0 0 0 / 0.04);
  --ring-hover: 0 0 0 1px rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.08), 0 2px 4px 0 rgb(0 0 0 / 0.06);
  --shadow-lg: 0 0 0 1px rgb(0 0 0 / 0.06), 0 24px 70px rgb(16 24 40 / 0.2);
  --backdrop: rgb(16 20 28 / 0.42);
  --spk-0: #4a505d;
  --spk-1: #8a5a00;
  --spk-2: #005f94;
  --spk-3: #a3195b;
  --spk-4: #1e7a1e;
  --spk-5: #a04800;
  --spk-6: #5b3db5;
}

[data-theme='light'] {
  --bg: #f4f5f8;
  --surface: #ffffff;
  --surface-2: #eceef3;
  --surface-3: #e1e4eb;
  --line: #dadde4;
  --field-border: #7c828e;
  --text: #12141a;
  --text-2: #4a505d;
  --interim: #5f6573;
  --accent: #3355d6;
  --accent-hover: #2945b8;
  --accent-ink: #ffffff;
  --local: #3355d6;
  --reply-bg: #e4eafc;
  --reply-text: #0d1a40;
}

/* Warm cream and brown ink, like a printed page. */
[data-theme='paper'] {
  --bg: #f6f0e3;
  --surface: #fbf8f0;
  --surface-2: #ede5d4;
  --surface-3: #e3d9c4;
  --line: #ddd2bd;
  --field-border: #857a68;
  --text: #2b2219;
  --text-2: #5f5342;
  --interim: #6e6250;
  --accent: #9c4a14;
  --accent-hover: #833d0f;
  --accent-ink: #ffffff;
  --local: #9c4a14;
  --reply-bg: #efdfc6;
  --reply-text: #2b2219;
}

/* Tints and soft shadows give way to solid white outlines. */
[data-theme='contrast'] {
  --bg: #000;
  --surface: #000;
  --surface-2: #161616;
  --surface-3: #262626;
  --line: #ffffff;
  --field-border: #ffffff;
  --text: #ffffff;
  --text-2: #ffffff;
  --interim: #ffe14d;
  --accent: #ffe14d;
  --accent-hover: #fff09a;
  --accent-ink: #000;
  --reply-bg: #0b3b8c;
  --reply-text: #ffffff;
  --tint: 0%;
  --tint-hover: 18%;
  --ring: 0 0 0 1px #ffffff;
  --ring-hover: 0 0 0 2px #ffffff;
  --shadow-lg: 0 0 0 2px #ffffff;
  --backdrop: rgb(0 0 0 / 0.8);
  --spk-0: #ffffff;
}

/* Custom: three chosen colors (set by display.js); every other surface is mixed from them. */
[data-theme='custom'] {
  --bg: var(--custom-bg);
  --text: var(--custom-text);
  --accent: var(--custom-accent);
  --accent-ink: var(--custom-accent-ink);
  --accent-hover: color-mix(in srgb, var(--custom-accent) 82%, var(--custom-text));
  --surface: color-mix(in srgb, var(--custom-bg), var(--custom-text) 4%);
  --surface-2: color-mix(in srgb, var(--custom-bg), var(--custom-text) 9%);
  --surface-3: color-mix(in srgb, var(--custom-bg), var(--custom-text) 14%);
  --line: color-mix(in srgb, var(--custom-bg), var(--custom-text) 14%);
  --field-border: color-mix(in srgb, var(--custom-bg), var(--custom-text) 55%);
  --text-2: color-mix(in srgb, var(--custom-text) 74%, var(--custom-bg));
  --interim: color-mix(in srgb, var(--custom-text) 66%, var(--custom-bg));
  --local: var(--custom-accent);
  --reply-bg: color-mix(in srgb, var(--custom-bg), var(--custom-accent) 22%);
  --reply-text: var(--custom-text);
}

* {
  box-sizing: border-box;
}

html,
body {
  height: 100%;
}

body {
  margin: 0;
  display: flex;
  flex-direction: column;
  height: 100dvh;
  overflow: hidden;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  -webkit-text-size-adjust: 100%;
  -webkit-tap-highlight-color: transparent;
}

button {
  cursor: pointer;
}

:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}

[hidden] {
  display: none !important;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

/* ---------- top bar ---------- */

.bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: max(8px, env(safe-area-inset-top)) max(8px, env(safe-area-inset-right)) 8px max(12px, env(safe-area-inset-left));
  background: var(--bg);
  border-bottom: 1px solid var(--line);
}

/* A pill tinted with the state color, so the state reads at a glance without relying on the dot alone. */
.status {
  --state: var(--spk-0);
  display: flex;
  align-items: center;
  gap: 8px;
  min-width: 0;
  min-height: 36px;
  padding: 6px 14px 6px 12px;
  border-radius: 18px;
  background: var(--surface-2);
  background: color-mix(in srgb, var(--state) var(--tint), transparent);
  font-size: 15px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  transition: background-color 150ms ease-out;
}

/* Wraps rather than truncating: the state (and download progress) must stay readable on narrow phones. */
#status-text {
  line-height: 1.35;
}

.dot {
  flex: none;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--state, var(--spk-0));
}

.status[data-state='cloud'] {
  --state: var(--ok);
}
.status[data-state='local'] {
  --state: var(--local);
}
.status[data-state='demo'] {
  --state: var(--demo);
}
.status[data-state='failed'] {
  --state: var(--danger);
}
.status[data-state='starting'],
.status[data-state='connecting'],
.status[data-state='loading'],
.status[data-state='waiting'] {
  --state: var(--warn);
}
[data-state='starting'] .dot,
[data-state='connecting'] .dot,
[data-state='loading'] .dot,
[data-state='waiting'] .dot {
  animation: pulse 1.1s ease-in-out infinite;
}

@keyframes pulse {
  50% {
    opacity: 0.25;
  }
}

.meter {
  display: inline-flex;
  align-items: flex-end;
  gap: 2px;
  height: 16px;
  flex: none;
  margin-left: 2px;
}
.meter i {
  width: 3px;
  border-radius: 2px;
  background: color-mix(in srgb, var(--text) 22%, transparent);
  transition: background-color 100ms ease-out;
}
.meter i:nth-child(1) { height: 5px; }
.meter i:nth-child(2) { height: 8px; }
.meter i:nth-child(3) { height: 11px; }
.meter i:nth-child(4) { height: 14px; }
.meter i:nth-child(5) { height: 16px; }
.meter i.on {
  background: var(--state);
}
[data-state='off'] .meter {
  display: none;
}

.bar-actions {
  display: flex;
  gap: 2px;
  flex: none;
}

.icon-btn {
  position: relative;
  display: inline-grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  border-radius: 12px;
  background: transparent;
  color: var(--text);
  transition-property: background-color, color, scale;
  transition-duration: 150ms;
  transition-timing-function: ease-out;
}
@media (hover: hover) {
  .icon-btn:hover {
    background: var(--surface-2);
  }
}
.icon-btn:active {
  scale: 0.96;
}
.icon-btn svg {
  width: 24px;
  height: 24px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.icon-btn.small {
  width: 36px;
  height: 36px;
  border-radius: 10px;
}
.icon-btn.small svg {
  width: 20px;
  height: 20px;
}

.badge {
  position: absolute;
  top: 3px;
  right: 1px;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  border-radius: 9px;
  background: var(--accent);
  box-shadow: 0 0 0 2px var(--bg);
  color: var(--accent-ink);
  font-size: 12px;
  font-weight: 700;
  line-height: 18px;
}

/* An inset card whose bar matches the caption bars; its color says what kind of notice it is. */
.banner {
  --tone: var(--accent);
  display: flex;
  align-items: center;
  gap: 12px;
  margin: 10px max(12px, env(safe-area-inset-right)) 0 max(12px, env(safe-area-inset-left));
  padding: 6px 6px 6px 12px;
  border-radius: 16px;
  background: var(--surface-2);
  background: color-mix(in srgb, var(--tone) var(--tint), var(--bg));
  font-size: 15px;
  line-height: 1.4;
}
.banner::before {
  content: '';
  flex: none;
  align-self: stretch;
  width: 4px;
  margin: 4px 0;
  border-radius: 2px;
  background: var(--tone);
}
.banner[data-id='insecure'],
.banner[data-id='access'] {
  --tone: var(--warn);
}
.banner[data-id='demo'] {
  --tone: var(--demo);
}
.banner p {
  flex: 1;
  margin: 0;
  text-wrap: pretty;
}

/* ---------- captions ---------- */

.captions {
  flex: 1;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 20px max(16px, calc((100% - 72rem) / 2)) 32px;
  font-family: var(--cap-font);
  font-size: var(--caption-size);
  line-height: var(--cap-leading);
}
/* Earlier lines fade out under the top edge instead of being sliced mid-letter.
   The fade stays inside the top padding, so a line at rest is never dimmed. */
#captions:not(:focus-visible) {
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 18px);
  mask-image: linear-gradient(to bottom, transparent, #000 18px);
}
.captions:focus-visible {
  outline-offset: -3px;
}

.line {
  --spk: var(--spk-0);
  position: relative;
  margin: 0 0 0.5em;
  padding-left: 0.5em;
}
/* The speaker bar: a rounded stroke rather than a square border. */
.line::before {
  content: '';
  position: absolute;
  top: 0.14em;
  bottom: 0.14em;
  left: 0;
  width: 4px;
  border-radius: 2px;
  background: var(--spk);
}
.line[data-color='1'] { --spk: var(--spk-1); }
.line[data-color='2'] { --spk: var(--spk-2); }
.line[data-color='3'] { --spk: var(--spk-3); }
.line[data-color='4'] { --spk: var(--spk-4); }
.line[data-color='5'] { --spk: var(--spk-5); }
.line[data-color='6'] { --spk: var(--spk-6); }
.line[data-color='0']::before,
.line.reply::before {
  display: none;
}
/* A new speaker gets more room above than a continuation of the same speaker. */
.line + .line:has(> .who:not([hidden])),
.line + .pending > .line:first-child:has(> .who:not([hidden])) {
  margin-top: 1em;
}

.who {
  display: block;
  margin: 0 0 0.1em;
  padding: 0;
  border: 0;
  background: none;
  color: var(--spk);
  font: inherit;
  font-size: max(14px, 0.5em);
  font-weight: 700;
  line-height: 1.3;
  text-align: left;
}
/* Tap to rename: a pill tinted with the speaker's color, so it reads as a control, not part of the caption. */
button.who,
.who.as-button {
  display: inline-block;
  margin-bottom: 0.2em;
  padding: 0.2em 0.65em;
  border-radius: 999px;
  background: var(--surface-2);
  background: color-mix(in srgb, var(--spk) var(--tint), transparent);
  transition-property: background-color, scale;
  transition-duration: 150ms;
  transition-timing-function: ease-out;
}
@media (hover: hover) {
  button.who:hover {
    background: color-mix(in srgb, var(--spk) var(--tint-hover), transparent);
  }
}
button.who:active {
  scale: 0.96;
}
button.who {
  position: relative;
}
button.who::after {
  content: '';
  position: absolute;
  inset: -8px -4px;
}

.said {
  display: block;
  margin: 0;
  overflow-wrap: anywhere;
}

/* In-progress words may still change: dimmer, and dotted so the difference doesn't rest on color. */
.tmp {
  color: var(--cap-interim, var(--interim));
  text-decoration: underline dotted;
  text-underline-offset: 0.18em;
}

/* A line someone read back from the captions: folded behind a small button, and dimmed when opened
   or while it's still being said, so the original stays the one that stands out. */
.fold {
  display: inline-flex;
  align-items: center;
  gap: 0.35em;
  min-height: 32px;
  margin: 0 0 0.1em;
  padding: 0;
  border: 0;
  background: none;
  color: var(--text-2);
  font: inherit;
  font-size: max(14px, 0.5em);
  font-weight: 700;
  line-height: 1.3;
  text-align: left;
  cursor: pointer;
}
.fold::before {
  content: '▸';
}
.fold[aria-expanded='true']::before {
  content: '▾';
}
@media (hover: hover) {
  .fold:hover {
    text-decoration: underline;
  }
}
.line.readback::before {
  opacity: 0.4;
}
.line.readback .said,
.line.readback .tr {
  opacity: 0.6;
}
.line.folded .said,
.line.folded .tr {
  display: none;
}

/* New words appear with the short animation chosen in the Display panel (data-caption-motion), at
   most a fifth of a second so reading is never held up. Only a word's first appearance animates.
   With reduced motion, rising and blurring become a plain fade. */
@keyframes word-fade {
  from {
    opacity: 0;
  }
}
@keyframes word-rise {
  from {
    opacity: 0;
    top: 0.3em;
  }
}
@keyframes word-blur {
  from {
    opacity: 0;
    filter: blur(4px);
  }
}
.w-in {
  position: relative;
}
[data-caption-motion='fade'] .w-in,
[data-caption-motion='rise'] .w-in,
[data-caption-motion='blur'] .w-in {
  animation: word-fade 160ms ease-out both;
}
@media (prefers-reduced-motion: no-preference) {
  [data-caption-motion='rise'] .w-in {
    animation: word-rise 200ms cubic-bezier(0.2, 0, 0, 1) both;
  }
  [data-caption-motion='blur'] .w-in {
    animation: word-blur 200ms cubic-bezier(0.2, 0, 0, 1) both;
  }
}

/* Words the speech service may have misheard keep their color, with a wavy underline: "check this". */
.unsure {
  text-decoration: underline wavy;
  text-decoration-color: var(--cap-interim, var(--interim));
  text-decoration-skip-ink: auto;
  text-underline-offset: 0.2em;
}

/* A translation sits under the caption it translates, a step smaller, after the languages it's between. */
.tr {
  display: block;
  margin: 0.15em 0 0;
  font-size: 0.85em;
  overflow-wrap: anywhere;
}
.tr-label {
  margin-right: 0.45em;
  color: var(--text-2);
  font-size: max(13px, 0.55em);
  font-weight: 700;
  white-space: nowrap;
}

/* ---------- caption appearance (Display panel) ---------- */

.said,
.tr {
  font-weight: var(--cap-weight);
  letter-spacing: var(--cap-tracking);
}
.line:not(.reply) .said,
.line:not(.reply) .tr {
  color: var(--cap-color);
  text-shadow: var(--cap-edge);
}

/* A box behind each caption, like broadcast subtitles. */
[data-cap-box] .line:not(.reply) .said,
[data-cap-box] .line:not(.reply) .tr {
  width: fit-content;
  max-width: 100%;
  padding: 0.04em 0.3em 0.08em;
  border-radius: 0.2em;
  background: var(--cap-box);
}

[data-align='center'] .line:not(.reply) {
  padding-left: 0;
  text-align: center;
}
[data-align='center'] .line:not(.reply)::before {
  display: none;
}
[data-align='center'][data-cap-box] .line:not(.reply) .said,
[data-align='center'][data-cap-box] .line:not(.reply) .tr {
  margin-inline: auto;
}

[data-mono-speakers] .line[data-color] {
  --spk: var(--spk-0);
}

/* Everything before the latest two lines can be dimmed (the last child is the in-progress group). */
#captions > .line {
  transition: opacity 300ms ease-out;
}
#captions > .line:not(:nth-last-child(-n + 3)) {
  opacity: var(--earlier-opacity);
}

.line.reply {
  display: block;
  width: fit-content;
  max-width: 85%;
  margin-left: auto;
  padding: 0.35em 0.65em 0.4em;
  border: 0;
  border-radius: 0.7em 0.7em 0.2em 0.7em;
  background: var(--reply-bg);
  color: var(--reply-text);
  font: inherit;
  font-size: 0.82em;
  text-align: start;
  transition: background-color 150ms ease-out;
}
.line.reply .who {
  margin-bottom: 0.15em;
  color: var(--accent);
}

.empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  max-width: 30em;
  min-height: 85%;
  margin: 0 auto;
  color: var(--text-2);
  font-size: 18px;
  line-height: 1.45;
  text-align: center;
  text-wrap: balance;
}
.empty p {
  margin: 0;
}
.empty .empty-title {
  margin: 0 0 8px;
  color: var(--text);
  font-size: 30px;
  font-weight: 700;
  line-height: 1.2;
}
/* First impression: the parts arrive in reading order. */
.empty > * {
  animation: rise 400ms ease-out backwards;
}
.empty > :nth-child(2) { animation-delay: 100ms; }
.empty > :nth-child(3) { animation-delay: 200ms; }
.empty > :nth-child(4) { animation-delay: 300ms; }

@keyframes rise {
  from {
    opacity: 0;
    translate: 0 12px;
    filter: blur(4px);
  }
}

.empty-mark {
  width: 88px;
  height: 88px;
  margin-bottom: 16px;
}
.empty-mark .bubble {
  fill: var(--surface-2);
  stroke: var(--text);
  stroke-width: 2.5;
  stroke-linejoin: round;
}
.empty-mark .bar-1 {
  fill: var(--spk-1);
}
.empty-mark .bar-2 {
  fill: var(--spk-2);
}
/* While listening, the caption bars breathe; the "Listening…" title carries the same message. */
.empty:has(#start-big[hidden]) .empty-mark rect {
  animation: pulse 1.6s ease-in-out infinite;
}
.empty:has(#start-big[hidden]) .empty-mark .bar-2 {
  animation-delay: 0.3s;
}

/* Floats just above the composer, whatever height the composer has. */
.jump {
  position: absolute;
  left: 50%;
  bottom: calc(100% + 12px);
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 10px 16px 10px 18px;
  border: 0;
  border-radius: 999px;
  background: var(--accent);
  color: var(--accent-ink);
  font: inherit;
  font-size: 16px;
  font-weight: 700;
  transform: translateX(-50%);
  box-shadow: 0 6px 20px rgb(0 0 0 / 0.3);
  animation: pop-in 200ms var(--ease);
  transition-property: background-color, scale;
  transition-duration: 150ms;
  transition-timing-function: ease-out;
}
@media (hover: hover) {
  .jump:hover {
    background: var(--accent-hover);
  }
}
.jump:active {
  scale: 0.96;
}

@keyframes pop-in {
  from {
    opacity: 0;
    translate: 0 8px;
  }
}

/* ---------- composer ---------- */

.composer {
  --pad-l: max(12px, env(safe-area-inset-left));
  --pad-r: max(12px, env(safe-area-inset-right));
  position: relative;
  padding: 10px var(--pad-r) max(12px, env(safe-area-inset-bottom)) var(--pad-l);
  background: var(--surface);
  border-top: 1px solid var(--line);
}

/* Runs edge to edge and fades out at the sides, so a cut-off chip reads as "scroll for more". */
.phrases {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  margin: -6px calc(-1 * var(--pad-r)) 4px calc(-1 * var(--pad-l));
  padding: 6px var(--pad-r) 6px var(--pad-l);
  scrollbar-width: thin;
  -webkit-mask-image: linear-gradient(to right, transparent, #000 8px, #000 calc(100% - 40px), transparent);
  mask-image: linear-gradient(to right, transparent, #000 8px, #000 calc(100% - 40px), transparent);
}

.chip {
  flex: none;
  min-height: 40px;
  padding: 8px 15px;
  border: 0;
  border-radius: 999px;
  background: var(--surface-2);
  box-shadow: var(--ring);
  color: var(--text);
  font: inherit;
  font-size: 15px;
  white-space: nowrap;
  transition-property: background-color, box-shadow, scale;
  transition-duration: 150ms;
  transition-timing-function: ease-out;
}
@media (hover: hover) {
  .chip:hover {
    background: var(--surface-3);
    box-shadow: var(--ring-hover);
  }
}
.chip:active {
  scale: 0.96;
}

.reply-row {
  display: flex;
  align-items: flex-end;
  gap: 8px;
}

/* The text box and its send button share one pill. */
.reply-box {
  display: flex;
  align-items: flex-end;
  flex: 1;
  min-width: 0;
  border: 1px solid var(--field-border);
  border-radius: 28px;
  background: var(--bg);
}

#reply-input {
  flex: 1;
  min-width: 0;
  min-height: 54px;
  max-height: 30vh;
  padding: 13px 4px 13px 19px;
  /* Transparent rather than none: app.js sizes the box as scrollHeight plus a 1px border each side. */
  border: 1px solid transparent;
  border-radius: 27px;
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: 18px;
  line-height: 1.35;
  resize: none;
}
@supports selector(:has(*)) {
  #reply-input:focus-visible {
    outline: none;
  }
  .reply-box:has(#reply-input:focus-visible) {
    outline: 3px solid var(--accent);
    outline-offset: 2px;
  }
}

/* Lights up once there's something to send. */
.send {
  flex: none;
  margin: 5px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--accent-ink);
}
@media (hover: hover) {
  .send:hover {
    background: var(--accent-hover);
  }
}
#reply-input:placeholder-shown ~ .send {
  background: transparent;
  color: var(--text-2);
}
@media (hover: hover) {
  #reply-input:placeholder-shown ~ .send:hover {
    background: var(--surface-2);
    color: var(--text);
  }
}

.mic-btn {
  flex: none;
  display: grid;
  place-items: center;
  width: 56px;
  height: 56px;
  border: 0;
  border-radius: 50%;
  background: var(--accent);
  color: var(--accent-ink);
  transition-property: background-color, color, box-shadow, scale;
  transition-duration: 150ms;
  transition-timing-function: ease-out;
}
@media (hover: hover) {
  .mic-btn:hover {
    background: var(--accent-hover);
  }
}
.mic-btn:active {
  scale: 0.96;
}
/* Both icons stay in place and cross-fade, so the swap reads as one control changing state. */
.mic-btn svg {
  grid-area: 1 / 1;
  width: 26px;
  height: 26px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linecap: round;
  transition-property: opacity, scale, filter;
  transition-duration: 300ms;
  transition-timing-function: var(--ease);
}
.mic-btn .pause,
.mic-btn.listening .mic {
  opacity: 0;
  scale: 0.25;
  filter: blur(4px);
}
.mic-btn.listening .pause {
  opacity: 1;
  scale: 1;
  filter: none;
}
.mic-btn.listening {
  background: var(--surface-2);
  background: color-mix(in srgb, var(--ok) var(--tint), var(--surface));
  color: var(--text);
  box-shadow: inset 0 0 0 2.5px var(--ok);
}
@media (hover: hover) {
  .mic-btn.listening:hover {
    background: color-mix(in srgb, var(--ok) var(--tint-hover), var(--surface));
  }
}

/* ---------- buttons and forms ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 44px;
  padding: 0 16px;
  border: 0;
  border-radius: 12px;
  background: var(--surface-2);
  box-shadow: var(--ring);
  color: var(--text);
  font: inherit;
  font-size: 16px;
  font-weight: 700;
  transition-property: background-color, box-shadow, scale;
  transition-duration: 150ms;
  transition-timing-function: ease-out;
}
@media (hover: hover) {
  .btn:hover {
    background: var(--surface-3);
    box-shadow: var(--ring-hover);
  }
}
.btn:active {
  scale: 0.96;
}
.btn svg {
  flex: none;
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.btn.primary {
  background: var(--accent);
  box-shadow: none;
  color: var(--accent-ink);
}
@media (hover: hover) {
  .btn.primary:hover {
    background: var(--accent-hover);
  }
}
/* The leading icon side gets 2px less padding so the label looks centered. */
.btn.big {
  min-height: 56px;
  margin-top: 28px;
  padding: 0 32px 0 28px;
  border-radius: 16px;
  font-size: 20px;
}
.btn.big svg {
  width: 24px;
  height: 24px;
  stroke-width: 2.2;
}
.btn.small {
  min-height: 36px;
  padding: 0 12px;
  border-radius: 10px;
  font-size: 14px;
}
.btn.subtle {
  background: transparent;
  box-shadow: none;
}
@media (hover: hover) {
  .btn.subtle:hover {
    background: var(--surface-2);
  }
}
.btn.danger {
  color: var(--danger);
}
.btn:disabled {
  opacity: 0.5;
  cursor: default;
  scale: none;
}
/* In a card, a button sits on the card's color, so it's a step lighter than usual. */
.card .btn:not(.primary, .subtle) {
  background: var(--surface-3);
}
@media (hover: hover) {
  .card .btn:not(.primary, .subtle):hover {
    background: color-mix(in srgb, var(--surface-3), var(--text) 6%);
  }
}

input:not([type]),
input[type='text'],
input[type='email'],
input[type='password'],
textarea,
select {
  width: 100%;
  padding: 11px 14px;
  border: 1px solid var(--field-border);
  border-radius: 12px;
  background: var(--bg);
  color: var(--text);
  font: inherit;
  font-size: 17px;
  line-height: 1.4;
}
textarea {
  resize: vertical;
}

select {
  padding-right: 42px;
  appearance: none;
  /* A mid-grey chevron reads on every theme's field color. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238b919d' stroke-width='2.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  background-size: 18px;
}
/* In a card a choice is a pill showing the current value, like a button, rather than a text field. */
.card select {
  min-height: 42px;
  padding: 8px 38px 8px 14px;
  border: 0;
  border-radius: 11px;
  background-color: var(--surface-3);
  box-shadow: var(--ring);
  font-size: 16px;
  font-weight: 700;
  line-height: 1.3;
  background-position: right 12px center;
  cursor: pointer;
  transition: background-color 150ms ease-out;
}
@media (hover: hover) {
  .card select:hover {
    background-color: color-mix(in srgb, var(--surface-3), var(--text) 6%);
  }
}

::placeholder {
  color: var(--text-2);
  opacity: 1;
}

/* ---------- settings ---------- */

/* One setting: its label, a hint under it, then the control. On its own it's a form field; in a card it's a row. */
.setting {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 8px;
  min-width: 0;
  margin: 16px 0;
  padding: 0;
  border: 0;
}
.setting > :is(label, legend, .label),
.setting > .text > :is(label, .label) {
  padding: 0;
  font-size: 16px;
  line-height: 1.35;
}
/* A floated legend is laid out like any other child, so the gaps stay even. */
.setting > legend {
  float: left;
  width: 100%;
}
.setting > legend > small {
  margin-top: 2px;
}
/* A button in a setting is as wide as its label, not the row. */
.setting > .btn {
  align-self: flex-start;
}
/* A hint hugs its label, before the control. */
.setting > small,
.setting > .text > small {
  margin-top: -4px;
}
/* A slider's label carries its value at the end of the line. */
.setting > label.readout {
  display: flex;
  justify-content: space-between;
  gap: 12px;
}
output {
  color: var(--text-2);
  font-weight: 400;
  font-variant-numeric: tabular-nums;
}
small {
  display: block;
  color: var(--text-2);
  font-size: 14px;
  font-weight: 400;
  line-height: 1.4;
  text-wrap: pretty;
}

/* Label and hint on the left, a short control on the right. When there's no room for both, the control
   drops under the text. */
.setting.inline {
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 8px 16px;
}
.setting.inline > .text {
  display: flex;
  flex: 1 1 14em;
  flex-direction: column;
  gap: 4px;
  min-width: 0;
}
.setting.inline > .text > small {
  margin: 0;
}
.setting.inline > :is(select, .btn) {
  flex: 0 0 auto;
  width: auto;
  max-width: 100%;
}
.setting.inline > progress {
  flex-basis: 100%;
  margin: 0;
}

/* A setting that's on or off: a switch at the end of its row, after the label and hint. */
.toggle {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas: 'label switch' 'hint switch';
  align-items: center;
  column-gap: 16px;
  row-gap: 4px;
  margin: 16px 0;
}
.toggle > label {
  grid-area: label;
  font-size: 16px;
  line-height: 1.35;
  cursor: pointer;
}
.toggle > small {
  grid-area: hint;
}
.toggle input {
  grid-area: switch;
  width: 48px;
  height: 28px;
  margin: 0;
  border-radius: 14px;
  appearance: none;
  background: var(--surface-3) radial-gradient(circle closest-side, var(--text-2) 92%, transparent) no-repeat 4px 50% / 20px 20px;
  box-shadow: inset 0 0 0 1px var(--field-border);
  cursor: pointer;
  transition-property: background-color, background-position, box-shadow;
  transition-duration: 200ms;
  transition-timing-function: var(--ease);
}
.toggle input:checked {
  background-color: var(--accent);
  background-image: radial-gradient(circle closest-side, var(--accent-ink) 92%, transparent);
  background-position: calc(100% - 4px) 50%;
  box-shadow: none;
}

/* One of several choices, with a line about it; the chosen one's dot fills in. */
.radio {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 10px 0;
  font-size: 16px;
  line-height: 1.35;
  cursor: pointer;
}
.radio > span {
  flex: 1;
}
.radio > span > small {
  margin-top: 2px;
}
.radio input {
  flex: none;
  width: 22px;
  height: 22px;
  margin: 0;
  border: 2px solid var(--field-border);
  border-radius: 50%;
  appearance: none;
  background: var(--bg);
  cursor: pointer;
  transition-property: border-color, box-shadow;
  transition-duration: 150ms;
  transition-timing-function: ease-out;
}
.radio input:checked {
  border-color: var(--accent);
  box-shadow: inset 0 0 0 3px var(--bg), inset 0 0 0 10px var(--accent);
}
.radios .radio {
  transition: background-color 150ms ease-out;
}
@media (hover: hover) {
  .radios .radio:hover {
    background: var(--surface-3);
  }
}

/* One track with the choice raised inside it; inner radius = outer radius − padding. */
.segmented {
  display: flex;
  gap: 4px;
  padding: 4px;
  border-radius: 14px;
  background: var(--surface-2);
  box-shadow: var(--ring);
}
.card .segmented {
  background: var(--bg);
}
.segmented label {
  position: relative;
  display: grid;
  flex: 1;
}
.segmented input {
  position: absolute;
  opacity: 0;
}
.segmented span {
  display: grid;
  place-items: center;
  min-height: 42px;
  padding: 8px 6px;
  border-radius: 10px;
  color: var(--text-2);
  font-weight: 700;
  line-height: 1.2;
  text-align: center;
  cursor: pointer;
  transition-property: background-color, color;
  transition-duration: 150ms;
  transition-timing-function: ease-out;
}
@media (hover: hover) {
  .segmented label:hover span {
    color: var(--text);
  }
}
.segmented input:checked + span {
  background: var(--accent);
  color: var(--accent-ink);
}
.segmented input:focus-visible + span {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}

/* Sliders: a quiet track and a big round thumb in the accent color. */
input[type='range'] {
  width: 100%;
  height: 36px;
  margin: 0;
  appearance: none;
  background: transparent;
  cursor: pointer;
}
input[type='range']::-webkit-slider-runnable-track {
  height: 6px;
  border-radius: 3px;
  background: var(--surface-3);
  box-shadow: var(--ring);
}
input[type='range']::-webkit-slider-thumb {
  width: 24px;
  height: 24px;
  margin-top: -9px;
  border: 0;
  border-radius: 50%;
  appearance: none;
  background: var(--accent);
  box-shadow: 0 1px 4px rgb(0 0 0 / 0.35);
  transition: scale 150ms ease-out;
}
input[type='range']:active::-webkit-slider-thumb {
  scale: 1.1;
}
input[type='range']::-moz-range-track {
  height: 6px;
  border-radius: 3px;
  background: var(--surface-3);
  box-shadow: var(--ring);
}
input[type='range']::-moz-range-progress {
  height: 6px;
  border-radius: 3px;
  background: var(--accent);
}
input[type='range']::-moz-range-thumb {
  width: 24px;
  height: 24px;
  border: 0;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 1px 4px rgb(0 0 0 / 0.35);
}

progress {
  width: 100%;
  height: 8px;
  overflow: hidden;
  border: 0;
  border-radius: 4px;
  appearance: none;
  background: var(--surface-3);
  accent-color: var(--accent);
}
progress::-webkit-progress-bar {
  background: var(--surface-3);
}
progress::-webkit-progress-value {
  border-radius: 4px;
  background: var(--accent);
}
progress::-moz-progress-bar {
  border-radius: 4px;
  background: var(--accent);
}

.hint {
  margin: 6px 0;
  color: var(--text-2);
  font-size: 14px;
  line-height: 1.5;
  text-wrap: pretty;
}

.row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
.row.wrap {
  flex-wrap: wrap;
  justify-content: flex-start;
}
.row.end {
  justify-content: flex-end;
}

/* ---------- grouped settings ---------- */

/* Settings come in cards: a rounded block of rows, one setting each, parted by hairlines. The card
   clips its rows' hover color at the corners, so focus rings on whole rows are drawn inside. */
.card {
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 16px;
  background: var(--surface-2);
  box-shadow: var(--ring);
  overflow: hidden;
}
.card > * {
  margin: 0;
  padding: 12px 16px;
}
.card > .setting:not(.inline) {
  padding: 12px 16px 16px;
}
.card > .toggle,
.card > .setting.inline {
  min-height: 56px;
}
.card > :not([hidden]) ~ :not([hidden]) {
  border-top: 1px solid var(--line);
}
.card > .device-list {
  padding: 0;
}
.card .device-item {
  padding: 12px 16px;
}
.card .font-aa {
  background: var(--bg);
}
.card-note {
  color: var(--text-2);
  font-size: 14px;
  line-height: 1.5;
  text-wrap: pretty;
}

/* A row that does something: an action with its icon, or a step into another sheet (with a chevron). */
.row-btn {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: 54px;
  border: 0;
  background: transparent;
  color: var(--text);
  font: inherit;
  font-size: 16px;
  line-height: 1.35;
  text-align: left;
  cursor: pointer;
  transition: background-color 150ms ease-out;
}
@media (hover: hover) {
  .row-btn:hover {
    background: var(--surface-3);
  }
}
.row-btn:focus-visible {
  outline-offset: -3px;
}
.row-btn > svg {
  flex: none;
  width: 22px;
  height: 22px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  color: var(--accent);
}
.row-btn > span {
  flex: 1;
}
.row-btn.more::after {
  content: '';
  flex: none;
  width: 9px;
  height: 9px;
  margin-right: 4px;
  border-top: 2px solid var(--text-2);
  border-right: 2px solid var(--text-2);
  rotate: 45deg;
}
.row-btn.danger,
.row-btn.danger > svg {
  color: var(--danger);
}
.row-btn:disabled {
  color: var(--text-2);
  cursor: default;
}
.row-btn:disabled > svg {
  color: inherit;
}
@media (hover: hover) {
  .row-btn:disabled:hover {
    background: transparent;
  }
}

/* A card's heading sits above it, small and quiet, in line with the rows' text; a note under the
   card says more about the group. */
.group > :is(h3, h4) {
  margin: 0 0 8px 16px;
  color: var(--text-2);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.06em;
  line-height: 1.3;
  text-transform: uppercase;
}
.group-note {
  margin: 8px 16px 0;
  color: var(--text-2);
  font-size: 14px;
  line-height: 1.45;
  text-wrap: pretty;
}
.group-note:empty {
  display: none;
}

/* ---------- dialogs ---------- */

dialog.sheet {
  --sheet-pad: 24px; /* side padding */
  width: min(560px, calc(100% - 32px));
  max-height: min(88dvh, 920px);
  padding: 0 var(--sheet-pad) 28px;
  border: 0;
  border-radius: 24px;
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--shadow-lg);
  overflow-y: auto;
  overscroll-behavior: contain;
  transition-property: opacity, translate;
  transition-duration: 300ms;
  transition-timing-function: var(--ease);
}
/* Sheets ease in. */
@starting-style {
  dialog.sheet[open] {
    opacity: 0;
    translate: 0 16px;
  }
}
dialog::backdrop {
  background: var(--backdrop);
  transition-property: background-color;
  transition-duration: 300ms;
  transition-timing-function: var(--ease);
}
@starting-style {
  dialog[open]::backdrop {
    background: transparent;
  }
}
/* Where a closing dialog can stay on top for a moment, sheets slip away a little faster than they
   came, taking no taps meanwhile. Elsewhere closing is instant, as the focus has already moved on. */
@supports (overlay: auto) {
  dialog.sheet,
  .big-reply {
    transition-property: opacity, translate, display, overlay;
    transition-behavior: allow-discrete;
  }
  dialog.sheet:not([open]) {
    opacity: 0;
    translate: 0 8px;
    transition-duration: 200ms;
  }
  .big-reply:not([open]) {
    opacity: 0;
  }
  dialog:not([open]) {
    pointer-events: none;
  }
  dialog::backdrop {
    transition-property: background-color, display, overlay;
    transition-behavior: allow-discrete;
  }
  dialog:not([open])::backdrop {
    background: transparent;
    transition-duration: 200ms;
  }
}

/* The settings sheets (Display, Menu) keep their top in place (the title, the Display preview, the
   Menu's sections) and scroll the settings under it. */
dialog.settings-sheet {
  padding: 0;
  overflow: hidden;
}
dialog.settings-sheet[open] {
  display: grid;
  grid-template-rows: auto minmax(0, 1fr);
}
.settings-sheet .sheet-top {
  min-width: 0;
  box-shadow: 0 1px 0 var(--line);
}
.settings-panes {
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 16px var(--sheet-pad) var(--sheet-pad);
}

@media (max-width: 640px) {
  dialog.sheet {
    --sheet-pad: 20px;
    width: 100%;
    max-width: 100%;
    margin: auto 0 0;
    padding: 0 var(--sheet-pad) max(24px, env(safe-area-inset-bottom));
    border-radius: 24px 24px 0 0;
  }
  dialog.sheet.tall,
  dialog.settings-sheet {
    height: 92dvh;
    max-height: none;
  }
  dialog.settings-sheet {
    padding: 0;
  }
  .settings-panes {
    padding-bottom: max(24px, env(safe-area-inset-bottom));
  }
}
/* On a tablet or computer, the sheets that hold the most get more room than the narrow column. */
@media (min-width: 641px) {
  dialog.sheet.tall {
    --sheet-pad: 32px;
    width: min(720px, calc(100% - 64px));
    height: min(88dvh, 960px);
    max-height: none;
    padding-bottom: 32px;
    border-radius: 28px;
  }
  dialog.settings-sheet {
    --sheet-pad: 32px;
    width: min(920px, calc(100% - 64px));
    height: min(88dvh, 880px);
    max-height: none;
    border-radius: 28px;
  }
  dialog.display-sheet {
    width: min(1040px, calc(100% - 64px));
  }
}

/* The negative margin lines the close and back icons up with the content edge, not their button edge. */
.sheet-head {
  position: sticky;
  top: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 4px;
  margin: 0 -10px 4px;
  padding: 16px 0 8px;
  background: var(--surface);
}
.sheet-head > h2:first-child,
.sheet-head > [hidden]:first-child + h2 {
  padding-left: 10px;
}
.sheet h2 {
  flex: 1;
  text-wrap: balance;
  margin: 0;
  font-size: 22px;
  line-height: 1.25;
}
.settings-sheet .sheet-head {
  position: static;
  margin: 0;
  padding: 14px calc(var(--sheet-pad) - 10px) 10px var(--sheet-pad);
}
.settings-sheet .sheet-head > h2 {
  padding-left: 0;
}
/* Parts of the simpler sheets (TVs, phones): a hairline and a small heading. */
.sheet > section {
  margin-top: 24px;
  border-top: 1px solid var(--line);
}
.sheet > section > h3 {
  margin: 28px 0 4px;
  color: var(--text-2);
  font-size: 13px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
}

/* ---------- the Menu's sections ---------- */

/* On a phone the sections are a strip of pills under the title, scrolling sideways; on anything
   wider, a list down the left side. */
.settings-nav {
  display: flex;
  gap: 4px;
  padding: 0 var(--sheet-pad) 12px;
  overflow-x: auto;
  scrollbar-width: none;
}
.settings-nav::-webkit-scrollbar {
  display: none;
}
.nav-item {
  display: inline-flex;
  flex: none;
  align-items: center;
  gap: 8px;
  min-height: 40px;
  padding: 0 16px 0 12px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--text-2);
  font: inherit;
  font-size: 15px;
  font-weight: 700;
  white-space: nowrap;
  cursor: pointer;
  transition-property: background-color, color;
  transition-duration: 150ms;
  transition-timing-function: ease-out;
}
.nav-item svg {
  flex: none;
  width: 20px;
  height: 20px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
@media (hover: hover) {
  .nav-item:hover {
    background: var(--surface-2);
    color: var(--text);
  }
}
.nav-item[aria-selected='true'] {
  background: var(--accent);
  color: var(--accent-ink);
}

.pane {
  display: flex;
  flex-direction: column;
  gap: 24px;
  max-width: 640px;
}
.pane-title {
  margin: 0 0 -8px;
  font-size: 22px;
  font-weight: 700;
  line-height: 1.25;
}
.pane-note {
  margin: -12px 0 0;
  color: var(--text-2);
  font-size: 14px;
  line-height: 1.5;
  text-wrap: pretty;
}
/* On a phone the chosen pill names the section, so the pane's own title is only for screen readers.
   The strip fades out at its end, so a cut-off pill reads as "scroll for more". */
@media (max-width: 719px) {
  .settings-nav {
    padding-right: calc(var(--sheet-pad) + 28px);
    -webkit-mask-image: linear-gradient(to right, transparent, #000 8px, #000 calc(100% - 36px), transparent);
    mask-image: linear-gradient(to right, transparent, #000 8px, #000 calc(100% - 36px), transparent);
  }
  .menu-sheet .pane-title {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }
  .menu-sheet .pane-note {
    margin-top: 0;
  }
}
@media (min-width: 720px) {
  dialog.menu-sheet[open] {
    grid-template-columns: 232px minmax(0, 1fr);
  }
  .menu-sheet .sheet-top {
    display: contents;
  }
  .menu-sheet .sheet-head {
    grid-column: 1 / -1;
    border-bottom: 1px solid var(--line);
  }
  .menu-sheet .settings-nav {
    flex-direction: column;
    gap: 2px;
    padding: 16px 12px 24px var(--sheet-pad);
    overflow: hidden auto;
  }
  .menu-sheet .nav-item {
    justify-content: flex-start;
    min-height: 42px;
    padding: 0 12px;
    border-radius: 10px;
  }
  .menu-sheet .nav-item[aria-selected='true'] {
    background: color-mix(in srgb, var(--accent) var(--tint), transparent);
    color: var(--text);
  }
  .menu-sheet .nav-item[aria-selected='true'] svg {
    color: var(--accent);
  }
  .menu-sheet .settings-panes {
    padding: 22px var(--sheet-pad) var(--sheet-pad) 20px;
  }
}

/* TVs and phones: each kind of device in a row, its icon in a tinted circle and, for phones, the QR
   code beside the words; role="list" keeps them a list once the markers are gone. */
@media (min-width: 641px) {
  dialog.devices-sheet {
    width: min(600px, calc(100% - 32px));
  }
}
.ways {
  margin: 4px 0 0;
  padding: 0;
  list-style: none;
}
.way {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  padding: 14px 0;
}
.way + .way {
  border-top: 1px solid var(--line);
}
.way-icon {
  flex: none;
  width: 36px;
  height: 36px;
  padding: 7px;
  border-radius: 50%;
  background: var(--surface-2);
  background: color-mix(in srgb, var(--accent) var(--tint), transparent);
  fill: none;
  stroke: var(--accent);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.way-text {
  flex: 1;
  min-width: 0;
}
.way-text h3 {
  margin: 6px 0 4px;
  font-size: 17px;
  line-height: 1.35;
}
.way-text p {
  margin: 0;
  color: var(--text-2);
  font-size: 15px;
  line-height: 1.5;
  text-wrap: pretty;
}
.way-text .url {
  color: var(--text);
  font-size: 17px;
}
.way .qr {
  width: 136px;
}
/* On a phone the QR code goes under the words, still in line with them. */
@media (max-width: 480px) {
  .way {
    flex-wrap: wrap;
  }
  .way-text {
    flex-basis: calc(100% - 50px); /* the row beside the icon, so the QR code wraps under it */
  }
  .way .qr {
    margin-left: 50px;
  }
}

/* The one code box, for whichever TV or phone shows a code. */
.pair-form {
  margin-top: 16px;
}
.pair-form label {
  display: block;
  margin-bottom: 10px;
  font-size: 17px;
  font-weight: 700;
}

.url {
  display: inline-block;
  margin-top: 2px;
  font-size: 22px;
  overflow-wrap: anywhere;
}

.pair-row {
  display: flex;
  gap: 8px;
}
#pair-code {
  flex: 1;
  min-width: 0;
  min-height: 56px;
  font-size: 26px;
  font-weight: 700;
  letter-spacing: 0.25em;
  /* Balances the letter-spacing after the last character, so the code sits optically centered. */
  text-indent: 0.25em;
  text-align: center;
  text-transform: uppercase;
}
#pair-code::placeholder {
  letter-spacing: normal;
  font-weight: 400;
}
.pair-row .btn {
  min-height: 56px;
  padding: 0 22px;
  border-radius: 12px;
}

#devices-section > .btn {
  margin: 8px 0 0 -12px;
}
#tv-settings > .row {
  margin-top: 12px;
}
#tv-settings select {
  width: auto;
}
#tv-alert-hint,
#tv-popups-hint {
  margin-top: 6px;
}
#tv-popups-setting > .row {
  flex-wrap: wrap;
  margin-top: 12px;
}
/* The bell swings as it alerts the TV. */
#alert-btn.ringing svg {
  transform-origin: 50% 12%;
  animation: ring 700ms ease-in-out;
}
/* Look for TVs, lined up with the content edge like the sheet's other subtle buttons. */
.scan-row {
  margin-top: 4px;
}
#scan-tvs {
  margin-left: -12px;
}
/* The remote's Look for TVs icon turns while the helpers look. */
#remote-scan.looking svg {
  animation: turn 1s linear infinite;
}
@keyframes turn {
  to {
    rotate: 360deg;
  }
}
@keyframes ring {
  15% { rotate: 16deg; }
  35% { rotate: -14deg; }
  55% { rotate: 9deg; }
  75% { rotate: -5deg; }
}
.stepper {
  display: flex;
  gap: 6px;
}
.stepper .btn {
  min-width: 52px;
  background: var(--surface);
}

details {
  margin-top: 16px;
  font-size: 15px;
  line-height: 1.5;
}
summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  min-height: 44px;
  padding: 8px 0;
  font-weight: 700;
  list-style: none;
  cursor: pointer;
}
summary::-webkit-details-marker {
  display: none;
}
/* A chevron that turns to point down when open. */
summary::after {
  content: '';
  flex: none;
  width: 8px;
  height: 8px;
  margin-right: 6px;
  border-right: 2px solid var(--text-2);
  border-bottom: 2px solid var(--text-2);
  rotate: -45deg;
  transition: rotate 200ms var(--ease);
}
details[open] > summary::after {
  rotate: 45deg;
}
.link-row {
  display: flex;
  align-items: center;
  gap: 10px;
}
.link-row a {
  flex: 1;
  color: var(--accent);
  overflow-wrap: anywhere;
}

/* Saved conversations: one card of rows, newest first. */
.history-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
  align-items: flex-start;
  margin-top: 8px;
}
.history-list:has(.history-item) {
  gap: 0;
  align-items: stretch;
  border-radius: 16px;
  background: var(--surface-2);
  box-shadow: var(--ring);
  overflow: hidden;
}
.history-list > .hint {
  margin: 0;
}
.history-item {
  display: block;
  width: 100%;
  padding: 14px 16px;
  border: 0;
  background: transparent;
  color: var(--text);
  font: inherit;
  text-align: left;
  transition: background-color 150ms ease-out;
}
.history-item + .history-item {
  border-top: 1px solid var(--line);
}
@media (hover: hover) {
  .history-item:hover {
    background: var(--surface-3);
  }
}
.history-item:focus-visible {
  outline-offset: -3px;
}
.history-item strong {
  display: block;
  font-size: 16px;
}
.history-item span {
  display: block;
  margin-top: 4px;
  overflow: hidden;
  color: var(--text-2);
  font-size: 14px;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.captions.readonly {
  margin-top: 16px;
  padding: 0;
  overflow: visible;
  font-size: 20px;
}

/* ---------- display panel ---------- */

/* The preview stays in view while the controls scroll, so every change shows at once. */
.display-sheet .sheet-top {
  padding: 0 var(--sheet-pad) 14px;
}
.display-sheet .sheet-head {
  padding-inline: calc(var(--sheet-pad) - 10px) 0;
  margin-left: -10px;
}
.display-sheet .sheet-head > h2 {
  padding-left: 10px;
}
.display-sheet .settings-panes {
  padding-top: 22px;
}
/* On short screens the preview scrolls away with the rest, leaving room for the controls. */
@media (max-height: 640px) {
  dialog.display-sheet[open] {
    display: block;
    overflow-y: auto;
  }
  .display-sheet .settings-panes {
    overflow: visible;
  }
}

.captions.preview {
  flex: none;
  overflow: hidden;
  padding: 14px 16px 12px;
  border-radius: 16px;
  background: var(--bg);
  box-shadow: var(--ring);
  /* Follows the size setting without letting the largest sizes swallow the panel. */
  font-size: clamp(18px, calc(var(--caption-size) * 0.75), 34px);
}
.captions.preview .line {
  margin: 0;
}

.contrast {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 10px 2px 0;
  color: var(--text-2);
  font-size: 14px;
  font-variant-numeric: tabular-nums;
}
.contrast::before {
  content: '';
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--ok);
}
.contrast[data-level='fair']::before {
  background: var(--warn);
}
.contrast[data-level='poor'] {
  color: var(--danger);
  font-weight: 700;
}
.contrast[data-level='poor']::before {
  background: var(--danger);
}

/* The settings in two columns when there's room, each a stack of groups. */
.sheet-columns {
  display: flex;
  flex-direction: column;
  gap: 24px;
}
.sheet-columns > .column {
  display: flex;
  flex-direction: column;
  gap: 24px;
  min-width: 0;
}
@media (min-width: 900px) {
  .sheet-columns {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 24px 28px;
    align-items: start;
  }
}

/* Picture choices (themes, fonts): the chosen tile is outlined in the accent color. */
.tiles {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 8px;
}
.tile {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 6px 6px 8px;
  border-radius: 16px;
  box-shadow: var(--ring);
  cursor: pointer;
  transition-property: background-color, box-shadow;
  transition-duration: 150ms;
  transition-timing-function: ease-out;
}
@media (hover: hover) {
  .tile:hover {
    box-shadow: var(--ring-hover);
  }
}
.tile input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}
.tile:has(input:checked) {
  background: color-mix(in srgb, var(--accent) var(--tint), transparent);
  box-shadow: inset 0 0 0 2px var(--accent);
}
.tile:has(input:focus-visible) {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}
.tile-name {
  font-size: 14px;
  font-weight: 700;
  line-height: 1.25;
  text-align: center;
}
/* Each swatch carries its own data-theme, so it shows that theme's real colors. Radius = tile radius − padding. */
.theme-swatch {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  height: 52px;
  padding: 0 12px;
  border-radius: 10px;
  background: var(--bg);
  box-shadow: inset 0 0 0 1px rgb(128 128 128 / 0.3);
  color: var(--text);
  font-size: 22px;
  font-weight: 700;
}
.theme-swatch[data-theme='auto'] {
  background: linear-gradient(135deg, #f7f8fa 50%, #0e1015 50%);
  color: #7d8390;
}
.theme-dot {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--accent);
}
.font-aa {
  display: grid;
  place-items: center;
  width: 100%;
  height: 52px;
  border-radius: 10px;
  background: var(--surface-2);
  font-size: 26px;
  font-weight: var(--cap-weight);
  line-height: 1;
}

/* Color choices. */
.swatches {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  padding: 2px;
}
.swatch {
  position: relative;
  display: grid;
  cursor: pointer;
}
.swatch input {
  position: absolute;
  opacity: 0;
  pointer-events: none;
}
.sw {
  display: grid;
  place-items: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--sw);
  box-shadow: inset 0 0 0 1px rgb(128 128 128 / 0.45);
  font-size: 18px;
  font-weight: 700;
  transition: box-shadow 150ms ease-out;
}
.swatch input:checked + .sw {
  box-shadow: inset 0 0 0 1px rgb(128 128 128 / 0.45), 0 0 0 3px var(--surface-2), 0 0 0 5px var(--accent);
}
.swatch input:focus-visible + .sw {
  outline: 3px solid var(--accent);
  outline-offset: 6px;
}
/* "Theme color": an A in the theme's own text color. */
.sw-theme {
  background: var(--bg);
  color: var(--text);
}
/* "No background": a struck-through circle. */
.sw-none {
  background:
    linear-gradient(to top right, transparent calc(50% - 1.5px), var(--text-2) calc(50% - 1.5px), var(--text-2) calc(50% + 1.5px), transparent calc(50% + 1.5px)),
    var(--surface);
}
.sw-custom {
  background: conic-gradient(#ff6b6b, #ffd54a, #8be58b, #6fd3ff, #8fb0ff, #c3a6ff, #ff8fc7, #ff6b6b);
}

.color-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.color-field {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  width: fit-content;
  padding: 6px 14px 6px 6px;
  border-radius: 14px;
  box-shadow: var(--ring);
  font-size: 15px;
  font-weight: 700;
  cursor: pointer;
}
@media (hover: hover) {
  .color-field:hover {
    box-shadow: var(--ring-hover);
  }
}
input[type='color'] {
  flex: none;
  width: 40px;
  height: 40px;
  padding: 0;
  border: 0;
  border-radius: 8px;
  appearance: none;
  background: none;
  cursor: pointer;
}
input[type='color']::-webkit-color-swatch-wrapper {
  padding: 0;
}
input[type='color']::-webkit-color-swatch {
  border: 0;
  border-radius: 8px;
  box-shadow: inset 0 0 0 1px rgb(128 128 128 / 0.45);
}
input[type='color']::-moz-color-swatch {
  border: 0;
  border-radius: 8px;
}

.sheet-foot {
  margin-top: 24px;
}

/* ---------- overlays ---------- */

/* Sits above the composer, or at the bottom of the screen when app.js moves it into an open dialog. */
.toast {
  position: absolute;
  left: 50%;
  bottom: calc(100% + 12px);
  z-index: 50;
  width: max-content;
  max-width: calc(100% - 32px);
  padding: 12px 18px;
  border-radius: 14px;
  background: var(--text);
  color: var(--bg);
  font-size: 16px;
  font-weight: 700;
  line-height: 1.4;
  text-wrap: pretty;
  transform: translateX(-50%);
  box-shadow: 0 8px 30px rgb(0 0 0 / 0.35);
  animation: pop-in 250ms var(--ease);
}
dialog .toast {
  position: fixed;
  bottom: max(16px, env(safe-area-inset-bottom));
}

.big-reply {
  width: 100%;
  max-width: none;
  height: 100%;
  max-height: none;
  margin: 0;
  padding: 24px;
  border: 0;
  background: var(--bg);
  color: var(--text);
  text-align: center;
  cursor: pointer;
  transition-property: opacity;
  transition-duration: 200ms;
  transition-timing-function: var(--ease);
}
@starting-style {
  .big-reply[open] {
    opacity: 0;
  }
}
.big-reply[open] {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}
.big-reply p {
  max-height: 85dvh;
  margin: 0;
  overflow-y: auto;
  font-size: clamp(34px, 9vw, 120px);
  font-weight: 700;
  line-height: 1.2;
  overflow-wrap: anywhere;
  text-wrap: balance;
}
.big-reply .hint {
  position: absolute;
  bottom: max(16px, env(safe-area-inset-bottom));
}

/* ---------- high contrast ---------- */

[data-theme='contrast'] .status,
[data-theme='contrast'] .banner,
[data-theme='contrast'] button.who,
[data-theme='contrast'] .who.as-button {
  box-shadow: inset 0 0 0 1px currentColor;
}
/* With no tint to show it, the chosen Menu section is outlined. */
[data-theme='contrast'] .menu-sheet .nav-item[aria-selected='true'] {
  box-shadow: inset 0 0 0 2px var(--accent);
}

/* Short landscape screens: quick replies sit beside the reply box, so captions keep most of the height. */
@media (max-height: 30rem) and (min-width: 34rem) {
  .composer {
    display: flex;
    align-items: center;
    gap: 8px;
  }
  .phrases {
    flex: 1 1 0;
    min-width: 0;
    margin: -6px 0 -6px calc(-1 * var(--pad-l));
    padding-right: 24px;
  }
  .reply-row {
    flex: 1.4 1 0;
    min-width: 0;
  }
}

/* Set by display.js for a moment while the theme changes. */
[data-no-transitions] *,
[data-no-transitions] *::before,
[data-no-transitions] *::after {
  transition: none !important;
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation: none !important;
    transition-duration: 0s !important;
    scroll-behavior: auto !important;
  }
}

/* ---------- phone microphones (the app's sheet, and the /mic page) ---------- */

.status.phones .meter {
  visibility: hidden;
}

/* Scanners need dark modules on light, whatever the theme. */
.qr {
  flex: none;
  width: 168px;
  padding: 6px;
  border-radius: 12px;
  background: #fff;
}
.qr svg {
  display: block;
  width: 100%;
  height: auto;
  fill: #000;
  shape-rendering: crispEdges;
}
.device-list {
  margin: 8px 0 0;
  padding: 0;
  list-style: none;
}
.device-item {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 0;
  border-bottom: 1px solid var(--line);
}
.device-item:last-child {
  border-bottom: 0;
}
.device-label {
  flex: 1;
  min-width: 0;
  overflow-wrap: anywhere;
}
.device-label input {
  width: 100%;
  margin-bottom: 4px;
}
.device-item[data-state='live'] {
  --state: var(--ok);
}
.device-item[data-state='starting'] {
  --state: var(--warn);
}
/* The account: its name, who is signed in, and today's cloud captions. */
.account-summary {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 14px 16px 16px;
  border-radius: 16px;
  background: var(--surface-2);
  box-shadow: var(--ring);
}
.account-summary > p {
  margin: 0;
}
.account-summary > .account-org {
  font-size: 19px;
  font-weight: 700;
  line-height: 1.3;
}
.account-summary > .account-who {
  color: var(--text-2);
  font-size: 14px;
  line-height: 1.45;
}
#account-usage {
  margin-top: 8px;
  font-size: 15px;
  line-height: 1.45;
}

/* People in the account; the owner can give one a new password or remove them. */
.member-item {
  flex-wrap: wrap;
}
.member-actions {
  display: flex;
  gap: 4px;
}
.member-password {
  flex-basis: 100%;
}
#invite-row input {
  flex: 1;
  min-width: 0;
}

/* Sign-in, sign-up and password forms */
.form-msg {
  margin: 8px 0;
  color: var(--danger);
  font-size: 15px;
  line-height: 1.5;
}
.form-msg:empty {
  display: none;
}
.form-switch {
  margin: 16px 0 0;
  color: var(--text-2);
  font-size: 15px;
}
.link-btn {
  padding: 0;
  border: 0;
  background: none;
  color: var(--accent);
  font: inherit;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
:is(input, textarea, select)[aria-invalid='true'] {
  border-color: var(--danger);
}

/* A TV the TV helper can switch to captions: its name and button, then how it shows them, lined
   up with its name past the dot. */
.remote-item {
  flex-wrap: wrap;
  row-gap: 8px;
}
.remote-item > :is(.remote-way, .toggle, .remote-status, .remote-pin) {
  flex-basis: 100%;
  margin: 0;
  padding-left: 22px;
}
.remote-way {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 15px;
}
.remote-way select {
  flex: 1;
  width: auto;
  min-width: 0;
  padding: 8px 38px 8px 12px;
  font-size: 16px;
}
.remote-item > .toggle > label {
  font-size: 15px;
}
.remote-status:empty {
  display: none;
}
.remote-status:is([data-state='asking'], [data-state='pin']) {
  color: var(--text);
  font-weight: 700;
}
.remote-pin {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 15px;
}
.remote-pin input {
  flex: none;
  width: 9ch;
  padding: 8px 12px;
  font-size: 20px;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-align: center;
}
.remote-status[data-state='failed'] {
  color: var(--danger);
}
.helper-list {
  margin-top: 0;
  border-top: 1px solid var(--line);
}

/* The TV remote: a column of big keys laid out as a TV's remote is, so they're found by thumb. Keys
   stand a step up from the sheet, lit from above, and sink when pressed. They press on touch and
   some repeat while held, so they don't select or call up menus. */
.remote-sheet {
  --key: var(--surface-2);
  --key-raised: var(--surface-3); /* the chosen tab, and OK in the middle of the arrows */
  --key-press: color-mix(in srgb, var(--text) 10%, transparent); /* over a part of a key: an arrow, half a rocker */
  --key-edge: inset 0 1px 0 rgb(255 255 255 / 0.05), 0 0 0 1px rgb(255 255 255 / 0.07), 0 2px 6px -2px rgb(0 0 0 / 0.55);
  --key-sunk: inset 0 2px 5px rgb(0 0 0 / 0.35), 0 0 0 1px rgb(255 255 255 / 0.05);
}
:is([data-theme='light'], [data-theme='paper'], [data-theme='custom'][data-mode='light']) .remote-sheet {
  --key-raised: var(--surface);
  --key-edge: inset 0 1px 0 rgb(255 255 255 / 0.8), 0 0 0 1px rgb(0 0 0 / 0.08), 0 1px 3px rgb(16 24 40 / 0.12);
  --key-sunk: inset 0 2px 4px rgb(16 24 40 / 0.16), 0 0 0 1px rgb(0 0 0 / 0.08);
}
[data-theme='contrast'] .remote-sheet {
  --key-edge: 0 0 0 1px #fff;
  --key-sunk: 0 0 0 2px #fff;
}
@media (min-width: 641px) {
  dialog.remote-sheet {
    width: min(420px, calc(100% - 32px));
  }
}
/* On a phone the remote gets nearly the whole height, so more of its keys fit on one screen. */
@media (max-width: 640px) {
  dialog.remote-sheet {
    max-height: 94dvh;
  }
}
/* Focus starts on the title, for screen readers; it isn't something to press, so it gets no ring. */
#remote-title:focus {
  outline: none;
}

/* The TV it controls: an icon with a dot for on or off, its name, and what it shows. With several,
   the list of them covers the card, unseen, so a tap anywhere on it opens the list; a chevron says so. */
.remote-tv {
  position: relative;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 6px 10px 10px;
  border-radius: 18px;
  background: var(--surface-2);
  box-shadow: var(--ring);
  transition: background-color 150ms ease-out;
}
.remote-tv[data-state='live'] {
  --state: var(--ok);
}
.remote-tv-icon {
  position: relative;
  display: grid;
  flex: none;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 12px;
  background: color-mix(in srgb, var(--accent) var(--tint), var(--surface-3));
  color: var(--accent);
}
.remote-tv-icon svg {
  width: 24px;
  height: 24px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.remote-tv-icon .dot {
  position: absolute;
  right: -3px;
  bottom: -3px;
  width: 13px;
  height: 13px;
  box-shadow: 0 0 0 3px var(--surface-2);
}
.remote-tv-text {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
  padding-right: 4px;
}
#remote-tv-name {
  display: -webkit-box;
  overflow: hidden;
  font-size: 17px;
  line-height: 1.3;
  overflow-wrap: anywhere;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
}
.remote-tv-state {
  color: var(--text-2);
  font-size: 14px;
  line-height: 1.35;
}
.remote-tv select {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  padding: 0;
  opacity: 0;
  cursor: pointer;
}
.remote-tv:has(> select:not([hidden]))::after {
  content: '';
  flex: none;
  order: 1;
  width: 9px;
  height: 9px;
  margin: 0 10px 5px 0;
  border-right: 2px solid var(--text-2);
  border-bottom: 2px solid var(--text-2);
  rotate: 45deg;
}
.remote-tv:has(> select:focus-visible) {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}
@media (hover: hover) {
  .remote-tv:has(> select:not([hidden])):hover {
    background: var(--surface-3);
  }
  .remote-tv:has(> select:not([hidden])):hover .dot {
    box-shadow: 0 0 0 3px var(--surface-3);
  }
}
/* Above the unseen list, so it's pressed by itself. */
#remote-scan {
  order: 2;
  color: var(--text-2);
}

/* How the last thing asked of the TV went, in its state's color: working, done, failed, or waiting
   for someone (to answer on the TV, or to type its PIN below). */
#remote-status {
  --state: var(--text-2);
  display: flex;
  align-items: baseline;
  gap: 10px;
  margin: 10px 0 0;
  padding: 10px 14px;
  border-radius: 14px;
  background: color-mix(in srgb, var(--state) var(--tint), var(--surface));
  color: var(--text);
  font-size: 15px;
  line-height: 1.4;
  text-wrap: pretty;
}
#remote-status:empty {
  display: none;
}
#remote-status::before {
  content: '';
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--state);
  translate: 0 -1px;
}
#remote-status[data-state='working'] {
  --state: var(--warn);
}
#remote-status[data-state='working']::before {
  animation: pulse 1.1s ease-in-out infinite;
}
#remote-status[data-state='done'] {
  --state: var(--ok);
}
#remote-status:is([data-state='asking'], [data-state='pin']) {
  --state: var(--accent);
}
#remote-status[data-state='failed'] {
  --state: var(--danger);
  color: var(--text);
}
.remote-sheet .remote-pin {
  margin-top: 10px;
  padding: 10px 10px 10px 16px;
  border-radius: 16px;
  background: var(--surface-2);
  box-shadow: var(--ring);
  font-weight: 700;
}
.remote-sheet .remote-pin input {
  flex: 1;
  min-width: 0;
}

/* No TV to control: a large icon, why, and what can be done from here. */
.remote-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 24px 8px 8px;
  text-align: center;
}
.remote-empty-icon {
  display: grid;
  place-items: center;
  width: 84px;
  height: 84px;
  border-radius: 50%;
  background: var(--surface-2);
  box-shadow: var(--ring);
  color: var(--text-2);
}
.remote-empty-icon svg {
  width: 42px;
  height: 42px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.remote-empty-icon [data-why] {
  display: none;
}
.remote-empty[data-why='offline'] [data-why='offline'],
.remote-empty[data-why='outdated'] [data-why='outdated'] {
  display: inline;
}
.remote-empty h3 {
  margin: 20px 0 6px;
  font-size: 20px;
  line-height: 1.3;
  text-wrap: balance;
}
.remote-empty p {
  max-width: 34ch;
  margin: 0;
  color: var(--text-2);
  font-size: 15px;
  line-height: 1.5;
  text-wrap: pretty;
}
.remote-empty .btn {
  margin-top: 22px;
}
#remote-empty-scan.looking svg {
  animation: turn 1s linear infinite;
}

.remote-pad {
  display: flex;
  flex-direction: column;
  gap: 14px;
  max-width: 340px;
  margin: 20px auto 0;
}
.remote-pad button {
  display: inline-grid;
  place-items: center;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--text);
  font: inherit;
  touch-action: manipulation;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
  transition-property: background-color, box-shadow, color, scale;
  transition-duration: 150ms;
  transition-timing-function: ease-out;
}
.remote-pad svg {
  width: 24px;
  height: 24px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
/* A key on its own: Power, Back, Home, Mute, a number, an app. A key that's two or more (the arrows,
   a rocker, the playback bar) is one raised shape, and only the part pressed darkens. */
.remote-pad :is(.remote-key, .rocker, .remote-dpad, .remote-media, .remote-numbers button, .remote-colors button, .remote-input, .remote-app) {
  background: var(--key);
  box-shadow: var(--key-edge);
}
@media (hover: hover) {
  .remote-pad :is(.remote-key, .remote-numbers button, .remote-colors button, .remote-input, .remote-app):hover {
    background: color-mix(in srgb, var(--key), var(--text) 5%);
  }
  .remote-pad :is(.rocker, .remote-media) button:hover,
  .remote-dpad > button:not(.dpad-ok):hover {
    background: color-mix(in srgb, var(--text) 5%, transparent);
  }
}
/* After hovering, so a press shows under a mouse too. */
.remote-pad :is(.remote-key, .remote-numbers button, .remote-colors button, .remote-input, .remote-app):is(:active, .pressed) {
  background: var(--surface-3);
  box-shadow: var(--key-sunk);
  scale: 0.96;
}
.remote-pad :is(.rocker, .remote-media) button:is(:active, .pressed),
.remote-dpad > button:not(.dpad-ok):is(:active, .pressed) {
  background: var(--key-press);
}
/* Its icon, and its name under it. */
.remote-pad .remote-key {
  gap: 4px;
  height: 60px;
  border-radius: 18px;
  font-size: 13px;
  font-weight: 700;
  line-height: 1;
}
.remote-pad .remote-key svg {
  width: 22px;
  height: 22px;
}

.remote-top {
  display: flex;
  gap: 12px;
}
.remote-pad .remote-key.power {
  flex: none;
  width: 60px;
  border-radius: 50%;
  color: var(--danger);
}
.remote-pad .remote-key.power svg {
  width: 24px;
  height: 24px;
  stroke-width: 2.4;
}
/* The remote's own button, in the accent color; once the TV shows captions, Stop is a plain key. */
.remote-pad .remote-captions {
  display: inline-flex;
  flex: 1;
  gap: 10px;
  min-height: 60px;
  border-radius: 20px;
  background: var(--accent);
  box-shadow: 0 6px 16px -8px color-mix(in srgb, var(--accent) 80%, transparent);
  color: var(--accent-ink);
  font-size: 17px;
  font-weight: 700;
}
.remote-pad .remote-captions:active {
  scale: 0.97;
}
@media (hover: hover) {
  .remote-pad .remote-captions:hover {
    background: var(--accent-hover);
  }
}
.remote-pad .remote-captions.showing {
  background: var(--key);
  box-shadow: var(--key-edge);
  color: var(--text);
}
.remote-pad .remote-captions.showing svg {
  color: var(--ok);
}
@media (hover: hover) {
  .remote-pad .remote-captions.showing:hover {
    background: color-mix(in srgb, var(--key), var(--text) 5%);
  }
}

/* The arrows: each a quarter of the ring, cut on the diagonals, so a thumb anywhere in it presses
   the right one; OK is raised in the middle. */
.remote-dpad {
  position: relative;
  align-self: center;
  width: min(100%, 244px);
  aspect-ratio: 1;
  overflow: hidden;
  border-radius: 50%;
  isolation: isolate;
}
.remote-dpad > button:not(.dpad-ok) {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  color: var(--text-2);
}
.remote-dpad > button:not(.dpad-ok):is(:active, .pressed) {
  color: var(--text);
}
.remote-dpad > button:not(.dpad-ok):focus-visible {
  outline: none;
  background: color-mix(in srgb, var(--accent) 22%, transparent);
  color: var(--accent);
}
.remote-dpad svg {
  width: 28px;
  height: 28px;
  stroke-width: 2.4;
}
.remote-dpad .dpad-up {
  clip-path: polygon(0 0, 100% 0, 50% 50%);
  place-items: start center;
  padding-top: 11%;
}
.remote-dpad .dpad-down {
  clip-path: polygon(0 100%, 100% 100%, 50% 50%);
  place-items: end center;
  padding-bottom: 11%;
}
.remote-dpad .dpad-left {
  clip-path: polygon(0 0, 0 100%, 50% 50%);
  place-items: center start;
  padding-left: 11%;
}
.remote-dpad .dpad-right {
  clip-path: polygon(100% 0, 100% 100%, 50% 50%);
  place-items: center end;
  padding-right: 11%;
}
.remote-pad .dpad-ok {
  position: absolute;
  z-index: 1;
  top: 30%;
  left: 30%;
  width: 40%;
  height: 40%;
  border-radius: 50%;
  background: var(--key-raised);
  box-shadow: var(--key-edge), 0 0 0 6px color-mix(in srgb, var(--key) 60%, transparent);
  font-size: 19px;
  font-weight: 700;
  letter-spacing: 0.02em;
}
.remote-pad .dpad-ok:is(:active, .pressed) {
  background: var(--key-raised);
  box-shadow: var(--key-sunk);
  scale: 0.95;
}
@media (hover: hover) {
  .remote-pad .dpad-ok:hover {
    background: color-mix(in srgb, var(--key-raised), var(--text) 5%);
  }
}

/* Back, Home and Menu share the width, whichever of them the TV has. */
.remote-row {
  display: grid;
  grid-auto-columns: 1fr;
  grid-auto-flow: column;
  gap: 12px;
}

/* Volume and channel are rockers either side of Mute and Input; a missing one leaves its place empty. */
.remote-levels {
  display: grid;
  grid-template-columns: 72px 1fr 72px;
  gap: 12px;
}
.rocker {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  border-radius: 36px;
}
.rocker:first-child {
  grid-column: 1;
}
.rocker:last-child {
  grid-column: 3;
}
.remote-pad .rocker button {
  height: 58px;
  border-radius: 36px;
}
.rocker-label {
  color: var(--text-2);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.08em;
  line-height: 1;
  text-align: center;
  text-transform: uppercase;
}
/* Mute and Input stack between them; either alone sits halfway down. */
.remote-middle {
  display: grid;
  grid-column: 2;
  align-content: center;
  gap: 12px;
}
.remote-pad .remote-middle .remote-key {
  height: 62px;
}

/* The TV's volume, as an LG says it: the slider fills to it, and greys while it's muted. */
.remote-volume {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 0 4px 0 8px;
}
.remote-pad .remote-volume-icon {
  flex: none;
  width: 22px;
  height: 22px;
  color: var(--text-2);
}
.remote-volume .cross,
.remote-volume.muted .waves {
  display: none;
}
.remote-volume.muted .cross {
  display: inline;
}
.remote-volume input[type='range'] {
  flex: 1;
  height: 44px;
  transition: opacity 150ms ease-out;
}
.remote-volume.muted input[type='range'] {
  opacity: 0.5;
}
.remote-volume input[type='range']::-webkit-slider-runnable-track {
  height: 8px;
  border-radius: 4px;
  background: linear-gradient(to right, var(--accent) calc(13px + (100% - 26px) * var(--level, 0) / 100), var(--surface-3) 0);
}
.remote-volume input[type='range']::-webkit-slider-thumb {
  width: 26px;
  height: 26px;
  margin-top: -9px;
  background: var(--text);
  box-shadow: 0 0 0 1px rgb(0 0 0 / 0.1), 0 2px 6px rgb(0 0 0 / 0.35);
}
.remote-volume input[type='range']::-moz-range-track {
  height: 8px;
  border-radius: 4px;
}
.remote-volume input[type='range']::-moz-range-progress {
  height: 8px;
  border-radius: 4px;
}
.remote-volume input[type='range']::-moz-range-thumb {
  width: 26px;
  height: 26px;
  background: var(--text);
  box-shadow: 0 0 0 1px rgb(0 0 0 / 0.1), 0 2px 6px rgb(0 0 0 / 0.35);
}
#remote-volume-value {
  min-width: 3ch;
  color: var(--text-2);
  font-size: 15px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  text-align: end;
}

/* Rewind, play, pause, fast forward and stop: one bar, as on most remotes. */
.remote-media {
  display: flex;
  gap: 2px;
  height: 56px;
  padding: 4px;
  border-radius: 18px;
}
.remote-pad .remote-media button {
  flex: 1;
  border-radius: 14px;
}
.remote-pad .remote-media svg {
  width: 22px;
  height: 22px;
  fill: currentColor;
  stroke-width: 1.5;
}
.remote-pad .remote-media [data-key='pause'] svg {
  stroke-width: 3.2;
}

/* The less-used controls: a tab for each the TV has, an icon over its name. */
.remote-tabs {
  margin-top: 10px;
}
.remote-tabs > label > span {
  gap: 4px;
  min-height: 58px;
  padding: 8px 2px 7px;
  font-size: 13px;
}
.remote-tabs svg {
  width: 20px;
  height: 20px;
}
.remote-tabs input:checked + span {
  background: var(--key-raised);
  box-shadow: var(--key-edge);
  color: var(--text);
}
.remote-tabs input:checked + span svg {
  color: var(--accent);
}
#remote-apps-tab {
  display: inline;
  min-height: 0;
  padding: 0;
  color: inherit;
}
.remote-panel {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.remote-panel:not(.chosen) {
  display: none;
}
/* The tab names the panel; a TV with only one panel has no tabs, so its title shows instead. */
.remote-panel-title {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.remote-tabs[hidden] ~ .remote-panel .remote-panel-title {
  position: static;
  width: auto;
  height: auto;
  margin: 10px 0 0;
  overflow: visible;
  clip-path: none;
  color: var(--text-2);
  font-size: 13px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
}
.remote-panel .hint {
  margin: 0;
}

/* Inputs are chips; apps are tiles, each with its initial on a color of its own. The one the TV
   shows is outlined. */
.remote-find {
  width: 100%;
  min-height: 46px;
  padding: 10px 14px 10px 42px;
  border: 1px solid var(--field-border);
  border-radius: 14px;
  appearance: none;
  background: var(--bg) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238b919d' stroke-width='2.2' stroke-linecap='round'%3E%3Ccircle cx='10.5' cy='10.5' r='6.5'/%3E%3Cpath d='m15.5 15.5 5 5'/%3E%3C/svg%3E") no-repeat 14px center / 18px;
  color: var(--text);
  font: inherit;
  font-size: 17px;
}
.remote-find::-webkit-search-decoration {
  appearance: none;
}
.remote-sources {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.remote-sources h4 {
  margin: 4px 0 -2px;
  color: var(--text-2);
  font-size: 13px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
}
.remote-inputs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.remote-pad .remote-input {
  display: inline-flex;
  gap: 8px;
  min-height: 44px;
  max-width: 100%;
  padding: 0 16px 0 12px;
  border-radius: 14px;
  font-size: 15px;
  font-weight: 700;
  overflow-wrap: anywhere;
}
.remote-input::before {
  content: '';
  flex: none;
  width: 18px;
  height: 18px;
  background: var(--text-2);
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14 3.5h4.5a2 2 0 0 1 2 2v13a2 2 0 0 1-2 2H14M9.5 16.5 14 12 9.5 7.5M14 12H3.5'/%3E%3C/svg%3E") center / contain no-repeat;
}
.remote-apps {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
  gap: 10px;
}
.remote-pad .remote-app {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  gap: 8px;
  min-width: 0;
  min-height: 108px;
  padding: 14px 6px 10px;
  border-radius: 18px;
}
.remote-app-mark {
  display: grid;
  flex: none;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: 13px;
  background: color-mix(in srgb, var(--mark) 22%, var(--surface));
  color: var(--mark);
  font-size: 21px;
  font-weight: 700;
  line-height: 1;
}
.remote-app-mark[data-color='1'] { --mark: var(--spk-1); }
.remote-app-mark[data-color='2'] { --mark: var(--spk-2); }
.remote-app-mark[data-color='3'] { --mark: var(--spk-3); }
.remote-app-mark[data-color='4'] { --mark: var(--spk-4); }
.remote-app-mark[data-color='5'] { --mark: var(--spk-5); }
.remote-app-mark[data-color='6'] { --mark: var(--spk-6); }
.remote-app-name {
  display: -webkit-box;
  max-width: 100%;
  overflow: hidden;
  font-size: 13px;
  font-weight: 700;
  line-height: 1.25;
  overflow-wrap: anywhere;
  text-align: center;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  line-clamp: 2;
}
.remote-pad :is(.remote-app, .remote-input)[aria-current='true'] {
  box-shadow: inset 0 0 0 2px var(--accent), var(--key-edge);
}

.remote-type {
  display: flex;
  gap: 8px;
}
.remote-type input {
  flex: 1;
  min-width: 0;
}
.remote-pad .remote-type .btn {
  min-height: 48px;
  padding: 0 20px;
  border-radius: 14px;
}

/* Shaped like the TV's screen, and all of it the TV's: no scrolling, zooming or selecting here. Dots
   like a laptop's touchpad say it's one. */
.remote-touchpad {
  display: grid;
  place-items: center;
  aspect-ratio: 16 / 10;
  max-height: 45dvh;
  border-radius: 22px;
  background: radial-gradient(circle at 1px 1px, color-mix(in srgb, var(--text) 12%, transparent) 1px, transparent 0) 7px 7px / 16px 16px, var(--key);
  box-shadow: var(--key-sunk);
  cursor: crosshair;
  touch-action: none;
  user-select: none;
  -webkit-user-select: none;
  -webkit-touch-callout: none;
  transition: background-color 150ms ease-out;
}
.remote-touchpad:active {
  background-color: var(--surface-3);
}
.remote-touchpad svg {
  width: 32px;
  height: 32px;
  fill: none;
  stroke: var(--text-2);
  stroke-width: 1.6;
  stroke-linejoin: round;
  opacity: 0.6;
}

.remote-numbers {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
}
.remote-pad .remote-numbers button {
  height: 54px;
  border-radius: 16px;
  font-size: 21px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}
/* 0 sits under 8, with Dash to its left where the TV has one. */
.remote-numbers [data-key='0'] {
  grid-column: 2;
}
.remote-colors {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 10px;
}
/* The colors of a TV remote's buttons, the same in every theme. */
.remote-pad .remote-colors button {
  height: 46px;
  border-radius: 14px;
}
.remote-colors button::before {
  content: '';
  width: 32px;
  height: 8px;
  border-radius: 4px;
}
.remote-colors .red::before { background: #e5484d; }
.remote-colors .green::before { background: #30a46c; }
.remote-colors .yellow::before { background: #f5d90a; }
.remote-colors .blue::before { background: #3e63dd; }
.remote-extras {
  display: grid;
  grid-auto-columns: 1fr;
  grid-auto-flow: column;
  gap: 10px;
}

/* On a phone the remote fills the width, a little tighter, so its main keys fit on one screen. */
@media (max-width: 640px) {
  .remote-pad {
    gap: 12px;
    max-width: none;
    margin-top: 16px;
  }
  .remote-pad .remote-key,
  .remote-pad .remote-captions {
    height: 56px;
    min-height: 56px;
  }
  .remote-pad .remote-key.power {
    width: 56px;
  }
  .remote-dpad {
    width: min(100%, 232px);
  }
}
/* With colors forced, keys keep an outline, as backgrounds and shadows are gone. */
@media (forced-colors: active) {
  .remote-pad :is(.remote-key, .remote-captions, .rocker, .remote-dpad, .dpad-ok, .remote-media, .remote-numbers button, .remote-colors button, .remote-input, .remote-app),
  .remote-tv,
  .remote-touchpad {
    border: 1px solid ButtonText;
  }
  .remote-colors button::before,
  .remote-app-mark {
    forced-color-adjust: none;
  }
}
#helper-about code {
  flex: 1;
  font-size: 0.95em;
  overflow-wrap: anywhere;
  user-select: all; /* one tap selects the whole command */
}

/* Lost its connection (usually the phone's screen locked); it comes back when the phone wakes. */
.device-item[data-state='away'] .dot {
  background: transparent;
  box-shadow: inset 0 0 0 2px var(--spk-0);
}
.device-item[data-state='away'] strong {
  color: var(--text-2);
}

body.mic-page {
  height: auto;
  min-height: 100dvh;
  overflow: auto;
}
.mic-brand {
  margin: 0;
  padding: 10px 0;
  font-size: 15px;
  font-weight: 700;
}
.mic-main {
  width: min(32rem, 100%);
  margin: 0 auto;
  padding: 20px 16px max(32px, env(safe-area-inset-bottom));
  font-size: 17px;
  line-height: 1.45;
}
.mic-main h1 {
  margin: 8px 0 12px;
  font-size: 26px;
  line-height: 1.2;
  text-wrap: balance;
}
.mic-main .lead {
  margin: 0;
}
.mic-code {
  margin: 20px 0;
  font-size: clamp(44px, 16vw, 72px);
  font-weight: 700;
  letter-spacing: 0.18em;
  text-indent: 0.18em;
  text-align: center;
}
/* The same state-tinted pill as the app's top bar, sized for the page. */
.mic-status {
  min-height: 48px;
  padding: 12px 16px 12px 14px;
  border-radius: 16px;
  font-size: 17px;
}
.mic-status #status-text {
  flex: 1;
}
.btn.wide {
  width: 100%;
}
.heard {
  min-height: 7.5em;
  margin: 18px 0 0;
  padding: 14px 16px;
  border-radius: 16px;
  background: var(--bg);
  box-shadow: var(--ring);
  font-size: 22px;
  line-height: 1.35;
}
.heard.empty {
  color: var(--text-2);
  font-size: 17px;
}
/* ---------- the admin page, for the server's admins (admin.html) ---------- */

body.admin-page {
  height: auto;
  min-height: 100dvh;
  overflow: auto;
}
.admin-main {
  width: min(72rem, 100%);
  margin: 0 auto;
  padding: 8px 16px max(32px, env(safe-area-inset-bottom));
  font-size: 16px;
  line-height: 1.45;
}
.admin-head {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  justify-content: space-between;
  gap: 12px 24px;
}
.admin-head h1 {
  margin: 8px 0 0;
  font-size: 26px;
  line-height: 1.2;
  text-wrap: balance;
}
.admin-head .hint {
  margin: 4px 0 0;
}
.admin-range {
  min-width: min(20rem, 100%);
  margin: 0;
  border: 0;
}
.admin-msg {
  margin: 20px 0;
}
.admin-msg:empty {
  display: none;
}
.admin-msg a {
  color: var(--accent);
}
.admin-tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(13rem, 1fr));
  gap: 12px;
  margin: 24px 0 0;
}
.admin-tiles > div {
  padding: 14px 16px;
  border-radius: 16px;
  background: var(--surface);
  box-shadow: var(--ring);
}
.admin-tiles dt {
  color: var(--text-2);
  font-size: 14px;
}
.admin-tiles dd {
  margin: 2px 0 0;
  font-size: 28px;
  font-weight: 700;
  line-height: 1.2;
  font-variant-numeric: tabular-nums;
}
.admin-tiles dd.hint {
  margin: 4px 0 0;
  font-size: 14px;
  font-weight: 400;
  line-height: 1.5;
}
.admin-main section {
  margin-top: 36px;
}
.admin-main h2 {
  margin: 0 0 12px;
  color: var(--text-2);
  font-size: 13px;
  letter-spacing: 0.07em;
  text-transform: uppercase;
}
.admin-main #report > .hint {
  margin-top: 16px;
}

/* Two tabs, People and Usage, on a hairline. */
.admin-tabs {
  display: flex;
  gap: 4px;
  margin: 8px 0 16px;
  border-bottom: 1px solid var(--line);
}
.admin-tab {
  min-height: 44px;
  margin-bottom: -1px;
  padding: 0 14px;
  border: 0;
  border-bottom: 3px solid transparent;
  background: none;
  color: var(--text-2);
  font: inherit;
  font-size: 16px;
  font-weight: 700;
  cursor: pointer;
  transition: color 150ms ease-out;
}
@media (hover: hover) {
  .admin-tab:hover {
    color: var(--text);
  }
}
.admin-tab[aria-selected='true'] {
  border-bottom-color: var(--accent);
  color: var(--text);
}
.admin-tab:focus-visible {
  border-radius: 8px 8px 0 0;
  outline-offset: -3px;
}

/* People: an invite form, unused invites, then a card for each account. */
.admin-invite {
  margin-top: 20px;
}
.admin-invite .link-row input {
  flex: 1;
  min-width: 0;
}
.admin-accounts {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.admin-account h3 {
  margin: 0;
  font-size: 19px;
  line-height: 1.3;
  overflow-wrap: anywhere;
}
.admin-account-head .hint {
  margin: 2px 0 0;
}
.admin-main .member-actions {
  flex-wrap: wrap;
}
.admin-limit .form-msg {
  flex-basis: 100%;
  margin: 0;
}
.limit-picker {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}
.limit-picker select {
  width: auto;
}
.limit-picker input {
  width: 6.5em;
  min-height: 42px;
  padding: 8px 12px;
  border: 1px solid var(--field-border);
  border-radius: 11px;
  background: var(--bg);
  color: var(--text);
  font: inherit;
  font-size: 16px;
  font-variant-numeric: tabular-nums;
}
.admin-page .toast {
  position: fixed;
  bottom: max(16px, env(safe-area-inset-bottom));
}

/* One bar a day, stacked by speech service (or by device and phones), against the busiest day. */
.day-chart {
  display: flex;
  gap: 2px;
  height: 160px;
  border-bottom: 1px solid var(--line);
}
.day-bar {
  display: flex;
  flex: 1;
  flex-direction: column-reverse;
  min-width: 0;
}
.day-bar span {
  flex: none;
  height: var(--share);
  min-height: 2px;
  background: var(--part);
}
.day-bar span:last-child {
  border-radius: 3px 3px 0 0;
}
[data-part='soniox'],
[data-part='device'] {
  --part: var(--accent);
}
[data-part='deepgram'] {
  --part: var(--spk-5);
}
[data-part='phone'] {
  --part: var(--spk-4);
}
[data-part='demo'] {
  --part: var(--demo);
}
[data-part='none'] {
  --part: var(--text-2);
}
.day-axis {
  display: flex;
  justify-content: space-between;
  margin-top: 6px;
  color: var(--text-2);
  font-size: 13px;
}
.chart-legend {
  display: flex;
  flex-wrap: wrap;
  gap: 6px 20px;
  margin: 12px 0 0;
  padding: 0;
  color: var(--text-2);
  font-size: 14px;
  list-style: none;
}
.chart-legend li {
  display: flex;
  align-items: center;
  gap: 8px;
}
.legend-mark {
  flex: none;
  width: 12px;
  height: 12px;
  border-radius: 3px;
  background: var(--part);
}

/* A wide table scrolls sideways inside its own box on narrow screens. */
.table-scroll {
  overflow-x: auto;
  border-radius: 16px;
  background: var(--surface);
  box-shadow: var(--ring);
}
.table-scroll:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
}
.admin-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 15px;
}
.admin-table th,
.admin-table td {
  padding: 10px 14px;
  text-align: start;
  vertical-align: top;
  white-space: nowrap;
}
.admin-table thead th {
  border-bottom: 1px solid var(--line);
  color: var(--text-2);
  font-size: 13px;
  font-weight: 400;
}
.admin-table tbody tr + tr > * {
  border-top: 1px solid var(--line);
}
.admin-table tbody th {
  min-width: 10rem;
  font-weight: 700;
  white-space: normal;
}
.admin-table .num {
  text-align: end;
  font-variant-numeric: tabular-nums;
}
.admin-table small {
  display: block;
  color: var(--text-2);
  font-size: 13px;
}

/* The account's own last 30 days of cloud captions, in the Account pane's summary. */
.usage-history {
  margin-top: 12px;
}
#admin-link {
  margin-top: 12px;
}
.usage-history .day-chart {
  height: 48px;
  margin-top: 8px;
}
.usage-history .chart-legend {
  margin-top: 8px;
  font-size: 13px;
}

@media (forced-colors: active) {
  .day-bar span,
  .legend-mark {
    forced-color-adjust: none;
  }
}

/* Styled like the app's banner: a tinted card with a rounded bar. */
.mic-notice {
  display: flex;
  gap: 12px;
  margin: 18px 0 0;
  padding: 12px 14px 12px 12px;
  border-radius: 16px;
  background: var(--surface-2);
  background: color-mix(in srgb, var(--warn) var(--tint), var(--bg));
  line-height: 1.45;
}
.mic-notice::before {
  content: '';
  flex: none;
  align-self: stretch;
  width: 4px;
  border-radius: 2px;
  background: var(--warn);
}

/* ---------- forced colors (Windows high contrast) ---------- */
/* Backgrounds and shadows are taken away, so controls drawn with them get real borders, and the
   chosen option is marked with the system's highlight color. */

@media (forced-colors: active) {
  .btn,
  .chip,
  .icon-btn,
  .card,
  .account-summary,
  .history-list:has(.history-item),
  .nav-item,
  .tile,
  .color-field,
  .status,
  .banner,
  .toast,
  button.who,
  .segmented,
  input[type='range']::-webkit-slider-runnable-track {
    border: 1px solid ButtonText;
  }
  .card select {
    border: 1px solid ButtonText;
  }
  .toggle input,
  .radio input {
    border: 2px solid ButtonText;
  }
  .toggle input:checked,
  .segmented input:checked + span,
  .tile:has(input:checked),
  .nav-item[aria-selected='true'] {
    background: Highlight;
    color: HighlightText;
    forced-color-adjust: none;
  }
  input[type='range']::-webkit-slider-thumb {
    background: Highlight;
    forced-color-adjust: none;
  }
  .radio input:checked {
    border-color: Highlight;
    box-shadow: inset 0 0 0 3px Canvas, inset 0 0 0 10px Highlight;
  }
  .swatch input:checked + .sw {
    outline: 3px solid Highlight;
    outline-offset: 3px;
  }
  .line::before,
  .dot,
  .meter i,
  .sw,
  .theme-swatch,
  .theme-dot {
    forced-color-adjust: none;
  }
  .empty-mark .bubble {
    fill: Canvas;
    stroke: CanvasText;
  }
}
