/* SMS – Super Messaging Service
   Frontend styling, translated from the Claude Design prototype
   (design/v2/SMS - Super Messaging Service v2.dc.html) into plain CSS.
   See design/v2/DESIGN_NOTES_V2.md for the token inventory this file
   implements, and design/DESIGN_NOTES.md for the v1 it grew out of. */

*, *::before, *::after { box-sizing: border-box; }

/* ==========================================================================
   Themes (DESIGN_NOTES_V2.md §1)
   --------------------------------------------------------------------------
   A theme is nothing but these eleven --t-* properties. The default one
   (Ästad Vingård) also sits on :root, so the page is correctly coloured
   before app.js has set html[data-theme] — and stays correct if a stored
   theme id is one this build doesn't know.

   Nothing below this block uses a --t-* value directly: the --color-*
   tokens map onto them, so every component rule written against
   --color-accent keeps working and simply follows the theme. The handful
   of exceptions are the places the prototype itself themes by hand (the
   login hero, the focus rings' rgb() triplets, the theme picker's dots).
   ========================================================================== */

:root,
html[data-theme="astad"] {
  --t-dark: #211D18;
  --t-acc: #8A6A35;
  --t-acch: #6F5429;
  --t-pale: #F6EFE1;
  --t-pale2: #E9DCC2;
  --t-ondark: #D9C7A3;
  --t-deco: #C9A66B;
  --t-bg: #F5F1E8;
  --t-acc-rgb: 138, 106, 53;
  --t-ondark-rgb: 217, 199, 163;
}

html[data-theme="kust"] {
  --t-dark: #16283A;
  --t-acc: #2F5E7A;
  --t-acch: #224861;
  --t-pale: #E9F0F3;
  --t-pale2: #CBDBE3;
  --t-ondark: #BCCFDA;
  --t-deco: #CDB894;
  --t-bg: #F1F3F2;
  --t-acc-rgb: 47, 94, 122;
  --t-ondark-rgb: 188, 207, 218;
}

:root {
  /* --- Colour tokens (DESIGN_NOTES_V2.md §2, "v1 → v2 token mapping") --- */
  --color-page-bg: var(--t-bg);
  --color-surface: #FFFFFF;
  --color-thread-bg: #F7F7F5;
  --color-surface-subtle: #F9FAFB;
  --color-track: #F2F4F7;
  --color-border: #E4E7EC;
  --color-border-subtle: #F2F4F7;
  --color-divider: #E9EDF3;
  --color-input-border: #D0D5DD;

  --color-text: #0F172A;
  --color-text-secondary: #334155;
  --color-text-muted: #64748B;
  --color-text-placeholder: #98A2B3;

  --color-navy: var(--t-dark);
  --color-accent: var(--t-acc);
  --color-accent-hover: var(--t-acch);
  --color-accent-tint-bg: var(--t-pale);
  --color-accent-tint-border: var(--t-pale2);

  /* (The plain #16B981 green went with v1's login hero — the success
     family is now only ever used as text on its own tint.) */
  --color-success-text: #0F8F66;
  --color-success-tint-bg: #E7F8F1;
  --color-success-border: #A7E8CF;
  --color-success-surface: #F3FBF7;

  --color-warning-text: #B54708;

  --color-danger-text: #C2410C;
  --color-danger-tint-bg: #FFF4F0;
  --color-danger-border: #F8B4A0;

  /* The toast reuses the theme's dark instead of a navy of its own. */
  --color-toast-bg: var(--t-dark);
  --color-toast-link: var(--t-ondark);

  /* (The avatar palette is not a token here: public/app.js sets each
     avatar's colour inline from AVATAR_PALETTE, whose first slot is the
     theme accent. The v1 --avatar-* tokens were never referenced by any
     rule and are gone.) */

  /* --- Radii --- */
  --radius-xs: 5px;
  --radius-tab: 7px;
  --radius-icon: 8px;
  --radius-input: 10px;
  --radius-card: 12px;
  --radius-toast: 11px;
  --radius-bubble: 14px;
  --radius-modal: 16px;
  --radius-sheet: 18px;
  --radius-sheet-lg: 20px;   /* account menu + sound sheet, v2 */
  --radius-login-card: 24px; /* the floating login card, v2 */
  --radius-pill: 999px;

  /* --- Shadows --- */
  --shadow-tab: 0 1px 2px rgba(16, 24, 40, .1);
  --shadow-focus: 0 0 0 3px rgba(var(--t-acc-rgb), .14);
  /* v2: plain inputs get a solid pale ring instead of a translucent one. */
  --shadow-focus-pale: 0 0 0 3px var(--t-pale);
  --shadow-modal: 0 24px 48px -12px rgba(16, 24, 40, .36);
  --shadow-popover: 0 16px 32px -8px rgba(16, 24, 40, .22);
  --shadow-toast: 0 12px 24px -8px rgba(16, 24, 40, .5);
  --shadow-fab: 0 10px 20px -6px rgba(var(--t-acc-rgb), .6);
  --shadow-login-card: 0 40px 80px -30px rgba(0, 0, 0, .6);

  /* --- Spacing scale (observed in the prototype, not a strict 8pt grid) --- */
  --space-1: 3px;
  --space-2: 4px;
  --space-3: 6px;
  --space-4: 8px;
  --space-5: 10px;
  --space-6: 12px;
  --space-7: 14px;
  --space-8: 16px;
  --space-9: 18px;
  --space-10: 20px;
  --space-11: 22px;
  --space-12: 24px;
  --space-13: 28px;
  --space-14: 32px;
  --space-15: 40px;
  --space-16: 56px;

  /* --- Type scale (the prototype's whole inventory, so a step with no
         current user is the scale being complete, not dead code; the
         login screen's display sizes are one-offs in its own rules) --- */
  --fs-10: 10px;
  --fs-11: 11px;
  --fs-12: 12px;
  --fs-13: 13px;
  --fs-14: 14px;
  --fs-15: 15px;
  --fs-16: 16px;
  --fs-17: 17px;
  --fs-20: 20px;
  --fs-22: 22px;
  --fs-26: 26px;
  --fs-30: 30px;

  --font-sans: Inter, -apple-system, "Segoe UI", system-ui, sans-serif;

  --breakpoint: 860px;
}

html, body {
  height: 100%;
  margin: 0;
}

body {
  font-family: var(--font-sans);
  background: var(--color-page-bg);
  color: var(--color-text);
  font-size: var(--fs-15);
  -webkit-font-smoothing: antialiased;
  overscroll-behavior-y: none;
}

a { color: var(--color-accent); text-decoration: none; }
a:hover { color: var(--color-accent-hover); text-decoration: underline; }

button, input, textarea, select { font: inherit; color: inherit; }
input, textarea, select { outline: none; }
::placeholder { color: var(--color-text-placeholder); }

button {
  cursor: pointer;
  background: none;
  border: none;
}

.hidden { display: none !important; }

kbd {
  padding: 1px 6px;
  border-radius: var(--radius-xs);
  border: 1px solid var(--color-border);
  background: var(--color-surface-subtle);
  font: inherit;
  font-weight: 600;
  color: var(--color-text-muted);
}

@keyframes toastIn {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}

@keyframes bubbleIn {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: translateY(0); }
}

@keyframes sheetIn {
  from { transform: translateY(100%); }
  to { transform: translateY(0); }
}

/* ==========================================================================
   App shell
   ========================================================================== */

#app {
  height: 100vh;
  height: 100dvh;
  display: flex;
  flex-direction: column;
  background: var(--color-surface);
  overflow: hidden;
}

.view-app {
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 0;
}

/* ==========================================================================
   Brand mark
   ========================================================================== */

.brand-mark {
  display: flex;
  align-items: center;
  gap: var(--space-5);
}

.brand-mark img, .brand-glyph { display: block; flex: none; }

.brand-wordmark {
  font-size: var(--fs-15);
  font-weight: 600;
  color: var(--color-text);
  white-space: nowrap;
}

.brand-wordmark strong {
  color: var(--color-navy);
  font-weight: 700;
  letter-spacing: -.02em;
}

.brand-wordmark span {
  font-size: var(--fs-11);
  font-weight: 600;
  letter-spacing: .12em;
  color: var(--color-text-placeholder);
  margin-left: var(--space-5);
}

/* ==========================================================================
   Buttons
   ========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  height: 38px;
  padding: 0 var(--space-7);
  border-radius: var(--radius-input);
  font-size: var(--fs-14);
  font-weight: 600;
  border: none;
  white-space: nowrap;
  transition: background .12s ease;
}

.btn-primary {
  background: var(--color-accent);
  color: var(--color-surface);
}
.btn-primary:hover { background: var(--color-accent-hover); }
.btn-primary:disabled { background: var(--color-border); color: var(--color-text-placeholder); cursor: default; }

.btn-secondary {
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  color: var(--color-text-secondary);
  font-weight: 500;
}
.btn-secondary:hover { background: var(--color-surface-subtle); }

.btn-danger {
  background: var(--color-surface);
  border: 1px solid var(--color-danger-border);
  color: var(--color-danger-text);
  font-weight: 600;
}
.btn-danger:hover { background: var(--color-danger-tint-bg); }

.btn-danger-solid {
  background: var(--color-danger-text);
  color: var(--color-surface);
}
.btn-danger-solid:hover { background: #A6380C; }

.btn-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: var(--radius-icon);
  background: transparent;
  color: var(--color-text-secondary);
  font-size: var(--fs-16);
  transition: background .12s ease;
}
.btn-icon:hover { background: var(--color-track); }

.btn-icon-outline {
  border: 1px solid var(--color-border);
  background: var(--color-surface);
}
.btn-icon-outline:hover { background: var(--color-surface-subtle); }

.btn-link {
  background: none;
  border: none;
  padding: 0;
  color: var(--color-accent);
  font-size: var(--fs-13);
  font-weight: 500;
}
.btn-link:hover { color: var(--color-accent-hover); text-decoration: underline; }

/* ==========================================================================
   Inputs
   ========================================================================== */

.field {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  font-size: var(--fs-13);
  font-weight: 500;
  color: var(--color-text-secondary);
}

.input, textarea.input, select.input {
  height: 46px;
  padding: 0 var(--space-7);
  border-radius: var(--radius-input);
  border: 1px solid var(--color-input-border);
  background: var(--color-surface);
  font-size: var(--fs-15);
  color: var(--color-text);
}

/* v2 (DESIGN_NOTES_V2.md §2): the everyday form fields get a solid pale
   ring in the theme's own tint. The login, search and rename fields keep
   the translucent accent ring — they override this below. */
.input:focus, textarea.input:focus, select.input:focus {
  border-color: var(--color-accent);
  box-shadow: var(--shadow-focus-pale);
}

/* ==========================================================================
   Login screen (DESIGN_NOTES_V2.md §3, "Login")
   --------------------------------------------------------------------------
   v2 turns the page inside out: the whole viewport is the theme's dark, the
   hero (wordmark + the three "vad SMS står för" lines) fills the wide left
   column, and the form is a white card floating on top of the dark on the
   right. The markup order is form-then-hero, so the two columns are placed
   with `order` rather than by moving anything app.js talks to.
   ========================================================================== */

.login-screen {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
  background: var(--t-dark);
  overflow-y: auto;
}

/* --- the form side: a floating white card ------------------------------ */

.login-form-col {
  order: 2;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-self: center;
  justify-self: center;
  width: 100%;
  max-width: 420px;
  margin: var(--space-14) var(--space-12);
  padding: var(--space-15) 36px var(--space-14);
  gap: 26px;
  background: var(--color-surface);
  border-radius: var(--radius-login-card);
  box-shadow: var(--shadow-login-card);
}

.login-form-col .brand-mark { gap: var(--space-5); }

.login-heading { display: flex; flex-direction: column; gap: var(--space-4); }

.login-heading h1 {
  margin: 0;
  font-size: 28px;
  font-weight: 700;
  letter-spacing: -.025em;
  line-height: 1.15;
  color: var(--color-text);
  text-wrap: pretty;
}

