/* Loci control center — design tokens + base components.
   Source: Claude Design project "Loci web control center design"
   (Loci Control Center.dc.html), Block 6 build-order step 9.
   Palette/type choices are the design's, not invented here — see that
   project for the full rationale (calm/unhurried over clever, cool
   neutral base, periwinkle-indigo accent for actions/trust, warm
   terracotta reserved for memory/connection moments). */

:root {
  --bg: oklch(0.975 0.004 250);
  --surface: oklch(0.995 0.002 250);
  --surface-2: oklch(0.955 0.006 250);
  --border: oklch(0.89 0.008 250);
  --border-strong: oklch(0.78 0.01 250);
  --text: oklch(0.24 0.014 258);
  --text-muted: oklch(0.48 0.012 258);
  --text-faint: oklch(0.65 0.01 258);
  --accent: oklch(0.62 0.09 258);
  --accent-hover: oklch(0.56 0.095 258);
  --accent-contrast: oklch(0.99 0 0);
  --accent-soft: oklch(0.94 0.025 258);
  --warm: oklch(0.64 0.09 45);
  --warm-soft: oklch(0.94 0.035 55);
  --success: oklch(0.58 0.08 150);
  --success-soft: oklch(0.94 0.04 150);
  --danger: oklch(0.58 0.1 25);
  --danger-soft: oklch(0.94 0.04 25);
  --shadow: 0 16px 40px oklch(0.3 0.02 258 / 0.16);
  color-scheme: light dark;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: oklch(0.20 0.012 258);
    --surface: oklch(0.245 0.013 258);
    --surface-2: oklch(0.29 0.014 258);
    --border: oklch(0.34 0.015 258);
    --border-strong: oklch(0.42 0.016 258);
    --text: oklch(0.94 0.006 258);
    --text-muted: oklch(0.72 0.012 258);
    --text-faint: oklch(0.55 0.012 258);
    --accent: oklch(0.72 0.09 258);
    --accent-hover: oklch(0.78 0.09 258);
    --accent-contrast: oklch(0.16 0.02 258);
    --accent-soft: oklch(0.32 0.04 258);
    --warm: oklch(0.74 0.09 50);
    --warm-soft: oklch(0.34 0.045 50);
    --success: oklch(0.70 0.09 150);
    --success-soft: oklch(0.30 0.045 150);
    --danger: oklch(0.68 0.1 25);
    --danger-soft: oklch(0.32 0.05 25);
    --shadow: 0 16px 40px oklch(0 0 0 / 0.45);
  }
}

/* Manual override wins over the OS preference either direction — set by
   the theme toggle in Settings (a cookie read server-side into
   data-theme, no client JS required). */
:root[data-theme="dark"] {
  --bg: oklch(0.20 0.012 258);
  --surface: oklch(0.245 0.013 258);
  --surface-2: oklch(0.29 0.014 258);
  --border: oklch(0.34 0.015 258);
  --border-strong: oklch(0.42 0.016 258);
  --text: oklch(0.94 0.006 258);
  --text-muted: oklch(0.72 0.012 258);
  --text-faint: oklch(0.55 0.012 258);
  --accent: oklch(0.72 0.09 258);
  --accent-hover: oklch(0.78 0.09 258);
  --accent-contrast: oklch(0.16 0.02 258);
  --accent-soft: oklch(0.32 0.04 258);
  --warm: oklch(0.74 0.09 50);
  --warm-soft: oklch(0.34 0.045 50);
  --success: oklch(0.70 0.09 150);
  --success-soft: oklch(0.30 0.045 150);
  --danger: oklch(0.68 0.1 25);
  --danger-soft: oklch(0.32 0.05 25);
  --shadow: 0 16px 40px oklch(0 0 0 / 0.45);
}
:root[data-theme="light"] {
  --bg: oklch(0.975 0.004 250);
  --surface: oklch(0.995 0.002 250);
  --surface-2: oklch(0.955 0.006 250);
  --border: oklch(0.89 0.008 250);
  --border-strong: oklch(0.78 0.01 250);
  --text: oklch(0.24 0.014 258);
  --text-muted: oklch(0.48 0.012 258);
  --text-faint: oklch(0.65 0.01 258);
  --accent: oklch(0.62 0.09 258);
  --accent-hover: oklch(0.56 0.095 258);
  --accent-contrast: oklch(0.99 0 0);
  --accent-soft: oklch(0.94 0.025 258);
  --warm: oklch(0.64 0.09 45);
  --warm-soft: oklch(0.94 0.035 55);
  --success: oklch(0.58 0.08 150);
  --success-soft: oklch(0.94 0.04 150);
  --danger: oklch(0.58 0.1 25);
  --danger-soft: oklch(0.94 0.04 25);
  --shadow: 0 16px 40px oklch(0.3 0.02 258 / 0.16);
}

* { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: 'Public Sans', -apple-system, system-ui, sans-serif;
  font-size: 14px;
  -webkit-font-smoothing: antialiased;
}

a { color: inherit; }

h1, h2, h3, .display {
  font-family: 'Manrope', sans-serif;
  font-weight: 700;
  margin: 0;
}

.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: 11px;
  padding: 20px 22px;
}

.field-label {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--text-muted);
  margin-bottom: 5px;
  display: block;
}

.field-input {
  box-sizing: border-box;
  width: 100%;
  background: var(--surface);
  border: 1.5px solid var(--border);
  border-radius: 8px;
  padding: 11px 13px;
  font-size: 14px;
  font-family: 'Public Sans', sans-serif;
  color: var(--text);
}
.field-input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px oklch(0.62 0.09 258 / 0.15);
}
.field-input.field-error {
  border-color: var(--danger);
}

