/* There & Then — mobile-first PWA styles */

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

/* The legacy-variable bridge is GONE (2026-09-22). It mapped the pre-design
   system names (--color-text, --color-border, ...) onto the DS semantic
   aliases so the old rules kept working through the adoption; every rule now
   names the alias directly, which is what the DS asks for and what makes a
   token rename a one-file change.
   Components read ONLY semantic aliases (--surface-*, --text-*, --accent*,
   --border-*), never the raw scales in ds/colors.css — that is what keeps
   theming automatic. */
:root {
  /* --radius-sm/md/lg come from ds/spacing.css. */
}


/* ============================================================
   Component pass (Task 5): buttons + form controls → DS tokens.
   Consolidated rules live here; the individual rules further down
   keep only layout specifics (padding/width/display) plus any
   deliberate per-component override (e.g. a visible border kept on
   top of the shared borderless base — source order lets the later,
   more specific declaration win for that one property).
   ============================================================ */
.btn, .refresh-btn {
  font-family: var(--font-sans);
  font-weight: var(--fw-semibold);
  font-size: 15px;
  border-radius: var(--radius-md);
  border: 0;
  cursor: pointer;
  transition: background var(--dur-sm) var(--ease-standard), transform var(--dur-xs) var(--ease-standard);
}
.btn:active { transform: translateY(1px); } /* press nudge */
:is(.btn, .refresh-btn):focus-visible { outline: none; box-shadow: var(--shadow-focus); }

/* OAuth keeps its brand look — normalize only radius/font/focus/press nudge. */
.btn-oauth {
  font-family: var(--font-sans);
  border-radius: var(--radius-md);
  transition: border-color var(--dur-sm) var(--ease-standard), transform var(--dur-xs) var(--ease-standard);
}
.btn-oauth:active { transform: translateY(1px); }
.btn-oauth:focus-visible { outline: none; box-shadow: var(--shadow-focus); }

/* Secondary/ghost. .show-more lives on a theme-following surface (memory
   card) so it gets the full treatment. .map-cancel sits on the map-overlay
   chrome, which is theme-following since the v53
   sheet conversion — their color/border read semantic aliases like everything
   else; normalized below for radius/font/focus. */
.show-more {
  background: transparent;
  border: 1px solid var(--border-default);
  color: var(--text-body);
  border-radius: var(--radius-md);
  font-family: var(--font-sans);
}
.show-more:focus-visible { outline: none; box-shadow: var(--shadow-focus); }

/* Danger stays soft */
.footer-action-danger { color: var(--error); }

/* Text fields */
:is(.text-input, .email-input, .ask-input, .admin-input, .dt-input, .loc-search, #memory-text, #edit-text) {
  background: var(--surface-card);
  color: var(--text-body);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  font-family: var(--font-sans);
  font-size: 16px;
  transition: border-color var(--dur-sm) var(--ease-standard), box-shadow var(--dur-sm) var(--ease-standard);
}
:is(.text-input, .email-input, .ask-input, .admin-input, .dt-input, .loc-search, #memory-text, #edit-text):focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: var(--shadow-focus);
}
:is(.text-input, .email-input, .ask-input, #memory-text, #edit-text)::placeholder { color: var(--text-muted); }

/* Mic + toggles */
.mic-btn { border: 1px solid var(--border-default); background: var(--surface-card); color: var(--text-secondary); border-radius: var(--radius-pill); }
.mic-btn.recording { background: var(--error-surface); border-color: var(--error); color: var(--error); }
.settings-radio input[type="radio"] { accent-color: var(--accent); }

/* ============================================================
   Component pass (Task 6): cards, sheets, chips, toasts → DS tokens.
   Shared declarations live here; the individual rules further down
   keep only layout specifics (padding/margin/display/gap) plus any
   deliberate per-component addition (e.g. .memory-item's hover lift).
   ============================================================ */
:is(.capture-card, .login-card, .memory-item, .ask-answer-card,
    .onboard-card, .welcome-card, .settings-card, .admin-card) {
  background: var(--surface-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}
/* Interactive cards lift */
.memory-item { transition: transform var(--dur-sm) var(--ease-standard), box-shadow var(--dur-sm) var(--ease-standard); }
.memory-item:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); }
@media (prefers-reduced-motion: reduce) {
  .memory-item { transition: none; }
  .memory-item:hover { transform: none; }
}

/* Chips / badges / pills */
:is(.category-chip, .category-add-chip, .gps-chip, .space-badge) {
  border-radius: var(--radius-pill);
  background: var(--accent-tint); color: var(--text-body);
  border: 1px solid transparent; font-size: 13px;
}
.category-chip.selected, .category-chip.active { background: var(--accent-soft); color: var(--text-on-accent); }
/* --beta-badge-ink is a theme-paired custom property (defined with the
   bloom-mark colors above) rather than the raw --rose-700 the DS spec
   names literally: accent-secondary-tint is itself a theme-paired
   background (pale rose in light, a translucent rose-over-dark wash in
   dark), and a fixed --rose-700 text color would go low-contrast on the
   dark variant. See task-6-report.md. */
.beta-badge {
  border-radius: var(--radius-pill); background: var(--accent-secondary-tint);
  color: var(--beta-badge-ink); font-family: var(--font-sans); font-weight: var(--fw-semibold);
  font-size: 11px; letter-spacing: var(--ls-wide); text-transform: uppercase;
}
.icon-badge, .menu-dot { background: var(--accent-secondary); }

html, body {
  height: 100%;
  background: var(--surface-canvas);
  color: var(--text-body);
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}

body { padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left); }

#app { max-width: 680px; margin: 0 auto; padding: 16px; }

/* ── Main app ── */
header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 0 20px;
}
header h1 { font-size: 21px; }
/* (font-weight/letter-spacing dropped here — .wordmark-text now owns those,
   so the Bloom mark + beta badge don't inherit the old bold/tight styling) */

/* Home bar on the login screen — mirrors the landing's .site-nav */
.login-home-bar {
  position: fixed; top: 0; left: 0; right: 0; z-index: 20;
  display: flex; align-items: center; justify-content: space-between;
  padding: calc(14px + env(safe-area-inset-top)) 24px 14px;
  background: color-mix(in srgb, var(--surface-page) 82%, transparent);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--border-subtle);
}
.login-home-brand { display: inline-flex; align-items: center; gap: 10px; text-decoration: none; }
.login-home-bar .bloom-mark { width: 26px; height: 26px; }
.login-home-bar .wordmark-text { font-size: 1.25rem; }
.login-home-cta {
  background: var(--action-primary-bg); color: var(--action-primary-fg);
  text-decoration: none; font-weight: var(--fw-semibold); font-size: 0.95rem;
  padding: 10px 18px; border-radius: var(--radius-pill);
}
.login-home-cta:hover { background: var(--action-primary-hover); }
.login-home-cta:focus-visible, .login-home-brand:focus-visible { outline: none; box-shadow: var(--shadow-focus); }

/* Wordmark lockup — Newsreader 500, tight tracking, italic rose "Ease" */
.wordmark { display: flex; align-items: center; gap: 10px; cursor: pointer; }
.wordmark .bloom-mark { width: 26px; height: 26px; flex: none; }
.bloom-lg { width: 44px; height: 44px; display: block; margin: 0 auto 12px; }
/* The wordmark is its own lockup, not a heading. Fraunces for the letters at
   the instance baked by scripts/build-wordmark-font.sh; the em is the ampersand
   and takes EB Garamond's italic Et form. Both fall back to the display face,
   so a failed font request degrades to a readable wordmark rather than tofu. */
.wordmark-text {
  font-family: "Fraunces Wordmark", var(--font-display);
  font-weight: 500;
  letter-spacing: -0.9px;   /* tuned for Fraunces; -1.4px was Newsreader's */
  color: var(--text-strong);
}
.wordmark-text em {
  font-family: "EBG Ampersand", var(--font-display);
  font-style: italic;
  color: var(--wordmark-amp);
  margin: 0 0.04em;
}

/* ── Capture area ── */
.capture-card {
  padding: 16px;
  margin-bottom: 24px;
}

.input-row {
  display: flex;
  gap: 10px;
  align-items: flex-start;
}

#memory-text {
  flex: 1;
  min-height: 100px;
  padding: 12px;
  resize: vertical;
}

.mic-btn {
  flex-shrink: 0;
  width: 48px;
  height: 48px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.mic-btn:hover { background: var(--border-default); color: var(--text-body); }
.mic-btn.recording { animation: pulse 1.2s infinite; }
.mic-btn svg { width: 20px; height: 20px; }

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.6; }
}

.save-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-top: 12px;
  gap: 12px;
}

/* Layout hook only — its look is .tt-btn--primary (ds/components.css). */
.save-btn { min-width: 140px; }
/* Slow-save bar beside the Save button (Helm 34) — takes the rest of the row,
   so revealing it never shifts the button. Look: .tt-progress. */
.save-row .save-progress { flex: 1; }

/* A just-saved note's photos, shown from the local previews while they
   upload: dimmed until each lands, with its own bar (Helm 34). */
.memory-mosaic.is-uploading .memory-mosaic-tile { cursor: default; }
.memory-mosaic.is-uploading .memory-mosaic-tile > img { transition: opacity var(--dur-md) var(--ease-out); }
.memory-mosaic.is-uploading .is-waiting   > img.is-loaded,
.memory-mosaic.is-uploading .is-uploading > img.is-loaded { opacity: 0.55; }
.memory-mosaic.is-uploading .is-failed    > img.is-loaded { opacity: 0.35; }
.memory-mosaic.is-uploading .is-failed { outline: 2px solid var(--error); outline-offset: -2px; }
.upload-tile-status {
  position: absolute; left: 8px; bottom: 8px; z-index: 1;
  padding: 2px 8px; border-radius: var(--radius-pill);
  background: var(--surface-card); color: var(--error);
  font-size: 0.78rem; font-weight: 600;
}
/* Floating toast — fixed at bottom-center, layered above every overlay (z 1100)
   so action feedback is visible on any screen, including the admin overlay. */
