/* ============================================================
   Theme tokens (light default; dark via [data-theme="dark"] set
   by common.js before first paint)
   ============================================================ */
:root {
  --bg: #f4f5f8;
  --surface: #ffffff;
  --surface-2: #f0f1f5;
  --surface-hover: #e9eaf0;
  --border: #e3e5ec;
  --text: #14161c;
  --text-muted: #6b7080;
  --text-faint: #9498a8;
  --accent: #e4002b;
  --accent-hover: #b80022;
  --accent-contrast: #ffffff;
  --danger: #ef4444;
  --success: #22c55e;
  --overlay: rgba(15, 16, 22, 0.55);
  --shadow-sm: 0 1px 2px rgba(20, 22, 28, 0.06);
  --shadow-md: 0 8px 24px rgba(20, 22, 28, 0.12);

  --xl-grid: #c7ccd1;
  --xl-header-bg: #f3f2f1;
  --xl-header-text: #21252b;
  --xl-green: #e4002b;
  --xl-green-dark: #a60021;
  --xl-cell-bg: #ffffff;
  --xl-row-sender: #ddebf7;
  --xl-row-receiver: #e2efda;
  --xl-selection: #e4002b;
}

:root[data-theme="dark"] {
  --bg: #0f1115;
  --surface: #171a21;
  --surface-2: #1d2129;
  --surface-hover: #262b35;
  --border: #2a2f3a;
  --text: #eef0f5;
  --text-muted: #9498a8;
  --text-faint: #6b7080;
  --accent: #ff4d6d;
  --accent-hover: #ff7389;
  --accent-contrast: #0f1115;
  --danger: #f87171;
  --success: #4ade80;
  --overlay: rgba(0, 0, 0, 0.65);
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
  --shadow-md: 0 12px 32px rgba(0, 0, 0, 0.45);

  --xl-grid: #3a3f44;
  --xl-header-bg: #23272b;
  --xl-header-text: #d7dadd;
  --xl-green: #ff4d6d;
  --xl-green-dark: #c2184a;
  --xl-cell-bg: var(--surface);
  --xl-row-sender: rgba(56, 132, 197, 0.22);
  --xl-row-receiver: rgba(46, 139, 87, 0.2);
  --xl-selection: #ff4d6d;
}

/* ============================================================
   Reset & base
   ============================================================ */
* {
  box-sizing: border-box;
  min-width: 0;
}
/* Several components below set `display: flex` at the same specificity as
   the browser's built-in `[hidden] { display: none }` rule, which lets the
   author rule win and silently defeats `hidden` (e.g. the lightbox was
   rendering as a full-viewport opaque layer on every page load). This
   always wins regardless of what any individual component declares. */
[hidden] {
  display: none !important;
}
html,
body {
  height: 100%;
  margin: 0;
}
body {
  background: var(--bg);
  color: var(--text);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}
button,
input,
textarea {
  font: inherit;
  color: inherit;
}
button {
  cursor: pointer;
  background: none;
  border: none;
  transition: transform 0.1s ease-out;
}
/* Quick tactile "pressed" feedback, the way a native app button dips on tap. */
button:not(:disabled):active {
  transform: scale(0.95);
}
@media (prefers-reduced-motion: reduce) {
  button { transition: none; }
  button:not(:disabled):active { transform: none; }
}
a {
  color: inherit;
  text-decoration: none;
}
img,
video {
  max-width: 100%;
  display: block;
}
::selection {
  background: var(--accent);
  color: var(--accent-contrast);
}

.scrollbar-thin {
  scrollbar-width: thin;
  scrollbar-color: var(--border) transparent;
}
.scrollbar-thin::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}
.scrollbar-thin::-webkit-scrollbar-thumb {
  background: var(--border);
  border-radius: 999px;
}
.scrollbar-thin::-webkit-scrollbar-track {
  background: transparent;
}