.btn {
  border: none;
  border-radius: 8px;
  padding: 11px 20px;
  font-size: 14px;
  font-weight: 600;
  font-family: 'Public Sans', sans-serif;
  cursor: pointer;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.btn-primary { background: var(--accent); color: var(--accent-contrast); }
.btn-primary:hover { background: var(--accent-hover); }
.btn-secondary { background: transparent; color: var(--accent); border: 1.5px solid var(--accent); padding: 9.5px 20px; }
.btn-secondary:hover { background: var(--accent-soft); }
.btn-ghost { background: transparent; color: var(--text-muted); }
.btn-ghost:hover { background: var(--surface-2); }
.btn-danger { background: transparent; color: var(--danger); border: 1.5px solid var(--danger); padding: 9.5px 14px; }
.btn-danger:hover { background: var(--danger-soft); }
.btn-block { width: 100%; }
.btn:disabled { background: var(--surface-2); color: var(--text-faint); cursor: not-allowed; }

.badge {
  font-size: 11.5px;
  font-weight: 600;
  padding: 4px 10px;
  border-radius: 100px;
  white-space: nowrap;
}
.badge-verified { background: var(--success-soft); color: var(--success); }
.badge-pending { background: var(--warm-soft); color: var(--warm); }
.badge-rejected { background: var(--danger-soft); color: var(--danger); }

.error-banner {
  background: var(--danger-soft);
  border: 1px solid var(--border-strong);
  border-radius: 10px;
  padding: 12px 14px;
  font-size: 13px;
  color: var(--danger);
}
.error-banner a { color: var(--danger); font-weight: 600; }

.otp-boxes { display: flex; gap: 7px; }
.otp-boxes input {
  width: 38px;
  height: 44px;
  border: 1.5px solid var(--border);
  border-radius: 8px;
  text-align: center;
  font-size: 17px;
  font-weight: 600;
  color: var(--text);
  background: var(--bg);
}

/* Pre-auth centered-card layout (login/signup/request-access/rejected) */
.auth-shell {
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.auth-card { width: 100%; max-width: 360px; }
.auth-mark { display: flex; justify-content: center; margin-bottom: 10px; }
.auth-title { font-size: 30px; text-align: center; color: var(--text); margin-bottom: 6px; }
.auth-subtitle { font-family: 'Manrope', sans-serif; font-weight: 600; font-size: 15px; text-align: center; color: var(--text-muted); margin-bottom: 32px; }
.auth-divider { display: flex; align-items: center; gap: 10px; margin: 18px 0; }
.auth-divider .line { flex: 1; height: 1px; background: var(--border); }
.auth-divider span { font-size: 11.5px; color: var(--text-faint); }
.auth-footer { font-size: 13.5px; color: var(--text-muted); text-align: center; margin-top: 4px; }
.auth-footer a { color: var(--accent); font-weight: 600; text-decoration: none; }

/* Authenticated shell: fixed sidebar + content.
   Responsive: one breakpoint at 840px (mirrored in app.js as BP). Below
   it the 240px sidebar becomes an off-canvas drawer behind a sticky top
   bar; above it nothing changes. Layout adapts to viewport width only —
   there is no server-side device detection. The mobile overrides live in
   one @media block further down ("Mobile shell"), not scattered here. */
:root {
  --content-px: 40px;
  --content-py: 36px;
  --topbar-h: 0px;
}

.app-shell { display: flex; min-height: 100vh; }

/* Mobile-only chrome — inert (display:none) at desktop width. */
.app-topbar, .app-scrim, .drawer-close { display: none; }
.sidebar {
  width: 240px;
  flex: none;
  background: var(--surface-2);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  padding: 24px 16px;
  position: sticky;
  top: 0;
  height: 100vh;
}
.sidebar-brand { display: flex; align-items: center; gap: 8px; padding: 4px 8px 28px; }
.sidebar-brand span { font-family: 'Manrope', sans-serif; font-weight: 700; font-size: 19px; color: var(--text); }
.sidebar-nav { display: flex; flex-direction: column; gap: 2px; }
.sidebar-link {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 12px; border-radius: 9px;
  text-decoration: none; font-size: 14px; font-weight: 500;
  color: var(--text-muted);
}
.sidebar-link:hover { background: var(--surface); }
.sidebar-link.active { background: var(--accent-soft); color: var(--accent); font-weight: 600; }
.sidebar-link.admin.active { background: var(--warm-soft); color: var(--warm); }
.sidebar-divider { height: 1px; background: var(--border); margin: 12px 4px; }
.sidebar-spacer { flex: 1; }
.sidebar-user {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 8px; border-top: 1px solid var(--border); margin-top: 8px;
}
.sidebar-user-initials {
  width: 28px; height: 28px; border-radius: 50%;
  background: var(--accent-soft); color: var(--accent);
  display: flex; align-items: center; justify-content: center;
  font-size: 12px; font-weight: 600; flex: none;
}
.sidebar-user-name { font-size: 13px; color: var(--text); font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sidebar-user-signout { font-size: 11.5px; color: var(--text-faint); background: none; border: none; padding: 0; cursor: pointer; font-family: inherit; }

.content { flex: 1; padding: var(--content-py) var(--content-px); overflow: auto; position: relative; }
.content-header { margin-bottom: 26px; }
.content-header .subtitle { font-size: 13.5px; color: var(--text-muted); margin-top: 4px; }

.section-eyebrow {
  font-size: 12px; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase;
  color: var(--text-faint); margin-bottom: 10px;
}

/* ============================================================
   Mobile shell (max-width: 840px) — keep BP in sync with app.js.
   Sidebar -> off-canvas drawer + sticky top bar. See BACKLOG
   "Web app is not mobile-optimized" and the mobile build plan.
   ============================================================ */
@media (max-width: 840px) {
  :root {
    --content-px: 16px;
    --content-py: 20px;
    --topbar-h: 52px;
  }

  /* top bar */
  .app-topbar {
    display: flex;
    align-items: center;
    gap: 10px;
    height: var(--topbar-h);
    padding: 0 10px 0 4px;
    position: sticky;
    top: 0;
    z-index: 30;
    background: var(--surface);
    border-bottom: 1px solid var(--border);
  }
  .app-topbar-menu {
    flex: none;
    width: 40px; height: 40px;
    display: flex; align-items: center; justify-content: center;
    background: none; border: none; border-radius: 9px;
    color: var(--text); cursor: pointer;
  }
  .app-topbar-menu:hover { background: var(--surface-2); }
  .app-topbar-brand { flex: none; display: flex; padding-left: 8px; }
  .app-topbar-title {
    flex: 1; min-width: 0;
    font-family: 'Manrope', sans-serif; font-weight: 700; font-size: 17px;
    color: var(--text);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  }
  .app-topbar-login { font-size: 13.5px; font-weight: 600; color: var(--accent); text-decoration: none; flex: none; }

  /* shell + content */
  .app-shell { display: block; min-height: 0; }
  .content { min-height: calc(100dvh - var(--topbar-h)); }

  /* the top bar already names the page */
  .page-h1 { display: none; }

  /* sidebar -> drawer */
  .sidebar {
    position: fixed;
    top: 0; bottom: 0; left: 0;
    width: min(82%, 320px);
    height: 100%;
    z-index: 50;
    background: var(--surface);
    border-right: 1px solid var(--border);
    padding: 18px 14px;
    transform: translateX(-100%);
    transition: transform 0.22s ease;
    box-shadow: 8px 0 32px oklch(0.1 0.01 258 / 0.28);
  }
  body.drawer-open { overflow: hidden; }
  body.drawer-open .sidebar { transform: none; }

  .sidebar-brand { padding: 6px 8px 18px; }
  .drawer-close {
    display: flex; align-items: center; justify-content: center;
    margin-left: auto;
    width: 32px; height: 32px;
    background: none; border: none; border-radius: 8px;
    color: var(--text-muted); cursor: pointer;
  }
  .drawer-close:hover { background: var(--surface-2); color: var(--text); }

  /* touch-sized nav rows */
  .sidebar-link { padding: 13px 12px; font-size: 15px; min-height: 48px; box-sizing: border-box; }

  .app-scrim {
    display: block;
    position: fixed; inset: 0; z-index: 40;
    background: oklch(0.12 0.01 258 / 0.45);
    opacity: 0; pointer-events: none;
    transition: opacity 0.22s ease;
  }
  body.drawer-open .app-scrim { opacity: 1; pointer-events: auto; }
}

@media (max-width: 840px) and (prefers-reduced-motion: reduce) {
  .sidebar, .app-scrim { transition: none; }
}

.modal-backdrop {
  position: fixed; inset: 0; background: oklch(0.1 0.01 258 / 0.35);
  display: flex; align-items: center; justify-content: center; z-index: 20;
}
.modal-card { background: var(--surface); border: 1px solid var(--border); border-radius: 14px; padding: 28px 32px; width: 360px; box-shadow: var(--shadow); }

.fact-group { border: 1px solid var(--border); border-radius: 11px; margin-bottom: 12px; overflow: hidden; }
/* overflow:hidden above clips the header's background to the rounded
   corners, but it also clips the Edit/Forget/Wipe popovers whenever they
   overflow the card's bottom edge (found 2026-08-14: the Wipe confirm on
   a fact near the bottom of a card rendered half cut-off). Relax it back
   to visible only while a popover inside is actually open, so the normal
   rounded-corner clipping is unaffected the rest of the time. */
.fact-group:has(details[open]) { overflow: visible; }
.fact-group-header { display: flex; align-items: center; gap: 10px; padding: 15px 18px; background: var(--surface); cursor: pointer; list-style: none; }
.fact-group-header::-webkit-details-marker { display: none; }
.fact-group-chevron { flex: none; color: var(--text-faint); transition: transform 0.15s ease; }
.fact-group[open] .fact-group-chevron { transform: rotate(90deg); }

.profile-search { position: relative; margin-bottom: 18px; }
.profile-search input { width: 100%; box-sizing: border-box; background: var(--surface); border: 1.5px solid var(--border); border-radius: 10px; padding: 11px 40px 11px 40px; font-size: 13.5px; font-family: 'Public Sans', sans-serif; color: var(--text); }
.profile-search input:focus { outline: none; border-color: var(--accent); }
.profile-search .search-icon { position: absolute; left: 14px; top: 50%; transform: translateY(-50%); color: var(--text-faint); pointer-events: none; }
.profile-search-clear { position: absolute; right: 8px; top: 50%; transform: translateY(-50%); background: none; border: none; cursor: pointer; color: var(--text-faint); font-size: 16px; line-height: 1; padding: 6px 8px; display: none; }
.profile-search-clear.visible { display: block; }
.profile-search-clear:hover { color: var(--text); }

.people-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 12px; }
.person-card {
  display: flex; align-items: center; gap: 12px; padding: 16px 18px;
  background: var(--surface); border: 1px solid var(--border); border-radius: 11px;
  text-decoration: none; color: inherit; transition: border-color 0.12s ease, box-shadow 0.12s ease;
}
.person-card:hover { border-color: var(--accent); box-shadow: var(--shadow); }
.person-card-avatar {
  width: 34px; height: 34px; border-radius: 50%; flex: none;
  background: var(--accent-soft); color: var(--accent);
  display: flex; align-items: center; justify-content: center;
  font-size: 12.5px; font-weight: 700; font-family: 'Manrope', sans-serif;
}
.person-card-name { font-size: 14px; font-weight: 700; color: var(--text); }
.person-card-meta { font-size: 12px; color: var(--text-faint); margin-top: 1px; }
.person-card-count { margin-left: auto; font-size: 11.5px; color: var(--text-faint); white-space: nowrap; flex: none; }

.search-results-header { font-size: 12.5px; color: var(--text-muted); margin-bottom: 12px; }
.search-result-row { display: flex; align-items: center; gap: 12px; padding: 11px 15px; border: 1px solid var(--border); border-radius: 9px; margin-bottom: 8px; background: var(--surface); }
.search-result-text { flex: 1; font-size: 13.5px; color: var(--text); }
.search-result-meta { font-size: 11px; color: var(--text-faint); white-space: nowrap; }
/* Search results have no hover-reveal ancestor (.fact-row) the way the
   grouped view does — actions stay visible outright rather than only on
   hover, since a search result is usually the one thing being looked at. */
.search-result-row .fact-actions { opacity: 1; }
.search-result-empty { text-align: center; padding: 28px; color: var(--text-faint); font-size: 13px; }
.fact-group-title { font-size: 14.5px; font-weight: 600; color: var(--text); flex: 1; }
.fact-group-count { font-size: 11.5px; color: var(--text-faint); background: var(--surface-2); padding: 3px 9px; border-radius: 100px; }
.fact-sub-label { font-size: 12px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: var(--text-faint); margin: 10px 0 8px 24px; }
.fact-thread { display: flex; flex-direction: column; position: relative; padding-left: 24px; }
.fact-thread::before { content: ""; position: absolute; left: 3.5px; top: 6px; bottom: 6px; width: 1px; background: var(--border); }
.fact-row { display: flex; align-items: center; gap: 12px; padding: 9px 10px; border-radius: 8px; position: relative; }
/* Hover-reveal is desktop only — on touch the actions are reached by
   tapping the row (.is-open, added by app.js); see the mobile @media
   block. Guarding the hover keeps a lingering touch-hover from flashing
   the controls. */
@media (hover: hover) {
  .fact-row:hover { background: var(--surface-2); }
  .fact-row:hover .fact-actions { opacity: 1; }
}
.fact-text { flex: 1; font-size: 13.5px; color: var(--text); }
.fact-date { font-size: 11.5px; color: var(--text-faint); }
.fact-actions { display: flex; gap: 10px; opacity: 0; }
.fact-actions summary, .fact-actions button { all: unset; cursor: pointer; font-size: 12px; color: var(--text-muted); }
.fact-actions summary:hover, .fact-actions button:hover { color: var(--accent); }
.fact-actions .delete-trigger:hover { color: var(--danger); }
.fact-actions summary::-webkit-details-marker { display: none; }
details.fact-edit, details.fact-delete { position: relative; }
.fact-edit-popover, .fact-delete-popover {
  position: absolute; top: 100%; right: 0; z-index: 20; margin-top: 6px; box-shadow: var(--shadow);
}
.fact-edit-popover {
  width: 260px; padding: 12px 14px; border: 1px solid var(--border); border-radius: 10px; background: var(--surface);
  display: flex; flex-direction: column; gap: 8px;
}
.fact-edit-popover textarea {
  min-height: 64px; font: inherit; color: inherit; background: var(--bg);
  border: 1px solid var(--border); border-radius: 6px; padding: 8px; resize: vertical;
}
.fact-delete-popover {
  padding: 10px 12px; border: 1px solid var(--danger); border-radius: 10px; background: var(--surface);
  display: flex; align-items: center; gap: 10px; font-size: 13px; white-space: nowrap;
}
/* Wipe's sibling checklist (2026-08-14): a multi-line list of checkboxes
   instead of the single-line "Confirm?" text, so needs its own layout —
   wraps normally and picks a fixed width rather than growing to fit
   whatever the longest sibling statement happens to be. */
.fact-delete-popover.has-siblings {
  flex-direction: column; align-items: stretch; white-space: normal; width: 280px;
}
.fact-delete-popover .sibling-list { display: flex; flex-direction: column; gap: 6px; }
.fact-delete-popover .sibling-option {
  display: flex; align-items: flex-start; gap: 6px; font-size: 12.5px; font-weight: 400; color: var(--text);
}
.fact-delete-popover .sibling-option input { margin-top: 3px; flex: none; }

.channel-row { display: flex; align-items: center; gap: 14px; background: var(--surface); border: 1px solid var(--border); border-radius: 11px; padding: 16px 18px; }
.channel-row.unlinked { border-style: dashed; border-color: var(--border-strong); }
.channel-icon { width: 36px; height: 36px; border-radius: 9px; display: flex; align-items: center; justify-content: center; flex: none; }
.channel-name { font-size: 14px; font-weight: 600; color: var(--text); }
.channel-detail { font-size: 12.5px; color: var(--text-faint); }

.chat-log { flex: 1; padding: 28px 40px; display: flex; flex-direction: column; gap: 16px; overflow: auto; }
.chat-bubble { max-width: min(460px, 78%); padding: 12px 16px; border-radius: 14px; font-size: 14px; line-height: 1.5; white-space: pre-wrap; word-wrap: break-word; overflow-wrap: anywhere; }
.chat-bubble.user { align-self: flex-end; background: var(--accent); color: var(--accent-contrast); border-radius: 14px 14px 3px 14px; }
.chat-bubble.loci { align-self: flex-start; background: var(--surface); border: 1px solid var(--border); color: var(--text); border-radius: 14px 14px 14px 3px; }
.chat-input-row { padding: 20px 32px 26px; border-top: 1px solid var(--border); display: flex; gap: 10px; }
.chat-input-row input { flex: 1; box-sizing: border-box; background: var(--surface); border: 1.5px solid var(--border); border-radius: 22px; padding: 12px 18px; font-size: 14px; font-family: 'Public Sans', sans-serif; color: var(--text); }
.chat-send { width: 44px; height: 44px; border-radius: 50%; background: var(--accent); border: none; display: flex; align-items: center; justify-content: center; cursor: pointer; flex: none; }
.chat-send:hover { background: var(--accent-hover); }
.chat-send:disabled { background: var(--surface-2); cursor: default; }

.chat-bubble.thinking { display: flex; gap: 4px; align-items: center; padding: 14px 16px; }
.chat-bubble.thinking span { width: 6px; height: 6px; border-radius: 50%; background: var(--text-faint); animation: chat-thinking 1.1s infinite ease-in-out; }
.chat-bubble.thinking span:nth-child(2) { animation-delay: 0.15s; }
.chat-bubble.thinking span:nth-child(3) { animation-delay: 0.3s; }
@keyframes chat-thinking { 0%, 60%, 100% { opacity: 0.3; transform: translateY(0); } 30% { opacity: 1; transform: translateY(-2px); } }
@media (prefers-reduced-motion: reduce) { .chat-bubble.thinking span { animation: none; opacity: 0.6; } }

.account-facts { gap: 48px; }
.settings-tabs { display: inline-flex; gap: 3px; padding: 4px; background: var(--surface-2); border: 1px solid var(--border); border-radius: 12px; margin-bottom: 26px; }
.settings-tab { padding: 9px 22px; border-radius: 9px; font-size: 13.5px; font-weight: 600; color: var(--text-faint); text-decoration: none; transition: background 0.12s ease, color 0.12s ease; }
.settings-tab:hover { color: var(--text-muted); }
.settings-tab.active { background: var(--surface); color: var(--text); font-weight: 700; box-shadow: 0 1px 3px oklch(0.3 0.02 258 / 0.12); }

/* Notifications tab (2026-09-01) — one form, one card per proactive
   feature, each headed by a toggle switch. Every option is a whole-row
   <label> so the text is clickable, not just the tiny control. A card's
   details collapse into .pref-body via a grid-rows trick, independent of
   the switch: turning the switch on expands them, turning it off forces
   them shut, but a card left on can still be collapsed by its own chevron
   (server-rendered initial state, flipped live by app.js — purely visual,
   the server never reads either state). */
.pref-card { margin-bottom: 14px; }
.pref-card-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }
.pref-card-title { font-size: 14px; font-weight: 700; color: var(--text); margin-bottom: 3px; }
.pref-sub-title { font-size: 13.5px; font-weight: 700; color: var(--text); margin-bottom: 2px; }
.pref-card-help { font-size: 12.5px; color: var(--text-muted); margin-bottom: 6px; }
.pref-lock { font-size: 12.5px; color: var(--warm); margin-top: 2px; }
.pref-sub { padding: 12px 0 4px; border-top: 1px solid var(--border); }
.pref-card-controls { display: flex; align-items: center; gap: 10px; }
.pref-expand-toggle { display: flex; align-items: center; justify-content: center; width: 26px; height: 26px; margin-top: 2px; padding: 0; border: none; border-radius: 7px; background: none; color: var(--text-faint); cursor: pointer; transition: background 0.12s ease; }
.pref-expand-toggle:hover:not(:disabled) { background: var(--surface-2); }
.pref-expand-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.pref-expand-toggle svg { transition: transform 0.2s cubic-bezier(.4,0,.2,1), color 0.15s ease; }
.pref-expand-toggle[aria-expanded="true"] svg { transform: rotate(180deg); color: var(--accent); }
.pref-expand-toggle:disabled { opacity: 0.35; cursor: default; }
.pref-body { display: grid; grid-template-rows: 0fr; transition: grid-template-rows 0.22s cubic-bezier(.4,0,.2,1); }
.pref-body.is-expanded { grid-template-rows: 1fr; }
.pref-body-inner { overflow: hidden; }
.pref-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; margin-top: 10px; }
.pref-grid .field-input { padding: 9px 11px; font-size: 13.5px; }
.pref-radios { display: flex; gap: 14px; align-items: center; min-height: 38px; }
.pref-option { display: flex; align-items: flex-start; gap: 12px; padding: 9px 0; border-top: 1px solid var(--border); cursor: pointer; }
.pref-option input { margin: 3px 0 0; flex: none; accent-color: var(--accent); }
.pref-option-name { display: block; font-size: 13.5px; font-weight: 600; color: var(--text); }
.pref-option-detail { display: block; font-size: 12.5px; color: var(--text-muted); margin-top: 2px; }
.pref-option-detail a { color: var(--accent); font-weight: 600; }
.pref-option.disabled { opacity: 0.55; cursor: default; }
.pref-channel { display: flex; flex-wrap: wrap; align-items: center; gap: 16px; margin-top: 12px; padding-top: 12px; border-top: 1px solid var(--border); }
.pref-channel-label { font-size: 12.5px; font-weight: 600; color: var(--text-muted); }
.pref-inline { display: inline-flex; align-items: center; gap: 6px; font-size: 13px; font-weight: 600; color: var(--text); cursor: pointer; }
.pref-inline input { margin: 0; accent-color: var(--accent); }
.pref-inline.disabled { opacity: 0.5; cursor: default; }