.toast {
  position: fixed;
  left: 50%;
  bottom: calc(24px + env(safe-area-inset-bottom, 0px));
  transform: translateX(-50%);
  z-index: 2000;
  max-width: min(90vw, 420px);
  padding: 11px 18px;
  background: var(--surface-card);
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);
  color: var(--success);
  font-size: 0.875rem;
  text-align: center;
  transition: opacity 0.3s, transform 0.3s;
}
.toast.error { color: var(--error); }
.toast.hidden {
  opacity: 0;
  pointer-events: none;
  transform: translateX(-50%) translateY(8px);
}

/* ── Memory list ── */
.memories-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 0.8rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-secondary);
  margin-bottom: 12px;
}

.memory-list { display: flex; flex-direction: column; gap: 10px; }

.memory-item {
  padding: 14px 16px;
}

.memory-meta {
  display: flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 6px;
  font-size: 0.85rem;
  color: var(--text-secondary);
}

.memory-source {
  font-size: 0.78rem;
  background: var(--surface-canvas);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-pill);
  padding: 1px 6px;
}

.memory-text { font-size: 1.0625rem; line-height: 1.5; word-break: break-word; }
.memory-text.truncated { display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }

.show-more {
  font-size: 0.9rem;
  cursor: pointer;
  padding: 4px 0 0;
  display: block;
}

.empty-state {
  text-align: center;
  color: var(--text-secondary);
  padding: 40px 0;
  font-size: 0.9rem;
}

.rhythm-line { font-size: 0.82rem; opacity: 0.6; margin: 2px 0 10px; }

.funnel-row { display: flex; justify-content: space-between; font-size: 0.85rem; padding: 3px 0; }
.funnel-activated { font-weight: 600; border-top: 1px solid var(--border-default); margin-top: 4px; padding-top: 6px; }

/* ── Shared button ── */
.btn {
  padding: 12px 24px;
}

/* ================================================================
   Auth screens
   ================================================================ */

.center-screen {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
}


#login-screen,
#confirm-link-screen,
#merge-confirm-screen {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  padding: 24px;
  box-sizing: border-box;
}

.login-card {
  width: 100%;
  max-width: 360px;
  padding: 32px 24px;
  text-align: center;
}

.login-card h1 {
  font-size: 1.8rem;
  font-weight: 700;
  margin: 0 0 8px;
  color: var(--text-strong);
}

.login-subtitle {
  color: var(--text-secondary);
  margin: 0 0 28px;
  font-size: 0.95rem;
}

.email-input {
  width: 100%;
  padding: 12px 16px;
  box-sizing: border-box;
  margin-bottom: 12px;
}

.btn { display: block; width: 100%; margin-bottom: 10px; }

.btn-oauth {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  background: var(--surface-canvas);
  color: var(--text-body);
  border: 1px solid var(--border-default);
  padding: 13px;
  font-size: 0.97rem;
  font-weight: 500;
  width: 100%;
  margin-bottom: 10px;
  box-sizing: border-box;
}

.btn-oauth:hover { border-color: var(--accent); }

/* Apple's mark is a single solid glyph and takes currentColor, unlike the
   multi-colour Google and Facebook marks. Apple's guidelines require its button
   be no less prominent than the other providers', which is why it renders in
   the same .btn-oauth shell rather than something quieter. */
.btn-apple .oauth-icon { color: var(--text-body); }

.oauth-icon { width: 20px; height: 20px; flex-shrink: 0; }

.login-email-display {
  color: var(--accent);
  font-size: 0.95rem;
  margin: 0 0 20px;
  word-break: break-all;
}

.login-error {
  color: var(--error);
  font-size: 0.9rem;
  margin-top: 16px;
  padding: 10px;
  background: var(--error-surface);
  border-radius: 8px;
}

/* GPS readiness chip in the capture card */
.gps-chip {
  margin-top: 8px;
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.gps-pin { width: 13px; height: 13px; flex-shrink: 0; }
.gps-chip.gps-ready { color: var(--success); }
.gps-chip.gps-denied { color: var(--warning); cursor: pointer; }
.gps-chip.gps-unavailable { color: var(--text-disabled); }

/* Location controls (shared by the edit sheet) */
.loc-current {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 7px 11px;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--surface-card);
  font: inherit;
  font-weight: 600;
  font-size: 0.9rem;
  color: var(--text-body);
  cursor: pointer;
}
.loc-current:hover { background: var(--surface-canvas); }
.loc-current:disabled { opacity: 0.6; cursor: default; }

.loc-search {
  padding: 7px 11px;
}

.loc-result {
  display: flex;
  flex-direction: column;
  gap: 2px;
  width: 100%;
  text-align: left;
  padding: 7px 11px;
  border: 1px solid transparent;
  border-radius: var(--radius-md);
  background: var(--surface-card);
  font: inherit;
  font-size: 0.9rem;
  cursor: pointer;
}
.loc-result:hover { background: var(--accent-tint); border-color: var(--accent); }
.loc-result-name { font-weight: 600; color: var(--text-body); }
.loc-result-addr { font-size: 0.78rem; color: var(--text-secondary); }

.loc-hint { font-size: 0.8rem; color: var(--text-secondary); padding: 2px; }

.dt-input {
  padding: 7px 11px;
}
/* Note text input (shared by the edit sheet) */
.text-input {
  width: 100%;
  box-sizing: border-box;
  resize: vertical;
  min-height: 80px;
  padding: 7px 11px;
}
[x-cloak] { display: none !important; }

/* Full-screen map picker overlay */
.map-overlay {
  position: fixed;
  inset: 0;
  z-index: 1000;
  background: var(--surface-card);
  display: flex;
  flex-direction: column;
  /* Keep the top bar below the iOS status bar/notch and the bottom sheet above
     the home indicator. */
  padding-top: env(safe-area-inset-top);
  padding-bottom: env(safe-area-inset-bottom);
}
.map-overlay-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 10px 12px;
  border-bottom: 1px solid var(--border-subtle);
  background: var(--surface-card);
}
.map-overlay-title { font-size: 0.85rem; color: var(--text-secondary); text-align: center; flex: 1; }
.map-cancel {
  border: none; background: none; color: var(--text-secondary);
  font: inherit; font-family: var(--font-sans); cursor: pointer; padding: 6px 10px;
}
.map-cancel:focus-visible { outline: none; box-shadow: var(--shadow-focus); }
.map-save {
  border: 0; border-radius: var(--radius-md);
  background: var(--action-primary-bg); color: var(--action-primary-fg);
  font: inherit; font-weight: 600; cursor: pointer; padding: 8px 14px;
}
.map-save:hover { background: var(--action-primary-hover); }
.map-canvas { flex: 1; width: 100%; }

.loc-map-btn {
  display: flex; align-items: center; justify-content: center; gap: 6px;
  padding: 7px 11px; border: 1px solid var(--border-default); border-radius: var(--radius-md);
  background: var(--surface-card); font: inherit; font-weight: 600; font-size: 0.9rem; color: var(--text-body); cursor: pointer;
}
.loc-map-btn:hover { background: var(--surface-canvas); }

/* Heatmap header button + memory-map overlay extras */
/* v68: bloom menu button + wordmark share the header's left side. */
.header-brand { display: flex; align-items: center; gap: 6px; }
.map-bar-spacer { width: 56px; }

.heat-empty {
  position: absolute; left: 50%; top: 60%; transform: translateX(-50%);
  max-width: 80%; text-align: center; color: var(--text-secondary); font-size: 0.9rem;
  background: var(--surface-card); box-shadow: var(--shadow-sm);
  padding: 10px 14px; border-radius: var(--radius-md);
}
.heat-sheet {
  position: absolute; left: 0; right: 0; bottom: 0;
  max-height: 45%; display: flex; flex-direction: column;
  background: var(--surface-card); border-top: 1px solid var(--border-subtle);
  border-radius: var(--radius-xl) var(--radius-xl) 0 0;
  box-shadow: var(--shadow-md);
}
.heat-sheet-head {
  display: flex; align-items: center; justify-content: space-between;
  padding: 10px 14px; border-bottom: 1px solid var(--border-subtle); font-weight: 600;
}
.heat-sheet-close {
  border: none; background: none; color: var(--text-secondary); font: inherit;
  cursor: pointer; padding: 2px 8px; display: inline-flex; align-items: center;
}
.heat-sheet-close svg { width: 15px; height: 15px; display: block; }
.heat-sheet-list { overflow-y: auto; padding: 4px 0; }
.heat-item { padding: 8px 14px; border-bottom: 1px solid var(--border-subtle); }
.heat-item-meta { font-size: 0.78rem; color: var(--text-secondary); }
.heat-item-text { margin-top: 2px; white-space: pre-wrap; }

/* Refresh button on the Recent Memories header (dark theme) */
.refresh-btn {
  background: var(--surface-canvas);
  border: 1px solid var(--border-default);
  color: var(--text-secondary);
  line-height: 1;
  padding: 5px 10px;
  display: inline-flex;
  align-items: center;
}
.refresh-btn svg { width: 16px; height: 16px; display: block; }
.refresh-btn:hover { color: var(--text-body); }
.refresh-btn:disabled { opacity: 0.6; cursor: default; }
.refresh-btn.spinning { animation: refresh-spin 0.8s linear infinite; }
@keyframes refresh-spin { to { transform: rotate(360deg); } }

/* BETA badge on the login title */
.beta-badge {
  display: inline-block;
  vertical-align: middle;
  padding: 3px 7px;
  margin-left: 6px;
  position: relative;
  top: -3px;
}

/* "Center on me" button in the heatmap overlay bar */
.map-me-btn {
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  background: var(--surface-card);
  color: var(--text-body);
  font: inherit;
  font-size: 0.85rem;
  cursor: pointer;
  padding: 6px 10px;
  white-space: nowrap;
}
.map-me-btn:hover { background: var(--surface-canvas); }

/* Inline SVG icons inside buttons */
.btn-icon { width: 15px; height: 15px; flex-shrink: 0; }
.map-me-btn { display: inline-flex; align-items: center; gap: 6px; }

/* Admin overlay (dark, invite management) */
.header-icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--border-default); border-radius: 10px;
  background: var(--surface-canvas); color: var(--text-body);
  cursor: pointer; padding: 6px 8px;
}
.header-icon-btn:hover { background: var(--border-default); }

/* Bloom menu toggle — primes 45° on hover, 225° while the drawer is open */
.bloom-menu-btn .bloom-mark { width: 26px; height: 26px; transition: transform var(--dur-lg) var(--ease-out); }
.bloom-menu-btn:hover .bloom-mark { transform: rotate(45deg); }
.bloom-menu-btn.open .bloom-mark { transform: rotate(225deg); }

