/* Blindserve — tokens adapted from the wireframe handoff's "Industry" design
   system (docs/design/industry-tokens-reference.css), per the README's
   instruction to treat that file as a starting token set, not final styling.
   Deliberate deviation: no Google Fonts @import — a zero-knowledge privacy
   tool shouldn't phone home to a third party just to render text, so this
   falls back to the system sans/monospace stacks instead of Barlow. */

:root {
  --color-bg: #f2f2f3;
  --color-surface: #e9e9ea;
  --color-text: #1d1f20;
  --color-accent: #5980a6;
  --color-divider: color-mix(in srgb, #1d1f20 16%, transparent);

  --color-accent-100: #eef6ff;
  --color-accent-200: #d6ebff;
  --color-accent-300: #b5d9fd;
  --color-accent-400: #94bce3;
  --color-accent-600: #597ea3;
  --color-accent-700: #416180;
  --color-accent-800: #2c455d;
  --color-accent-900: #1d2d3d;

  --font-heading: "Barlow Condensed", ui-sans-serif, system-ui, sans-serif;
  --font-body: "Barlow", ui-sans-serif, system-ui, sans-serif;
  --font-mono: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;

  --space-1: 3.4px;
  --space-2: 6.8px;
  --space-3: 10.2px;
  --space-4: 13.6px;
  --space-6: 20.4px;
  --space-8: 27.2px;

  --detail-w: 300px;
  --send-w: 320px;
}

* , *::before, *::after { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  background: var(--color-bg);
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: 15px;
  line-height: 1.5;
}
h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-heading);
  font-weight: 600;
  line-height: 1.15;
  margin: 0 0 var(--space-2);
}
p { margin: 0 0 var(--space-3); }
.mono { font-family: var(--font-mono); }
.text-muted { color: color-mix(in srgb, var(--color-text) 58%, transparent); }
:focus { outline: none; }
:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 2px; }
button { font: inherit; color: inherit; }
#app { min-height: 100%; }
.boot-loading { padding: var(--space-8); text-align: center; color: color-mix(in srgb, var(--color-text) 55%, transparent); }

/* — buttons — */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  cursor: pointer; font-family: var(--font-heading); font-weight: 600; font-size: 14px;
  background: transparent; border: 1px solid var(--color-divider); border-radius: 0;
  padding: var(--space-2) calc(var(--space-3) * 1.2);
  /* Some buttons are necessarily <a> rather than <button> -- the pairing
     "Continue" has to be a real link so popup blockers don't eat the save tab
     (see wirePairWindowMessaging in app.js). Without this they render
     underlined and read as body-copy links rather than as buttons. */
  text-decoration: none;
}
.btn:disabled { opacity: 0.45; cursor: not-allowed; }
.btn-primary { background: var(--color-accent); border-color: var(--color-accent); color: var(--color-bg); }
.btn-primary:hover:not(:disabled) { background: var(--color-accent-600); }
.btn-primary:active:not(:disabled) { background: var(--color-accent-700); }
.btn-secondary:hover:not(:disabled) { background: color-mix(in srgb, var(--color-text) 7%, transparent); }
.btn-ghost { border-color: transparent; color: var(--color-accent); }
.btn-ghost:hover:not(:disabled) { background: color-mix(in srgb, var(--color-accent) 10%, transparent); }
.btn-block { width: 100%; }