/* Toggle switch — a plain checkbox, visually a track + knob. Uses the
   theme tokens rather than accent-color so it reads the same in light
   and dark. */
.switch { position: relative; display: inline-block; width: 40px; height: 22px; flex: none; margin-top: 2px; }
.switch input { position: absolute; opacity: 0; width: 0; height: 0; }
.switch-track { position: absolute; inset: 0; background: var(--border-strong); border-radius: 22px; cursor: pointer; transition: background 0.15s ease; }
.switch-track::after { content: ""; position: absolute; top: 3px; left: 3px; width: 16px; height: 16px; border-radius: 50%; background: var(--surface); box-shadow: 0 1px 2px oklch(0.3 0.02 258 / 0.3); transition: transform 0.15s ease; }
.switch input:checked + .switch-track { background: var(--accent); }
.switch input:checked + .switch-track::after { transform: translateX(18px); }
.switch input:focus-visible + .switch-track { box-shadow: 0 0 0 3px oklch(0.62 0.09 258 / 0.25); }
.switch input:disabled + .switch-track { opacity: 0.4; cursor: not-allowed; }

/* Day-of-week chips — checkboxes styled as pills. */
.day-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 6px; }
.pill { position: relative; }
.pill input { position: absolute; opacity: 0; width: 0; height: 0; }
.pill span { display: inline-block; padding: 6px 11px; border: 1px solid var(--border); border-radius: 999px; font-size: 12.5px; font-weight: 600; color: var(--text-muted); cursor: pointer; user-select: none; }
.pill input:checked + span { background: var(--accent); border-color: var(--accent); color: var(--accent-contrast); }
.pill input:focus-visible + span { box-shadow: 0 0 0 3px oklch(0.62 0.09 258 / 0.25); }