/* Bloom as processing spinner */
@keyframes me-bloom-spin { to { transform: rotate(360deg); } }
.bloom-spin { animation: me-bloom-spin 1.4s linear infinite; }

@media (prefers-reduced-motion: reduce) {
  .bloom-menu-btn .bloom-mark { transition: none; }
  .bloom-spin { animation: none; }
}

.admin-overlay {
  position: fixed; inset: 0; z-index: 1000;
  background: var(--surface-card); color: var(--text-body);
  display: flex; flex-direction: column;
  padding-top: env(safe-area-inset-top); padding-bottom: env(safe-area-inset-bottom);
}
.admin-bar {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 16px; border-bottom: 1px solid var(--border-default);
}
.admin-title { font-weight: 700; }
.admin-close {
  border: none; background: none; color: var(--text-secondary);
  font: inherit; cursor: pointer; padding: 6px 10px;
}
.admin-body {
  overflow-y: auto; padding: 16px; display: flex; flex-direction: column;
  gap: 16px; width: 100%; max-width: 680px; margin: 0 auto;
}
.admin-card {
  padding: 16px;
  display: flex; flex-direction: column; gap: 10px;
}
.admin-card-title { font-weight: 600; font-size: 0.9rem; }
.admin-input { padding: 10px 12px; }
.admin-days {
  background: var(--surface-canvas); border: 1px solid var(--border-default);
  border-radius: var(--radius-sm); color: var(--text-body); padding: 10px 12px;
  /* 16px for the same reason as .delete-gate input: anything smaller makes iOS
     Safari zoom the page on focus and never zoom back. */
  font-family: inherit; font-size: 16px;
  width: 72px;
}
.admin-days:focus { outline: none; border-color: var(--accent); }
.admin-field { display: flex; align-items: center; gap: 8px; color: var(--text-secondary); font-size: 0.9rem; }
.admin-invite-result { display: flex; gap: 8px; }
.admin-invite-result .admin-input { flex: 1; min-width: 0; }
.admin-invite-row {
  display: flex; align-items: center; justify-content: space-between;
  gap: 8px; padding: 8px 0; border-bottom: 1px solid var(--border-default);
}
.admin-invite-info { display: flex; align-items: center; gap: 8px; min-width: 0; }
.admin-invite-target { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.admin-invite-status { font-size: 0.7rem; padding: 1px 6px; border-radius: 4px; }
.admin-invite-status.pending { background: var(--success-surface); color: var(--success); }
.admin-invite-status.used { background: var(--surface-canvas); color: var(--text-secondary); }
.admin-invite-actions { display: flex; gap: 6px; flex-shrink: 0; }
/* Friend rows carry an identity block: display name, with the address the
   account actually signs in with underneath. That is deliberately NOT the
   address an invite was mailed to — redemption is token-only, so a person can
   join with a different account than the one we wrote to. */
.friend-identity { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1; }
.friend-identity .admin-invite-target { font-weight: 600; }
.friend-email {
  font-size: 0.8rem; color: var(--text-secondary);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* Tappable space row: name with its counts underneath, chevron on the right.
   A button (not the whole row) so the Members/Delete actions still get taps. */
.space-open {
  flex: 1; min-width: 0; display: grid;
  grid-template-columns: 1fr auto; align-items: center;
  gap: 2px 8px; text-align: left; cursor: pointer;
  background: none; border: none; padding: 4px 0; margin: -4px 0;
  color: inherit; font: inherit;
}
.space-open .admin-invite-target { grid-column: 1; grid-row: 1; font-weight: 600; }
.space-open .admin-invite-status { grid-column: 1; grid-row: 2; justify-self: start; }
.space-open-chevron {
  grid-column: 2; grid-row: 1 / span 2;
  width: 18px; height: 18px; color: var(--text-secondary);
}
.space-open:focus-visible { outline: none; box-shadow: var(--shadow-focus); border-radius: var(--radius-sm); }
.admin-hint { color: var(--text-secondary); font-size: 0.85rem; }

/* Legal admin dashboard (read-only): policy versions + adoption stats per
   document. One .legal-doc-block per doc inside the shared .admin-card. */
.legal-doc-block {
  display: flex; flex-direction: column; gap: 8px;
  padding: 10px 0;
}
/* Separator BETWEEN blocks, not "the first div in the card" — :first-of-type
   never matched here because .admin-card-title is already the first div, so
   every block (including the actual first one) drew a divider. */
.legal-doc-block + .legal-doc-block { border-top: 1px solid var(--border-default); }
.legal-doc-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.legal-doc-name { font-weight: 600; font-size: 0.9rem; text-transform: capitalize; }
.legal-doc-versions { display: flex; flex-direction: column; gap: 4px; }
.legal-version-row {
  display: flex; align-items: center; gap: 8px; flex-wrap: wrap;
  font-size: 0.82rem; padding: 3px 0;
}
.legal-version-num { font-weight: 600; }
.legal-version-badge {
  font-size: 0.68rem; font-weight: 600; padding: 1px 6px; border-radius: var(--radius-xs);
}
.legal-version-badge.material { background: var(--warning-surface); color: var(--warning); }
.legal-version-badge.minor { background: var(--surface-canvas); color: var(--text-secondary); }
.legal-version-link { color: var(--accent-ink); text-decoration: none; font-weight: 600; }
.legal-version-link:hover { text-decoration: underline; }
/* Hash is 64 hex chars — shown truncated (shortHash()), full value in the
   title tooltip and copyable via click, so it never dominates the row. */
.legal-hash-btn {
  background: var(--surface-canvas); color: var(--text-secondary); border: 1px solid var(--border-default);
  border-radius: var(--radius-xs); font-family: monospace; font-size: 0.72rem;
  cursor: pointer; padding: 2px 6px; margin-left: auto;
}
.legal-hash-btn:hover { color: var(--text-body); }
/* Shown only after a failed clipboard copy (see copyLegalHash) — the full
   hash as selectable text, since the :title tooltip it otherwise lives in
   is hover-only and unreachable on touch. */
.legal-hash-reveal {
  font-family: monospace; font-size: 0.72rem; color: var(--text-secondary);
  word-break: break-all; user-select: all; padding: 2px 0 4px;
}
.legal-doc-stats { display: flex; flex-direction: column; gap: 2px; }
/* Names now carry a disambiguating email (longer than a display name alone),
   so this line needs to wrap inside the card instead of overflowing on a
   narrow phone screen. */
.legal-outstanding-names { overflow-wrap: anywhere; }

/* Accounts admin card (read-only roster): reuses .legal-doc-block for the
   per-account layout and .legal-version-badge for badge sizing, adding only
   account-specific badge colors. Emails and identifiers run long (a 64-char
   address is realistic), so both the badge row and the chip row wrap and
   break anywhere rather than overflowing a narrow phone screen. */
.account-name { overflow-wrap: anywhere; }
.account-badges { display: flex; flex-wrap: wrap; gap: 6px; }
.account-badge-admin { background: var(--warning-surface); color: var(--warning); }
.account-badge-tombstoned { background: var(--error-surface); color: var(--error); }
.account-emails { display: flex; flex-wrap: wrap; gap: 6px; overflow-wrap: anywhere; }
.account-email-chip {
  background: var(--surface-canvas); color: var(--text-secondary);
  border: 1px solid var(--border-default); border-radius: var(--radius-xs);
  font-size: 0.78rem; padding: 2px 8px; overflow-wrap: anywhere;
}
.account-email-chip.primary { color: var(--text-body); font-weight: 600; }
.account-email-chip.unverified { border-style: dashed; }

/* Account screen (user-facing, non-admin — the first such surface; every
   user reaches it, not just isAdmin). Sits in the shared .insights-overlay
   shell alongside .admin-card for the two lists. Provider names and email
   addresses run long, so both wrap rather than overflow a narrow phone
   screen — same overflow-wrap: anywhere treatment as the admin legal card
   and the admin Accounts roster above. */
.account-row {
  display: flex; align-items: flex-start; justify-content: space-between;
  gap: 8px; padding: 10px 0; border-bottom: 1px solid var(--border-default);
}
.account-row:last-child { border-bottom: none; }
.account-row-main { display: flex; flex-direction: column; gap: 4px; min-width: 0; flex: 1; }
.account-row-title { font-weight: 600; overflow-wrap: anywhere; }
.account-row-title.account-provider-name { text-transform: capitalize; }
.account-row-meta { color: var(--text-secondary); font-size: 0.82rem; overflow-wrap: anywhere; }
.account-row-badges { display: flex; flex-wrap: wrap; gap: 6px; }
.account-badge {
  font-size: 0.68rem; font-weight: 600; padding: 1px 6px; border-radius: var(--radius-xs);
  align-self: flex-start;
}
.account-badge-primary { background: var(--accent-tint); color: var(--accent-ink); }
.account-badge-pending { background: var(--warning-surface); color: var(--warning); }
.account-row-actions { display: flex; flex-direction: column; gap: 6px; flex-shrink: 0; align-items: flex-end; }

/* Welcome modal */
.welcome-overlay {
  position: fixed; inset: 0; z-index: 1100;
  display: flex; align-items: center; justify-content: center;
  padding: calc(env(safe-area-inset-top) + 20px) 20px calc(env(safe-area-inset-bottom) + 20px);
  background: var(--scrim);
}
.welcome-card {
  width: 100%; max-width: 440px;
  padding: 20px;
  display: flex; flex-direction: column; gap: 14px;
  max-height: 100%; overflow-y: auto;
}
.welcome-vibes { display: flex; flex-wrap: wrap; gap: 6px; }
.welcome-vibe {
  border: 1px solid var(--border-default); border-radius: 999px;
  background: var(--surface-canvas); color: var(--text-secondary);
  font: inherit; font-size: 0.78rem; font-weight: 600; cursor: pointer; padding: 5px 12px;
}
.welcome-vibe.active { background: var(--accent); border-color: var(--accent); color: var(--text-inverse); }
.welcome-title { font-size: 1.35rem; font-weight: 700; letter-spacing: -0.01em; }
.welcome-body { color: var(--text-secondary); white-space: pre-line; line-height: 1.6; }
/* Layout hook only — its look is .tt-btn--primary. It used to be a LAVENDER
   primary while every other primary action was ink: two answers to the same
   question, found by the design-system specimen (2026-09-23). */
.welcome-cta { align-self: flex-start; margin-top: 4px; }
/* --- Legal acceptance gate --- */
/* Deliberately blocking with no dismiss affordance, so it must win over
   EVERY other surface — the menu drawer/backdrop (1200/1210) and the guide
   overlay (1220), the two highest competing overlays in this file, both
   reachable via async races (menu opened before loadLegal() resolves; the
   self-heal path flips legalBlocking while the menu happens to be open).
   1500 sits clearly above all of that; only the non-interactive toast
   (2000, deliberately above every overlay for action feedback) outranks it. */
.legal-overlay { z-index: 1500; }
.legal-card { gap: 12px; }
.legal-doc {
  display: flex; flex-direction: column; gap: 3px;
  border: 1px solid var(--border-default); border-radius: var(--radius-sm);
  padding: 12px;
}
.legal-doc-title { font-weight: 600; }
.legal-doc-summary { color: var(--text-secondary); font-size: 0.88rem; line-height: 1.5; }
.legal-doc-link { color: var(--accent); font-size: 0.88rem; font-weight: 600; }
.legal-consent {
  display: flex; align-items: flex-start; gap: 8px; font: inherit;
  font-size: 0.88rem; color: var(--text-body); cursor: pointer;
}
.legal-consent input[type="checkbox"] { accent-color: var(--accent); margin-top: 2px; }
.legal-consent input:disabled { cursor: not-allowed; }
.legal-actions { display: flex; flex-wrap: wrap; gap: 10px; align-items: center; }
.legal-actions .welcome-cta { align-self: auto; margin-top: 0; }
/* --- Onboarding: getting-started card, milestone moments, what's new --- */
.onboard-card {
  padding: 12px 14px;
  margin: 0 0 14px;
}
.onboard-head { display: flex; align-items: center; gap: 8px; }
.onboard-title { font-weight: 600; font-size: 0.95rem; color: var(--text-body); }
.onboard-progress { margin-left: auto; font-size: 0.8rem; color: var(--text-secondary); }
.onboard-dismiss {
  background: none; border: none; padding: 4px; cursor: pointer;
  color: var(--text-secondary); width: 28px; height: 28px;
}
.onboard-dismiss:hover { color: var(--text-body); }
.onboard-dismiss svg { width: 16px; height: 16px; }
/* A step is a button that opens its guidance sheet (.tt-sheet). Full-width
   row, chevron at the end; 44px+ tall so it is an honest touch target. */
.onboard-step {
  display: flex; gap: 10px; align-items: center; width: 100%;
  min-height: 44px; padding: 7px 0; margin: 0;
  background: none; border: 0; border-top: 1px solid var(--border-subtle);
  font: inherit; text-align: left; color: inherit; cursor: pointer;
}
.onboard-step:first-of-type { border-top: 0; }
.onboard-step:hover .onboard-step-title { color: var(--accent-ink); }
.onboard-step:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: var(--radius-sm); }
.onboard-step-chev { width: 18px; height: 18px; margin-left: auto; color: var(--text-secondary); flex: none; }
.onboard-step-text { display: flex; flex-direction: column; gap: 1px; }
.onboard-step-progress { font-variant-numeric: tabular-nums; }
.onboard-step-title { font-size: 0.9rem; color: var(--text-body); }
.onboard-step-hint { font-size: 0.78rem; color: var(--text-secondary); }
.moment-body { margin: 8px 0 10px; font-size: 0.88rem; color: var(--text-secondary); }
.moment-cta {
  border: none; border-radius: var(--radius-sm);
  padding: 8px 14px; font-size: 0.85rem; font-weight: 600;
  background: var(--accent); color: var(--text-inverse); cursor: pointer;
}
.moment-cta:hover { background: var(--accent-hover); }
.whats-new-entry { display: flex; flex-direction: column; gap: 1px; padding: 7px 0; }
.whats-new-title { font-weight: 600; font-size: 0.88rem; color: var(--text-body); }
/* pre-line, because the body is rendered with x-text (textContent), which
   preserves no formatting of its own — without this every paragraph break in an
   entry collapses into one run-on block. Entries are plain text by design: the
   body is author-written but rendering it as HTML would make the what's-new
   table an injection surface for no benefit. */
.whats-new-body {
  font-size: 0.82rem; color: var(--text-secondary);
  white-space: pre-line;
}

/* Settings screen (admin — embeddings provider/fallback/backfill) */
#settings-screen {
  position: fixed; inset: 0; z-index: 900;
  background: var(--surface-canvas); color: var(--text-body);
  display: flex; flex-direction: column;
  padding-top: env(safe-area-inset-top); padding-bottom: env(safe-area-inset-bottom);
}
.settings-bar {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 16px; border-bottom: 1px solid var(--border-default);
}
.settings-title { font-weight: 700; }
.settings-close {
  border: none; background: none; color: var(--text-secondary);
  font: inherit; cursor: pointer; padding: 6px 10px;
}
.settings-body {
  overflow-y: auto; padding: 16px; display: flex; flex-direction: column;
  gap: 16px; width: 100%; max-width: 680px; margin: 0 auto;
}
.settings-card {
  padding: 16px;
  display: flex; flex-direction: column; gap: 14px;
}
.settings-card-title { font-weight: 600; font-size: 0.9rem; }
.settings-field-group { display: flex; flex-direction: column; gap: 6px; }
.settings-label { color: var(--text-secondary); font-size: 0.85rem; font-weight: 600; }
.settings-radio, .settings-checkbox {
  display: flex; align-items: center; gap: 8px; font: inherit; cursor: pointer;
}
.settings-radio input:disabled, .settings-checkbox input:disabled { cursor: not-allowed; }
.settings-hint { color: var(--text-secondary); font-size: 0.78rem; margin: 0; }
.settings-readonly {
  background: var(--surface-canvas); border: 1px solid var(--border-default);
  border-radius: var(--radius-sm); color: var(--text-secondary); font-size: 0.9rem; padding: 8px 12px;
}
.settings-counts { display: flex; gap: 12px; color: var(--text-secondary); font-size: 0.9rem; }
.settings-backfill-btn {
  align-self: flex-start;
  background: var(--accent); color: var(--text-inverse); border: none;
  border-radius: var(--radius-sm); font: inherit; font-weight: 600; cursor: pointer; padding: 9px 14px;
}
.settings-backfill-btn:disabled { opacity: 0.6; cursor: default; }