/* — inputs — */
.field { display: block; margin-bottom: var(--space-3); }
.field > label { display: block; font-size: 12px; margin-bottom: 5px; color: color-mix(in srgb, var(--color-text) 70%, transparent); }
.input {
  width: 100%; min-height: 36px; padding: 6px 10px; font: inherit; font-size: 14px;
  color: var(--color-text); background: var(--color-surface);
  border: 1px solid var(--color-divider); border-radius: 0;
}
.input:hover { border-color: color-mix(in srgb, var(--color-text) 45%, transparent); }
.input:focus-visible { border-color: var(--color-accent); }
textarea.input { min-height: 140px; resize: vertical; }
.form-error { color: #b3261e; font-size: 13px; margin: 0 0 var(--space-2); }

.seg { display: inline-flex; border: 1px solid var(--color-divider); }
.seg-opt { display: inline-flex; align-items: center; gap: 6px; padding: 7px 12px; font-size: 13px; cursor: pointer; }
.seg-opt + .seg-opt { border-left: 1px solid var(--color-divider); }
.seg-opt input { position: absolute; opacity: 0; width: 0; height: 0; }
.seg-opt.is-active { background: var(--color-accent); color: var(--color-bg); }
.seg-opt:not(.is-active):hover { background: color-mix(in srgb, var(--color-text) 7%, transparent); }

.tag { display: inline-flex; align-items: center; font-size: 11px; letter-spacing: 0.02em; padding: 3px 9px; border: 1px solid transparent; }
.tag-accent { background: var(--color-accent-100); color: var(--color-accent-800); }
.tag-outline { border-color: var(--color-accent); color: var(--color-accent); }
.tag-neutral { background: color-mix(in srgb, var(--color-text) 8%, transparent); color: var(--color-text); }

.hr { height: 1px; border: 0; margin: var(--space-4) 0; background: var(--color-divider); }

/* — sign-in — */
.signin-shell { min-height: 100vh; display: grid; place-items: center; padding: var(--space-4); }
.signin-card { width: min(360px, 100%); border: 1px solid var(--color-divider); padding: var(--space-6); }
.signin-card h1 { font-size: 28px; margin-bottom: var(--space-1); }
.standing-note {
  font-size: 12px; color: color-mix(in srgb, var(--color-text) 60%, transparent);
  border: 1px solid var(--color-divider); padding: var(--space-2) var(--space-3); margin-top: var(--space-4);
}

/* — brand bar — */
.brand-bar {
  display: flex; align-items: center; gap: var(--space-4);
  padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--color-divider);
}
.brand-bar .wordmark { font-family: var(--font-heading); font-weight: 600; font-size: 20px; }
.brand-bar .standing-line { font-size: 12px; color: color-mix(in srgb, var(--color-text) 55%, transparent); flex: 1; }
.brand-bar .current-user { font-size: 13px; display: flex; align-items: center; gap: var(--space-2); }

/* — shell layout — */
.shell { display: flex; align-items: stretch; min-height: calc(100vh - 53px); }
/* Capped and centred rather than full-bleed: the inbox is a single column of
   rows now, and a line of text the full width of a 27" monitor is unreadable.
   Auto margins centre it in whatever space the detail column leaves. */
.list-col { flex: 1; min-width: 0; max-width: 900px; margin: 0 auto; display: flex; flex-direction: column; }
.list-col-header { padding: var(--space-3) var(--space-4); }
.file-row {
  display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--color-divider);
}
.file-row.is-collected { opacity: 0.55; }
.file-row.is-sending { background: var(--color-accent-100); }
.file-row.is-selected { background: color-mix(in srgb, var(--color-text) 5%, transparent); }
.file-row .file-main { flex: 1; min-width: 0; }
.file-row .filename { font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.file-row .file-meta { font-size: 12px; color: color-mix(in srgb, var(--color-text) 55%, transparent); display: flex; gap: var(--space-2); align-items: center; }
.file-row.is-wrong .file-meta { color: #b3261e; }
.list-footer-note { padding: var(--space-3) var(--space-4); font-size: 11px; color: color-mix(in srgb, var(--color-text) 55%, transparent); }
.empty-state { padding: var(--space-8); text-align: center; color: color-mix(in srgb, var(--color-text) 55%, transparent); }

/* — flat inbox timeline — */
.daysep {
  padding: var(--space-3) var(--space-4) var(--space-1);
  font: 600 11px var(--font-heading);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--color-text) 50%, transparent);
  border-bottom: 1px solid var(--color-divider);
}
.chip {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 11px; padding: 2px 8px;
  border: 1px solid var(--color-divider);
}
/* Lives inside .list-col rather than spanning the page: these controls act on
   that list, so they track its width -- including when the detail column opens
   and narrows it. */
.filterbar {
  display: flex; align-items: center; gap: var(--space-2);
  padding: var(--space-2) var(--space-4);
  border-bottom: 1px solid var(--color-divider);
}
.filterbar .input { flex: 1; min-height: 32px; font-size: 13px; }
.inbox-empty { padding: var(--space-8) var(--space-6); text-align: center; }
.inbox-empty h3 { font-size: 22px; }
.inbox-empty .inbox-empty-body { max-width: 380px; margin: 0 auto var(--space-4); }
.inbox-empty .inbox-empty-actions { display: flex; gap: var(--space-2); justify-content: center; }
.inbox-empty .standing-note { max-width: 420px; margin: var(--space-8) auto 0; text-align: left; }