.change-password-toggle summary { list-style: none; }
.change-password-toggle summary::-webkit-details-marker { display: none; }
.change-password-toggle .fields { margin-top: 16px; }

.channel-type-group { border: 1px solid var(--border); border-radius: 11px; margin-bottom: 14px; overflow: hidden; }
/* Same clipping issue as .fact-group above — the Unlink confirm popover
   can overflow this card's bottom edge too. */
.channel-type-group:has(details[open]) { overflow: visible; }
.channel-type-header { padding: 13px 18px; background: var(--surface-2); font-size: 12.5px; font-weight: 700; letter-spacing: 0.02em; color: var(--text-muted); text-transform: uppercase; }
.channel-type-body { padding: 4px 0; }
.channel-type-body .channel-row { border: none; border-radius: 0; border-bottom: 1px solid var(--border); }
.channel-type-body .channel-row:last-child { border-bottom: none; }
.add-another-row { padding: 12px 18px; }

.legal-doc .page { max-width: 680px; margin: 0; padding: 0; color: var(--text); font-family: 'Public Sans', sans-serif; line-height: 1.65; }
.legal-doc .eyebrow { font-size: 12px; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase; color: var(--accent); margin: 0 0 8px; }
.legal-doc h1 { font-family: 'Manrope', sans-serif; font-weight: 700; font-size: 26px; margin: 0 0 6px; text-wrap: balance; color: var(--text); }
.legal-doc .meta { color: var(--text-faint); font-size: 12.5px; margin: 0 0 28px; }
.legal-doc .toc { background: var(--surface); border: 1px solid var(--border); border-radius: 11px; padding: 18px 22px; margin-bottom: 32px; }
.legal-doc .toc-label { font-size: 11px; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase; color: var(--text-faint); margin: 0 0 12px; }
.legal-doc .toc ol { margin: 0; padding-left: 20px; columns: 2; column-gap: 24px; }
.legal-doc .toc li { margin-bottom: 6px; font-size: 13px; }
.legal-doc .toc a { color: var(--text); text-decoration: none; border-bottom: 1px solid var(--border); }
.legal-doc .toc a:hover { border-bottom-color: var(--accent); color: var(--accent); }
@media (max-width: 560px) { .legal-doc .toc ol { columns: 1; } }
.legal-doc section { margin-bottom: 28px; scroll-margin-top: 20px; }
.legal-doc h2 { font-family: 'Manrope', sans-serif; font-weight: 700; font-size: 16px; margin: 0 0 10px; display: flex; align-items: baseline; gap: 8px; color: var(--text); }
.legal-doc h2 .num { font-size: 12px; font-weight: 600; color: var(--accent); }
.legal-doc p { margin: 0 0 10px; max-width: 62ch; font-size: 13.5px; color: var(--text-muted); }
.legal-doc ul { margin: 0 0 10px; padding-left: 20px; max-width: 62ch; font-size: 13.5px; color: var(--text-muted); }
.legal-doc li { margin-bottom: 5px; }
.legal-doc strong { font-weight: 600; color: var(--text); }
.legal-doc a.inline { color: var(--accent); }
.legal-doc footer { border-top: 1px solid var(--border); padding-top: 16px; margin-top: 32px; font-size: 12.5px; color: var(--text-faint); }
.legal-doc footer a { color: var(--text-muted); }