/* ── Ask There & Then panel ── */
.ask-close {
  display: inline-flex; align-items: center; justify-content: center;
  border: none; background: none; color: var(--text-secondary);
  cursor: pointer; padding: 4px;
}
.ask-close:hover { color: var(--text-body); }
/* Spaced from ✕ rather than adjacent: these do very different things and a
   mis-tap costs the user their conversation. */
.ask-new {
  display: inline-flex; align-items: center; justify-content: center;
  border: none; background: none; color: var(--text-secondary);
  font: inherit; cursor: pointer; padding: 6px 10px; margin-right: 4px;
}
.ask-new:hover { color: var(--text-body); }
/* Wraps .ask-new + .ask-close so their header position is set once, on the
   wrapper — neither button's placement depends on DOM order or on being
   `:last-child` of .overlay-head (that's exactly how this broke: grid
   auto-placement gave .ask-new the whole 1fr column-3 track and pushed
   .ask-close, the actual last-child match, onto row 2). */
.ask-bar .ask-head-actions {
  grid-column: 3; grid-area: 1 / 3; justify-self: end;
  display: inline-flex; align-items: center; gap: 4px;
}
.ask-input {
  width: 100%;
  padding: 12px;
}
.ask-deep {
  display: flex; align-items: center; gap: 8px;
  color: var(--text-secondary); font-size: 0.9rem; cursor: pointer;
}
/* Layout hook only — its look is .tt-btn--primary. */
.ask-btn { min-width: 100px; }
.ask-loading { display: flex; align-items: center; gap: 8px; color: var(--text-secondary); font-size: 0.9rem; }
.ask-answer-card {
  padding: 12px 14px;
}
.ask-answer-text { white-space: pre-wrap; font-size: 0.95rem; line-height: 1.5; }
/* The scope an answer was asked under. Deliberately quiet — it is context,
   not content — but always present so a narrowed answer is never mistaken
   for a complete one. */
.ask-answer-scope {
  margin-top: 8px; font-size: 0.75rem; color: var(--text-secondary);
}
.ask-sources { display: flex; flex-direction: column; gap: 8px; }
.ask-source-item { padding: 12px 14px; }

/* Ask overlay: fixed viewport, scrolling transcript, pinned composer.
   min-height:0 on the scroll child is what lets it actually scroll inside
   a flex column (same fix as v90). */
.ask-overlay {
  position: fixed; inset: 0; z-index: 1000;
  background: var(--surface-card); color: var(--text-body);
  display: flex; flex-direction: column;
  height: 100dvh;
  padding-top: env(safe-area-inset-top); padding-bottom: env(safe-area-inset-bottom);
}
.ask-bar {
  /* Full-bleed bar, centered content. .overlay-head's generic padding-inline
     rule (styles.css, `.overlay-head`) is `!important` and wins the cascade
     for the inline padding regardless of what's set here — this rule's own
     padding-inline value is byte-identical to that one, so the vertical
     padding + border below are the only parts this rule actually controls;
     the horizontal values are kept in sync for clarity, not because they win. */
  padding: 12px max(16px, calc((100% - 680px) / 2));
  border-bottom: 1px solid var(--border-default);
}
.ask-body {
  flex: 1; min-height: 0; overflow-y: auto;
  padding: 16px; display: flex; flex-direction: column; gap: 12px;
  width: 100%; max-width: 680px; margin: 0 auto;
}
.ask-turn-user {
  align-self: flex-end; max-width: 85%;
  background: var(--accent-tint); color: var(--text-body);
  border-radius: var(--radius-md); padding: 10px 14px;
  font-size: 0.95rem; line-height: 1.45;
}
.ask-answer-error { border-color: var(--border-default); color: var(--text-secondary); }
/* Attached to an otherwise-successful partial answer when the stream failed
   partway through (see runAsk's catch block) — distinct from the answer body
   itself, so it can't be mistaken for part of the model's reply. */