.login-heading p {
  margin: 0;
  font-size: var(--fs-14);
  line-height: 1.55;
  color: var(--color-text-muted);
}

.login-fields {
  display: flex;
  flex-direction: column;
  gap: var(--space-7);
}

/* The login fields are the one place with a heavier border and a tinted
   resting background (DESIGN_NOTES_V2.md §2, "Spacing/borders"), and they
   keep the translucent accent focus ring the rest of the app dropped. */
.login-fields .input {
  height: 48px;
  padding: 0 var(--space-8);
  border-width: 1.5px;
  border-color: #E2E8F0;
  background: var(--color-surface-subtle);
  transition: border-color .15s ease, box-shadow .15s ease, background .15s ease;
}
.login-fields .input:focus {
  border-color: var(--color-accent);
  background: var(--color-surface);
  box-shadow: 0 0 0 4px rgba(var(--t-acc-rgb), .14);
}

.login-error {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-5) var(--space-6);
  border-radius: var(--radius-input);
  background: var(--color-danger-tint-bg);
  border: 1px solid var(--color-danger-border);
  color: var(--color-danger-text);
  font-size: var(--fs-13);
  font-weight: 500;
}

.login-fields button[type="submit"] {
  margin-top: var(--space-2);
  height: 52px;
  border-radius: var(--radius-input);
  border: none;
  background: var(--color-accent);
  color: var(--color-surface);
  font-size: var(--fs-15);
  font-weight: 700;
  box-shadow: 0 10px 24px -10px rgba(var(--t-acc-rgb), .8);
  transition: background .15s ease, transform .1s ease;
}
.login-fields button[type="submit"]:hover { background: var(--color-accent-hover); }
.login-fields button[type="submit"]:active { transform: scale(.98); }

.login-microcopy {
  margin: 0;
  font-size: var(--fs-12);
  line-height: 1.5;
  color: var(--color-text-placeholder);
  text-align: center;
}

/* --- the hero side ------------------------------------------------------ */

.login-hero {
  order: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--space-13);
  padding: 44px clamp(32px, 6vw, 88px) 40px;
  position: relative;
  overflow: hidden;
  color: var(--color-surface);
}

/* Two out-of-frame discs in the theme's accent and its decorative gold —
   the only decoration on the page. */
.login-hero::before, .login-hero::after {
  content: "";
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
}
.login-hero::before {
  left: -160px; bottom: -220px; width: 560px; height: 560px;
  background: var(--t-acc); opacity: .22;
}
.login-hero::after {
  right: -120px; top: 40%; width: 300px; height: 300px;
  background: var(--t-deco); opacity: .12;
}

.login-hero-kicker {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  position: relative;
  font-size: var(--fs-11);
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--t-ondark);
}
.login-hero-kicker .dot {
  width: 8px; height: 8px; border-radius: 50%; background: var(--t-deco);
}

/* The fun "what SMS stands for" lines ARE the hero text. */
.login-hero-fun {
  position: relative;
  margin: 0;
  max-width: 560px;
  display: flex;
  flex-direction: column;
  gap: var(--space-13);
}
.login-hero-fun-title {
  font-size: max(96px, min(15vw, 22vh, 220px));
  line-height: .82;
  font-weight: 800;
  letter-spacing: -.06em;
  color: var(--color-surface);
}
/* The hairline under the wordmark. */
.login-hero-fun-title::after {
  content: "";
  display: block;
  width: 100%;
  max-width: 520px;
  height: 1px;
  margin-top: var(--space-13);
  background: rgba(var(--t-ondark-rgb), .22);
}
.login-hero-fun-row {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  min-width: 0;
  padding: var(--space-5) 0;
  border-bottom: 1px solid rgba(var(--t-ondark-rgb), .12);
}
.login-hero-fun-row:last-child { border-bottom: none; }
.login-hero-fun-row dt {
  margin: 0;
  font-size: var(--fs-12);
  color: var(--t-ondark);
}
.login-hero-fun-row dd {
  margin: 0;
  font-size: clamp(15px, 1.5vw, 20px);
  line-height: 1.3;
  font-weight: 700;
  color: var(--color-surface);
}
/* Each word's initial, so the acronym reads out of the sentence. */
.login-hero-fun-row dd .i { color: var(--t-ondark); }
.login-hero-fun-row:last-child dd .i { color: var(--t-deco); }

/* ==========================================================================
   Desktop top bar
   ========================================================================== */

.topbar {
  height: 56px;
  flex: none;
  padding: 0 var(--space-10);
  border-bottom: 1px solid var(--color-border);
  display: flex;
  align-items: center;
  gap: var(--space-6);
  background: var(--color-surface);
}

.topbar .brand-phone {
  font-size: var(--fs-13);
  color: var(--color-text-placeholder);
}

.topbar-spacer { flex: 1; }

.user-chip {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  padding: var(--space-2) var(--space-5) var(--space-2) var(--space-2);
  border-radius: var(--radius-pill);
  background: var(--color-track);
  cursor: pointer;
  transition: background .12s ease;
}
.user-chip:hover { background: var(--color-border); }

.user-chip-avatar {
  width: 26px; height: 26px; border-radius: 50%;
  background: var(--color-accent); color: var(--color-surface);
  display: grid; place-items: center;
  font-size: var(--fs-11); font-weight: 700;
  cursor: pointer;
}

.user-chip-name {
  font-size: var(--fs-13);
  font-weight: 500;
  color: var(--color-text-secondary);
}

/* ==========================================================================
   Inbox screen layout
   ========================================================================== */

#screen-inbox {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.inbox-body {
  flex: 1;
  min-height: 0;
  display: flex;
  overflow: hidden;
  position: relative;
}

.pane-list {
  width: 372px;
  flex: none;
  border-right: 1px solid var(--color-border);
  display: flex;
  flex-direction: column;
  background: var(--color-surface);
  min-height: 0;
}

.list-header-mobile {
  display: none;
}

.list-toolbar {
  padding: var(--space-6) var(--space-7) var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

/* v2 (DESIGN_NOTES_V2.md §3): the two send buttons share the top row and
   the search field gets the full width underneath, instead of all three
   fighting over one row — at 372px the search box was down to a few
   characters. The markup order is search-then-buttons, so the grid places
   the items rather than the DOM doing it. */
.search-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: var(--space-4);
  align-items: center;
}
.search-row #btn-new-sms { grid-area: 1 / 1; }
.search-row #btn-multi-sms { grid-area: 1 / 2; }
.search-row .search-wrap { grid-area: 2 / 1 / 3 / -1; }

.search-wrap {
  flex: 1;
  position: relative;
  display: flex;
  align-items: center;
}

.search-wrap .search-icon {
  position: absolute;
  left: var(--space-6);
  font-size: var(--fs-14);
  color: var(--color-text-placeholder);
  pointer-events: none;
}

#search-input {
  width: 100%;
  height: 38px;
  padding: 0 14px 0 32px;
  border-radius: var(--radius-input);
  border: 1px solid var(--color-input-border);
  background: var(--color-surface);
  font-size: var(--fs-14);
  color: var(--color-text);
  transition: box-shadow .15s ease, border-color .15s ease;
}
#search-input:focus { border-color: var(--color-accent); box-shadow: var(--shadow-focus); }

#btn-new-sms {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
}

.filter-tabs {
  display: flex;
  gap: var(--space-2);
  padding: 3px;
  background: var(--color-track);
  border-radius: var(--radius-input);
}

.filter-tab {
  flex: 1;
  height: 30px;
  border-radius: var(--radius-tab);
  border: none;
  background: transparent;
  color: var(--color-text-muted);
  font-size: var(--fs-13);
  font-weight: 500;
  cursor: pointer;
}

.filter-tab.active {
  background: var(--color-surface);
  color: var(--color-text);
  font-weight: 600;
  box-shadow: var(--shadow-tab);
}

.conversation-list {
  flex: 1;
  overflow-y: auto;
  border-top: 1px solid var(--color-border-subtle);
}

.empty-hint {
  padding: var(--space-15) var(--space-6);
  text-align: center;
  font-size: var(--fs-13);
  color: var(--color-text-placeholder);
}