.admin-table { border: 1px solid var(--border); border-radius: 11px; overflow: hidden; }
.admin-table-header { display: flex; padding: 12px 20px; background: var(--surface-2); font-size: 11.5px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; color: var(--text-faint); }
.admin-table-row { display: flex; align-items: center; padding: 14px 20px; border-top: 1px solid var(--border); }

/* Tasks & Calendar tab (2026-08-28). Source: Claude Design project
   "Loci web control center design" (Tasks and Calendar.dc.html). Phase 1
   is the Tasks list; the Calendar views (Phase 2) will add to this block. */
.tc-subtabs { display: flex; gap: 24px; border-bottom: 1px solid var(--border); margin: 18px 0 26px; }
.tc-subtab { padding: 0 2px 11px; font-size: 14px; color: var(--text-muted); text-decoration: none; }
.tc-subtab.active { font-weight: 600; color: var(--text); box-shadow: inset 0 -2px 0 var(--accent); }
.tc-subtab.disabled { color: var(--text-faint); cursor: not-allowed; }

.tc-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 14px; margin-bottom: 18px; flex-wrap: wrap; }
.tc-toolbar-left { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.tc-search { display: flex; align-items: center; gap: 9px; width: 320px; max-width: 100%; background: var(--surface); border: 1px solid var(--border); border-radius: 7px; padding: 8px 12px; }
.tc-search:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px oklch(0.62 0.09 258 / 0.1); }
.tc-search-icon { color: var(--text-faint); flex: none; }
.tc-search input { flex: 1; min-width: 0; border: none; background: none; outline: none; font-family: inherit; font-size: 13.5px; color: var(--text); }
.tc-search-clear { color: var(--text-faint); text-decoration: none; font-size: 15px; line-height: 1; padding: 0 2px; }
.tc-search-clear:hover { color: var(--text); }
.tc-count { font-size: 13px; color: var(--text-muted); }

.tc-pills { display: flex; gap: 8px; }
.tc-pill { display: flex; align-items: center; gap: 7px; font-size: 13px; color: var(--text-muted); border: 1px solid var(--border); background: var(--surface); border-radius: 999px; padding: 6px 12px; text-decoration: none; }
.tc-pill:hover { border-color: var(--border-strong); }
.tc-pill.active { color: var(--accent); border-color: var(--accent); background: var(--accent-soft); }
.tc-pill-dot { width: 7px; height: 7px; border-radius: 999px; background: var(--border-strong); flex: none; }
.tc-pill.active .tc-pill-dot { background: var(--accent); }

.tc-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; align-items: start; }
.tc-group { background: var(--surface); border: 1px solid var(--border); border-radius: 10px; padding-bottom: 6px; }
.tc-group-header { display: flex; align-items: baseline; gap: 10px; padding: 16px 24px 10px; }
.tc-group-name { font-size: 12px; font-weight: 600; letter-spacing: 0.07em; text-transform: uppercase; color: var(--text-faint); }
.tc-group-count { font-size: 12px; color: var(--text-faint); }

.task-row { display: flex; align-items: center; gap: 14px; padding: 11px 24px; border-top: 1px solid var(--surface-2); }
/* .task-main is a passthrough on desktop (children lay out in .task-row's
   flow); it becomes a real swipe surface only in the mobile @media block.
   .task-nr is the swipe-revealed "Not relevant" button — mobile only. */
.task-main { display: contents; }
.task-nr { display: none; }
.task-checkbox { width: 17px; height: 17px; flex: none; margin: 0; accent-color: var(--accent); cursor: pointer; }
.task-checkbox.placeholder { border: 1.5px dashed var(--border-strong); border-radius: 4.5px; box-sizing: border-box; }
.task-row.done .task-checkbox { accent-color: var(--success); }
.task-dismiss { width: 19px; height: 19px; flex: none; border: none; background: none; border-radius: 5px; display: flex; align-items: center; justify-content: center; color: var(--text-faint); cursor: pointer; padding: 0; }
.task-dismiss:hover { color: var(--danger); background: var(--danger-soft); }
.task-text { flex: 1; min-width: 0; font-size: 14.5px; line-height: 1.45; color: var(--text); }
.task-row.done .task-text { text-decoration: line-through; color: var(--text-faint); }
.task-row.dismissed .task-text { color: var(--text-faint); }
.task-text mark { background: var(--warm-soft); color: inherit; border-radius: 3px; padding: 0 2px; }
.task-tag { font-size: 11.5px; letter-spacing: 0.04em; text-transform: uppercase; color: var(--text-faint); border: 1px solid var(--border); border-radius: 999px; padding: 2px 9px; flex: none; }

.tc-link { font-size: 12.5px; color: var(--text-faint); background: none; border: none; border-bottom: 1px solid var(--border-strong); padding: 0 0 1px; cursor: pointer; font-family: inherit; text-decoration: none; }
.tc-link:hover { color: var(--accent); border-bottom-color: var(--accent); }

.tc-save-row { display: flex; align-items: center; gap: 16px; margin-top: 20px; flex-wrap: wrap; }
.tc-save-hint { font-size: 13px; color: var(--text-faint); }

.tc-empty { background: var(--surface); border: 1px solid var(--border); border-radius: 10px; padding: 56px 40px; text-align: center; }
.tc-empty-icon { width: 34px; height: 34px; margin: 0 auto 16px; border-radius: 999px; border: 1.5px solid var(--success); display: flex; align-items: center; justify-content: center; }
.tc-empty-title { font-size: 16px; font-weight: 600; margin-bottom: 6px; color: var(--text); }
.tc-empty-body { font-size: 14px; color: var(--text-muted); line-height: 1.55; max-width: 380px; margin: 0 auto; }
.tc-empty-body a { color: var(--accent); }

@media (max-width: 900px) {
  .tc-grid { grid-template-columns: 1fr; }
  .tc-toolbar { align-items: stretch; }
}

/* --- Phase 2: Calendar month / week / day (2026-08-29) --------------
   Source: Tasks and Calendar.dc.html §1c/1f/1g. Geometry constants
   (56px/hr, 116px cell, 340px panel) mirror calendar_viewmodel.py —
   PX_PER_HOUR there must equal --tc-hour-h here. */

.tc-cal-toolbar { display: flex; align-items: center; justify-content: space-between; gap: 14px; margin-bottom: 16px; flex-wrap: wrap; }
.tc-cal-navwrap { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; }
.tc-nav { display: flex; align-items: stretch; border: 1px solid var(--border); background: var(--surface); border-radius: 7px; overflow: hidden; }
.tc-nav a { display: flex; align-items: center; padding: 7px 11px; color: var(--text-muted); text-decoration: none; }
.tc-nav a:hover { background: var(--surface-2); color: var(--text); }
.tc-nav-today { font-size: 13px; font-weight: 600; color: var(--text); border-left: 1px solid var(--border); border-right: 1px solid var(--border); }
.tc-period { font-size: 16px; font-weight: 600; letter-spacing: -0.01em; }
.tc-viewseg { display: inline-flex; gap: 2px; padding: 3px; background: var(--surface-2); border: 1px solid var(--border); border-radius: 7px; }
.tc-viewseg a { padding: 5px 14px; font-size: 13px; color: var(--text-muted); text-decoration: none; border-radius: 5px; }
.tc-viewseg a:hover { color: var(--text); }
.tc-viewseg a.active { font-weight: 600; color: var(--text); background: var(--surface); box-shadow: 0 1px 2px oklch(0.3 0.02 258 / 0.08); }