.ask-answer-note {
  margin: 8px 0 0; padding-top: 8px;
  border-top: 1px dashed var(--border-default);
  font-size: 0.82rem; font-style: italic; color: var(--error);
}
.ask-sources-toggle {
  display: inline-flex; align-items: center; gap: 6px;
  margin-top: 10px; padding: 4px 0;
  background: none; border: none; cursor: pointer;
  color: var(--text-secondary); font: inherit; font-size: 0.82rem;
}
.ask-sources-toggle:hover { color: var(--text-body); }
.ask-sources-chev { width: 16px; height: 16px; transition: transform 140ms ease; }
.ask-sources-chev.open { transform: rotate(90deg); }
.ask-source-photos { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.ask-source-thumb {
  width: 56px; height: 56px; object-fit: cover;
  border-radius: var(--radius-sm); cursor: pointer;
}
.ask-composer {
  border-top: 1px solid var(--border-default); padding: 10px 16px;
  display: flex; flex-direction: column; gap: 8px;
  width: 100%; max-width: 680px; margin: 0 auto;
}
.ask-composer-row { display: flex; align-items: center; gap: 8px; }
.ask-composer-row .ask-input { flex: 1; }

/* ── Shared site footer (login screen + legal pages) ── */
.site-footer {
  max-width: 42rem; margin: 40px auto 0; padding: 20px;
  border-top: 1px solid var(--border-default); text-align: center;
}
.footer-links { display: flex; gap: 18px; justify-content: center; flex-wrap: wrap; }
.footer-links a { color: var(--text-secondary); text-decoration: none; font-size: 0.9rem; }
.footer-links a:hover { color: var(--text-body); }
/* Footer action button styled to match the links (Export my data) */
.footer-action {
  border: none; background: none; cursor: pointer; padding: 0;
  color: var(--text-secondary); font: inherit; font-size: 0.9rem;
}
.footer-action:hover { color: var(--text-body); }
.footer-meta { color: var(--text-secondary); font-size: 0.8rem; margin-top: 10px; }

/* ============================================================
   Auto-categorization: per-note chips, filter banner, Insights
   ============================================================ */

/* Category chips under each memory */
.memory-categories {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  margin-top: 8px;
}
.category-chip {
  display: inline-flex; align-items: center; gap: 2px;
  padding: 1px 2px 1px 4px;
}
.category-chip-label {
  border: none; background: none; color: var(--text-secondary);
  font: inherit; font-size: 0.72rem; cursor: pointer; padding: 2px 6px;
  border-radius: 999px;
}
.category-chip-label:hover { color: var(--text-body); }
.category-chip-x {
  border: none; background: none; color: var(--text-secondary);
  font-size: 0.9rem; line-height: 1; cursor: pointer; padding: 0 6px 0 2px;
}
.category-chip-x:hover { color: var(--error); }
.category-add-chip {
  font: inherit; font-size: 0.72rem;
  cursor: pointer; padding: 2px 8px;
}
.category-add-chip:hover { color: var(--text-body); border-color: var(--accent); }

/* Category filter banner above the list */
/* Space view: header for the home list narrowed to a single space. */
.space-view-head {
  display: flex; align-items: center; gap: 10px;
  padding: 4px 0 10px;
}
.space-view-back {
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
  width: 34px; height: 34px; border-radius: 999px;
  border: 1px solid var(--border-default); background: transparent;
  color: var(--text-body); cursor: pointer;
}
.space-view-back .btn-icon { width: 18px; height: 18px; }
.space-view-back:focus-visible { outline: none; box-shadow: var(--shadow-focus); }
.space-view-info { display: flex; flex-direction: column; min-width: 0; }
.space-view-name {
  font-family: var(--font-display); font-weight: var(--fw-medium);
  letter-spacing: var(--ls-tight); line-height: var(--lh-heading);
  font-size: 1.15rem; color: var(--text-strong);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.space-view-meta { font-size: 0.8rem; color: var(--text-secondary); }
.category-filter-banner {
  display: flex; align-items: center; justify-content: space-between;
  background: var(--surface-card); border: 1px solid var(--border-default);
  border-radius: var(--radius-sm); padding: 8px 12px; margin-bottom: 8px;
  font-size: 0.8rem; color: var(--text-secondary);
}
.category-filter-banner strong { color: var(--text-body); }
.category-filter-clear {
  border: none; background: none; color: var(--accent);
  font: inherit; cursor: pointer; padding: 2px 6px;
}

/* Insights overlay */
.insights-overlay {
  position: fixed; inset: 0; z-index: 1000;
  background: var(--surface-card); color: var(--text-body);
  display: flex; flex-direction: column;
  padding-top: env(safe-area-inset-top); padding-bottom: env(safe-area-inset-bottom);
}
.insights-bar {
  display: flex; align-items: center; justify-content: space-between;
  padding: 12px 16px; border-bottom: 1px solid var(--border-default);
}
.insights-title { font-weight: 700; }
.insights-close {
  border: none; background: none; color: var(--text-secondary);
  font: inherit; cursor: pointer; padding: 6px 10px;
}
.insights-body {
  overflow-y: auto; padding: 16px; display: flex; flex-direction: column;
  gap: 10px; width: 100%; max-width: 680px; margin: 0 auto;
}
.insights-summary { color: var(--text-secondary); font-size: 0.85rem; margin-bottom: 6px; }
.insights-row {
  display: block; width: 100%; text-align: left; cursor: pointer;
  background: transparent; border-radius: var(--radius-md); padding: 10px 12px;
}
.insights-row:hover { background: var(--accent-tint); }
.insights-row-static { cursor: default; }
.insights-row-static:hover { background: transparent; }
.insights-row-head {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 6px;
}
.insights-cat { color: var(--text-body); font-size: 0.85rem; font-weight: 600; }
.insights-count { color: var(--text-secondary); font-size: 0.78rem; }
.insights-bar-track {
  height: 6px; background: var(--accent-tint);
  border-radius: var(--radius-pill); overflow: hidden;
}
.insights-bar-fill {
  height: 100%; background: var(--accent); border-radius: var(--radius-pill);
  min-width: 2px;
}

/* ============================================================
   Unified "Edit memory" bottom sheet + card pencil
   ============================================================ */

/* Pencil on each card — sits at the right end of the meta row */
.memory-meta { position: relative; }
.memory-edit-btn {
  margin-left: auto;
  border: none; background: none; color: var(--text-secondary);
  cursor: pointer; padding: 2px 4px; line-height: 0;
}
.memory-edit-btn .btn-icon { width: 15px; height: 15px; }
.memory-edit-btn:hover { color: var(--accent); }

/* Edit memory is a .tt-sheet (ds/components.css) since 2026-09-29; only its
   form layout lives here. */
.edit-form { display: flex; flex-direction: column; gap: 6px; }
.edit-field-label {
  font-size: 0.72rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.05em; color: var(--text-secondary); margin-top: 6px;
}
.edit-loc-current {
  display: flex; align-items: center; gap: 6px;
  font-size: 0.9rem; color: var(--text-body);
}
.edit-loc-current .btn-icon { width: 14px; height: 14px; flex-shrink: 0; color: var(--text-secondary); }
.edit-loc-actions { display: flex; gap: 8px; }
.edit-loc-actions .loc-current, .edit-loc-actions .loc-map-btn { flex: 1; }
.edit-sheet-cats { margin-top: 2px; }
/* The base .category-chip/.category-add-chip DS treatment (theme-aware
   accent-tint pill) now applies here directly — the light-only overrides
   this used to need (back when .edit-sheet was a fixed-white sheet) are
   gone. Only the functional (non-color) override remains. */
.edit-sheet-cats .category-chip-label { cursor: default; }
/* Markdown rendering inside the Ask answer (renderedAskAnswer output) */
.ask-md p { margin: 0 0 8px; }
.ask-md p:last-child { margin-bottom: 0; }
.ask-md .md-h { font-weight: 700; margin-top: 10px; }
.ask-md ul, .ask-md ol { margin: 0 0 8px 4px; padding-left: 18px; }
.ask-md li { margin: 2px 0; }
.ask-md code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.85em; background: var(--accent-tint);
  border-radius: 4px; padding: 1px 5px;
}

/* Deletion affordances */
/* Actionable-event badge on header icons (e.g. pending friend requests) */
.header-icon-btn { position: relative; }
.icon-badge {
  position: absolute; top: -2px; right: -4px;
  min-width: 16px; height: 16px; padding: 0 4px;
  border-radius: 999px; color: var(--text-on-accent);
  font-size: 0.65rem; font-weight: 700; line-height: 16px; text-align: center;
  box-shadow: 0 0 0 2px var(--surface-canvas);
}


/* Shared-space badge: provenance is always visible on shared notes */
.space-badge {
  display: inline-flex; align-items: center; gap: 5px;
  margin-top: 8px; padding: 2px 8px;
}
.space-badge .btn-icon { width: 11px; height: 11px; }
.space-badge-author { color: var(--text-secondary); }
.space-add-friends { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: 6px; }

/* --- Menu drawer + guide (header refactor) --- */
.menu-backdrop {
  position: fixed; inset: 0; background: var(--scrim); z-index: 1200;
}
.menu-drawer {
  /* Slides from the LEFT since v68 — the bloom menu button lives on the
     header's left as the dual-purpose logo. */
  position: fixed; top: 0; left: 0; bottom: 0; width: min(264px, 78vw);
  background: var(--surface-card); z-index: 1210;
  display: flex; flex-direction: column; padding: 14px 12px;
  padding-top: calc(env(safe-area-inset-top) + 14px);
  padding-bottom: calc(env(safe-area-inset-bottom) + 14px);
  box-shadow: 4px 0 24px rgba(0, 0, 0, 0.18);
  overflow-y: auto;
}
.menu-head { display: flex; align-items: center; justify-content: space-between; padding: 2px 6px 12px; }
.menu-title { font-weight: 600; }
.menu-item {
  display: flex; align-items: center; gap: 12px; width: 100%;
  background: none; border: none; cursor: pointer; text-align: left;
  color: var(--text-body); font-size: 0.95rem; padding: 12px 10px;
  border-radius: var(--radius-sm);
}
.menu-item:hover { background: rgba(127, 127, 127, 0.08); }
.menu-item .btn-icon { width: 20px; height: 20px; flex: none; }
.menu-subitem { padding-left: 42px; font-size: 0.9rem; color: var(--text-secondary); text-decoration: none; }
.menu-divider { border-top: 1px solid var(--border-default); margin: 8px 6px; }
.menu-signout { margin-top: auto; }

/* Theme segmented control in the drawer */
.menu-theme { display: flex; align-items: center; justify-content: space-between; padding: 10px 16px; }
.menu-theme-label { color: var(--text-secondary); font-size: 14px; }
.menu-theme-seg { display: flex; border: 1px solid var(--border-default); border-radius: var(--radius-pill); overflow: hidden; }
.menu-theme-seg button {
  border: 0; background: transparent; color: var(--text-secondary);
  font: inherit; font-size: 13px; padding: 6px 12px; cursor: pointer;
}
.menu-theme-seg button.active { background: var(--accent-soft); color: var(--text-on-accent); }
.menu-theme-seg button:focus-visible { outline: none; box-shadow: var(--shadow-focus); }

.menu-dot {
  position: absolute; top: 4px; right: 4px; width: 9px; height: 9px;
  border-radius: 50%;
}
.guide-overlay {
  position: fixed; inset: 0; background: var(--surface-card);
  z-index: 1220; overflow-y: auto; padding: 18px 16px;
  padding-top: calc(env(safe-area-inset-top) + 18px);
  padding-bottom: calc(env(safe-area-inset-bottom) + 18px);
}
.guide-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 4px; }
.guide-title { font-size: 1.15rem; font-weight: 700; }
.guide-progress { font-size: 0.82rem; color: var(--text-secondary); margin: 0 0 14px; }
.guide-step {
  display: flex; align-items: flex-start; gap: 12px; width: 100%;
  background: none; border: 1px solid var(--border-default); cursor: pointer;
  text-align: left; color: var(--text-body); border-radius: var(--radius-md);
  padding: 12px 14px; margin-bottom: 10px;
}
.guide-step-icon { width: 20px; height: 20px; margin-top: 1px; flex: none; }
.guide-step.done .guide-step-icon { color: var(--accent); }
.guide-step.done .guide-step-title { opacity: 0.65; }
.guide-step-title { display: block; font-size: 0.95rem; font-weight: 600; }
.guide-step-hint { display: block; font-size: 0.8rem; opacity: 0.6; margin-top: 1px; }