@keyframes fade-in-up {
  from {
    opacity: 0;
    transform: translateY(6px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
.fade-in-up {
  animation: fade-in-up 0.18s ease-out;
}

/* Briefly flashes the target row light grey when a reply's quoted snippet jumps to it —
   plain grey rather than the accent color so it reads clearly against either message
   color (sent/received) and in both light and dark mode, instead of blending in. */
@keyframes msg-row-highlight {
  0%, 35% { background: rgba(90, 95, 105, 0.85); box-shadow: inset 0 0 0 2px rgba(90, 95, 105, 0.9); }
  100% { background: transparent; box-shadow: inset 0 0 0 2px transparent; }
}
.msg-row-highlight {
  animation: msg-row-highlight 2s ease-out;
}
/* A ring (drawn on top, not blended into the row's own color) is the reliable cue — a plain
   background flash alone can still read as "barely different" against some message colors.
   The text itself also gets a brief, distinct pulse rather than only the row around it. */
@keyframes msg-text-highlight {
  0%, 35% { color: #fff; font-weight: 700; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5); }
  100% { color: inherit; font-weight: inherit; text-shadow: none; }
}
.msg-row-highlight .msg-text,
.msg-row-highlight .xl-call-log .txt,
.msg-row-highlight .msg-deleted {
  animation: msg-text-highlight 2s ease-out;
}

@keyframes toast-in {
  from {
    opacity: 0;
    transform: translateY(-12px) scale(0.98);
  }
  to {
    opacity: 1;
    transform: translateY(0) scale(1);
  }
}

@keyframes typing-dot {
  0%,
  60%,
  100% {
    transform: translateY(0);
    opacity: 0.5;
  }
  30% {
    transform: translateY(-3px);
    opacity: 1;
  }
}

@keyframes spin {
  to {
    transform: rotate(360deg);
  }
}
.spinner-icon {
  display: inline-block;
  width: 1em;
  height: 1em;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 50%;
  animation: spin 0.6s linear infinite;
}

/* ============================================================
   Utilities
   ============================================================ */
.truncate {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.min-w-0 {
  min-width: 0;
}
.muted {
  color: var(--text-muted);
}
.small {
  font-size: 0.75rem;
}

/* ============================================================
   App shell layout
   ============================================================ */
.app-shell {
  position: relative;
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  min-height: 100dvh;
  /* A plain CSS gradient, not an image file — renders instantly at any screen
     size with nothing to fail to load or get cropped oddly by "cover". Kept
     clearly colourful on purpose (not a washed-out pastel) so it still reads
     as a background behind the app's white cards and bars, not as white itself. */
  background: linear-gradient(165deg, #6fa8dc 0%, #b48ee0 30%, #ffc86b 58%, #ff8fa3 80%, #ffa978 100%) fixed;
}
:root[data-theme="dark"] .app-shell {
  background: linear-gradient(165deg, #060a1c 0%, #1a1240 32%, #3a1240 60%, #4a1530 82%, #381018 100%) fixed;
}
/* One person's own wallpaper: set as a full inline style on #app-shell by
   includes/shell.php (scrim + photo + this same gradient as a fallback layer),
   not through a CSS variable — an earlier var(--user-bg-url) version rendered
   only the gradient even though the same photo loaded fine as an <img>. */

.shell-sidebar {
  display: none;
  width: 16rem;
  flex-shrink: 0;
  flex-direction: column;
  border-right: 1px solid var(--border);
  background: var(--surface);
}
.shell-brand {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  padding: 1.25rem;
}
.shell-brand span {
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.shell-other {
  margin: 0 0.75rem 0.75rem;
  display: flex;
  align-items: center;
  gap: 0.625rem;
  border-radius: 0.75rem;
  background: var(--surface-2);
  padding: 0.625rem 0.75rem;
}
.shell-avatar {
  position: relative;
  display: flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border-radius: 999px;
  font-size: 1rem;
}
.shell-other .shell-name {
  font-size: 0.875rem;
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.shell-sub {
  font-size: 0.75rem;
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.shell-nav {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: 0.25rem;
  padding: 0 0.75rem;
}
.shell-nav-item {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  border-radius: 0.75rem;
  padding: 0.625rem 0.75rem;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--text-muted);
  transition: background 0.15s, color 0.15s;
}
.shell-nav-item:hover {
  background: var(--surface-hover);
  color: var(--text);
}
.shell-nav-item.active {
  background: var(--accent);
  color: var(--accent-contrast);
}
.nav-badge {
  margin-left: auto;
  display: flex;
  height: 1.25rem;
  min-width: 1.25rem;
  align-items: center;
  justify-content: center;
  border-radius: 999px;
  background: var(--danger);
  padding: 0 0.25rem;
  font-size: 11px;
  font-weight: 600;
  color: #fff;
}

.shell-footer {
  border-top: 1px solid var(--border);
  padding: 0.75rem;
}
.shell-me {
  margin-bottom: 0.5rem;
  display: flex;
  align-items: center;
  gap: 0.625rem;
  padding: 0 0.5rem;
}
.shell-logout {
  display: flex;
  width: 100%;
  align-items: center;
  gap: 0.5rem;
  border-radius: 0.75rem;
  padding: 0.5rem 0.75rem;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--text-muted);
  transition: background 0.15s, color 0.15s;
}
.shell-logout:hover {
  background: var(--surface-hover);
  color: var(--danger);
}

.shell-main {
  display: flex;
  min-width: 0;
  flex: 1;
  flex-direction: column;
}
.page-content {
  min-height: 0;
  flex: 1;
  display: flex;
  flex-direction: column;
}

.bottom-nav {
  display: none;
  flex-shrink: 0;
  align-items: center;
  justify-content: space-around;
  border-top: 1px solid var(--border);
  background: var(--surface);
  padding: 0.375rem 0;
  padding-bottom: max(0.375rem, env(safe-area-inset-bottom));
}
.bottom-nav-item {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.125rem;
  border-radius: 0.5rem;
  padding: 0.375rem 0.75rem;
  font-size: 11px;
  font-weight: 500;
  color: var(--text-muted);
}
.bottom-nav-item.active {
  color: var(--accent);
}
.bottom-nav-item .nav-icon {
  font-size: 20px;
  line-height: 1;
}
.bottom-nav-item .nav-badge {
  position: absolute;
  right: 0.25rem;
  top: 0.125rem;
  height: 1rem;
  min-width: 1rem;
  font-size: 10px;
}

@media (min-width: 768px) {
  .app-shell.nav-open .shell-sidebar {
    display: flex;
  }
}
@media (max-width: 767px) {
  .app-shell.nav-open .bottom-nav {
    display: flex;
  }
}

.shell-topbar {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
  padding: 0.3125rem 0.5rem;
}
.nav-toggle-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2rem;
  height: 2rem;
  border-radius: 0.5rem;
  color: var(--text-muted);
  font-size: 1.0625rem;
}
.nav-toggle-btn:hover {
  background: var(--surface-hover);
  color: var(--text);
}

/* ============================================================
   Lock gate (heavy full-page blur) + reveal toggle (lighter blur)
   ============================================================ */
.shell-body-inner {
  display: flex;
  flex: 1;
  min-height: 0;
  overflow: hidden;
}
.app-shell.locked .shell-body-inner,
.app-shell.privacy-blur .shell-body-inner {
  transition: filter 0.25s ease-out, transform 0.25s ease-out;
}
.app-shell.locked .shell-body-inner {
  pointer-events: none;
  user-select: none;
  filter: blur(100px);
  transform: scale(1.1);
}
/* Soft blur while the desktop window is unfocused (no password needed). */
.app-shell.privacy-blur .shell-body-inner {
  pointer-events: none;
  user-select: none;
  filter: blur(30px);
}
@media (prefers-reduced-motion: reduce) {
  .app-shell.locked .shell-body-inner,
  .app-shell.privacy-blur .shell-body-inner { transition: none; }
}
/* Nothing should be printable or easy to drag out. */
@media print {
  body { display: none !important; }
}
.app-shell img, .app-shell video {
  -webkit-user-drag: none;
  -webkit-touch-callout: none;
}
.lock-overlay {
  display: none;
  position: absolute;
  inset: 0;
  z-index: 50;
  align-items: center;
  justify-content: center;
  padding: 1rem;
  background: rgba(15, 16, 22, 0.55);
}
.app-shell.locked .lock-overlay {
  display: flex;
}

.reveal-backdrop {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
  background: rgba(15, 16, 22, 0.4);
  backdrop-filter: blur(24px);
  -webkit-backdrop-filter: blur(24px);
}

/* ============================================================
   Excel password prompt card (shared: lock gate, reveal toggle, login)
   ============================================================ */
.excel-password-card {
  display: flex;
  width: 100%;
  max-width: 360px;
  flex-direction: column;
  overflow: hidden;
  border-radius: 4px;
  border: 1px solid #8a8a8a;
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.35);
  font-family: Calibri, "Segoe UI", Aptos, Arial, sans-serif;
}
.excel-password-titlebar {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0.75rem;
  background: #f0f0f0;
  border-bottom: 1px solid #d4d4d4;
  color: #1a1a1a;
  font-size: 13px;
  font-weight: 600;
}
.excel-password-titlebar .titlebar-icon {
  width: 14px;
  height: 14px;
  border-radius: 3px;
}
.excel-password-body {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  padding: 1.25rem;
  background: #ffffff;
}
.excel-password-row {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
}
.lock-badge {
  margin-top: 2px;
  display: flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 999px;
  background: #fdecea;
  font-size: 16px;
}
.protected-line {
  margin: 0;
  font-size: 13px;
  line-height: 1.35;
  color: #1a1a1a;
}
.protected-sub {
  margin: 2px 0 0;
  font-size: 13px;
  line-height: 1.35;
  color: #444444;
}
.excel-password-body input[type="password"],
.excel-password-body input.pc-secret {
  width: 100%;
  border: 1px solid #767676;
  color: #1a1a1a;
  background: #fff;
  padding: 0.375rem 0.625rem;
  font-size: 14px;
  outline: none;
}
.excel-password-body input[type="password"]:focus,
.excel-password-body input.pc-secret:focus {
  border-color: var(--xl-green, #e4002b);
}
/* Dots without type=password, so browsers and password managers never offer
   to save, fill or update it. */
.pc-secret {
  -webkit-text-security: disc;
  text-security: disc;
}
.excel-password-actions {
  display: flex;
  justify-content: flex-end;
  padding-top: 0.25rem;
}
.btn-ok {
  display: flex;
  min-width: 76px;
  align-items: center;
  justify-content: center;
  gap: 0.375rem;
  border: 1px solid #a60021;
  background: #e4002b;
  color: #fff;
  padding: 0.375rem 1rem;
  font-size: 13px;
  font-weight: 500;
}
.btn-ok:hover {
  background: #a60021;
}
.btn-ok:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
.field-error {
  margin: 0;
  font-size: 12px;
  color: #c00000;
}

/* ============================================================
   Login page (identity picker)
   ============================================================ */
.login-body {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100%;
  padding: 1rem;
  background: var(--bg);
}
.login-main {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}
.identity-card {
  display: flex;
  width: 100%;
  max-width: 360px;
  flex-direction: column;
  gap: 0.625rem;
  border-radius: 0.75rem;
  border: 1px solid var(--border);
  background: var(--surface);
  padding: 1.5rem;
  box-shadow: var(--shadow-md);
}
.identity-title {
  margin: 0 0 0.25rem;
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--text);
  text-align: center;
}
.identity-btn {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  border-radius: 0.75rem;
  border: 1px solid var(--border);
  background: var(--surface-2);
  padding: 0.75rem 1rem;
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--text);
  transition: background 0.15s, border-color 0.15s;
}
.identity-btn:hover {
  background: var(--surface-hover);
  border-color: var(--accent);
}
.identity-btn:disabled {
  opacity: 0.6;
  cursor: not-allowed;
}
.identity-btn .avatar {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 999px;
  font-size: 1.125rem;
}
.link-btn {
  align-self: center;
  margin-top: 0.25rem;
  font-size: 0.8125rem;
  color: var(--text-muted);
}
.link-btn:hover {
  color: var(--accent);
}

/* ============================================================
   Toasts
   ============================================================ */
.toast-stack {
  position: fixed;
  top: 1rem;
  right: 1rem;
  left: 1rem;
  z-index: 60;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 0.5rem;
  pointer-events: none;
}
.toast {
  pointer-events: auto;
  display: flex;
  align-items: flex-start;
  gap: 0.625rem;
  max-width: 320px;
  width: 100%;
  border-radius: 0.75rem;
  border: 1px solid var(--border);
  background: var(--surface);
  box-shadow: var(--shadow-md);
  padding: 0.75rem;
  animation: toast-in 0.2s ease-out;
}
.toast-icon {
  font-size: 1.125rem;
}
.toast-title {
  margin: 0;
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--text);
}
.toast-body {
  margin: 2px 0 0;
  font-size: 0.75rem;
  color: var(--text-muted);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ============================================================
   Excel worksheet chat theme
   ============================================================ */
.xl-sheet {
  display: flex;
  height: 100%;
  min-height: 0;
  flex-direction: column;
  /* Transparent on purpose: the app-shell's background (see .app-shell) shows
     through here. The chrome bars (toolbar, headers) and message bubbles each
     already carry their own opaque background, so nothing becomes unreadable. */
  background: transparent;
  font-family: Calibri, "Segoe UI", Aptos, Arial, sans-serif;
}
/* While hiding behind the blank decoy grid (see chat.js / initHideToggle in
   common.js), this needs to look exactly like a real, boring blank
   spreadsheet — a colourful background behind it would give the game away. */
.xl-sheet-blank {
  background: var(--xl-cell-bg);
}
.xl-cell {
  border-right: 1px solid var(--xl-grid);
  border-bottom: 1px solid var(--xl-grid);
}
.xl-active-cell {
  outline: 2px solid var(--xl-selection);
  outline-offset: -2px;
  position: relative;
}
.xl-active-cell::after {
  content: "";
  position: absolute;
  right: -3px;
  bottom: -3px;
  width: 6px;
  height: 6px;
  background: var(--xl-selection);
}

.xl-titlebar {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0.75rem;
  color: #fff;
  background: var(--xl-green-dark);
}
.xl-titlebar .xl-title {
  font-size: 0.875rem;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.xl-titlebar .xl-saved {
  display: none;
  flex-shrink: 0;
  font-size: 0.75rem;
  color: rgba(255, 255, 255, 0.6);
}
.xl-titlebar-right {
  margin-left: auto;
  display: flex;
  flex-shrink: 0;
  align-items: center;
  gap: 0.5rem;
}
.xl-reconnecting {
  border-radius: 4px;
  background: rgba(255, 255, 255, 0.15);
  padding: 0.125rem 0.5rem;
  font-size: 11px;
  font-weight: 500;
}
.xl-titlebar-avatar {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.15);
  font-size: 0.875rem;
}
.xl-titlebar-who {
  display: none;
  text-align: right;
}
.xl-titlebar-who .name {
  margin: 0;
  font-size: 0.75rem;
  font-weight: 600;
  line-height: 1.2;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.xl-titlebar-who .status {
  margin: 0;
  font-size: 10px;
  line-height: 1.2;
  color: rgba(255, 255, 255, 0.7);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
@media (min-width: 640px) {
  .xl-titlebar .xl-saved,
  .xl-titlebar-who {
    display: block;
  }
}

.xl-toolbar {
  display: flex;
  flex-wrap: wrap;
  flex-shrink: 0;
  align-items: center;
  justify-content: space-between;
  gap: 0.375rem 0.5rem;
  border-bottom: 1px solid var(--xl-grid);
  background: var(--xl-header-bg);
  padding: 0.25rem 0.75rem;
}
.xl-toolbar-group {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.xl-toolbar-label {
  font-size: 11px;
  font-weight: 500;
  color: var(--xl-header-text);
}
.xl-jumpdate {
  cursor: pointer;
}
.xl-jumpdate input[type="date"] {
  width: 6.5rem;
  padding: 0.125rem 0.25rem;
  border: 1px solid var(--xl-grid);
  border-radius: 0.25rem;
  background: var(--surface);
  color: var(--text);
  font-size: 11px;
}
.xl-spinner {
  display: flex;
  align-items: center;
  border: 1px solid var(--xl-grid);
  background: var(--surface);
}
.xl-spinner-value {
  width: 1.5rem;
  text-align: center;
  font-size: 12px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
  color: var(--xl-header-text);
}
.xl-spinner-btns {
  display: flex;
  flex-direction: column;
  border-left: 1px solid var(--xl-grid);
}
.xl-spinner-btns button {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 1rem;
  height: 0.875rem;
  line-height: 1;
  color: var(--xl-header-text);
  font-size: 9px;
}
.xl-spinner-btns button:first-child {
  border-bottom: 1px solid var(--xl-grid);
}
.xl-spinner-btns button:hover:not(:disabled) {
  background: var(--surface-hover);
}
.xl-spinner-btns button:disabled {
  opacity: 0.3;
  cursor: not-allowed;
}

.xl-toggle-btn {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  gap: 0.375rem;
  border: 1px solid var(--xl-grid);
  background: var(--surface);
  color: var(--xl-header-text);
  padding: 0.25rem 0.625rem;
  font-size: 11px;
  font-weight: 500;
  transition: background 0.15s;
}
.xl-toggle-btn:hover {
  background: var(--surface-hover);
}

.xl-scroll {
  position: relative;
  min-height: 0;
  flex: 1;
  overflow: auto;
}
.xl-scroll-inner {
  min-width: 420px;
  font-size: var(--xl-msg-font-size, 13px);
}
.xl-grid-header {
  position: sticky;
  top: 0;
  z-index: 10;
  display: grid;
  grid-template-columns: 1fr;
  font-size: 0.85em;
  font-weight: 600;
  color: var(--xl-header-text);
}
.xl-grid-header .xl-cell {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0.375rem 0;
  background: var(--xl-header-bg);
}

/* Blank-sheet look for the hidden state: real column letters + gridded
   empty cells, so a glance shows an ordinary empty spreadsheet rather than
   an obvious "content hidden" placeholder. */
.blank-grid-header,
.blank-grid-row {
  display: grid;
  grid-template-columns: 2.75rem repeat(6, minmax(4rem, 1fr));
}
.blank-grid-header .xl-cell {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0.375rem 0;
  background: var(--xl-header-bg);
}
.blank-grid-cell {
  min-height: 1.75rem;
  border-right: 1px solid var(--xl-grid);
  border-bottom: 1px solid var(--xl-grid);
}
.blank-grid-cell.blank-row-num {
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 0.85em;
  font-weight: 600;
  background: var(--xl-header-bg);
  color: var(--xl-header-text);
}

.xl-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 4rem 1.5rem;
  text-align: center;
  color: var(--text-muted);
}
.xl-empty .emoji {
  font-size: 1.875rem;
}
.xl-hidden-state {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.375rem;
  padding: 6rem 1.5rem;
  text-align: center;
  color: var(--xl-header-text);
  opacity: 0.35;
}
.xl-hidden-state .emoji {
  font-size: 1.375rem;
}
.xl-hidden-state p {
  margin: 0;
  font-size: 0.85em;
}

.xl-date-sep {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0.25rem 0;
  background: var(--xl-header-bg);
  color: var(--xl-header-text);
}
.xl-date-sep span {
  font-size: 0.85em;
  font-weight: 600;
}
.xl-unread-sep {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0.25rem 0;
  font-size: 0.85em;
  font-weight: 600;
  color: var(--danger);
  background: var(--xl-header-bg);
}

/* ---- message row (grid: row-number | message bubble, tick wraps under
   the bubble on the same side) — bubble sits right for your own messages,
   left for the other person's, WhatsApp-style. The row-number gutter stays
   put on the left, like column A of a sheet. ---- */
.msg-row {
  position: relative;
  display: grid;
  grid-template-columns: 1fr;
  padding: 0 0.625rem;
  /* A small gap between consecutive bubbles — without it they'd stack with
     zero space between them, which also hid the app's background (gradient
     or wallpaper) almost entirely in any conversation with enough messages
     to fill the screen. Tighter when grouped (same sender back-to-back). */
  margin-bottom: 0.3125rem;
  font-size: var(--xl-msg-font-size, 13px);
}
.msg-row-grouped {
  margin-bottom: 0.125rem;
}
.msg-row-body {
  position: relative;
  width: fit-content;
  max-width: min(82%, 38rem);
  padding: 0.4375rem 0.625rem;
  border-radius: 0.875rem;
  box-shadow: var(--shadow-sm);
}
.msg-row.msg-mine .msg-row-body {
  justify-self: end;
  border-bottom-right-radius: 0.25rem;
}
.msg-row.msg-theirs .msg-row-body {
  justify-self: start;
  border-bottom-left-radius: 0.25rem;
}
/* Consecutive messages from the same person sit a little closer together — a tighter top
   gap only, never hiding the row's own time (see the comment in buildEntries()): that
   stays on every row so you can always tell when each one landed. */
.msg-row-grouped .msg-row-body,
.msg-row-grouped .msg-row-tick {
  padding-top: 0.0625rem;
}
.msg-row-tick {
  display: flex;
  align-items: center;
  gap: 0.3125rem;
  width: fit-content;
  margin: 0.0625rem 0.25rem 0.1875rem;
  padding: 0.125rem 0.5rem;
  border-radius: 999px;
  /* A soft pill behind the time/ticks so the grey ticks stay readable
     over a wallpaper or gradient, not just on a plain background. */
  background: color-mix(in srgb, var(--surface) 82%, transparent);
}
/* Time first, ticks last (WhatsApp order) — no reversing, which used to put
   the ticks on the wrong side of the time for your own messages. */
.msg-row.msg-mine .msg-row-tick {
  justify-self: end;
}
.msg-row.msg-theirs .msg-row-tick {
  justify-self: start;
}
.msg-row.msg-mine .msg-deleted {
  margin-left: auto;
  border-radius: 0.875rem;
}
.msg-time {
  white-space: nowrap;
  font-size: 0.8em;
  line-height: 1;
  color: var(--text-muted);
}
.msg-edited {
  font-size: 0.7em;
  font-style: italic;
  line-height: 1;
  color: var(--text-faint);
}
.msg-deleted {
  display: flex;
  align-items: center;
  width: fit-content;
  max-width: min(82%, 38rem);
  padding: 0.375rem 0.625rem;
  font-style: italic;
  color: var(--text-faint);
}

.msg-actions {
  position: absolute;
  right: 0.25rem;
  top: 0.25rem;
  opacity: 0;
  transition: opacity 0.15s;
}
.msg-row:hover .msg-actions,
.msg-actions.open {
  opacity: 1;
}
.msg-actions-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 1.5rem;
  height: 1.5rem;
  border-radius: 4px;
  color: var(--text-muted);
}
.msg-actions-btn:hover {
  background: var(--surface-hover);
}
.msg-actions-menu {
  position: absolute;
  right: 0;
  top: 1.75rem;
  z-index: 20;
  min-width: 140px;
  border-radius: 0.5rem;
  border: 1px solid var(--border);
  background: var(--surface);
  box-shadow: var(--shadow-md);
  padding: 0.25rem;
  display: none;
}
.msg-actions-menu.open {
  display: block;
}
.msg-actions-menu button {
  display: flex;
  width: 100%;
  align-items: center;
  gap: 0.5rem;
  border-radius: 0.375rem;
  padding: 0.375rem 0.5rem;
  font-size: 0.8125rem;
  color: var(--text);
  text-align: left;
}
.msg-actions-menu button:hover {
  background: var(--surface-hover);
}
.msg-actions-menu .danger {
  color: var(--danger);
}
.msg-actions-emojis {
  display: flex;
  gap: 0.125rem;
  padding: 0.25rem;
}
.msg-actions-emojis button {
  width: 1.75rem;
  padding: 0.125rem;
  text-align: center;
  font-size: 1rem;
  border-radius: 0.375rem;
}

.msg-reply {
  display: block;
  width: 100%;
  max-width: 28rem;
  margin-bottom: 0.375rem;
  border-radius: 0.25rem;
  border-left: 2px solid var(--xl-green);
  background: var(--xl-header-bg);
  padding: 0.25rem 0.5rem;
  font-size: 0.85em;
  text-align: left;
  opacity: 0.8;
}
.msg-reply:hover {
  opacity: 1;
  background: var(--surface-hover);
}
.msg-reply p {
  margin: 0;
}
.msg-reply .who {
  font-weight: 500;
}
.msg-reply .snippet {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.msg-media-note {
  margin-bottom: 0.25rem;
  display: flex;
  align-items: center;
  gap: 0.375rem;
  padding-right: 1.5rem;
  font-size: 0.85em;
  font-style: italic;
  color: var(--text-faint);
}
.msg-media-note .icon {
  color: var(--xl-green);
}

.msg-text {
  margin: 0;
  padding-right: 1.5rem;
  white-space: pre-wrap;
  overflow-wrap: break-word;
  line-height: 1.5;
  color: var(--text);
}

.msg-edit-box {
  display: flex;
  max-width: 28rem;
  flex-direction: column;
  gap: 0.375rem;
}
.msg-edit-box textarea {
  resize: none;
  border: 1px solid var(--xl-green);
  background: var(--surface);
  padding: 0.25rem 0.5rem;
  outline: none;
}
.msg-edit-actions {
  display: flex;
  justify-content: flex-end;
  gap: 0.25rem;
}
.msg-edit-actions button {
  border-radius: 0.375rem;
  padding: 0.25rem;
}
.msg-edit-actions button:hover {
  background: var(--surface-hover);
}

.msg-tags {
  margin-top: 0.25rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
}
.msg-tag {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  border-radius: 0.375rem;
  padding: 0.125rem 0.375rem;
  font-size: 0.75em;
  font-weight: 500;
}
.msg-tag button {
  opacity: 0;
  transition: opacity 0.15s;
}
.msg-tag:hover button {
  opacity: 1;
}

.msg-tagging {
  margin-top: 0.375rem;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.25rem;
}
.msg-tagging button {
  border-radius: 0.375rem;
  border: 1px solid var(--border);
  background: var(--surface);
  color: var(--text-muted);
  padding: 0.125rem 0.375rem;
  font-size: 10px;
}
.msg-tagging button:hover {
  background: var(--surface-hover);
}
.msg-tagging input {
  width: 6rem;
  border-radius: 0.375rem;
  border: 1px solid var(--border);
  background: var(--surface);
  padding: 0.125rem 0.375rem;
  font-size: 10px;
  outline: none;
}
.msg-tagging input:focus {
  border-color: var(--accent);
}

.msg-reactions {
  margin-top: 0.25rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.25rem;
}
.msg-reaction-pill {
  display: flex;
  align-items: center;
  gap: 0.25rem;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--surface);
  padding: 0.0625rem 0.4375rem;
  font-size: 0.75em;
}
.msg-reaction-pill.mine {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 15%, transparent);
}

/* One tick = sent, two grey = delivered, two blue = read. The two ticks
   overlap slightly (negative letter-spacing) so "✓✓" reads as a pair. */
.msg-ticks {
  display: inline-flex;
  align-items: center;
  font-size: 1.05em;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.28em;
  padding-right: 0.28em; /* gives back what the negative spacing took off the last tick */
}
.msg-ticks svg {
  display: block;
}
.msg-ticks.read {
  color: var(--tick-read, #1e90ff);
}
.msg-ticks:not(.read) {
  color: var(--text-muted);
}

.typing-row {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0.75rem;
  font-size: 0.8em;
  color: var(--text-muted);
}
.typing-dots {
  display: inline-flex;
  gap: 3px;
}
.typing-dots span {
  width: 5px;
  height: 5px;
  border-radius: 999px;
  background: var(--text-muted);
  animation: typing-dot 1.2s ease-in-out infinite;
}
.typing-dots span:nth-child(2) {
  animation-delay: 0.15s;
}
.typing-dots span:nth-child(3) {
  animation-delay: 0.3s;
}

.jump-wrap {
  pointer-events: none;
  display: flex;
  justify-content: center;
}
.jump-btn {
  pointer-events: auto;
  margin-top: -3.5rem;
  display: flex;
  align-items: center;
  gap: 0.375rem;
  border-radius: 999px;
  border: 1px solid var(--border);
  background: var(--surface);
  padding: 0.375rem 0.75rem;
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--text);
  box-shadow: var(--shadow-md);
}

/* ---- composer ---- */
.composer {
  flex-shrink: 0;
  border-top: 1px solid var(--xl-grid);
  background: var(--surface);
  padding: 0.5rem 0.75rem;
  padding-bottom: max(0.5rem, env(safe-area-inset-bottom));
}
.composer-reply {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0.375rem;
  border-radius: 0.5rem;
  background: var(--surface-2);
  padding: 0.375rem 0.625rem;
  font-size: 0.8125rem;
}
.composer-reply .info {
  min-width: 0;
  flex: 1;
}
.composer-reply .who {
  margin: 0;
  font-weight: 600;
  color: var(--accent);
}
.composer-reply .snippet {
  margin: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text-muted);
}
.composer-row {
  display: flex;
  align-items: flex-end;
  gap: 0.5rem;
}
.composer-icon-btn {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 999px;
  color: var(--text-muted);
}
.composer-icon-btn:hover {
  background: var(--surface-hover);
  color: var(--text);
}
.composer textarea {
  flex: 1;
  resize: none;
  max-height: 8rem;
  border-radius: 1.125rem;
  border: 1px solid var(--border);
  background: var(--surface-2);
  padding: 0.5rem 0.875rem;
  font-size: 0.9375rem;
  line-height: 1.4;
  outline: none;
}
.composer textarea:focus {
  border-color: var(--accent);
}
.composer-send {
  display: flex;
  flex-shrink: 0;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 999px;
  background: var(--accent);
  color: var(--accent-contrast);
}
.composer-send:hover {
  background: var(--accent-hover);
}
.composer-send:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}
.composer-upload-progress {
  margin-bottom: 0.375rem;
  font-size: 0.75rem;
  color: var(--text-muted);
}

/* ============================================================
   Gallery
   ============================================================ */
.gallery-page {
  display: flex;
  height: 100%;
  min-height: 0;
  flex-direction: column;
}
.gallery-header {
  flex-shrink: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
  padding: 0.75rem 1rem;
}
.gallery-title {
  margin: 0;
  font-size: 1rem;
  font-weight: 600;
}
.gallery-tabs {
  display: flex;
  gap: 0.25rem;
  border-radius: 0.5rem;
  background: var(--surface-2);
  padding: 0.1875rem;
}
.gallery-tab {
  border-radius: 0.375rem;
  padding: 0.3125rem 0.75rem;
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--text-muted);
}
.gallery-tab.active {
  background: var(--surface);
  color: var(--text);
  box-shadow: var(--shadow-sm);
}
.gallery-controls {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 0.75rem;
}

.gallery-scroll {
  min-height: 0;
  flex: 1;
  overflow: auto;
  padding: 0.75rem;
}
.gallery-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(var(--tile-size, 150px), 1fr));
  gap: 0.5rem;
}
.gallery-tile {
  position: relative;
  aspect-ratio: 1;
  overflow: hidden;
  border-radius: 0.5rem;
  background: var(--surface-2);
}
.gallery-tile img,
.gallery-tile video {
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.gallery-tile-caption {
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  padding: 1rem 0.5rem 0.375rem;
  background: linear-gradient(to top, rgba(0, 0, 0, 0.7), transparent);
  opacity: 0;
  transition: opacity 0.15s;
}
.gallery-tile:hover .gallery-tile-caption {
  opacity: 1;
}
.gallery-tile-caption p {
  margin: 0;
  color: #fff;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.gallery-tile-caption .who {
  font-size: 11px;
  font-weight: 500;
}
.gallery-tile-caption .when {
  font-size: 10px;
  color: rgba(255, 255, 255, 0.7);
}
.gallery-tile-video-ph {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--surface-2);
}
.gallery-tile-video-ph span {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.45);
  color: #fff;
  font-size: 1.125rem;
}
.gallery-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 4rem 1.5rem;
  text-align: center;
  color: var(--text-muted);
}

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 70;
  display: flex;
  flex-direction: column;
  background: rgba(0, 0, 0, 0.92);
}
.lightbox-top {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 0.5rem;
  padding: 0.75rem;
}
.lightbox-top button {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.1);
  color: #fff;
}
.lightbox-top button:hover {
  background: rgba(255, 255, 255, 0.2);
}
.lightbox-body {
  display: flex;
  min-height: 0;
  flex: 1;
  align-items: center;
  justify-content: center;
  padding: 0 1rem;
}
.lightbox-body {
  overflow: hidden;
  position: relative;
  -webkit-user-select: none;
  user-select: none;
  -webkit-touch-callout: none;
}
.lightbox-media {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}
img.lightbox-media {
  touch-action: none; /* pinch / drag are handled by gallery.js */
  transform-origin: center center;
  cursor: zoom-in;
  -webkit-user-drag: none;
}
.lightbox-body.zoomed img.lightbox-media { cursor: grab; }