.tc-cal-empty { padding: 14px 18px; margin-bottom: 14px; font-size: 13.5px; color: var(--text-muted); text-align: left; }

/* month grid */
.tc-month-wrap { overflow-x: auto; }
.tc-month { min-width: 680px; background: var(--surface); border: 1px solid var(--border); border-radius: 10px; overflow: hidden; }
.tc-month-dow { display: grid; grid-template-columns: repeat(7, 1fr); border-bottom: 1px solid var(--border); }
.tc-month-dow div { padding: 10px 12px; font-size: 11.5px; font-weight: 600; letter-spacing: 0.07em; text-transform: uppercase; color: var(--text-faint); }
.tc-month-row { display: grid; grid-template-columns: repeat(7, 1fr); }
/* A week-boundary rule, distinct from .tc-cell's internal border-top
   (2026-08-31) — without it, a spanning-segment band (which renders as
   the FIRST child of its week's row, above that week's own numbered
   cells) has no visual marker showing which week it belongs to: it sits
   flush against the previous week's empty cells with nothing to signal
   "a new row starts here," reading as if it belonged to the week ABOVE
   instead. This border sits above the band, making the grouping
   unambiguous. Skips the first row (no preceding row to separate from —
   .tc-month-dow's own border-bottom already closes it off). */
.tc-month-row + .tc-month-row { border-top: 1px solid var(--border); }
.tc-cell { min-height: 116px; padding: 8px 9px 10px; border-top: 1px solid var(--surface-2); border-right: 1px solid var(--surface-2); display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.tc-cell:nth-child(7n) { border-right: none; }
.tc-cell.open { background: var(--surface-2); }
.tc-cell-numwrap { display: flex; }
.tc-cell-num { font-size: 12.5px; font-weight: 600; color: var(--text-muted); text-decoration: none; padding: 3px 4px; border-radius: 999px; }
.tc-cell.dim .tc-cell-num { color: var(--text-faint); font-weight: 400; }
a.tc-cell-num:hover { background: var(--surface-2); color: var(--text); }
.tc-cell-num.today { background: var(--accent); color: var(--accent-contrast); width: 24px; height: 24px; padding: 0; display: flex; align-items: center; justify-content: center; }
a.tc-cell-num.today:hover { background: var(--accent-hover); color: var(--accent-contrast); }

/* dots / bottom-sheet chrome are mobile-only (see the mobile @media block) */
.tc-cell-dots, .tc-sheet-scrim, .tc-sheet-grab { display: none; }
/* .tc-cell-chips is a passthrough on desktop (chips stay direct flex
   children of .tc-cell); mobile hides it and shows .tc-cell-dots. */
.tc-cell-chips { display: contents; }

.tc-chip { display: flex; align-items: baseline; gap: 5px; font-size: 12px; line-height: 1.3; padding: 2px 6px; border-radius: 4px; text-decoration: none; color: var(--text); white-space: nowrap; overflow: hidden; }
.tc-chip:hover { background: var(--surface-2); }
.tc-chip.allday { background: var(--warm-soft); color: var(--warm); }
.tc-chip.allday:hover { filter: brightness(0.97); }
.tc-chip.done .tc-chip-title { text-decoration: line-through; color: var(--text-faint); }
.tc-chip-dot { width: 4px; height: 4px; border-radius: 999px; background: var(--accent); flex: none; align-self: center; }
.tc-chip-time { color: var(--text-muted); font-variant-numeric: tabular-nums; flex: none; }
.tc-chip-title { overflow: hidden; text-overflow: ellipsis; }

/* multi-day spanning bars (2026-08-31, structured event fields) — a band
   above each week row's day cells, one lane per concurrently-overlapping
   span (see calendar_viewmodel._month_week_spans). left_pct/width_pct are
   computed against the same 7-column width as .tc-month-row below it, so
   a bar lines up with the day cells it covers. */
.tc-span-band { grid-column: 1 / -1; position: relative; padding: 4px 0 3px; }
.tc-span-bar { position: absolute; box-sizing: border-box; height: 17px; margin: 0 2px; border-radius: 4px; background: var(--warm-soft); color: var(--warm); font-size: 11px; font-weight: 600; line-height: 17px; padding: 0 8px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; text-decoration: none; }
.tc-span-bar:hover { filter: brightness(0.97); }
.tc-span-bar.timed { background: var(--accent-soft); color: var(--accent); }
.tc-span-bar.done { text-decoration: line-through; opacity: 0.6; }
.tc-span-bar.continues-left { border-top-left-radius: 0; border-bottom-left-radius: 0; margin-left: 0; }
.tc-span-bar.continues-right { border-top-right-radius: 0; border-bottom-right-radius: 0; margin-right: 0; }
.tc-chip.allday.multiday { background: var(--warm-soft); color: var(--warm); font-weight: 600; }

.tc-day-panel { grid-column: 1 / -1; border-top: 1px solid var(--border); background: var(--surface-2); padding: 20px 22px 22px; }
.tc-day-panel-head { display: flex; align-items: baseline; justify-content: space-between; margin-bottom: 14px; gap: 12px; }
.tc-day-panel-heading { font-size: 15px; font-weight: 600; margin-right: 10px; }
.tc-day-panel-sub { font-size: 13px; color: var(--text-muted); }
.tc-ecards { display: flex; flex-direction: column; gap: 10px; }
.tc-ecard { background: var(--surface); border: 1px solid var(--border); border-radius: 8px; padding: 12px 16px; display: flex; gap: 16px; align-items: flex-start; }
.tc-ecard-time { width: 66px; flex: none; font-size: 13px; font-weight: 600; font-variant-numeric: tabular-nums; }
.tc-ecard-body { flex: 1; min-width: 0; }
.tc-ecard-title { font-size: 14px; margin-bottom: 3px; }
.tc-ecard-desc { font-size: 13px; color: var(--text-muted); line-height: 1.5; }
.tc-ecard-cat { flex: none; font-size: 11px; letter-spacing: 0.04em; text-transform: uppercase; color: var(--text-muted); border: 1px solid var(--border); border-radius: 999px; padding: 3px 9px; }
.tc-ecard-x { flex: none; width: 22px; height: 22px; border: none; background: none; border-radius: 5px; display: flex; align-items: center; justify-content: center; color: var(--text-faint); cursor: pointer; padding: 0; }
.tc-ecard-x:hover { color: var(--danger); background: var(--danger-soft); }

/* week + day time grid */
.tc-tg-wrap { overflow-x: auto; }
.tc-tg { --tc-hour-h: 56px; min-width: 720px; background: var(--surface); border: 1px solid var(--border); border-radius: 10px; overflow: hidden; }
.tc-day-layout .tc-tg { min-width: 420px; }
.tc-tg-head { display: grid; border-bottom: 1px solid var(--border); }
.tc-colhead { padding: 9px 12px; border-left: 1px solid var(--surface-2); display: flex; align-items: baseline; gap: 7px; }
.tc-colhead-dow { font-size: 11.5px; font-weight: 600; letter-spacing: 0.07em; text-transform: uppercase; color: var(--text-faint); }
.tc-daynum { font-size: 13px; font-weight: 600; color: var(--text-muted); }
.tc-daynum.today { background: var(--accent); color: var(--accent-contrast); width: 22px; height: 22px; border-radius: 999px; display: flex; align-items: center; justify-content: center; }
.tc-allday-lane { display: grid; border-bottom: 1px solid var(--border); background: var(--surface-2); min-height: 34px; align-items: center; }
.tc-allday-label { padding: 8px 10px; font-size: 11px; letter-spacing: 0.04em; text-transform: uppercase; color: var(--text-faint); text-align: right; }
.tc-allday-col { border-left: 1px solid var(--surface-2); padding: 5px 6px; display: flex; flex-direction: column; gap: 3px; min-height: 34px; box-sizing: border-box; }
.tc-allday-none { font-size: 12px; color: var(--text-faint); }
.tc-tg-body { display: grid; }
.tc-hours { border-right: 1px solid var(--surface-2); }
.tc-hour { height: var(--tc-hour-h); padding: 0 10px; font-size: 11.5px; color: var(--text-faint); text-align: right; transform: translateY(-6px); font-variant-numeric: tabular-nums; }
.tc-daycol { position: relative; border-left: 1px solid var(--surface-2); background-image: linear-gradient(var(--surface-2) 1px, transparent 1px); background-size: 100% var(--tc-hour-h); }
.tc-daycol.today { background-color: var(--accent-soft); }
.tc-block { position: absolute; box-sizing: border-box; min-height: 20px; border-radius: 5px; background: var(--accent-soft); border-left: 2px solid var(--accent); padding: 3px 6px; font-size: 11px; line-height: 1.25; overflow: hidden; text-decoration: none; color: var(--text); }
.tc-block:hover { filter: brightness(0.98); }
.tc-block.selected { box-shadow: 0 0 0 2px var(--accent); }
.tc-block.done .tc-block-title { text-decoration: line-through; color: var(--text-faint); }
.tc-block-time { font-weight: 600; display: block; }
.tc-block-title { display: block; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tc-nowline { position: absolute; left: 0; right: 0; height: 1px; background: var(--danger); z-index: 3; }
.tc-nowline-dot { position: absolute; left: -3px; top: -3.5px; width: 8px; height: 8px; border-radius: 999px; background: var(--danger); }

/* day view detail panel */
.tc-day-layout { display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: 20px; align-items: start; }
.tc-day-layout.no-panel { grid-template-columns: minmax(0, 1fr); }
.tc-epanel { background: var(--surface); border: 1px solid var(--border); border-radius: 10px; padding: 20px 22px 22px; box-shadow: 0 16px 40px oklch(0.3 0.02 258 / 0.06); }
.tc-epanel-top { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }
.tc-epanel-eyebrow { font-size: 11.5px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--text-faint); }
.tc-epanel-close { color: var(--text-faint); display: flex; }
.tc-epanel-close:hover { color: var(--text); }
.tc-epanel-title { font-size: 16px; font-weight: 600; line-height: 1.35; margin-bottom: 5px; }
.tc-epanel-when { font-size: 13.5px; color: var(--text-muted); font-variant-numeric: tabular-nums; margin-bottom: 16px; }
.tc-epanel-rows { display: flex; flex-direction: column; gap: 11px; padding-top: 14px; border-top: 1px solid var(--border); }
.tc-erow { display: flex; gap: 14px; font-size: 13px; line-height: 1.5; }
.tc-erow-key { width: 76px; flex: none; color: var(--text-faint); }
.tc-epanel-actions { display: flex; align-items: center; gap: 16px; margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--border); flex-wrap: wrap; }
.tc-note { position: relative; }
.tc-note-trigger { list-style: none; cursor: pointer; font-size: 13.5px; font-weight: 600; color: var(--accent); border: 1px solid var(--accent); background: var(--accent-soft); border-radius: 7px; padding: 7px 15px; }
.tc-note-trigger::-webkit-details-marker { display: none; }
.tc-note-form { position: absolute; top: 100%; left: 0; z-index: 20; margin-top: 6px; width: 280px; padding: 12px 14px; border: 1px solid var(--border); border-radius: 10px; background: var(--surface); box-shadow: var(--shadow); display: flex; flex-direction: column; gap: 8px; }
.tc-note-form textarea { min-height: 64px; font: inherit; color: inherit; background: var(--bg); border: 1px solid var(--border); border-radius: 6px; padding: 8px; resize: vertical; }