/* ── Typography pass (DS): serif headings, eyebrow labels, mono metadata ── */
.login-card h1, .welcome-title, .guide-title, .insights-title, .settings-title,
.admin-title, .heat-sheet-head, .moment-body strong {
  font-family: var(--font-display);
  font-weight: var(--fw-medium);
  letter-spacing: var(--ls-tight);
  color: var(--text-strong);
  line-height: var(--lh-heading);
}
.login-card h1 { font-size: 1.9rem; }

/* Eyebrow labels — one voice for every small uppercase section label */
.me-eyebrow, .memories-header, .edit-field-label,
.admin-card-title, .settings-label {
  font-family: var(--font-sans);
  font-weight: var(--fw-semibold);
  font-size: var(--text-xs);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: var(--text-muted);
}

/* Metadata rows in mono (timestamps, counts) */
.memory-meta, .footer-meta { font-family: var(--font-mono); }

/* Signature entrance — me-rise-in keyframes ship in ds/motion.css */
.memory-item, .ask-answer-card, .onboard-card, .welcome-card, .toast {
  animation: me-rise-in var(--dur-md) var(--ease-out) backwards;
}
.memory-item:nth-child(2) { animation-delay: 40ms; }
.memory-item:nth-child(3) { animation-delay: 80ms; }
.memory-item:nth-child(4) { animation-delay: 120ms; }
@media (prefers-reduced-motion: reduce) {
  .memory-item, .ask-answer-card, .onboard-card, .welcome-card, .toast { animation: none; }
}

/* ── Screen pass (DS): editorial Ask answers, insights accents, footer polish ── */
.ask-answer-text, .ask-md {
  font-family: var(--font-display);
  font-size: 1.1rem;
  line-height: var(--lh-relaxed);
}
.ask-md code {
  font-family: var(--font-mono); font-size: 0.82em;
  background: var(--surface-canvas); border-radius: var(--radius-xs); padding: 1px 4px;
}
.ask-source-item { border-left: 2px solid var(--accent-tint); }
.ask-deep { accent-color: var(--accent); }

.memory-list { gap: 16px; }
.empty-state { color: var(--text-secondary); }

.insights-bar-track { background: var(--accent-tint); }
.insights-bar-fill { background: var(--accent-soft); }
.insights-row:first-of-type .insights-bar-fill { background: var(--accent); }

.footer-links a { color: var(--text-muted); }
.footer-links a:hover { color: var(--accent-ink); text-decoration: none; }
.footer-meta { font-size: 12px; color: var(--text-muted); }

/* Friend invite: email/link actions + copy panel */
.friend-invite-actions { display: flex; gap: 8px; margin-top: 8px; }
.friend-link-btn {
  background: transparent; border: 1px solid var(--border-default);
  color: var(--text-body); border-radius: var(--radius-md);
  font-family: var(--font-sans); font-weight: var(--fw-semibold); font-size: 15px;
  padding: 8px 14px; cursor: pointer;
}
.friend-link-btn:focus-visible { outline: none; box-shadow: var(--shadow-focus); }
.friend-invite-link {
  margin-top: 10px; padding: 12px; background: var(--surface-canvas);
  border: 1px solid var(--border-subtle); border-radius: var(--radius-md);
}
.friend-invite-link code {
  display: block; font-family: var(--font-mono); font-size: 12px;
  word-break: break-all; margin-bottom: 8px; color: var(--text-body);
}

/* Floating scroll-to-top arrow (mobile-first: header scrolls away with the page) */
.scroll-top-btn {
  position: fixed; right: 16px;
  bottom: calc(20px + env(safe-area-inset-bottom, 0px));
  z-index: 800;
  width: 44px; height: 44px; border-radius: var(--radius-pill);
  display: flex; align-items: center; justify-content: center;
  background: var(--surface-card); color: var(--text-secondary);
  border: 1px solid var(--border-subtle); box-shadow: var(--shadow-md);
  cursor: pointer;
  animation: me-rise-in var(--dur-sm) var(--ease-out);
}
.scroll-top-btn:hover { color: var(--text-body); }
.scroll-top-btn:active { transform: translateY(1px); }
.scroll-top-btn:focus-visible { outline: none; box-shadow: var(--shadow-focus); }
@media (prefers-reduced-motion: reduce) { .scroll-top-btn { animation: none; } }

/* Invite-arrival note on the login card */
.login-invite-note {
  background: var(--accent-tint);
  border-radius: var(--radius-md);
  padding: 10px 14px;
  font-size: 0.9rem;
  line-height: 1.5;
  color: var(--text-body);
  margin-bottom: 14px;
  text-align: left;
}

