/* MorseHub web app. Every color comes from tokens.css (DESIGN.md). No new colors here. */
@import url("tokens.css");

*, *::before, *::after { box-sizing: border-box; }
html, body { height: 100%; }
html { -webkit-tap-highlight-color: transparent; }
body {
  margin: 0; background: var(--canvas); color: var(--ink);
  font: 400 var(--t-body)/var(--lh) var(--font);
  -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility;
}
[hidden] { display: none !important; }
h1, h2, h3, p { margin: 0; }
button, input, textarea { font: inherit; color: inherit; }
button { cursor: pointer; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
::selection { background: color-mix(in srgb, var(--accent) 28%, transparent); }
.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
.skip { position: absolute; left: var(--s2); top: -100px; background: var(--card); color: var(--accent); padding: var(--s2) var(--s3); border-radius: var(--r-pill); border: 1px solid var(--line); z-index: 10; }
.skip:focus { top: var(--s2); }
/* Thin scrollbars in the palette, everywhere something scrolls. */
* { scrollbar-width: thin; scrollbar-color: var(--line) transparent; }
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-thumb { background: var(--line); border-radius: var(--r-pill); }
::-webkit-scrollbar-track { background: transparent; }
.mono { font-family: ui-monospace, "Cascadia Mono", "SF Mono", Menlo, Consolas, monospace; }
.icon { display: block; flex: none; }

.wordmark { font-size: var(--t-mark); font-weight: 700; letter-spacing: -0.01em; display: inline-flex; align-items: center; gap: var(--s2); }
/* The mark (UIcons "comment dots", DESIGN.md "Logo"): Signal blue beside the ink wordmark. */
.mark { display: block; flex: none; }
.wordmark .mark { width: 22px; height: 22px; color: var(--accent); }
/* Typing dots: first load and first sync only, never for sends or status. */
.mark.typing .dot { animation: mh-typing 1.2s ease-in-out infinite; }
.mark.typing .dot:nth-of-type(2) { animation-delay: .15s; }
.mark.typing .dot:nth-of-type(3) { animation-delay: .3s; }
@keyframes mh-typing { 0%, 60%, 100% { transform: translateY(0); opacity: .4; } 30% { transform: translateY(-2.5px); opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .mark.typing .dot { animation: none; } }
.loading-mark { display: grid; justify-items: center; gap: var(--s3); color: var(--ink-2); }
.loading-mark .mark { color: var(--accent); }

/* ---------- buttons and inputs ---------- */
.btn {
  min-height: var(--tap); padding: 0 var(--s5); border-radius: var(--r-pill);
  font-size: var(--t-small); font-weight: 600; border: 1px solid transparent; background: none;
  display: inline-flex; align-items: center; justify-content: center; gap: var(--s2); white-space: nowrap;
  transition: background var(--fast) var(--ease), opacity var(--fast) var(--ease);
}
.btn.fill { background: var(--accent-fill); color: var(--on-accent); }
.btn.line { border-color: var(--accent); color: var(--accent); }
.btn.plain { color: var(--ink); border-color: var(--line); }
.btn.wide { width: 100%; }
.btn:disabled { opacity: .5; cursor: default; }
.btn.small { min-height: 32px; padding: 0 var(--s3); font-size: var(--t-meta); }
/* Small buttons keep a 44 px hit area around them. */
.btn.small { position: relative; }
.btn.small::after { content: ""; position: absolute; inset: -6px -2px; }

.icon-btn {
  width: var(--tap); height: var(--tap); border-radius: var(--r-pill); border: 0; background: none;
  display: inline-flex; align-items: center; justify-content: center; color: var(--ink); flex: none;
  transition: background var(--fast) var(--ease);
}

.input {
  width: 100%; min-height: var(--tap); padding: var(--s2) var(--s4);
  border: 1px solid var(--line); border-radius: var(--r-card); background: var(--card);
}
.input { font-size: var(--t-body); }
.input::placeholder { color: var(--ink-2); }
.input { caret-color: var(--accent); }
.input:focus { outline: 2px solid var(--accent); outline-offset: -1px; border-color: transparent; }

.label { display: block; font-size: var(--t-meta); font-weight: 600; color: var(--ink-2); margin: 0 0 var(--s1); }
.help { color: var(--ink-2); }
.note, .row-help { color: var(--ink-2); font-size: var(--t-small); }
.error { color: var(--ink); font-size: var(--t-small); font-weight: 600; display: flex; gap: var(--s2); align-items: flex-start; }
.error .icon { margin-top: 1px; }

/* ---------- full screens (pairing, revoked) ---------- */
.screen { min-height: 100%; display: grid; place-items: center; padding: var(--s6) var(--s4); }
.screen-card {
  width: 100%; max-width: 440px; background: var(--card); border: 1px solid var(--line);
  border-radius: var(--r-card); padding: var(--s6); display: grid; gap: var(--s4);
}
.screen-card h1 { font-size: var(--t-body); font-weight: 600; }
.screen-card .input { font-size: var(--t-body); letter-spacing: .04em; text-transform: uppercase; }

/* ---------- app shell ---------- */
#app { height: 100vh; height: 100dvh; display: flex; flex-direction: column; }
.bar {
  height: var(--bar); flex: none; display: flex; align-items: center; gap: var(--s3);
  padding: 0 var(--s2) 0 var(--s4); width: 100%; max-width: var(--max); margin: 0 auto;
}
.bar .wordmark { margin-right: auto; }
.pill {
  display: inline-flex; align-items: center; gap: var(--s2); min-height: 32px; padding: 0 var(--s3);
  border: 1px solid var(--line); border-radius: var(--r-pill); font-size: var(--t-meta); font-weight: 600;
  color: var(--ink-2); background: var(--card); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 60vw;
}
.pill .dot { width: 8px; height: 8px; border-radius: var(--r-pill); border: 1.5px solid var(--ink); flex: none; }
.pill.on .dot { background: var(--ink); }
.pill.on { color: var(--ink); }
/* Phone status colors (Chris 2026-10-02, the one exception to "no red, one accent"): green when the
   phone is connected, red when it is offline. The words always say it too. Nowhere else. */
.pill.ok { color: var(--ok); background: var(--ok-wash); border-color: var(--ok); }
.pill.ok .dot { background: var(--ok); border-color: var(--ok); }
.pill.bad { color: var(--bad); background: var(--bad-wash); border-color: var(--bad); }
.pill.bad .dot { border-color: var(--bad); }

.panes {
  flex: 1; min-height: 0; width: 100%; max-width: var(--max); margin: 0 auto;
  display: grid; grid-template-columns: var(--list) 1fr; gap: var(--s3); padding: 0 var(--s3) var(--s3);
}
.card { background: var(--card); border: 1px solid var(--line); border-radius: var(--r-card); }
.pane { min-height: 0; display: flex; flex-direction: column; overflow: hidden; }
.pane-head {
  min-height: 56px; display: flex; align-items: center; gap: var(--s2);
  padding: var(--s1) var(--s2) var(--s1) var(--s4); border-bottom: 1px solid var(--line); flex: none;
}
.pane-title { font-size: var(--t-body); font-weight: 600; flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.convo-head { padding-left: var(--s2); }
.convo-head .back { display: none; }
.convo-h { flex: 1; min-width: 0; font: inherit; }
/* Name and number together are one button that copies the number (44 px+ tall). */
.convo-title {
  display: grid; width: 100%; min-height: var(--tap); padding: var(--s1) var(--s2); margin-left: calc(var(--s1) * -1);
  border: 0; background: none; text-align: left; border-radius: var(--r-row); justify-items: start; align-content: center;
  transition: background var(--fast) var(--ease);
}
.convo-title:disabled { cursor: default; }
.convo-title .pane-title { max-width: 100%; }
.convo-head > .avatar { margin-left: var(--s2); }
.sub { font-size: var(--t-meta); font-weight: 400; color: var(--ink-3); font-variant-numeric: tabular-nums; }

/* ---------- banners ---------- */
.banner {
  margin: var(--s3); padding: var(--s3) var(--s4); border: 1px solid var(--line); border-radius: var(--r-card);
  display: grid; gap: var(--s2); font-size: var(--t-small);
}
.banner strong { font-weight: 600; font-size: var(--t-small); }
.banner p { color: var(--ink-2); }
.banner .actions { justify-content: flex-start; }
/* One line of text and its button side by side, so the banner stays short. */
.banner.row-banner { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); }
.banner.row-banner .btn { flex: none; }
.convo-note { padding: var(--s2) var(--s4); font-size: var(--t-small); color: var(--ink-2); border-top: 1px solid var(--line); }

/* ---------- list header: "Mark all read" is a plain text button (it was a one-item menu) ---------- */
.list-head { gap: 0; }
.text-btn {
  min-height: var(--tap); padding: 0 var(--s3); border: 0; border-radius: var(--r-pill); background: none;
  font-size: var(--t-small); font-weight: 600; color: var(--accent); white-space: nowrap; flex: none;
}
.text-btn[aria-disabled="true"] { color: var(--ink-3); cursor: default; }

/* ---------- search: a filled field with the magnifier, like iMessage ---------- */
.search-row { padding: 0 var(--s3) var(--s2); flex: none; }
/* The label is the 44 px target; the filled field inside it is 36 px. */
.search-field { display: flex; align-items: center; min-height: var(--tap); cursor: text; position: relative; }
.search-icon { position: absolute; left: var(--s3); color: var(--ink-2); pointer-events: none; }
.search {
  width: 100%; height: 36px; border: 0; border-radius: var(--r-row); background: var(--wash);
  padding: 0 var(--s3) 0 34px; font-size: 16px; caret-color: var(--accent);
}
.search::placeholder { color: var(--ink-2); }
.search:focus { outline: 2px solid var(--accent); outline-offset: 0; }
.search::-webkit-search-cancel-button { cursor: pointer; }

/* ---------- thread list (iMessage rows, DESIGN.md "Thread list") ---------- */
.threads {
  list-style: none; margin: 0; padding: 0 var(--s2) var(--s2); overflow-y: auto; flex: 1;
}
.threads > li { position: relative; }
/* Inset hairline under each row: from the text column to the right padding. Not next to the
   selected or hovered row, whose filled shape needs no edge. */
.threads > li:not(.empty)::after {
  content: ""; position: absolute; left: calc(var(--s3) + 48px + var(--s3)); right: var(--s3); bottom: 0;
  height: 1px; background: var(--line); pointer-events: none;
}
.threads > li:last-child::after,
.threads > li.sel::after, .threads > li:has(+ li.sel)::after { display: none; }
.thread {
  width: 100%; display: grid; grid-template-columns: 48px 1fr; gap: 0 var(--s3); align-items: center;
  padding: var(--s3); background: none; border: 0; text-align: left; min-height: 72px;
  border-radius: var(--r-row); position: relative; color: var(--ink);
  transition: background var(--fast) var(--ease);
}
.thread:focus-visible { outline-offset: -2px; }
/* The open thread: a filled accent pill, all text white (white on #2c6bed is 4.7:1 in both themes). */
.thread[aria-current="true"], .thread[aria-current="true"]:hover { background: var(--accent-fill); color: var(--on-accent); }
.thread[aria-current="true"] .time, .thread[aria-current="true"] .preview { color: var(--on-accent); }
.thread[aria-current="true"]:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* Unread: a dot in the left gutter, next to the avatar. */
.udot { position: absolute; left: 1px; top: 50%; width: 9px; height: 9px; margin-top: -4.5px; border-radius: var(--r-pill); }
.thread.unread .udot { background: var(--accent); }
.thread[aria-current="true"].unread .udot { background: var(--on-accent); }
.avatar {
  width: 48px; height: 48px; border-radius: var(--r-pill); background: var(--wash); color: var(--ink-2);
  display: grid; place-items: center; font-weight: 600; font-size: var(--t-body); letter-spacing: .02em; flex: none;
}
.avatar.hue-1 { background: var(--av1); color: var(--av1-ink); }
.avatar.hue-2 { background: var(--av2); color: var(--av2-ink); }
.avatar.hue-3 { background: var(--av3); color: var(--av3-ink); }
.avatar.hue-4 { background: var(--av4); color: var(--av4-ink); }
.avatar.hue-5 { background: var(--av5); color: var(--av5-ink); }
.avatar.hue-6 { background: var(--av6); color: var(--av6-ink); }
.avatar.small { width: 32px; height: 32px; font-size: var(--t-meta); }
.avatar.small .icon { width: 18px; height: 18px; }
.thread .row { min-width: 0; display: grid; gap: 2px; align-self: center; }
.thread .top { display: flex; align-items: baseline; gap: var(--s2); min-width: 0; }
.thread .name { flex: 1; min-width: 0; font-size: var(--t-body); font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.thread .time { flex: none; font-size: var(--t-small); font-weight: 400; color: var(--ink-3); font-variant-numeric: tabular-nums; }
.thread .preview {
  font-size: var(--t-small); line-height: 1.35; color: var(--ink-2); min-width: 0;
  display: flex; align-items: flex-start; gap: var(--s1);
}
.thread .preview .icon { margin-top: 2px; }
.thread .ptext strong { font-weight: 700; color: var(--ink); }
.thread[aria-current="true"] .ptext strong { color: var(--on-accent); }
.thread .ptext {
  overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2;
  overflow-wrap: anywhere; min-height: calc(2 * 1.35em);
}
.thread.unread .name { font-weight: 700; }
.thread.unread .preview { color: var(--ink); }
.thread[aria-current="true"].unread .preview { color: var(--on-accent); }
.empty { padding: var(--s6) var(--s4); color: var(--ink-2); text-align: center; font-size: var(--t-small); }

/* ---------- conversation ---------- */
.messages {
  flex: 1; min-height: 0; overflow-y: auto; overflow-x: hidden; padding: var(--s2) var(--s4) var(--s4); display: flex; flex-direction: column;
}
/* Short threads sit at the bottom, next to the composer, like every messenger. */
.messages::before { content: ""; flex: 1 0 auto; }
.messages:focus { outline: none; }
/* Holds the message list and the jump-to-newest button that floats over its bottom edge. */
.msgs-wrap { flex: 1; min-height: 0; display: flex; flex-direction: column; position: relative; }
.to-bottom {
  position: absolute; right: var(--s4); bottom: var(--s3); width: var(--tap); height: var(--tap);
  border-radius: var(--r-pill); border: 1px solid var(--line); background: var(--card); color: var(--ink);
  display: inline-flex; align-items: center; justify-content: center; box-shadow: 0 2px 8px rgba(0, 0, 0, .15);
}
.to-bottom[hidden] { display: none; }
/* Time separator above a run more than an hour after the one before: "Today 10:25 AM". */
.stamp { align-self: center; text-align: center; font-size: var(--t-meta); color: var(--ink-3); margin: var(--s5) 0 var(--s2); font-variant-numeric: tabular-nums; }
.stamp strong { font-weight: 600; }
.msg { display: flex; flex-direction: column; max-width: min(75%, 520px); position: relative; }
/* Runs from one side sit 2 px apart; a new run starts 12 px down. */
.msg.first { margin-top: var(--s3); }
.msg.cont { margin-top: 2px; }
/* Room for the reaction badge that sits on the bubble's top corner. */
.msg.reacted { margin-top: var(--s4); }
.stamp + .msg { margin-top: 0; }
.msg.in { align-self: flex-start; align-items: flex-start; }
.msg.out { align-self: flex-end; align-items: flex-end; }
.msg.new { animation: slide var(--fast) var(--ease); }
@keyframes slide { from { transform: translateY(6px); opacity: 0; } to { transform: none; opacity: 1; } }
.bw { position: relative; max-width: 100%; }
.bubble {
  padding: var(--s2) var(--s3); border-radius: var(--r-bubble); white-space: pre-wrap; overflow-wrap: anywhere;
  font-size: var(--t-body); line-height: var(--lh);
}
.msg.in .bubble { background: var(--wash); }
.msg.out .bubble { background: var(--accent-fill); color: var(--on-accent); }
/* Only the last bubble of a run has the tail corner. */
.msg.in.tail .bubble, .msg.in.tail .otp, .msg.in.tail .code-btn { border-bottom-left-radius: var(--r-tail); }
.msg.out.tail .bubble { border-bottom-right-radius: var(--r-tail); }
/* Not yet with the phone: outlined, full-contrast ink text (no opacity). Cancelled: hairline, secondary ink. */
.msg.pending .bubble { background: var(--card); color: var(--ink); border: 1px solid var(--accent); padding: calc(var(--s2) - 1px) calc(var(--s3) - 1px); }
.msg.muted .bubble { background: var(--card); color: var(--ink-2); border: 1px solid var(--line); padding: calc(var(--s2) - 1px) calc(var(--s3) - 1px); }
.otp {
  background: var(--wash); border-radius: var(--r-bubble);
  padding: var(--s3) var(--s4); display: grid; gap: var(--s2); justify-items: start;
}
.otp-code { font-size: 28px; font-weight: 600; line-height: 1.2; letter-spacing: .08em; font-variant-numeric: tabular-nums; user-select: all; }
.otp-text { white-space: pre-wrap; overflow-wrap: anywhere; }
.otp-actions { justify-content: flex-start; }
.link {
  background: none; border: 0; padding: 0; min-height: 32px; color: var(--accent); font-size: var(--t-small); font-weight: 600;
  text-decoration: underline; text-underline-offset: 3px; position: relative;
}
.link::after { content: ""; position: absolute; inset: -6px -4px; }
.code-btn {
  display: inline-flex; align-items: center; gap: var(--s2); min-height: var(--tap); padding: 0 var(--s4);
  border-radius: var(--r-bubble); border: 1px dashed var(--ink-3);
  background: var(--wash); font-weight: 600;
}
.meta { font-size: var(--t-meta); font-weight: 400; color: var(--ink-3); margin: 2px var(--s1) 0; display: flex; gap: var(--s2); align-items: center; flex-wrap: wrap; justify-content: flex-end; }
.msg.in .meta { justify-content: flex-start; }
.meta .problem { color: var(--ink); display: inline-flex; align-items: center; gap: var(--s1); }
.meta .status { color: var(--ink-3); }
.meta .actions { gap: var(--s1); }
.meta.quiet { margin: 0; }
.call { align-self: center; display: flex; align-items: center; gap: var(--s2); font-size: var(--t-small); color: var(--ink-2); padding: var(--s2) var(--s3); border: 1px solid var(--line); border-radius: var(--r-pill); margin: var(--s3) 0 var(--s1); }
.call .icon { width: 16px; height: 16px; }
/* Tapbacks: emoji on the bubble's top corner (away from the tail), like iMessage. */
.reacts {
  position: absolute; top: -14px; display: flex; gap: 2px; padding: 1px 6px; z-index: 1;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r-pill);
  font-size: 13px; line-height: 20px; white-space: nowrap; pointer-events: none;
}
.msg.in .reacts { right: -10px; }
.msg.out .reacts { left: -10px; }
/* A reaction to a text we cannot find: one quiet line, not a bubble. */
.msg.note { max-width: 85%; }
.tapnote { font-size: var(--t-small); color: var(--ink-2); padding: 2px var(--s1); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 100%; }
/* Per-message time and Copy: beside the bubble on hover, under it after a tap. */
.aside { display: none; align-items: center; gap: var(--s2); font-size: var(--t-meta); color: var(--ink-3); white-space: nowrap; font-variant-numeric: tabular-nums; }
.msg.show > .aside { display: flex; margin: 2px var(--s1) 0; }
.mini {
  position: relative; min-height: 28px; padding: 0 var(--s3); border: 1px solid var(--line); border-radius: var(--r-pill);
  background: var(--card); color: var(--ink); font-size: var(--t-meta); font-weight: 600;
}
.mini::after { content: ""; position: absolute; inset: -8px -4px; }
.hidden-note { align-self: center; font-size: var(--t-small); color: var(--ink-2); padding: var(--s2) 0; }

.composer { display: flex; padding: var(--s2) var(--s3) calc(var(--s2) + env(safe-area-inset-bottom, 0px)); border-top: 1px solid var(--line); flex: none; }
/* Filled at rest, a 2 px accent ring on focus. 44 px tall exactly: 22 px line + 11 px padding. */
.compose-box {
  flex: 1; min-width: 0; display: flex; align-items: flex-end; background: var(--wash); border-radius: 22px;
}
.compose-box:focus-within { outline: 2px solid var(--accent); outline-offset: 0; }
.compose {
  flex: 1; min-width: 0; height: var(--tap); max-height: 160px; resize: none; border: 0; background: none;
  font-size: 16px; line-height: 22px; padding: 11px var(--s1) 11px var(--s4); caret-color: var(--accent);
}
.compose::placeholder { color: var(--ink-2); }
.compose:focus, .compose:focus-visible { outline: none; }
.compose:disabled { cursor: not-allowed; }
/* 32 px circle inside the field, 44 px hit area. Always there; grey and inert when there is nothing to send. */
.send-btn {
  position: relative; width: 32px; height: 32px; margin: 6px; border-radius: var(--r-pill); border: 0; flex: none;
  background: var(--accent-fill); color: var(--on-accent); display: grid; place-items: center;
  transition: background var(--fast) var(--ease), transform var(--fast) var(--ease);
}
.send-btn::after { content: ""; position: absolute; inset: -6px; }
.send-btn:disabled { background: var(--ink-3); color: var(--card); cursor: default; }
.send-btn .icon { width: 18px; height: 18px; }

.to-row { padding: var(--s3) var(--s4); border-bottom: 1px solid var(--line); display: grid; gap: var(--s1); flex: none; }
.to-results { list-style: none; margin: var(--s2) 0 0; padding: 0; max-height: 50vh; overflow-y: auto; }
.to-results button {
  width: 100%; min-height: var(--tap); display: flex; align-items: center; gap: var(--s3); text-align: left;
  padding: var(--s2) var(--s2); border: 0; background: none; border-radius: var(--r-card);
}
.to-results .sub { font-weight: 400; }
.to-results .row-title { font-weight: 500; }

/* ---------- dialogs ---------- */
.dialog {
  width: min(480px, calc(100vw - 32px)); max-height: calc(100vh - 48px); padding: 0; border: 1px solid var(--line);
  border-radius: var(--r-card); background: var(--card); color: var(--ink); box-shadow: var(--shadow-dialog);
}
.dialog.small { width: min(400px, calc(100vw - 32px)); }
.dialog::backdrop { background: color-mix(in srgb, var(--canvas) 75%, transparent); }
.dialog-head { display: flex; align-items: center; padding: var(--s2) var(--s2) var(--s2) var(--s5); border-bottom: 1px solid var(--line); }
.dialog-head h2 { flex: 1; font-size: var(--t-body); font-weight: 600; }
.dialog-body { padding: var(--s5); display: grid; gap: var(--s4); }
.dialog-body h2 { font-size: var(--t-body); font-weight: 600; }
.set { display: grid; gap: var(--s3); }
.set + .set { border-top: 1px solid var(--line); padding-top: var(--s4); }
.set h3 { font-size: var(--t-meta); font-weight: 600; color: var(--ink-2); text-transform: uppercase; letter-spacing: .04em; }
.devices { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--s2); }
.device { display: flex; align-items: center; gap: var(--s3); min-height: var(--tap); }
.device > div { flex: 1; min-width: 0; }
.device .row-title { display: block; font-weight: 600; }
.row-toggle { display: flex; align-items: center; gap: var(--s4); justify-content: space-between; min-height: var(--tap); }
.row-toggle > .btn { flex: none; }
.row-title { display: block; font-weight: 600; }
.row-help { display: block; }
.actions { display: flex; gap: var(--s2); flex-wrap: wrap; justify-content: flex-end; }

.switch {
  appearance: none; -webkit-appearance: none; width: 48px; height: 28px; border-radius: var(--r-pill); flex: none;
  border: 1px solid var(--line); background: var(--wash); position: relative; cursor: pointer; margin: 8px 0;
  transition: background var(--fast) var(--ease);
}
.switch::before {
  content: ""; position: absolute; top: 3px; left: 3px; width: 20px; height: 20px; border-radius: var(--r-pill);
  background: var(--card); border: 1px solid var(--line); transition: transform var(--fast) var(--ease);
}
.switch:checked { background: var(--accent-fill); border-color: var(--accent-fill); }
.switch:checked::before { transform: translateX(20px); border-color: var(--accent-fill); }

.seg { display: inline-flex; border: 1px solid var(--line); border-radius: var(--r-pill); padding: 3px; gap: 2px; justify-self: start; }
.seg label { position: relative; }
.seg input { position: absolute; opacity: 0; inset: 0; margin: 0; cursor: pointer; }
.seg span { display: inline-flex; align-items: center; min-height: 38px; padding: 0 var(--s4); border-radius: var(--r-pill); font-size: var(--t-small); font-weight: 600; color: var(--ink-2); }
.seg input:checked + span { background: var(--wash); color: var(--ink); }
.seg input:focus-visible + span { outline: 2px solid var(--accent); outline-offset: 1px; }

.code-box {
  font-size: 28px; font-weight: 600; letter-spacing: .04em; line-height: 1.5; text-align: center; overflow-wrap: normal;
  padding: var(--s4); border: 1px solid var(--line); border-radius: var(--r-card); background: var(--canvas); user-select: all;
}
.code-box .grp { white-space: nowrap; }
@media (max-width: 479.98px) { .code-box { font-size: 22px; } }
.countdown { text-align: center; font-size: var(--t-small); color: var(--ink-2); font-weight: 600; }
.warn { display: flex; gap: var(--s3); align-items: flex-start; font-size: var(--t-small); color: var(--ink); }
.warn .icon { width: 20px; height: 20px; margin-top: 1px; }

.toast {
  position: fixed; left: 50%; bottom: var(--s6); transform: translateX(-50%); max-width: calc(100vw - 32px);
  background: var(--ink); color: var(--card); padding: var(--s3) var(--s5); border-radius: var(--r-pill);
  font-size: var(--t-small); font-weight: 600; z-index: 20;
}

/* ---------- hover (only where there is a pointer that hovers) and pressed ---------- */
@media (hover: hover) {
  .btn.fill:hover { opacity: .9; }
  .btn.line:hover, .btn.plain:hover { background: var(--wash); }
  .icon-btn:hover { background: var(--wash); }
  .text-btn:not([aria-disabled="true"]):hover { background: var(--wash); }
  .thread:hover { background: color-mix(in srgb, var(--wash) 60%, var(--card)); }
  .threads > li:hover::after, .threads > li:has(+ li:hover)::after { display: none; }
  .to-results button:hover { background: var(--wash); }
  .convo-title:not(:disabled):hover { background: var(--wash); }
  .mini:hover { background: var(--wash); }
  /* Time and Copy beside the bubble while the pointer is on it (padding bridges the gap). */
  .msg:not(.show):hover > .aside { display: flex; position: absolute; top: 3px; }
  .msg.in:not(.show):hover > .aside { left: 100%; padding-left: var(--s2); }
  .msg.out:not(.show):hover > .aside { right: 100%; padding-right: var(--s2); flex-direction: row-reverse; }
}
.btn:active, .icon-btn:active, .text-btn:not([aria-disabled="true"]):active, .to-results button:active, .convo-title:not(:disabled):active, .mini:active {
  background: color-mix(in srgb, var(--ink) 10%, var(--wash));
}
.btn.fill:active, .send-btn:not(:disabled):active { opacity: 1; transform: scale(.96); }
.thread:active { background: color-mix(in srgb, var(--ink) 6%, var(--wash)); }
.thread[aria-current="true"]:active { background: var(--accent-fill); }

/* ---------- one pane under 720 px ---------- */
@media (max-width: 719.98px) {
  .panes { grid-template-columns: 1fr; padding: 0; gap: 0; }
  .card { border-radius: 0; border-left: 0; border-right: 0; border-bottom: 0; }
  .bar { padding-left: var(--s4); }
  body:not(.in-convo) #convo-pane { display: none; }
  body.in-convo #list-pane { display: none; }
  .convo-head .back { display: inline-flex; }
  .convo-head > .avatar { margin-left: 0; }
  .msg { max-width: 85%; }
  .pill { max-width: 52vw; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}