/* Shown while the full-size original downloads, or if it fails. */
.lightbox-loading {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1rem;
}
.lightbox-placeholder {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  filter: blur(14px);
  opacity: 0.5;
  transform: scale(1.05); /* hides the blurred edge */
}
.lightbox-spinner {
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 999px;
  border: 3px solid rgba(255, 255, 255, 0.25);
  border-top-color: #fff;
  animation: lightbox-spin 0.8s linear infinite;
  position: relative;
  z-index: 1;
}
@keyframes lightbox-spin {
  to { transform: rotate(360deg); }
}
.lightbox-error {
  position: relative;
  z-index: 1;
  color: #fff;
  text-align: center;
  padding: 0 1.5rem;
  line-height: 1.5;
}
.lightbox-retry {
  position: relative;
  z-index: 1;
  padding: 0.5rem 1.25rem;
  border-radius: 999px;
  background: #fff;
  color: #111;
  font-weight: 600;
}
.lightbox.is-video #lightbox-zoom-in,
.lightbox.is-video #lightbox-zoom-out,
.lightbox.is-video #lightbox-zoom-reset { display: none; }
.lightbox-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.1);
  color: #fff;
}
.lightbox-nav:hover {
  background: rgba(255, 255, 255, 0.2);
}
.lightbox-nav.prev {
  left: 0.75rem;
}
.lightbox-nav.next {
  right: 0.75rem;
}