/* Logged-in identity at the drawer's foot, beside Sign out */
.menu-user { display: flex; align-items: center; gap: 10px; padding: 10px 16px 6px; }
.menu-user-avatar, .menu-user-initial {
  width: 34px; height: 34px; border-radius: var(--radius-full); flex: none;
}
.menu-user-avatar { object-fit: cover; }
.menu-user-initial {
  display: flex; align-items: center; justify-content: center;
  background: var(--accent-soft); color: var(--text-on-accent);
  font-weight: var(--fw-semibold);
}
.menu-user-info { display: flex; flex-direction: column; min-width: 0; }
.menu-user-name { font-size: 0.92rem; font-weight: var(--fw-semibold); color: var(--text-body);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.menu-user-email { font-family: var(--font-mono); font-size: 0.72rem; color: var(--text-muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* Shared scope selector — horizontally scrolling chip row (capture + map).
   The designated pattern for all space/scope pickers (spec 2026-07-24). */
/* .tt-chip-row supplies display/gap; this keeps the capture row's horizontal
   scroll (a long list of spaces must not wrap the card taller) and its
   breathing room. nowrap beats the component's wrap here on purpose. */
.scope-chips {
  flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch;
  scrollbar-width: none; padding: 8px 2px 2px; white-space: nowrap;
}
.scope-chips::-webkit-scrollbar { display: none; }
.scope-chips > .tt-chip { flex: none; }
.scope-chips-map { max-width: 60vw; }

/* Spaces read as rose, category tags as lavender — distinct families in the
   memory list (Dylan 2026-07-24; re-applied v80 — the v78 attempt was lost
   to a killed shell and never committed). */
.space-badge, .space-badge-author {
  background: var(--accent-secondary-tint);
  color: var(--beta-badge-ink);
}
.space-badge-author { background: transparent; }

/* Overlay page headers (v81): bloom menu + wordmark left, true-centered
   title, close right — same brand affordance on every page. */
.overlay-head {
  display: grid !important;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
}
.overlay-head .overlay-menu-btn { justify-self: start; grid-column: 1; display: inline-flex; }
.overlay-head .overlay-wordmark { grid-column: 1; justify-self: start; margin-left: 44px; font-size: 1.05rem; }
.overlay-head .overlay-title {
  grid-column: 2; justify-self: center;
  font-family: var(--font-display); font-weight: var(--fw-medium);
  letter-spacing: var(--ls-tight); color: var(--text-strong); font-size: 1.05rem;
  white-space: nowrap;
}
.overlay-head > button:last-child { grid-column: 3; justify-self: end; }
.overlay-head .bloom-mark { width: 24px; height: 24px; }
@media (max-width: 430px) {
  /* Tight phones: brand shrinks to just the bloom; title stays centered */
  .overlay-head .overlay-wordmark { display: none; }
}

/* v82: Close buttons retired from overlay headers — the bloom menu (with its
   Timeline item) and the tap-home wordmark are the navigation. */
.overlay-head .overlay-wordmark { cursor: pointer; }
.overlay-head .overlay-wordmark:focus-visible { outline: none; box-shadow: var(--shadow-focus); border-radius: var(--radius-sm); }
.map-overlay-bar.overlay-head { grid-template-columns: 1fr auto 1fr; gap: 6px; }
.map-overlay-bar.overlay-head .scope-chips-map { grid-column: 1 / -1; grid-row: 2; max-width: none; padding-top: 6px; }
.map-overlay-bar.overlay-head .map-me-btn { grid-column: 3; justify-self: end; grid-row: 1; }

/* v83 fix: pin overlay-head children to row 1 explicitly — grid auto-placement
   was dropping the wordmark onto its own row (column set, row unset). The
   button and wordmark share cell 1/1 deliberately; the margin offsets the
   wordmark clear of the 40px button. */
.overlay-head .overlay-menu-btn { grid-area: 1 / 1; }
.overlay-head .overlay-wordmark { grid-area: 1 / 1; margin-left: 46px; align-self: center; }
.overlay-head .overlay-title { grid-area: 1 / 2; }
.map-overlay-bar.overlay-head .map-me-btn { grid-area: 1 / 3; }

/* v84: page-width consistency — overlay page content aligns to the app's
   680px column (bars stay full-bleed; their content centers). The Map keeps
   the column by default with an expand toggle for full-bleed. */
/* Bars only: bodies already carry max-width:680 + auto margins — adding
   viewport-relative padding to them crushed content to ~60px (v84 bug). */
.overlay-head {
  padding-inline: max(16px, calc((100% - 680px) / 2)) !important;
}
.map-canvas {
  max-width: 680px;
  margin-inline: auto;
  transition: max-width var(--dur-md) var(--ease-standard);
}
.map-canvas-expanded { max-width: none; }
@media (prefers-reduced-motion: reduce) { .map-canvas { transition: none; } }

/* v86: map gets the card treatment — pops like every other surface.
   Expanded mode goes back to edge-to-edge (no chrome). */
.map-canvas {
  width: calc(100% - 24px);
  margin: 12px auto;
  border: 1px solid var(--border-subtle);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-md);
  overflow: hidden;
}
.map-canvas-expanded {
  width: 100%;
  margin: 0;
  border: 0;
  border-radius: 0;
  box-shadow: none;
}

/* ============================================================
   Photos (Phase 4) — capture/edit attach, cover cards, viewer.
   ============================================================ */
.visually-hidden-input { display: none; }

/* Capture-card photo button — mirrors .mic-btn's box, swapped icon. */
.photo-btn {
  flex-shrink: 0;
  width: 48px; height: 48px;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--border-default);
  background: var(--surface-card);
  color: var(--text-secondary);
  border-radius: var(--radius-pill);
  cursor: pointer;
  transition: background var(--dur-sm) var(--ease-standard), color var(--dur-sm) var(--ease-standard);
}
.photo-btn:hover { background: var(--border-default); color: var(--text-body); }
.photo-btn:disabled { opacity: 0.5; cursor: default; }
.photo-btn svg { width: 20px; height: 20px; }

/* Staged photo thumbnails (capture card) + existing-photo thumbnails (edit
   sheet) share the same small-square treatment. */
:is(.capture-photo-list, .edit-photo-list) {
  display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px;
}
:is(.capture-photo-thumb, .edit-photo-thumb) {
  position: relative; width: 56px; height: 56px;
  border-radius: var(--radius-sm); overflow: hidden;
  border: 1px solid var(--border-subtle);
  flex-shrink: 0;
}
:is(.capture-photo-thumb, .edit-photo-thumb) img {
  width: 100%; height: 100%; object-fit: cover; display: block; cursor: pointer;
}
:is(.capture-photo-remove, .edit-photo-delete) {
  position: absolute; top: 2px; right: 2px;
  width: 18px; height: 18px; line-height: 16px; text-align: center;
  border: none; border-radius: 999px; cursor: pointer; padding: 0;
  background: color-mix(in srgb, var(--surface-ink) 55%, transparent);
  color: var(--white); font-size: 13px;
}
.edit-add-photos-btn {
  display: flex; align-items: center; gap: 6px;
  width: auto; height: 56px; padding: 0 12px;
  border: 1px dashed var(--border-default); border-radius: var(--radius-sm);
  background: transparent; color: var(--text-secondary);
  font: inherit; font-size: 0.85rem; font-weight: 600; cursor: pointer;
}
.edit-add-photos-btn:hover { background: var(--surface-canvas); }
.edit-add-photos-btn:disabled { opacity: 0.5; cursor: default; }
.edit-add-photos-btn .btn-icon { width: 16px; height: 16px; }

/* Cover card — edge-to-edge photo atop the memory card, text below
   unaffected. Negative margins cancel .memory-item's own padding so the
   image runs to the card's rounded edge (radius-inherit via the top
   corners of --radius-lg, matching the card itself). */
.memory-cover {
  position: relative;
  margin: -14px -16px 10px;
  height: 190px;
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  overflow: hidden;
  cursor: pointer;
  background: var(--surface-canvas);
}
.memory-cover-img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Multi-photo cover: mosaic grid (1 = full, 2 = split, 3 = 1+2, 4 = 2x2). The
   2px gap shows the card canvas as a hairline divider between tiles. */
.memory-mosaic { display: grid; gap: 2px; background: var(--surface-canvas); }
.memory-mosaic.m1 { grid-template-columns: 1fr; }
.memory-mosaic.m2 { grid-template-columns: 1fr 1fr; }
.memory-mosaic.m3, .memory-mosaic.m4 { grid-template-columns: 1fr 1fr; grid-template-rows: 1fr 1fr; }
.memory-mosaic.m3 .mosaic-lead { grid-row: 1 / span 2; }
.memory-mosaic-tile { position: relative; overflow: hidden; cursor: pointer; }
.memory-mosaic-tile img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Photo loading: the tile itself is the placeholder (a gently pulsing surface),
   and the image fades in over it once decoded. Images are only rendered once a
   photo token exists — without one the request 401s and the browser paints its
   broken-image icon, which is what this replaces. */
:is(.memory-mosaic-tile, .edit-photo-thumb) { background: var(--surface-canvas); }
:is(.memory-mosaic-tile, .edit-photo-thumb, .photo-viewer-slide) > img {
  opacity: 0; transition: opacity var(--dur-md) var(--ease-out);
}
:is(.memory-mosaic-tile, .edit-photo-thumb, .photo-viewer-slide) > img.is-loaded {
  opacity: 1;
}
:is(.memory-mosaic-tile, .edit-photo-thumb):not(:has(img.is-loaded)) {
  animation: photo-skeleton 1.4s ease-in-out infinite;
}
@keyframes photo-skeleton {
  0%, 100% { background-color: var(--surface-canvas); }
  50%      { background-color: var(--surface-raised); }
}
@media (prefers-reduced-motion: reduce) {
  :is(.memory-mosaic-tile, .edit-photo-thumb):not(:has(img.is-loaded)) { animation: none; }
  :is(.memory-mosaic-tile, .edit-photo-thumb, .photo-viewer-slide) > img { transition: none; }
}
.photo-count-badge {
  position: absolute; top: 8px; right: 8px;
  padding: 3px 9px; border-radius: var(--radius-pill);
  background: color-mix(in srgb, var(--surface-ink) 55%, transparent);
  color: var(--white); font-size: 0.72rem; font-weight: 600;
}

/* Full-screen photo viewer — deliberately theme-fixed (black stage), like a
   standard photo-viewer surface rather than app chrome; sits above every
   other overlay except the menu drawer/toast. */
.photo-viewer {
  position: fixed; inset: 0; z-index: 1150; overflow: hidden;
  background: var(--black); color: var(--white);
  display: flex; flex-direction: column;
  padding-top: env(safe-area-inset-top); padding-bottom: env(safe-area-inset-bottom);
}
.photo-viewer-bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 8px; padding: 10px 12px; flex-shrink: 0;
}
.photo-viewer-close {
  border: none; background: none; color: var(--white); cursor: pointer; padding: 6px; line-height: 0;
}
.photo-viewer-close .btn-icon { width: 20px; height: 20px; }
.photo-viewer-count { font-size: 0.85rem; opacity: 0.8; }
.photo-viewer-delete {
  border: none; background: none; color: var(--white); cursor: pointer;
  padding: 6px; line-height: 0;
}
.photo-viewer-delete .btn-icon { width: 20px; height: 20px; }
.photo-viewer-delete:hover { color: color-mix(in srgb, var(--white) 80%, transparent); }
.photo-viewer-stage {
  position: relative; flex: 1; min-height: 0; display: flex;
}
.photo-viewer-scroll {
  flex: 1; min-width: 0; width: 100%; display: flex; overflow-x: auto;
  scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch;
}
.photo-viewer-slide {
  flex: 0 0 100%; scroll-snap-align: center;
  display: flex; align-items: center; justify-content: center;
  padding: 8px;
}
.photo-viewer-nav {
  position: absolute; top: 50%; transform: translateY(-50%); z-index: 2;
  display: flex; align-items: center; justify-content: center;
  width: 40px; height: 40px; border-radius: 999px; border: none;
  background: color-mix(in srgb, var(--black) 45%, transparent);
  color: var(--white); cursor: pointer;
}
.photo-viewer-nav .btn-icon { width: 22px; height: 22px; }
.photo-viewer-prev { left: 8px; }
.photo-viewer-next { right: 8px; }
.photo-viewer-img { max-width: 100%; max-height: 100%; object-fit: contain; display: block; }

/* Friend rename — deliberately quiet. The pencil is invisible until the row is
   hovered or the button focused, so the friends list doesn't grow a column of
   icons; keyboard users still reach it via :focus-visible. Sized to the 44px
   touch guidance despite the small glyph. */
.friend-name-line { display: inline-flex; align-items: center; gap: 2px; }
.friend-rename-btn {
  background: none; border: 0; padding: 10px; margin: -10px 0 -10px -2px;
  color: var(--text-secondary); cursor: pointer; line-height: 0;
  opacity: 0; transition: opacity .12s;
}
.friend-rename-btn svg { width: 14px; height: 14px; }
.admin-invite-row:hover .friend-rename-btn,
.friend-rename-btn:focus-visible { opacity: 1; }
.friend-rename-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 0; border-radius: 4px; }
@media (hover: none) { .friend-rename-btn { opacity: .55; } }

/* --- Delete-account confirmation --- */
/* Above the legal gate (1500): the "You've declined" card is one of the two
   entry points, so this has to win over it. Only the toast (2000) is higher. */