.conv-row {
  display: flex;
  gap: 11px;
  align-items: flex-start;
  padding: 10px 14px;
  padding-left: 11px;
  border-bottom: 1px solid var(--color-border-subtle);
  border-left: 3px solid transparent;
  background: var(--color-surface);
  cursor: pointer;
  transition: background .12s ease;
}
.conv-row:hover { background: #F7F9FC; }
.conv-row.selected { background: var(--color-accent-tint-bg); border-left-color: var(--color-accent); }

.conv-avatar {
  width: 38px; height: 38px; flex: none; border-radius: 50%;
  display: grid; place-items: center;
  font-size: var(--fs-12); font-weight: 700; letter-spacing: .02em;
}

.conv-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.conv-top-row {
  display: flex;
  align-items: baseline;
  gap: var(--space-4);
}

.conv-name {
  flex: 1;
  min-width: 0;
  font-size: var(--fs-14);
  font-weight: 500;
  color: var(--color-text-secondary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.conv-row.unread .conv-name { font-weight: 700; color: var(--color-text); }

.conv-time {
  flex: none;
  font-size: var(--fs-12);
  color: var(--color-text-placeholder);
}
.conv-row.unread .conv-time { font-weight: 600; color: var(--color-accent-hover); }

.conv-preview {
  font-size: var(--fs-13);
  line-height: 1.35;
  color: var(--color-text-placeholder);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.conv-row.unread .conv-preview { color: var(--color-text-secondary); font-weight: 500; }

.conv-lastby {
  font-size: var(--fs-11);
  color: var(--color-text-placeholder);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  height: 14px;
}

.conv-side {
  width: 20px;
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
}

.conv-unread-badge {
  min-width: 18px; height: 18px; padding: 0 5px;
  border-radius: var(--radius-pill);
  background: var(--color-accent); color: var(--color-surface);
  font-size: var(--fs-11); font-weight: 700;
  display: grid; place-items: center;
}

.conv-failed-dot {
  width: 16px; height: 16px; border-radius: 50%;
  background: var(--color-danger-tint-bg); color: var(--color-danger-text);
  font-size: var(--fs-11); font-weight: 700;
  display: grid; place-items: center;
}

.fab-new-sms { display: none; }

/* ==========================================================================
   Thread pane
   ========================================================================== */

.pane-thread {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  background: var(--color-thread-bg);
}

.thread-empty {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-6);
  text-align: center;
  padding: var(--space-15);
}

.thread-empty-icon {
  width: 56px; height: 56px; border-radius: var(--radius-card);
  background: var(--color-accent-tint-bg); color: var(--color-accent);
  display: grid; place-items: center; font-size: var(--fs-22);
}

.thread-empty h2 {
  margin: 0; font-size: var(--fs-17); font-weight: 600; color: var(--color-text);
}

.thread-empty p {
  margin: 0; font-size: var(--fs-14); color: var(--color-text-muted);
  max-width: 320px; line-height: 1.5;
}

.thread-view {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

.thread-header {
  height: 64px;
  flex: none;
  padding: 0 var(--space-11);
  border-bottom: 1px solid var(--color-border);
  background: var(--color-surface);
  display: flex;
  align-items: center;
  gap: var(--space-6);
}

.thread-avatar {
  width: 36px; height: 36px; flex: none; border-radius: 50%;
  display: grid; place-items: center;
  font-size: var(--fs-13); font-weight: 700; letter-spacing: .02em;
}

.thread-header-info {
  display: flex;
  flex-direction: column;
  gap: 1px;
  /* flex-basis 0% (not auto) so the available-width computation isn't
     circular with the ellipsis-truncated child below — see .name-text. */
  flex: 1 1 0%;
  min-width: 0;
}

.thread-name-btn {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  height: 26px;
  margin: -3px -8px;
  padding: 0 var(--space-4);
  border-radius: var(--radius-tab);
  background: transparent;
  font-size: var(--fs-15);
  font-weight: 600;
  color: var(--color-text);
  cursor: text;
  text-align: left;
  width: 100%;
  min-width: 0;
  transition: background .12s ease;
}
.thread-name-btn:hover { background: var(--color-track); }
.thread-name-btn .name-text {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.thread-name-btn .pencil { font-size: var(--fs-12); font-weight: 500; color: var(--color-text-placeholder); flex: none; }

#edit-name-input {
  height: 26px;
  width: 260px;
  margin: -3px -8px;
  padding: 0 var(--space-4);
  border-radius: var(--radius-tab);
  border: 1px solid var(--color-accent);
  box-shadow: var(--shadow-focus);
  font-size: var(--fs-15);
  font-weight: 600;
  color: var(--color-text);
  background: var(--color-surface);
}

.thread-phone {
  font-size: var(--fs-13);
  color: var(--color-text-muted);
}

/* Persistent warning badge for a non-Swedish conversation (docs/WISHLIST.md
   "Skicka till alla länder") — SMS to it costs more than to a Swedish
   number, so this stays visible in the header, not just on first send. */
.badge-foreign {
  display: inline-flex;
  align-items: center;
  width: fit-content;
  height: 18px;
  padding: 0 var(--space-4);
  margin-top: 1px;
  border-radius: var(--radius-pill);
  background: var(--color-danger-tint-bg);
  border: 1px solid var(--color-danger-border);
  color: var(--color-warning-text);
  font-size: var(--fs-11);
  font-weight: 600;
  white-space: nowrap;
}


.thread-header-actions {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

#btn-archive {
  height: 36px;
  padding: 0 var(--space-7);
  border-radius: var(--radius-input);
  border: 1px solid var(--color-border);
  background: var(--color-surface);
  color: var(--color-text-secondary);
  font-size: var(--fs-13);
  font-weight: 500;
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
}
#btn-archive:hover { background: var(--color-surface-subtle); }

#btn-delete-trigger {
  height: 36px;
  padding: 0 var(--space-7);
  border-radius: var(--radius-input);
  font-size: var(--fs-13);
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
}

#btn-archive .icon-glyph, #btn-delete-trigger .icon-glyph { display: none; }

#btn-rename-mobile, #btn-back { display: none; }

.messages {
  flex: 1;
  overflow-y: auto;
  padding: var(--space-11) var(--space-12) var(--space-6);
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.thread-empty-hint {
  margin: auto;
  text-align: center;
  font-size: var(--fs-13);
  color: var(--color-text-placeholder);
  max-width: 300px;
  line-height: 1.5;
}

.day-separator {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  padding: 14px 0 10px;
}
.day-separator .line { flex: 1; height: 1px; background: var(--color-divider); }
.day-separator .label { font-size: var(--fs-12); font-weight: 500; color: var(--color-text-placeholder); white-space: nowrap; }

.msg-wrap {
  display: flex;
  flex-direction: column;
  margin-top: 8px;
}
.msg-wrap.out { align-items: flex-end; }
.msg-wrap.in { align-items: flex-start; }

.bubble {
  max-width: 560px;
  padding: 10px 14px;
  border-radius: var(--radius-bubble);
  font-size: var(--fs-15);
  line-height: 1.5;
  white-space: pre-wrap;
  word-break: break-word;
  animation: bubbleIn .16s ease-out;
}
.msg-wrap.out .bubble {
  background: var(--color-accent);
  color: var(--color-surface);
  border-radius: 14px 14px 4px 14px;
}
.msg-wrap.in .bubble {
  background: var(--color-surface);
  color: var(--color-text);
  border: 1px solid var(--color-border);
  border-radius: 14px 14px 14px 4px;
}

.bubble-meta {
  margin-top: 4px;
  font-size: var(--fs-11);
  font-weight: 500;
  color: var(--color-text-placeholder);
}
.bubble-meta.failed { color: var(--color-danger-text); }

/* ==========================================================================
   Mock dev panel
   ========================================================================== */

.mock-panel {
  flex: none;
  border-top: 1px dashed var(--color-border);
  background: var(--color-surface-subtle);
  padding: var(--space-4) var(--space-11);
}

.mock-panel summary {
  font-size: var(--fs-12);
  font-weight: 600;
  color: var(--color-text-muted);
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  gap: var(--space-3);
}
.mock-panel summary::-webkit-details-marker { display: none; }
.mock-panel summary::before { content: "⚙"; font-size: var(--fs-12); }

.mock-panel-body {
  display: flex;
  gap: var(--space-4);
  margin-top: var(--space-4);
}

.mock-panel-body input {
  flex: 1;
  height: 32px;
  padding: 0 var(--space-5);
  border-radius: var(--radius-tab);
  border: 1px solid var(--color-border);
  background: var(--color-surface);
  font-size: var(--fs-13);
}

.mock-panel-body button {
  height: 32px;
  padding: 0 var(--space-6);
  border-radius: var(--radius-tab);
  border: 1px solid var(--color-border);
  background: var(--color-surface);
  color: var(--color-text-secondary);
  font-size: var(--fs-13);
  font-weight: 500;
}
.mock-panel-body button:hover { background: var(--color-track); }

/* ==========================================================================
   Compose box
   ========================================================================== */

.compose {
  flex: none;
  padding: var(--space-6) var(--space-12) var(--space-9);
  border-top: 1px solid var(--color-border);
  background: var(--color-surface);
}

.compose-box {
  border: 1px solid var(--color-input-border);
  border-radius: var(--radius-card);
  background: var(--color-surface);
  padding: 10px 12px 8px;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

#compose-text {
  width: 100%;
  border: none;
  outline: none;
  resize: none;
  font-size: var(--fs-15);
  line-height: 1.5;
  color: var(--color-text);
  background: transparent;
  min-height: 48px;
  max-height: 140px;
  font-family: inherit;
}

.compose-row {
  display: flex;
  align-items: center;
  gap: var(--space-6);
}

.compose-counter {
  font-size: var(--fs-12);
  font-weight: 500;
  white-space: nowrap;
  flex: none;
  color: var(--color-text-placeholder);
}
.compose-counter.over { color: var(--color-warning-text); }

.compose-helper {
  font-size: var(--fs-12);
  color: var(--color-text-placeholder);
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.compose-spacer { flex: 1; }

#btn-templates {
  height: 30px;
  padding: 0 var(--space-5);
  border-radius: var(--radius-tab);
  border: 1px solid var(--color-border);
  background: var(--color-surface);
  color: var(--color-text-secondary);
  font-size: var(--fs-12);
  font-weight: 500;
  flex: none;
}
#btn-templates:hover { background: var(--color-surface-subtle); }

#compose-send {
  height: 38px;
  padding: 0 20px;
  border-radius: var(--radius-input);
  border: none;
  font-size: var(--fs-14);
  font-weight: 600;
  background: var(--color-border);
  color: var(--color-text-placeholder);
  cursor: default;
  transition: background .15s ease;
}
#compose-send.can-send {
  background: var(--color-accent);
  color: var(--color-surface);
  cursor: pointer;
}
#compose-send.can-send:hover { background: var(--color-accent-hover); }

/* ==========================================================================
   Modals / dialogs
   ========================================================================== */

.modal-backdrop {
  position: fixed;
  inset: 0;
  background: rgba(16, 24, 40, .42);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding-top: 120px;
  z-index: 60;
}

.modal-backdrop.hidden { display: none; }

.modal {
  width: 520px;
  max-width: calc(100vw - 32px);
  max-height: calc(100vh - 160px);
  background: var(--color-surface);
  border-radius: var(--radius-modal);
  box-shadow: var(--shadow-modal);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.modal-sm { width: 420px; padding: var(--space-10); gap: var(--space-7); }
.modal-sm.modal { display: flex; flex-direction: column; }

.modal-header {
  padding: 18px 20px 14px;
  border-bottom: 1px solid var(--color-border);
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
}

.modal-header-row {
  display: flex;
  align-items: center;
}

.modal-header-row h3 {
  margin: 0;
  font-size: var(--fs-16);
  font-weight: 600;
  color: var(--color-text);
}

.modal-close {
  width: 32px; height: 32px; border-radius: var(--radius-icon);
  background: var(--color-track); color: var(--color-text-muted);
  font-size: var(--fs-15);
  margin-left: auto;
}
.modal-close:hover { background: var(--color-border); }

.modal-back { display: none; }

#new-sms-search {
  height: 44px;
  padding: 0 var(--space-7);
  border-radius: var(--radius-input);
  border: 1px solid var(--color-input-border);
  font-size: var(--fs-15);
  color: var(--color-text);
}
#new-sms-search:focus { border-color: var(--color-accent); box-shadow: var(--shadow-focus); }

.modal-list {
  max-height: 320px;
  overflow-y: auto;
}

.suggestion-item, .new-number-item {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  padding: 10px 20px;
  cursor: pointer;
  border-bottom: 1px solid var(--color-border-subtle);
}
.suggestion-item:hover, .new-number-item:hover { background: #F7F9FC; }

.new-number-item .plus-avatar {
  width: 36px; height: 36px; border-radius: 50%;
  background: var(--color-accent-tint-bg); color: var(--color-accent);
  display: grid; place-items: center; font-size: var(--fs-15); font-weight: 700;
}

.suggestion-item .conv-avatar { width: 36px; height: 36px; }

.suggestion-text, .new-number-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
}
.suggestion-text strong, .new-number-text strong {
  font-size: var(--fs-14);
  font-weight: 500;
  color: var(--color-text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.suggestion-text span, .new-number-text span {
  font-size: var(--fs-12);
  color: var(--color-text-muted);
}

.modal-empty {
  padding: 28px 20px;
  text-align: center;
  font-size: var(--fs-13);
  color: var(--color-text-placeholder);
}

.error-text {
  margin: 0;
  padding: 12px 20px;
  font-size: var(--fs-13);
  color: var(--color-danger-text);
}

/* Inside a .modal-sm the dialog already has its own padding, so an error
   line shouldn't add a second indent on top of it. */
.modal-sm .error-text { padding: 0; }

/* Rename + delete-confirm modals share .modal-sm */

.modal-sm h3 { margin: 0; font-size: var(--fs-16); font-weight: 600; color: var(--color-text); }
.modal-sm p { margin: 0; font-size: var(--fs-13); color: var(--color-text-muted); line-height: 1.5; }
#rename-input {
  height: 44px; padding: 0 var(--space-7);
  border-radius: var(--radius-input); border: 1px solid var(--color-input-border);
  font-size: var(--fs-15); color: var(--color-text);
}
#rename-input:focus { border-color: var(--color-accent); box-shadow: var(--shadow-focus); }

.modal-actions {
  display: flex;
  gap: var(--space-4);
  justify-content: flex-end;
}

/* ==========================================================================
   Templates ("Mallar") popover + manage dialog
   ========================================================================== */

/* The "Mallar" picker reads as a popover next to the compose box, so it
   gets the popover shadow rather than the dialog one. */
.modal-templates { width: 340px; padding: var(--space-8) var(--space-8) var(--space-6); gap: 0; }
.modal-templates.modal { box-shadow: var(--shadow-popover); }
.modal-templates .modal-header-row { padding-bottom: var(--space-6); }
.modal-templates .modal-header-row h3 { margin: 0; font-size: var(--fs-16); font-weight: 600; color: var(--color-text); }

.templates-popover-list {
  max-height: 280px;
  overflow-y: auto;
  margin: 0 calc(-1 * var(--space-8));
}

.template-item {
  display: flex;
  flex-direction: column;
  gap: 2px;
  width: 100%;
  padding: 9px var(--space-8);
  text-align: left;
  cursor: pointer;
  border-bottom: 1px solid var(--color-border-subtle);
}
.template-item:hover { background: #F7F9FC; }
.template-item .title { font-size: var(--fs-14); font-weight: 600; color: var(--color-text); }
.template-item .snippet {
  font-size: var(--fs-12);
  color: var(--color-text-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.templates-empty {
  padding: 24px 4px;
  text-align: center;
  font-size: var(--fs-13);
  color: var(--color-text-placeholder);
}

.templates-popover-footer {
  padding-top: var(--space-6);
  margin-top: var(--space-3);
  border-top: 1px solid var(--color-border);
  text-align: center;
}

/* ==========================================================================
   "Ljud och notiser" — per-account notification sound (on/off, volume, tone)
   ========================================================================== */

/* `.modal` clips its overflow, and on a short laptop screen (max-height is
   100vh - 160px) the five tone rows plus the note are taller than that —
   so this one scrolls instead of quietly cutting the last tone off. */
.modal-sound { width: 440px; gap: var(--space-8); overflow-y: auto; }

.sound-switch-row {
  display: flex;
  align-items: center;
  gap: var(--space-8);
  cursor: pointer;
}
.sound-switch-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.sound-switch-title { font-size: var(--fs-14); font-weight: 600; color: var(--color-text); }
.sound-switch-hint { font-size: var(--fs-12); color: var(--color-text-muted); }
/* A real on/off switch rather than a tick box — it is the same control as
   the speaker button in the header, and reads as "on or off" at a glance. */
.sound-switch-row input[type="checkbox"] {
  flex: none;
  margin: 0 0 0 auto;
  position: relative;
  width: 44px;
  height: 26px;
  border-radius: var(--radius-pill);
  border: none;
  background: var(--color-input-border);
  appearance: none;
  -webkit-appearance: none;
  cursor: pointer;
  transition: background .15s ease;
}
.sound-switch-row input[type="checkbox"]::after {
  content: "";
  position: absolute;
  top: 3px;
  left: 3px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--color-surface);
  box-shadow: 0 1px 2px rgba(16, 24, 40, .25);
  transition: transform .15s ease;
}
.sound-switch-row input[type="checkbox"]:checked { background: var(--color-accent); }
.sound-switch-row input[type="checkbox"]:checked::after { transform: translateX(18px); }
.sound-switch-row input[type="checkbox"]:focus-visible { box-shadow: var(--shadow-focus); }

.sound-volume-row {
  display: flex;
  align-items: center;
  gap: var(--space-6);
}
.sound-volume-row label {
  font-size: var(--fs-13);
  font-weight: 600;
  color: var(--color-text-secondary);
}
.sound-volume-row input[type="range"] {
  flex: 1;
  min-width: 0;
  accent-color: var(--color-accent);
  cursor: pointer;
}
.sound-volume-row output {
  min-width: 34px;
  text-align: right;
  font-size: var(--fs-13);
  font-variant-numeric: tabular-nums;
  color: var(--color-text-muted);
}

.sound-tones {
  display: flex;
  flex-direction: column;
  /* Never let the flex column squeeze the list: it clips its own overflow
     (that is what rounds the corners), so a squeezed list would simply cut
     the last tone off with no way to reach it. The dialog scrolls instead. */
  flex: none;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-input);
  overflow: hidden;
}

.sound-tone-row {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  padding: var(--space-5) var(--space-6);
  border-bottom: 1px solid var(--color-border-subtle);
}
.sound-tone-row:last-child { border-bottom: none; }
.sound-tone-row:hover { background: var(--color-surface-subtle); }
.sound-tone-row input[type="radio"] { flex: none; accent-color: var(--color-accent); cursor: pointer; }
.sound-tone-label {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
  cursor: pointer;
}
.sound-tone-label .name { font-size: var(--fs-14); font-weight: 600; color: var(--color-text); }
.sound-tone-label .hint {
  font-size: var(--fs-12);
  color: var(--color-text-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.sound-preview {
  flex: none;
  padding: 0 var(--space-6);
  min-height: 30px;
  font-size: var(--fs-12);
}

.sound-note {
  margin: 0;
  font-size: var(--fs-12);
  color: var(--color-text-muted);
  line-height: 1.5;
}

/* ==========================================================================
   Theme picker (DESIGN_NOTES_V2.md §1)
   --------------------------------------------------------------------------
   The same setting in two places: a segmented pill track in the account
   menu (where the prototype puts it) and a radio list inside "Ljud och
   notiser". Both are filled from THEMES in public/app.js, so a third
   theme needs nothing but a new entry there and a new
   html[data-theme="…"] block at the top of this file.
   ========================================================================== */

.sound-section {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.sound-section-title {
  font-size: var(--fs-11);
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--color-text-muted);
}

/* --- the account-menu pill track --- */

.user-menu-theme {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-6) var(--space-5);
  border-bottom: 1px solid var(--color-border-subtle);
  margin-bottom: var(--space-3);
}
.user-menu-theme-label {
  font-size: var(--fs-11);
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--color-text-placeholder);
}

.theme-segments {
  display: flex;
  gap: 2px;
  padding: 2px;
  border-radius: var(--radius-input);
  background: var(--color-track);
}
.theme-segment {
  flex: 1;
  min-width: 0;
  height: 30px;
  padding: 0 var(--space-4);
  border: none;
  border-radius: var(--radius-icon);
  background: transparent;
  color: var(--color-text-muted);
  font-family: inherit;
  font-size: var(--fs-12);
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
}
.theme-segment[aria-checked="true"] {
  background: var(--color-surface);
  color: var(--color-text);
  box-shadow: var(--shadow-tab);
}
.theme-segment:focus-visible { outline: 2px solid var(--color-accent); outline-offset: 1px; }
.theme-dot {
  flex: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
}
.theme-segment .theme-label {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* --- the radio list in "Ljud och notiser" --- */

.theme-radios {
  display: flex;
  flex-direction: column;
  flex: none;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-input);
  overflow: hidden;
}
.theme-radio-row {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  padding: var(--space-5) var(--space-6);
  min-height: 48px;
  border-bottom: 1px solid var(--color-border-subtle);
}
.theme-radio-row:last-child { border-bottom: none; }
.theme-radio-row:hover { background: var(--color-surface-subtle); }
.theme-radio-row input[type="radio"] { flex: none; accent-color: var(--color-accent); cursor: pointer; }
.theme-radio-label {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: var(--space-6);
  cursor: pointer;
  font-size: var(--fs-14);
  font-weight: 600;
  color: var(--color-text);
}
/* A three-dot swatch of the theme's dark / accent / decorative gold, so
   the choice can be made by looking rather than by reading. */
.theme-swatch { display: flex; flex: none; gap: var(--space-1); }
.theme-swatch span {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 1px solid rgba(16, 24, 40, .08);
}

.modal-manage-templates { width: 480px; }

.templates-manage-list { max-height: 340px; overflow-y: auto; }

.template-manage-row {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  padding: var(--space-5) 20px;
  border-bottom: 1px solid var(--color-border-subtle);
}
.template-manage-row .info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.template-manage-row .info strong { font-size: var(--fs-14); font-weight: 600; color: var(--color-text); }
.template-manage-row .info span {
  font-size: var(--fs-12);
  color: var(--color-text-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.template-manage-row .actions { display: flex; gap: var(--space-3); flex: none; }
.template-manage-row .actions button {
  height: 30px;
  padding: 0 var(--space-5);
  border-radius: var(--radius-tab);
  border: 1px solid var(--color-border);
  background: var(--color-surface);
  color: var(--color-text-secondary);
  font-size: var(--fs-12);
  font-weight: 500;
}
.template-manage-row .actions button:hover { background: var(--color-surface-subtle); }
.template-manage-row .actions .danger { color: var(--color-danger-text); border-color: var(--color-danger-border); }
.template-manage-row .actions .danger:hover { background: var(--color-danger-tint-bg); }

.templates-manage-footer { padding: var(--space-7) 20px var(--space-2); }

.templates-manage-form {
  padding: 20px;
  display: flex;
  flex-direction: column;
  gap: var(--space-7);
}

.template-body-field {
  width: 100%;
  min-height: 120px;
  padding: var(--space-6) var(--space-7);
  border-radius: var(--radius-input);
  border: 1px solid var(--color-input-border);
  background: var(--color-surface);
  font-size: var(--fs-14);
  font-family: inherit;
  line-height: 1.5;
  color: var(--color-text);
  resize: vertical;
}
.template-body-field:focus { border-color: var(--color-accent); box-shadow: var(--shadow-focus); outline: none; }

.template-form-counter {
  margin-top: calc(-1 * var(--space-4));
  font-size: var(--fs-12);
  color: var(--color-text-placeholder);
}

/* ==========================================================================
   Account menu + users admin (per-person logins)
   ========================================================================== */

.user-chip-caret {
  font-size: var(--fs-11);
  color: var(--color-text-placeholder);
  margin-left: calc(-1 * var(--space-2));
}

/* Transparent full-viewport layer so a click anywhere outside the menu
   closes it; it also dims the page on mobile, where the menu becomes a
   bottom sheet (see the media query at the end of this file). */
.menu-backdrop {
  position: fixed;
  inset: 0;
  z-index: 70;
}
.menu-backdrop.hidden { display: none; }

.user-menu {
  position: absolute;
  top: 60px;
  right: var(--space-10);
  width: 240px;
  padding: var(--space-3);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
  /* A popover, not a modal: v2 gives the dropdowns a shallower shadow
     than the dialogs (DESIGN_NOTES_V2.md §2). */
  box-shadow: var(--shadow-popover);
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.user-menu-head {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: var(--space-4) var(--space-5) var(--space-5);
  border-bottom: 1px solid var(--color-border-subtle);
  margin-bottom: var(--space-3);
}
.user-menu-name { font-size: var(--fs-14); font-weight: 600; color: var(--color-text); }
.user-menu-role { font-size: var(--fs-12); color: var(--color-text-muted); }

.user-menu-item {
  appearance: none;
  border: none;
  background: transparent;
  text-align: left;
  padding: var(--space-5);
  border-radius: var(--radius-icon);
  font-family: inherit;
  font-size: var(--fs-14);
  font-weight: 500;
  color: var(--color-text-secondary);
  cursor: pointer;
}
.user-menu-item:hover { background: var(--color-track); color: var(--color-text); }

.modal-users { width: 560px; }

.users-list {
  max-height: 360px;
  overflow-y: auto;
}

/* Name/username on one line, the three actions below it: the Swedish
   action labels ("Återställ lösenord", "Gör till användare") are too wide
   to sit beside the name without truncating "senaste inloggning ...". */
.user-row {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--space-5);
  padding: var(--space-6) 20px;
  border-bottom: 1px solid var(--color-border-subtle);
}
.user-row.inactive { background: var(--color-surface-subtle); }
.user-row .info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.user-row .info strong {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  flex-wrap: wrap;
  font-size: var(--fs-14);
  font-weight: 600;
  color: var(--color-text);
}
/* Wraps rather than truncating: this line ends with the "måste byta
   lösenord" flag, which was silently cut off by an ellipsis in the bottom
   sheet on a phone — the one place an admin is most likely to be scanning
   the list. Same reasoning as the wrapping action row below. */
.user-row .info .meta {
  font-size: var(--fs-12);
  color: var(--color-text-muted);
  white-space: normal;
  overflow-wrap: anywhere;
}
.user-row .actions { display: flex; gap: var(--space-3); flex: none; flex-wrap: wrap; justify-content: flex-start; }
.user-row .actions button {
  height: 30px;
  padding: 0 var(--space-5);
  border-radius: var(--radius-xs);
  border: 1px solid var(--color-input-border);
  background: var(--color-surface);
  font-family: inherit;
  font-size: var(--fs-12);
  font-weight: 500;
  color: var(--color-text-secondary);
  cursor: pointer;
}
.user-row .actions button:hover { background: var(--color-surface-subtle); }
.user-row .actions button:disabled { color: var(--color-text-placeholder); cursor: default; }

.user-badge {
  display: inline-flex;
  align-items: center;
  height: 20px;
  padding: 0 var(--space-4);
  border-radius: var(--radius-pill);
  font-size: var(--fs-11);
  font-weight: 600;
}
.user-badge.admin { background: var(--color-accent-tint-bg); color: var(--color-accent-hover); }
.user-badge.inactive { background: var(--color-track); color: var(--color-text-muted); }

.users-footer { padding: var(--space-7) 20px var(--space-8); }
.users-error { margin: 0 20px; }

.users-form, .users-password {
  display: flex;
  flex-direction: column;
  gap: var(--space-7);
  padding: var(--space-8) 20px var(--space-10);
}
.users-password h4 { margin: 0; font-size: var(--fs-16); font-weight: 600; color: var(--color-text); }
.users-password-note {
  margin: 0;
  font-size: var(--fs-13);
  font-weight: 600;
  color: var(--color-warning-text);
}
.users-hint { margin: 0; font-size: var(--fs-12); color: var(--color-text-muted); }

.temp-password-row {
  display: flex;
  align-items: center;
  gap: var(--space-5);
}
.temp-password {
  flex: 1;
  min-width: 0;
  padding: var(--space-6) var(--space-7);
  border-radius: var(--radius-input);
  border: 1px dashed var(--color-accent-tint-border);
  background: var(--color-accent-tint-bg);
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: var(--fs-16);
  font-weight: 600;
  letter-spacing: .04em;
  color: var(--color-text);
  overflow-wrap: anywhere;
}

/* ==========================================================================
   Toast
   ========================================================================== */

#toast {
  position: absolute;
  left: 50%;
  bottom: 26px;
  transform: translateX(-50%);
  animation: toastIn .18s ease-out;
  display: flex;
  align-items: center;
  gap: var(--space-5);
  padding: 11px 16px;
  border-radius: var(--radius-toast);
  background: var(--color-toast-bg);
  color: var(--color-surface);
  font-size: var(--fs-13);
  font-weight: 500;
  box-shadow: var(--shadow-toast);
  z-index: 70;
  max-width: calc(100vw - 32px);
}

#toast .toast-action {
  border: none;
  background: transparent;
  color: var(--color-toast-link);
  font-size: var(--fs-13);
  font-weight: 600;
  cursor: pointer;
  padding: 0;
  flex: none;
}

/* ==========================================================================
   Import screen
   ========================================================================== */

#screen-import {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.import-topbar {
  height: 64px;
  flex: none;
  padding: 0 var(--space-13);
  border-bottom: 1px solid var(--color-border);
  display: flex;
  align-items: center;
  gap: var(--space-6);
}

.import-topbar h2 {
  margin: 0;
  font-size: var(--fs-17);
  font-weight: 600;
  color: var(--color-text);
}

.import-topbar .import-subtitle {
  font-size: var(--fs-13);
  color: var(--color-text-placeholder);
}

.import-body {
  flex: 1;
  overflow: auto;
  padding: var(--space-13) var(--space-13) var(--space-15);
  display: flex;
  justify-content: center;
}

.import-content {
  width: 880px;
  max-width: 100%;
  display: flex;
  flex-direction: column;
  gap: var(--space-11);
}

.import-steps {
  display: flex;
  gap: var(--space-5);
}

.import-step {
  flex: 1;
  padding: 10px 14px;
  border-radius: var(--radius-input);
  font-size: var(--fs-13);
  font-weight: 500;
  background: var(--color-surface-subtle);
  color: var(--color-text-placeholder);
  border: 1px solid #EAECF0;
  text-align: center;
}
.import-step.active {
  background: var(--color-accent-tint-bg);
  color: var(--color-accent-hover);
  font-weight: 600;
  border-color: var(--color-accent-tint-border);
}
.import-step.done { color: var(--color-success-text); }

.import-dropzone {
  border: 2px dashed #CDD5E0;
  border-radius: var(--radius-bubble);
  background: var(--color-surface-subtle);
  padding: 56px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-6);
  text-align: center;
  transition: border-color .12s ease, background .12s ease;
}
.import-dropzone.dragover {
  border-color: var(--color-accent);
  background: var(--color-accent-tint-bg);
}

.import-dropzone-icon {
  width: 48px; height: 48px; border-radius: var(--radius-card);
  background: var(--color-accent-tint-bg); color: var(--color-accent);
  display: grid; place-items: center; font-size: var(--fs-20); font-weight: 700;
}

.import-dropzone h3 { margin: 0; font-size: var(--fs-16); font-weight: 600; color: var(--color-text); }
.import-dropzone p { margin: 0; font-size: var(--fs-14); color: var(--color-text-muted); }

.import-file-card {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  padding: var(--space-7) var(--space-8);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
  background: var(--color-surface);
}

.import-file-check {
  width: 36px; height: 36px; border-radius: var(--radius-tab);
  background: var(--color-success-tint-bg); color: var(--color-success-text);
  display: grid; place-items: center; font-size: var(--fs-15); font-weight: 700; flex: none;
}

.import-file-meta { flex: 1; min-width: 0; }
.import-file-meta .filename {
  font-size: var(--fs-14); font-weight: 600; color: var(--color-text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.import-file-meta .rowcount { font-size: var(--fs-13); color: var(--color-text-muted); }

.import-mapping {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-8);
}

.import-mapping select {
  height: 44px;
  padding: 0 var(--space-6);
  border-radius: var(--radius-input);
  border: 1px solid var(--color-input-border);
  background: var(--color-surface);
  font-size: var(--fs-14);
  color: var(--color-text);
}

.import-table-wrap {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
  overflow: auto;
}

.import-table {
  border-collapse: collapse;
  width: 100%;
  font-size: var(--fs-13);
}

.import-table thead th {
  padding: 10px 14px;
  font-size: var(--fs-12);
  font-weight: 600;
  color: var(--color-text-secondary);
  background: var(--color-surface-subtle);
  border-bottom: 1px solid var(--color-border);
  text-align: left;
  white-space: nowrap;
}
.import-table thead th.mapped { color: var(--color-accent); }
.import-table thead th .col-tag { color: var(--color-accent); font-weight: 600; }

.import-table tbody td {
  padding: 11px 14px;
  color: var(--color-text);
  border-bottom: 1px solid var(--color-border-subtle);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 220px;
}
.import-table tbody tr.invalid { background: #FFFBFA; }
.import-table tbody tr.invalid td.phone-cell { color: var(--color-danger-text); font-weight: 500; }

.import-table-footer {
  padding: 10px 14px;
  background: var(--color-surface-subtle);
  border-top: 1px solid var(--color-border);
  font-size: var(--fs-12);
  color: var(--color-text-muted);
}

.import-summary {
  display: flex;
  align-items: center;
  gap: var(--space-10);
  padding: var(--space-9) var(--space-10);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
  background: var(--color-surface-subtle);
  flex-wrap: wrap;
}

.import-summary-stat { display: flex; flex-direction: column; gap: 2px; }
.import-summary-stat .n { font-size: var(--fs-22); font-weight: 700; }
.import-summary-stat .label { font-size: var(--fs-13); color: var(--color-text-muted); }
.import-summary-stat.new .n { color: var(--color-success-text); }
.import-summary-stat.updated .n { color: var(--color-accent); }
.import-summary-stat.merged .n { color: var(--color-accent); }
.import-summary-stat.foreign .n { color: var(--color-warning-text); }
.import-summary-stat.invalid .n { color: var(--color-warning-text); }
.import-summary-stat.unchanged .n { color: var(--color-text-muted); }

.import-summary-divider { width: 1px; height: 36px; background: var(--color-border); }
.import-summary-spacer { flex: 1; }

.import-footnote { margin: 0; font-size: var(--fs-13); color: var(--color-text-muted); }

/* Per-file breakdown under the file card (multi-file import). */
.import-file-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  font-size: var(--fs-13);
  color: var(--color-text-muted);
}
.import-file-list li {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-2) var(--space-3);
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius-xs);
}
.import-file-list .import-file-list-name { flex: 1; color: var(--color-text); font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.import-file-list .import-file-list-warning { color: var(--color-warning-text); font-weight: 600; }

/* "Sammanslagna dubbletter" review list. */
.import-duplicates {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
  padding: var(--space-7) var(--space-8);
  background: var(--color-surface);
}
.import-duplicates h4 { margin: 0 0 var(--space-4); font-size: var(--fs-14); font-weight: 600; color: var(--color-text); }
.import-duplicates-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: var(--space-3); font-size: var(--fs-13); }
.import-duplicates-list li { color: var(--color-text-muted); }
.import-duplicates-list .kept-name { color: var(--color-text); font-weight: 600; }

.import-done-summary { margin-top: var(--space-2); }

.import-done-card {
  border: 1px solid var(--color-success-border);
  background: var(--color-success-surface);
  border-radius: var(--radius-bubble);
  padding: 40px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-5);
  text-align: center;
}
.import-done-check {
  width: 48px; height: 48px; border-radius: 50%;
  background: var(--color-success-tint-bg); color: var(--color-success-text);
  display: grid; place-items: center; font-size: var(--fs-22); font-weight: 700;
}
.import-done-card h3 { margin: 0; font-size: var(--fs-17); font-weight: 600; color: var(--color-text); }
.import-done-card p { margin: 0; font-size: var(--fs-14); color: var(--color-text-muted); }