@media (max-width: 900px) {
  .tc-day-layout, .tc-day-layout.no-panel { grid-template-columns: 1fr; }
  .tc-cal-toolbar { align-items: stretch; }
}

/* ============================================================
   Mobile page passes (max-width: 840px) — Chat, Tasks (swipe /
   long-press / sticky Save), Living Profile (tap-to-expand
   actions), Settings. Kept at the end of the file so these
   overrides win over the component rules above at equal
   specificity. Companion behaviour is in app.js.
   ============================================================ */
@media (max-width: 840px) {

  /* --- Chat --- */
  .chat-header { display: none; }              /* the top bar names it */
  .chat-log { padding: 16px 14px; gap: 12px; }
  .chat-input-row { padding: 10px 12px 12px; gap: 8px; }

  /* --- Living Profile header (intro + Refresh) stacks --- */
  .profile-header { flex-direction: column; align-items: stretch; gap: 12px; }
  .profile-header .btn { align-self: flex-start; }

  /* --- Tasks list --- */
  .tc-group-header { padding: 14px 16px 8px; }
  .tc-group-count { margin-left: auto; }

  .task-row { position: relative; overflow: hidden; padding: 0; align-items: stretch; }
  .task-main {
    display: flex; align-items: flex-start; gap: 12px; flex: 1;
    padding: 12px 16px; min-height: 48px; box-sizing: border-box;
    background: var(--surface); position: relative; z-index: 1;
    transition: transform 0.22s ease;
    touch-action: pan-y; -webkit-user-select: none; user-select: none;
    -webkit-touch-callout: none;
  }
  /* revealed behind the row by a left swipe (app.js) */
  .task-nr {
    display: flex; align-items: center; justify-content: center; gap: 7px;
    position: absolute; top: 0; right: 0; bottom: 0; width: 140px;
    border: none; background: var(--danger-soft); color: var(--danger);
    font: 600 13px/1 'Public Sans', sans-serif; cursor: pointer;
  }
  .task-row.task-swipe-open .task-main { transform: translateX(-140px); }
  /* the tiny always-visible x becomes an accessible-only control; the
     swipe reveal is the visible affordance on touch */
  .task-dismiss {
    position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
    overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
  }

  .task-tooltip {
    position: fixed; z-index: 60;
    background: oklch(0.22 0.014 258); color: oklch(0.97 0.005 258);
    font-size: 11.5px; font-weight: 500; padding: 6px 10px; border-radius: 7px;
    white-space: nowrap; box-shadow: 0 6px 16px oklch(0.2 0.02 258 / 0.35);
    pointer-events: none;
  }

  /* sticky Save bar — armed by app.js once a checkbox is ticked */
  .tc-save-row.tc-save-row {
    position: sticky; bottom: 0; z-index: 6;
    margin: 16px calc(-1 * var(--content-px)) 0;
    padding: 12px var(--content-px);
    background: var(--surface); border-top: 1px solid var(--border);
    transform: translateY(115%); transition: transform 0.2s ease;
  }
  .tc-save-row.is-armed { transform: none; }
  .tc-save-hint { font-size: 12px; }

  /* --- Living Profile: tap a fact row to expand its actions --- */
  .fact-row { flex-wrap: wrap; padding: 12px 8px; align-items: center; }
  .fact-row .fact-text { flex: 1 1 auto; }
  .fact-row .fact-date { margin-left: auto; flex: none; }
  .fact-row .fact-actions {
    opacity: 0; max-height: 0; overflow: hidden; width: 100%;
    flex-wrap: wrap; gap: 10px 20px; margin-top: 0;
    transition: max-height 0.25s ease, opacity 0.15s ease, margin-top 0.2s ease;
  }
  .fact-row.is-open { background: var(--surface-2); border-radius: 8px; }
  .fact-row.is-open .fact-actions,
  .fact-row:focus-within .fact-actions { opacity: 1; max-height: 460px; margin-top: 10px; }
  .fact-row:focus-within { background: var(--surface-2); border-radius: 8px; }
  .fact-row .fact-actions summary, .fact-row .fact-actions button { font-size: 13.5px; padding: 4px 0; }
  /* an opened action detail takes its own row so the popover has room and
     the other triggers don't get pushed off-screen */
  .fact-row .fact-actions details[open] { flex-basis: 100%; }

  /* popovers flow in-column instead of overflowing a narrow screen */
  .fact-edit-popover, .fact-delete-popover, .tc-note-form {
    position: static; width: auto; margin-top: 8px; box-shadow: none;
  }
  .fact-group:has(details[open]) { overflow: visible; }

  /* --- Settings --- */
  /* verify / confirm dialogs become bottom sheets */
  .modal-backdrop { align-items: flex-end; }
  .modal-card {
    width: 100%; border-radius: 16px 16px 0 0;
    padding: 22px 20px calc(22px + env(safe-area-inset-bottom, 0px));
  }
  /* channel rows: name + icon on the first line, badge and the
     verify/unlink control wrap to a second line */
  .channel-row { flex-wrap: wrap; column-gap: 12px; row-gap: 10px; }
  .channel-row-body { flex: 1 1 0; min-width: 0; }
  .channel-row-body .channel-name { overflow-wrap: anywhere; }
  .channel-row > .badge { order: 2; }
  .channel-row > details { order: 3; margin-left: auto; }
  .channel-row > details > summary { margin-left: 0 !important; }
  .settings-tabs { display: flex; width: 100%; }
  .settings-tab { flex: 1; text-align: center; padding: 9px 6px; }
  .account-facts { gap: 16px 32px; }

  /* --- Admin queue: table rows become stacked cards --- */
  .admin-table-header { display: none; }
  .admin-table-row { flex-direction: column; align-items: stretch; gap: 3px; padding: 14px 16px; }
  .admin-table-row > div { flex: none !important; text-align: left !important; }
  .admin-table-row > div:last-child { margin-top: 12px; justify-content: stretch !important; }
  .admin-table-row > div:last-child form { flex: 1; }
  .admin-table-row > div:last-child .btn { width: 100%; }

  /* --- Calendar month: dots instead of chips, fits without h-scroll --- */
  .tc-day-panel { padding: 18px 16px 20px; }
  .tc-day-panel-head { flex-wrap: wrap; gap: 6px 10px; }
  .tc-ecard { flex-wrap: wrap; gap: 4px 10px; padding: 12px 14px; }
  .tc-ecard-time { width: auto; font-size: 12px; color: var(--text-muted); }
  .tc-ecard-cat { order: 2; margin-left: auto; }
  .tc-ecard-x { order: 2; }
  .tc-ecard-body { flex: 1 1 100%; order: 3; }
  .tc-ecard-title { text-decoration: none; }

  .tc-month-wrap { overflow-x: visible; }
  .tc-month { min-width: 0; }
  .tc-month-dow div { padding: 6px 0; text-align: center; font-size: 10px; }
  .tc-cell { min-height: 58px; padding: 4px 2px 6px; cursor: pointer; }
  .tc-cell-numwrap { justify-content: center; }
  .tc-cell-num { font-size: 12px; padding: 2px 5px; }
  .tc-cell-num.today { width: 22px; height: 22px; }
  .tc-cell-chips { display: none; }
  .tc-cell-dots { display: flex; align-items: center; justify-content: center; gap: 3px; flex-wrap: wrap; margin-top: 3px; }
  .tc-dot { width: 5px; height: 5px; border-radius: 50%; background: var(--accent); }
  .tc-dot.allday { background: var(--warm); }
  .tc-dot-more { font-size: 9px; font-weight: 600; color: var(--text-faint); line-height: 1; }
  .tc-span-bar { font-size: 9px; height: 14px; line-height: 14px; padding: 0 4px; }

  /* --- Calendar week: 3-day scroll-snap window with a pinned time gutter --- */
  /* overflow:visible so the sticky time gutter can pin to .tc-week-wrap
     (base .tc-tg is overflow:hidden, which would trap the sticky) */
  .tc-tg.tc-week { min-width: max-content; overflow: visible; border-radius: 0; }
  .tc-week-wrap { scroll-snap-type: x proximity; scroll-padding-left: 52px; border: 1px solid var(--border); border-radius: 10px; }
  .tc-week .tc-tg-head, .tc-week .tc-allday-lane, .tc-week .tc-tg-body {
    grid-template-columns: 52px repeat(7, 26vw) !important;
  }
  .tc-week .tc-colhead, .tc-week .tc-daycol, .tc-week .tc-allday-col { scroll-snap-align: start; }
  .tc-week .tc-hours,
  .tc-week .tc-tg-head > :first-child,
  .tc-week .tc-allday-label {
    position: sticky; left: 0; z-index: 4;
    align-self: stretch; background: var(--surface);
  }
  .tc-week .tc-allday-label {
    background: var(--surface-2);
    display: flex; align-items: center; justify-content: flex-end;
  }
  .tc-week .tc-allday-col { overflow: hidden; }

  /* --- Calendar day: detail panel becomes a bottom sheet --- */
  .tc-sheet-scrim {
    display: block; position: fixed; inset: 0; z-index: 45;
    background: oklch(0.12 0.01 258 / 0.4);
  }
  .tc-day-layout .tc-epanel[data-sheet] {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 46;
    border-radius: 18px 18px 0 0; box-shadow: 0 -12px 32px oklch(0.15 0.02 258 / 0.2);
    max-height: 82vh; overflow-y: auto; padding: 8px 20px calc(20px + env(safe-area-inset-bottom, 0px));
    transition: transform 0.22s ease;
  }
  .tc-sheet-grab {
    display: block; width: 40px; height: 4px; border-radius: 999px;
    background: var(--border-strong); margin: 4px auto 12px;
  }
}