.delete-overlay { z-index: 1600; }
.delete-card { gap: 12px; }
.delete-whose {
  display: flex; flex-direction: column; gap: 2px;
  border: 1px solid var(--border-default); border-left: 3px solid var(--error);
  border-radius: var(--radius-sm); padding: 10px 12px;
}
.delete-whose-label { color: var(--text-secondary); font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.06em; }
.delete-whose-name { font-weight: 700; font-size: 1rem; word-break: break-word; }
.delete-whose-email { color: var(--text-secondary); font-size: 0.85rem; word-break: break-all; }
.delete-outcomes { display: flex; flex-direction: column; gap: 10px; }
.delete-outcome {
  display: flex; flex-direction: column; gap: 3px;
  border: 1px solid var(--border-default); border-radius: var(--radius-sm);
  padding: 11px 12px;
}
.delete-outcome-head { font-weight: 600; font-size: 0.92rem; }
.delete-outcome-note { color: var(--text-secondary); font-size: 0.85rem; line-height: 1.5; }
.delete-export {
  display: flex; flex-direction: column; gap: 8px;
  border: 1px solid var(--border-default); border-radius: var(--radius-sm);
  background: var(--surface-canvas); padding: 12px;
}
.delete-export .welcome-body { font-size: 0.88rem; }
.delete-export-btn { align-self: flex-start; margin-top: 0; }
.delete-gate { display: flex; flex-direction: column; gap: 6px; font-size: 0.88rem; }
.delete-gate input {
  /* 16px, NOT `font: inherit`. iOS Safari zooms the whole page when a text
     input under 16px takes focus, and does NOT zoom back out on blur — so
     typing DELETE here left the page zoomed, and the login screen you land on
     afterwards ran off the right edge. Reported from a real phone; every other
     text input in the app was already 16px and this one was the anomaly. */
  font-family: inherit; font-size: 16px; letter-spacing: 0.08em; text-transform: uppercase;
  border: 1px solid var(--border-default); border-radius: var(--radius-sm);
  background: var(--surface-card); color: var(--text-body); padding: 10px 12px;
}
.delete-gate input:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
/* --- Admin page (/admin/) --- */
.admin-leave-link {
  color: var(--text-secondary); font-size: 0.88rem; font-weight: 600;
  text-decoration: none; padding: 8px 4px; white-space: nowrap;
}
.admin-leave-link:hover { color: var(--text-body); }
@media (max-width: 420px) {
  /* The app fits an ICON in this slot (Ask); 89px of text does not, and at
     320px it pushed the whole page 8px wide. The exit is in the drawer — where
     it belongs anyway — and the wordmark also leads back to /app/. */
  .admin-leave-link { display: none; }
}
/* Sections are the flex children of .admin-body now, so the 16px gap that used
   to sit between CARDS lands between sections instead — which made two cards
   in one section touch. Re-establish it inside the section. */
.admin-body > section {
  display: flex; flex-direction: column; gap: 16px;
}
/* Admin is its own page now, so these are the only styles it adds on top of
   the shared .admin-* card styles it inherits from the old overlay. */
/* "Leave admin" lives in the drawer with the sections, because that is where
   someone goes looking for the way out. Separated by a rule so it reads as an
   exit rather than a seventh place to go. */
.menu-leave {
  margin-top: 10px; padding-top: 14px;
  border-top: 1px solid var(--border-default);
  text-decoration: none;
}
/* The section you are in. The app's menu has no equivalent — its items all
   navigate away — so this borrows the hover tint rather than inventing a
   treatment, and 600 to sit in the same family as the rest of the drawer. */
.menu-item.current { background: rgba(127, 127, 127, 0.08); font-weight: 600; }
/* Same shape as .admin-invite-row — identity on the left, actions on the
   right, a thin rule between rows. A bordered box would be a container type
   this design system does not use for lists. */
.admin-message {
  /* STACKED by default, unlike .admin-invite-row. An invite row holds one
     short line, so content-left/actions-right fits a phone; a message holds a
     paragraph, and the same layout squeezed it into a 100px column where every
     word wrapped onto its own line. Side by side only once there is room. */
  display: flex; flex-direction: column; gap: 6px;
  padding: 10px 0; border-bottom: 1px solid var(--border-default);
}
.admin-message .friend-identity { min-width: 0; }
/* "Reply" is an <a> so it can be a mailto:, but it is a BUTTON in the layout —
   without this it wears a link underline none of its neighbours have. */
@media (min-width: 640px) {
  .admin-message { flex-direction: row; align-items: flex-start; justify-content: space-between; gap: 12px; }
}
.admin-message.handled { opacity: .55; }
.admin-message-head { display: flex; flex-wrap: wrap; gap: 6px; align-items: baseline; }
.admin-message-meta { color: var(--text-secondary); font-size: 0.78rem; }
.admin-message-body {
  white-space: pre-wrap; overflow-wrap: anywhere;
  font-size: 0.9rem; line-height: 1.5; margin-top: 2px;
}
.admin-show-handled { align-self: flex-start; margin-top: 10px; }

/* --- Capture: the note box is the screen ------------------------------ */
/* Auto-grow. The height is set in JS from scrollHeight; this holds the
   resting size and stops the manual drag handle fighting it. */
#memory-text { min-height: 132px; resize: none; overflow: hidden; font-size: 16px; }

/* The location chip is a CONTROL now, not a status light: it opens the place
   picker. A chosen place replaces the GPS text, because it replaces what gets
   saved. */
/* The location chip is a .tt-chip now (ds/components.css); only its place in
   the capture card's flow belongs here. */
.place-chip { margin-top: 8px; }

.place-panel {
  margin-top: 12px; padding-top: 12px;
  border-top: 1px solid var(--border-subtle);
  display: flex; flex-direction: column; gap: 8px;
}
.place-panel-label {
  font-size: 12px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--text-secondary);
}
.place-list { display: flex; flex-direction: column; gap: 2px; }
/* Location help (Helm 32): stays open until dismissed or location works. */
.gps-help {
  padding: 12px 14px; border-radius: var(--radius-md);
  background: var(--accent-tint); color: var(--text-body);
  font-size: 0.9rem; line-height: 1.45;
}
.gps-help p { margin: 0 0 8px; }
.gps-help ol { margin: 0; padding-left: 1.2em; display: flex; flex-direction: column; gap: 6px; }
.gps-help-actions { margin-top: 10px; }
.linkish-btn {
  background: none; border: none; padding: 0; font: inherit; font-weight: 600;
  color: var(--accent-ink); cursor: pointer; text-decoration: underline;
}
.place-row {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  width: 100%; text-align: left; font: inherit; cursor: pointer;
  background: none; border: none; border-radius: var(--radius-md);
  padding: 10px; color: var(--text-body);
}
.place-row:hover { background: var(--accent-tint); }
.place-row-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.place-row-hint { font-size: 12px; color: var(--text-secondary); flex: none; }

/* --- Recent: three, and an honest count ------------------------------- */
.memories-header-title { display: inline-flex; align-items: baseline; gap: 8px; }
.memories-count {
  text-transform: none; letter-spacing: 0; font-weight: 400;
  color: var(--text-secondary); font-variant-numeric: tabular-nums;
}
/* Layout hook only — its look is .tt-btn--secondary / --quiet. */
.see-all-btn { margin-top: 12px; }
.recent-filters { margin-bottom: 12px; }   /* layout; .tt-chip-row supplies the rest */

/* --- Admin: design-system specimen ------------------------------------ */
.ds-group { display: flex; flex-direction: column; gap: 6px; }
.ds-group + .ds-group { margin-top: 10px; }
.ds-group-name, .ds-caption {
  font-size: 12px; color: var(--text-secondary); margin: 0;
}
.ds-group-name { font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; }
.ds-caption code, .admin-hint code {
  font-family: var(--font-mono); font-size: 0.92em;
}
.ds-swatches { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; }
.ds-swatch {
  display: grid; grid-template-columns: 28px 1fr; grid-template-rows: auto auto;
  column-gap: 8px; align-items: center;
  padding: 6px; border: 1px solid var(--border-subtle); border-radius: var(--radius-sm);
}
.ds-swatch-chip {
  grid-row: 1 / 3; width: 28px; height: 28px; border-radius: 6px;
  border: 1px solid var(--border-subtle);
}
.ds-swatch-name { font-family: var(--font-mono); font-size: 11px; color: var(--text-body); overflow-wrap: anywhere; }
.ds-swatch-value { font-family: var(--font-mono); font-size: 11px; color: var(--text-secondary); overflow-wrap: anywhere; }

.ds-type { display: flex; flex-direction: column; gap: 2px; }
.ds-type-sample { margin: 10px 0 0; color: var(--text-strong); }
.ds-type-wordmark { font-size: 28px; }
.ds-type-display { font-family: var(--font-display); font-size: 24px; font-weight: 500; }
.ds-type-body { font-size: 16px; color: var(--text-body); }
.ds-type-mono { font-family: var(--font-mono); font-size: 13px; color: var(--text-secondary); }
.ds-type-eyebrow { font-size: 12px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-secondary); }

.ds-demo { display: flex; flex-direction: column; gap: 6px; }
.ds-demo + .ds-demo { margin-top: 12px; padding-top: 12px; border-top: 1px dashed var(--border-subtle); }
.ds-row { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }

/* Login-card actions: tt-btn stacked on the rhythm .btn used to give them. */
.login-btn { margin-bottom: 10px; }

/* Getting started guidance sheet (Dylan 2026-09-29). Structure is
   .tt-sheet; these are only the pieces of its body. */
.step-sheet-why { margin: 0 0 12px; }
.step-sheet-label {
  margin: 14px 0 6px; font-size: 0.72rem; font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.06em; color: var(--text-secondary);
}
.step-sheet-how { margin: 0; padding-left: 1.3em; display: flex; flex-direction: column; gap: 6px; }
.step-sheet-done-when { margin: 0; color: var(--text-secondary); }
.step-sheet-blocker {
  margin: 0 0 12px; padding: 10px 12px; border-radius: var(--radius-md);
  background: var(--accent-tint); color: var(--text-body);
}
.step-sheet-status {
  display: inline-flex; align-items: center; gap: 6px; margin: 0 0 10px;
  font-weight: 600; color: var(--success);
}
.step-sheet-status svg { width: 18px; height: 18px; }
.step-sheet-progress { display: flex; align-items: center; gap: 10px; margin: 0 0 12px; font-size: 0.85rem; color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.step-sheet-progress .tt-progress { flex: 1; }
