/* =====================================================================
   ECHOED MOMENTS — App & Auth screens
   Extends the landing design system (em.css). Built on the same tokens:
   Echo Blue / Moment Gold, Poppins (display) + Mulish (body), warm paper.
   These screens are NOT in the original design file — they are designed
   here to be consistent with the landing page's system.
   ===================================================================== */

/* ---- generic app page shell --------------------------------------- */
.app-body { background: var(--canvas); min-height: 100vh; display: flex; flex-direction: column; }

/* landing/auth header sign-in link */
.app-header .signin {
  font-family: var(--font-display); font-weight: 600; font-size: var(--text-sm);
  color: var(--ink-800); text-decoration: none; margin-right: 4px;
}
.app-header .signin:hover { color: var(--blue-600); }

/* inline notice (allauth alerts, form-level messages) */
.notice {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 14px 16px; border-radius: var(--radius-md);
  border: 1px solid var(--border); border-left-width: 4px;
  font-family: var(--font-body); font-size: var(--text-sm); color: var(--fg1);
  margin-bottom: 20px; background: var(--surface);
}
.notice .ic { width: 18px; height: 18px; flex: none; margin-top: 1px; }
.notice-error { border-left-color: var(--danger); background: var(--danger-bg); }
.notice-error .ic { color: var(--danger); }
.notice-success { border-left-color: var(--success); background: var(--success-bg); }
.notice-success .ic { color: var(--success); }
.notice-info { border-left-color: var(--echo-blue); background: var(--wash-blue); }
.notice-info .ic { color: var(--echo-blue); }

/* simple data table (allauth manage screens) */
.data-table { width: 100%; border-collapse: collapse; font-family: var(--font-body); font-size: var(--text-sm); }
.data-table th, .data-table td { text-align: left; padding: 12px 14px; border-bottom: 1px solid var(--border); }
.data-table th { font-weight: 700; color: var(--fg3); text-transform: uppercase; letter-spacing: .06em; font-size: var(--text-xs); }

.page-head-action { flex: none; }

/* ---- error pages -------------------------------------------------- */
.error-page {
  flex: 1; display: flex; align-items: center; justify-content: center;
  text-align: center; padding: clamp(48px, 9vw, 120px) 24px;
}
.error-page .error-inner { max-width: 480px; }
.error-page .error-code {
  font-family: var(--font-display); font-weight: 700; line-height: 1;
  font-size: clamp(4rem, 14vw, 7rem); color: var(--blue-100); letter-spacing: -0.04em; margin: 0 0 8px;
}
.error-page h1 { font-family: var(--font-display); font-weight: 700; font-size: var(--text-2xl); color: var(--fg1); margin: 0 0 12px; }
.error-page p { font-family: var(--font-body); color: var(--fg2); margin: 0 auto 28px; max-width: 40ch; }
.error-page .spark { margin: 0 auto 24px; }

/* simplified app header (logged-in / app context) */
.app-header {
  position: sticky; top: 0; z-index: 40;
  background: color-mix(in srgb, var(--canvas) 86%, transparent);
  backdrop-filter: blur(18px); -webkit-backdrop-filter: blur(18px);
  border-bottom: 1px solid var(--border);
}
.app-header-inner {
  max-width: 1180px; margin: 0 auto; padding: 14px 32px;
  display: flex; align-items: center; justify-content: space-between; gap: 20px;
}
.app-header .logo { height: 26px; }
.app-header .header-cta { display: flex; gap: 12px; align-items: center; }
.app-header .btn { padding: 10px 20px; font-size: var(--text-sm); }

/* avatar chip */
.avatar {
  width: 38px; height: 38px; border-radius: var(--radius-pill);
  background: var(--wash-blue); color: var(--blue-600);
  display: flex; align-items: center; justify-content: center;
  font-family: var(--font-display); font-weight: 700; font-size: var(--text-base);
  border: 1px solid var(--blue-100); cursor: pointer; text-decoration: none;
}

/* avatar dropdown menu */
.avatar-menu { position: relative; }
.avatar-dropdown {
  position: absolute; right: 0; top: calc(100% + 10px); z-index: 50;
  min-width: 232px; background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg); padding: 8px; overflow: hidden;
}
.avatar-dropdown[hidden] { display: none; }
.avatar-id { padding: 10px 12px 12px; border-bottom: 1px solid var(--border); margin-bottom: 6px; }
.avatar-id-name { display: block; font-family: var(--font-display); font-weight: 700; font-size: var(--text-sm); color: var(--fg1); }
.avatar-id-email { display: block; font-family: var(--font-body); font-size: var(--text-xs); color: var(--fg3); margin-top: 2px; word-break: break-all; }
.avatar-item {
  display: flex; align-items: center; gap: 11px; width: 100%;
  padding: 10px 12px; border-radius: var(--radius-xs);
  font-family: var(--font-body); font-weight: 600; font-size: var(--text-sm);
  color: var(--fg2); text-decoration: none; background: none; border: none; cursor: pointer; text-align: left;
}
.avatar-item .ic { width: 17px; height: 17px; }
.avatar-item:hover { background: var(--bg-sunk); color: var(--ink-800); }
.avatar-item.is-danger { color: var(--danger); }
.avatar-item.is-danger:hover { background: var(--danger-bg); }
.avatar-logout { margin: 6px 0 0; padding: 6px 0 0; border-top: 1px solid var(--border); }

/* =====================================================================
   AUTH LAYOUT — split: brand panel + form card
   ===================================================================== */
.auth {
  flex: 1; display: grid; grid-template-columns: 1.05fr 1fr; min-height: 100vh;
}
.auth-aside {
  position: relative; overflow: hidden; color: #fff;
  background-color: var(--ink-900);
  background-image:
    linear-gradient(to bottom, rgba(10,15,24,.62), rgba(10,15,24,.82)),
    url("../images/design/hero.801735669bbb.jpg");
  background-size: cover; background-position: center 42%;
  padding: clamp(40px, 5vw, 72px);
  display: flex; flex-direction: column; justify-content: space-between;
}
.auth-aside .logo { height: 30px; filter: brightness(0) invert(1); }
.auth-aside .mark {
  position: absolute; right: -120px; bottom: -40px; width: min(420px, 50%);
  opacity: .08; filter: brightness(0) invert(1); pointer-events: none;
}
.auth-aside-body { position: relative; z-index: 1; max-width: 30ch; }
.auth-aside-body .spark { margin-bottom: 28px; }
.auth-aside-body h2 {
  font-family: var(--font-display); font-weight: 700; color: #fff;
  font-size: clamp(1.9rem, 2.6vw, 2.6rem); line-height: 1.1; letter-spacing: -0.02em;
  margin: 0 0 18px;
}
.auth-aside-body p { font-family: var(--font-body); color: rgba(255,255,255,.8); font-size: var(--text-md); line-height: 1.55; margin: 0; }
.auth-aside-foot { position: relative; z-index: 1; font-family: var(--font-body); font-size: var(--text-sm); color: rgba(255,255,255,.6); }

.auth-main {
  display: flex; align-items: center; justify-content: center;
  padding: clamp(32px, 5vw, 64px); background: var(--canvas);
}
.auth-card { width: 100%; max-width: 440px; }
.auth-card .eyebrow { margin-bottom: 14px; }
.auth-card h1 {
  font-family: var(--font-display); font-weight: 700; color: var(--fg1);
  font-size: var(--text-2xl); letter-spacing: -0.02em; margin: 0 0 10px; line-height: 1.1;
}
/* Base subtitle treatment so a `.sub` used outside .auth-card / .page-head
   (e.g. signup and password-reset inside .card.pad-lg) is still styled. The
   scoped rules below/above override this where they apply. */
.sub { font-family: var(--font-body); color: var(--fg2); font-size: var(--text-md); line-height: var(--leading-normal); margin: 0 0 var(--space-6); }
.auth-card .sub { font-family: var(--font-body); color: var(--fg2); font-size: var(--text-md); margin: 0 0 32px; line-height: 1.5; }
.auth-foot { margin-top: 28px; font-family: var(--font-body); font-size: var(--text-sm); color: var(--fg2); text-align: center; }
.auth-foot a { color: var(--blue-600); font-weight: 700; text-decoration: none; }
.auth-foot a:hover { text-decoration: underline; }

/* mobile-only top bar for auth */
.auth-mobile-top { display: none; }

/* =====================================================================
   FORMS
   ===================================================================== */
.field { margin-bottom: 20px; }
.field > label {
  display: block; font-family: var(--font-body); font-weight: 700;
  font-size: var(--text-sm); color: var(--ink-700); margin-bottom: 8px;
}
.input, .select, .textarea {
  width: 100%; font-family: var(--font-body); font-size: var(--text-base);
  color: var(--fg1); background: var(--surface);
  border: 1.5px solid var(--border-strong); border-radius: var(--radius-sm);
  padding: 13px 16px; transition: border-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
}
.input::placeholder, .textarea::placeholder { color: var(--fg3); }
.input:focus, .select:focus, .textarea:focus {
  outline: none; border-color: var(--echo-blue);
  box-shadow: 0 0 0 4px rgba(21,138,255,.14);
}
.textarea { resize: vertical; min-height: 120px; line-height: 1.55; }
.input-wrap { position: relative; display: flex; align-items: center; }
.input-wrap .input { padding-right: 46px; }
.input-toggle {
  position: absolute; right: 6px; width: 34px; height: 34px; border: none; background: none;
  color: var(--fg3); cursor: pointer; display: flex; align-items: center; justify-content: center;
  border-radius: var(--radius-xs);
}
.input-toggle:hover { color: var(--ink-700); background: var(--bg-sunk); }
.input-toggle .ic { width: 18px; height: 18px; }
.field-hint { font-family: var(--font-body); font-size: var(--text-xs); color: var(--fg3); margin-top: 7px; }
/* Hints that lead with a glyph (e.g. the recipient notes in the create modal)
   would otherwise get lucide's unstyled 24px default. */
.field-hint .ic { width: 15px; height: 15px; flex: none; vertical-align: -2px; }
/* label row with a trailing char counter (e.g. title 0/50) */
.label-row { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.char-count { font-family: var(--font-body); font-weight: 700; font-size: var(--text-xs); color: var(--fg3); font-variant-numeric: tabular-nums; transition: color var(--dur-fast); }
.char-count.is-warn { color: var(--danger); }
.field-error { font-family: var(--font-body); font-size: var(--text-xs); color: var(--danger); margin-top: 7px; }
.field.has-error .input { border-color: var(--danger); }

.form-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 24px; }
.checkline { display: inline-flex; align-items: center; gap: 9px; font-family: var(--font-body); font-size: var(--text-sm); color: var(--fg2); cursor: pointer; }
.checkline input { width: 17px; height: 17px; accent-color: var(--echo-blue); }
.link-sm { font-family: var(--font-body); font-size: var(--text-sm); color: var(--blue-600); font-weight: 700; text-decoration: none; }
.link-sm:hover { text-decoration: underline; }

.btn-block { width: 100%; }
.btn-lg { padding: 16px 30px; font-size: var(--text-md); }

/* =====================================================================
   GENERIC APP MAIN / SECTION CONTAINERS
   ===================================================================== */
.app-main { flex: 1; padding: clamp(32px, 5vw, 56px) 0 96px; }
.app-wrap { max-width: 1100px; margin: 0 auto; padding: 0 32px; }
.app-wrap-narrow { max-width: 760px; margin: 0 auto; padding: 0 32px; }

.page-head { display: flex; align-items: flex-end; justify-content: space-between; gap: 24px; margin-bottom: 36px; flex-wrap: wrap; }
.page-head .eyebrow { margin-bottom: 10px; }
.page-head h1 { font-family: var(--font-display); font-weight: 700; font-size: var(--text-2xl); letter-spacing: -0.02em; color: var(--fg1); margin: 0; }
.page-head .sub { font-family: var(--font-body); color: var(--fg2); margin: 8px 0 0; max-width: 52ch; }

.back-link { display: inline-flex; align-items: center; gap: 8px; font-family: var(--font-body); font-weight: 700; font-size: var(--text-sm); color: var(--fg2); text-decoration: none; margin-bottom: 22px; }
.back-link .ic { width: 16px; height: 16px; }
.back-link:hover { color: var(--echo-blue); }

/* card surface */
.card {
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-lg); box-shadow: var(--shadow-sm); padding: 32px;
}
.card.pad-lg { padding: clamp(32px, 4vw, 48px); }

/* =====================================================================
   VAULT DASHBOARD
   ===================================================================== */