.import-error {
  font-size: var(--fs-13);
  color: var(--color-danger-text);
  margin: 0;
}

/* ==========================================================================
   Mobile layout (single breakpoint, DESIGN_NOTES.md §1)
   ========================================================================== */

@media (max-width: 859px) {
  .topbar { display: none; }

  /* v2: the hero is no longer hidden on the phone — it is the dark top of
     the page, with the form sheet rounded over it. */
  .login-screen {
    display: flex;
    flex-direction: column;
    padding: 0;
    gap: 0;
  }
  .login-hero {
    order: 1;
    flex: none;
    justify-content: flex-start;
    gap: var(--space-10);
    padding: var(--space-12) 22px var(--space-13);
  }
  .login-hero::before {
    left: auto; right: -90px; top: -90px; bottom: auto;
    width: 260px; height: 260px; opacity: .25;
  }
  .login-hero::after { display: none; }
  .login-hero-kicker { font-size: var(--fs-10); letter-spacing: .16em; }
  .login-hero-fun { gap: var(--space-10); }
  .login-hero-fun-title { font-size: 112px; }
  .login-hero-fun-title::after { display: none; }
  .login-hero-fun-row { padding: var(--space-3) 0; }
  .login-hero-fun-row dt { font-size: var(--fs-11); }
  .login-hero-fun-row dd { font-size: var(--fs-15); }

  .login-form-col {
    order: 2;
    flex: 1;
    max-width: none;
    margin: 0;
    padding: 26px 22px var(--space-14);
    gap: var(--space-9);
    justify-content: flex-start;
    border-radius: var(--radius-login-card) var(--radius-login-card) 0 0;
    box-shadow: none;
  }
  .login-form-col .brand-mark { gap: var(--space-4); }
  .login-form-col .brand-wordmark span { display: none; }
  .login-heading h1 { font-size: 23px; letter-spacing: -.02em; }
  .login-fields { gap: var(--space-9); }
  .login-fields .input { height: 50px; font-size: var(--fs-16); }
  .login-fields button[type="submit"] { height: 54px; font-size: var(--fs-16); }

  .inbox-body { flex-direction: column; }

  .pane-list {
    width: 100%;
    border-right: none;
    position: absolute;
    inset: 0;
    z-index: 1;
  }
  .pane-thread {
    position: absolute;
    inset: 0;
    z-index: 2;
  }
  #app.mobile-pane-list .pane-thread { display: none; }
  #app.mobile-pane-chat .pane-list { display: none; }

  .list-header-mobile {
    display: flex;
    align-items: center;
    gap: var(--space-4);
    padding: var(--space-2) var(--space-6) 0;
  }
  .list-header-mobile .mobile-title {
    font-size: var(--fs-20);
    font-weight: 700;
    letter-spacing: -.02em;
    color: var(--color-text);
  }
  .list-header-mobile .spacer { flex: 1; }
  .list-header-mobile .btn-icon-outline {
    width: 44px; height: 44px; border-radius: var(--radius-input);
  }
  .list-header-mobile .user-chip-avatar {
    width: 44px; height: 44px; border-radius: 50%; font-size: var(--fs-14);
  }

  .list-toolbar { padding: var(--space-5) var(--space-6) var(--space-5); }
  #search-input { height: 44px; font-size: var(--fs-15); }
  .filter-tabs { border-radius: var(--radius-input); }
  .filter-tab { height: 38px; font-size: var(--fs-14); }
  /* Back to a flex row on the phone: "Nytt SMS" has moved into the
     floating button, so there is nothing to place in a grid. */
  .search-row { display: flex; }
  .search-row #btn-new-sms { display: none; }
  .search-row .search-wrap { flex: 1; }

  .conv-row { min-height: 72px; padding: 12px 14px; padding-left: 11px; }

  .fab-new-sms {
    display: inline-flex;
    align-items: center;
    gap: var(--space-3);
    position: absolute;
    right: 18px;
    bottom: 26px;
    height: 56px;
    padding: 0 22px;
    border-radius: 28px;
    border: none;
    background: var(--color-accent);
    color: var(--color-surface);
    font-size: var(--fs-15);
    font-weight: 600;
    box-shadow: var(--shadow-fab);
    z-index: 3;
  }
  .fab-new-sms:hover { background: var(--color-accent-hover); }

  .thread-empty { display: none; }

  .thread-header { height: 56px; padding: 0 var(--space-4) 0 var(--space-2); gap: var(--space-3); }
  /* v2's mobile chat header is name + number only. The group chips wrap
     onto their own lines on a 375px screen and pushed the name out of the
     56px bar; they are one tap away in the contact panel. The foreign-number
     badge stays — it is a warning, not decoration. */
  .thread-header #thread-groups { display: none; }
  #btn-back {
    display: inline-flex;
    width: 44px; height: 44px;
    color: var(--color-accent);
    font-size: var(--fs-20);
  }
  /* The name is not editable in place on a phone (the ✎ button opens the
     rename sheet instead), but it is still the header's title — v1 hid the
     whole button, which took the name with it and left the chat header
     showing nothing but the number. */
  .thread-name-btn {
    cursor: default;
    pointer-events: none;
    height: auto;
    width: auto;
    margin: 0;
    padding: 0;
    background: transparent;
    border: none;
  }
  .thread-name-btn .name-text { font-size: var(--fs-15); }
  .thread-name-btn .pencil { display: none; }
  #btn-archive, #btn-delete-trigger {
    width: 44px; height: 44px; padding: 0; border: none;
    background: transparent; font-size: var(--fs-16); justify-content: center;
  }
  #btn-archive:hover, #btn-delete-trigger:hover { background: var(--color-track); }
  #btn-archive .label-text, #btn-delete-trigger .label-text { display: none; }
  #btn-archive .icon-glyph, #btn-delete-trigger .icon-glyph { display: inline; }
  #btn-rename-mobile { display: inline-flex; width: 44px; height: 44px; font-size: var(--fs-16); }

  .messages { padding: var(--space-8) var(--space-7) var(--space-4); }
  .bubble { max-width: 286px; }
  #compose-text { font-size: var(--fs-16); min-height: 36px; rows: 1; }
  .compose { padding: var(--space-5) var(--space-6) var(--space-7); }
  .compose-box { border-radius: var(--radius-bubble); padding: 8px 10px; }
  .compose-helper { display: none; }
  #compose-send { height: 44px; padding: 0 22px; font-size: var(--fs-15); }

  .mock-panel { padding: var(--space-4) var(--space-6); }

  /* New SMS: full-screen page instead of centered modal */
  #modal-new-sms.modal-backdrop {
    background: transparent;
    align-items: stretch;
    padding-top: 0;
  }
  #modal-new-sms .modal {
    width: 100%;
    max-width: none;
    height: 100%;
    max-height: none;
    border-radius: 0;
    box-shadow: none;
  }
  #modal-new-sms .modal-header { padding: 0; border-bottom: none; gap: 0; }
  #modal-new-sms .modal-header-row {
    height: 56px; padding: 0 8px 0 4px;
    border-bottom: 1px solid var(--color-border);
  }
  #modal-new-sms .modal-header-row h3 { font-size: var(--fs-16); margin-left: var(--space-3); }
  #modal-new-sms .modal-close { display: none; }
  #modal-new-sms .modal-back {
    display: inline-flex;
    width: 44px; height: 44px;
    color: var(--color-accent);
    font-size: var(--fs-20);
    border-radius: var(--radius-input);
  }
  #modal-new-sms #new-sms-search { margin: var(--space-6) var(--space-7) 0; height: 48px; font-size: var(--fs-16); }
  #modal-new-sms .modal-list { flex: 1; max-height: none; margin-top: var(--space-6); }

  /* Rename: bottom sheet instead of centered modal */
  #modal-rename.modal-backdrop {
    align-items: flex-end;
    padding-top: 0;
    background: rgba(16, 24, 40, .42);
  }
  #modal-rename .modal {
    width: 100%;
    border-radius: var(--radius-sheet) var(--radius-sheet) 0 0;
    animation: sheetIn .18s ease-out;
    padding: 20px 16px 24px;
  }
  #modal-rename #rename-input { height: 48px; font-size: var(--fs-16); }
  #modal-rename .modal-actions button { flex: 1; height: 48px; }

  #modal-delete.modal-backdrop { align-items: flex-end; padding-top: 0; }
  #modal-delete .modal {
    width: 100%;
    border-radius: var(--radius-sheet) var(--radius-sheet) 0 0;
    animation: sheetIn .18s ease-out;
  }
  #modal-delete .modal-actions button { flex: 1; height: 48px; }

  /* Foreign-number send confirm: bottom sheet, same treatment as Radera. */
  #modal-foreign-confirm.modal-backdrop { align-items: flex-end; padding-top: 0; }
  #modal-foreign-confirm .modal {
    width: 100%;
    border-radius: var(--radius-sheet) var(--radius-sheet) 0 0;
    animation: sheetIn .18s ease-out;
  }
  #modal-foreign-confirm .modal-actions button { flex: 1; height: 48px; }

  /* Templates popover + manage dialog: bottom sheets on mobile, same
     treatment as the rename dialog. */
  #modal-templates.modal-backdrop,
  #modal-manage-templates.modal-backdrop {
    align-items: flex-end;
    padding-top: 0;
  }
  #modal-templates .modal,
  #modal-manage-templates .modal {
    width: 100%;
    max-height: calc(100vh - 56px);
    border-radius: var(--radius-sheet) var(--radius-sheet) 0 0;
    animation: sheetIn .18s ease-out;
  }
  #modal-templates .modal-templates,
  #modal-manage-templates .modal-manage-templates { width: 100%; }
  #template-form-save, #template-form-cancel { flex: 1; height: 48px; }

  /* Templates: bring controls up to the 44px minimum touch target used by
     the other icon buttons (rename/archive/delete, sound toggle). */
  #btn-templates { min-height: 44px; }
  #templates-popover-close { width: 44px; height: 44px; }
  .templates-popover-footer #btn-manage-templates {
    display: inline-flex; align-items: center; justify-content: center;
    min-height: 44px; min-width: 44px; padding: 0 var(--space-5);
  }
  #btn-add-template { min-height: 44px; }

  /* Account menu: bottom sheet on mobile, same treatment as the other
     dialogs (the trigger is the avatar in the list header). */
  .menu-backdrop { background: rgba(16, 24, 40, .42); display: flex; align-items: flex-end; }
  .user-menu {
    position: static;
    width: 100%;
    padding: var(--space-5) var(--space-5) var(--space-9);
    border: none;
    /* v2: the account menu and the sound sheet are a touch rounder than
       the rest (DESIGN_NOTES_V2.md §2, "Radii"). */
    border-radius: var(--radius-sheet-lg) var(--radius-sheet-lg) 0 0;
    animation: sheetIn .18s ease-out;
  }
  .user-menu-item { min-height: 48px; display: flex; align-items: center; font-size: var(--fs-15); }
  .user-menu-theme { padding: var(--space-3) var(--space-5) var(--space-5); }
  .theme-segment { height: 44px; font-size: var(--fs-14); }

  /* "Ljud och notiser": bottom sheet like the other dialogs, with
     finger-sized controls (the switch, the slider thumb and every
     "Provlyssna" button). */
  #modal-sound.modal-backdrop { align-items: flex-end; padding-top: 0; }
  #modal-sound .modal {
    width: 100%;
    max-height: calc(100vh - 56px);
    overflow-y: auto;
    border-radius: var(--radius-sheet-lg) var(--radius-sheet-lg) 0 0;
    animation: sheetIn .18s ease-out;
  }
  #modal-sound .modal-sound { width: 100%; }
  #modal-sound .sound-switch-row { min-height: 44px; }
  #modal-sound .sound-volume-row input[type="range"] { min-height: 44px; }
  #modal-sound .sound-tone-row { min-height: 52px; }
  #modal-sound .theme-radio-row { min-height: 52px; }
  /* The row is narrow on a phone, so let the one-line description wrap
     instead of ending in an ellipsis. */
  #modal-sound .sound-tone-label .hint { white-space: normal; overflow: visible; }
  #modal-sound .sound-preview { min-height: 44px; min-width: 44px; }
  #modal-sound .modal-actions button { flex: 1; height: 48px; }
  #sound-close { width: 44px; height: 44px; }

  /* Change password + Användare: bottom sheets, like Mallar/Radera. */
  #modal-change-password.modal-backdrop,
  #modal-users.modal-backdrop { align-items: flex-end; padding-top: 0; }
  #modal-change-password .modal,
  #modal-users .modal {
    width: 100%;
    max-height: calc(100vh - 56px);
    border-radius: var(--radius-sheet) var(--radius-sheet) 0 0;
    animation: sheetIn .18s ease-out;
  }
  #modal-change-password .input { height: 48px; font-size: var(--fs-16); }
  #modal-change-password .modal-actions button { flex: 1; height: 48px; }
  #modal-users .modal-users { width: 100%; }
  #users-close { width: 44px; height: 44px; }
  #btn-new-user, #user-form-save, #user-form-cancel,
  #users-password-done, #users-copy-password { min-height: 48px; }
  .users-form .modal-actions button { flex: 1; }
  .user-row .actions button { min-height: 40px; }

  #toast { left: 12px; right: 12px; bottom: 96px; transform: none; max-width: none; }

  .import-topbar { height: 52px; padding: 0 var(--space-4) 0 var(--space-2); gap: var(--space-2); }
  .import-topbar .import-subtitle { display: none; }
  .import-topbar h2 { font-size: var(--fs-16); }
  #btn-import-back-desktop { display: none; }
  #btn-import-back-mobile { display: inline-flex; width: 44px; height: 44px; font-size: var(--fs-20); }
  .import-body { padding: var(--space-8) var(--space-6) var(--space-12); }
  .import-steps { display: none; }
  .import-dropzone { padding: 32px 20px; }
  .import-mapping { grid-template-columns: 1fr; gap: var(--space-7); }
  .import-summary { flex-direction: column; align-items: stretch; gap: var(--space-4); padding: var(--space-7) var(--space-8); }
  .import-summary-divider { display: none; }
  .import-summary-spacer { display: none; }
  .import-summary button { height: 48px; }
  .import-table td:nth-child(n+3), .import-table th:nth-child(n+3) { display: none; }
}