/* ============================================================
   Search
   ============================================================ */
.search-page {
  display: flex;
  height: 100%;
  min-height: 0;
  flex-direction: column;
}
.search-header {
  flex-shrink: 0;
  border-bottom: 1px solid var(--border);
  background: var(--surface);
  padding: 0.75rem 1rem;
  display: flex;
  flex-direction: column;
  gap: 0.625rem;
}
.search-input-wrap {
  position: relative;
}
.search-input-wrap input {
  width: 100%;
  border-radius: 0.75rem;
  border: 1px solid var(--border);
  background: var(--surface-2);
  padding: 0.5rem 0.75rem 0.5rem 2.25rem;
  font-size: 0.875rem;
  outline: none;
}
.search-input-wrap input:focus {
  border-color: var(--accent);
}
.search-input-wrap .icon {
  position: absolute;
  left: 0.75rem;
  top: 50%;
  transform: translateY(-50%);
  color: var(--text-muted);
}
.search-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.375rem;
}
.search-tag-chip {
  border-radius: 999px;
  border: 1px solid var(--border);
  padding: 0.25rem 0.625rem;
  font-size: 0.75rem;
  font-weight: 500;
  color: var(--text-muted);
}
.search-tag-chip.active {
  border-color: var(--accent);
  background: color-mix(in srgb, var(--accent) 15%, transparent);
  color: var(--accent);
}
.search-results {
  min-height: 0;
  flex: 1;
  overflow: auto;
  padding: 0.5rem 0.75rem;
}
.search-result {
  border-radius: 0.75rem;
  padding: 0.625rem 0.75rem;
  margin-bottom: 0.375rem;
  cursor: pointer;
}
.search-result:hover {
  background: var(--surface-hover);
}
.search-result .meta {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  margin-bottom: 0.125rem;
  font-size: 0.75rem;
  color: var(--text-muted);
}
.search-result .snippet {
  margin: 0;
  font-size: 0.875rem;
  color: var(--text);
}
.search-result mark {
  background: color-mix(in srgb, var(--accent) 35%, transparent);
  color: inherit;
  border-radius: 2px;
}

/* ============================================================
   Settings / Profile
   ============================================================ */
.settings-page,
.profile-page {
  min-height: 0;
  flex: 1;
  overflow: auto;
  padding: 1rem;
}
.settings-section,
.profile-card {
  max-width: 32rem;
  margin: 0 auto 1rem;
  border-radius: 0.75rem;
  border: 1px solid var(--border);
  background: var(--surface);
  padding: 1rem 1.25rem;
}
.settings-section h2,
.profile-card h2 {
  margin: 0 0 0.75rem;
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--text-muted);
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.settings-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.625rem 0;
  border-bottom: 1px solid var(--border);
}
.settings-row:last-child {
  border-bottom: none;
}
.settings-row .label {
  font-size: 0.875rem;
  font-weight: 500;
}
.settings-row .desc {
  margin: 2px 0 0;
  font-size: 0.75rem;
  color: var(--text-muted);
}

.toggle {
  position: relative;
  display: inline-flex;
  align-items: center;
  width: 2.75rem;
  height: 1.5rem;
  border-radius: 999px;
  background: var(--border);
  flex-shrink: 0;
  transition: background 0.15s;
}
.toggle.on {
  background: var(--accent);
}
.toggle .knob {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 1.25rem;
  height: 1.25rem;
  border-radius: 999px;
  background: #fff;
  box-shadow: var(--shadow-sm);
  transition: transform 0.15s;
}
.toggle.on .knob {
  transform: translateX(1.25rem);
}

.theme-options {
  display: flex;
  gap: 0.5rem;
}
.theme-option {
  flex: 1;
  border-radius: 0.5rem;
  border: 1px solid var(--border);
  padding: 0.5rem;
  font-size: 0.8125rem;
  font-weight: 500;
  text-align: center;
  color: var(--text-muted);
}
.theme-option.active {
  border-color: var(--accent);
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
}

.profile-avatar-row {
  display: flex;
  align-items: center;
  gap: 1rem;
  margin-bottom: 1rem;
}
.profile-avatar {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 3.5rem;
  height: 3.5rem;
  border-radius: 999px;
  font-size: 1.75rem;
}
.profile-name {
  margin: 0;
  font-size: 1rem;
  font-weight: 600;
}
.profile-role {
  margin: 2px 0 0;
  font-size: 0.8125rem;
  color: var(--text-muted);
}

/* ============================================================
   Presence dot
   ============================================================ */
.presence-dot {
  position: absolute;
  width: 0.625rem;
  height: 0.625rem;
  border-radius: 999px;
  border: 2px solid var(--surface);
  background: var(--text-faint);
}
.presence-dot.online {
  background: var(--success);
}

/* ============================================================
   Generic loading state
   ============================================================ */
.page-loading {
  display: flex;
  flex: 1;
  min-height: 100%;
  align-items: center;
  justify-content: center;
}
.page-loading .spin {
  width: 2rem;
  height: 2rem;
  border-radius: 999px;
  border: 2px solid var(--border);
  border-top-color: var(--accent);
  animation: spin 0.6s linear infinite;
}

/* Settings → Security log */
.security-log { display: flex; flex-direction: column; gap: 0.375rem; max-height: 18rem; overflow: auto; }
.security-row { display: flex; flex-direction: column; gap: 0.125rem; padding: 0.5rem 0.625rem; border: 1px solid var(--border); border-radius: 0.5rem; font-size: 0.8125rem; }
.security-row.bad { border-color: var(--danger); background: color-mix(in srgb, var(--danger) 8%, transparent); }
.security-row .desc { font-size: 0.75rem; }

/* Messages still being sent / not sent (instant-send with retry) */
.msg-ticks.pending { opacity: 0.55; }
.msg-failed { display: inline-flex; gap: 0.5rem; align-items: center; color: var(--danger); font-size: 0.75rem; }
.msg-failed button { color: var(--danger); text-decoration: underline; background: none; border: 0; padding: 0; font: inherit; cursor: pointer; }
.msg-row.is-pending .msg-text { opacity: 0.75; }

/* ============================================================
   Phone / touch polish
   ============================================================ */
html, body { overscroll-behavior-y: none; }          /* no pull-to-refresh reload (it would re-lock the app) */
* { -webkit-tap-highlight-color: transparent; }
button, a, .msg-row, label { touch-action: manipulation; } /* no double-tap zoom delay */

/* Chat, Gallery and Search fill exactly the visible screen; only the message
   list / grid / results scroll — header, typing line and composer stay put.
   --app-h is kept in sync with the on-screen keyboard by common.js. */
.chat-body, .gallery-body, .search-body { overflow: hidden; }
.chat-body .app-shell,
.gallery-body .app-shell,
.search-body .app-shell {
  height: var(--app-h, 100dvh);
  min-height: 0;
  overflow: hidden;
}
.shell-main { min-height: 0; }
.xl-scroll { overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }

/* "Eve is typing…" lives under the message list, not inside it. */
/* ---- pinned messages bar (persistent, above the message list) ---- */
.pinned-bar {
  display: flex;
  flex-shrink: 0;
  align-items: stretch;
  border-bottom: 1px solid var(--xl-grid);
  background: var(--surface);
}
.pinned-bar[hidden] { display: none; }
.pinned-bar-main {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 0.5rem;
  min-width: 0;
  padding: 0.375rem 0.75rem;
  text-align: left;
  font-size: 0.8125rem;
}
.pinned-bar-main .ic { flex-shrink: 0; }
.pinned-bar-main .snippet {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: var(--text-muted);
}
.pinned-bar-main .count {
  flex-shrink: 0;
  padding: 0.0625rem 0.4375rem;
  border-radius: 999px;
  background: var(--surface-2);
  color: var(--text-muted);
  font-size: 0.75em;
}
.pinned-bar-list-toggle {
  flex-shrink: 0;
  width: 2.25rem;
  border-left: 1px solid var(--xl-grid);
  color: var(--text-muted);
}
.pinned-list {
  flex-shrink: 0;
  max-height: 40vh;
  overflow-y: auto;
  border-bottom: 1px solid var(--xl-grid);
  background: var(--surface);
}
.pinned-list[hidden] { display: none; }
.pinned-list-item {
  display: flex;
  width: 100%;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0.75rem;
  text-align: left;
  font-size: 0.8125rem;
  border-bottom: 1px solid var(--border);
}
.pinned-list-item:hover { background: var(--surface-hover); }
.pinned-list-item .info { flex: 1; min-width: 0; }
.pinned-list-item .who { margin: 0; font-weight: 600; font-size: 0.75em; color: var(--text-muted); }
.pinned-list-item .snippet { margin: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.pinned-list-item .unpin { flex-shrink: 0; color: var(--text-muted); }
.pinned-list-item .unpin:hover { color: var(--danger); }

/* Small marker next to the timestamp on a pinned message itself. */
.msg-pin-mark { flex-shrink: 0; }

.typing-bar {
  display: none;
  flex-shrink: 0;
  align-items: center;
  gap: 0.5rem;
  padding: 0.25rem 0.75rem;
  font-size: 0.8125rem;
  color: var(--text-muted);
  background: var(--surface);
  border-top: 1px solid var(--xl-grid);
}
.typing-bar.show { display: flex; }

/* Notch / home-indicator safe areas (installed app, landscape). */
.app-shell {
  padding-left: env(safe-area-inset-left);
  padding-right: env(safe-area-inset-right);
}
.shell-topbar { padding-top: max(0.3125rem, env(safe-area-inset-top)); }

@media (max-width: 767px) {
  /* iOS zooms the page when a field under 16px is focused. */
  input[type="text"], input[type="search"], input:not([type]), textarea, select,
  .excel-password-body input, .excel-password-body input.pc-secret,
  .excel-password-body input[type="password"], .composer textarea { font-size: 16px; }

  /* Fit narrow screens: the message grid no longer forces sideways scrolling. */
  .xl-scroll-inner { min-width: 0; }
  .blank-grid-header, .blank-grid-row { grid-template-columns: 2rem repeat(6, minmax(3rem, 1fr)); }
  .msg-row-tick { padding-left: 0.125rem; padding-right: 0.125rem; }

  /* Bigger touch targets. */
  .composer-icon-btn, .composer-send { width: 2.75rem; height: 2.75rem; }
  .nav-toggle-btn { width: 2.5rem; height: 2.5rem; }
  .bottom-nav-item { padding: 0.5rem 0.75rem; }
  .msg-actions-btn { width: 2rem; height: 2rem; }
  .msg-actions-menu button { padding: 0.625rem 0.75rem; font-size: 0.9375rem; }
  .msg-actions-emojis button { width: 2.25rem; font-size: 1.25rem; padding: 0.25rem; }
  .composer { padding-left: 0.5rem; padding-right: 0.5rem; }
  .xl-titlebar { padding: 0.5rem 0.625rem; }
}

/* No hover on touch screens: keep the ⋮ message menu button visible. */
@media (hover: none) {
  .msg-actions { opacity: 0.55; }
  .msg-actions.open { opacity: 1; }
}

/* ============================================================
   Location page
   ============================================================ */
.location-body { overflow: hidden; }
.location-body .app-shell { height: var(--app-h, 100dvh); min-height: 0; overflow: hidden; }

.loc-page { display: flex; height: 100%; min-height: 0; flex-direction: column; }
.loc-content { display: flex; flex: 1; min-height: 0; flex-direction: column; }
.loc-map-wrap { position: relative; flex: 0 0 52%; min-height: 220px; border-bottom: 1px solid var(--border); }
#loc-map { position: absolute; inset: 0; background: var(--surface-2); z-index: 0; }
.loc-panel { flex: 1; min-height: 0; overflow: auto; padding: 0.75rem; display: flex; flex-direction: column; gap: 0.625rem; overscroll-behavior: contain; }
@media (min-width: 900px) {
  .loc-content { flex-direction: row; }
  .loc-map-wrap { flex: 1; border-bottom: 0; border-right: 1px solid var(--border); }
  .loc-panel { flex: 0 0 24rem; }
}

.loc-card { border: 1px solid var(--border); border-radius: 0.75rem; background: var(--surface); padding: 0.625rem 0.75rem; }
.loc-share-row { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; }
.loc-share-row .label { margin: 0; font-weight: 600; }
.loc-share-row .desc, .loc-card .desc { margin: 0.125rem 0 0; font-size: 0.8125rem; color: var(--text-muted); }
.loc-fine { font-size: 0.75rem !important; margin-top: 0.5rem !important; }
.loc-status { margin: 0; font-size: 0.9375rem; font-weight: 500; }
.loc-link { background: none; border: 0; padding: 0; margin-top: 0.5rem; font: inherit; font-size: 0.8125rem; text-decoration: underline; cursor: pointer; color: var(--text-muted); }
.loc-link.danger { color: var(--danger); }

.loc-tabs { display: flex; gap: 0.375rem; }
.loc-tab { flex: 1; border: 1px solid var(--border); border-radius: 999px; padding: 0.5rem 0.75rem; background: var(--surface); font-weight: 500; }
.loc-tab.active { background: var(--accent); color: var(--accent-contrast); border-color: var(--accent); }

.loc-actions { display: flex; gap: 0.5rem; margin-top: 0.5rem; }
.loc-btn { display: inline-flex; align-items: center; justify-content: center; min-height: 2.5rem; min-width: 2.5rem; padding: 0 0.875rem; border: 1px solid var(--border); border-radius: 0.5rem; background: var(--surface); color: var(--text); font-weight: 500; text-decoration: none; }
.loc-btn:disabled { opacity: 0.35; }
.loc-daynav { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; }
.loc-day { font-weight: 600; }

.loc-stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0.375rem; }
.loc-stats > div { border: 1px solid var(--border); border-radius: 0.625rem; background: var(--surface); padding: 0.5rem 0.25rem; text-align: center; }
.loc-stats b { display: block; font-size: 0.9375rem; }
.loc-stats span { font-size: 0.6875rem; color: var(--text-muted); }

.loc-timeline { display: flex; flex-direction: column; gap: 0.375rem; }
.loc-seg { display: flex; gap: 0.625rem; align-items: center; text-align: left; border: 1px solid var(--border); border-radius: 0.625rem; background: var(--surface); padding: 0.5rem 0.625rem; }
.loc-seg .ic { flex: 0 0 1.75rem; height: 1.75rem; display: flex; align-items: center; justify-content: center; border-radius: 999px; background: var(--surface-2); font-weight: 700; font-size: 0.8125rem; }
.loc-seg small { color: var(--text-muted); }