@media (max-width: 840px) and (prefers-reduced-motion: no-preference) {
  .tc-day-layout .tc-epanel[data-sheet] { animation: tc-sheet-up 0.24s ease; }
  @keyframes tc-sheet-up { from { transform: translateY(100%); } }
}

/* pull-to-refresh indicator (Tasks / Calendar list) — app.js drives the
   height; hidden and inert everywhere else */
.ptr-indicator { display: none; }
@media (max-width: 840px) {
  /* on mobile the document scrolls (.content grows to fit) — put the
     native-pull-to-refresh suppression on the actual scroller */
  body:has(.tc-grid), body:has(.tc-month), body:has(.tc-cal-empty), body:has(.tc-empty) {
    overscroll-behavior-y: contain;
  }
  .ptr-indicator {
    display: flex; align-items: center; justify-content: center; gap: 8px;
    height: 0; overflow: hidden; margin-top: -4px;
    font-size: 12.5px; color: var(--text-muted);
    transition: height 0.16s ease;
  }
  .ptr-indicator.loading svg { animation: ptr-spin 1s linear infinite; }
}
@keyframes ptr-spin { to { transform: rotate(360deg); } }

@media (max-width: 840px) and (prefers-reduced-motion: reduce) {
  .task-main, .tc-save-row, .fact-row .fact-actions, .ptr-indicator,
  .tc-day-layout .tc-epanel[data-sheet] { transition: none; }
  .ptr-indicator.loading svg { animation: none; }
}

/* iOS Safari zooms the whole page in on focus for any text input under
   16px — found on the chat composer (14px), which then left the send
   button off-screen until the user manually zoomed back out. Same root
   cause hits every input/textarea/select in the app (auth forms, task
   and profile search, fact-edit popovers, settings), so fix it there
   too rather than one page at a time. Only changes font-size; each
   field's own padding/width/etc. rules are untouched. An inline
   font-size (the 6-digit code fields) already sits at 17px and wins
   regardless, so it's unaffected. */
@media (max-width: 840px) {
  .field-input,
  .chat-input-row input,
  .profile-search input,
  .tc-search input,
  .fact-edit-popover input,
  .fact-edit-popover textarea,
  .tc-note-form textarea {
    font-size: 16px;
  }
}