@media (min-width: 860px) {
  #btn-import-back-mobile { display: none; }
}

/* ==========================================================================
   Group chips ("Grupper") — conversation rows, thread header, contacts table
   ========================================================================== */

.chip-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
}

.chip-row-inline { display: inline-flex; }

/* Sized by its content, never by a fixed box: the old `line-height: 18px`
   plus a 160px cap chopped the tail off a real company name ("Hotellet vid
   Lilla Apelviken AB") and clipped the descenders of j/g/p. The height now
   comes from the line box (1.45 × 11px) plus padding, and the cap is wide
   enough for the longest real group name — an ellipsis only appears when a
   name is genuinely longer than that, and the full name is always on the
   `title` attribute (see renderGroupChips in public/app.js).

   `overflow: hidden` stays, because the removable chips rely on it (their
   44px mobile remove button has to be inside the pill — see
   tests/mobileTouchTargets.test.js). Text-overflow on a flex container does
   not reach its anonymous text item, so the label is its own
   `.chip-label` span, which is where the ellipsis actually happens. */
.chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  max-width: min(100%, 34ch);
  padding: 2px var(--space-4);
  border-radius: var(--radius-pill);
  border: 1px solid var(--color-accent-tint-border);
  background: var(--color-accent-tint-bg);
  color: var(--color-accent-hover);
  font-size: var(--fs-11);
  font-weight: 600;
  line-height: 1.45;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.chip-more {
  background: var(--color-track);
  border-color: var(--color-border);
  color: var(--color-text-muted);
}