/* map pins */
.loc-pin-wrap, .loc-dot-wrap, .loc-stop-wrap { background: none; border: 0; }
.loc-pin { position: relative; width: 40px; height: 40px; display: flex; align-items: center; justify-content: center; border-radius: 999px; background: #fff; border: 3px solid var(--c, #e4002b); box-shadow: 0 2px 8px rgba(0,0,0,.35); font-size: 20px; }
.loc-arrow { position: absolute; left: 50%; top: 50%; width: 0; height: 0; margin: 0; pointer-events: none; }
.loc-arrow::before { content: ""; position: absolute; left: -6px; top: -33px; border-left: 6px solid transparent; border-right: 6px solid transparent; border-bottom: 11px solid var(--c, #e4002b); }
.loc-dot { width: 14px; height: 14px; border-radius: 999px; border: 3px solid #fff; box-shadow: 0 1px 4px rgba(0,0,0,.4); }
.loc-dot.start { background: #22c55e; }
.loc-stop { width: 24px; height: 24px; border-radius: 999px; background: #f59e0b; color: #fff; display: flex; align-items: center; justify-content: center; font-size: 12px; font-weight: 700; border: 2px solid #fff; box-shadow: 0 1px 4px rgba(0,0,0,.4); }
:root[data-theme="dark"] .leaflet-tile-pane { filter: invert(1) hue-rotate(180deg) brightness(0.92) contrast(0.9); }
.leaflet-container { font: inherit; }

/* Right-hand cluster in the top bar of every page: countdown, "sharing" reminder, Booster.
   A shared flex wrapper (gap, not each badge's own margin) so a hidden badge takes no space
   and never leaves an uneven gap next to whichever badge is actually showing. */
.shell-topbar-badges { margin-left: auto; display: flex; align-items: center; gap: 0.5rem; }
.countdown-badge { display: inline-flex; align-items: center; gap: 0.375rem; padding: 0.375rem 0.875rem; border-radius: 999px; background: var(--surface-2); color: var(--text); font-size: 1rem; font-weight: 700; }
.loc-badge { display: inline-flex; align-items: center; gap: 0.25rem; padding: 0.1875rem 0.625rem; border-radius: 999px; background: color-mix(in srgb, var(--danger) 14%, transparent); color: var(--danger); font-size: 0.75rem; font-weight: 600; text-decoration: none; }
.loc-badge[hidden] { display: none; }

/* six nav items on a phone */
@media (max-width: 767px) {
  .bottom-nav-item { padding-left: 0.375rem; padding-right: 0.375rem; min-width: 0; }
}

/* Location → phone-app set-up card */
.loc-device .label { margin: 0 0 0.25rem; font-weight: 600; }
.loc-steps { margin: 0.5rem 0; padding-left: 1.25rem; display: flex; flex-direction: column; gap: 0.5rem; font-size: 0.875rem; }
.loc-steps a { text-decoration: underline; }
.loc-url { width: 100%; margin-top: 0.25rem; padding: 0.375rem 0.5rem; border: 1px solid var(--border); border-radius: 0.375rem; background: var(--surface-2); color: var(--text); font-size: 12px; }
.loc-btn.danger { color: var(--danger); }
.loc-actions { flex-wrap: wrap; }

/* ============================================================
   Phones: the menu is a tab bar at the bottom, always visible
   (no hamburger / slide-out menu). Desktop keeps its sidebar.
   ============================================================ */
@media (max-width: 767px) {
  .bottom-nav { display: flex; }
  .nav-toggle-btn { display: none; }

  /* The top bar is hidden by default on phones (the tab bar covers navigation) —
     it only reappears for something that belongs there: sharing location, Booster,
     or the countdown badge. */
  .shell-topbar { display: none; }
  .loc-on .shell-topbar,
  .countdown-on .shell-topbar { display: flex; }

  /* Every page fills the screen; the content area scrolls above the tab bar. */
  .settings-body .app-shell,
  .profile-body .app-shell {
    height: var(--app-h, 100dvh);
    min-height: 0;
    overflow: hidden;
  }
  .settings-body, .profile-body { overflow: hidden; }
  .settings-body .page-content,
  .profile-body .page-content { overflow-y: auto; -webkit-overflow-scrolling: touch; overscroll-behavior: contain; }

  /* The tab bar already clears the home indicator; the composer sits above it. */
  .composer { padding-bottom: 0.5rem; }
  .bottom-nav { padding-bottom: max(0.375rem, env(safe-area-inset-bottom)); }

  /* Keyboard up: give the room back to the text field. */
  .kbd-open .bottom-nav { display: none; }
  .kbd-open .composer { padding-bottom: max(0.5rem, env(safe-area-inset-bottom)); }
}

/* Chat title bar status, every screen size: just "online" or "today at 9:05 PM"
   (no name, no "last seen"). */
.xl-titlebar .xl-title { min-width: 0; }
.xl-titlebar-who { display: block; }
.xl-titlebar-who .name { display: none; }
.xl-titlebar-who .status { font-size: 12px; color: rgba(255, 255, 255, 0.9); }

/* ============================================================
   Calls
   ============================================================ */
.xl-call-btn { display: flex; align-items: center; justify-content: center; gap: 0.375rem; height: 2.25rem; min-width: 2.25rem; padding: 0 0.5rem; border-radius: 999px; background: #fff; color: var(--xl-green-dark); font-size: 0.8125rem; font-weight: 600; box-shadow: 0 1px 3px rgba(0,0,0,0.3); }
.xl-call-btn:hover { background: #e8f5ee; }
.xl-call-btn .lbl { display: none; }
@media (min-width: 640px) { .xl-call-btn { padding: 0 0.875rem; } .xl-call-btn .lbl { display: inline; } }

.call-overlay { position: fixed; inset: 0; z-index: 200; background: #0b0d12; color: #fff; display: flex; flex-direction: column; align-items: center; justify-content: center; padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left); }
.call-overlay[hidden] { display: none; }
.call-remote { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; background: #000; display: none; }
.call-overlay.is-video.has-remote-video .call-remote { display: block; }
.call-local { position: absolute; top: max(0.75rem, env(safe-area-inset-top)); right: 0.75rem; width: 28vw; max-width: 9rem; min-width: 5.5rem; aspect-ratio: 3 / 4; object-fit: cover; border-radius: 0.75rem; border: 2px solid rgba(255,255,255,0.7); background: #222; display: none; transform: scaleX(-1); z-index: 2; }
.call-overlay.is-video .call-local { display: block; }
.call-info { position: relative; z-index: 1; display: flex; flex-direction: column; align-items: center; gap: 0.5rem; text-shadow: 0 1px 6px rgba(0,0,0,0.6); margin-bottom: 4rem; }
.call-overlay.is-video.has-remote-video .call-info { position: absolute; top: max(1rem, env(safe-area-inset-top)); left: 1rem; margin: 0; align-items: flex-start; }
.call-overlay.is-video.has-remote-video .call-avatar { display: none; }
.call-avatar { width: 7rem; height: 7rem; border-radius: 999px; display: flex; align-items: center; justify-content: center; font-size: 3.5rem; }
.call-name { font-size: 1.5rem; font-weight: 600; }
.call-status { font-size: 1rem; opacity: 0.85; font-variant-numeric: tabular-nums; }
.call-actions { position: absolute; left: 0; right: 0; bottom: max(1.5rem, env(safe-area-inset-bottom)); z-index: 3; display: flex; flex-wrap: wrap; justify-content: center; gap: 1rem; padding: 0 1rem; }
.call-btn { display: flex; flex-direction: column; align-items: center; gap: 0.375rem; min-width: 4.5rem; color: #fff; font-size: 0.75rem; text-shadow: 0 1px 4px rgba(0,0,0,0.6); }
.call-btn .ic { display: flex; align-items: center; justify-content: center; width: 3.75rem; height: 3.75rem; border-radius: 999px; background: rgba(255,255,255,0.18); font-size: 1.5rem; backdrop-filter: blur(6px); }
.call-btn.red .ic { background: #ef4444; }
.call-btn.green .ic { background: #22c55e; }
.call-btn.grey .ic { background: rgba(255,255,255,0.28); }
.call-btn.on .ic { background: #fff; color: #111; }
.in-call body { overflow: hidden; }
@media (max-width: 767px) {
  .xl-titlebar-right { gap: 0.375rem; }
}
.xl-titlebar > img { flex-shrink: 0; }

/* Call records in the chat */
.xl-call-log { display: flex; align-items: center; gap: 0.625rem; width: fit-content; max-width: min(85%, 26rem); margin: 0.375rem 0.75rem; padding: 0.5rem 0.75rem; border: 1px solid var(--border); border-radius: 0.75rem; background: var(--surface-2); color: var(--text); }
.xl-call-log.msg-mine { margin-left: auto; }
.xl-call-log.msg-theirs { margin-right: auto; }
.xl-call-log .ic { flex: 0 0 auto; font-size: 1.125rem; }
.xl-call-log .txt { flex: 1; min-width: 0; display: flex; flex-direction: column; font-size: 0.9em; }
.xl-call-log .txt b { font-weight: 600; }
.xl-call-log .txt small { color: var(--text-muted); font-size: 0.85em; }
.xl-call-log .t { flex: 0 0 auto; font-size: 0.75em; color: var(--text-muted); white-space: nowrap; }
.call-sub { font-size: 0.9375rem; opacity: 0.9; text-align: center; }
/* Links inside messages */
.msg-text, .search-result .snippet { overflow-wrap: anywhere; }
.msg-link { color: var(--accent); text-decoration: underline; text-underline-offset: 2px; cursor: pointer; }
.msg-link:hover { text-decoration-thickness: 2px; }
@media (max-width: 767px) { .msg-link { padding: 0.125rem 0; } } /* a slightly bigger target for a thumb */
/* Booster */
.xl-booster-btn { display: inline-flex; align-items: center; gap: 0.375rem; height: 2rem; padding: 0 0.75rem; border: 1px solid var(--border); border-radius: 999px; background: var(--surface); color: var(--text); font-size: 0.8125rem; font-weight: 600; white-space: nowrap; }
.xl-booster-btn .bolt { opacity: 0.55; }
.xl-booster-btn .tm { font-variant-numeric: tabular-nums; }
.xl-booster-btn.on { background: #f59e0b; border-color: #d97706; color: #1f1300; box-shadow: 0 0 0 3px rgba(245, 158, 11, 0.25); }
.xl-booster-btn.on .bolt { opacity: 1; }
.booster-badge { display: inline-flex; align-items: center; gap: 0.25rem; padding: 0.1875rem 0.625rem; border-radius: 999px; background: #f59e0b; color: #1f1300; border: 0; font-size: 0.75rem; font-weight: 700; font-variant-numeric: tabular-nums; cursor: pointer; }
.booster-badge[hidden] { display: none; }
@media (max-width: 767px) {
  .booster-on .shell-topbar { display: flex; }
  .xl-booster-btn .lbl { display: none; }       /* phones: just ⚡ and the countdown */
  .xl-booster-btn:not(.on) .lbl { display: inline; }
}
/* Partner's online / last-seen time on the password screens */
.partner-line { display: flex; align-items: center; gap: 0.5rem; margin: 0 0 0.625rem; padding: 0.375rem 0.625rem; border: 1px solid #c8cdd3; border-radius: 4px; background: #f3f5f7; color: #3b4148; font-size: 13px; }
.partner-line[hidden] { display: none; }
.partner-line .pdot { flex: 0 0 auto; width: 9px; height: 9px; border-radius: 999px; background: #9aa3ab; }
.partner-line.online .pdot { background: #22c55e; box-shadow: 0 0 0 3px rgba(34, 197, 94, 0.25); }
.partner-line .ptxt { font-weight: 600; font-variant-numeric: tabular-nums; }
.time-input { padding: 0.25rem 0.375rem; border: 1px solid var(--border); border-radius: 0.375rem; background: var(--surface-2); color: var(--text); font-size: 16px; }

/* Booster choices */
.booster-choices { margin: 0 0 0.625rem; }
.booster-choices .desc { margin: 0 0 0.375rem; font-size: 13px; color: #3b4148; }
.seg { display: flex; gap: 0.375rem; margin-bottom: 0.5rem; }
.seg-btn { flex: 1; padding: 0.375rem 0.25rem; border: 1px solid #767676; background: #fff; color: #1a1a1a; font-size: 14px; }
.seg-btn.active { background: #e4002b; border-color: #e4002b; color: #fff; font-weight: 600; }
.check-row { display: flex; align-items: flex-start; gap: 0.5rem; font-size: 13px; color: #3b4148; }
.check-row input { margin-top: 0.1875rem; width: 1rem; height: 1rem; }
.session-row .loc-link { margin-top: 0.25rem; align-self: flex-start; }
/* ---------- Face ID / fingerprint ---------- */
.bio-row { margin-top: 0.5rem; text-align: center; }
.bio-btn { width: 100%; padding: 0.5rem; border: 1px solid #767676; background: #fff; color: #1a1a1a; font-size: 14px; cursor: pointer; }
.bio-btn:disabled { opacity: 0.6; }
.bio-item { display: flex; flex-wrap: wrap; align-items: center; gap: 0.25rem 0.75rem; }

/* ---------- Test my phone ---------- */
.pt-row { display: flex; align-items: flex-start; gap: 0.625rem; padding: 0.625rem 0; border-bottom: 1px solid var(--border); }
.pt-row:last-child { border-bottom: 0; }
.pt-icon { width: 1.5rem; text-align: center; flex: none; font-size: 16px; line-height: 1.4; }
.pt-main { flex: 1; min-width: 0; }
.pt-main p { margin: 0; }
.pt-help { font-size: 12px; }
.pt-result { font-size: 13px; margin-top: 0.125rem !important; overflow-wrap: anywhere; }
.pt-row[data-state="bad"] .pt-result { color: var(--danger); }
.pt-row[data-state="warn"] .pt-result { color: #9a6700; }
.pt-one { flex: none; padding: 0.25rem 0.5rem; }
#pt-summary[data-state="bad"] { color: var(--danger); font-weight: 600; }
#pt-summary[data-state="ok"] { color: #e4002b; font-weight: 600; }

/* ---------- call connection indicator + call back ---------- */
.call-quality { margin-top: 0.375rem; font-size: 0.8125rem; opacity: 0.95; }
.call-quality[data-level="good"] { color: #7ee2a0; }
.call-quality[data-level="fair"] { color: #ffd166; }
.call-quality[data-level="poor"], .call-quality[data-level="reconnecting"] { color: #ff8a80; }
.call-quality[data-level="reconnecting"] { animation: pc-blink 1.2s ease-in-out infinite; }
@keyframes pc-blink { 50% { opacity: 0.45; } }
.xl-call-log .callback { flex: 0 0 auto; border: 1px solid var(--border); background: var(--surface); color: var(--accent, #e4002b); border-radius: 999px; padding: 0.25rem 0.625rem; font-size: 0.8125rem; font-weight: 600; cursor: pointer; }
.xl-call-log .callback:active { background: var(--surface-2); }

/* ---------- voice notes ---------- */
.voice-bar { display: flex; align-items: center; gap: 0.625rem; padding: 0.375rem 0.625rem; border-top: 1px solid var(--border); background: var(--surface); }
.voice-bar[hidden] { display: none; }
.voice-dot { width: 0.625rem; height: 0.625rem; border-radius: 50%; background: #d93025; animation: pc-blink 1.2s ease-in-out infinite; }
.voice-time { font-variant-numeric: tabular-nums; font-weight: 600; min-width: 2.75rem; }
.voice-hint { flex: 1; color: var(--text-muted); font-size: 0.875em; }
.msg-media-inline-link { display: block; border: 0; background: none; padding: 0; margin: 0; font: inherit; text-align: left; }
.msg-media-inline { display: block; max-width: min(16rem, 62vw); max-height: 18rem; width: 100%; border-radius: 0.625rem; margin-bottom: 0.25rem; object-fit: cover; background: var(--surface-2); }
.msg-media-inline-link .msg-media-inline { cursor: zoom-in; }

/* ---------- chat photo popup (tap a photo in Chat — plain, no zoom/nav) ---------- */
.chat-media-lightbox {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
  background: rgba(6, 8, 15, 0.9);
  cursor: zoom-out;
  animation: pc-lightbox-in 0.15s ease-out;
}
.chat-media-lightbox img {
  max-width: 100%;
  max-height: 100%;
  border-radius: 0.5rem;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
}
@keyframes pc-lightbox-in {
  from { opacity: 0; }
  to { opacity: 1; }
}
.msg-voice { display: flex; align-items: center; gap: 0.5rem; max-width: 100%; }
.msg-voice audio { height: 2rem; max-width: min(15rem, 62vw); }
.msg-voice .dur { color: var(--text-muted); font-size: 0.75em; font-variant-numeric: tabular-nums; }

/* ---------- location: timed sharing, places, pins ---------- */
.loc-len { display: block; margin-top: 0.375rem; font-size: 0.875em; }
.loc-len select, .loc-place-form select, .loc-place-form input[type="text"], .loc-place-form input:not([type]) { font: inherit; padding: 0.25rem 0.375rem; border: 1px solid #767676; background: #fff; color: #1a1a1a; max-width: 100%; }
.loc-until { margin-top: 0.375rem; }
.loc-place-row { display: flex; flex-wrap: wrap; align-items: center; gap: 0.25rem 0.75rem; padding: 0.375rem 0; border-bottom: 1px solid var(--border); }
.loc-place-notify { font-size: 0.8125em; display: inline-flex; align-items: center; gap: 0.25rem; }
.loc-place-form { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem; margin-top: 0.5rem; }
.loc-place-form input:not([type]) { flex: 1 1 10rem; min-width: 0; }
.loc-place-tag { transform: translate(-50%, -50%); white-space: nowrap; background: #e4002b; color: #fff; font-size: 11px; padding: 1px 6px; border-radius: 8px; }
.xl-pin-log .callback { text-decoration: none; display: inline-block; }
.gallery-tile-missing { flex-direction: column; gap: 0.25rem; color: var(--text-muted); }
.gallery-tile-missing span { background: none; width: auto; height: auto; font-size: 1.75rem; color: inherit; }
.gallery-tile-missing small { font-size: 0.6875rem; }
.lightbox-restore { display: inline-block; margin-top: 0.75rem; padding: 0.5rem 1rem; border: 0; border-radius: 999px; background: #e4002b; color: #fff; font-weight: 600; font-size: 0.875rem; cursor: pointer; }
.lightbox-restore:disabled { opacity: 0.7; }
#lightbox-caption .lightbox-restore { display: block; margin: 0.5rem auto 0; }

/* ---------- location: Life360-style people list ---------- */
.loc-members { padding: 0.25rem; gap: 0; }
.loc-member { display: flex; align-items: center; gap: 0.75rem; width: 100%; padding: 0.625rem 0.5rem; border: 0; border-radius: 0.625rem; background: none; color: var(--text); text-align: left; cursor: pointer; }
.loc-member + .loc-member { border-top: 1px solid var(--border); border-radius: 0 0 0.625rem 0.625rem; }
.loc-member.active { background: var(--surface-2); }
.loc-avatar { position: relative; flex: 0 0 auto; display: flex; align-items: center; justify-content: center; width: 2.75rem; height: 2.75rem; border-radius: 999px; background: #fff; border: 3px solid var(--c, #e4002b); font-size: 1.375rem; }
.loc-avatar.live::after { content: ""; position: absolute; right: -2px; bottom: -2px; width: 0.75rem; height: 0.75rem; border-radius: 999px; background: #22c55e; border: 2px solid var(--surface); }
.loc-member-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; line-height: 1.3; }
.loc-member-txt b { font-size: 0.9375rem; }
.loc-member-txt span { font-size: 0.875rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.loc-member-txt small { color: var(--text-muted); font-size: 0.75rem; }
.loc-batt { flex: 0 0 auto; padding: 0.125rem 0.5rem; border: 1px solid var(--border); border-radius: 999px; font-size: 0.75rem; font-variant-numeric: tabular-nums; color: var(--text-muted); }
.loc-batt.low { color: #fff; background: var(--danger, #d93025); border-color: transparent; }
.loc-stale { margin: 0.25rem 0.5rem 0.375rem; padding: 0.5rem 0.625rem; border-radius: 0.5rem; background: rgba(245, 158, 11, 0.12); }
.loc-btn.primary { background: #e4002b; border-color: #e4002b; color: #fff; font-weight: 600; }
.loc-pin.live::before { content: ""; position: absolute; inset: -3px; border-radius: 999px; border: 3px solid var(--c, #e4002b); animation: loc-pulse 1.8s ease-out infinite; }
@keyframes loc-pulse { from { transform: scale(1); opacity: 0.7; } to { transform: scale(2); opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .loc-pin.live::before { animation: none; } }
.loc-gate { display: flex; flex-direction: column; align-items: center; gap: 0.5rem; padding: 1.25rem 1rem; text-align: center; }
.loc-gate-ic { font-size: 2rem; }
.loc-gate .loc-btn { margin-top: 0.25rem; }
.loc-days { display: flex; flex: 0 0 auto; gap: 0.375rem; overflow-x: auto; padding-bottom: 0.125rem; }
.loc-daychip { flex: 0 0 auto; padding: 0.375rem 0.75rem; border: 1px solid var(--border); border-radius: 999px; background: var(--surface); color: var(--text); font-size: 0.8125rem; white-space: nowrap; }
.loc-daychip.active { background: var(--accent); border-color: var(--accent); color: var(--accent-contrast); }

/* ---------- location required (whole app) ---------- */
.app-shell.loc-required .shell-body-inner { pointer-events: none; user-select: none; filter: blur(40px); transform: scale(1.05); }
.loc-gate-overlay { display: none; position: absolute; inset: 0; z-index: 45; align-items: center; justify-content: center; padding: 1rem; background: rgba(15, 16, 22, 0.45); }
.app-shell.loc-required .loc-gate-overlay { display: flex; }
.loc-gate-card { width: 100%; max-width: 22rem; padding: 1.5rem 1.25rem; border-radius: 1rem; background: var(--surface); color: var(--text); text-align: center; box-shadow: 0 12px 40px rgba(0, 0, 0, 0.35); display: flex; flex-direction: column; gap: 0.625rem; }
.loc-gate-card h2 { margin: 0; font-size: 1.25rem; }
.loc-gate-card p { margin: 0; font-size: 0.9375rem; line-height: 1.45; color: var(--text-muted); }
.loc-gate-card .field-error { color: var(--danger, #d93025); font-size: 0.8125rem; text-align: left; }
.loc-gate-ic { font-size: 2.5rem; line-height: 1; }
.loc-gate-btn { min-height: 2.875rem; border: 0; border-radius: 0.75rem; background: #e4002b; color: #fff; font-size: 1rem; font-weight: 600; cursor: pointer; }
.loc-gate-btn:disabled { opacity: 0.7; }
.loc-gate-out { border: 0; background: none; color: var(--text-muted); font-size: 0.8125rem; text-decoration: underline; cursor: pointer; }


/* ============================================================
   Astro-style theme: deep-blue backdrop + white card + red action,
   shared by the login page and the in-app lock screen popup.
   ============================================================ */
.login-body {
  display: block;
  padding: 0;
  min-height: 100vh;
  color: #fff;
  background: radial-gradient(1200px 600px at 50% -10%, #24408f 0%, #0b1a3a 55%, #060d21 100%);
  background-attachment: fixed;
}
.astro-login { flex-direction: column; gap: 1.5rem; }
.astro-brand {
  color: #fff;
  font-family: "Segoe UI", Helvetica, Arial, sans-serif;
  font-size: 2.5rem;
  font-weight: 800;
  letter-spacing: -0.02em;
  text-transform: lowercase;
}
.astro-brand span { color: #ff2d55; font-weight: 600; }

/* The lock-screen popup (any page while locked) gets the same navy backdrop. */
.lock-overlay {
  background: radial-gradient(1200px 600px at 50% -10%, #24408f 0%, #0b1a3a 55%, #060d21 100%) !important;
}

.login-body .excel-password-card,
.lock-overlay .excel-password-card {
  max-width: 380px;
  border: 0;
  border-radius: 16px;
  box-shadow: 0 24px 60px rgba(0, 0, 0, 0.5);
  font-family: "Segoe UI", Helvetica, Arial, sans-serif;
}
.login-body .excel-password-titlebar,
.lock-overlay .excel-password-titlebar {
  display: none;
}
.login-body .excel-password-body,
.lock-overlay .excel-password-body {
  padding: 1.25rem;
  background: #fff;
  border-radius: 16px;
}
.login-body .lock-badge,
.lock-overlay .lock-badge { background: #e8edfa; }
.login-body .excel-password-body input.pc-secret,
.lock-overlay .excel-password-body input.pc-secret {
  border: 1.5px solid #c9d1e6;
  border-radius: 10px;
  padding: 0.65rem 0.8rem;
  font-size: 15px;
}
.login-body .excel-password-body input.pc-secret:focus,
.lock-overlay .excel-password-body input.pc-secret:focus { border-color: #e4002b; }
.login-body .btn-ok,
.lock-overlay .btn-ok {
  width: 100%;
  border: 0;
  border-radius: 999px;
  background: #e4002b;
  padding: 0.7rem 1rem;
  font-size: 15px;
  font-weight: 700;
}
.login-body .btn-ok:hover,
.lock-overlay .btn-ok:hover { background: #b80022; }
.login-body .excel-password-actions,
.lock-overlay .excel-password-actions { justify-content: stretch; }
.login-body input.ax-email,
.lock-overlay input.ax-email { -webkit-text-security: none; text-security: none; }

/* Login layout: top bar, hero with copy on the left and the card on the right */
.ax-top { background: rgba(6, 13, 33, 0.85); border-bottom: 1px solid rgba(255, 255, 255, 0.12); }
.ax-top-in { max-width: 1120px; margin: 0 auto; padding: 0.9rem 1.25rem; display: flex; align-items: center; justify-content: space-between; }
.ax-top .astro-brand { font-size: 1.6rem; }
.ax-nav { display: flex; gap: 1.5rem; font-size: 0.9rem; }
.ax-nav a { color: rgba(255, 255, 255, 0.85); cursor: default; }
.ax-hero { min-height: calc(100vh - 120px); display: flex; align-items: center; }
.ax-hero-in { max-width: 1120px; width: 100%; margin: 0 auto; padding: 2rem 1.25rem; display: grid; grid-template-columns: 1.1fr 0.9fr; gap: 3rem; align-items: center; }
.ax-kicker { margin: 0 0 0.5rem; color: #ff2d55; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; font-size: 0.8rem; }
.ax-copy h1 { margin: 0; font-size: clamp(2rem, 5vw, 3.4rem); line-height: 1.05; font-weight: 800; }
.ax-tag { margin: 1rem 0 1.25rem; font-size: 1.1rem; color: rgba(255, 255, 255, 0.85); }
.ax-list { list-style: none; margin: 0 0 1.5rem; padding: 0; display: grid; gap: 0.6rem; }
.ax-list li { padding-left: 1.75rem; position: relative; }
.ax-list li::before { content: "\2713"; position: absolute; left: 0; top: 0; width: 1.2rem; height: 1.2rem; border-radius: 50%; background: #e4002b; font-size: 0.75rem; line-height: 1.2rem; text-align: center; }
.ax-dots { display: flex; gap: 0.4rem; }
.ax-dots i { width: 0.5rem; height: 0.5rem; border-radius: 50%; background: rgba(255, 255, 255, 0.35); }
.ax-dots i.on { background: #fff; width: 1.4rem; border-radius: 99px; }
.ax-login { display: flex; justify-content: center; }
.ax-login #auth-root { width: 100%; display: flex; justify-content: center; }
.ax-foot { text-align: center; padding: 1rem; font-size: 0.8rem; color: rgba(255, 255, 255, 0.55); }
@media (max-width: 820px) {
  .ax-hero-in { grid-template-columns: 1fr; gap: 1.75rem; }
  .ax-nav { display: none; }
}

/* ============================================================
   App-wide refinement: richer Astro red/navy theme across the
   whole system (sidebar, nav, cards, buttons, badges, inputs).
   The spreadsheet-disguise message grid in chat.php is left as
   plain as before on purpose — everything around it gets the
   polish instead.
   ============================================================ */
:root {
  --brand-navy: #0b1a3a;
  --brand-navy-2: #152a5c;
  --accent-grad: linear-gradient(135deg, #ff3b57 0%, #e4002b 60%, #b80022 100%);
  --shadow-accent: 0 8px 20px rgba(228, 0, 43, 0.28);
  --bg: #f3f4fa;
}
:root[data-theme="dark"] {
  --accent-grad: linear-gradient(135deg, #ff7389 0%, #ff4d6d 55%, #e0264a 100%);
  --shadow-accent: 0 8px 22px rgba(255, 77, 109, 0.32);
}

/* ---- Brand sidebar rail: carries the login page's navy identity
   through the whole app, so chrome stays recognisably "Astro Cloud"
   on every page without re-skinning the message grid itself. ---- */
.shell-sidebar {
  background: radial-gradient(900px 480px at 15% -10%, var(--brand-navy-2) 0%, var(--brand-navy) 55%, #060d21 100%);
  border-right: 0;
  box-shadow: inset -1px 0 0 rgba(255, 255, 255, 0.06);
}
.shell-brand {
  padding: 1.375rem 1.25rem 1rem;
}
.shell-brand span {
  color: #fff;
  font-weight: 700;
  letter-spacing: -0.01em;
}
.shell-other {
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.08);
}
.shell-other .shell-name { color: #fff; }
.shell-sidebar .shell-sub { color: rgba(255, 255, 255, 0.55); }
.shell-nav-item { color: rgba(255, 255, 255, 0.72); }
.shell-nav-item:hover {
  background: rgba(255, 255, 255, 0.08);
  color: #fff;
}
.shell-nav-item.active {
  background: var(--accent-grad);
  color: #fff;
  box-shadow: var(--shadow-accent);
}
.shell-footer { border-top: 1px solid rgba(255, 255, 255, 0.1); }
.shell-sidebar .shell-me .shell-name { color: #fff; }
.shell-sidebar .shell-logout { color: rgba(255, 255, 255, 0.65); }
.shell-sidebar .shell-logout:hover {
  background: rgba(239, 68, 68, 0.18);
  color: #ff8080;
}

/* ---- Top bar: subtle depth so it reads as its own layer. ---- */
.shell-topbar {
  box-shadow: 0 1px 0 var(--border), 0 2px 8px rgba(15, 16, 22, 0.04);
}
.nav-toggle-btn:hover { color: var(--accent); }

/* ---- Bottom nav (mobile): active tab gets a soft pill + icon lift. ---- */
.bottom-nav-item.active {
  color: var(--accent);
}
.bottom-nav-item.active .nav-icon {
  transform: translateY(-1px);
  filter: drop-shadow(0 2px 6px rgba(228, 0, 43, 0.35));
}
.bottom-nav-item .nav-icon { transition: transform 0.15s, filter 0.15s; }

/* ---- Badges ---- */
.countdown-badge {
  background: color-mix(in srgb, var(--accent) 10%, var(--surface-2));
  border: 1px solid color-mix(in srgb, var(--accent) 25%, transparent);
}

/* ---- Cards: settings / profile / identity / location, a touch more
   lift and a hover state so the whole system feels consistent. ---- */
.settings-section,
.profile-card,
.loc-card,
.identity-card {
  border-radius: 1rem;
  box-shadow: var(--shadow-sm);
  transition: box-shadow 0.2s, transform 0.2s;
}
.identity-card { box-shadow: var(--shadow-md); }
.identity-btn:hover {
  box-shadow: var(--shadow-sm);
  transform: translateY(-1px);
}

/* ---- Buttons: primary actions get the brand gradient + glow. ---- */
.btn-ok {
  background: var(--accent-grad);
  box-shadow: var(--shadow-accent);
  transition: transform 0.15s, box-shadow 0.15s, filter 0.15s;
}
.btn-ok:hover:not(:disabled) {
  filter: brightness(1.06);
  transform: translateY(-1px);
}
.loc-gate-btn,
.loc-btn.primary {
  background: var(--accent-grad) !important;
  box-shadow: var(--shadow-accent);
  border: 0 !important;
}

/* ---- Toggles / tabs / chips: gradient instead of flat fill. ---- */
.toggle.on { background: var(--accent-grad); }
.loc-tab.active,
.seg-btn.active {
  background: var(--accent-grad) !important;
  border-color: transparent !important;
  box-shadow: var(--shadow-accent);
}
.gallery-tab.active { box-shadow: var(--shadow-sm), 0 0 0 1px var(--border) inset; }
.search-tag-chip.active {
  background: color-mix(in srgb, var(--accent) 16%, transparent);
  box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent) 30%, transparent) inset;
}

/* ---- Inputs: soft focus glow in the brand colour. ---- */
.search-input-wrap input:focus,
.excel-password-body input.pc-secret:focus {
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent);
}

/* ---- Gallery tiles: gentle zoom + shadow on hover for a livelier grid. ---- */
.gallery-tile {
  transition: box-shadow 0.2s, transform 0.2s;
}
.gallery-tile:hover {
  box-shadow: var(--shadow-md);
}
.gallery-tile:hover img,
.gallery-tile:hover video {
  transform: scale(1.04);
}
.gallery-tile img,
.gallery-tile video {
  transition: transform 0.25s ease-out;
}

/* ---- Thin accent scrollbars where supported (progressive enhancement). ---- */
@supports (scrollbar-color: auto) {
  .shell-main, .gallery-scroll, .search-results, .settings-page, .profile-page {
    scrollbar-color: color-mix(in srgb, var(--accent) 45%, var(--border)) transparent;
    scrollbar-width: thin;
  }
}

/* No green "online" dots anywhere — being online is shown as the text
   "Now - editing" instead (title bar, lock screen, sidebar, profile). */
.presence-dot,
.partner-line .pdot { display: none; }

/* ============================================================
   Call screen (voice + video): refreshed layout. Later rules override
   the earlier .call-* ones; the markup/ids in call.js are unchanged.
   ============================================================ */
.call-overlay {
  background: radial-gradient(1100px 700px at 50% 18%, #24408f 0%, #0b1a3a 52%, #060d21 100%);
  overflow: hidden;
}
.call-info { gap: 0.375rem; margin-bottom: 7rem; text-align: center; }
.call-avatar {
  position: relative;
  width: 8.5rem; height: 8.5rem; font-size: 4rem;
  border: 3px solid rgba(255, 255, 255, 0.35);
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.45);
}
/* Soft rings pulse out while it is ringing / connecting, then stop once you're talking. */
.call-overlay[data-phase="calling"] .call-avatar::after,
.call-overlay[data-phase="ringing"] .call-avatar::after,
.call-overlay[data-phase="connecting"] .call-avatar::after {
  content: ""; position: absolute; inset: -3px; border-radius: 999px;
  border: 2px solid rgba(255, 255, 255, 0.55);
  animation: call-pulse 1.8s ease-out infinite;
}
.call-overlay[data-phase="calling"] .call-avatar::before,
.call-overlay[data-phase="ringing"] .call-avatar::before,
.call-overlay[data-phase="connecting"] .call-avatar::before {
  content: ""; position: absolute; inset: -3px; border-radius: 999px;
  border: 2px solid rgba(255, 255, 255, 0.4);
  animation: call-pulse 1.8s ease-out 0.9s infinite;
}
@keyframes call-pulse {
  from { transform: scale(1); opacity: 0.9; }
  to { transform: scale(1.7); opacity: 0; }
}
.call-name { font-size: 1.75rem; font-weight: 700; letter-spacing: -0.01em; margin-top: 0.5rem; }
.call-sub { font-size: 0.9375rem; opacity: 0.75; }
.call-status { font-size: 1.25rem; font-weight: 600; opacity: 0.95; font-variant-numeric: tabular-nums; margin-top: 0.125rem; }
.call-overlay[data-phase="live"] .call-status { font-size: 1.5rem; letter-spacing: 0.02em; }

/* Connection badge as a small pill. */
.call-quality {
  display: inline-flex; align-items: center; gap: 0.25rem;
  margin-top: 0.5rem; padding: 0.25rem 0.75rem; border-radius: 999px;
  background: rgba(0, 0, 0, 0.35); font-size: 0.8125rem; font-weight: 600;
  -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
}
.call-quality[hidden] { display: none; }

/* Reconnecting: a clear banner over the call, not just a small badge. */
.call-overlay.is-reconnecting::after {
  content: "Reconnecting\2026  your call is being kept alive";
  position: absolute; z-index: 6;
  top: max(0.75rem, env(safe-area-inset-top)); left: 50%; transform: translateX(-50%);
  max-width: calc(100% - 1.5rem); text-align: center;
  padding: 0.5rem 1rem; border-radius: 999px;
  background: #b45309; color: #fff; font-size: 0.8125rem; font-weight: 600;
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4);
  animation: pc-blink 1.4s ease-in-out infinite;
}

/* Control dock: one frosted pill with round buttons, thumb-friendly at the bottom. */
.call-actions {
  left: 50%; right: auto; transform: translateX(-50%);
  width: max-content; max-width: calc(100% - 1.25rem);
  flex-wrap: nowrap; gap: 0.5rem;
  padding: 0.75rem 0.875rem;
  background: rgba(14, 20, 40, 0.55);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 2rem;
  -webkit-backdrop-filter: blur(18px); backdrop-filter: blur(18px);
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.4);
}
.call-actions:empty { display: none; }
.call-btn { min-width: 0; width: 4.25rem; gap: 0.3125rem; font-size: 0.6875rem; font-weight: 500; transition: transform 0.12s; }
.call-btn:active { transform: scale(0.94); }
.call-btn .ic { width: 3.25rem; height: 3.25rem; font-size: 1.375rem; background: rgba(255, 255, 255, 0.16); transition: background 0.15s; }
.call-btn.red .ic { background: linear-gradient(135deg, #ff5a6e, #e4002b); box-shadow: 0 6px 18px rgba(228, 0, 43, 0.5); }
.call-btn.green .ic { background: linear-gradient(135deg, #34d399, #16a34a); box-shadow: 0 6px 18px rgba(22, 163, 74, 0.5); }
.call-overlay[data-phase="calling"] .call-actions,
.call-overlay[data-phase="ringing"] .call-actions { gap: 2.25rem; padding: 0.875rem 1.75rem; }
.call-overlay[data-phase="calling"] .call-btn .ic,
.call-overlay[data-phase="ringing"] .call-btn .ic { width: 4.25rem; height: 4.25rem; font-size: 1.75rem; }
.call-overlay[data-phase="calling"] .call-btn,
.call-overlay[data-phase="ringing"] .call-btn { width: 5rem; font-size: 0.75rem; }
/* Answer pulses so it is the obvious thing to press. */
.call-overlay[data-phase="ringing"] .call-btn.green .ic { animation: call-answer 1.4s ease-in-out infinite; }
@keyframes call-answer {
  0%, 100% { box-shadow: 0 6px 18px rgba(22, 163, 74, 0.5), 0 0 0 0 rgba(52, 211, 153, 0.6); }
  50% { box-shadow: 0 6px 18px rgba(22, 163, 74, 0.5), 0 0 0 14px rgba(52, 211, 153, 0); }
}

/* Your own picture: small rounded window with a shadow; hidden when your camera is off. */
.call-local {
  border-radius: 1rem; border: 2px solid rgba(255, 255, 255, 0.85);
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.5);
  top: max(1rem, env(safe-area-inset-top)); right: 1rem;
}
.call-overlay.cam-off .call-local { display: none; }
/* In a video call, a soft shade behind the top and bottom so text and buttons stay readable. */
.call-overlay.is-video.has-remote-video::before {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(rgba(0, 0, 0, 0.45), transparent 22%, transparent 70%, rgba(0, 0, 0, 0.55));
}
.call-overlay.is-video.has-remote-video .call-info { z-index: 2; }
.call-overlay.is-video.has-remote-video .call-name { font-size: 1.25rem; margin-top: 0; }

/* Phones held sideways / short windows: smaller avatar, dock stays on screen. */
@media (max-height: 520px) {
  .call-info { margin-bottom: 4.5rem; }
  .call-avatar { width: 4.5rem; height: 4.5rem; font-size: 2.25rem; }
  .call-name { font-size: 1.25rem; margin-top: 0.25rem; }
  .call-btn .ic { width: 2.75rem; height: 2.75rem; font-size: 1.125rem; }
  .call-overlay[data-phase="calling"] .call-btn .ic,
  .call-overlay[data-phase="ringing"] .call-btn .ic { width: 3.25rem; height: 3.25rem; font-size: 1.375rem; }
  .call-actions { bottom: max(0.625rem, env(safe-area-inset-bottom)); padding: 0.5rem 0.75rem; }
}
@media (prefers-reduced-motion: reduce) {
  .call-overlay .call-avatar::before, .call-overlay .call-avatar::after,
  .call-overlay .call-btn.green .ic, .call-overlay.is-reconnecting::after { animation: none; }
}