.vault-hero {
  position: relative; overflow: hidden; color: #fff;
  border-radius: var(--radius-xl); padding: clamp(32px, 4vw, 48px);
  min-height: 230px; display: flex; align-items: center;
  background: linear-gradient(135deg, var(--blue-700) 0%, var(--echo-blue) 55%, var(--blue-500) 100%);
  box-shadow: 0 24px 56px rgba(21,138,255,.28); margin-bottom: 40px;
}
.vault-hero .cta-spark { position: absolute; right: -50px; top: -60px; width: 220px; height: 220px; border-radius: 999px; background: radial-gradient(circle, rgba(249,192,11,.32), transparent 65%); pointer-events: none; z-index: 1; }
/* photographic layer on the right, faded into the blue toward the text */
.vault-hero .vault-hero-media {
  position: absolute; inset: 0 0 0 auto; z-index: 0; pointer-events: none;
  /* cover fills the layer edge-to-edge (no internal hard edge), so a long
     left-to-right mask can dissolve the whole photo into the gradient with no
     seam. The layer is wide and the fade gradual, so the blend reads as one
     surface rather than a pasted rectangle. */
  width: 62%;
  background-size: cover;
  background-repeat: no-repeat;
  background-position: 50% 38%;
  -webkit-mask-image: linear-gradient(to right, transparent 0%, transparent 8%, rgba(0,0,0,.5) 48%, #000 100%);
  mask-image: linear-gradient(to right, transparent 0%, transparent 8%, rgba(0,0,0,.5) 48%, #000 100%);
  opacity: .9;
}
.vault-hero-inner { position: relative; z-index: 2; display: flex; align-items: center; justify-content: space-between; gap: 28px; flex-wrap: wrap; }
.vault-hero h1 { font-family: var(--font-display); font-weight: 700; font-size: var(--text-2xl); color: #fff; margin: 0 0 10px; letter-spacing: -0.02em; }
.vault-hero p { font-family: var(--font-body); color: rgba(255,255,255,.88); margin: 0; max-width: 48ch; }
.vault-hero-link {
  display: inline-flex; align-items: center; gap: 8px;
  margin-top: 18px;
  font-family: var(--font-display); font-weight: 600; font-size: var(--text-sm);
  color: #fff; text-decoration: none;
  padding: 9px 16px; border-radius: var(--radius-pill);
  background: rgba(255,255,255,.14);
  border: 1px solid rgba(255,255,255,.28);
  transition: background var(--dur-fast), border-color var(--dur-fast);
}
.vault-hero-link .ic { width: 16px; height: 16px; }
.vault-hero-link:hover { background: rgba(255,255,255,.24); border-color: rgba(255,255,255,.5); }
.vault-hero-link:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

/* stat strip */
.stat-strip { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; margin-bottom: 40px; }
.stat {
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xs); padding: 24px 26px;
}
.stat .stat-ic { width: 42px; height: 42px; border-radius: var(--radius-md); background: var(--wash-blue); color: var(--echo-blue); display: flex; align-items: center; justify-content: center; margin-bottom: 16px; }
.stat .stat-ic .ic { width: 21px; height: 21px; }
.stat .stat-value { font-family: var(--font-display); font-weight: 700; font-size: var(--text-2xl); color: var(--fg1); line-height: 1; }
.stat .stat-label { font-family: var(--font-body); font-size: var(--text-sm); color: var(--fg2); margin-top: 6px; }

/* section subhead within app */
.app-subhead { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin: 0 0 20px; flex-wrap: wrap; }
.app-subhead h2 { font-family: var(--font-display); font-weight: 700; font-size: var(--text-xl); color: var(--fg1); margin: 0; }

/* Right-hand side of the subhead: quota badge, plus the phone-only create
   button (see .subhead-add near the phone breakpoint). */
.subhead-actions { display: flex; align-items: center; gap: 10px; }
/* Hidden on desktop, where the dashed tile at the end of the grid is already in
   view without scrolling. It takes over from that tile at phone widths. */
.subhead-add { display: none; white-space: nowrap; }

/* "X / Y vaults" quota badge — how many vaults this account may create. */
.vault-quota { display: inline-flex; align-items: center; gap: 6px; white-space: nowrap; font-family: var(--font-body); font-weight: 700; font-size: var(--text-xs); letter-spacing: var(--tracking-caps); text-transform: uppercase; padding: 5px 11px; border-radius: var(--radius-pill); color: var(--gold-700); background: var(--wash-gold); }
.vault-quota .ic { width: 12px; height: 12px; }
.vault-quota.is-full { color: #fff; background: var(--gold-600); }
.vault-search { position: relative; display: flex; align-items: center; }
.vault-search .ic { position: absolute; left: 12px; width: 16px; height: 16px; color: var(--fg3); pointer-events: none; }
.vault-search input {
  width: 200px; max-width: 46vw; font-family: var(--font-body); font-size: var(--text-sm);
  color: var(--fg1); background: var(--surface); border: 1.5px solid var(--border-strong);
  border-radius: var(--radius-pill); padding: 9px 14px 9px 34px;
  transition: border-color var(--dur-fast), box-shadow var(--dur-fast);
}
.vault-search input::placeholder { color: var(--fg3); }
.vault-search input:focus { outline: none; border-color: var(--echo-blue); box-shadow: 0 0 0 4px rgba(21,138,255,.14); }
.vault-search input::-webkit-search-cancel-button { -webkit-appearance: none; }

.view-toggle { display: inline-flex; background: var(--bg-sunk); border: 1px solid var(--border); border-radius: var(--radius-pill); padding: 3px; gap: 2px; }
.view-btn {
  width: 34px; height: 32px; border: none; background: none; cursor: pointer;
  border-radius: var(--radius-pill); color: var(--fg3);
  display: flex; align-items: center; justify-content: center;
  transition: background var(--dur-fast), color var(--dur-fast);
}
.view-btn .ic { width: 17px; height: 17px; }
.view-btn:hover { color: var(--ink-700); }
.view-btn.is-active { background: var(--surface); color: var(--echo-blue); box-shadow: var(--shadow-xs); }

/* locked-memory modal */
.modal-overlay {
  position: fixed; inset: 0; z-index: 80;
  display: flex; align-items: center; justify-content: center; padding: 24px;
  background: rgba(14, 23, 38, .55); -webkit-backdrop-filter: blur(3px); backdrop-filter: blur(3px);
  animation: modal-fade var(--dur-base) var(--ease-out);
}
.modal-overlay.hidden, .modal-overlay[hidden] { display: none; }
@keyframes modal-fade { from { opacity: 0; } to { opacity: 1; } }
.modal-card {
  position: relative; width: 100%; max-width: 420px; text-align: center;
  background: var(--surface); border-radius: var(--radius-xl);
  box-shadow: var(--shadow-lg); padding: clamp(32px, 5vw, 44px) clamp(28px, 4vw, 40px);
  animation: modal-rise var(--dur-base) var(--ease-out);
}
@keyframes modal-rise { from { opacity: 0; transform: translateY(10px) scale(.98); } to { opacity: 1; transform: none; } }
.modal-close {
  position: absolute; top: 14px; right: 14px; width: 34px; height: 34px;
  border: none; background: none; cursor: pointer; border-radius: var(--radius-pill);
  color: var(--fg3); display: flex; align-items: center; justify-content: center;
}
.modal-close:hover { background: var(--bg-sunk); color: var(--ink-700); }
.modal-close .ic { width: 18px; height: 18px; }
.modal-ic {
  width: 64px; height: 64px; border-radius: var(--radius-pill); margin: 0 auto 20px;
  background: var(--wash-gold); color: var(--gold-600);
  display: flex; align-items: center; justify-content: center;
}
.modal-ic .ic { width: 30px; height: 30px; }
/* A lock in a modal is the brand mark, so it wears true brand gold rather than
   the softer amber the generic modal icon uses. */
.modal-ic.is-lock { color: var(--moment-gold); }
.modal-card h2 { font-family: var(--font-display); font-weight: 700; font-size: var(--text-xl); color: var(--fg1); margin: 0 0 12px; }
.modal-sub { font-family: var(--font-body); font-size: var(--text-base); color: var(--fg2); line-height: 1.55; margin: 0 0 28px; }

/* ── Welcome carousel modal ─────────────────────────────────────────── */
.wc-card {
  max-width: 520px; width: 100%;
  padding: clamp(28px, 4vw, 40px) clamp(24px, 4vw, 36px) 28px;
  text-align: center;
  /* no overflow:hidden here — let the viewport div handle clipping */
}

/* Clipping viewport — sits between the card padding and the track.
   Its height is set in px by the modal's script to the active slide's own
   height. A flex track is as tall as its tallest slide, which is the intro,
   so without this every step slide carried ~200px of dead space above the
   dots and the card outgrew a 568px-tall phone. */
.wc-viewport {
  overflow: hidden;
  width: 100%;
}
/* Added by the script once the first height is measured, so the opening
   frame doesn't animate up from zero. */
.wc-viewport--anim { transition: height 380ms cubic-bezier(.4,0,.2,1); }
/* Height and slide move together or not at all: animating one while the other
   snaps reads worse than either on its own. */
@media (prefers-reduced-motion: reduce) {
  .wc-viewport--anim { transition: none; }
  .wc-track { transition: none; }}

/* Slide track — full-width overflow window */
.wc-track {
  display: flex;
  /* flex-start, not the default stretch: each slide keeps its natural height
     so the script can measure it. */
  align-items: flex-start;
  transition: transform 380ms cubic-bezier(.4,0,.2,1);
  will-change: transform;
  /* width is auto; each slide is 100% of the viewport, not the track */
}
.wc-slide {
  flex: 0 0 100%;
  width: 100%;
  min-width: 0;
  box-sizing: border-box;
}

/* Intro slide */
.wc-intro { padding: 8px 0 20px; }
.wc-intro .wt-scene { margin: 0 auto 24px; }
.wc-intro h2 { font-family: var(--font-display); font-weight: 700; font-size: var(--text-xl); color: var(--fg1); margin: 0 0 12px; }
.wc-intro .modal-sub { margin-bottom: 8px; }
.wc-hint { font-size: var(--text-sm); color: var(--fg3); margin: 0; }
.wc-hint-link { color: var(--echo-blue); font-weight: 600; text-decoration: none; }
.wc-hint-link:hover { text-decoration: underline; }

/* Step slides — image frame */
.wc-frame {
  position: relative;
  /* Match the crops' aspect ratio so the whole screenshot shows at every
     width and the percentage-positioned callouts stay accurate on mobile. */
  width: 100%; aspect-ratio: 448 / 220;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--ink-50);
  margin-bottom: 16px;
  display: flex; align-items: center; justify-content: center;
  border: 1px solid var(--border);
}
.wc-frame img {
  width: 100%; height: 100%;
  /* Crops are pre-cut to the frame's aspect ratio, so cover fills edge-to-edge
     with no letterboxing while keeping the framed UI fully visible. */
  object-fit: cover; object-position: center top;
  display: block;
}

/* Callout annotation — pill badge that points at the relevant UI area.
   A small dot anchors the pill to the exact spot it describes. */
.wc-callout {
  position: absolute;
  display: flex; align-items: center; gap: 6px;
  background: var(--echo-blue); color: #fff;
  font-family: var(--font-display); font-size: 11px; font-weight: 600;
  padding: 6px 12px 6px 8px;
  border-radius: var(--radius-pill);
  box-shadow: 0 6px 18px rgba(21,138,255,.40), 0 0 0 3px rgba(255,255,255,.6);
  white-space: nowrap;
  max-width: calc(100% - 24px);
  pointer-events: none;
  z-index: 2;
  animation: wc-callout-in 420ms cubic-bezier(.34,1.56,.64,1) both;
}
/* On narrow frames the pills shrink rather than spill past the screenshot. */
@media (max-width: 460px) {
  .wc-callout { font-size: 10px; padding: 5px 10px 5px 7px; }}
.wc-callout .ic { width: 14px; height: 14px; flex-shrink: 0; }

/* Pulsing anchor dot, centred on the pill's leading edge */
.wc-callout::before {
  content: "";
  position: absolute; left: -5px; top: 50%;
  width: 10px; height: 10px; margin-top: -5px;
  border-radius: 50%;
  background: var(--echo-blue);
  box-shadow: 0 0 0 3px rgba(255,255,255,.85), 0 0 0 6px rgba(21,138,255,.25);
  animation: wc-dot-pulse 2s ease-out infinite;
}

@keyframes wc-callout-in {
  from { opacity: 0; transform: translateX(var(--wc-tx, 0)) scale(.85); }
  to   { opacity: 1; transform: translateX(var(--wc-tx, 0)) scale(1); }
}
@keyframes wc-dot-pulse {
  0%   { box-shadow: 0 0 0 3px rgba(255,255,255,.85), 0 0 0 4px rgba(21,138,255,.45); }
  70%  { box-shadow: 0 0 0 3px rgba(255,255,255,.85), 0 0 0 12px rgba(21,138,255,0); }
  100% { box-shadow: 0 0 0 3px rgba(255,255,255,.85), 0 0 0 12px rgba(21,138,255,0); }
}
@media (prefers-reduced-motion: reduce) {
  .wc-callout { animation: none; }
  .wc-callout::before { animation: none; }}

.wc-text { text-align: left; padding: 0 2px; }
.wc-step-badge {
  display: inline-block; font-size: var(--text-xs); font-weight: 600;
  color: var(--echo-blue); text-transform: uppercase; letter-spacing: .06em;
  margin-bottom: 6px;
}
.wc-text h3 {
  font-family: var(--font-display); font-weight: 700;
  font-size: var(--text-lg); color: var(--fg1); margin: 0 0 8px;
}
.wc-text p { font-size: var(--text-base); color: var(--fg2); line-height: 1.55; margin: 0; }

/* Dot indicators */
.wc-dots {
  display: flex; justify-content: center; gap: 6px;
  margin: 20px 0 16px;
}
.wc-dot {
  width: 8px; height: 8px; border-radius: var(--radius-pill);
  background: var(--ink-300); transition: background var(--dur-fast), width var(--dur-fast);
}
.wc-dot--active { background: var(--echo-blue); width: 22px; }

/* Prev / Next row */
.wc-nav {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
}
/* nowrap because a squeezed pill wraps its label to two lines rather than
   admitting it has run out of room, which reads as a broken button. */
.wc-nav .btn { min-width: 120px; white-space: nowrap; }
.wc-btn-next { margin-left: auto; }

/* Large phones: both labels still fit once the pills give up some side padding,
   so the pair survives down to 381px. The min-height keeps this band out of the
   way of the Mobile S rules below, which own every short viewport. */
@media (min-width: 381px) and (max-width: 460px) and (min-height: 621px) {
  .wc-nav .btn { min-width: 0; padding-left: 20px; padding-right: 20px; }}

/* Mobile S — 320px-wide phones, and any viewport too short for the carousel's
   full rhythm. The intro slide is the tall one: at 320x568 it asked for 640px
   of card inside 536px of usable height, which put the opening call to action
   below the fold on the first screen a new member ever sees. Sizing the
   viewport to the active slide (above) reclaims the dead space on the step
   slides; this block runs the intro one density step down and rebuilds the nav
   row so it cannot wrap or spill. Kept as one media query because the two
   conditions are the same squeeze from different directions. */
@media (max-width: 380px), (max-height: 620px) {
  .wc-card { padding: 20px 18px; }

  .wc-intro { padding: 0 0 10px; }
  /* The gradient tile is the decorative element here, so it gives up the most
     room: the screenshot and its callout are what actually teach the product. */
  .wc-intro .wt-scene { width: 68px; height: 68px; margin: 0 auto 14px; border-radius: var(--radius-lg); }
  .wc-intro .wt-scene .wt-scene-main { width: 32px; height: 32px; }
  .wc-intro .wt-scene .wt-scene-accent { width: 16px; height: 16px; bottom: 7px; right: 7px; }
  .wc-intro h2 { font-size: var(--text-lg); margin-bottom: 8px; }
  .wc-intro .modal-sub { margin-bottom: 6px; }

  .wc-frame { margin-bottom: 12px; }
  .wc-dots { margin: 12px 0 10px; }

  /* Two 120px pills need 252px inside a 240px card, so they overflowed the card
     edge and wrapped "Get started" onto two lines. One square icon button plus
     one flexible action fits any width, and 46px keeps the tap target honest. */
  .wc-nav { gap: 10px; }
  .wc-nav .btn { min-width: 0; font-size: var(--text-sm); }
  .wc-nav .btn .ic { width: 16px; height: 16px; }
  .wc-nav .wc-btn-prev {
    flex: 0 0 46px; width: 46px; height: 46px; padding: 0; gap: 0;
  }
  /* The label is carried by aria-label at this width. */
  .wc-nav .wc-btn-prev .wc-btn-label { display: none; }
  .wc-nav .wc-btn-next {
    flex: 1 1 auto; min-height: 46px; padding: 12px 18px; white-space: nowrap;
  }}

/* =====================================================================
   MEMORY CARDS — each reflection type carries its own hue, so a vault of
   moments reads as a warm, varied collection rather than a wall of blue.
   The gradient band is short (a signal, not a hero image); title + meta
   lead. Grid and list share one card; list reflows it into a row.
   ===================================================================== */

/* per reflection-type identity (icon hue, deep ink, soft wash) — blue default */
.memory-card { --rt: var(--echo-blue); --rt-ink: var(--blue-700); --rt-wash: var(--wash-blue); }
.memory-card[data-rtype="child"]       { --rt:#e8588f; --rt-ink:#a5285c; --rt-wash:#fdeef4; }
.memory-card[data-rtype="future_self"] { --rt:#7a5af0; --rt-ink:#4a32a8; --rt-wash:#f0ecfd; }
.memory-card[data-rtype="loved_one"]   { --rt:#e2503f; --rt-ink:#a8331f; --rt-wash:#fdecea; }
.memory-card[data-rtype="personal"]    { --rt:#0e9c8c; --rt-ink:#0a6b60; --rt-wash:#e6f7f4; }
.memory-card[data-rtype="advice"]      { --rt:#e0a800; --rt-ink:#8f6800; --rt-wash:#fff8e6; }
.memory-card[data-rtype="other"]       { --rt:#158aff; --rt-ink:#0a59b4; --rt-wash:#eef6ff; }

.memory-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 20px; }

/* full-bleed hero card: gradient "image" + bottom scrim + overlaid text */
.memory-card {
  position: relative; display: block; overflow: hidden;
  /* width:100% is load-bearing. Without it the 248px min-height transfers back
     through the aspect ratio into a 310px minimum WIDTH, which is wider than the
     grid track on a 320px phone and pushes the card off the side of the page.
     Pinning the width to the track lets min-height win on the vertical axis
     instead, so narrow cards simply come out a little taller than 5:4. */
  width: 100%;
  aspect-ratio: 5 / 4; min-height: 248px;
  border-radius: var(--radius-lg); border: 1px solid var(--border);
  box-shadow: var(--shadow-sm); text-decoration: none; color: #fff;
  transition: transform var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out);
}
.memory-card:hover { transform: translateY(-4px); box-shadow: var(--shadow-lg); }
.memory-card:focus-visible { outline: none; box-shadow: 0 0 0 3px color-mix(in srgb, var(--rt) 45%, transparent), var(--shadow-lg); }
/* large faint type glyph, set into the upper area like a watermark */
.memory-glyph { position: absolute; right: 14px; top: 12px; color: rgba(255,255,255,.18); display: flex; }
.memory-glyph .ic { width: 104px; height: 104px; }
/* bottom scrim so overlaid text always reads, whatever the hue */
.memory-card::after {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(180deg, transparent 30%, rgba(8,12,20,.18) 52%, rgba(8,12,20,.74) 100%);
}
/* over a real photo, deepen the scrim a touch so any image keeps text legible */
.memory-card.has-cover::after {
  background: linear-gradient(180deg, rgba(8,12,20,.12) 0%, transparent 34%, rgba(8,12,20,.32) 60%, rgba(8,12,20,.82) 100%);
}

/* top-right corner status badge (lock / open / draft) */
.memory-corner {
  position: absolute; z-index: 3; right: 14px; top: 14px;
  width: 34px; height: 34px; border-radius: var(--radius-md);
  display: flex; align-items: center; justify-content: center;
  background: rgba(255,255,255,.22); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  color: #fff; border: 1px solid rgba(255,255,255,.32);
}
.memory-corner .ic { width: 17px; height: 17px; }
.memory-corner.is-open { background: color-mix(in srgb, var(--success) 88%, transparent); border-color: transparent; }

/* overlaid content block at the bottom */
.memory-overlay { position: absolute; z-index: 2; inset: auto 0 0 0; padding: 18px 18px 18px; display: flex; flex-direction: column; gap: 4px; }
.memory-overlay h3 { font-family: var(--font-display); font-weight: 700; font-size: var(--text-lg); color: #fff; margin: 0; line-height: 1.2; text-shadow: 0 1px 10px rgba(0,0,0,.3); }
.memory-overlay p { font-family: var(--font-body); font-size: var(--text-sm); color: rgba(255,255,255,.86); margin: 0; line-height: 1.4; }
.memory-unlock { display: inline-flex; align-items: center; gap: 7px; margin-top: 8px; font-family: var(--font-body); font-weight: 700; font-size: var(--text-sm); color: #fff; }
.memory-unlock .ic { width: 15px; height: 15px; color: rgba(255,255,255,.92); }

/* ---- LIST (feed) view: shorter hero rows ----
   The card flows top→bottom: media pill (+ optional "From" badge) on the first
   row, then the title / type / status stacked just under it. The overlay is NOT
   bottom-anchored here (a short row would push the title up behind the pill). */
.memory-grid.is-list { display: flex; flex-direction: column; gap: 14px; }
.memory-grid.is-list .memory-card {
  aspect-ratio: auto; min-height: 0;
  padding: 14px 16px 16px; display: flex; flex-direction: column;
}
.memory-grid.is-list .memory-card:hover { transform: translateY(-2px); }
.memory-grid.is-list .memory-glyph { top: 50%; transform: translateY(-50%); }
/* scrim spans the whole row (no longer a bottom-only fade) so text stays legible */
.memory-grid.is-list .memory-card::after { background: linear-gradient(180deg, rgba(8,12,20,.16), rgba(8,12,20,.52)); }
.memory-grid.is-list .memory-corner { top: 12px; right: 14px; }
/* title block sits below the pills, in normal flow */
.memory-grid.is-list .memory-overlay { position: static; inset: auto; padding: 12px 0 0; padding-right: 44px; }
.memory-grid.is-list .memory-overlay h3 { font-size: var(--text-md); }
.memory-grid.is-list .memory-unlock { margin-top: 6px; }
@media (max-width: 560px) {
  .memory-grid.is-list .memory-glyph .ic { width: 84px; height: 84px; }}

.status-pill { display: inline-flex; align-items: center; gap: 6px; font-family: var(--font-body); font-weight: 700; font-size: var(--text-xs); letter-spacing: var(--tracking-caps); text-transform: uppercase; padding: 5px 11px; border-radius: var(--radius-pill); }
.status-pill .ic { width: 12px; height: 12px; }
.status-sealed { color: var(--gold-700); background: var(--wash-gold); }
/* Actionable status pill (rendered as a <button>): opens the set-date modal. */
.status-pill-action { border: none; cursor: pointer; transition: background 0.15s ease, color 0.15s ease; }
.status-pill-action:hover,
.status-pill-action:focus-visible { color: #fff; background: var(--gold-600); }
.status-open { color: var(--success); background: var(--success-bg); }
/* Semantic status pills so badges map level -> the correct colour family
   (a danger badge must read red, an info badge blue), not reuse the gold
   "sealed" style. */
.status-danger { color: var(--danger); background: var(--danger-bg); }
.status-info { color: var(--blue-700); background: var(--wash-blue); }

/* empty state */
.empty-state { text-align: center; padding: clamp(48px, 7vw, 88px) 32px; }
.empty-state .empty-ic { width: 72px; height: 72px; border-radius: var(--radius-pill); background: var(--wash-blue); color: var(--echo-blue); display: inline-flex; align-items: center; justify-content: center; margin-bottom: 22px; }
.empty-state .empty-ic .ic { width: 34px; height: 34px; }
/* The lock is the brand mark (gold), so a lock badge wears gold rather than the
   default blue used by mail/check empty states. See the .spark-lock signature.
   Defined unscoped as well so a lock badge works outside an .empty-state parent
   (e.g. the seal screen's centred badge inside a plain .card). */
.empty-ic.is-lock,
.empty-state .empty-ic.is-lock { background: var(--wash-gold); color: var(--moment-gold); }
.empty-ic.is-lock {
  width: 72px; height: 72px; border-radius: var(--radius-pill);
  display: inline-flex; align-items: center; justify-content: center;
}
.empty-ic.is-lock .ic { width: 34px; height: 34px; }
.empty-state h2 { font-family: var(--font-display); font-weight: 700; font-size: var(--text-xl); margin: 0 0 10px; }
.empty-state p { font-family: var(--font-body); color: var(--fg2); max-width: 42ch; margin: 0 auto 26px; }

/* =====================================================================
   RECORDING WIZARD
   ===================================================================== */
.wizard { max-width: 820px; margin: 0 auto; padding: 0 32px; }
.stepper { display: flex; align-items: center; gap: 0; margin-bottom: 40px; }

.wizard-head { text-align: center; margin-bottom: 36px; }
.wizard-head .eyebrow { margin-bottom: 12px; }
.wizard-head h1 { font-family: var(--font-display); font-weight: 700; font-size: var(--text-2xl); letter-spacing: -0.02em; margin: 0 0 10px; }
.wizard-head p { font-family: var(--font-body); color: var(--fg2); max-width: 50ch; margin: 0 auto; }

/* type choice cards */
.choice-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
@media (max-width: 860px) { .choice-grid { grid-template-columns: repeat(2, 1fr); }}
/* small screens: a swipeable slider (cards peek to signal there's more) */
@media (max-width: 640px) {
  .choice-grid {
    display: flex; grid-template-columns: none; gap: 14px;
    overflow-x: auto; scroll-snap-type: x mandatory; scroll-behavior: smooth;
    margin: 0 -20px; padding: 4px 20px 16px;          /* full-bleed scroll within the wrap */
    scrollbar-width: none; -ms-overflow-style: none;
  }
  .choice-grid::-webkit-scrollbar { display: none; }
  .choice-grid .choice { flex: 0 0 78%; max-width: 320px; scroll-snap-align: center; }}

/* Per reflection-type bottom wash for the picker cards (empty-vault starter
   slider + new-memory type chooser). Mirrors the .memory-card --rt-wash map,
   each deepened with a touch of the type's main hue so the bottom blend reads
   a little stronger while staying subtle. Cards without a data-rtype fall back
   to the neutral blue wash. */
.choice{ --rt: var(--echo-blue); --rt-ink: var(--blue-700); --rt-wash: var(--wash-blue); }
.choice[data-rtype="child"]{ --rt:#e8588f; --rt-ink:#a5285c; --rt-wash: color-mix(in srgb, #e8588f 22%, #fdeef4); }
.choice[data-rtype="future_self"]{ --rt:#7a5af0; --rt-ink:#4a32a8; --rt-wash: color-mix(in srgb, #7a5af0 22%, #f0ecfd); }
.choice[data-rtype="loved_one"]{ --rt:#e2503f; --rt-ink:#a8331f; --rt-wash: color-mix(in srgb, #e2503f 22%, #fdecea); }
.choice[data-rtype="personal"]{ --rt:#0e9c8c; --rt-ink:#0a6b60; --rt-wash: color-mix(in srgb, #0e9c8c 22%, #e6f7f4); }
.choice[data-rtype="advice"]{ --rt:#e0a800; --rt-ink:#8f6800; --rt-wash: color-mix(in srgb, #e0a800 22%, #fff8e6); }
.choice[data-rtype="other"]{ --rt:#158aff; --rt-ink:#0a59b4; --rt-wash: color-mix(in srgb, #158aff 22%, #eef6ff); }

.choice {
  background: var(--surface); border: 1.5px solid var(--border); border-radius: var(--radius-lg);
  padding: 30px 26px; cursor: pointer; text-align: left; text-decoration: none; color: inherit;
  transition: transform var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out), border-color var(--dur-base) var(--ease-out);
  display: block; position: relative; overflow: hidden;
}
/* slight bottom-up wash of the card's reflection-type hue (see --rt-wash map) */
.choice::after {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: linear-gradient(0deg, var(--rt-wash, transparent) 0%, transparent 38%);
}
.choice > * { position: relative; z-index: 1; }
.choice:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); border-color: var(--blue-200); }
.choice.selected { border-color: var(--echo-blue); box-shadow: 0 0 0 4px rgba(21,138,255,.12); }
.choice .choice-ic { width: 52px; height: 52px; border-radius: var(--radius-md); background: var(--wash-blue); color: var(--echo-blue); display: flex; align-items: center; justify-content: center; margin-bottom: 20px; }
.choice .choice-ic .ic { width: 26px; height: 26px; }
.choice h3 { font-family: var(--font-display); font-weight: 700; font-size: var(--text-md); margin: 0 0 8px; }
.choice p { font-family: var(--font-body); font-size: var(--text-sm); color: var(--fg2); margin: 0; line-height: 1.5; }

/* recorder stage */
.recorder { text-align: center; }
.recorder-stage {
  position: relative; aspect-ratio: 16/10; border-radius: var(--radius-xl); overflow: hidden;
  background: radial-gradient(120% 90% at 50% 0%, rgba(21,138,255,.18), transparent 60%), linear-gradient(180deg, var(--ink-900), var(--ink-800));
  display: flex; align-items: center; justify-content: center; color: rgba(255,255,255,.5);
  border: 1px solid rgba(255,255,255,.08); margin-bottom: 26px;
}
.recorder-stage .placeholder { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 16px; }
.recorder-stage .placeholder .ic { width: 46px; height: 46px; opacity: .8; }
/* one shared label style for BOTH the video + audio placeholders */
.stage-label { font-family: var(--font-body); font-size: var(--text-sm); font-weight: 500; color: rgba(255,255,255,.6); letter-spacing: .03em; }
.rec-controls-hint { font-family: var(--font-body); font-size: var(--text-sm); color: var(--fg3); letter-spacing: .03em; }
.rec-timer { position: absolute; top: 18px; left: 18px; z-index: 3; display: inline-flex; align-items: center; gap: 9px; background: rgba(0,0,0,.5); backdrop-filter: blur(6px); color: #fff; font-family: var(--font-mono); font-size: var(--text-sm); padding: 8px 14px; border-radius: var(--radius-pill); }
.rec-timer .rec-dot { width: 9px; height: 9px; border-radius: 999px; background: var(--danger); animation: pulse-rec 1.4s var(--ease-soft) infinite; }
@keyframes pulse-rec { 0%,100%{opacity:1;} 50%{opacity:.3;} }
.rec-controls { display: flex; align-items: center; justify-content: center; gap: 16px; margin-top: 4px; }

/* record / stop button — a ring around a red shape (dot = idle/record, square = stop).
   Sits on the light card background below the stage. */
.rec-btn {
  width: 70px; height: 70px; border-radius: var(--radius-pill); cursor: pointer; flex: none;
  background: var(--surface); border: 3px solid var(--border-strong);
  display: flex; align-items: center; justify-content: center; padding: 0;
  box-shadow: var(--shadow-sm);
  transition: transform var(--dur-fast) var(--ease-out), border-color var(--dur-fast), box-shadow var(--dur-fast);
}
.rec-btn.start:hover { transform: scale(1.06); border-color: var(--danger); box-shadow: 0 6px 16px rgba(226,80,63,.28); }
.rec-btn:active { transform: scale(.94); }
/* the inner red shape; default a circle (record), square when stopping */
.rec-btn.start::before { content: ""; width: 30px; height: 30px; border-radius: 999px; background: var(--danger); transition: border-radius var(--dur-fast), width var(--dur-fast), height var(--dur-fast); }
.rec-btn.start.is-stop::before { width: 24px; height: 24px; border-radius: 6px; }
.rec-btn.start .ic { display: none; }  /* shape is drawn via ::before, not an icon */
/* secondary round control (restart) — light surface with an icon */
.rec-btn.secondary { width: 52px; height: 52px; background: var(--surface); color: var(--ink-700); border: 1px solid var(--border-strong); box-shadow: var(--shadow-sm); }
.rec-btn.secondary::before { content: none; }
.rec-btn.secondary .ic { display: block; width: 22px; height: 22px; }

/* recorder tabs (Video / Audio / Upload) */
.rec-tabs { display: flex; justify-content: center; gap: 4px; border-bottom: 1px solid var(--border); margin-bottom: 24px; }
.rec-tab {
  display: inline-flex; align-items: center; gap: 9px; cursor: pointer;
  font-family: var(--font-display); font-weight: 600; font-size: var(--text-base);
  color: var(--fg2); background: none; border: none;
  padding: 12px 18px; position: relative; transition: color var(--dur-fast);
}
.rec-tab .ic { width: 18px; height: 18px; }
.rec-tab:hover { color: var(--ink-700); }
.rec-tab.active { color: var(--echo-blue); }
.rec-tab.active::after { content: ""; position: absolute; left: 12px; right: 12px; bottom: -1px; height: 2px; background: var(--echo-blue); border-radius: 2px; }

/* upload dropzone (inside recorder stage) */
.rec-dropzone {
  position: absolute; inset: 22px; border-radius: var(--radius-lg);
  border: 2px dashed rgba(255,255,255,.24);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px;
  color: rgba(255,255,255,.6); font-family: var(--font-body); text-align: center;
}
.rec-dropzone .ic { width: 40px; height: 40px; color: rgba(255,255,255,.4); }
.rec-dropzone .formats { font-size: var(--text-xs); color: rgba(255,255,255,.35); margin-top: 4px; }
.rec-dropzone .uploaded-name { color: var(--gold-300); font-weight: 700; }

/* audio stage centerpiece */
.rec-audio { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 16px; font-family: var(--font-body); }

/* consistent icon-in-orb used by BOTH the video and audio placeholders */
.stage-orb {
  width: 88px; height: 88px; border-radius: var(--radius-pill); flex: none;
  background: rgba(21,138,255,.16); border: 1px solid rgba(255,255,255,.14);
  display: flex; align-items: center; justify-content: center;
}
.stage-orb img { width: 42px; height: 42px; filter: brightness(0) invert(1); opacity: .92; }

/* optional image attach panel */
.attach-panel {
  margin-top: 24px; padding: 20px 22px; border: 1px solid var(--border);
  border-radius: var(--radius-md); background: var(--bg-sunk);
}
.attach-panel label.title { display: block; font-family: var(--font-body); font-weight: 700; font-size: var(--text-sm); color: var(--ink-700); }
.attach-panel .hint { font-family: var(--font-body); font-size: var(--text-xs); color: var(--fg3); margin: 2px 0 12px; }

/* multi-image attach: thumbnail grid + cover selection (new_record) */
.attach-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(88px, 1fr)); gap: 10px; margin-top: 4px; }
.attach-grid:empty { display: none; }
.attach-thumb {
  position: relative; aspect-ratio: 1; border-radius: var(--radius-sm); overflow: hidden;
  cursor: pointer; border: 2px solid transparent; background: var(--surface);
  transition: border-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
}
.attach-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.attach-thumb:hover { box-shadow: var(--shadow-sm); }
.attach-thumb.is-cover { border-color: var(--echo-blue); box-shadow: 0 0 0 3px rgba(21,138,255,.16); }
.attach-thumb-x {
  position: absolute; top: 5px; right: 5px; width: 24px; height: 24px; border-radius: var(--radius-pill);
  border: none; cursor: pointer; background: rgba(14,23,38,.62); color: #fff;
  display: flex; align-items: center; justify-content: center; -webkit-backdrop-filter: blur(4px); backdrop-filter: blur(4px);
}
.attach-thumb-x:hover { background: var(--danger); }
.attach-thumb-x .ic { width: 14px; height: 14px; }
.attach-cover-badge {
  position: absolute; left: 0; right: 0; bottom: 0; display: none;
  align-items: center; justify-content: center; gap: 5px;
  background: linear-gradient(180deg, transparent, rgba(21,138,255,.92)); color: #fff;
  font-family: var(--font-body); font-weight: 700; font-size: 10px; letter-spacing: var(--tracking-caps);
  text-transform: uppercase; padding: 12px 4px 5px;
}
.attach-cover-badge .ic { width: 11px; height: 11px; }
.attach-thumb.is-cover .attach-cover-badge { display: flex; }
.attach-add {
  display: inline-flex; align-items: center; gap: 9px; margin-top: 12px; cursor: pointer;
  font-family: var(--font-display); font-weight: 600; font-size: var(--text-sm); color: var(--blue-600);
  background: var(--wash-blue); border: 1px solid var(--blue-100); border-radius: var(--radius-sm);
  padding: 10px 16px; transition: background var(--dur-fast), border-color var(--dur-fast);
}
.attach-add:hover { background: #e3f0ff; border-color: var(--blue-200); }
.attach-add .ic { width: 17px; height: 17px; }
.attach-cover-hint { display: inline-flex; align-items: center; gap: 7px; margin: 12px 0 0; font-family: var(--font-body); font-size: var(--text-xs); color: var(--fg3); }
.attach-cover-hint .ic { width: 14px; height: 14px; color: var(--gold-500); }

.hidden { display: none !important; }

/* preview / playback */
.player {
  position: relative; aspect-ratio: 16/9; border-radius: var(--radius-xl); overflow: hidden;
  background-color: var(--ink-900); background-size: cover; background-position: center;
  display: flex; align-items: center; justify-content: center; box-shadow: var(--shadow-lg);
}
.player::after { content: ""; position: absolute; inset: 0; background: linear-gradient(180deg, rgba(10,15,24,.1), rgba(10,15,24,.5)); }

/* video playback — the element hugs the recording's own shape.
   Recordings come from phone cameras, so most are portrait. A <video> stretched
   to the card's full width letterboxes those in black down both sides, which
   reads as unfinished. Letting the element size to its intrinsic dimensions
   removes the bars entirely (there is no box left over to fill), and the warm
   well behind it gives a tall video something to sit on instead of floating. */
.playback-media {
  display: flex; align-items: center; justify-content: center;
  background: var(--bg-sunk); border-radius: var(--radius-md);
  padding: clamp(10px, 2.5vw, 20px);
}
.playback-video {
  display: block; width: auto; height: auto;
  max-width: 100%; max-height: min(70vh, 34rem);
  border-radius: var(--radius-sm); box-shadow: var(--shadow-md);
  /* Deliberately not a dark fill. Until the first frame decodes the element has
     no intrinsic size and falls back to the UA's 300x150, so a dark background
     here would be a grey slab sitting on the cream. Transparent lets the well
     show through, and preload="metadata" on the tag keeps that moment short by
     fetching the header (and therefore the real dimensions) up front. */
  background: transparent;
}

/* playback image gallery (cover-first, with thumbnail strip) */
.playback-gallery-main { width: 100%; max-height: 28rem; object-fit: contain; border-radius: var(--radius-md); background: var(--bg-sunk); }
.playback-thumbs { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 12px; }
.playback-thumb {
  width: 64px; height: 64px; padding: 0; border-radius: var(--radius-xs); overflow: hidden; cursor: pointer;
  border: 2px solid transparent; background: none; transition: border-color var(--dur-fast) var(--ease-out);
}
.playback-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.playback-thumb:hover { border-color: var(--border-strong); }
.playback-thumb.is-active { border-color: var(--echo-blue); }

.wizard-foot { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-top: 36px; }
.wizard-foot .spacer { flex: 1; }

/* summary list (details review) */
.summary { display: flex; flex-direction: column; gap: 0; }

/* =====================================================================
   FLOATING ACTION BUTTON — single "new memory" entry point
   ===================================================================== */
.fab {
  position: fixed; right: clamp(20px, 4vw, 40px); bottom: clamp(20px, 4vw, 40px);
  z-index: 60; width: 60px; height: 60px; border-radius: var(--radius-pill);
  background: var(--echo-blue); color: var(--fg-on-blue); border: none; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 10px 28px rgba(21,138,255,.42); text-decoration: none;
  transition: transform var(--dur-fast) var(--ease-out), box-shadow var(--dur-base) var(--ease-out), background var(--dur-base) var(--ease-out);
}
.fab .ic { width: 26px; height: 26px; }
.fab::after {
  content: ""; position: absolute; inset: -6px; border-radius: var(--radius-pill);
  border: 2px solid var(--spark-soft); pointer-events: none;
}
.fab:hover { background: var(--blue-600); transform: translateY(-3px) scale(1.04); box-shadow: 0 16px 36px rgba(21,138,255,.5); }
.fab:active { transform: scale(.95); }
@media (prefers-reduced-motion: reduce) { .fab, .fab:hover { transition: none; transform: none; }}

/* =====================================================================
   TOASTS  (parity with existing window.showToast)
   ===================================================================== */
#toast-container { position: fixed; bottom: 20px; right: 20px; z-index: 1000; display: flex; flex-direction: column; gap: 10px; align-items: flex-end; }
.toast {
  display: flex; align-items: center; gap: 12px; min-width: 280px; max-width: 400px;
  background: var(--surface); border: 1px solid var(--border); border-left-width: 4px;
  box-shadow: var(--shadow-lg); border-radius: var(--radius-sm); padding: 14px 16px;
  font-family: var(--font-body); font-size: var(--text-sm); color: var(--fg1);
  transition: opacity .3s; animation: toast-in .3s var(--ease-out);
}
@keyframes toast-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
.toast .ic { width: 18px; height: 18px; flex: none; }
.toast .toast-msg { flex: 1; }
.toast .toast-x { border: none; background: none; cursor: pointer; color: var(--fg3); font-size: 18px; line-height: 1; }
.toast.success { border-left-color: var(--success); } .toast.success .ic { color: var(--success); }
.toast.error { border-left-color: var(--danger); } .toast.error .ic { color: var(--danger); }
.toast.warning { border-left-color: var(--warning); } .toast.warning .ic { color: var(--gold-600); }
.toast.info { border-left-color: var(--echo-blue); } .toast.info .ic { color: var(--echo-blue); }

/* =====================================================================
   RESPONSIVE
   ===================================================================== */
/* ── Tablet & smart-display (Nest Hub Max 1280, iPad 1024/768) ─────────── */
@media (max-width: 1024px) {
  .app-wrap { padding: 0 28px; }
  .stat-strip { gap: 14px; }}

@media (max-width: 860px) {
  .auth { grid-template-columns: 1fr; }
  .auth-aside { display: none; }
  .auth-mobile-top { display: flex; align-items: center; justify-content: center; padding: 22px; border-bottom: 1px solid var(--border); }
  .auth-mobile-top .logo { height: 26px; }}

/* ── Small tablets / large phones ──────────────────────────────────────── */
@media (max-width: 720px) {
  .app-main { padding: clamp(24px, 5vw, 40px) 0 88px; }
  .app-wrap { padding: 0 20px; }
  .app-header-inner { padding: 12px 20px; }
  .vault-hero { min-height: 0; padding: clamp(26px, 5vw, 36px); margin-bottom: 28px; }
  .vault-hero h1 { font-size: var(--text-xl); }
  /* stats sit in one compact row of three on phones, not a tall stack */
  .stat-strip { grid-template-columns: repeat(3, 1fr); gap: 10px; margin-bottom: 30px; }
  .stat { padding: 16px 14px; }
  .stat .stat-ic { width: 34px; height: 34px; margin-bottom: 10px; }
  .stat .stat-ic .ic { width: 17px; height: 17px; }
  .stat .stat-value { font-size: var(--text-lg); }
  .stat .stat-label { font-size: var(--text-xs); }
  /* controls stack under the heading and go full width */
  .app-subhead { flex-direction: column; align-items: stretch; gap: 14px; }
  /* One column of tall cards puts the dashed add tile a long scroll below the
     fold (about 2,600px at the ten-vault cap), so on phones the create button
     moves up beside the heading and the tile stands down. */
  .subhead-actions { width: 100%; justify-content: space-between; }
  .subhead-add { display: inline-flex; flex: 1; justify-content: center; }
  /* Modals: a phone runs out of height long before the create flow runs out of
     fields, and .modal-card-wide caps itself at 92vh without clipping (so the
     date popup can escape), which left the Continue/Back buttons hanging out of
     the card. Scroll the overlay instead and let the card be its natural height:
     the popup still escapes the card, and every control stays reachable.
     overflow-x is pinned because setting only overflow-y to auto computes the
     other axis to auto too, and the open date popup would then raise a
     horizontal scrollbar across the overlay. */
  .modal-overlay { align-items: flex-start; overflow-y: auto; overflow-x: hidden; padding: 16px; }
  /* Two classes on purpose: .modal-card-wide sets its 92vh cap further down the
     file, so an equally specific selector here would lose on source order. */
  .modal-overlay .modal-card-wide { max-height: none; }
  /* Two classes on purpose: .memory-card-add sets display:flex further down the
     file, so an equally specific selector here would lose on source order. */
  .memory-grid .memory-card-add { display: none; }
  .vault-search { flex: 1; }
  .vault-search input { width: 100%; max-width: none; }}

/* ── Recording wizard (type / details / record) on small screens ───────── */
@media (max-width: 640px) {
  /* footer buttons must wrap, never overflow the card edge */
  .wizard-foot { flex-wrap: wrap; gap: 12px; margin-top: 28px; }
  .wizard-foot .spacer { display: none; }            /* no rigid push that forces overflow */
  .wizard-foot .btn { flex: 1 1 auto; justify-content: center; }
  .wizard-foot .btn-ghost { order: 2; }              /* Back below the primary action */
  .wizard-foot .btn-primary, .wizard-foot .btn-lg { order: 1; flex-basis: 100%; }
  .wizard-head h1 { font-size: var(--text-xl); }
  .card.pad-lg { padding: clamp(20px, 5vw, 28px); }
  /* unlock-mode pills wrap and fill the row evenly */
  [data-mode-btn] { flex: 1 1 calc(50% - 10px); }
  /* the recorder controls' preview actions (Re-record / Save) also wrap cleanly */
  .rec-controls { flex-wrap: wrap; }
  /* recorder tabs fit three across without overflow */
  .rec-tabs { gap: 0; }
  .rec-tab { padding: 12px 10px; font-size: var(--text-sm); flex: 1 1 0; justify-content: center; }
  .rec-tab .ic { width: 16px; height: 16px; }
  .rec-btn { width: 62px; height: 62px; }
  .rec-btn.secondary { width: 48px; height: 48px; }
  /* date-picker popup must stay within the viewport */
  .emw-pop { left: 0; right: 0; }
  /* Compound, not descendant: the popup carries both classes on one element.
     Two classes are needed because the base .emw-cal width sits further down the
     file, so a single-class selector here lost on source order and this cap
     never applied, leaving the calendar off the right edge of a 320px phone. */
  .emw-pop.emw-cal { width: min(286px, calc(100vw - 56px)); }}

/* ── Phones (iPhone 14/Pixel 7 ≈390–412, down toward SE) ───────────────── */
@media (max-width: 480px) {
  .memory-grid { grid-template-columns: 1fr; gap: 14px; }
  .vault-hero p { font-size: var(--text-sm); }
  .recorder-stage { aspect-ratio: 4 / 3; }           /* a little taller/narrower so the preview + label fit */
  /* The recorder gained a fourth tab (Write), and four icon+label tabs can't
     shrink below about 350px of min-content, so the last one hung off the card.
     Drop to labels only here; they name the action on their own. Scoped by
     [data-tab-btn] so the install page's platform tabs keep their icons. */
  .rec-tab[data-tab-btn] { padding: 12px 6px; gap: 0; }
  .rec-tab[data-tab-btn] .ic { display: none; }}

/* ── iPhone SE and the narrowest viewports (375 and below) ─────────────── */
@media (max-width: 380px) {
  .app-wrap { padding: 0 14px; }
  /* The narrow wrap was left on the wide 32px gutter here, which cost the
     recorder card 36px it needs to fit its four tabs. */
  .app-wrap-narrow { padding: 0 14px; }
  .app-header-inner { padding: 11px 14px; }
  .vault-hero { padding: 22px; }
  .vault-hero h1 { font-size: var(--text-lg); }
  /* three tiny stats still fit; tighten further */
  .stat-strip { gap: 8px; }
  .stat { padding: 13px 10px; }
  .stat .stat-value { font-size: var(--text-md); }
  .fab { width: 54px; height: 54px; right: 18px; bottom: 18px; }
  .fab .ic { width: 23px; height: 23px; }}

/* =====================================================================
   CUSTOM WIDGETS — branded date picker + select (em-widgets.js)
   The native field stays in the DOM as the value source but is hidden.
   ===================================================================== */
.emw { position: relative; }
.emw .emw-native {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); border: 0;
}
/* trigger looks exactly like an .input field */
.emw-trigger {
  width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 10px;
  font-family: var(--font-body); font-size: var(--text-base); color: var(--fg1); text-align: left;
  background: var(--surface); border: 1.5px solid var(--border-strong); border-radius: var(--radius-sm);
  padding: 13px 16px; cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease-out), box-shadow var(--dur-fast) var(--ease-out);
}
.emw-trigger:hover { border-color: var(--ink-300); }
.emw-trigger:focus-visible { outline: none; border-color: var(--echo-blue); box-shadow: 0 0 0 4px rgba(21,138,255,.14); }
.emw .emw-trigger > .ic { width: 18px; height: 18px; color: var(--fg3); flex: none; }
.emw-trigger .emw-val.is-placeholder { color: var(--fg3); }
.emw .emw-val { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* shared popup */
.emw-pop {
  position: absolute; top: calc(100% + 6px); left: 0; z-index: 70;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-md); box-shadow: var(--shadow-lg);
  display: none;
}
.emw-pop.is-open { display: block; animation: emw-pop-in var(--dur-fast) var(--ease-out); }
/* flip above the field when there's no room below (e.g. low inside a modal) */
.emw-pop.is-up { top: auto; bottom: calc(100% + 6px); }
@keyframes emw-pop-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }

/* ---- calendar ---- */
.emw-cal { width: 286px; padding: 14px; }
.emw-cal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.emw-cal-titlewrap { display: inline-flex; align-items: baseline; gap: 6px; }
.emw-cal-title { font-family: var(--font-display); font-weight: 700; font-size: var(--text-base); color: var(--fg1); }
/* month-name / year in the header are clickable to open the month / year grids */
.emw-cal-title-btn { border: none; background: none; cursor: pointer; padding: 2px 5px; border-radius: var(--radius-xs); }
.emw-cal-title-btn:hover { background: var(--wash-blue); color: var(--blue-700); }
.emw-cal-nav { display: flex; gap: 4px; }
.emw-nav { width: 30px; height: 30px; border: none; background: none; border-radius: var(--radius-xs); cursor: pointer; color: var(--fg2); display: flex; align-items: center; justify-content: center; }
.emw-nav:hover:not(:disabled) { background: var(--bg-sunk); color: var(--ink-800); }
.emw-nav:disabled { color: var(--ink-200); cursor: not-allowed; }
.emw-nav .ic { width: 17px; height: 17px; }
.emw-cal-dow { display: grid; grid-template-columns: repeat(7, 1fr); margin-bottom: 4px; }
.emw-cal-dow span { text-align: center; font-family: var(--font-body); font-weight: 700; font-size: var(--text-xs); color: var(--fg3); padding: 4px 0; }
.emw-cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.emw-day {
  aspect-ratio: 1; border: none; background: none; cursor: pointer; border-radius: var(--radius-xs);
  font-family: var(--font-body); font-size: var(--text-sm); color: var(--ink-700);
  display: flex; align-items: center; justify-content: center;
}
.emw-day:hover:not(:disabled):not(.is-empty) { background: var(--wash-blue); color: var(--blue-700); }
.emw-day.is-empty { cursor: default; }
.emw-day.is-today { font-weight: 700; color: var(--echo-blue); }
.emw-day.is-selected { background: var(--echo-blue); color: #fff; font-weight: 700; }
.emw-day.is-selected:hover { background: var(--blue-600); color: #fff; }
.emw-day:disabled { color: var(--ink-200); cursor: not-allowed; }

/* month + year pickers: 3-column grids reusing the day-cell look */
.emw-cal-months, .emw-cal-years { grid-template-columns: repeat(3, 1fr); gap: 6px; }
.emw-mo, .emw-yr {
  border: none; background: none; cursor: pointer; border-radius: var(--radius-xs);
  font-family: var(--font-body); font-size: var(--text-sm); color: var(--ink-700);
  padding: 12px 0; display: flex; align-items: center; justify-content: center;
}
.emw-mo:hover:not(:disabled), .emw-yr:hover:not(:disabled) { background: var(--wash-blue); color: var(--blue-700); }
.emw-mo.is-current, .emw-yr.is-current { font-weight: 700; color: var(--echo-blue); }
.emw-mo.is-selected, .emw-yr.is-selected { background: var(--echo-blue); color: #fff; font-weight: 700; }
.emw-mo.is-selected:hover, .emw-yr.is-selected:hover { background: var(--blue-600); color: #fff; }
.emw-mo:disabled, .emw-yr:disabled { color: var(--ink-200); cursor: not-allowed; }

.emw-cal-foot { display: flex; justify-content: space-between; margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--border); }
.emw-link { border: none; background: none; cursor: pointer; font-family: var(--font-body); font-weight: 700; font-size: var(--text-sm); color: var(--blue-600); padding: 4px 6px; border-radius: var(--radius-xs); }
.emw-link:hover { background: var(--wash-blue); }

/* ---- select menu ---- */
.emw-menu { min-width: 100%; max-height: 280px; overflow-y: auto; padding: 6px; }
.emw-opt {
  display: block; width: 100%; text-align: left; border: none; background: none; cursor: pointer;
  font-family: var(--font-body); font-size: var(--text-sm); color: var(--fg1);
  padding: 10px 12px; border-radius: var(--radius-xs);
}
.emw-opt:hover { background: var(--bg-sunk); }
.emw-opt.is-active { background: var(--wash-blue); color: var(--blue-700); font-weight: 700; }

/* visually-hidden but accessible to screen readers (replaces the old Tailwind utility) */
.sr-only {
  position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* =====================================================================
   "OPENING A MOMENT" — seal-breaking animation before playback
   ===================================================================== */
.unseal-overlay { background: rgba(10,15,24,.78); -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px); }
.unseal-stage { display: flex; flex-direction: column; align-items: center; gap: 28px; text-align: center; }
.unseal-seal { position: relative; width: 132px; height: 132px; display: flex; align-items: center; justify-content: center; }

/* concentric rings that pulse outward */
.unseal-rings, .unseal-rings::before, .unseal-rings::after {
  position: absolute; left: 50%; top: 50%; width: 92px; height: 92px;
  border-radius: 999px; border: 2px solid var(--gold-400); transform: translate(-50%,-50%);
  opacity: 0;
}
.unseal-rings { animation: unseal-ring 1.8s var(--ease-out) .15s forwards; }
.unseal-rings::before { content: ""; animation: unseal-ring 1.8s var(--ease-out) .35s forwards; }
.unseal-rings::after  { content: ""; animation: unseal-ring 1.8s var(--ease-out) .55s forwards; }
@keyframes unseal-ring {
  0% { opacity: .7; width: 92px; height: 92px; }
  100% { opacity: 0; width: 190px; height: 190px; }
}

/* the gold wax-seal disc */
.unseal-disc {
  position: relative; z-index: 2; width: 92px; height: 92px; border-radius: 999px;
  background: linear-gradient(180deg, var(--gold-300), var(--gold-500));
  color: var(--ink-900); display: flex; align-items: center; justify-content: center;
  box-shadow: 0 12px 30px rgba(249,192,11,.5), inset 0 -3px 8px rgba(143,104,0,.4);
  animation: unseal-disc-pop .5s var(--ease-spring) both;
}
@keyframes unseal-disc-pop { 0% { transform: scale(.4); opacity: 0; } 60% { transform: scale(1.08); } 100% { transform: scale(1); opacity: 1; } }
.unseal-disc .ic { position: absolute; width: 40px; height: 40px; }
/* lock fades/rotates out, lock-open fades in — the "break" */
.unseal-lock { animation: unseal-lock-out .4s var(--ease-out) .55s both; }
.unseal-open { opacity: 0; animation: unseal-open-in .5s var(--ease-spring) .95s both; }
@keyframes unseal-lock-out { 0% { opacity: 1; transform: scale(1) rotate(0); } 100% { opacity: 0; transform: scale(.6) rotate(-18deg); } }
@keyframes unseal-open-in  { 0% { opacity: 0; transform: scale(.5); } 60% { transform: scale(1.15); } 100% { opacity: 1; transform: scale(1); } }

/* gold burst flash at the moment it opens */
.unseal-burst {
  position: absolute; left: 50%; top: 50%; width: 16px; height: 16px; transform: translate(-50%,-50%);
  border-radius: 999px; background: radial-gradient(circle, rgba(255,247,225,.95), rgba(249,192,11,.5) 40%, transparent 70%);
  opacity: 0; animation: unseal-burst .6s var(--ease-out) .95s forwards;
}
@keyframes unseal-burst { 0% { opacity: 0; transform: translate(-50%,-50%) scale(.3); } 30% { opacity: 1; } 100% { opacity: 0; transform: translate(-50%,-50%) scale(9); } }

.unseal-title {
  font-family: var(--font-display); font-weight: 600; font-size: var(--text-lg);
  color: #fff; margin: 0; letter-spacing: -0.01em;
  opacity: 0; animation: unseal-text .5s var(--ease-out) .9s both;
}
@keyframes unseal-text { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }

@media (prefers-reduced-motion: reduce) {
  .unseal-rings, .unseal-rings::before, .unseal-rings::after,
  .unseal-disc, .unseal-lock, .unseal-open, .unseal-burst, .unseal-title { animation: none; }
  .unseal-lock { display: none; } .unseal-open { opacity: 1; } .unseal-title { opacity: 1; }}

/* =====================================================================
   FIRST-LOGIN WELCOME — warm greeting shown once per browser
   ===================================================================== */

/* =====================================================================
   VAULT DASHBOARD — empty state, "add vault" card, and the wide
   two-step create modal. Reuses the design tokens above.
   ===================================================================== */

/* Empty dashboard: a calm invitation to make the first vault. */
.vault-empty { text-align: center; max-width: 520px; margin: clamp(40px, 9vh, 100px) auto 0; }
.vault-empty-orb {
  width: 84px; height: 84px; border-radius: var(--radius-pill); margin: 0 auto 22px;
  background: var(--wash-gold); color: var(--gold-600);
  display: flex; align-items: center; justify-content: center;
}
.vault-empty-orb .ic { width: 38px; height: 38px; }
.vault-empty h2 { font-family: var(--font-display); font-weight: 700; font-size: var(--text-2xl); color: var(--fg1); margin: 0 0 10px; }
.vault-empty .sub { font-family: var(--font-body); font-size: var(--text-base); color: var(--fg2); line-height: 1.6; margin: 0 0 26px; }

/* "New vault" tile that lives at the end of the memory grid. */
.memory-card-add {
  border: 2px dashed var(--border); background: var(--bg-sunk);
  display: flex; align-items: center; justify-content: center;
  cursor: pointer; color: var(--fg2);
  font-family: var(--font-body); font-weight: 700;
  transition: border-color var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
}
.memory-card-add::after { content: none; }   /* no gradient veil on the add tile */
.memory-card-add:hover { border-color: var(--gold-500); color: var(--gold-600); transform: translateY(-4px); }
.add-inner { display: inline-flex; align-items: center; gap: 8px; }
.add-inner .ic { width: 18px; height: 18px; }

/* Wide modal variant for the multi-field create flow (base modal is a
   narrow, centered confirmation dialog). */
.modal-card-wide {
  max-width: 780px; text-align: left;
  /* Cap height to the viewport, but DON'T clip with overflow:auto — that traps
     the absolutely-positioned date popup and forces a stray scrollbar. The
     calendar flips up (.emw-pop.is-up) when low, so it stays on-screen. */
  max-height: 92vh; overflow: visible;
}
.modal-card-wide h2 { text-align: left; }
.modal-card-wide .modal-sub { text-align: left; margin-bottom: 22px; }
/* Tall wide modals (create vault, change cover) on a laptop-height screen: the
   create flow's Details step outgrew 92vh once it carried the cover picker, and
   .modal-card-wide deliberately doesn't clip (the date popup must escape), so
   its Continue button fell below the fold with no way to reach it. Same fix
   the phone breakpoint applies to every modal: the overlay scrolls and the card
   takes its natural height. margin:auto keeps a card that fits centred and
   drops to zero when it doesn't, so a tall card starts at the top and is never
   cut off above the fold. overflow-x pinned for the same reason as on phones. */
.modal-overlay-scroll { overflow-y: auto; overflow-x: hidden; }
.modal-overlay-scroll > .modal-card-wide { max-height: none; margin: auto; }

/* ── Settings modal (Account ▸ Billing two-pane layout) ───────────────── */
.settings-layout { display: flex; gap: 28px; margin-top: 18px; }
.settings-sidebar { flex: 0 0 160px; border-right: 1px solid var(--border); padding-right: 18px; }
.settings-section-label { font-family: var(--font-body); font-size: var(--text-xs); font-weight: 700; text-transform: uppercase; letter-spacing: .06em; color: var(--fg3); margin: 0 0 8px; }
.settings-nav-item {
  display: block; width: 100%; text-align: left; font-family: var(--font-body); font-size: var(--text-sm);
  background: transparent; border: none; padding: 9px 12px; border-radius: var(--radius-sm);
  color: var(--fg2); cursor: pointer;
}
.settings-nav-item.is-active { background: var(--bg-sunk); color: var(--fg1); font-weight: 700; }
.settings-panel { flex: 1 1 auto; min-width: 0; }
.settings-row { display: flex; align-items: center; justify-content: space-between; gap: 20px; }
.settings-row-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.settings-row-title { font-family: var(--font-body); font-weight: 700; font-size: var(--text-base); color: var(--fg1); }
.settings-row-sub {
  font-family: var(--font-body); font-size: var(--text-sm); color: var(--fg2); line-height: 1.5;
}
.settings-reactivate-link {
  display: inline-block; margin-top: 10px;
  font-family: var(--font-body); font-size: var(--text-sm); font-weight: 700;
  color: var(--echo-blue); text-decoration: none;
  /* Rendered as a <button> (POSTs to billing:resume) — reset native chrome so
     it still reads as a text link. */
  appearance: none; border: 0; background: none; padding: 0; cursor: pointer;
}
.settings-reactivate-link:hover { text-decoration: underline; }
/* Keep the action button on one line: don't let the flex row shrink it or wrap
   its label. Use the compact button padding/size within this settings row. */
.settings-row .btn {
  flex: 0 0 auto; white-space: nowrap;
  padding: 10px 20px; font-size: var(--text-sm);
}
@media (max-width: 640px) {
  .settings-layout { flex-direction: column; }
  .settings-sidebar { flex-basis: auto; border-right: 0; border-bottom: 1px solid var(--border); padding: 0 0 14px; }}

/* ── Numbered stepper at the top of the create-vault modal ───────────── */
.stepper {
  list-style: none; margin: 0 0 26px; padding: 0;
  display: flex; align-items: center; gap: 0;
}
.stepper-step {
  display: flex; align-items: center; gap: 9px; flex: 1; min-width: 0;
  font-family: var(--font-body); font-size: var(--text-sm); font-weight: 600; color: var(--fg3);
}
/* connector line between steps */
.stepper-step:not(:last-child)::after {
  content: ""; flex: 1; height: 2px; margin: 0 12px; border-radius: 2px;
  background: var(--border); transition: background var(--dur-base) var(--ease-out);
}
.stepper-dot {
  flex: none; width: 28px; height: 28px; border-radius: 999px;
  display: flex; align-items: center; justify-content: center;
  background: var(--bg-sunk); color: var(--fg3); border: 1.5px solid var(--border);
  font-size: var(--text-sm); font-weight: 700;
  transition: background var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out), border-color var(--dur-base) var(--ease-out);
}
.stepper-label { white-space: nowrap; }
/* active step: filled blue dot + dark label */
.stepper-step.is-active .stepper-dot { background: var(--echo-blue); color: #fff; border-color: var(--echo-blue); }
.stepper-step.is-active { color: var(--fg1); }
/* completed step: blue-tinted dot + filled connector */
.stepper-step.is-done .stepper-dot { background: var(--wash-blue); color: var(--echo-blue); border-color: transparent; }
.stepper-step.is-done::after { background: var(--echo-blue); }
@media (max-width: 560px) {
  .stepper-label { display: none; }
  .stepper-step:not(:last-child)::after { margin: 0 8px; }}

/* ── Release-date mode tiles (replaces the bulky pills) — 2×2 icon cards ── */
.mode-tiles { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; }
.mode-tile {
  display: flex; align-items: center; gap: 12px; text-align: left;
  padding: 14px 16px; cursor: pointer;
  background: var(--surface); border: 1.5px solid var(--border); border-radius: var(--radius-md);
  font-family: var(--font-body); font-weight: 600; font-size: var(--text-sm); color: var(--fg1);
  transition: border-color var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out), background var(--dur-base) var(--ease-out);
}
.mode-tile:hover { border-color: var(--blue-200); box-shadow: var(--shadow-sm); }
.mode-tile .mode-tile-ic {
  flex: none; width: 34px; height: 34px; border-radius: var(--radius-sm, 8px);
  display: flex; align-items: center; justify-content: center;
  background: var(--wash-blue); color: var(--echo-blue);
  transition: background var(--dur-base) var(--ease-out), color var(--dur-base) var(--ease-out);
}
.mode-tile .mode-tile-ic .ic { width: 18px; height: 18px; }
.mode-tile.selected {
  border-color: var(--echo-blue); background: var(--wash-blue);
  box-shadow: 0 0 0 3px rgba(21,138,255,.12);
}
.mode-tile.selected .mode-tile-ic { background: var(--echo-blue); color: #fff; }

/* Fifth tile: "decide later" — spans both columns, with a supporting hint line */
.mode-tile-wide { grid-column: 1 / -1; align-items: flex-start; }
.mode-tile-text { display: flex; flex-direction: column; gap: 3px; }
.mode-tile-wide .mode-tile-hint {
  font-weight: 400; font-size: var(--text-xs); color: var(--fg2); line-height: 1.45;
}
.mode-tile-wide.selected .mode-tile-hint { color: color-mix(in srgb, var(--echo-blue) 70%, var(--fg1)); }

/* Breathing room between the mode tiles and the active mode pane below them. */
[data-mode-pane] { padding-top: 8px; }

@media (max-width: 480px) { .mode-tiles { grid-template-columns: 1fr; }}

/* Tighter choice grid inside the modal (the wizard version is full-page). */
.choice-grid-compact { grid-template-columns: repeat(2, 1fr); gap: 12px; margin-bottom: 20px; }
.choice-grid-compact .choice { padding: 16px 18px; }
/* tighter icon + smaller wash so the compact card isn't hollow */
.choice-grid-compact .choice .choice-ic { width: 40px; height: 40px; margin-bottom: 12px; }
.choice-grid-compact .choice .choice-ic .ic { width: 20px; height: 20px; }
.choice-grid-compact .choice h3 { font-size: var(--text-base); margin: 0 0 4px; }
.choice-grid-compact .choice p { font-size: var(--text-xs); line-height: 1.45; }
.choice-grid-compact .choice::after { background: linear-gradient(0deg, var(--rt-wash, transparent) 0%, transparent 60%); }
/* selected-state check badge (top-right), shown only when the card is chosen */
.choice-check {
  position: absolute; top: 12px; right: 12px; z-index: 2;
  width: 22px; height: 22px; border-radius: 999px;
  display: flex; align-items: center; justify-content: center;
  background: var(--echo-blue); color: #fff;
  opacity: 0; transform: scale(.6); transition: opacity var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
}
.choice-check .ic { width: 14px; height: 14px; }
.choice.selected .choice-check { opacity: 1; transform: scale(1); }
@media (max-width: 560px) { .choice-grid-compact { grid-template-columns: 1fr; }}

/* Inline error summary shown at the top of the create-vault modal's details
   step when a submit comes back invalid (so it's never hidden below the fold). */
.form-error-summary {
  display: flex; align-items: center; gap: 10px;
  margin: 0 0 18px; padding: 12px 14px; border-radius: var(--radius-md);
  background: var(--danger-bg); color: var(--danger);
  border: 1px solid color-mix(in srgb, var(--danger) 30%, transparent);
  font-family: var(--font-body); font-size: var(--text-sm); font-weight: 600;
}
.form-error-summary .ic { width: 18px; height: 18px; flex: none; }

/* Walkthrough nudge inside the welcome banner (first-visit only). */
.vault-hero-link {
  display: inline-flex; align-items: center; gap: 7px; margin-top: 20px;
  font-family: var(--font-body); font-weight: 600; font-size: var(--text-sm);
  color: #fff; text-decoration: none; padding: 8px 14px; border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, .16); transition: background var(--dur-base) var(--ease-out);
}
.vault-hero-link:hover { background: rgba(255, 255, 255, .26); }
.vault-hero-link .ic { width: 16px; height: 16px; }

/* =====================================================================
   VAULT DETAIL PAGE — header + moments grid
   ===================================================================== */
/* Reflection-type hue map, shared by the detail header and moment cards. */
.vault-head[data-rtype="child"],       .moment-card[data-rtype="child"]       { --rt:#e8588f; --rt-ink:#a5285c; --rt-wash:#fdeef4; }
.vault-head[data-rtype="future_self"], .moment-card[data-rtype="future_self"] { --rt:#7a5af0; --rt-ink:#4a32a8; --rt-wash:#f0ecfd; }
.vault-head[data-rtype="loved_one"],   .moment-card[data-rtype="loved_one"]   { --rt:#e2503f; --rt-ink:#a8331f; --rt-wash:#fdecea; }
.vault-head[data-rtype="personal"],    .moment-card[data-rtype="personal"]    { --rt:#0e9c8c; --rt-ink:#0a6b60; --rt-wash:#e6f7f4; }
.vault-head[data-rtype="advice"],      .moment-card[data-rtype="advice"]      { --rt:#e0a800; --rt-ink:#8f6800; --rt-wash:#fff8e6; }
.vault-head[data-rtype="other"],       .moment-card[data-rtype="other"]       { --rt:#158aff; --rt-ink:#0a59b4; --rt-wash:#eef6ff; }
.vault-head, .moment-card { --rt: var(--echo-blue); --rt-ink: var(--blue-700); --rt-wash: var(--wash-blue); }

/* Header band: a soft type-tinted card with the glyph as a watermark. */
.vault-head {
  position: relative; overflow: hidden; margin: 18px 0 18px;
  display: flex; align-items: flex-start; gap: 20px;
  padding: clamp(24px, 3vw, 34px); border-radius: var(--radius-xl);
  background: linear-gradient(135deg, color-mix(in srgb, var(--rt) 14%, var(--surface)), var(--surface) 70%);
  border: 1px solid var(--border);
}
.vault-head-glyph {
  flex: none; width: 58px; height: 58px; border-radius: var(--radius-lg);
  display: flex; align-items: center; justify-content: center;
  background: var(--rt-wash); color: var(--rt-ink);
}
.vault-head-glyph .ic { width: 28px; height: 28px; }
.vault-head-main { flex: 1; min-width: 0; }
.vault-head-main h1 { font-family: var(--font-display); font-weight: 700; font-size: var(--text-2xl); color: var(--fg1); margin: 0 0 6px; letter-spacing: -0.02em; }
.vault-head-meta { font-family: var(--font-body); font-size: var(--text-base); color: var(--fg2); margin: 0; }
.vault-head-desc { font-family: var(--font-body); font-size: var(--text-sm); color: var(--fg2); margin: 10px 0 0; line-height: 1.55; }
.vault-head-status { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 16px; }

/* Live countdown to a sealed vault's release date. Pinned to the right of the
   banner (a direct flex child of .vault-head, which keeps .vault-head-main at
   flex:1 on the left). */
.countdown { flex: none; align-self: flex-start; display: flex; gap: clamp(12px, 2vw, 22px); }
.countdown-cell { display: flex; flex-direction: column; align-items: center; }

/* Odometer digit window: a fixed-size clipped box showing one line. On update the
   inner reel (current value + incoming value stacked above it) slides down so the
   new number rolls in from the top, like a mechanical meter. */
.countdown-num {
  /* Fixed width so digit changes (e.g. 9 → 10) never shift the layout. h/m/s are
     always 2 zero-padded digits; days can run to 3 (a year+ out). */
  --cd-line: clamp(1.7rem, 4vw, 2.4rem);
  display: block; width: 2.2ch; height: var(--cd-line);
  overflow: hidden; position: relative;
  font-family: var(--font-display); font-weight: 700;
  font-size: var(--cd-line); line-height: var(--cd-line);
  color: var(--fg1); font-variant-numeric: tabular-nums; letter-spacing: -0.02em;
}
.countdown-num[data-cd="days"] { width: 3.4ch; }
.countdown-reel {
  display: flex; flex-direction: column;
  /* Start showing the bottom line (current value); the incoming value sits above. */
  transform: translateY(calc(var(--cd-line) * -1));
}
.countdown-reel > span { display: block; height: var(--cd-line); text-align: center; }
.countdown-num.is-rolling .countdown-reel {
  transform: translateY(0);
  transition: transform 0.6s cubic-bezier(0.22, 1, 0.36, 1);
}
@media (prefers-reduced-motion: reduce) {
  .countdown-num.is-rolling .countdown-reel { transition: none; }}
.countdown-label {
  margin-top: 6px; font-family: var(--font-body); font-size: var(--text-xs);
  color: var(--fg2); text-transform: lowercase; letter-spacing: var(--tracking-caps);
}
.status-muted { background: var(--bg-sunk); color: var(--fg2); }
.status-sealed { background: var(--wash-gold); color: var(--gold-600); }
.vault-locked-note { display: flex; align-items: center; gap: 8px; margin: 0 0 26px; }
.vault-locked-note .ic { width: 15px; height: 15px; flex: none; }

/* Delivery address + the way to change it, under the vault header. Owner-only
   and open-vaults-only (see vault_detail.html). */
.recipient-strip {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
  padding: 13px 18px; margin: 0 0 14px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-md);
}
.recipient-strip > .ic { width: 17px; height: 17px; color: var(--fg3); flex: none; }
.recipient-strip-text {
  flex: 1; min-width: 0;
  font-family: var(--font-body); font-size: var(--text-sm); color: var(--fg2);
}
.recipient-strip-text strong { color: var(--fg1); font-weight: 700; word-break: break-all; }
.recipient-strip .btn { flex: none; }
@media (max-width: 620px) {
  .recipient-strip { align-items: flex-start; }
  .recipient-strip .btn { width: 100%; justify-content: center; }}

/* A value the owner may read but not edit (a released vault's address, on the
   no-JS fallback page behind the change-email modal). */
.readonly-value {
  font-family: var(--font-body); font-size: var(--text-base); color: var(--fg1);
  background: var(--bg-sunk); border: 1px solid var(--border);
  border-radius: var(--radius-md); padding: 14px 16px; word-break: break-all;
}
@media (max-width: 620px) {
  .vault-head { flex-wrap: wrap; }
  /* Countdown drops below the content and reads left-aligned on small screens. */
  .countdown { width: 100%; margin-top: 4px; justify-content: flex-start; }}

/* Moments grid: same card language as the dashboard, a touch smaller. */
.moment-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); gap: 16px; }
.moment-card {
  position: relative; display: block; overflow: hidden; text-decoration: none; color: #fff;
  aspect-ratio: 1 / 1; min-height: 180px;
  border-radius: var(--radius-lg); border: 1px solid var(--border); box-shadow: var(--shadow-sm);
  transition: transform var(--dur-base) var(--ease-out), box-shadow var(--dur-base) var(--ease-out);
}
.moment-card[href]:hover { transform: translateY(-4px); box-shadow: var(--shadow-lg); }
.moment-card-bg {
  position: absolute; inset: 0; z-index: 0;
  background:
    radial-gradient(95% 75% at 78% 12%, rgba(255,255,255,.24), transparent 60%),
    linear-gradient(160deg, var(--rt) 0%, var(--rt-ink) 80%);
  /* An inline background-image cover, when present, layers over the gradient
     fallback. Size/position live here so the shorthand above can't reset them. */
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}
.moment-card.is-sealed .moment-card-bg { filter: saturate(.82) brightness(.92); }
.moment-card-glyph { position: absolute; right: 10px; top: 8px; z-index: 1; color: rgba(255,255,255,.18); display: flex; }
.moment-card-glyph .ic { width: 84px; height: 84px; }
.moment-card::after {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(180deg, transparent 35%, rgba(8,12,20,.62) 100%);
}
.moment-card-corner, .moment-card-play {
  position: absolute; z-index: 3; right: 12px; top: 12px;
  width: 32px; height: 32px; border-radius: var(--radius-pill);
  display: flex; align-items: center; justify-content: center;
  background: rgba(255,255,255,.22); -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
  color: #fff; border: 1px solid rgba(255,255,255,.32);
}
.moment-card-corner .ic, .moment-card-play .ic { width: 16px; height: 16px; }
/* The sealed-moment corner badge carries the lock, which is the brand mark, so
   it wears gold (the play badge beside it stays neutral white-on-glass). */
.moment-card-corner.is-lock { color: var(--moment-gold); }
.moment-card-overlay { position: absolute; z-index: 2; inset: auto 0 0 0; padding: 14px 14px 16px; }
.moment-card-overlay h3 { font-family: var(--font-display); font-weight: 700; font-size: var(--text-md); color: #fff; margin: 0; line-height: 1.2; text-shadow: 0 1px 10px rgba(0,0,0,.3); }
.moment-card-sub { font-family: var(--font-body); font-size: var(--text-xs); color: rgba(255,255,255,.82); margin: 3px 0 0; }

/* Storage meter in the vault header (owner only) — account-wide usage vs the
   accruing allowance (PRD 03 scope item 9), with a warning state at
   STORAGE_WARNING_THRESHOLD_PERCENT and an over-allowance state once uploads
   are refused. */
.storage-meter { margin-top: 16px; max-width: 320px; }
.storage-meter-bar {
  height: 7px; border-radius: 999px; background: var(--bg-sunk); overflow: hidden;
  border: 1px solid var(--border);
}
.storage-meter-bar span {
  display: block; height: 100%; border-radius: 999px;
  background: linear-gradient(90deg, var(--echo-blue), var(--blue-500));
  transition: width var(--dur-base) var(--ease-out);
}
.storage-meter-bar.is-warning span { background: var(--warning); }
.storage-meter-bar.is-over span { background: var(--danger); }
.storage-meter-label { display: block; margin-top: 6px; font-family: var(--font-body); font-size: var(--text-xs); color: var(--fg3); }
.storage-meter.is-warning .storage-meter-label { color: var(--gold-600); }
.storage-meter.is-over .storage-meter-label { color: var(--danger); }
/* PRD 05: "Need more space?" CTA, shown only for an eligible owner near/over
   allowance (vault_detail.html) — kept minimal, matching .settings-reactivate-link. */
.storage-meter-cta {
  display: inline-block; margin-top: 8px;
  font-family: var(--font-body); font-size: var(--text-xs); font-weight: 700;
  color: var(--echo-blue); text-decoration: none;
}
.storage-meter-cta:hover { text-decoration: underline; }

/* Empty-vault first-moment tile (shown only when there are no moments). */
.moment-empty {
  display: flex; flex-direction: column; align-items: center; text-align: center;
  gap: 8px; padding: clamp(32px, 6vw, 56px) 24px; max-width: 460px; margin: 8px 0;
  border: 2px dashed var(--border); border-radius: var(--radius-lg);
  background: var(--bg-sunk); text-decoration: none; cursor: pointer;
  transition: border-color var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-out);
}
.moment-empty:hover { border-color: var(--gold-500); transform: translateY(-3px); }
.moment-empty-orb {
  width: 52px; height: 52px; border-radius: var(--radius-pill); margin-bottom: 6px;
  display: flex; align-items: center; justify-content: center;
  background: var(--wash-gold); color: var(--gold-600);
}
.moment-empty-orb .ic { width: 24px; height: 24px; }
.moment-empty-title { font-family: var(--font-display); font-weight: 700; font-size: var(--text-md); color: var(--fg1); }
.moment-empty-sub { font-family: var(--font-body); font-size: var(--text-sm); color: var(--fg2); line-height: 1.5; }

/* =====================================================================
   MOMENTS TOOLBAR + LIST VIEW + SPEED-DIAL FAB (vault detail)
   ===================================================================== */
.moment-toolbar {
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin: 0 0 20px;
}
.moment-search {
  position: relative; flex: 1; min-width: 220px;
  display: flex; align-items: center;
}
.moment-search .ic { position: absolute; left: 14px; width: 17px; height: 17px; color: var(--fg3); pointer-events: none; }
.moment-search input {
  width: 100%; padding: 11px 14px 11px 40px;
  border: 1px solid var(--border); border-radius: var(--radius-pill);
  background: var(--surface); font-family: var(--font-body); font-size: var(--text-sm); color: var(--fg1);
}
.moment-search input:focus { outline: none; border-color: var(--border-focus); box-shadow: 0 0 0 3px rgba(21,138,255,.12); }
.moment-tools { display: flex; align-items: center; gap: 10px; }
.moment-sort .select { min-width: 150px; }

/* sealed moment cards are <button>s now — reset native button chrome */
button.moment-card { width: 100%; text-align: left; font: inherit; cursor: pointer; }

/* List view: cards reflow into compact horizontal rows. */
/* List view: clean neutral rows — a small type-tinted thumbnail on the left,
   dark title + sub text on a surface row, and the status/lock pulled right.
   (Reads like a real list rather than a full-bleed colored banner.) */
.moment-grid.is-list { display: flex; flex-direction: column; gap: 8px; }
.moment-grid.is-list .moment-card {
  aspect-ratio: auto; min-height: 0; height: 64px;
  display: flex; align-items: center; gap: 14px;
  padding: 0 16px 0 0; overflow: hidden;
  /* Soft tint of the row's own reflection-type hue (not flat white), so rows
     stand off the near-white page and read as cards. --rt is set per row via
     data-rtype; ~12% over the surface gives a gentle lavender/pink/etc. wash. */
  background: color-mix(in srgb, var(--rt) 12%, var(--surface));
  color: var(--fg1);
  border: 1px solid color-mix(in srgb, var(--rt) 22%, var(--border));
  box-shadow: var(--shadow-xs);
}
.moment-grid.is-list .moment-card:hover {
  transform: translateY(-1px); box-shadow: var(--shadow-sm);
  background: color-mix(in srgb, var(--rt) 18%, var(--surface));
  border-color: color-mix(in srgb, var(--rt) 38%, var(--border));
}
/* No gradient block in list view (a dark thumbnail leaves a visible seam
   against the soft row tint). Instead, drop the gradient surface and show the
   glyph in a soft rounded badge — same hue family as the row, so it blends. */
.moment-grid.is-list .moment-card-bg { display: none; }
.moment-grid.is-list .moment-card::after { content: none; }   /* no full-card scrim in list mode */
.moment-grid.is-list .moment-card-glyph {
  position: static; flex: none; order: 0; transform: none;
  width: 40px; height: 40px; margin-left: 14px; border-radius: var(--radius-md);
  display: flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--rt) 26%, var(--surface));
  color: var(--rt-ink);
}
.moment-grid.is-list .moment-card-glyph .ic { width: 20px; height: 20px; }
/* text block flows after the thumbnail, dark on the neutral row */
.moment-grid.is-list .moment-card-overlay { position: static; flex: 1; min-width: 0; padding: 0; order: 1; }
.moment-grid.is-list .moment-card-overlay h3 {
  font-size: var(--text-md); color: var(--fg1); text-shadow: none;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.moment-grid.is-list .moment-card-sub { color: var(--fg2); }
.moment-grid.is-list .moment-card-sub .ic { color: var(--fg3); }
/* status / lock / play pulled to the right edge, as a quiet chip */
.moment-grid.is-list .moment-card-corner,
.moment-grid.is-list .moment-card-play {
  position: static; flex: none; transform: none; margin-left: auto; order: 2;
  width: 32px; height: 32px;
  background: var(--surface); color: var(--fg2); border: 1px solid var(--border);
  -webkit-backdrop-filter: none; backdrop-filter: none;
}
/* Keep the brand gold on the lock chip in list view too (matching specificity
   so it isn't reset to --fg2 by the rule above). */
.moment-grid.is-list .moment-card-corner.is-lock { color: var(--moment-gold); }
.moment-grid.is-list .moment-card-play { color: var(--echo-blue); }

/* =====================================================================
   UNIFIED CARD LANGUAGE — one soft, type-tinted look across dashboard
   vault cards, detail moment cards, list rows and reflection tiles.
   (Overrides the older bold-gradient treatment; source-order wins.)
   ===================================================================== */

/* ---- Dashboard vault cards + detail grid moment cards: soft tint ---- */
.memory-card:not(.memory-card-add), .moment-card:not(.moment-card-add) {
  color: var(--fg1);
  background: color-mix(in srgb, var(--rt) 10%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--rt) 22%, var(--border));
}
/* drop the saturated gradient + dark scrim — light surface needs neither */
.moment-card-bg{ display: none; }
.memory-card::after, .moment-card::after { content: none; }

/* ---- Moment cards that carry a cover photo: show it edge-to-edge ----
   The unified light surface hides .moment-card-bg, but when a moment has an
   uploaded cover we reveal that layer (its inline background-image paints the
   photo), restore the dark bottom scrim for legibility, and switch the title
   to white so it reads over the image. */
.moment-card.has-cover .moment-card-bg { display: block; }
.moment-card.has-cover::after {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(180deg, transparent 35%, rgba(8,12,20,.62) 100%);
}
.moment-card.has-cover { color: #fff; }
.moment-card.has-cover .moment-card-overlay h3,
.moment-card.has-cover .moment-card-sub { color: #fff; }

/* glyph → a rounded type-colored badge, top-left, like the list/choice icon */
.memory-glyph, .moment-card-glyph {
  position: absolute; right: auto; left: 16px; top: 16px; transform: none;
  width: 46px; height: 46px; border-radius: var(--radius-md);
  display: flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--rt) 22%, var(--surface));
  color: var(--rt-ink);
}
.memory-glyph .ic, .moment-card-glyph .ic { width: 24px; height: 24px; }

/* overlaid text → dark, sits at the bottom over the tint (no scrim needed) */
.memory-overlay h3, .moment-card-overlay h3 { color: var(--fg1); text-shadow: none; }
.memory-overlay p, .moment-card-sub { color: var(--fg2); }
/* meta line (moment count + release status) under the title */
.memory-meta { display: flex; flex-direction: column; gap: 5px; margin-top: 10px; }
.memory-meta > span { display: inline-flex; align-items: center; gap: 6px; font-family: var(--font-body); font-weight: 600; font-size: var(--text-sm); color: var(--fg2); }
.memory-meta .ic { width: 14px; height: 14px; color: var(--fg3); }
.memory-unlock { color: var(--rt-ink); }
.memory-unlock .ic { color: var(--rt-ink); }
.memory-corner, .moment-card-corner, .moment-card-play {
  background: var(--surface); color: var(--fg2);
  border: 1px solid var(--border); -webkit-backdrop-filter: none; backdrop-filter: none;
}
.memory-corner.is-open { background: var(--wash-gold); color: var(--gold-600); border-color: transparent; }
.moment-card-play { color: var(--echo-blue); }
.memory-card:not(.memory-card-add):hover, .moment-card:not(.moment-card-add):hover {
  border-color: color-mix(in srgb, var(--rt) 40%, var(--border));
}

/* ---- Dashboard vault tiles that carry a theme photo ----
   Mirrors .moment-card.has-cover above. The photo comes from a per-tile
   --vault-img custom property (set inline on the card), and legibility is done
   HERE, in CSS, never baked into the image: a bottom scrim restores contrast
   under the overlaid title/meta and the text switches to white, so any
   candidate photo — light paper or a dark candle — keeps the name readable.
   Same (0,2,0) specificity as the tint rule above, so source order wins. */
.memory-card.has-cover {
  color: #fff;
  background-color: var(--ink-700);
  background-image: var(--vault-img, none);
  background-size: cover; background-position: center;
}
.memory-card.has-cover::after {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(180deg, rgba(8,12,20,.10) 0%, transparent 22%, rgba(8,12,20,.50) 50%, rgba(8,12,20,.86) 100%);
}
.memory-card.has-cover .memory-overlay h3 { color: #fff; text-shadow: 0 1px 10px rgba(0,0,0,.35); }
.memory-card.has-cover .memory-overlay p,
.memory-card.has-cover .memory-meta > span,
.memory-card.has-cover .memory-meta .ic,
.memory-card.has-cover .memory-unlock,
.memory-card.has-cover .memory-unlock .ic { color: rgba(255,255,255,.92); }

/* ---- Vault detail header over its cover (vault/covers.py) ----
   The same cover as the dashboard tile, and the same rule: legibility lives in
   CSS layers, never in the image. Top to bottom: a dark scrim, heaviest on the
   left where the title and meta sit; a wash of the type hue, so the header
   still reads as its reflection type; then the photo. The type glyph badge
   keeps its own tinted chip on top. Falls back to the tinted header (the
   .vault-head rule above) when there's no cover or it fails to load. */
.vault-head.has-cover {
  border-color: transparent;
  background-color: var(--ink-700);
  background-image:
    linear-gradient(90deg, rgba(8,12,20,.80) 0%, rgba(8,12,20,.60) 55%, rgba(8,12,20,.40) 100%),
    linear-gradient(135deg, color-mix(in srgb, var(--rt) 40%, transparent), transparent 65%),
    var(--vault-img, none);
  background-size: cover; background-position: center;
}
.vault-head.has-cover .vault-head-main h1 { color: #fff; text-shadow: 0 1px 12px rgba(0,0,0,.3); }
.vault-head.has-cover .vault-head-meta,
.vault-head.has-cover .vault-head-desc,
.vault-head.has-cover .storage-meter-label { color: rgba(255,255,255,.88); }
.vault-head.has-cover .storage-meter-bar { background: rgba(255,255,255,.2); border-color: transparent; }
.vault-head.has-cover .storage-meter-cta { color: #fff; }
.vault-head.has-cover .countdown-num { color: #fff; }
.vault-head.has-cover .countdown-label { color: rgba(255,255,255,.8); }
.vault-head.has-cover .status-muted { background: rgba(255,255,255,.16); color: #fff; }
.vault-head.has-cover .status-pill-action.status-muted:hover,
.vault-head.has-cover .status-pill-action.status-muted:focus-visible { background: rgba(255,255,255,.3); color: #fff; }

/* ---- Cover picker (vault/_cover_picker.html) ----
   Reuses the moment-photo cover selection (.attach-thumb / .is-cover / the
   "Cover" badge) so choosing a vault cover feels the same; tiles take the
   dashboard card's 5:4 shape instead of square. */
.cover-grid { grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); }
.cover-opt { aspect-ratio: 5 / 4; border-color: var(--border); }
.cover-opt-face {
  width: 100%; height: 100%; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 6px; text-align: center;
  font-family: var(--font-body); font-weight: 700; font-size: var(--text-xs);
  color: var(--blue-600); background: var(--wash-blue);
}
.cover-opt-face .ic { width: 20px; height: 20px; }
/* .attach-thumb img sets display:block, which would beat the UA's [hidden]. */
.cover-opt-face[hidden], .cover-opt img[hidden] { display: none; }
.cover-file { display: block; margin-top: 10px; font-family: var(--font-body); font-size: var(--text-sm); }
/* "Save cover" stays disabled until a pick is made (data-require-change). */
.cover-form .btn:disabled { opacity: .45; cursor: not-allowed; box-shadow: none; }

/* ---- Reflection-type tiles: color the icon badge by type (was always blue) ---- */
.choice .choice-ic {
  background: color-mix(in srgb, var(--rt, var(--echo-blue)) 18%, var(--surface));
  color: var(--rt-ink, var(--echo-blue));
}
.choice.selected .choice-check { background: var(--rt, var(--echo-blue)); }

/* Write (letter) pane — a full-height text editor inside the recorder stage. */
.rec-write { position: absolute; inset: 0; padding: 14px; display: flex; }
.rec-write .textarea {
  flex: 1; width: 100%; height: 100%; resize: none; border-radius: var(--radius-lg);
  border: 1px solid var(--border); background: var(--surface); color: var(--fg1);
  padding: 16px 18px; font-family: var(--font-body); font-size: var(--text-base); line-height: 1.6;
}
.rec-write .textarea:focus { outline: none; border-color: var(--border-focus); box-shadow: 0 0 0 3px rgba(21,138,255,.12); }

/* A written letter, shown on the playback page. */
.playback-letter { font-family: var(--font-body); font-size: var(--text-md); line-height: 1.75; color: var(--fg1); white-space: normal; }
.playback-letter p { margin: 0 0 14px; }

/* =====================================================================
   WALKTHROUGH — scene tiles, step rows, and welcome modal scene
   Used by: vault/walkthrough.html and vault/_welcome_modal.html
   Tokens: --echo-blue --moment-gold --blue-700 --gold-600 --ink-800
           --radius-xl --shadow-md --font-display --text-xl --text-lg
           --surface --border --fg2
   ===================================================================== */

/* ---- Shared scene tile (gradient panel with Lucide glyphs) --------- */
.wt-scene {
  position: relative;
  width: 108px; height: 108px;
  border-radius: var(--radius-xl);
  display: flex; align-items: center; justify-content: center;
  flex-shrink: 0;
  /* subtle inner highlight */
  box-shadow: var(--shadow-md), inset 0 1px 0 rgba(255,255,255,.18);
  overflow: hidden;
}

/* Gradient variants */
.wt-scene--blue  { background: linear-gradient(135deg, var(--echo-blue) 0%, var(--blue-700) 100%); }

/* Main glyph — large, white, centered */
.wt-scene .wt-scene-main {
  width: 48px; height: 48px; color: #fff; flex-shrink: 0;
  position: relative; z-index: 1;
}

/* Accent glyph — smaller, bottom-right offset */
.wt-scene .wt-scene-accent {
  position: absolute; bottom: 10px; right: 10px;
  width: 22px; height: 22px; color: rgba(255,255,255,.65);
  z-index: 1;
}

/* ---- Screenshot tile (real app screenshots, replaces .wt-scene on the
        static /walkthrough/ page; .wt-scene itself is kept for the modal) - */
.wt-shot {
  flex-shrink: 0;
  width: 400px; max-width: 400px;
}
.wt-shot img {
  display: block; width: 100%; height: auto;
  border-radius: var(--radius-lg);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-md);
  background: var(--surface);
}

/* ---- Step 1 hero carousel: cross-fading stack of the four create screens -- */
/* The hero step gets a colossal shot; the paired text stays flexible beside it. */
.wt-step-hero .wt-shot-carousel {
  width: 620px; max-width: 620px;
  position: relative;
  aspect-ratio: 5 / 4;              /* holds the frame while images cross-fade */
  background: var(--bg-sunk);       /* letterbox fill behind contained images */
  border-radius: var(--radius-lg);
  overflow: hidden;
}
/* Show the whole screenshot (never crop): portrait moment-form shots and
   landscape vault/modal shots both fit inside the frame, letterboxed as needed. */
.wt-shot-carousel img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: contain; object-position: center;
  opacity: 0;
  transition: opacity var(--dur-slow, 700ms) var(--ease-out);
}
.wt-shot-carousel img.is-active { opacity: 1; }
/* Progress dots, bottom-center over the frame */
.wt-carousel-dots {
  position: absolute; z-index: 2; left: 0; right: 0; bottom: 14px;
  display: flex; justify-content: center; gap: 8px;
}
.wt-carousel-dots span {
  width: 8px; height: 8px; border-radius: var(--radius-pill);
  background: rgba(255,255,255,.55); box-shadow: 0 1px 4px rgba(0,0,0,.25);
  transition: background var(--dur-base) var(--ease-out), width var(--dur-base) var(--ease-out);
}
.wt-carousel-dots span.is-active { background: #fff; width: 22px; }
/* Prev / next arrows, overlaid on the left and right edges of the frame */
.wt-carousel-nav {
  position: absolute; z-index: 3; top: 50%; transform: translateY(-50%);
  width: 40px; height: 40px; border-radius: var(--radius-pill);
  display: flex; align-items: center; justify-content: center;
  border: 1px solid rgba(255,255,255,.4);
  background: rgba(14,23,38,.42); color: #fff;
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
  cursor: pointer;
  transition: background var(--dur-base) var(--ease-out), transform var(--dur-fast) var(--ease-out);
}
.wt-carousel-nav:hover { background: rgba(14,23,38,.62); }
.wt-carousel-nav:active { transform: translateY(-50%) scale(.92); }
.wt-carousel-nav .ic { width: 20px; height: 20px; }
.wt-carousel-prev { left: 12px; }
.wt-carousel-next { right: 12px; }
@media (prefers-reduced-motion: reduce) {
  .wt-shot-carousel img { transition: none; }}

/* ---- Page header (walkthrough.html only) --------------------------- */
.wt-head { max-width: 60ch; margin: 4px 0 48px; }
.wt-eyebrow {
  font-family: var(--font-display); font-size: var(--text-sm); font-weight: 600;
  text-transform: uppercase; letter-spacing: .12em;
  color: var(--echo-blue); margin: 0 0 12px;
}
.wt-head h1 {
  font-family: var(--font-display); font-weight: 700;
  font-size: var(--text-3xl); letter-spacing: -0.02em; line-height: 1.08;
  color: var(--fg1); margin: 0 0 16px;
}
.wt-lede {
  font-family: var(--font-body); font-size: var(--text-md);
  line-height: 1.65; color: var(--fg2); margin: 0;
}

/* ---- Walkthrough steps container ------------------------------------ */
.wt-steps {
  display: flex; flex-direction: column;
  gap: 40px;
  padding: 8px 0 40px;
}

/* Numbered eyebrow above each step heading — the steps are a real sequence,
   so the order carries meaning the reader needs. */
.wt-step-num {
  display: inline-block;
  font-family: var(--font-display); font-size: var(--text-sm); font-weight: 600;
  text-transform: uppercase; letter-spacing: .1em;
  color: var(--echo-blue); margin-bottom: 10px;
}

/* ---- Individual step row: scene tile + descriptive text ------------- */
.wt-step {
  display: flex; flex-direction: row;
  align-items: center;
  gap: 36px;
}

/* On the page, make the scene tile larger than in the modal */
.wt-steps .wt-scene {
  width: 200px; height: 200px;
  flex-shrink: 0;
}
.wt-steps .wt-scene .wt-scene-main { width: 80px; height: 80px; }
.wt-steps .wt-scene .wt-scene-accent { width: 36px; height: 36px; bottom: 16px; right: 16px; }

/* Reversed steps: text left, tile right. Explicit class (not :nth-child) so the
   spark-row dividers interleaved between steps don't flip the alternation. */
.wt-step-reverse { flex-direction: row-reverse; }

/* Lock + line divider between steps, reusing the landing page's .spark-row. */
.wt-divider { margin: 4px 0; }

/* Step text block */
.wt-step-text { flex: 1; }
.wt-step h2 {
  font-family: var(--font-display); font-size: var(--text-lg); font-weight: 700;
  color: var(--fg1); margin: 0 0 10px; letter-spacing: -0.01em;
}
.wt-step p {
  font-family: var(--font-body); color: var(--fg2); font-size: var(--text-md);
  line-height: 1.65; margin: 0; max-width: 50ch;
}

/* ---- Closing call to action ---------------------------------------- */
.wt-cta {
  margin: 24px 0 8px;
  padding: clamp(32px, 5vw, 52px);
  border-radius: var(--radius-xl);
  background: var(--wash-blue);
  border: 1px solid color-mix(in srgb, var(--echo-blue) 14%, transparent);
  text-align: center;
}
.wt-cta h2 {
  font-family: var(--font-display); font-weight: 700; font-size: var(--text-xl);
  color: var(--fg1); margin: 0 0 8px; letter-spacing: -0.01em;
}
.wt-cta p {
  font-family: var(--font-body); font-size: var(--text-md); color: var(--fg2);
  line-height: 1.6; margin: 0 auto 24px; max-width: 46ch;
}

/* ---- Responsive: stack vertically on small screens ----------------- */
@media (max-width: 720px) {
  .wt-head { margin-bottom: 36px; }
  .wt-steps { gap: 36px; }
  .wt-step, .wt-step-reverse {
    flex-direction: column;
    align-items: center;
    text-align: center;
  }
  .wt-steps .wt-scene {
    width: 140px; height: 140px;
  }
  .wt-steps .wt-scene .wt-scene-main { width: 60px; height: 60px; }
  .wt-steps .wt-scene .wt-scene-accent { width: 28px; height: 28px; }
  .wt-shot { width: 100%; max-width: 440px; }
  .wt-step-hero .wt-shot-carousel { width: 100%; max-width: 440px; }
  .wt-step p { max-width: none; }}

/* ---- Install page (/install/) --------------------------------------- */
/* Platform tabs reuse .rec-tabs from the recording page. The steps themselves
   reuse the walkthrough's .wt-step / .wt-shot / .wt-step-num rhythm, including
   its 720px stacking breakpoint, so there is no second step pattern to keep in
   sync. Left-aligned like the walkthrough rather than a centred column. */

.inst-head { max-width: 60ch; margin: 0 0 var(--space-6); }
.inst-head h1 {
  font-family: var(--font-display); font-weight: 700; font-size: var(--text-2xl);
  letter-spacing: -0.02em; line-height: 1.15; margin: 0 0 var(--space-3);
  color: var(--fg1); text-wrap: balance;
}
.inst-lede { font-size: var(--text-base); color: var(--fg2); line-height: 1.6; margin: 0; }

/* When the page was last checked against real devices. Quiet on purpose: it is
   for the next person maintaining the copy as much as for the reader. */
.inst-stamp {
  font-family: var(--font-body); font-size: var(--text-xs); color: var(--fg3);
  margin: 14px 0 0; display: flex; align-items: center; gap: 7px;
}
.inst-stamp .ic { width: 14px; height: 14px; flex: none; }

/* Centred, which is .rec-tabs' own default and how the recording page shows
   them. The heading above stays left-aligned, matching the walkthrough. */
.inst .rec-tabs { margin-bottom: var(--space-2); }

/* "Written for iOS 26…" note at the top of each platform panel. Centred to sit
   under the tabs it belongs to, and capped so it stays one readable column. */
.inst-version {
  display: flex; align-items: flex-start; gap: 10px;
  max-width: 68ch; margin: 0 auto var(--space-6);
  padding: 12px 16px; border-radius: var(--radius-md);
  background: var(--bg-sunk); border: 1px solid var(--border);
  font-family: var(--font-body); font-size: var(--text-sm);
  color: var(--fg2); line-height: 1.55;
}
.inst-version .ic { width: 16px; height: 16px; flex: none; color: var(--fg3); margin-top: 3px; }

/* Caption under each step mockup. The images depict one version's UI, so this
   stops an authored screenshot reading as a promise about the reader's screen. */
.wt-shot-caption {
  font-family: var(--font-body); font-size: var(--text-xs); color: var(--fg3);
  text-align: center; margin: 10px 0 0;
}

/* Already-installed confirmation. Hidden unless <html data-standalone>, which
   pwa_head.html sets before paint. */
.inst-done { display: none; }
:root[data-standalone] .inst-done {
  display: flex; align-items: center; gap: var(--space-3);
  max-width: 60ch; margin: 0 0 var(--space-5);
  padding: var(--space-4); border-radius: var(--radius-md);
  background: var(--success-bg); border: 1px solid #b7e4cd;
  color: #14764f; font-weight: 600; font-size: var(--text-sm); line-height: 1.5;
}
.inst-done-orb {
  width: 34px; height: 34px; border-radius: var(--radius-pill); flex: none;
  background: #fff; color: var(--success);
  display: grid; place-items: center;
}
.inst-done-orb .ic { width: 18px; height: 18px; }
/* The page and the header pill both stand down inside the installed app. */
:root[data-standalone] .inst,
:root[data-standalone] .header-getapp { display: none; }

/* The CTA's buttons. Wrapping is driven by flex-basis, not a breakpoint: each
   button asks for 240px and grows to fill, so they sit side by side whenever
   both fit and stack to full width the moment they do not. No magic viewport
   number to keep in sync with the button labels. */
.inst-actions {
  display: flex; flex-wrap: wrap; gap: 12px; justify-content: center;
}
.inst-actions .btn { flex: 1 1 240px; }
.inst-prompt .ic { width: 18px; height: 18px; }

/* Below this the card itself has to give way: at 320px its 32px padding left
   only 228px of content, so the label wrapped and stranded its icon on a line
   of its own. `white-space: nowrap` then keeps each label on one line, which
   flex-basis alone cannot guarantee. */
@media (max-width: 440px) {
  .inst .wt-cta { padding: 30px 18px; }
  .inst .wt-cta h2 { font-size: var(--text-lg); }
  .inst-actions .btn {
    flex-basis: 100%; padding-left: 14px; padding-right: 14px;
    font-size: var(--text-base); white-space: nowrap;
  }
  .inst-actions .btn .ic { display: none; }}

/* ---- "Get app" header pill ----------------------------------------- */
.header-getapp {
  display: inline-flex; align-items: center; gap: 7px; flex: none;
  height: 34px; padding: 0 14px; border-radius: var(--radius-pill);
  border: 1px solid var(--blue-200); background: var(--wash-blue);
  color: var(--blue-700); text-decoration: none;
  font-family: var(--font-body); font-weight: 700; font-size: var(--text-sm);
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}
.header-getapp:hover { background: var(--blue-100); color: var(--blue-800); }
.header-getapp .ic { width: 16px; height: 16px; }

@media (max-width: 560px) {
  /* Label goes, icon stays: the header has to hold a logo and an avatar too. */
  .header-getapp { padding: 0; width: 34px; justify-content: center; gap: 0; font-size: 0; }
  .header-getapp .ic { width: 18px; height: 18px; }}