.chip-empty { font-size: var(--fs-13); color: var(--color-text-placeholder); }

.chip-removable { padding-right: var(--space-2); }

.chip-remove {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: inherit;
  font-size: var(--fs-11);
  cursor: pointer;
}
.chip-remove:hover { background: var(--color-accent-tint-border); }

.conv-groups { margin-top: var(--space-1); }
.conv-groups:empty { display: none; }

/* The inbox group filter, under the Alla/Olästa/Arkiverade tabs. */
.group-filter {
  height: 38px;
  padding: 0 var(--space-5);
  font-size: var(--fs-13);
  color: var(--color-text-secondary);
}

/* ==========================================================================
   Kontakter page
   ========================================================================== */

#screen-contacts {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.contacts-body {
  flex: 1;
  min-height: 0;
  display: flex;
  gap: var(--space-12);
  padding: var(--space-12) var(--space-13);
  overflow: hidden;
}

.contacts-main {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-7);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
  padding: var(--space-8);
  overflow: hidden;
}

.contacts-toolbar {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  flex: none;
}
.contacts-toolbar .search-wrap { flex: 1; min-width: 160px; }
.contacts-toolbar .search-wrap input {
  width: 100%;
  height: 38px;
  padding: 0 14px 0 32px;
  border-radius: var(--radius-input);
  border: 1px solid var(--color-input-border);
  background: var(--color-surface);
  font-size: var(--fs-14);
}
.contacts-toolbar .search-wrap input:focus { border-color: var(--color-accent); box-shadow: var(--shadow-focus); }
.contacts-toolbar select { height: 38px; font-size: var(--fs-13); padding: 0 var(--space-5); flex: none; max-width: 240px; }