.detail-col { width: var(--detail-w); flex: none; border-left: 1px solid var(--color-divider); padding: var(--space-4); display: flex; flex-direction: column; gap: var(--space-3); }
.detail-kicker { font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--color-accent); }
.detail-preview { border: 1px solid var(--color-divider); padding: var(--space-6); flex: 1; display: flex; align-items: center; justify-content: center; text-align: center; color: color-mix(in srgb, var(--color-text) 55%, transparent); overflow: auto; white-space: pre-wrap; word-break: break-word; }
.countdown-block { border: 1px solid var(--color-divider); padding: var(--space-3); }
.countdown-bar { height: 4px; background: color-mix(in srgb, var(--color-text) 12%, transparent); margin-top: var(--space-2); }
.countdown-bar > span { display: block; height: 100%; background: var(--color-accent); }

/* — overlays: dialog on desktop, bottom sheet on mobile (same DOM) — */
.overlay-backdrop { position: fixed; inset: 0; background: color-mix(in srgb, #1d1f20 45%, transparent); display: grid; place-items: center; z-index: 20; }
.overlay-panel { width: min(420px, 100%); max-height: 90vh; overflow: auto; background: var(--color-bg); border: 1px solid var(--color-divider); padding: var(--space-4); }
.send-panel .overlay-panel { width: var(--send-w); }

.progress-step { display: flex; align-items: center; gap: var(--space-3); margin-bottom: var(--space-2); }
.progress-step .bar { flex: 1; height: 6px; background: color-mix(in srgb, var(--color-text) 12%, transparent); }
.progress-step .bar > span { display: block; height: 100%; background: var(--color-accent-300); }
.progress-step.is-active .bar > span { background: var(--color-accent); }
.progress-step.is-done .bar > span { background: var(--color-accent-300); width: 100% !important; }
.progress-step .label { width: 140px; font-size: 13px; flex: none; }
.progress-step.is-waiting { opacity: 0.5; }
.progress-step .bar.is-neutral > span { background: color-mix(in srgb, var(--color-text) 35%, transparent) !important; }

.pairing-methods { list-style: none; margin: 0; padding: 0; }
.pairing-methods li { padding: var(--space-2) var(--space-3); border: 1px solid var(--color-divider); margin-bottom: var(--space-1); }
.pairing-methods li:nth-child(1) { opacity: 1; }
.pairing-methods li:nth-child(2) { opacity: 0.92; }
.pairing-methods li:nth-child(3) { opacity: 0.84; }
.pairing-methods li:nth-child(4) { opacity: 0.76; }
.pairing-methods li:nth-child(5) { opacity: 0.68; }
.pairing-methods li:nth-child(6) { opacity: 0.6; }
.qr-box { width: 180px; height: 180px; border: 1px solid var(--color-divider); margin: var(--space-3) auto; display: grid; place-items: center; padding: var(--space-2); }
.qr-box svg { width: 100%; height: 100%; display: block; }
.secret-words { font-size: 20px; text-align: center; letter-spacing: 0.04em; padding: var(--space-3); border: 1px solid var(--color-divider); margin-bottom: var(--space-3); }

.roster-caret { cursor: pointer; color: var(--color-accent); }
.group-roster { list-style: none; margin: var(--space-2) 0 0; padding: 0; font-size: 13px; }
.group-roster li { padding: var(--space-1) 0; }

/* — nav header actions — */
.header-actions { display: flex; gap: var(--space-2); }

/* Below 860px, renderApp (views.js) switches to an entirely different mobile
 * render tree (state.isMobile) rather than reflowing this one -- see the
 * "— mobile —" section at the end of this file for its styles. Nothing in
 * this file above that section needs a mobile override any more. */
.brand-bar .send-cta { margin-left: auto; }

/* — Messages (chat) — */
.messages-shell { display: flex; align-items: stretch; flex: 1; min-height: 0; width: 100%; }
.convo-list { width: 280px; flex: none; border-right: 1px solid var(--color-divider); overflow-y: auto; }
.convo-row { display: flex; align-items: center; gap: var(--space-2); padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--color-divider); cursor: pointer; }
.convo-row:hover { background: color-mix(in srgb, var(--color-text) 5%, transparent); }
.convo-row.is-selected { background: color-mix(in srgb, var(--color-text) 7%, transparent); }
.convo-main { flex: 1; min-width: 0; }
.convo-label { font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.convo-preview { font-size: 12px; }
.convo-badge { background: var(--color-accent); color: var(--color-bg); font-size: 11px; min-width: 18px; height: 18px; border-radius: 9px; display: inline-flex; align-items: center; justify-content: center; padding: 0 5px; flex: none; }

.thread-col { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.thread-empty { align-items: center; justify-content: center; }
.thread-locked { padding: 0; }
.thread-unlock-body { max-width: 360px; margin: var(--space-6) auto 0; padding: 0 var(--space-4); }
.thread-header { display: flex; align-items: center; justify-content: space-between; padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--color-divider); }
.thread-title { font-family: var(--font-heading); font-weight: 600; font-size: 17px; }
.thread-scroll { flex: 1; overflow-y: auto; padding: var(--space-4); display: flex; flex-direction: column; gap: var(--space-3); }

.msg-row { display: flex; flex-direction: column; max-width: 65%; }
.msg-row.is-mine { align-self: flex-start; align-items: flex-start; }
.msg-row.is-theirs { align-self: flex-end; align-items: flex-end; }
.msg-sender { font-size: 11px; color: color-mix(in srgb, var(--color-text) 55%, transparent); margin-bottom: 2px; }
.msg-bubble-wrap { display: flex; align-items: center; gap: 4px; }
.msg-row.is-theirs .msg-bubble-wrap { flex-direction: row-reverse; }
/* Theirs gets an explicit fill (not just a border) so it reads as a distinct
   colored bubble against the page background, not an outline that blends
   into it -- mine's accent fill already had that contrast, theirs didn't. */
.msg-bubble { padding: var(--space-2) var(--space-3); border: 1px solid var(--color-divider); background: var(--color-surface); white-space: pre-wrap; word-break: break-word; }
.msg-row.is-mine .msg-bubble { background: var(--color-accent); color: var(--color-bg); border-color: var(--color-accent); }
.msg-bubble.is-pending { opacity: 0.6; }
.msg-time { font-size: 11px; color: color-mix(in srgb, var(--color-text) 50%, transparent); margin-top: 2px; }

/* Delete-now: tucked into the gutter beside the bubble, hidden until hover so
   the thread doesn't read as cluttered with controls at rest. */
.msg-delete {
  opacity: 0; flex: none; border: none; background: none; cursor: pointer;
  font-size: 16px; line-height: 1; padding: 4px 6px;
  color: color-mix(in srgb, var(--color-text) 45%, transparent);
}
.msg-bubble-wrap:hover .msg-delete { opacity: 1; }
.msg-delete:hover { color: #b3261e; }

.thread-compose-bar { border-top: 1px solid var(--color-divider); }
.thread-expiry-row { display: flex; align-items: center; gap: var(--space-2); padding: var(--space-2) var(--space-4) 0; font-size: 12px; }
.thread-expiry-row .seg-opt { padding: 4px 9px; font-size: 12px; }
.thread-compose { display: flex; gap: var(--space-2); padding: var(--space-2) var(--space-4) var(--space-3); }
.thread-compose textarea { flex: 1; resize: none; min-height: 40px; max-height: 140px; }

/* ============================================================
   — mobile —
   Below 860px, views.js's renderApp renders an entirely different tree
   (state.isMobile) instead of reflowing the desktop one above: a top bar +
   bottom tab bar instead of the brand bar, real pushed screens instead of
   fixed overlays, a chip filter row instead of the wrapping filterbar. See
   design_handoff_mobile/README.md for the spec this implements. Everything
   below targets `.m-*` classes only, which the desktop tree never renders,
   so nothing here can affect the ≥861px layout above.
   ============================================================ */
@media (max-width: 860px) {
  html, body { overflow-x: hidden; }

  .m-app {
    display: flex; flex-direction: column;
    min-height: 100vh; min-height: 100dvh;
  }
  .m-content { flex: 1; min-width: 0; min-height: 0; display: flex; flex-direction: column; }
  .m-content.is-greyscale { filter: grayscale(1); }

  /* — top bar (§0) — */
  .m-topbar {
    flex: none; height: 52px; display: flex; align-items: center; gap: var(--space-3);
    padding: 0 var(--space-4); border-bottom: 1px solid var(--color-divider);
  }
  .m-topbar-title { flex: 1; font-family: var(--font-heading); font-weight: 600; font-size: 17px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .m-iconbtn {
    flex: none; display: inline-flex; align-items: center; justify-content: center;
    width: 44px; height: 44px; margin: 0 -13px; /* 44px hit area around a 28px/20px visual */
    background: none; border: none; color: var(--color-text); cursor: pointer;
  }

  /* — bottom tab bar (§0) — */
  .m-tabbar { flex: none; height: 66px; display: flex; border-top: 1px solid var(--color-divider); }
  .m-tab {
    flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 5px;
    background: none; border: none; color: color-mix(in srgb, var(--color-text) 60%, transparent); cursor: pointer;
  }
  .m-tab-icon { position: relative; display: inline-flex; }
  .m-tab-label { font-size: 10.5px; font-weight: 400; }
  .m-tab.is-active { color: var(--color-accent); }
  .m-tab.is-active .m-tab-label { font-weight: 600; }
  .m-tab-badge {
    position: absolute; top: -4px; right: -6px; min-width: 14px; height: 14px; padding: 0 2px;
    border-radius: 7px; background: var(--color-accent); color: var(--color-bg);
    font-size: 9px; font-weight: 600; line-height: 14px; text-align: center;
  }
  .m-tab-send-cell { justify-content: center; }
  .m-tab-send {
    display: inline-flex; align-items: center; justify-content: center;
    width: 44px; height: 30px; border: 1px solid var(--color-accent); color: var(--color-accent);
    font-family: var(--font-heading); font-weight: 600; font-size: 13px;
  }

  /* — back / nav links shared by pushed screens — */
  .m-back, .m-back-plain {
    display: inline-flex; align-items: center; gap: 2px; color: var(--color-accent);
    text-decoration: none; font-size: 14px; padding: var(--space-2) 0; flex: none;
  }
  .m-back svg { margin-left: -4px; }

  /* — pushed-screen shell, shared by detail/thread/contacts/pairing/send — */
  .m-screen { flex: 1; min-height: 0; display: flex; flex-direction: column; }
  .m-screen-header {
    flex: none; min-height: 52px; display: flex; align-items: center; gap: var(--space-3);
    padding: 0 var(--space-4); border-bottom: 1px solid var(--color-divider);
  }
  .m-screen-header-title { flex: 1; text-align: center; font-family: var(--font-heading); font-weight: 600; font-size: 17px; }
  .m-screen-header-kicker { flex: 1; text-align: right; font-size: 10px; font-weight: 500; letter-spacing: 0.06em; text-transform: uppercase; color: var(--color-accent); }
  .m-scroll { flex: 1; min-height: 0; overflow-y: auto; display: flex; flex-direction: column; }
  .m-screen-footer { flex: none; border-top: 1px solid var(--color-divider); padding: var(--space-3) var(--space-4) 26px; display: flex; flex-direction: column; gap: var(--space-2); }
  .m-footer-note { margin-top: auto; padding: var(--space-4); font-size: 11px; line-height: 1.55; color: color-mix(in srgb, var(--color-text) 55%, transparent); border-top: 1px solid var(--color-divider); }
  /* Same note styling, but for one sitting mid-list (e.g. between the People
     and Groups sections) rather than as the last child of a .m-scroll --
     margin-top:auto there would push everything after it to the bottom of
     the viewport whenever the list above is short. */
  .m-inline-note { padding: var(--space-2) var(--space-4) var(--space-3); font-size: 11px; line-height: 1.55; color: color-mix(in srgb, var(--color-text) 55%, transparent); }

  /* — bottom sheets (unlock, send-progress N/A, delete confirm, overflow) — */
  .m-sheet-backdrop {
    position: fixed; inset: 0; z-index: 20; display: flex; align-items: flex-end; justify-content: center;
    background: color-mix(in srgb, #1d1f20 45%, transparent);
  }
  .m-sheet {
    width: 100%; max-height: 85vh; overflow-y: auto; background: var(--color-bg);
    border-top: 1px solid var(--color-divider); border-radius: 14px 14px 0 0;
    padding: var(--space-3) var(--space-6) 26px;
  }
  .m-sheet-handle { width: 38px; height: 4px; margin: 0 auto 16px; background: var(--color-divider); }
  .m-sheet-title { font-size: 22px; margin-bottom: var(--space-2); }
  .m-sheet .btn-block + .btn-block { margin-top: var(--space-2); }
  .m-hidden-username { font-size: 11px; margin-bottom: var(--space-2); }

  /* — overflow sheet (top bar's "...") — */
  .m-overflow-identity { display: flex; align-items: center; gap: var(--space-3); padding-bottom: var(--space-3); margin-bottom: var(--space-2); border-bottom: 1px solid var(--color-divider); }
  .m-overflow-identity-name { font-size: 15px; font-weight: 500; }
  .m-overflow-row { display: block; padding: var(--space-3) 0; font-size: 15px; color: var(--color-text); text-decoration: none; border-bottom: 1px solid var(--color-divider); }
  .m-overflow-row:last-of-type { border-bottom: none; margin-bottom: var(--space-3); }
  .m-thread-expiry { display: flex; align-items: center; justify-content: space-between; }

  /* — avatars — */
  .m-avatar {
    flex: none; display: inline-flex; align-items: center; justify-content: center;
    border-radius: 50%; border: 1px solid var(--color-divider); font-family: var(--font-heading); font-weight: 600;
    background: var(--color-surface); color: var(--color-text);
  }
  .m-avatar.is-accent { background: var(--color-accent-100); border-color: var(--color-accent); color: var(--color-accent-800); }
  .m-avatar-28 { width: 28px; height: 28px; font-size: 11px; }
  .m-avatar-30 { width: 30px; height: 30px; font-size: 12px; }
  .m-avatar-34 { width: 34px; height: 34px; font-size: 13px; }
  .m-avatar-38 { width: 38px; height: 38px; font-size: 14px; }
  .m-avatar-40 { width: 40px; height: 40px; font-size: 15px; }

  /* — chip filter row (§1, fix for defect 2) — */
  .m-chiprow {
    flex: none; display: flex; gap: var(--space-2); padding: var(--space-3) var(--space-4);
    overflow-x: auto; scrollbar-width: none; border-bottom: 1px solid var(--color-divider);
  }
  .m-chiprow::-webkit-scrollbar { display: none; }
  .m-chip {
    flex: none; display: inline-flex; align-items: center; gap: 4px; padding: 6px 12px;
    font: inherit; font-size: 12px; color: var(--color-text); background: transparent;
    border: 1px solid var(--color-divider); cursor: pointer;
  }
  .m-chip.is-active { border-color: var(--color-accent); background: var(--color-accent-100); color: var(--color-accent-800); font-weight: 500; }
  .m-searchrow { align-items: center; }
  .m-searchrow .input { flex: 1; min-height: 32px; font-size: 13px; }
  .m-search-cancel { flex: none; font-size: 13px; color: var(--color-accent); text-decoration: none; }

  /* — file row (§1, fix for defect 5) — */
  .m-row {
    display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3) var(--space-4);
    min-height: 64px; border-top: 1px solid var(--color-divider); cursor: pointer;
  }
  .m-row:active { background: color-mix(in srgb, var(--color-text) 6%, transparent); }
  .m-row.is-collected { opacity: 0.5; }
  .m-row-badge {
    flex: none; width: 36px; height: 36px; display: flex; align-items: center; justify-content: center;
    border: 1px solid var(--color-divider); color: color-mix(in srgb, var(--color-text) 55%, transparent);
    font-size: 10px; font-weight: 500; text-transform: uppercase;
  }
  .m-row-badge.is-accent { background: var(--color-accent-100); border-color: var(--color-accent); color: var(--color-accent-800); }
  .m-row-main { flex: 1; min-width: 0; }
  .m-row-title { font-size: 15px; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .m-row-meta { font-size: 12px; color: color-mix(in srgb, var(--color-text) 55%, transparent); }
  .m-row-meta.is-error { color: #b3261e; }
  .m-row.is-wrong { align-items: flex-start; }
  .m-row-trailing { flex: none; display: flex; align-items: center; color: var(--color-accent); }
  .m-row-tag { padding: 3px 8px; font-size: 11px; font-weight: 500; background: var(--color-accent-100); color: var(--color-accent-800); }

  /* — inbox empty (Waiting tab, §2) — */
  .m-inbox-empty { flex: 1; display: flex; flex-direction: column; padding: 64px var(--space-8) 0; text-align: center; }
  .m-inbox-empty-icon { width: 46px; height: 46px; margin: 0 auto 18px; border: 1px dashed var(--color-divider); }
  .m-inbox-empty h3 { font-size: 22px; }
  .m-inbox-empty p { font-size: 13px; line-height: 1.6; max-width: 340px; margin: 0 auto var(--space-4); }
  .m-inbox-empty-actions { display: flex; flex-direction: column; gap: var(--space-2); max-width: 320px; margin: 0 auto; }
  .m-inbox-empty-footer { margin-top: var(--space-8); text-align: left; }

  /* — file detail (§6) — */
  .m-detail-body { padding: var(--space-4); }
  .m-detail-title { font-size: 22px; margin: var(--space-1) 0 var(--space-3); }
  .m-detail-preview { border: 1px solid var(--color-divider); padding: var(--space-6); min-height: 160px; display: flex; align-items: center; justify-content: center; text-align: center; color: color-mix(in srgb, var(--color-text) 55%, transparent); margin-bottom: var(--space-3); white-space: pre-wrap; word-break: break-word; }
  .m-detail-footer { flex-direction: row; }
  .m-detail-primary { flex: 1; height: 52px; }
  .m-detail-delete { width: 96px; flex: none; height: 52px; }

  /* — Messages list (§7) — */
  .m-convo-row { display: flex; align-items: center; gap: var(--space-3); padding: 15px var(--space-4); border-top: 1px solid var(--color-divider); cursor: pointer; }
  .m-convo-row:active { background: color-mix(in srgb, var(--color-text) 6%, transparent); }
  .m-convo-main { flex: 1; min-width: 0; }
  .m-convo-top { display: flex; align-items: baseline; gap: var(--space-2); }
  .m-convo-label { flex: 1; font-size: 15px; font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .m-convo-time { flex: none; font-size: 11px; }
  .m-convo-preview { font-size: 12.5px; margin-top: 2px; }
  .m-convo-badge {
    flex: none; min-width: 22px; height: 22px; padding: 0 6px; border-radius: 11px;
    background: var(--color-accent); color: var(--color-bg); font-size: 11px; font-weight: 600;
    display: inline-flex; align-items: center; justify-content: center;
  }

  /* — thread (§8) — */
  .m-thread-title { flex: 1; display: flex; flex-direction: column; font-size: 15px; font-weight: 500; }
  .m-thread-sub { font-size: 10.5px; font-weight: 400; color: var(--color-accent); }
  .m-thread-scroll { flex: 1; min-height: 0; overflow-y: auto; padding: var(--space-4) 14px; display: flex; flex-direction: column; gap: var(--space-3); }
  .m-thread-note { flex: none; text-align: center; font-size: 11px; padding: var(--space-2) var(--space-4) 0; }
  .m-thread-compose { flex: none; border-top: 1px solid var(--color-divider); padding: var(--space-3) 14px 24px; }
  .m-thread-compose .thread-compose { padding: 0; align-items: flex-end; }
  .m-thread-send { width: 60px; height: 44px; flex: none; }

  /* Mine/theirs bubble side is flipped on mobile only -- desktop's own
     choice (commit e930986) is untouched above this media query. */
  .msg-row.is-mine { align-self: flex-end; align-items: flex-end; }
  .msg-row.is-theirs { align-self: flex-start; align-items: flex-start; }
  .msg-row.is-mine .msg-bubble-wrap { flex-direction: row-reverse; }
  .msg-row.is-theirs .msg-bubble-wrap { flex-direction: row; }
  /* No hover on touch -- delete moves to a long-press action sheet (app.js). */
  .msg-delete { display: none; }

  /* — Send sheet (§4) — */
  .m-send-body { padding: var(--space-6) var(--space-4); gap: var(--space-6); }
  .m-send-body > .field { margin-bottom: var(--space-6); }
  .m-drop-target {
    min-height: 132px; display: flex; flex-direction: column; align-items: center; justify-content: center;
    text-align: center; border-style: dashed; cursor: pointer;
  }
  .m-drop-line1 { color: var(--color-accent); font-size: 14px; }
  .m-drop-ios-hint { font-size: 11px; margin-top: 4px; }
  .m-send-chips { display: flex; flex-wrap: wrap; gap: var(--space-2); }
  .m-send-chip {
    display: inline-flex; align-items: center; gap: 4px; padding: 8px 14px; font: inherit; font-size: 13px;
    color: var(--color-text); background: transparent; border: 1px solid var(--color-divider); cursor: pointer;
  }
  .m-send-chip.is-active { border-color: var(--color-accent); background: var(--color-accent-100); color: var(--color-accent-800); }
  .m-chip-caret { color: var(--color-accent); }
  .m-send-note { font-size: 11px; line-height: 1.5; margin-top: auto; }

  /* — sending progress (§5) / interrupted (§10) — */
  .m-send-progress { padding: var(--space-6) var(--space-4); gap: var(--space-6); display: flex; flex-direction: column; }
  .m-kicker-muted { font-size: 10px; text-transform: uppercase; letter-spacing: 0.06em; color: color-mix(in srgb, var(--color-text) 55%, transparent); }
  .m-progress-step { display: flex; flex-direction: column; gap: 6px; }
  .m-progress-label { display: flex; justify-content: space-between; font-size: 13px; }
  .m-progress-bar { height: 5px; background: color-mix(in srgb, var(--color-text) 12%, transparent); }
  .m-progress-bar > span { display: block; height: 100%; background: var(--color-accent-300); }
  .m-progress-bar.is-active > span { background: var(--color-accent); }
  .m-progress-bar.is-waiting { opacity: 0.5; }
  .m-progress-bar.is-neutral > span { background: color-mix(in srgb, var(--color-text) 35%, transparent) !important; }
  .m-send-progress-note { font-size: 12px; line-height: 1.55; border: 1px solid var(--color-divider); padding: var(--space-3); }

  /* — Add-a-contact flow (§9) — */
  .m-flow-body { padding: var(--space-4); }
  .m-flow-heading { font-size: 24px; line-height: 1.2; margin-bottom: var(--space-2); }
  .m-flow-body-text { font-size: 13px; line-height: 1.6; }
  .m-flow-footer-links { display: flex; justify-content: space-between; font-size: 12px; margin-top: var(--space-1); }
  .m-beats { display: flex; flex-direction: column; gap: var(--space-2); margin: var(--space-4) 0; }
  .m-beat { border: 1px solid var(--color-divider); padding: var(--space-3); }
  .m-beat-title { font-family: var(--font-heading); font-weight: 600; font-size: 15px; }
  .m-beat-body { font-size: 12px; line-height: 1.5; }
  .m-qa { margin-top: var(--space-4); }
  .m-qa-q { font-family: var(--font-heading); font-weight: 600; font-size: 17px; }
  .m-qa-a { font-size: 13px; line-height: 1.5; }
  .m-options { display: flex; flex-direction: column; gap: var(--space-2); margin: var(--space-4) 0; }
  .m-option { border: 1px solid var(--color-divider); padding: var(--space-3); cursor: pointer; }
  .m-option.is-active { border-color: var(--color-accent); background: var(--color-accent-100); }
  .m-option-title { font-family: var(--font-heading); font-weight: 600; font-size: 16px; }
  .m-option-body { font-size: 12px; line-height: 1.5; }
  .m-added-body { padding: 80px var(--space-6) 0; }

  /* — Contacts & groups (§12, fix for defect 4) — */
  .m-section-label { padding: var(--space-3) var(--space-4) var(--space-1); font: 500 10px var(--font-heading); letter-spacing: 0.1em; text-transform: uppercase; color: color-mix(in srgb, var(--color-text) 50%, transparent); }
  .m-contact-row { display: flex; align-items: center; gap: var(--space-3); padding: var(--space-3) var(--space-4); border-top: 1px solid var(--color-divider); }
  .m-group-block { border-top: 1px solid var(--color-divider); padding-top: var(--space-2); margin-bottom: var(--space-2); }
  .m-group-block .m-contact-row { border-top: none; }

  /* — sign-in (§13) — */
  .m-signin-shell { flex: 1; padding: 56px var(--space-6) 0; }
  .m-signin-heading { font-size: 30px; margin-bottom: var(--space-2); }
}

/* — touch: keep form controls at 16px (iOS zoom) — */
/* iOS Safari magnifies the whole page whenever a focused text control renders
   under 16px, and it never undoes that zoom on blur. In a single-page app the
   magnification then rides along through every client-side navigation, so
   every screen after the first comes up "pinched in" until the user pinches
   back out by hand. Sixteen pixels on coarse pointers is the only way to stop
   that without disabling zoom outright.

   Keyed off pointer rather than the 860px layout breakpoint because the
   trigger is the input device, not the window: the vault secret-field iframe
   is only ~300px wide even on a desktop and should keep its 14px there. The
   cross-origin vault pages load this same stylesheet, which they need to --
   an under-16px field inside an iframe zooms the top-level page just the
   same. */
@media (pointer: coarse) {
  .input, input, select, textarea { font-size: 16px; }
  /* Both search fields set their own smaller size and outrank the rule above
     on specificity, so they have to be named. */
  .filterbar .input, .m-searchrow .input { font-size: 16px; }
}