.contacts-table-wrap {
  flex: 1;
  min-height: 0;
  overflow: auto;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
}

.contacts-table {
  width: 100%;
  border-collapse: collapse;
  font-size: var(--fs-14);
}

.contacts-table thead th {
  position: sticky;
  top: 0;
  z-index: 1;
  text-align: left;
  padding: var(--space-5) var(--space-7);
  background: var(--color-surface-subtle);
  border-bottom: 1px solid var(--color-border);
  font-size: var(--fs-12);
  font-weight: 600;
  color: var(--color-text-muted);
  white-space: nowrap;
}

.contacts-sort {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
}
.contacts-sort:hover { color: var(--color-accent); }

.contacts-table tbody td {
  padding: var(--space-5) var(--space-7);
  border-bottom: 1px solid var(--color-border-subtle);
  vertical-align: middle;
}

.contact-row { cursor: pointer; }
.contact-row:hover { background: #F7F9FC; }
.contact-row:focus-visible { outline: 2px solid var(--color-accent); outline-offset: -2px; }

.contact-name-cell { display: flex; align-items: center; gap: var(--space-5); }
.contact-name-cell .conv-avatar { width: 32px; height: 32px; font-size: var(--fs-12); }
.contact-name { font-weight: 600; color: var(--color-text); }
.contact-phone-cell { color: var(--color-text-secondary); white-space: nowrap; }

.contacts-footer {
  flex: none;
  display: flex;
  align-items: center;
  gap: var(--space-6);
}
.contacts-shown { font-size: var(--fs-13); color: var(--color-text-muted); }

.contacts-groups {
  width: 320px;
  flex: none;
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
  padding: var(--space-8);
  overflow: auto;
}
.contacts-groups h3 { margin: 0; font-size: var(--fs-16); font-weight: 600; color: var(--color-text); }

.groups-list { display: flex; flex-direction: column; gap: var(--space-3); }

.group-row {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  padding: var(--space-5) var(--space-6);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-input);
}
.group-row .info { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.group-row .info strong {
  font-size: var(--fs-14); font-weight: 600; color: var(--color-text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.group-row .info .meta { font-size: var(--fs-12); color: var(--color-text-muted); }
.group-row .actions { display: flex; gap: var(--space-3); flex: none; }
.group-row .actions button {
  height: 32px;
  padding: 0 var(--space-5);
  border-radius: var(--radius-xs);
  border: 1px solid var(--color-border);
  background: var(--color-surface);
  font-size: var(--fs-12);
  font-weight: 500;
  color: var(--color-text-secondary);
  cursor: pointer;
}
.group-row .actions button:hover { background: var(--color-surface-subtle); }
.group-row .actions .danger { color: var(--color-danger-text); border-color: var(--color-danger-border); }
.group-row .actions .danger:hover { background: var(--color-danger-tint-bg); }
.group-rename-input { height: 36px; font-size: var(--fs-14); width: 100%; }

.groups-new { display: flex; gap: var(--space-4); }
.groups-new .input { flex: 1; height: 38px; font-size: var(--fs-14); min-width: 0; }
.groups-new button { flex: none; }

/* ==========================================================================
   Contact panel (bottom sheet on mobile)
   ========================================================================== */

.modal-contact { width: 520px; }

.contact-panel-body {
  display: flex;
  flex-direction: column;
  gap: var(--space-7);
  padding: var(--space-8) 20px var(--space-4);
  max-height: 60vh;
  overflow: auto;
}

.contact-group-add { display: flex; gap: var(--space-4); }
.contact-group-add select { flex: 1; height: 38px; font-size: var(--fs-14); min-width: 0; }
.contact-group-add button { flex: none; }

.contact-panel-actions { align-items: center; flex-wrap: wrap; }
.contact-panel-spacer { flex: 1; }
.contact-panel-link { margin: 0; }

/* The employee number is read-only, so v2 draws it as a card rather than
   as a disabled form field. */
.contact-empno-card {
  flex-direction: row;
  align-items: center;
  gap: var(--space-6);
  padding: var(--space-6) var(--space-7);
  border-radius: var(--radius-card);
  border: 1px solid #EAECF0;
  background: var(--color-surface-subtle);
}
.contact-empno-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.contact-empno-label { font-size: var(--fs-12); font-weight: 600; color: var(--color-text-muted); }

#contact-empno-input {
  height: auto;
  padding: 0;
  border: none;
  background: transparent;
  font-size: var(--fs-15);
  font-weight: 600;
  color: var(--color-text);
  font-variant-numeric: tabular-nums;
}

.contact-empno-pill {
  flex: none;
  padding: var(--space-2) var(--space-5);
  border-radius: var(--radius-pill);
  background: var(--color-surface);
  border: 1px solid var(--color-border);
  font-size: var(--fs-12);
  font-weight: 500;
  color: var(--color-text-muted);
  white-space: nowrap;
}

/* ==========================================================================
   Import: company (group) per file
   ========================================================================== */

.import-companies {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
  padding: var(--space-8);
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  background: var(--color-surface-subtle);
}
.import-companies h4 { margin: 0; font-size: var(--fs-14); font-weight: 600; color: var(--color-text); }

.import-companies-list { display: flex; flex-direction: column; gap: var(--space-5); }

.import-company-row {
  display: flex;
  align-items: center;
  gap: var(--space-6);
}
.import-company-row .input { flex: 1; height: 40px; font-size: var(--fs-14); min-width: 0; }
.import-company-meta { width: 260px; flex: none; display: flex; flex-direction: column; gap: 2px; }
.import-company-label { font-size: var(--fs-13); font-weight: 600; color: var(--color-text); }
.import-company-file {
  font-size: var(--fs-12); color: var(--color-text-muted);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

.import-summary-stat.groups .n { color: var(--color-accent); }

/* ==========================================================================
   Mobile (<= 859px) for everything above
   ========================================================================== */

@media (max-width: 859px) {
  .group-filter { height: 44px; font-size: var(--fs-14); }

  /* Kontakter: full-screen page with a back button, like the import page. */
  #btn-contacts-back-desktop { display: none; }
  #btn-contacts-back-mobile { display: inline-flex; width: 44px; height: 44px; font-size: var(--fs-20); }
  #screen-contacts .import-topbar { height: 52px; padding: 0 var(--space-4) 0 var(--space-2); gap: var(--space-2); }
  #screen-contacts .import-topbar h2 { font-size: var(--fs-16); }
  #screen-contacts .import-subtitle { display: none; }

  .contacts-body {
    flex-direction: column;
    gap: var(--space-8);
    padding: var(--space-6);
    overflow: auto;
  }
  .contacts-main, .contacts-groups {
    width: 100%;
    flex: none;
    padding: var(--space-6);
    overflow: visible;
  }
  .contacts-toolbar { flex-wrap: wrap; }
  .contacts-toolbar .search-wrap { flex: 1 1 100%; }
  .contacts-toolbar .search-wrap input { height: 44px; font-size: var(--fs-15); }
  .contacts-toolbar select { height: 44px; flex: 1; max-width: none; }
  .contacts-toolbar #btn-new-contact { height: 44px; flex: none; }
  .contacts-table-wrap { max-height: none; overflow: visible; }
  /* The "Namn" sort toggle is a real touch target (44x44). The header cell
     gives up most of its own vertical padding so the row does not grow
     taller than the button needs. */
  .contacts-table thead th { padding-top: var(--space-2); padding-bottom: var(--space-2); }
  .contacts-sort {
    display: inline-flex;
    align-items: center;
    gap: var(--space-2);
    min-height: 44px;
    min-width: 44px;
  }
  .contacts-table tbody td { padding: var(--space-6) var(--space-5); }
  .contact-row { min-height: 56px; }
  .contacts-table .col-groups { display: none; }
  .contacts-footer #contacts-more { min-height: 44px; }
  .group-row { min-height: 56px; }
  .group-row .actions button { min-height: 44px; }
  .groups-new .input { height: 44px; }
  .groups-new button { min-height: 44px; }

  /* Contact panel: bottom sheet, same treatment as Radera/Mallar. */
  #modal-contact.modal-backdrop { align-items: flex-end; padding-top: 0; }
  #modal-contact .modal {
    width: 100%;
    max-width: none;
    max-height: calc(100vh - 56px);
    border-radius: var(--radius-sheet) var(--radius-sheet) 0 0;
    animation: sheetIn .18s ease-out;
  }
  #modal-contact .modal-contact { width: 100%; }
  #modal-contact .input { height: 48px; font-size: var(--fs-16); }
  #modal-contact .contact-panel-body { max-height: calc(100vh - 220px); }
  #modal-contact .contact-group-add select { height: 48px; }
  #modal-contact .contact-group-add button,
  #modal-contact .contact-panel-actions button { min-height: 48px; }
  /* A finger-sized remove button. An invisible overlay around a small "✕"
     would not work here: `.chip` sets `overflow: hidden` (that is what keeps
     a long group name inside the pill), so anything sticking out of the chip
     is clipped away. The button itself is therefore the 44x44 target and the
     chip grows to fit it — it gives up its own right padding and its 160px
     desktop cap in exchange, so the group name keeps its room. */
  #modal-contact .chip-removable {
    max-width: 100%;
    min-height: 44px;
    padding: 0 0 0 var(--space-6);
  }
  #modal-contact .chip-remove { width: 44px; height: 44px; font-size: var(--fs-13); }
  #contact-panel-close { width: 44px; height: 44px; }

  .import-company-row { flex-direction: column; align-items: stretch; gap: var(--space-3); }
  .import-company-meta { width: auto; }
  .import-company-row .input { height: 48px; font-size: var(--fs-16); }
}

@media (min-width: 860px) {
  /* Same as #btn-import-back-mobile: the arrow-only back button belongs to
     the mobile layout, the "← Till inboxen" button to the desktop one. */
  #btn-contacts-back-mobile { display: none; }
}

/* ==========================================================================
   "Skicka till flera" — the multi-recipient send dialog (three steps plus
   a progress view) and the read-only "Utskick" list.
   docs/WISHLIST.md #7.
   ========================================================================== */

#btn-multi-sms {
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
}

.modal-multi { width: 560px; }

/* The step rail under the dialog title. */
.multi-steps {
  display: flex;
  gap: var(--space-5);
  flex-wrap: wrap;
}

.multi-step {
  font-size: var(--fs-12);
  font-weight: 600;
  color: var(--color-text-placeholder);
}
.multi-step.done { color: var(--color-success-text); }
.multi-step.active { color: var(--color-accent); }

/* Each step's body scrolls on its own, so the header and the action row
   stay put however many recipient chips there are. */
.multi-body {
  padding: var(--space-8) var(--space-10);
  display: flex;
  flex-direction: column;
  gap: var(--space-9);
  overflow-y: auto;
  min-height: 0;
}
.multi-body.hidden { display: none; }

.multi-section {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

.multi-section h4 {
  margin: 0;
  font-size: var(--fs-12);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--color-text-muted);
}

.multi-hint {
  margin: 0;
  font-size: var(--fs-13);
  color: var(--color-text-placeholder);
}

/* --- group picker --- */

.multi-group-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
}

.multi-group-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--space-4);
  max-width: 100%;
  min-height: 32px;
  padding: var(--space-3) var(--space-6);
  border-radius: var(--radius-pill);
  border: 1px solid var(--color-input-border);
  background: var(--color-surface);
  color: var(--color-text-secondary);
  font-size: var(--fs-13);
  font-weight: 500;
  cursor: pointer;
}
.multi-group-chip:hover { background: var(--color-surface-subtle); }
.multi-group-chip .name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.multi-group-chip .count {
  padding: 0 var(--space-4);
  border-radius: var(--radius-pill);
  background: var(--color-track);
  color: var(--color-text-muted);
  font-size: var(--fs-11);
  font-weight: 600;
}
.multi-group-chip.picked {
  border-color: var(--color-accent);
  background: var(--color-accent-tint-bg);
  color: var(--color-accent-hover);
}
.multi-group-chip.picked .count {
  background: var(--color-accent-tint-border);
  color: var(--color-accent-hover);
}

/* --- contact search results --- */

.multi-results {
  max-height: 190px;
  overflow-y: auto;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-input);
}
.multi-results .multi-hint { padding: var(--space-6) var(--space-7); }

.multi-result {
  display: flex;
  align-items: center;
  gap: var(--space-6);
  width: 100%;
  padding: var(--space-5) var(--space-7);
  border: none;
  border-bottom: 1px solid var(--color-border-subtle);
  background: transparent;
  text-align: left;
  cursor: pointer;
}
.multi-result:last-child { border-bottom: none; }
.multi-result:hover { background: var(--color-surface-subtle); }
.multi-result.picked { background: var(--color-accent-tint-bg); }

.multi-result .conv-avatar { width: 32px; height: 32px; }

.multi-result-text {
  display: flex;
  flex-direction: column;
  min-width: 0;
  flex: 1;
}
.multi-result-text strong {
  font-size: var(--fs-14);
  font-weight: 500;
  color: var(--color-text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.multi-result-text span { font-size: var(--fs-12); color: var(--color-text-muted); }

.multi-result-mark {
  font-size: var(--fs-15);
  font-weight: 700;
  color: var(--color-accent);
}

/* --- free-typed numbers --- */

textarea.multi-numbers {
  height: auto;
  min-height: 64px;
  padding: var(--space-5) var(--space-6);
  font-size: var(--fs-14);
  line-height: 1.45;
  resize: vertical;
}
#multi-numbers-add { align-self: flex-start; }

/* --- the chosen recipients --- */

.multi-recipients {
  max-height: 160px;
  overflow-y: auto;
  padding: var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-input);
  background: var(--color-surface-subtle);
  align-content: flex-start;
}

/* The label inside a chip. `min-width: 0` lets it actually shrink inside the
   flex pill (a flex item's default min-width: auto would otherwise push the
   chip wider than its max-width and the text would be cut without an
   ellipsis), and the three properties below are what draw the "…". */
.chip-label {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* A foreign recipient is marked in the chip list too, so the "(varav N
   utländska)" counter can be matched to actual people at a glance. */
.chip-foreign {
  border-color: var(--color-danger-border);
  background: var(--color-danger-tint-bg);
  color: var(--color-danger-text);
}

.multi-count {
  margin: 0;
  font-size: var(--fs-13);
  font-weight: 600;
  color: var(--color-text-secondary);
}

/* --- step 2: the message --- */

.multi-textarea {
  width: 100%;
  min-height: 130px;
  padding: var(--space-6) var(--space-7);
  border-radius: var(--radius-input);
  border: 1px solid var(--color-input-border);
  background: var(--color-surface);
  font-family: inherit;
  font-size: var(--fs-15);
  line-height: 1.5;
  color: var(--color-text);
  resize: vertical;
}
.multi-textarea:focus { outline: none; border-color: var(--color-accent); box-shadow: var(--shadow-focus); }

.multi-compose-row {
  display: flex;
  align-items: center;
  gap: var(--space-6);
}

.multi-preview {
  padding: var(--space-6) var(--space-7);
  border-radius: var(--radius-card);
  background: var(--color-thread-bg);
  border: 1px solid var(--color-border);
}
.multi-preview-name {
  margin: 0;
  font-size: var(--fs-12);
  font-weight: 600;
  color: var(--color-text-muted);
}
.multi-preview-text {
  margin: 0;
  font-size: var(--fs-14);
  line-height: 1.5;
  color: var(--color-text);
  white-space: pre-wrap;
  word-break: break-word;
}

/* --- step 3: confirm --- */

.multi-confirm-text {
  margin: 0;
  font-size: var(--fs-16);
  font-weight: 600;
  line-height: 1.45;
  color: var(--color-text);
}
.multi-confirm-sub {
  margin: 0;
  font-size: var(--fs-13);
  line-height: 1.5;
  color: var(--color-text-muted);
}
.multi-confirm-sub.hidden { display: none; }

/* --- progress --- */

.multi-progress-bar {
  height: 8px;
  border-radius: var(--radius-pill);
  background: var(--color-track);
  overflow: hidden;
}
.multi-progress-bar span {
  display: block;
  height: 100%;
  width: 0;
  border-radius: var(--radius-pill);
  background: var(--color-accent);
  transition: width .3s ease;
}
.multi-progress-text {
  margin: 0;
  font-size: var(--fs-16);
  font-weight: 600;
  color: var(--color-text);
}

.multi-actions {
  padding: var(--space-6) var(--space-10) var(--space-9);
  border-top: 1px solid var(--color-border);
}
.multi-actions #multi-prev { margin-right: auto; }

/* --- "Utskick" list --- */

.modal-batches { width: 520px; }

.batches-list {
  padding: var(--space-4) var(--space-10) var(--space-10);
  overflow-y: auto;
  max-height: 60vh;
}
.batches-list .multi-hint, .batches-list .error-text { padding: var(--space-9) 0; }

.batch-row {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding: var(--space-6) 0;
  border-bottom: 1px solid var(--color-border-subtle);
}
.batch-row:last-child { border-bottom: none; }

.batch-row-head {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  flex-wrap: wrap;
}
.batch-date { font-size: var(--fs-13); font-weight: 600; color: var(--color-text); }
.batch-by { font-size: var(--fs-13); color: var(--color-text-muted); }

.batch-status {
  margin-left: auto;
  padding: 1px var(--space-5);
  border-radius: var(--radius-pill);
  font-size: var(--fs-11);
  font-weight: 600;
  background: var(--color-track);
  color: var(--color-text-muted);
}
.batch-status.status-done {
  background: var(--color-success-tint-bg);
  color: var(--color-success-text);
}
.batch-status.status-failed {
  background: var(--color-danger-tint-bg);
  color: var(--color-danger-text);
}
.batch-status.status-running {
  background: var(--color-accent-tint-bg);
  color: var(--color-accent-hover);
}

.batch-counts { font-size: var(--fs-12); color: var(--color-text-muted); }
.batch-snippet {
  font-size: var(--fs-13);
  color: var(--color-text-secondary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

@media (max-width: 859px) {
  /* "Skicka till flera" gets its own full-width row under the search
     field: the search row itself only has room for the search box once
     "Nytt SMS" has moved into the floating button. */
  .search-row { flex-wrap: wrap; }
  .search-row #btn-multi-sms {
    flex: 1 1 100%;
    justify-content: center;
    min-height: 44px;
  }

  /* Full-screen page instead of a centred modal, exactly like Nytt SMS. */
  #modal-multi-sms.modal-backdrop {
    background: transparent;
    align-items: stretch;
    padding-top: 0;
  }
  #modal-multi-sms .modal {
    width: 100%;
    max-width: none;
    height: 100%;
    max-height: none;
    border-radius: 0;
    box-shadow: none;
  }
  #modal-multi-sms .modal-header { padding: 0 0 var(--space-5); }
  #modal-multi-sms .modal-header-row {
    height: 56px;
    padding: 0 var(--space-4) 0 var(--space-2);
  }
  #modal-multi-sms .modal-header-row h3 { font-size: var(--fs-16); margin-left: var(--space-3); }
  #modal-multi-sms .modal-close { width: 44px; height: 44px; }
  /* The arrow goes one step back, so it only appears once there is a step
     to go back to — on step 1 the ✕ (and Avbryt) is the way out. app.js
     puts `is-step` on it for steps 2 and 3. */
  #modal-multi-sms .modal-back.is-step {
    display: inline-flex;
    width: 44px; height: 44px;
    color: var(--color-accent);
    font-size: var(--fs-20);
    border-radius: var(--radius-input);
  }
  #modal-multi-sms .multi-steps { padding: 0 var(--space-7); }
  #modal-multi-sms .multi-body { flex: 1; padding: var(--space-7); }
  #modal-multi-sms .input { min-height: 48px; font-size: var(--fs-16); }
  #modal-multi-sms textarea.multi-numbers { min-height: 72px; }
  #modal-multi-sms .multi-textarea { font-size: var(--fs-16); }
  /* Every tappable thing in the dialog is at least 44px tall. */
  #modal-multi-sms .multi-group-chip { min-height: 44px; }
  #modal-multi-sms .multi-result { min-height: 56px; }
  #modal-multi-sms .multi-actions button { flex: 1; min-height: 48px; }
  /* Same reasoning as the contact sheet's remove button: `.chip` clips
     anything sticking out (that is what keeps a long name inside the
     pill), so the button's own box has to be the 44x44 target and the
     chip has to make room for it. */
  #modal-multi-sms .chip-removable {
    max-width: 100%;
    min-height: 44px;
    padding: 0 0 0 var(--space-6);
  }
  #modal-multi-sms .chip-remove { width: 44px; height: 44px; font-size: var(--fs-13); }
  #modal-multi-sms .multi-recipients { max-height: 220px; }

  /* "Utskick": bottom sheet, same treatment as Mallar/Radera. */
  #modal-batches.modal-backdrop { align-items: flex-end; padding-top: 0; }
  #modal-batches .modal {
    width: 100%;
    max-width: none;
    max-height: calc(100vh - 56px);
    border-radius: var(--radius-sheet) var(--radius-sheet) 0 0;
    animation: sheetIn .18s ease-out;
  }
  #modal-batches .modal-close { width: 44px; height: 44px; }
  #modal-batches .batches-list { padding: var(--space-4) var(--space-7) var(--space-9); }
  #modal-batches .batch-row { padding: var(--space-7) 0; }
}
