/* ============================================================
   Marzi Memories — design system
   Warm, premium, emotional. Mobile-first.
   ============================================================ */

:root {
  --cream: #faf6f0;
  --ivory: #fffcf7;
  --paper: #f3ece0;
  --ink:   #1f1b17;
  --ink-2: #4a4037;
  --muted: #7d7166;
  --line:  #e7dfd1;
  --accent: #b4692a;      /* warm amber */
  --accent-2: #8a4a1a;
  --rose: #c27d6a;
  --sage: #6d8873;
  --shadow: 0 12px 40px rgba(60, 40, 20, 0.10);
  --shadow-lg: 0 28px 80px rgba(60, 40, 20, 0.18);
  --radius: 14px;
  --radius-lg: 22px;
  --font-sans: "Inter", system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  --font-display: "Fraunces", "Cormorant Garamond", Georgia, serif;
  --container: 1200px;
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; scroll-padding-top: 24px; }
/* Reserve room for the sticky timeline UI (mobile-topbar + filter
   chips + year strip) so anchor jumps land BELOW the sticky stack
   instead of being hidden behind it. Per-breakpoint values match
   the actual heights of the pinned elements. */
@media (max-width: 1100px) { html { scroll-padding-top: 130px; } }
@media (max-width: 900px)  { html { scroll-padding-top: 180px; } }
body {
  margin: 0;
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.6;
  color: var(--ink);
  background: var(--cream);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
img, svg { max-width: 100%; display: block; }
a { color: var(--accent-2); text-decoration: none; }
a:hover { color: var(--ink); }
h1,h2,h3,h4 { font-family: var(--font-display); font-weight: 500; letter-spacing: -0.01em; color: var(--ink); margin: 0 0 0.5em; }
h1 { font-size: clamp(2.25rem, 5vw, 4rem); line-height: 1.05; }
h2 { font-size: clamp(1.75rem, 3.5vw, 2.5rem); line-height: 1.15; }
h3 { font-size: 1.35rem; }
p  { margin: 0 0 1em; color: var(--ink-2); }

.container { max-width: var(--container); margin: 0 auto; padding: 0 1.5rem; }

/* -------- Buttons -------- */
.btn {
  display: inline-flex; align-items: center; gap: 0.5rem;
  padding: 0.85rem 1.6rem;
  border-radius: 999px;
  font-weight: 500;
  font-size: 0.95rem;
  cursor: pointer;
  border: 1px solid transparent;
  transition: transform 0.18s ease, background 0.18s, color 0.18s, box-shadow 0.18s;
  text-decoration: none;
  background: var(--ink); color: var(--ivory);
}
.btn:hover { transform: translateY(-1px); box-shadow: var(--shadow); color: var(--ivory); }
.btn-primary { background: var(--accent); color: white; }
.btn-primary:hover { background: var(--accent-2); color: white; }
.btn-ghost { background: transparent; color: var(--ink); border-color: var(--line); }
.btn-ghost:hover { background: var(--paper); color: var(--ink); }
/* Dark-panel variant — used inside the in-tour note panel and any other
   dark surface where the cream `.btn-ghost:hover` background would clash
   with white-ish text (resulting in invisible text on hover). */
.btn-ghost-dark {
  color: rgba(255, 255, 255, 0.92);
  border-color: rgba(255, 255, 255, 0.3);
}
.btn-ghost-dark:hover {
  background: rgba(255, 255, 255, 0.14);
  color: #ffffff;
  border-color: rgba(255, 255, 255, 0.55);
}
.btn-danger { background: #a0362b; color: white; }
.btn-danger:hover { background: #7c2920; color: white; }
.btn-sm { padding: 0.5rem 0.9rem; font-size: 0.85rem; }
.btn-block { width: 100%; justify-content: center; }

/* -------- Forms -------- */
.field { margin-bottom: 1rem; }
.field label { display: block; font-size: 0.85rem; color: var(--ink-2); margin-bottom: 0.4rem; font-weight: 500; }
.input, .select, .textarea {
  width: 100%;
  padding: 0.75rem 0.9rem;
  font: inherit;
  color: var(--ink);
  background: white;
  border: 1px solid var(--line);
  border-radius: 10px;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.input:focus, .select:focus, .textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 4px rgba(180, 105, 42, 0.15);
}
.textarea { min-height: 120px; resize: vertical; }
.help { font-size: 0.8rem; color: var(--muted); margin-top: 0.3rem; }
.error-text { font-size: 0.8rem; color: #a0362b; margin-top: 0.3rem; }

/* -------- Alerts -------- */
.alert {
  padding: 0.85rem 1.1rem;
  border-radius: 10px;
  margin-bottom: 1rem;
  font-size: 0.92rem;
  border: 1px solid transparent;
}
.alert-success { background: #eaf2ea; color: #2b5733; border-color: #cde0cf; }
.alert-error   { background: #f7e8e5; color: #7c2920; border-color: #e9c5bd; }

/* -------- Cards -------- */
.card {
  background: var(--ivory);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  overflow: hidden;
}

/* Two-column "feature spotlight" section used on the landing page for
   the timeline and people previews. Visual on one side, copy + CTA on
   the other. Reverses on `.reverse` so we can alternate the direction. */
.landing-feature .feature-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4rem;
  align-items: center;
  max-width: 1100px;
  margin: 0 auto;
}
.landing-feature .feature-grid.reverse > .feature-text  { order: 2; }
.landing-feature .feature-grid.reverse > .feature-visual { order: 1; }
@media (max-width: 900px) {
  .landing-feature .feature-grid { grid-template-columns: 1fr; gap: 2.5rem; }
  .landing-feature .feature-grid.reverse > .feature-text,
  .landing-feature .feature-grid.reverse > .feature-visual { order: 0; }
}
.landing-feature .feature-text p {
  font-size: 1.05rem; line-height: 1.7; color: var(--ink-2);
  margin-bottom: 1.5rem;
}

/* Timeline mockup — mimics the look of the in-app timeline so visitors
   immediately recognise the feature when they sign up. */
.feature-visual-timeline {
  background: white;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 2rem;
  box-shadow: var(--shadow-lg);
}
.feature-visual-timeline .tl-pill {
  display: inline-block;
  font-family: var(--font-display);
  background: var(--cream);
  border: 1px solid var(--line);
  padding: 0.35rem 1.1rem;
  border-radius: 999px;
  font-size: 1.1rem;
  color: var(--accent-2);
  margin-bottom: 1.25rem;
  letter-spacing: 0.04em;
}
.feature-visual-timeline .tl-event {
  display: flex; gap: 1rem;
  padding: 1rem 0;
  border-top: 1px solid var(--line);
}
.feature-visual-timeline .tl-event:first-of-type { border-top: none; padding-top: 0; }
.feature-visual-timeline .tl-icon {
  width: 42px; height: 42px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  color: white;
  display: grid; place-items: center;
  flex: none;
  box-shadow: 0 4px 12px rgba(180, 105, 42, 0.35);
}
.feature-visual-timeline .tl-icon svg {
  width: 22px; height: 22px;
  fill: none; stroke: white; stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
}
.feature-visual-timeline .tl-body strong {
  display: block; font-family: var(--font-display); font-size: 1.05rem;
  color: var(--ink); margin-bottom: 0.15rem;
}
.feature-visual-timeline .tl-body span {
  display: block; font-size: 0.72rem; color: var(--accent);
  letter-spacing: 0.08em; text-transform: uppercase;
  margin-bottom: 0.35rem;
}
.feature-visual-timeline .tl-body p {
  font-size: 0.88rem; color: var(--ink-2); margin: 0; line-height: 1.5;
}

/* People mockup — a soft 3×2 grid of avatar cards. */
.feature-visual-people .people-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1rem;
}
@media (max-width: 480px) {
  .feature-visual-people .people-grid { grid-template-columns: repeat(2, 1fr); }
}
.feature-visual-people .person {
  text-align: center;
  background: white;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 1.4rem 0.85rem 1rem;
  box-shadow: var(--shadow);
  transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
}
.feature-visual-people .person:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-lg);
  border-color: var(--accent);
}
.feature-visual-people .person-avatar {
  width: 64px; height: 64px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--paper), var(--cream));
  margin: 0 auto 0.75rem;
  border: 2.5px solid white;
  box-shadow: 0 4px 14px rgba(60, 40, 20, 0.18);
  display: grid; place-items: center;
  font-family: var(--font-display);
  font-size: 1.6rem;
  color: var(--accent-2);
  font-weight: 500;
}
.feature-visual-people .person-name {
  font-family: var(--font-display);
  font-size: 1rem;
  color: var(--ink);
  margin-bottom: 0.1rem;
}
.feature-visual-people .person-role {
  font-size: 0.78rem;
  color: var(--muted);
  letter-spacing: 0.02em;
}

/* Embedded virtual-tour demo on the landing page. 16:9 box, rounded,
   shadow that matches the rest of the cards. The iframe inside is the
   normal viewer (which renders fullscreen-within-its-host), so a
   constrained 16:9 frame just gives us a tasteful inline embed. */
.example-demo-frame {
  width: 100%;
  max-width: 1100px;
  margin: 0 auto;
  aspect-ratio: 16 / 9;
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: #1a1512;
  border: 1px solid var(--line);
  box-shadow: var(--shadow-lg);
}
.example-demo-frame iframe {
  width: 100%; height: 100%;
  border: 0; display: block;
}

/* -------- Layout: landing -------- */
.site-header {
  position: sticky; top: 0; z-index: 50;
  backdrop-filter: saturate(150%) blur(12px);
  background: rgba(250, 246, 240, 0.82);
  border-bottom: 1px solid var(--line);
}
.site-header .inner {
  display: flex; align-items: center; justify-content: space-between;
  padding: 1rem 1.5rem; max-width: var(--container); margin: 0 auto;
  gap: 1rem;
}
.site-nav-toggle {
  display: none;
  width: 40px; height: 40px;
  background: transparent; border: 1px solid var(--line);
  border-radius: 8px;
  cursor: pointer;
  padding: 0;
  flex: none;
}
.site-nav-toggle span {
  display: block; width: 18px; height: 2px;
  background: var(--ink); border-radius: 2px;
  margin: 4px auto;
  transition: transform 0.2s ease, opacity 0.2s ease;
}
.site-nav-toggle.is-open span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.site-nav-toggle.is-open span:nth-child(2) { opacity: 0; }
.site-nav-toggle.is-open span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }
@media (max-width: 720px) {
  .site-header .inner { flex-wrap: wrap; }
  .site-nav-toggle { display: block; }
  .nav {
    display: none;
    flex-basis: 100%;
    flex-direction: column;
    align-items: stretch;
    gap: 0.25rem;
    padding-top: 0.5rem;
    border-top: 1px solid var(--line);
    margin-top: 0.5rem;
  }
  .nav.is-open { display: flex; }
  .nav a:not(.btn) { margin-left: 0; padding: 0.6rem 0.4rem; }
  .nav a.btn { margin-left: 0; align-self: flex-start; }
}
.brand { font-family: var(--font-display); font-size: 1.4rem; color: var(--ink); display: inline-flex; align-items: center; }
.brand span { color: var(--accent); }
/* Logo replacement: sized to live comfortably in any navbar (top header
   or sidebar). Object-fit:contain keeps wide and square logos legible
   without forcing the host to upload a specific aspect ratio. */
.brand-logo-img {
  display: block;
  height: 36px;
  width: auto;
  max-width: 220px;
  object-fit: contain;
}
.side .brand-logo-img { height: 38px; max-width: 200px; }
.auth-card .brand-logo-img { height: 42px; max-width: 240px; }
/* Plain text links in the nav. Excludes .btn so the button rules win and
   the button's own background/color combo isn't broken on hover (the
   :hover rule used to flip text color to var(--ink) on a button whose
   background was already var(--ink) → invisible text). */
.nav a:not(.btn) { margin-left: 1.5rem; color: var(--ink-2); font-size: 0.95rem; }
.nav a:not(.btn):hover { color: var(--ink); }
.nav a.btn { margin-left: 1.5rem; }

.hero { position: relative; padding: 6rem 0 4rem; overflow: hidden; }
.hero::before {
  content: ""; position: absolute; inset: 0;
  background: radial-gradient(60% 60% at 50% 0%, rgba(180,105,42,0.12), transparent 60%),
              radial-gradient(40% 40% at 85% 30%, rgba(194,125,106,0.15), transparent 60%);
  pointer-events: none;
}
.hero .wrap { position: relative; display: grid; grid-template-columns: 1.1fr 1fr; gap: 3rem; align-items: center; }
@media (max-width: 900px) { .hero .wrap { grid-template-columns: 1fr; } }
.eyebrow { display: inline-block; font-size: 0.8rem; letter-spacing: 0.15em; text-transform: uppercase; color: var(--accent-2); margin-bottom: 1rem; }
.hero p.lead { font-size: 1.15rem; color: var(--ink-2); max-width: 52ch; }
.hero-visual {
  aspect-ratio: 4/3;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  background:
    linear-gradient(180deg, rgba(31,27,23,0.05), rgba(31,27,23,0.35)),
    url('../img/hero.svg') center/cover no-repeat,
    linear-gradient(135deg, #d8c3a1, #b4692a);
  position: relative;
  overflow: hidden;
  animation: float 9s ease-in-out infinite;
}
.hero-visual::after {
  content: ""; position: absolute; inset: 0;
  background: radial-gradient(circle at 30% 30%, rgba(255,255,255,0.35), transparent 50%);
}
@keyframes float { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-8px); } }

.section { padding: 5rem 0; }
.section-title { text-align: center; margin-bottom: 3rem; }
.section-title .eyebrow { display: block; }

.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.5rem; }
@media (max-width: 900px) { .grid-3 { grid-template-columns: 1fr; } }

.feature {
  padding: 2rem;
  background: var(--ivory);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  transition: transform 0.25s ease, box-shadow 0.25s ease;
}
.feature:hover { transform: translateY(-4px); box-shadow: var(--shadow); }
.feature .n {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; border-radius: 50%;
  background: var(--paper); color: var(--accent-2);
  font-family: var(--font-display); font-size: 1.2rem; margin-bottom: 1rem;
}

.example-card {
  background: var(--ivory);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-lg);
  border: 1px solid var(--line);
}
.example-card .thumb {
  aspect-ratio: 16/9;
  background: linear-gradient(135deg, #b8a389, #6d8873);
  position: relative;
}
.example-card .thumb::after {
  content: "▶"; position: absolute; inset: 0; display: grid; place-items: center;
  font-size: 3rem; color: white; opacity: 0.85; text-shadow: 0 4px 20px rgba(0,0,0,0.35);
}
.example-card .body { padding: 2rem; }

.contact-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 3rem; align-items: start; }
@media (max-width: 900px) { .contact-grid { grid-template-columns: 1fr; } }

.site-footer {
  padding: 3rem 0;
  text-align: center;
  color: var(--muted);
  font-size: 0.9rem;
  border-top: 1px solid var(--line);
  background: var(--ivory);
}

/* -------- Auth pages -------- */
.auth-wrap {
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 2rem 1rem;
  background:
    radial-gradient(60% 60% at 50% 0%, rgba(180,105,42,0.10), transparent 60%),
    linear-gradient(180deg, var(--cream), var(--paper));
}
.auth-card {
  width: 100%; max-width: 440px;
  background: var(--ivory);
  border-radius: var(--radius-lg);
  padding: 2.5rem;
  box-shadow: var(--shadow-lg);
  border: 1px solid var(--line);
}

/* -------- Dashboard shell -------- */
.app-shell {
  min-height: 100vh;
  display: grid;
  grid-template-columns: 260px 1fr;
  background: var(--cream);
}
@media (max-width: 900px) { .app-shell { grid-template-columns: 1fr; } }

.side {
  background: var(--ink);
  color: var(--cream);
  padding: 2rem 1.5rem;
  position: sticky; top: 0;
  height: 100vh;
  overflow-y: auto;
  z-index: 70;
}

/* Mobile drawer behaviour. The .side becomes a fixed-position overlay
   that slides in when the hamburger is tapped. A semi-transparent
   .side-backdrop dims the rest of the page and closes on tap. */
.mobile-topbar { display: none; }
.side-backdrop { display: none; }

@media (max-width: 900px) {
  .app-shell { grid-template-columns: 1fr; padding-top: 56px; }

  .mobile-topbar {
    display: flex; align-items: center; gap: 0.75rem;
    position: fixed; top: 0; left: 0; right: 0;
    height: 56px;
    padding: 0 1rem;
    background: var(--ink);
    color: var(--ivory);
    z-index: 60;
    box-shadow: 0 2px 8px rgba(0,0,0,0.18);
  }
  .mobile-topbar-brand .brand,
  .mobile-topbar-brand .brand a { color: var(--ivory); font-size: 1.15rem; }
  .mobile-topbar-brand .brand span { color: var(--accent); }
  .mobile-topbar-brand .brand-logo-img { height: 28px; max-width: 160px; }

  .mobile-topbar-toggle {
    width: 40px; height: 40px;
    background: transparent; border: 1px solid rgba(255,255,255,0.18);
    border-radius: 8px;
    display: grid; place-items: center;
    cursor: pointer;
    padding: 0;
  }
  .mobile-topbar-toggle span {
    display: block; width: 18px; height: 2px;
    background: var(--ivory); border-radius: 2px;
    margin: 2px 0;
    transition: transform 0.2s ease, opacity 0.2s ease;
  }
  .is-side-open .mobile-topbar-toggle span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
  .is-side-open .mobile-topbar-toggle span:nth-child(2) { opacity: 0; }
  .is-side-open .mobile-topbar-toggle span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

  .side {
    position: fixed; top: 56px; bottom: 0; left: 0;
    width: 280px; max-width: 85vw;
    height: auto;
    transform: translateX(-105%);
    transition: transform 0.25s ease;
    box-shadow: 8px 0 24px rgba(0,0,0,0.3);
  }
  .is-side-open .side { transform: translateX(0); }

  .side-backdrop {
    display: block;
    position: fixed; inset: 56px 0 0 0;
    background: rgba(20, 17, 14, 0.55);
    backdrop-filter: blur(2px);
    opacity: 0; pointer-events: none;
    transition: opacity 0.2s ease;
    z-index: 55;
  }
  .is-side-open .side-backdrop { opacity: 1; pointer-events: auto; }
}
.side .brand { color: var(--cream); margin-bottom: 2rem; display: block; }
.side .brand span { color: var(--accent); }
.side nav a {
  display: block;
  padding: 0.75rem 0.9rem;
  border-radius: 10px;
  color: rgba(250, 246, 240, 0.8);
  margin-bottom: 0.25rem;
  font-size: 0.95rem;
  transition: background 0.15s, color 0.15s;
}
.side nav a:hover, .side nav a.active { background: rgba(255,255,255,0.08); color: var(--ivory); }
.side .sep { height: 1px; background: rgba(255,255,255,0.1); margin: 1rem 0; }
/* Sign-out button. Earlier `all: unset` stripped every style including
   transitions and hover state — the button looked dead and didn't react
   to the cursor. Now styled to match a sidebar nav row with its own
   hover treatment so it feels like part of the nav. */
.side form button {
  display: block;
  width: 100%;
  padding: 0.75rem 0.9rem;
  background: transparent;
  color: rgba(250, 246, 240, 0.8);
  border: 1px solid rgba(255, 255, 255, 0.15);
  border-radius: 10px;
  font: inherit;
  font-size: 0.95rem;
  text-align: center;
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s, transform 0.15s;
}
.side form button:hover {
  background: rgba(255, 255, 255, 0.10);
  color: var(--ivory);
  border-color: rgba(255, 255, 255, 0.30);
}
.side form button:active { transform: translateY(1px); }

.app-main { padding: 2rem 2rem 4rem; min-width: 0; }
@media (max-width: 900px) { .app-main { padding: 1.5rem 1rem 3rem; } }
.app-header {
  display: flex; justify-content: space-between; align-items: center;
  margin-bottom: 2rem; gap: 1rem; flex-wrap: wrap;
}
.app-title { margin: 0; }

/* -------- Tables -------- */
.table { width: 100%; border-collapse: collapse; background: var(--ivory); border-radius: var(--radius); overflow: hidden; border: 1px solid var(--line); }
.table th, .table td { padding: 0.9rem 1rem; text-align: left; font-size: 0.92rem; border-bottom: 1px solid var(--line); }
.table tr:last-child td { border-bottom: none; }
.table th { background: var(--paper); font-weight: 500; color: var(--ink-2); }
.table tr:hover td { background: rgba(180, 105, 42, 0.04); }
/* -------- Family picker (checkbox grid with thumbnails) --------
   Used by the timeline event form (light theme) and the in-tour note
   panel (dark theme). One markup, two looks via .note-panel scoping. */
.family-picker {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
  gap: 0.5rem;
  max-height: 260px;
  overflow-y: auto;
  padding: 0.15rem;
  margin-top: 0.25rem;
}
.family-pick {
  display: flex; align-items: center; gap: 0.65rem;
  padding: 0.5rem 0.7rem;
  background: white;
  border: 1.5px solid var(--line);
  border-radius: 12px;
  cursor: pointer;
  user-select: none;
  transition: background 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
}
.family-pick:hover { border-color: var(--accent); }
.family-pick.is-checked {
  background: rgba(180, 105, 42, 0.08);
  border-color: var(--accent);
  box-shadow: 0 2px 10px rgba(180, 105, 42, 0.12);
}
/* Hide the native checkbox visually but keep it focusable. */
.family-pick input[type="checkbox"] {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0, 0, 0, 0); border: 0;
}
.family-pick-thumb {
  width: 38px; height: 38px;
  border-radius: 50%;
  background: var(--paper);
  background-size: cover;
  background-position: center;
  display: grid; place-items: center;
  flex: none;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 0.95rem;
  color: var(--accent-2);
  border: 1.5px solid rgba(255, 255, 255, 0.7);
  box-shadow: 0 1px 4px rgba(60, 40, 20, 0.12);
}
.family-pick-name {
  flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 0.9rem; color: var(--ink);
}
.family-pick-tick {
  width: 20px; height: 20px;
  border: 1.5px solid var(--line);
  border-radius: 5px;
  display: grid; place-items: center;
  flex: none;
  background: white;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.family-pick.is-checked .family-pick-tick {
  background: var(--accent);
  border-color: var(--accent);
  color: white;
}
.family-pick.is-checked .family-pick-tick::before {
  content: ''; width: 5px; height: 9px;
  border-right: 2px solid white; border-bottom: 2px solid white;
  transform: rotate(45deg) translate(-1px, -1px);
}

/* Dark variant for the in-tour note panel. */
.note-panel .family-picker {
  /* Force a single-column list inside the narrow note panel — auto-fill
     was sometimes squeezing two cramped chips into one row. */
  grid-template-columns: 1fr;
  max-height: 200px;
  gap: 0.4rem;
  padding: 0;
  margin-top: 0.4rem;
}
.note-panel .family-pick { padding: 0.45rem 0.6rem; gap: 0.55rem; }
.note-panel .family-pick-thumb { width: 30px; height: 30px; font-size: 0.85rem; }
.note-panel .family-pick-name  { font-size: 0.88rem; }
.note-panel .family-pick-tick  { width: 18px; height: 18px; }
.note-panel .family-pick {
  background: rgba(255, 255, 255, 0.06);
  border-color: rgba(255, 255, 255, 0.18);
  color: white;
}
.note-panel .family-pick:hover { border-color: var(--accent); background: rgba(255, 255, 255, 0.1); }
.note-panel .family-pick.is-checked {
  background: rgba(180, 105, 42, 0.28);
  border-color: var(--accent);
}
.note-panel .family-pick-name { color: white; }
.note-panel .family-pick-thumb {
  background-color: rgba(255, 255, 255, 0.1);
  color: var(--ivory);
  border-color: rgba(255, 255, 255, 0.2);
}
.note-panel .family-pick-tick {
  background: transparent;
  border-color: rgba(255, 255, 255, 0.4);
}

.badge { display: inline-block; padding: 0.2rem 0.6rem; border-radius: 999px; font-size: 0.75rem; font-weight: 500; }
.badge-success { background: #eaf2ea; color: #2b5733; }
.badge-muted   { background: var(--paper); color: var(--muted); }
.badge-warning { background: #f6e6cf; color: #8a4a1a; letter-spacing: 0.05em; }

/* "Customer accounts only" notice on the login page — sets the
   expectation that there's no self-registration so visitors who can't
   sign in know to contact us instead of hunting for a sign-up link. */
.login-notice {
  background: var(--paper);
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent);
  border-radius: 8px;
  padding: 0.75rem 0.95rem;
  /* Notice sits below the demo button now — give it breathing room
     so the two don't visually fuse. */
  margin: 1.5rem 0 0.25rem;
  font-size: 0.88rem;
  line-height: 1.5;
  color: var(--ink-2);
}
.login-notice strong { color: var(--ink); display: block; margin-bottom: 0.15rem; }
.login-notice a { color: var(--accent-2); font-weight: 500; }

/* "or" divider between the regular login form and the demo button. */
.login-demo-divider {
  display: flex; align-items: center;
  margin: 1.25rem 0;
  color: var(--muted);
  font-size: 0.78rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.login-demo-divider::before,
.login-demo-divider::after {
  content: ''; flex: 1;
  height: 1px;
  background: var(--line);
}
.login-demo-divider span { padding: 0 0.85rem; }

/* Two-line ghost button that auto-fills demo credentials and submits. */
.login-demo-btn {
  flex-direction: column;
  align-items: center;
  padding: 0.85rem 1rem;
  gap: 0.1rem;
  border-style: dashed;
  border-color: rgba(180, 105, 42, 0.4);
}
.login-demo-btn:hover {
  border-style: solid;
  border-color: var(--accent);
  background: rgba(180, 105, 42, 0.08);
  color: var(--ink);
}
.login-demo-btn:disabled { opacity: 0.7; cursor: wait; }
/* Slow attention-grabbing pulse — soft amber halo + a barely-there
   nudge on the title text. Tuned to be inviting, not annoying:
   ~2.6s cycle, eased curve, subtle scale (no jitter). Disabled the
   moment the user clicks it (the JS adds :disabled) and respected
   under prefers-reduced-motion. */
.login-demo-pulse {
  animation: login-demo-pulse 2.6s cubic-bezier(.4,.0,.2,1) infinite;
  position: relative;
}
.login-demo-pulse:hover,
.login-demo-pulse:disabled,
.login-demo-pulse:focus-visible { animation: none; }
.login-demo-pulse .login-demo-btn-title {
  animation: login-demo-title-pulse 2.6s cubic-bezier(.4,.0,.2,1) infinite;
}
.login-demo-pulse:hover .login-demo-btn-title,
.login-demo-pulse:disabled .login-demo-btn-title { animation: none; }

@keyframes login-demo-pulse {
  0%, 100% {
    box-shadow: 0 0 0 0 rgba(180, 105, 42, 0.0);
    border-color: rgba(180, 105, 42, 0.4);
  }
  50% {
    box-shadow: 0 0 0 6px rgba(180, 105, 42, 0.12),
                0 4px 16px rgba(180, 105, 42, 0.18);
    border-color: rgba(180, 105, 42, 0.85);
  }
}
@keyframes login-demo-title-pulse {
  0%, 100% { color: var(--accent-2); }
  50%      { color: var(--accent); }
}
@media (prefers-reduced-motion: reduce) {
  .login-demo-pulse,
  .login-demo-pulse .login-demo-btn-title { animation: none; }
}

.login-demo-btn-title {
  font-weight: 500;
  color: var(--accent-2);
}
.login-demo-btn-sub {
  font-size: 0.75rem;
  color: var(--muted);
  letter-spacing: 0.04em;
}

/* ============================================================
   Legal pages (Terms / Privacy + acceptance flow)
   ============================================================ */
.legal-page { padding: 1rem 0 4rem; }
.legal-doc {
  max-width: 760px;
  margin: 0 auto;
  background: white;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 3rem 3rem 2.5rem;
  box-shadow: var(--shadow);
}
@media (max-width: 720px) { .legal-doc { padding: 2rem 1.5rem; } }
.legal-doc-title {
  font-family: var(--font-display);
  font-size: 2.2rem;
  margin: 0 0 0.4rem;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.legal-doc-effective {
  margin: 0 0 2rem;
  font-size: 0.78rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
  font-weight: 600;
}
.legal-doc-body h2 {
  font-family: var(--font-display);
  font-size: 1.3rem;
  color: var(--ink);
  margin: 2rem 0 0.6rem;
  letter-spacing: -0.01em;
}
.legal-doc-body h3 {
  font-family: var(--font-sans);
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-2);
  margin: 1.4rem 0 0.4rem;
}
.legal-doc-body p {
  color: var(--ink-2);
  line-height: 1.7;
  margin: 0 0 1rem;
}
.legal-doc-body ul {
  padding-left: 1.25rem;
  margin: 0 0 1.25rem;
  color: var(--ink-2);
  line-height: 1.6;
}
.legal-doc-body li { margin-bottom: 0.35rem; }
.legal-doc-body strong { color: var(--ink); }

/* Acceptance flow */
.legal-accept {
  max-width: 760px;
  margin: 0 auto;
  padding: 0.5rem 0 4rem;
}
.legal-accept-intro h1 {
  font-size: clamp(1.6rem, 3.5vw, 2.2rem);
  margin: 0 0 0.4rem;
}
.legal-accept-intro p { margin-bottom: 1.5rem; }
.legal-accept-doc {
  background: white;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 0;
  margin-bottom: 1rem;
  box-shadow: var(--shadow);
  overflow: hidden;
}
.legal-accept-doc summary {
  list-style: none;
  cursor: pointer;
  padding: 1.1rem 1.4rem;
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 0.75rem;
  border-bottom: 1px solid transparent;
  transition: background 0.15s ease;
}
.legal-accept-doc summary::-webkit-details-marker { display: none; }
.legal-accept-doc summary::after {
  content: '+';
  font-family: var(--font-display);
  font-size: 1.4rem;
  color: var(--muted);
  margin-left: auto;
  flex: none;
}
.legal-accept-doc[open] summary::after { content: '–'; color: var(--accent); }
.legal-accept-doc[open] summary { border-bottom-color: var(--line); background: var(--cream); }
.legal-accept-doc summary strong {
  font-family: var(--font-display);
  font-size: 1.15rem;
  color: var(--ink);
  font-weight: 500;
}
.legal-accept-date {
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
}
.legal-accept-doc .legal-doc-body {
  max-height: 360px;
  overflow-y: auto;
  padding: 1.5rem 1.75rem;
}
.legal-accept-form { margin-top: 1.5rem; }
.legal-accept-check {
  display: flex; align-items: flex-start; gap: 0.65rem;
  padding: 0.6rem 0;
  cursor: pointer;
  font-size: 0.95rem;
  color: var(--ink-2);
}
.legal-accept-check input[type="checkbox"] {
  margin-top: 0.25rem;
  width: 18px; height: 18px;
  flex: none;
  accent-color: var(--accent);
}
.legal-accept-check a { color: var(--accent-2); text-decoration: underline; }
.legal-accept-form .btn-primary { margin-top: 0.75rem; }

/* Profile legal section */
.profile-legal-row {
  display: flex; align-items: center; justify-content: space-between;
  padding: 0.75rem 0;
  border-top: 1px solid var(--line);
  gap: 0.75rem;
  flex-wrap: wrap;
}
.profile-legal-row:first-of-type { border-top: none; padding-top: 0.5rem; }
.profile-legal-link {
  font-family: var(--font-display);
  color: var(--ink);
  font-size: 1.05rem;
}
.profile-legal-link:hover { color: var(--accent-2); }
.profile-legal-badge {
  display: inline-block;
  margin-left: 0.75rem;
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-weight: 600;
  padding: 0.2rem 0.6rem;
  border-radius: 999px;
}
.profile-legal-badge-ok      { background: #d6ead8; color: #2b5733; }
.profile-legal-badge-pending { background: #fbe8c9; color: #6b3a12; }

/* Footer with legal links */
.site-footer-inner {
  display: flex; justify-content: space-between; align-items: center;
  flex-wrap: wrap;
  gap: 0.5rem;
}
.site-footer-links {
  display: inline-flex; gap: 0.4rem; align-items: center;
  font-size: 0.85rem;
}
.site-footer-links a { color: var(--ink-2); }
.site-footer-links a:hover { color: var(--accent-2); }

/* ============================================================
   Finance dashboard (admin)
   ============================================================ */
.finance-currency-heading {
  font-family: var(--font-display);
  font-size: 1.1rem;
  color: var(--muted);
  letter-spacing: 0.04em;
  margin: 1.25rem 0 0.75rem;
  padding-bottom: 0.4rem;
  border-bottom: 1px solid var(--line);
}
.finance-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 1rem;
  margin-bottom: 0.5rem;
}
.finance-stat {
  background: var(--ivory);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 1.25rem 1.4rem;
  box-shadow: var(--shadow);
  position: relative;
  overflow: hidden;
}
.finance-stat::before {
  content: '';
  position: absolute; top: 0; left: 0;
  width: 4px; height: 100%;
  background: var(--accent);
}
.finance-stat-revenue::before { background: linear-gradient(180deg, #6d8873, #4f6856); }
.finance-stat-month::before   { background: linear-gradient(180deg, var(--accent), var(--accent-2)); }
.finance-stat-pending::before { background: linear-gradient(180deg, #d6863f, #8a4a1a); }
.finance-stat-overdue::before { background: linear-gradient(180deg, #c2604f, #7c2920); }
.finance-stat-label {
  font-size: 0.7rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 600;
  margin-bottom: 0.5rem;
}
.finance-stat-value {
  font-family: var(--font-display);
  font-size: 1.85rem;
  letter-spacing: -0.01em;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
}
.finance-stat-revenue .finance-stat-value { color: #2b5733; }
.finance-stat-overdue .finance-stat-value { color: #7c2920; }
.finance-stat-sub {
  margin-top: 0.35rem;
  font-size: 0.78rem;
  color: var(--muted);
}

/* ============================================================
   Invoices
   ============================================================ */

/* Status pill — used in lists, on the invoice header, and in the
   admin per-user table. Colors map to the warm palette. */
.invoice-status {
  display: inline-block;
  padding: 0.2rem 0.7rem;
  border-radius: 999px;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  border: 1px solid transparent;
}
.invoice-status-draft     { background: var(--paper); color: var(--muted); border-color: var(--line); }
.invoice-status-pending   { background: #fbe8c9; color: #6b3a12; border-color: #e9c98a; }
.invoice-status-paid      { background: #d6ead8; color: #2b5733; border-color: #a8c8ab; }
.invoice-status-unpaid    { background: #f7e0dc; color: #7c2920; border-color: #e9c5bd; }
.invoice-status-overdue   { background: #f3c9c2; color: #5a1a13; border-color: #d4928a; }
.invoice-status-cancelled { background: var(--paper); color: var(--muted); border-color: var(--line); text-decoration: line-through; }

/* Admin form — line-item table + totals block. */
.invoice-form .invoice-items-table {
  width: 100%;
  border-collapse: collapse;
  margin-top: 0.5rem;
}
.invoice-form .invoice-items-table th {
  text-align: left; font-size: 0.78rem;
  letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--muted);
  padding: 0.5rem 0.5rem 0.5rem 0;
  border-bottom: 1px solid var(--line);
}
.invoice-form .invoice-items-table td { padding: 0.4rem 0.5rem 0.4rem 0; vertical-align: middle; }
.invoice-form .invoice-items-table .input { padding: 0.5rem 0.7rem; font-size: 0.92rem; }
.invoice-form .it-remove {
  width: 30px; height: 30px; padding: 0;
  display: grid; place-items: center;
  font-size: 1.1rem; color: var(--error, #a0362b);
}
.invoice-form .it-remove:hover { background: var(--paper); color: var(--ink); }
.invoice-totals {
  margin-top: 1rem;
  border-top: 1px solid var(--line);
  padding-top: 1rem;
  display: flex; flex-direction: column; gap: 0.5rem;
  align-items: flex-end;
  max-width: 480px; margin-left: auto;
}
.invoice-totals-row {
  display: flex; align-items: center; gap: 0.75rem;
  width: 100%; justify-content: space-between;
}
.invoice-totals-grand {
  border-top: 2px solid var(--ink);
  padding-top: 0.5rem;
  font-size: 1.2rem;
  font-family: var(--font-display);
  color: var(--ink);
}

/* ---------------- Printable invoice sheet ---------------- */
.invoice-toolbar {
  display: flex; justify-content: space-between; align-items: center;
  max-width: 880px; margin: 0 auto 1.25rem;
}
.invoice-page {
  display: flex; justify-content: center;
  padding: 1rem 0 4rem;
}
.invoice-sheet {
  background: white;
  width: 100%;
  max-width: 880px;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  padding: 3rem 3.25rem;
  color: var(--ink);
}
.invoice-header {
  display: flex; justify-content: space-between; align-items: flex-start;
  gap: 2rem;
  padding-bottom: 1.5rem;
  border-bottom: 2px solid var(--ink);
  margin-bottom: 2rem;
}
.invoice-brand { display: flex; flex-direction: column; gap: 0.6rem; }
.invoice-logo { max-height: 56px; max-width: 240px; width: auto; display: block; object-fit: contain; }
.invoice-brand-text { font-family: var(--font-display); font-size: 1.6rem; color: var(--ink); }
.invoice-brand-text span { color: var(--accent); }
.invoice-company strong { display: block; font-family: var(--font-display); font-size: 1rem; color: var(--ink); }
.invoice-company span { display: block; font-size: 0.85rem; color: var(--muted); margin-top: 0.1rem; }

.invoice-meta { text-align: right; }
.invoice-title {
  font-size: 0.78rem; letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--muted); margin-bottom: 0.4rem;
}
.invoice-number {
  font-family: var(--font-display);
  font-size: 1.7rem;
  color: var(--ink);
  letter-spacing: -0.01em;
  margin-bottom: 0.6rem;
}
.invoice-meta .invoice-status { font-size: 0.74rem; }

.invoice-parties {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 2rem;
  margin-bottom: 2rem;
}
.invoice-party-label {
  font-size: 0.7rem; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--accent); font-weight: 600; margin-bottom: 0.35rem;
}
.invoice-party-name {
  font-family: var(--font-display);
  font-size: 1.15rem; color: var(--ink);
  margin-bottom: 0.2rem;
}
.invoice-party-line { font-size: 0.92rem; color: var(--ink-2); }
.invoice-dates { display: flex; gap: 2.5rem; text-align: right; }

.invoice-items {
  width: 100%;
  border-collapse: collapse;
  margin-bottom: 1.5rem;
}
.invoice-items th {
  text-align: left;
  font-size: 0.72rem; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--muted); font-weight: 600;
  padding: 0.65rem 0.5rem;
  border-bottom: 1.5px solid var(--ink);
}
.invoice-items th.ii-qty   { text-align: center; width: 80px; }
.invoice-items th.ii-price { text-align: right;  width: 130px; }
.invoice-items th.ii-total { text-align: right;  width: 130px; }
.invoice-items td {
  padding: 0.85rem 0.5rem;
  font-size: 0.95rem;
  color: var(--ink-2);
  border-bottom: 1px solid var(--line);
}
.invoice-items td.ii-qty   { text-align: center; }
.invoice-items td.ii-price { text-align: right; font-variant-numeric: tabular-nums; }
.invoice-items td.ii-total { text-align: right; font-variant-numeric: tabular-nums; color: var(--ink); font-weight: 500; }

.invoice-summary {
  margin-left: auto;
  width: 320px;
  margin-bottom: 2rem;
}
.invoice-summary-row {
  display: flex; justify-content: space-between;
  padding: 0.45rem 0;
  font-size: 0.95rem;
  color: var(--ink-2);
  font-variant-numeric: tabular-nums;
}
.invoice-summary-total {
  border-top: 2px solid var(--ink);
  margin-top: 0.5rem;
  padding-top: 0.7rem;
  font-family: var(--font-display);
  font-size: 1.4rem;
  color: var(--ink);
}

.invoice-notes {
  background: var(--cream);
  border-left: 3px solid var(--accent);
  padding: 1rem 1.25rem;
  border-radius: 0 8px 8px 0;
  margin-bottom: 2rem;
}
.invoice-notes p { margin: 0.25rem 0 0; color: var(--ink-2); white-space: pre-wrap; }

.invoice-footer {
  text-align: center;
  font-size: 0.78rem;
  color: var(--muted);
  padding-top: 1.5rem;
  border-top: 1px solid var(--line);
  margin-top: 2rem;
}

/* Print: hide everything except the invoice sheet, drop borders/shadow,
   white background, no page-margin from the sheet itself. */
@media print {
  @page { size: A4; margin: 16mm; }
  body, html, .app-shell, .app-main, .side, .site-header, .site-footer,
  .app-header, .demo-banner, .alert, .no-print { background: white !important; }
  .side, .site-header, .site-footer, .app-header, .demo-banner, .alert,
  .no-print, .invoice-toolbar { display: none !important; }
  .app-shell { display: block !important; }
  .app-main  { padding: 0 !important; }
  .invoice-page { padding: 0 !important; }
  .invoice-sheet {
    box-shadow: none !important;
    border: none !important;
    border-radius: 0 !important;
    padding: 0 !important;
    max-width: none !important;
  }
}

/* Top-of-page banner shown to demo (read-only) accounts. */
.demo-banner {
  background: linear-gradient(90deg, #fff3df 0%, #fbe8c9 100%);
  color: #6b3a12;
  border: 1px solid #e9c98a;
  border-radius: 10px;
  padding: 0.7rem 1rem;
  margin-bottom: 1rem;
  font-size: 0.9rem;
}
.demo-banner strong { color: var(--accent-2); }

/* -------- Stats -------- */
.stat-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1rem; margin-bottom: 2rem; }
@media (max-width: 900px) { .stat-grid { grid-template-columns: repeat(2, 1fr); } }
.stat { background: var(--ivory); padding: 1.5rem; border-radius: var(--radius); border: 1px solid var(--line); }
.stat .label { font-size: 0.8rem; color: var(--muted); text-transform: uppercase; letter-spacing: 0.08em; }
.stat .value { font-family: var(--font-display); font-size: 2.25rem; color: var(--ink); margin-top: 0.4rem; }

/* -------- Tour grid (user dashboard) -------- */
.tour-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 1.5rem; }
.tour-card-wrap { position: relative; }
.tour-card { display: block; background: var(--ivory); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow); transition: transform 0.2s, box-shadow 0.2s; }
.tour-card:hover { transform: translateY(-4px); box-shadow: var(--shadow-lg); }
.tour-card .cover { aspect-ratio: 16/10; background: linear-gradient(135deg, #d3bfa4, #8a4a1a); background-size: cover; background-position: center; }
.tour-card .body { padding: 1.25rem; }
.tour-card h3 { margin: 0 0 0.3rem; font-size: 1.15rem; }
.tour-card .meta { font-size: 0.85rem; color: var(--muted); }
.tour-card-share {
  position: absolute; top: 0.6rem; right: 0.6rem;
  background: rgba(20, 17, 14, 0.85) !important;
  color: white !important;
  border-color: rgba(255, 255, 255, 0.18) !important;
  backdrop-filter: blur(6px);
}
.tour-card-share:hover {
  background: var(--accent) !important;
  border-color: var(--accent) !important;
}

/* User share-management page */
.share-radio {
  display: flex; align-items: flex-start; gap: 0.7rem;
  padding: 0.75rem 0.85rem;
  border: 1.5px solid var(--line);
  border-radius: 10px;
  margin-bottom: 0.6rem;
  cursor: pointer;
  transition: border-color 0.15s ease, background 0.15s ease;
}
.share-radio:hover { border-color: var(--accent); }
.share-radio input[type="radio"] { margin-top: 0.25rem; flex: none; accent-color: var(--accent); }
.share-radio strong { display: block; font-family: var(--font-display); color: var(--ink); margin-bottom: 0.1rem; }
.share-public-link {
  margin-top: 1rem;
  padding: 0.75rem;
  background: var(--cream);
  border-radius: 8px;
  font-size: 0.85rem;
}
.share-public-link a { display: block; word-break: break-all; color: var(--accent-2); margin-top: 0.25rem; }
.share-card {
  padding: 0.85rem;
  border: 1px solid var(--line);
  border-radius: 10px;
  margin-bottom: 0.75rem;
  background: var(--ivory);
}
.share-card.is-expired { opacity: 0.55; background: var(--paper); }
.share-card-meta { font-size: 0.78rem; color: var(--muted); margin-top: 0.4rem; }

/* Profile two-form layout: auto-flexing cards. */
.profile-form-card { padding: 1.75rem; flex: 1 1 320px; }

/* ============================================================
   Comprehensive responsive sweep (≤720 + ≤480 breakpoints)
   ============================================================ */

/* Auto-wrapped scrollable container for every .table on the page
   (created at runtime by app.js). Lets wide tables scroll horizontally
   without overflowing the viewport, on every page, without each view
   having to remember to wrap its <table> in markup. */
.table-wrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  width: 100%;
}
.table-wrap > .table { min-width: 600px; /* keeps columns readable */ }

/* Tablet / large phone */
@media (max-width: 720px) {
  /* On phone widths convert every .table to a stacked-card view: each
     <tr> renders as a vertical card, every <td> stacks beneath. Header
     row is hidden (no horizontal scrolling, no cramped layout). The
     `data-label` attribute on a <td> renders as a small caption above
     the value; cells without one just show the raw value. */
  .table-wrap, .table-wrap > .table { overflow: visible; }
  .table-wrap { margin: 0; padding: 0; }
  .table-wrap > .table {
    min-width: 0;
    background: transparent;
    border: none;
    border-radius: 0;
  }
  .table-wrap > .table thead { display: none; }
  .table-wrap > .table,
  .table-wrap > .table tbody,
  .table-wrap > .table tr,
  .table-wrap > .table td {
    display: block;
    width: 100%;
  }
  .table-wrap > .table tr {
    background: var(--ivory);
    border: 1px solid var(--line);
    border-radius: 10px;
    padding: 0.9rem 1rem;
    margin-bottom: 0.75rem;
    box-shadow: var(--shadow);
  }
  .table-wrap > .table tr:hover td { background: transparent; }
  .table-wrap > .table td {
    padding: 0.3rem 0 !important;
    border: none !important;
    text-align: left !important;
    white-space: normal;
    font-size: 0.92rem;
  }
  .table-wrap > .table td:empty { display: none; }
  .table-wrap > .table td[data-label]::before {
    content: attr(data-label);
    display: block;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--muted);
    font-weight: 600;
    margin-bottom: 0.15rem;
  }
  /* Action-cell forms / buttons in the last cell stack with breathing room. */
  .table-wrap > .table tr > td:last-child {
    margin-top: 0.5rem;
    padding-top: 0.5rem !important;
    border-top: 1px solid var(--line) !important;
    display: flex; flex-wrap: wrap; gap: 0.4rem; align-items: center;
  }
  .table-wrap > .table tr > td:last-child::before { display: none; }
  .table-wrap > .table tr > td:last-child .btn-sm,
  .table-wrap > .table tr > td:last-child .select { font-size: 0.78rem; padding: 0.35rem 0.6rem; }
  .table-wrap > .table form { display: inline-flex; gap: 0.3rem; align-items: center; }

  /* Page headers — title + actions stack vertically. */
  .app-header {
    flex-direction: column; align-items: stretch;
    gap: 0.75rem;
    margin-bottom: 1.25rem;
  }
  .app-header > * { width: 100%; }
  .app-title { font-size: 1.55rem; line-height: 1.15; }

  /* Cards lose some padding so content has more room. */
  .card { padding: 1.25rem !important; }

  /* Form rows: any `.row` of inputs becomes a single column. !important
     beats inline styles like style="flex:1 1 360px" from existing views. */
  .row { gap: 0.75rem; }
  .row > * { flex: 1 1 100% !important; }

  /* Tour grid — smaller minimum so 1 column fits in 320 px viewports. */
  .tour-grid { gap: 1rem; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); }
  .tour-card .body { padding: 1rem; }
  .tour-card h3 { font-size: 1rem; }
  .tour-card .meta { font-size: 0.78rem; }
  .tour-card-share {
    /* Smaller / less obtrusive on mobile so it doesn't crowd the title. */
    top: 0.4rem; right: 0.4rem;
    padding: 0.35rem 0.65rem;
    font-size: 0.72rem;
  }

  /* Finance KPI grid: 2 across on tablet, 1 on phone (handled below). */
  .finance-stats { grid-template-columns: repeat(2, 1fr); gap: 0.75rem; }
  .finance-stat { padding: 1rem 1.1rem; }
  .finance-stat-value { font-size: 1.4rem; }

  /* Invoice form line-item table: wrap to its own scroll context. */
  .invoice-form .invoice-items-table { font-size: 0.85rem; }

  /* Settings tab strip wraps. */
  .settings-tabs { gap: 0.2rem; }
  .settings-tab  { padding: 0.5rem 0.75rem; font-size: 0.85rem; }

  /* Footer with legal links: stack the two halves. */
  .site-footer-inner { flex-direction: column; text-align: center; gap: 0.4rem; }

  /* Container side padding for content. */
  .app-main { padding: 1.25rem 1rem 2.5rem; }

  /* Share-page two-column layout collapses (both .row > * already 100%). */
  .share-public-link { font-size: 0.78rem; }

  /* Auth card full-width with breathing room. */
  .auth-wrap { padding: 1.5rem 1rem; }
  .auth-card { padding: 1.5rem !important; }

  /* Family-picker chips — single column reads better than cramped 2-up. */
  .family-picker { grid-template-columns: 1fr; max-height: 320px; }

  /* Hero on landing — tighter spacing + smaller buttons row. */
  .hero { padding: 3rem 0 2.5rem; }
  .hero p.lead { font-size: 1rem; }
  .hero .wrap { gap: 1.5rem; }

  /* Section vertical padding tightened. */
  .section { padding: 3rem 0; }
  .landing-feature .feature-grid { gap: 1.75rem; }

  /* Timeline mockup card on landing scrolls in narrow viewports. */
  .feature-visual-timeline { padding: 1.25rem; }
}

/* Small phone */
@media (max-width: 480px) {
  body { font-size: 15px; }
  .app-title { font-size: 1.35rem; }

  /* Single-column tour grid even when card minimum was 240. */
  .tour-grid { grid-template-columns: 1fr; }

  /* Finance KPIs: one per row. */
  .finance-stats { grid-template-columns: 1fr; }

  /* Buttons stretch full width by default for thumb-friendly hits in
     stacked action rows; keep inline buttons that are explicitly small. */
  .btn:not(.btn-sm):not(.btn-icon-only) { width: 100%; justify-content: center; }
  .btn-sm { padding: 0.45rem 0.75rem; font-size: 0.78rem; }

  /* People avatars wrap to 2 columns. */
  .feature-visual-people .people-grid { grid-template-columns: repeat(2, 1fr); gap: 0.6rem; }
  .feature-visual-people .person { padding: 1rem 0.5rem 0.75rem; }

  /* Hero buttons stack vertically and stretch. */
  .hero .btn { width: 100%; justify-content: center; }

  /* Cards even more padding-tight. */
  .card { padding: 1rem !important; }

  /* Hero visual hidden on very small screens — would just be decoration. */
  .hero-visual { display: none; }

  /* Lightbox spacing already tight, keep prev/next hidden (set earlier). */

  /* Note panel padding minimal. */
  .note-panel { padding: 0.85rem !important; }
  .note-edit-section { margin-bottom: 0.85rem; padding-bottom: 0.85rem; }
}

/* -------- Viewer -------- */
html.viewer, body.viewer { height: 100%; overflow: hidden; background: #000; }
.viewer-wrap { position: fixed; inset: 0; background: #000; color: white; font-family: var(--font-sans); }
#pano { position: absolute; inset: 0; background: #111; }
.viewer-top {
  position: absolute; top: 0; left: 0; right: 0;
  display: flex; justify-content: space-between; align-items: center;
  padding: 1rem 1.25rem;
  gap: 0.5rem;
  flex-wrap: wrap;
  background: linear-gradient(180deg, rgba(0,0,0,0.55), transparent);
  z-index: 10;
}
.viewer-top h1 { font-size: 1rem; color: white; margin: 0; font-family: var(--font-sans); font-weight: 500; }
.viewer-top .meta { font-size: 0.8rem; color: rgba(255,255,255,0.7); }
.viewer-btn {
  background: rgba(255,255,255,0.12);
  color: white;
  border: 1px solid rgba(255,255,255,0.2);
  padding: 0.5rem 0.9rem;
  border-radius: 999px;
  font-size: 0.85rem;
  cursor: pointer;
  backdrop-filter: blur(8px);
  transition: background 0.15s;
}
.viewer-btn:hover { background: rgba(255,255,255,0.2); }
/* ---------------- Mobile virtual-tour viewer ----------------
   On phones the side panels (note + settings) become bottom-sheets:
   full-width, slide up from the bottom, take ~80vh max. The pano
   stays visible above so the user keeps spatial context. */
@media (max-width: 600px) {
  /* Top toolbar — let it wrap if many buttons exist. */
  .viewer-top {
    padding: 0.55rem 0.75rem;
    gap: 0.4rem;
  }
  .viewer-top h1 { font-size: 0.92rem; }
  .viewer-top .meta { font-size: 0.7rem; }
  .viewer-btn { padding: 0.4rem 0.7rem; font-size: 0.78rem; }
  .viewer-btn-icon { width: 34px; height: 34px; }

  /* Scene thumbnails — smaller, tighter, easier to swipe. */
  .scene-list { gap: 0.5rem; padding: 0.55rem 0.65rem 0.75rem; }
  .scene-thumb { width: 96px; height: 58px; border-width: 1.5px; }
  .scene-thumb .name { font-size: 0.62rem; padding: 0.18rem 0.35rem; letter-spacing: 0; }
  .scene-thumb.active { transform: translateY(-2px); }

  /* Hotspot tooltips — give the title room and shift slightly closer. */
  .hotspot-tip { font-size: 0.78rem; max-width: 60vw; }

  /* Note panel → bottom sheet. Overrides the desktop right-side rules. */
  .note-panel {
    top: auto !important;
    right: 0 !important;
    left: 0 !important;
    bottom: 0 !important;
    width: 100% !important;
    max-width: none !important;
    max-height: 82vh;
    height: 82vh;
    padding: 1rem 1rem 0.75rem !important;
    border-radius: 18px 18px 0 0;
    border-left: none;
    border-right: none;
    border-bottom: none;
    box-shadow: 0 -10px 40px rgba(0, 0, 0, 0.5);
  }
  /* Tiny grabber bar at the top so it reads as a sheet. */
  .note-panel::before {
    content: '';
    display: block;
    width: 36px; height: 4px;
    background: rgba(255, 255, 255, 0.25);
    border-radius: 999px;
    margin: 0 auto 0.6rem;
    flex: none;
  }
  /* Close-X stays in the top-right corner of the sheet. */
  .note-close-x { top: 0.55rem; right: 0.55rem; }

  /* Settings panel → also a bottom sheet, slides up from the bottom
     instead of in from the left. Keep .is-open as the toggle so the
     existing JS still works. */
  .viewer-settings {
    top: auto !important;
    right: 0 !important;
    left: 0 !important;
    bottom: 0 !important;
    width: 100% !important;
    max-width: none !important;
    max-height: 82vh;
    height: 82vh;
    border-radius: 18px 18px 0 0;
    transform: translateY(105%);
    box-shadow: 0 -10px 40px rgba(0, 0, 0, 0.5);
  }
  .viewer-settings.is-open { transform: translateY(0); }
  .viewer-settings::before {
    content: '';
    display: block;
    width: 36px; height: 4px;
    background: rgba(255, 255, 255, 0.25);
    border-radius: 999px;
    margin: 0.5rem auto;
    flex: none;
  }
}

.scene-list {
  position: absolute; bottom: 0; left: 0; right: 0;
  display: flex; gap: 0.75rem; padding: 1rem 1.25rem;
  overflow-x: auto; z-index: 10;
  background: linear-gradient(0deg, rgba(0,0,0,0.65), transparent);
  scroll-behavior: smooth;
}
.scene-thumb {
  flex: 0 0 auto;
  width: 140px; height: 80px; border-radius: 10px;
  background-size: cover; background-position: center;
  border: 2px solid transparent;
  cursor: pointer;
  transition: transform 0.15s, border-color 0.15s;
  position: relative; overflow: hidden;
}
.scene-thumb.active { border-color: var(--accent); transform: translateY(-4px); }
.scene-thumb .name { position: absolute; bottom: 0; left: 0; right: 0; padding: 0.3rem 0.5rem; font-size: 0.75rem; background: linear-gradient(0deg, rgba(0,0,0,0.7), transparent); }

/* ----------------------------------------------------------------
 * Hotspot positioning.
 *
 * Marzipano writes `transform: translateX(x) translateY(y) translateZ(0) <extra>`
 * onto the hotspot element every frame. We pass `translate(-50%, -50%)` as
 * `extraTransforms` when creating the hotspot, so the icon ends up centered
 * on (x, y) with no wrapper element. Don't set `transform` on `.hotspot` or
 * `.hotspot-link` from CSS — Marzipano overwrites it. Use color, background,
 * border, and box-shadow for hover/active feedback instead of scale.
 * ---------------------------------------------------------------- */
.hotspot {
  width: 32px; height: 32px;
  border-radius: 50%;
  background:
    radial-gradient(circle at 30% 30%, #e08a4f 0%, #c47736 38%, #8a4a1a 100%);
  border: 2.5px solid #fffcf7;
  box-shadow:
    0 6px 18px rgba(20, 17, 14, 0.55),
    0 1px 0 rgba(255, 255, 255, 0.45) inset,
    0 -2px 6px rgba(60, 30, 5, 0.35) inset;
  cursor: pointer;
  display: grid; place-items: center;
  color: white;
  /* Marzipano writes the transform to position us; do NOT animate transform
     here — the box-shadow halo and pseudo-element rings carry the motion. */
  transition: background 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
}
/* Two concentric pulsing rings — the second is offset by half the cycle
   so the effect feels continuous instead of a single throb. */
.hotspot::before,
.hotspot::after {
  content: '';
  position: absolute;
  inset: -10px;
  border-radius: 50%;
  border: 2px solid rgba(180, 105, 42, 0.55);
  pointer-events: none;
  animation: hotspot-ring 2.6s cubic-bezier(.2,.7,.3,1) infinite;
  opacity: 0;
}
.hotspot::after {
  inset: -14px;
  border-color: rgba(180, 105, 42, 0.35);
  animation-delay: 1.3s;
}
@keyframes hotspot-ring {
  0%   { opacity: 0;   transform: scale(0.6); }
  20%  { opacity: 0.9; }
  100% { opacity: 0;   transform: scale(1.9); }
}
.hotspot:hover {
  background:
    radial-gradient(circle at 30% 30%, #f3a468 0%, #d6863f 38%, #9a5520 100%);
  border-color: #fffcf7;
  box-shadow:
    0 10px 28px rgba(180, 105, 42, 0.55),
    0 0 0 10px rgba(180, 105, 42, 0.18),
    0 1px 0 rgba(255, 255, 255, 0.55) inset,
    0 -2px 6px rgba(60, 30, 5, 0.35) inset;
}
/* SVG centering: same absolute + translate(-50%, -50%) trick as
   `.hotspot-link svg` below. Flex/grid `place-items:center` only
   centers the SVG's BOUNDING BOX — but the EVENT icon set has paths
   with asymmetric bboxes (sparkle, paw, sun, etc.), so the visual
   content drifted upward inside the bubble. Absolute centering with
   margin:0/padding:0 is the only method that survives Marzipano's
   per-frame transform AND every icon's individual path geometry. */
.hotspot svg {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: 14px; height: 14px;
  margin: 0; padding: 0;
  stroke: white; fill: white; stroke-width: 2;
  stroke-linecap: round; stroke-linejoin: round;
  filter: drop-shadow(0 1px 1px rgba(0,0,0,.45));
}
/* Curated picker icon variant — line-style render so multi-path
   icons (sparkle / sun / paw) don't blob-fill with white. */
.hotspot.has-icon svg {
  width: 18px; height: 18px;
  stroke: white; fill: none; stroke-width: 1.8;
}

/* Tooltip shown when the user hovers a note hotspot — surfaces the
   note's title without making them click. Hidden when the title is
   empty (we just don't render the element). */
.hotspot-tip {
  position: absolute;
  bottom: calc(100% + 14px);
  left: 50%;
  transform: translateX(-50%);
  background: rgba(20, 17, 14, 0.95);
  color: white;
  padding: 0.4rem 0.75rem;
  border-radius: 8px;
  font-size: 0.82rem;
  font-weight: 500;
  white-space: nowrap;
  max-width: 220px;
  overflow: hidden;
  text-overflow: ellipsis;
  border: 1px solid rgba(255, 255, 255, 0.1);
  box-shadow: 0 8px 22px rgba(0, 0, 0, 0.45);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.18s ease, transform 0.18s ease;
  z-index: 5;
}
.hotspot-tip::after {
  content: '';
  position: absolute;
  top: 100%; left: 50%;
  transform: translateX(-50%);
  border: 6px solid transparent;
  border-top-color: rgba(20, 17, 14, 0.95);
}
.hotspot:hover .hotspot-tip {
  opacity: 1;
  transform: translateX(-50%) translateY(-2px);
}
@keyframes pulse {
  0%   { box-shadow: 0 4px 14px rgba(0,0,0,0.45), 0 0 0 0 rgba(180, 105, 42, 0.55); }
  70%  { box-shadow: 0 4px 14px rgba(0,0,0,0.45), 0 0 0 14px rgba(180, 105, 42, 0); }
  100% { box-shadow: 0 4px 14px rgba(0,0,0,0.45), 0 0 0 0 rgba(180, 105, 42, 0); }
}

/* ---------------- Viewer settings panel ---------------- */
/* Gear button lives in .viewer-top alongside Add note / Close as a
   .viewer-btn.viewer-btn-icon. The slide-in panel anchors to the
   LEFT side of the viewer (right side is reserved for the note panel). */
.viewer-btn-icon {
  width: 38px; height: 38px;
  padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
}
.viewer-btn-icon svg {
  width: 18px; height: 18px;
  stroke: white; fill: none; stroke-width: 1.8;
  stroke-linecap: round; stroke-linejoin: round;
  transition: transform 0.25s ease;
}
.viewer-btn-icon.is-open {
  background: var(--accent);
  border-color: var(--accent);
}
.viewer-btn-icon.is-open svg { transform: rotate(60deg); }

.viewer-settings {
  position: absolute; top: 4.5rem; left: 1rem; bottom: 6.5rem;
  width: 300px; max-width: calc(100vw - 2rem);
  background: rgba(20, 17, 14, 0.92);
  color: white;
  border-radius: 16px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  box-shadow: 0 30px 60px rgba(0, 0, 0, 0.55);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  z-index: 25;
  display: flex; flex-direction: column;
  overflow: hidden;
  transform: translateX(calc(-100% - 2rem));
  opacity: 0;
  pointer-events: none;
  transition: transform 0.28s ease, opacity 0.2s ease;
}
.viewer-settings.is-open {
  transform: translateX(0);
  opacity: 1;
  pointer-events: auto;
}
.viewer-settings .vs-section {
  padding: 1rem 1.1rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
.viewer-settings .vs-section:last-child { border-bottom: none; flex: 1 1 0; min-height: 0; display: flex; flex-direction: column; }
.viewer-settings h4 {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: 0.88rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.55);
  margin: 0 0 0.65rem;
}

/* iOS-style toggle row */
.vs-toggle {
  display: flex; align-items: center; justify-content: space-between;
  gap: 0.75rem;
  padding: 0.55rem 0.6rem;
  border-radius: 8px;
  cursor: pointer;
  font-size: 0.92rem;
  color: rgba(255, 255, 255, 0.92);
  user-select: none;
  transition: background 0.15s;
}
.vs-toggle:hover { background: rgba(255, 255, 255, 0.06); }
.vs-toggle input[type="checkbox"] {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); border: 0;
}
.vs-switch {
  width: 38px; height: 22px;
  background: rgba(255, 255, 255, 0.22);
  border-radius: 999px;
  position: relative;
  flex: none;
  transition: background 0.2s ease;
}
.vs-switch::after {
  content: '';
  position: absolute;
  top: 3px; left: 3px;
  width: 16px; height: 16px;
  background: white;
  border-radius: 50%;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
  transition: transform 0.2s ease;
}
.vs-toggle input:checked ~ .vs-switch { background: var(--accent); }
.vs-toggle input:checked ~ .vs-switch::after { transform: translateX(16px); }
.vs-toggle input:focus-visible ~ .vs-switch {
  box-shadow: 0 0 0 3px rgba(180, 105, 42, 0.35);
}

/* Hotspot list */
.vs-hotspot-list {
  list-style: none; padding: 0; margin: 0;
  overflow-y: auto;
  flex: 1 1 0;
  min-height: 0;
}
.vs-hotspot-list li { margin: 0; }
.vs-hotspot-list .vs-hotspot-btn {
  display: flex; align-items: center; gap: 0.7rem;
  width: 100%;
  background: transparent; border: none; color: white;
  text-align: left;
  padding: 0.65rem 0.7rem;
  font: inherit;
  font-size: 0.9rem;
  cursor: pointer;
  border-radius: 8px;
  transition: background 0.15s ease;
}
.vs-hotspot-list .vs-hotspot-btn:hover {
  background: rgba(255, 255, 255, 0.08);
}
.vs-hotspot-list .vs-hotspot-dot {
  width: 12px; height: 12px;
  border-radius: 50%;
  background: var(--accent);
  flex: none;
  box-shadow: 0 0 0 3px rgba(180, 105, 42, 0.22);
}
/* Icon variant: shown when the note has a chosen hotspot icon. Same
   slot/footprint as .vs-hotspot-dot so the title column doesn't shift. */
.vs-hotspot-list .vs-hotspot-icon {
  width: 18px; height: 18px;
  flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--accent);
}
.vs-hotspot-list .vs-hotspot-icon svg {
  width: 18px; height: 18px;
  fill: none; stroke: currentColor; stroke-width: 1.6;
  stroke-linecap: round; stroke-linejoin: round;
}
.vs-hotspot-list .vs-hotspot-title {
  flex: 1; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.vs-hotspot-list .vs-hotspot-untitled { color: rgba(255, 255, 255, 0.55); font-style: italic; }
.vs-hotspot-empty {
  padding: 1rem 0.5rem;
  color: rgba(255, 255, 255, 0.45);
  font-size: 0.85rem;
  text-align: center;
}

/* Pull the floating Add note button out of the way of the gear when both visible */
.viewer-settings.is-open ~ .viewer-top { /* no-op placeholder for future */ }

/* Hide hotspot layers when toggled off. */
#pano.hide-notes .hotspot { display: none !important; }
#pano.hide-links .hotspot-link { display: none !important; }

.note-panel {
  position: absolute; right: 1.25rem; top: 4.5rem; bottom: 6.5rem;
  width: 340px; max-width: 90vw;
  background: rgba(20, 17, 14, 0.92);
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: var(--radius-lg);
  padding: 1.25rem;
  color: var(--cream);
  display: none; flex-direction: column;
  backdrop-filter: blur(14px);
  z-index: 20;
}
.note-panel.open { display: flex; }

/* Top-right close button — visible in both view and edit modes so the
   user always has a one-tap exit, even when the actions row scrolled
   below the fold. Sits above the scrollable section content. */
.note-close-x {
  position: absolute;
  top: 0.55rem; right: 0.55rem;
  width: 32px; height: 32px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.08);
  color: rgba(255, 255, 255, 0.85);
  border: 1px solid rgba(255, 255, 255, 0.18);
  font-size: 1.3rem; line-height: 1;
  display: grid; place-items: center;
  cursor: pointer;
  z-index: 6;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease, transform 0.15s ease;
}
.note-close-x:hover {
  background: rgba(255, 255, 255, 0.18);
  color: white;
  border-color: rgba(255, 255, 255, 0.4);
}
.note-close-x:active { transform: scale(0.94); }
.note-panel h3 { color: white; font-family: var(--font-display); margin-bottom: 0.5rem; }
.note-panel textarea,
.note-panel input[type="text"],
.note-panel input[type="url"],
.note-panel input[type="date"] {
  width: 100%; background: rgba(255, 255, 255, 0.06);
  color: white; border: 1px solid rgba(255, 255, 255, 0.12);
  padding: 0.55rem 0.75rem; border-radius: 8px;
  font: inherit; margin: 0;
  transition: border-color 0.15s ease, background 0.15s ease;
}
.note-panel textarea:focus,
.note-panel input[type="text"]:focus,
.note-panel input[type="url"]:focus,
.note-panel input[type="date"]:focus {
  outline: none;
  border-color: var(--accent);
  background: rgba(255, 255, 255, 0.09);
}
.note-panel textarea { min-height: 120px; resize: vertical; }
.note-panel .actions {
  display: flex; gap: 0.5rem;
  margin-top: 1rem;
  padding-top: 1rem;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  flex: none;
}
.note-panel .btn-sm { flex: 1; justify-content: center; }
.note-panel .note-view,
.note-panel .note-edit {
  display: flex; flex-direction: column;
  flex: 1 1 0; min-height: 0;
  overflow-y: auto;
  padding-right: 0.5rem; /* room for the scrollbar */
  margin-right: -0.5rem;
  /* Slim, theme-friendly scrollbar instead of the chunky OS default. */
  scrollbar-width: thin;
  scrollbar-color: rgba(255, 255, 255, 0.22) transparent;
}
.note-panel .note-view::-webkit-scrollbar,
.note-panel .note-edit::-webkit-scrollbar { width: 6px; }
.note-panel .note-view::-webkit-scrollbar-track,
.note-panel .note-edit::-webkit-scrollbar-track { background: transparent; }
.note-panel .note-view::-webkit-scrollbar-thumb,
.note-panel .note-edit::-webkit-scrollbar-thumb {
  background: rgba(255, 255, 255, 0.22);
  border-radius: 999px;
}
.note-panel .note-view::-webkit-scrollbar-thumb:hover,
.note-panel .note-edit::-webkit-scrollbar-thumb:hover {
  background: rgba(180, 105, 42, 0.55);
}
.note-panel .note-view[hidden],
.note-panel .note-edit[hidden] {
  display: none;
}

/* ---- Edit-mode form layout ---- */
.note-edit-heading {
  margin: 0 0 1rem;
  padding-bottom: 0.85rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.10);
  font-size: 1.3rem;
  letter-spacing: -0.01em;
}
.note-edit-section {
  margin-bottom: 1.1rem;
  padding-bottom: 1.1rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
.note-edit-section:last-of-type {
  border-bottom: none;
  margin-bottom: 0.5rem;
  padding-bottom: 0;
}
.note-edit-section-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 0.6rem; margin-bottom: 0.55rem;
}
.note-edit-label {
  display: block;
  margin: 0 0 0.4rem;
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
  font-weight: 600;
}
.note-edit-required { color: rgba(255, 255, 255, 0.45); margin-left: 0.15rem; font-weight: 400; }
.note-edit-optional {
  color: rgba(255, 255, 255, 0.45);
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
  margin-left: 0.3rem;
  font-size: 0.72rem;
}
.note-edit-section-hint {
  font-size: 0.7rem;
  color: rgba(255, 255, 255, 0.45);
  letter-spacing: 0.02em;
}
.note-edit-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.5fr);
  gap: 0.6rem;
}
.note-edit-field { display: flex; flex-direction: column; min-width: 0; }

/* Custom file picker — hides the ugly native input behind a styled label */
.note-edit-file-pick {
  position: relative;
  display: inline-flex; align-items: center; gap: 0.55rem;
  padding: 0.55rem 0.95rem;
  background: rgba(255, 255, 255, 0.05);
  color: rgba(255, 255, 255, 0.92);
  border: 1px dashed rgba(255, 255, 255, 0.28);
  border-radius: 8px;
  font-size: 0.85rem;
  cursor: pointer;
  margin-top: 0.5rem;
  transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.note-edit-file-pick:hover {
  background: rgba(180, 105, 42, 0.16);
  border-color: var(--accent);
  color: white;
}
.note-edit-file-pick input[type="file"] {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0, 0, 0, 0); border: 0;
}
.note-edit-file-icon {
  display: inline-grid; place-items: center;
  width: 22px; height: 22px;
  border-radius: 50%;
  background: var(--accent);
  color: white;
  font-size: 1.1rem; line-height: 0.9; font-weight: 500;
}

/* ---- Read-only view of a note ---- */
.note-view-header {
  display: flex; align-items: center; justify-content: flex-start;
  gap: 0.75rem;
  margin-bottom: 1.1rem;
  padding-bottom: 0.85rem;
  border-bottom: 1px solid rgba(255, 255, 255, 0.10);
}
/* Hotspot icon shown to the left of the title in view mode. Hidden via
   the `hidden` attribute when the note has no icon set. */
.note-view-icon {
  width: 28px; height: 28px;
  flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  color: var(--accent);
}
.note-view-icon svg {
  width: 24px; height: 24px;
  fill: none; stroke: currentColor; stroke-width: 1.6;
  stroke-linecap: round; stroke-linejoin: round;
}
.note-view-title  {
  margin: 0; color: white; font-family: var(--font-display);
  font-size: 1.45rem; line-height: 1.2; letter-spacing: -0.01em;
  flex: 1; min-width: 0;
}
.note-view-title.is-untitled { color: rgba(255, 255, 255, 0.65); font-style: italic; }
.note-view-date   {
  color: var(--accent); font-size: 0.78rem;
  letter-spacing: 0.06em; text-transform: uppercase; font-weight: 500;
  flex: none; white-space: nowrap;
}
.note-view-body   {
  color: rgba(255, 255, 255, 0.92);
  white-space: pre-wrap;
  line-height: 1.65;
  margin: 0 0 1.4rem;
  font-size: 0.95rem;
}
.note-view-body:empty { display: none; }

/* Generic labelled sub-section inside the read-only view. The data-label
   attribute renders as a small amber heading sitting on top of the
   section's top border, so Photos/Tagged/Related link all share one
   consistent visual treatment. JS toggles `[hidden]` on the wrapper
   when the inner content is empty. */
.note-view-section {
  position: relative;
  padding-top: 1.1rem;
  margin-top: 0.25rem;
  margin-bottom: 1rem;
  border-top: 1px solid rgba(255, 255, 255, 0.10);
}
.note-view-section[hidden] { display: none; }
.note-view-section::before {
  content: attr(data-label);
  position: absolute;
  top: -0.6rem; left: 0;
  background: rgba(20, 17, 14, 0.92); /* match .note-panel bg so it interrupts the rule */
  color: var(--accent);
  padding: 0 0.5rem 0 0;
  font-size: 0.72rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: 600;
}

.note-view-photos {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(80px, 1fr));
  gap: 0.4rem;
}
.note-view-photo {
  display: block;
  aspect-ratio: 1;
  border-radius: 10px;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.12);
  background: rgba(255, 255, 255, 0.04);
  cursor: zoom-in;
  padding: 0;
  transition: transform 0.18s ease, border-color 0.18s ease;
}
.note-view-photo:hover { transform: translateY(-1px); border-color: var(--accent); }
.note-view-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Related-link card inside the view (sits inside .note-view-section
   wrapper which carries the "Related link" subheading). */
.note-view-product {
  display: flex; align-items: center; gap: 0.7rem;
  padding: 0.7rem 0.85rem;
  background: rgba(180, 105, 42, 0.16);
  border: 1px solid rgba(180, 105, 42, 0.45);
  border-radius: 10px;
  color: white;
  text-decoration: none;
  transition: background 0.15s ease, border-color 0.15s ease, transform 0.15s ease;
}
.note-view-product:hover {
  background: rgba(180, 105, 42, 0.28);
  border-color: var(--accent);
  transform: translateY(-1px);
  color: white;
}
.note-view-product-meta { display: flex; flex-direction: column; line-height: 1.2; flex: 1; min-width: 0; }
.note-view-product-label { font-size: 0.78rem; color: rgba(255, 255, 255, 0.65); letter-spacing: 0.04em; text-transform: uppercase; }
.note-view-product-host  { font-weight: 500; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.note-view-product-arrow { flex: none; opacity: 0.7; }

/* Family chips inside their .note-view-section wrapper. */
.note-view-family {
  display: flex; flex-wrap: wrap;
  gap: 0.5rem;
}
.note-view-family-chip {
  display: inline-flex; align-items: center; gap: 0.5rem;
  padding: 0.35rem 0.85rem 0.35rem 0.35rem;
  background: rgba(180, 105, 42, 0.18);
  border: 1px solid rgba(180, 105, 42, 0.4);
  border-radius: 999px;
  font-size: 0.88rem;
  color: white;
  transition: background 0.15s ease, border-color 0.15s ease;
}
.note-view-family-chip:hover {
  background: rgba(180, 105, 42, 0.28);
  border-color: var(--accent);
}
.note-view-family-thumb {
  width: 28px; height: 28px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.12);
  background-size: cover;
  background-position: center;
  display: inline-grid; place-items: center;
  font-family: var(--font-display); font-size: 0.85rem; font-weight: 500;
  color: var(--ivory);
  border: 1.5px solid rgba(255, 255, 255, 0.25);
  flex: none;
}

/* ---- Edit-mode photo gallery ---- */
.note-edit-photos {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(70px, 1fr));
  gap: 0.4rem;
  margin-bottom: 0.6rem;
  min-height: 0;
}
.note-edit-photos-empty {
  grid-column: 1 / -1;
  padding: 0.5rem 0;
  font-size: 0.82rem;
  color: rgba(255, 255, 255, 0.5);
  text-align: center;
}
.note-edit-photo {
  position: relative;
  aspect-ratio: 1;
  border-radius: 8px;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.12);
}
.note-edit-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
.note-edit-photo-rm {
  position: absolute; top: 4px; right: 4px;
  width: 22px; height: 22px;
  border: none; border-radius: 50%;
  background: rgba(20, 17, 14, 0.85);
  color: white;
  font-size: 14px; line-height: 1;
  cursor: pointer;
  display: grid; place-items: center;
  transition: background 0.15s ease;
}
.note-edit-photo-rm:hover { background: var(--error, #a0362b); }

/* While a save is uploading, the actions row is hidden and this
   bar takes its place — gives the user clear feedback on a slow
   connection that something is happening, with real progress. */
.note-save-progress {
  margin-top: 1rem;
  padding-top: 1rem;
  border-top: 1px solid rgba(255, 255, 255, 0.08);
  flex: none;
}
.note-save-progress[hidden] { display: none; }
.note-save-progress-label {
  display: flex; align-items: baseline; justify-content: space-between;
  font-size: 0.78rem;
  color: rgba(255, 255, 255, 0.85);
  letter-spacing: 0.04em;
  margin-bottom: 0.5rem;
}
.note-save-progress-label span:last-child {
  color: var(--accent);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.note-save-progress-bar {
  height: 6px;
  background: rgba(255, 255, 255, 0.1);
  border-radius: 999px;
  overflow: hidden;
  position: relative;
}
.note-save-progress-fill {
  height: 100%;
  background: linear-gradient(90deg, var(--accent), #d68748);
  width: 0%;
  border-radius: 999px;
  transition: width 0.2s ease;
  box-shadow: 0 0 12px rgba(180, 105, 42, 0.5);
}
/* Indeterminate pulse when bytes-loaded is unknown (or after upload
   finishes and we're waiting for the server to respond). */
.note-save-progress.is-indeterminate .note-save-progress-fill {
  width: 40%;
  animation: note-save-pulse 1.4s ease-in-out infinite;
}
@keyframes note-save-pulse {
  0%   { transform: translateX(-100%); }
  100% { transform: translateX(250%); }
}

/* ---------------- Photo lightbox ---------------- */
.photo-lightbox {
  position: fixed; inset: 0;
  z-index: 200;
  background: rgba(8, 6, 4, 0.94);
  display: flex; align-items: center; justify-content: center;
  padding: 4rem 5rem;
  animation: lightbox-fade 0.18s ease;
}
.photo-lightbox[hidden] { display: none; }
@keyframes lightbox-fade {
  from { opacity: 0; }
  to   { opacity: 1; }
}
.lightbox-stage {
  display: flex; align-items: center; justify-content: center;
  max-width: 100%; max-height: 100%;
  cursor: zoom-out; /* clicking the backdrop area closes */
}
.lightbox-img {
  max-width: 100%; max-height: 100%;
  object-fit: contain;
  border-radius: 10px;
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.7);
  cursor: default;
  display: block;
}
.lightbox-btn {
  position: absolute;
  background: rgba(255, 255, 255, 0.08);
  color: white;
  border: 1px solid rgba(255, 255, 255, 0.18);
  width: 48px; height: 48px;
  border-radius: 50%;
  display: grid; place-items: center;
  font-size: 1.6rem; line-height: 1;
  cursor: pointer;
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  transition: background 0.15s ease, border-color 0.15s ease, transform 0.15s ease;
}
.lightbox-btn:hover { background: rgba(255, 255, 255, 0.18); border-color: rgba(255, 255, 255, 0.35); }
.lightbox-close { top: 1.25rem; right: 1.25rem; }
.lightbox-prev  { left: 1.25rem;  top: 50%; transform: translateY(-50%); }
.lightbox-next  { right: 1.25rem; top: 50%; transform: translateY(-50%); }
.lightbox-prev:hover { transform: translateY(-50%) translateX(-2px); }
.lightbox-next:hover { transform: translateY(-50%) translateX(2px); }
.lightbox-counter {
  position: absolute;
  bottom: 1.25rem; left: 50%;
  transform: translateX(-50%);
  color: rgba(255, 255, 255, 0.7);
  font-size: 0.85rem;
  letter-spacing: 0.04em;
  background: rgba(20, 17, 14, 0.6);
  padding: 0.3rem 0.75rem;
  border-radius: 999px;
  backdrop-filter: blur(8px);
}
@media (max-width: 600px) {
  .photo-lightbox { padding: 1rem; }
  .lightbox-btn { width: 40px; height: 40px; font-size: 1.4rem; }
  .lightbox-prev, .lightbox-next { display: none; } /* swipe handled by user manually for now */
}

.loading {
  position: absolute; inset: 0; display: grid; place-items: center;
  background: linear-gradient(135deg, #1a1512, #3a2a1e);
  color: var(--cream); font-family: var(--font-display); z-index: 30;
  transition: opacity 0.5s ease;
}
.loading.hide { opacity: 0; pointer-events: none; }
.loading .spinner {
  width: 48px; height: 48px; border-radius: 50%;
  border: 3px solid rgba(255,255,255,0.1);
  border-top-color: var(--accent);
  animation: spin 1s linear infinite;
  margin-bottom: 1rem;
}
@keyframes spin { to { transform: rotate(360deg); } }

/* -------- Utility -------- */
.row { display: flex; gap: 1rem; flex-wrap: wrap; }
.row > * { flex: 1 1 220px; }
.text-muted { color: var(--muted); }
.text-center { text-align: center; }
.mb-0 { margin-bottom: 0 !important; }
.mb-1 { margin-bottom: 0.5rem; }
.mb-2 { margin-bottom: 1rem; }
.mb-3 { margin-bottom: 1.5rem; }
.mt-3 { margin-top: 1.5rem; }
.hide-sm { }
@media (max-width: 720px) { .hide-sm { display: none; } }

/* -------- Reveal on scroll animation -------- */
.reveal { opacity: 0; transform: translateY(24px); transition: opacity 0.8s ease, transform 0.8s ease; }
.reveal.visible { opacity: 1; transform: translateY(0); }

/* ============================================================
   Marzi v2 — Timeline, family, scene links, admin scene editor
   ============================================================ */

.empty-card {
  padding: 3.5rem 2rem; text-align: center;
  background: var(--ivory); border: 1px dashed var(--line);
  border-radius: var(--radius-lg);
}
.empty-card .empty-icon {
  font-family: var(--font-display); font-size: 2.5rem;
  color: var(--accent); margin-bottom: 0.5rem;
}

/* -------- Timeline feed (theme-consistent) -------- */
.timeline-feed {
  position: relative; max-width: 780px;
  padding-left: 0;
  min-width: 0; /* lets the feed shrink inside the grid track */
}
/* Invisible scroll anchor — sits at the natural document position of
   each year section, takes no vertical space, and (critically) is NOT
   position:sticky. Decoupling the anchor target from the visual sticky
   pill below avoids the Chromium "smooth-scroll under-shoot" bug that
   triggers when scrolling UP to a sticky-or-recently-sticky element. */
.timeline-anchor {
  display: block;
  height: 0;
  overflow: hidden;
  visibility: hidden;
}

.timeline-year-row {
  display: flex; justify-content: center; margin: 2.5rem 0 1.25rem;
  position: sticky; top: 0; z-index: 5; padding: 0.25rem 0;
}
/* On screens where the horizontal year strip pins to the top, drop
   the in-feed pill's sticky behaviour — otherwise the two stack and
   the layout looks busy. The strip's IntersectionObserver handles
   "what year am I currently in" anyway. */
@media (max-width: 1100px) {
  .timeline-year-row { position: static; }
}
/* The very first year-row in the feed sits closer to the top — but
   `:first-child` no longer matches because we inject a `.timeline-anchor`
   before each year row. `:first-of-type` matches the first <div>, which
   is the first year-row regardless of the preceding <a> anchors. */
.timeline-feed > .timeline-year-row:first-of-type { margin-top: 0.5rem; }
.timeline-year-pill {
  font-family: var(--font-display); font-size: 1.5rem;
  color: var(--accent-2);
  background: var(--ivory);
  border: 1px solid var(--line);
  padding: 0.35rem 1.5rem; border-radius: 999px;
  box-shadow: var(--shadow);
  letter-spacing: 0.04em;
}

/* -------- Timeline filter bar (Family & Friends chips) --------
   Horizontal scrollable strip; chips stay readable down to ~360px wide.
   Becomes sticky on tablet & mobile so the active filter stays one
   tap away while the user scrolls through years of memories. */
.timeline-filter-bar {
  display: flex; gap: 0.5rem;
  overflow-x: auto;
  padding: 0.5rem 0.1rem 0.6rem;
  margin-bottom: 0.5rem;
  scrollbar-width: thin;
  -webkit-overflow-scrolling: touch;
}
.timeline-filter-bar::-webkit-scrollbar { height: 6px; }
.timeline-filter-bar::-webkit-scrollbar-thumb { background: var(--line); border-radius: 3px; }
@media (max-width: 1100px) {
  .timeline-filter-bar {
    position: sticky; top: 0; z-index: 7;
    background: rgba(250, 246, 240, 0.96);
    backdrop-filter: blur(8px);
    /* Negative side margins so the bar's translucent backdrop bleeds
       to the edges of .app-main. The padding values here MUST match
       .app-main's horizontal padding for the breakpoint (2rem above
       900px, 1rem at/below 900). */
    margin-left: -2rem; margin-right: -2rem;
    padding-left: 2rem; padding-right: 2rem;
  }
}
@media (max-width: 900px) {
  /* Below 900px the fixed mobile-topbar (56px) lives above the page,
     so push the chips down to clear it. .app-main padding also drops
     to 1rem here, so re-tune the bleed margins. */
  .timeline-filter-bar {
    top: 56px;
    margin-left: -1rem; margin-right: -1rem;
    padding-left: 1rem; padding-right: 1rem;
  }
}
.tl-chip {
  display: inline-flex; align-items: center; gap: 0.5rem;
  padding: 0.4rem 0.85rem 0.4rem 0.45rem;
  background: var(--ivory);
  border: 1px solid var(--line);
  border-radius: 999px;
  color: var(--ink);
  font-size: 0.88rem;
  white-space: nowrap;
  transition: border-color 0.15s ease, background 0.15s ease, transform 0.15s ease;
  flex: none;
}
.tl-chip:hover {
  border-color: var(--accent);
  background: white;
  transform: translateY(-1px);
}
.tl-chip.is-active {
  border-color: var(--accent);
  background: var(--accent);
  color: white;
  box-shadow: 0 4px 14px rgba(180, 105, 42, 0.25);
}
.tl-chip-thumb {
  width: 26px; height: 26px;
  border-radius: 50%;
  background-size: cover; background-position: center;
  background-color: var(--paper);
  display: inline-grid; place-items: center;
  flex: none;
  border: 1.5px solid white;
  box-shadow: 0 0 0 1px var(--line);
  font-weight: 600;
  font-size: 0.78rem;
  color: var(--accent-2);
  text-transform: uppercase;
}
.tl-chip.is-active .tl-chip-thumb { box-shadow: 0 0 0 1px rgba(255,255,255,0.6); }
.tl-chip-thumb-all {
  background: linear-gradient(135deg, var(--accent), var(--accent-2));
  color: white;
  font-family: var(--font-display);
  font-size: 1rem;
}
.tl-chip-thumb-initial { color: var(--accent-2); }

/* -------- Timeline layout: feed + sticky year nav --------
   Two-column on desktop (feed grows, year rail fixed-ish), single
   column on tablet/mobile with the year rail collapsing into a
   horizontal sticky strip pinned under the page header. */
.timeline-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 140px;
  gap: 2rem;
  align-items: start;
}
/* Source-order is <aside> then <div.feed> (a11y: navigation first),
   but visually we want the feed wide on the left and the year rail
   narrow on the right — so place them explicitly on desktop. */
.timeline-layout > .timeline-feed  { grid-column: 1; grid-row: 1; }
.timeline-layout > .timeline-years { grid-column: 2; grid-row: 1; }
/* No year navigation (single year or none): collapse to a single
   column so the feed isn't pushed left by an empty right rail. */
.timeline-layout.no-nav { grid-template-columns: minmax(0, 1fr); }
.timeline-years {
  position: sticky;
  top: 1.5rem;
  align-self: start;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: 0.85rem 0.75rem 0.95rem;
  max-height: calc(100vh - 3rem);
  overflow-y: auto;
  scrollbar-width: thin;
}
.timeline-years-label {
  font-size: 0.7rem; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--muted); margin: 0 0 0.5rem 0.35rem;
}
.timeline-years-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 0.15rem; }
.tl-year-link {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 0.5rem;
  padding: 0.45rem 0.6rem;
  border-radius: 8px;
  color: var(--ink-2);
  font-family: var(--font-sans);
  transition: background 0.12s ease, color 0.12s ease;
  cursor: pointer;
}
.tl-year-link:hover { background: var(--ivory); color: var(--ink); }
.tl-year-link.is-on-page { color: var(--ink); }
.tl-year-link.is-off-page .tl-year-num { color: var(--muted); }
.tl-year-link.is-active {
  background: var(--accent);
  color: white;
}
.tl-year-link.is-active .tl-year-count { color: rgba(255,255,255,0.78); }
.tl-year-num { font-family: var(--font-display); font-size: 1.05rem; line-height: 1; }
.tl-year-count {
  font-size: 0.72rem; color: var(--muted);
  font-variant-numeric: tabular-nums;
}

/* Tablet & mobile: drop the right rail, pin the year list as a
   horizontal scrolling strip just under the filter bar.
   Breakpoint is 1100px (not 900) because the persistent 260px sidebar
   eats most of the viewport between 900-1100 — keeping the right rail
   visible there squeezed memory cards into a barely-readable column. */
@media (max-width: 1100px) {
  .timeline-layout {
    grid-template-columns: 1fr;
    gap: 0.5rem;
  }
  /* Reset the desktop placement so children flow in source order
     (year nav first, feed second) instead of overlapping in row 1. */
  .timeline-layout > .timeline-feed,
  .timeline-layout > .timeline-years { grid-column: auto; grid-row: auto; }
  .timeline-years {
    position: sticky;
    /* Pinned just under the sticky filter chip bar (z-index 7); the
       strip itself sits at z-index 6 so the chips overlap it during
       scroll. The `top` value matches the chip bar's bottom edge. */
    top: 60px;
    z-index: 6;
    max-height: none; overflow: hidden;
    padding: 0.5rem 2rem;
    margin-bottom: 0.5rem;
    background: rgba(250, 246, 240, 0.96);
    backdrop-filter: blur(8px);
    /* Same negative-margin trick as the chip bar so the backdrop
       blur extends to the edges of .app-main (padding 2rem above
       the 900 breakpoint). */
    margin-left: -2rem; margin-right: -2rem;
  }
  /* Below 900 the fixed .mobile-topbar (56px) lives above the page,
     pushing the chip bar to top:56 — so the year strip pins to
     56 + ~60 (chip bar height) = 116. .app-main padding also drops
     to 1rem here. */
  @media (max-width: 900px) {
    .timeline-years {
      top: 116px;
      padding: 0.5rem 1rem;
      margin-left: -1rem; margin-right: -1rem;
    }
  }
  .timeline-years-label { display: none; }
  .timeline-years-list {
    flex-direction: row;
    overflow-x: auto;
    gap: 0.3rem;
    -webkit-overflow-scrolling: touch;
  }
  .timeline-years-list::-webkit-scrollbar { display: none; }
  .tl-year-link {
    flex: none;
    flex-direction: row;
    align-items: center;
    padding: 0.4rem 0.75rem;
    border: 1px solid var(--line);
    background: white;
    gap: 0.4rem;
  }
  .tl-year-link.is-active { border-color: var(--accent); }
  .tl-year-num { font-size: 0.95rem; }
}

.memory {
  display: grid; grid-template-columns: 84px minmax(0, 1fr); gap: 1.25rem;
  margin-bottom: 1.75rem; position: relative;
}
@media (max-width: 600px) { .memory { grid-template-columns: 56px minmax(0, 1fr); gap: 0.6rem; } }

.memory-stamp {
  text-align: center; padding-top: 1rem;
  position: relative;
}
.memory-stamp::after {
  content: ""; position: absolute; top: 0.5rem; bottom: -1.75rem;
  left: 50%; width: 2px; background: var(--line); z-index: 0;
}
.memory:last-child .memory-stamp::after { display: none; }
.stamp-day {
  font-family: var(--font-display); font-size: 2.25rem; line-height: 1;
  color: var(--ink); position: relative; z-index: 1;
  background: var(--cream); padding: 0 0.25rem;
}
.stamp-month {
  font-size: 0.7rem; letter-spacing: 0.18em; color: var(--accent-2);
  margin-top: 0.25rem; font-weight: 600;
  background: var(--cream); padding: 0 0.25rem; position: relative; z-index: 1;
}
.stamp-time {
  font-size: 0.75rem; color: var(--muted); margin-top: 0.5rem;
  background: var(--cream); padding: 0 0.25rem; position: relative; z-index: 1;
}

.memory-card {
  background: var(--ivory);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  padding: 1.5rem 1.5rem 1.25rem;
  transition: box-shadow 0.2s ease, transform 0.2s ease;
  /* Without an explicit min-width:0 the card refuses to shrink below
     its longest unbroken word — a single long URL or untaggable title
     blows out the whole timeline grid on narrow viewports. */
  min-width: 0;
  overflow: hidden;
}
.memory-card:hover { box-shadow: var(--shadow-lg); transform: translateY(-2px); }
.memory-card-head {
  display: flex; justify-content: space-between; align-items: flex-start;
  gap: 1rem; margin-bottom: 0.5rem;
  min-width: 0;
}
.memory-card-head h2 {
  font-family: var(--font-display); font-size: 1.45rem;
  margin: 0; color: var(--ink);
  /* Long unbroken words / URLs would otherwise force the card wider
     than the grid track. `anywhere` lets the browser break inside a
     word as a last resort. */
  overflow-wrap: anywhere;
  word-break: break-word;
}
/* The right side of .memory-card-title is a <div> wrapping h2 + date.
   Give it min-width:0 so the h2 inside can actually wrap when the
   icon takes up part of the row. */
.memory-card-title > div { min-width: 0; flex: 1; }
.memory-date {
  font-size: 0.82rem; color: var(--muted); margin-top: 0.1rem;
  letter-spacing: 0.02em;
  overflow-wrap: anywhere;
}
.memory-actions { display: flex; gap: 0.4rem; flex-shrink: 0; }
.memory-actions form { margin: 0; }
.memory-text {
  white-space: pre-wrap; line-height: 1.6; color: var(--ink-2);
  margin: 0.75rem 0 1rem;
  /* pre-wrap preserves whitespace + wraps soft lines but does NOT
     break inside long unbroken strings (URLs, hashes). Add the
     overflow-wrap escape hatch so those don't push the card sideways. */
  overflow-wrap: anywhere;
  word-break: break-word;
}
.memory-grid {
  display: grid; gap: 0.4rem; margin: 0.75rem 0 1rem;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  min-width: 0;
}
.memory-grid.count-1 { grid-template-columns: 1fr; }
.memory-grid.count-2 { grid-template-columns: 1fr 1fr; }
.memory-photo {
  display: block; border-radius: 12px; overflow: hidden;
  aspect-ratio: 1; background: var(--paper);
  position: relative;
}
.memory-photo img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.4s ease; }
.memory-photo:hover img { transform: scale(1.06); }
.memory-photo.more {
  display: grid; place-items: center;
  font-family: var(--font-display); font-size: 1.5rem;
  color: var(--accent-2); background: var(--paper);
}

.memory-footer {
  display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap;
  border-top: 1px solid var(--line); padding-top: 0.75rem; margin-top: 0.5rem;
}
.footer-label {
  font-size: 0.75rem; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--muted); font-weight: 500;
}
.memory-people { display: flex; gap: 0.4rem; flex-wrap: wrap; }
.person-chip {
  display: inline-flex; align-items: center; gap: 0.4rem;
  padding: 0.25rem 0.75rem 0.25rem 0.25rem; border-radius: 999px;
  background: var(--paper); font-size: 0.82rem; color: var(--ink);
  border: 1px solid var(--line);
  transition: border-color 0.15s ease, background 0.15s ease, transform 0.15s ease;
  /* Cap the chip width so a long name truncates instead of pushing
     the card past the timeline column on narrow viewports. */
  max-width: 100%;
  min-width: 0;
}
.person-chip > :last-child:not(img):not(.person-initial) {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  min-width: 0;
}
/* When the chip is also a link (timeline filter shortcut on each
   memory's footer), give it a subtle hover affordance so users know
   it's clickable. */
a.person-chip:hover {
  border-color: var(--accent);
  background: white;
  transform: translateY(-1px);
}
.person-chip img {
  width: 24px; height: 24px; border-radius: 50%; object-fit: cover;
}
.person-chip .person-initial {
  width: 24px; height: 24px; border-radius: 50%;
  display: grid; place-items: center;
  background: var(--accent); color: white;
  font-size: 0.75rem; font-weight: 600;
}

/* -------- Timeline responsive (≤600px) --------
   At narrow widths the existing memory card ran into three problems:
   1. .memory-card-head crammed the title and Edit/Delete buttons onto
      one line and the title squashed into a tiny column.
   2. .memory-grid kept 3 columns even when each thumb was ~60px wide.
   3. .memory-card padding (1.5rem) ate too much of the available width.
   This block fixes all three plus tightens the Family & Friends filter
   bar and the year-nav strip pill sizes for small screens. */
@media (max-width: 600px) {
  .memory-card { padding: 1.1rem 1rem 0.95rem; }
  .memory-card-head {
    flex-direction: column;
    align-items: stretch;
    gap: 0.6rem;
  }
  .memory-actions {
    justify-content: flex-end;
  }
  .memory-card-head h2 { font-size: 1.2rem; }
  .memory-card-title { gap: 0.6rem; }
  .memory-icon { width: 36px; height: 36px; }
  .memory-icon svg { width: 18px; height: 18px; }
  .memory-grid { grid-template-columns: repeat(2, 1fr); }
  .memory-text { font-size: 0.92rem; margin: 0.6rem 0 0.85rem; }
  .stamp-day { font-size: 1.65rem; }

  /* Filter chips: smaller padding, smaller avatar */
  .timeline-filter-bar { padding-bottom: 0.6rem; }
  .tl-chip { padding: 0.35rem 0.7rem 0.35rem 0.4rem; font-size: 0.82rem; }
  .tl-chip-thumb { width: 22px; height: 22px; }

  /* Year nav strip on phones: tighter (vertical only — horizontal
     stays at 1rem to match .app-main padding). */
  .timeline-years { padding: 0.4rem 1rem; }
  .tl-year-link { padding: 0.35rem 0.6rem; }
  .tl-year-num { font-size: 0.88rem; }
  .tl-year-count { font-size: 0.65rem; }

  .pagination {
    flex-direction: column; gap: 0.75rem;
    text-align: center; padding: 1.25rem 0 0.5rem;
  }
  .pagination .page-link { width: 100%; justify-content: center; }
  .pagination .page-info { order: -1; }
}

/* -------- Pagination -------- */
.pagination {
  display: flex; justify-content: space-between; align-items: center;
  gap: 1rem; max-width: 780px;
  margin: 2.5rem 0 1rem; padding: 1rem 0;
  border-top: 1px solid var(--line);
}
.pagination .page-link {
  display: inline-flex; align-items: center;
  padding: 0.6rem 1.25rem; border-radius: 999px;
  background: var(--ivory); color: var(--ink);
  border: 1px solid var(--line); font-size: 0.9rem;
  transition: background 0.15s, color 0.15s;
}
.pagination .page-link:hover { background: var(--accent); color: white; border-color: var(--accent); }
.pagination .page-link.disabled {
  opacity: 0.4; pointer-events: none;
}
.pagination .page-info {
  font-family: var(--font-display); font-size: 0.95rem; color: var(--muted);
}

/* -------- Family / People grid (theme-consistent) -------- */
.people-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 1.5rem;
}
.person-card {
  background: var(--ivory);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  overflow: hidden;
  display: flex; flex-direction: column;
  transition: box-shadow 0.2s ease, transform 0.2s ease;
}
.person-card:hover { box-shadow: var(--shadow-lg); transform: translateY(-3px); }
.person-portrait {
  aspect-ratio: 4/3;
  background-size: cover; background-position: center;
  background-color: var(--paper);
  position: relative;
}
.person-portrait::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(to bottom, transparent 60%, rgba(31,27,23,0.25));
}
.person-portrait.placeholder {
  display: grid; place-items: center;
  background: linear-gradient(135deg, var(--paper), #d8c3a1);
}
.person-portrait.placeholder span {
  font-family: var(--font-display); font-size: 4rem; color: var(--accent-2);
  z-index: 1; position: relative;
}
.person-body { padding: 1.25rem 1.35rem; display: flex; flex-direction: column; gap: 0.35rem; }
.person-name { font-family: var(--font-display); font-size: 1.35rem; margin: 0 0 0.1rem; color: var(--ink); }
.person-relation {
  font-size: 0.78rem; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--accent-2); font-weight: 500;
}
.person-meta { font-size: 0.85rem; color: var(--muted); display: flex; align-items: center; gap: 0.4rem; margin-top: 0.25rem; }
.person-meta .dot { color: var(--accent); }
.person-notes {
  font-size: 0.88rem; color: var(--ink-2); margin: 0.6rem 0 0;
  line-height: 1.5;
}
.person-actions {
  display: flex; gap: 0.4rem; margin-top: 1rem;
  padding-top: 0.85rem; border-top: 1px solid var(--line);
}
.person-actions form { margin: 0; display: inline; }

/* The .avatar style is reused on edit pages; keep it minimal. */
.avatar {
  width: 80px; height: 80px; border-radius: 50%;
  background-size: cover; background-position: center;
  background-color: var(--paper);
  display: grid; place-items: center;
  font-family: var(--font-display); font-size: 1.5rem; color: var(--accent-2);
}
.avatar.lg { width: 140px; height: 140px; font-size: 2.6rem; }

/* -------- Edit-mode photo gallery (timeline + admin) -------- */
.memory-gallery {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
  gap: 0.5rem;
}
.memory-gallery .thumb {
  position: relative; display: block; border-radius: 10px; overflow: hidden;
  aspect-ratio: 1; background: var(--paper);
}
.memory-gallery .thumb img { width: 100%; height: 100%; object-fit: cover; }
.memory-gallery .thumb.existing .rm {
  position: absolute; top: 6px; right: 6px;
  width: 26px; height: 26px; border-radius: 50%;
  border: 0; background: rgba(31,27,23,0.7); color: white;
  font-size: 16px; line-height: 1; cursor: pointer;
}

/* -------- Note panel (viewer) additions -------- */
.note-panel .note-label {
  display: block; color: rgba(255,255,255,0.65); font-size: 0.72rem;
  margin: 0.5rem 0 0.3rem; text-transform: uppercase; letter-spacing: 0.08em;
}
.note-panel .link-select,
.note-panel select {
  width: 100%; background: rgba(255,255,255,0.06); color: white;
  border: 1px solid rgba(255,255,255,0.12); padding: 0.55rem 0.75rem;
  border-radius: 8px; font: inherit; margin-bottom: 0.5rem;
}
.note-panel select option { color: var(--ink); background: white; }
.note-panel .help-dark {
  font-size: 0.72rem; color: rgba(255,255,255,0.5);
  margin: -0.25rem 0 0.5rem;
}

/* -------- Scene-link hotspots (Marzipano linkHotspots) --------
   Same rule as .hotspot above: Marzipano writes the transform every frame,
   so we don't set one here. Centering is handled by the `extraTransforms`
   option passed to createHotspot().

   Designed to feel like a piece of polished glass with a warm core —
   distinguishable from note hotspots (which are solid amber discs) but
   part of the same family. The pulsing ring is much subtler than the
   note ring so navigation feels secondary to the storytelling. */
.hotspot-link {
  /* No grid/flex centering here — the SVG inside is positioned absolutely
     and translate(-50%, -50%) centered. That's the only layout method
     that survives every combination of: Marzipano's transform on .hotspot-link,
     the optional .hotspot-link-label child, the absolute pseudo-element rings,
     and arbitrary SVG path bbox offsets. Flex/grid centering kept drifting
     subtly under certain icons. */
  width: 50px; height: 50px;
  background:
    radial-gradient(circle at 30% 28%, rgba(255, 255, 255, 0.22) 0%, rgba(255, 255, 255, 0.03) 42%),
    radial-gradient(circle at 50% 100%, rgba(180, 105, 42, 0.42) 0%, rgba(20, 17, 14, 0.88) 72%);
  color: white;
  border: 2px solid rgba(255, 252, 247, 0.92);
  border-radius: 50%;
  cursor: pointer;
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  box-shadow:
    0 10px 26px rgba(0, 0, 0, 0.5),
    0 1px 0 rgba(255, 255, 255, 0.4) inset,
    0 -3px 8px rgba(0, 0, 0, 0.35) inset;
  pointer-events: auto;
  transition: background 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
}
.hotspot-link::before,
.hotspot-link::after {
  content: '';
  position: absolute;
  inset: -8px;
  border-radius: 50%;
  border: 1.5px solid rgba(255, 252, 247, 0.32);
  pointer-events: none;
  animation: link-ring 4s cubic-bezier(.2,.7,.3,1) infinite;
  opacity: 0;
}
.hotspot-link::after {
  inset: -14px;
  border-color: rgba(180, 105, 42, 0.28);
  animation-delay: 2s;
}
@keyframes link-ring {
  0%   { transform: scale(0.7); opacity: 0; }
  18%  { opacity: 0.65; }
  100% { transform: scale(1.5); opacity: 0; }
}
.hotspot-link:hover {
  background:
    radial-gradient(circle at 30% 28%, rgba(255, 255, 255, 0.3) 0%, rgba(255, 255, 255, 0.06) 42%),
    radial-gradient(circle at 50% 100%, rgba(180, 105, 42, 0.7) 0%, rgba(20, 17, 14, 0.85) 72%);
  border-color: #fffcf7;
  box-shadow:
    0 14px 34px rgba(180, 105, 42, 0.5),
    0 0 0 10px rgba(180, 105, 42, 0.18),
    0 1px 0 rgba(255, 255, 255, 0.5) inset,
    0 -3px 8px rgba(0, 0, 0, 0.35) inset;
}
.hotspot-link:hover::before { opacity: 1; }
.hotspot-link svg {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);
  width: 24px; height: 24px; display: block;
  margin: 0; padding: 0;
  stroke: rgba(255, 255, 255, 0.95); fill: none;
  stroke-width: 1.7; stroke-linecap: round; stroke-linejoin: round;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.55));
}
.hotspot-link.icon-dot  { width: 18px; height: 18px; }
.hotspot-link.icon-dot svg { width: 8px; height: 8px; fill: white; stroke: none; }
.hotspot-link .hotspot-link-label {
  position: absolute; top: calc(100% + 10px); left: 50%; transform: translateX(-50%);
  background: rgba(20, 17, 14, 0.94); color: white;
  font-size: 0.78rem; letter-spacing: 0.02em; padding: 0.3rem 0.65rem; border-radius: 6px;
  white-space: nowrap; opacity: 0; pointer-events: none; transition: opacity 0.2s;
  border: 1px solid rgba(255,255,255,0.08);
}
.hotspot-link:hover .hotspot-link-label { opacity: 1; }

/* -------- Admin scene editor --------
   The whole page is locked to the viewport height: a flex column whose
   header is auto-height and whose grid (pano + sidebar) flex-fills the
   remainder. Nothing here uses calc(100vh - X) — that approach broke
   whenever the header reflowed (font swap, long titles, alerts), pushing
   the grid past the viewport. With flex, every section gets exactly the
   space the layout has actually allocated. */
.scene-edit-page {
  display: flex; flex-direction: column;
  /* Subtract .app-main padding (top 2rem + bottom 4rem) so we never overflow
     even though .app-shell itself uses min-height. */
  height: calc(100vh - 6rem);
  min-height: 480px;
  gap: 1.25rem;
}
.scene-edit-header { margin-bottom: 0; flex: none; }
.scene-edit-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: 1rem;
  flex: 1 1 0;
  min-height: 0;
}
@media (max-width: 900px) {
  .scene-edit-page { height: auto; min-height: 0; }
  .scene-edit-grid {
    grid-template-columns: 1fr;
    flex: none;
  }
}
.scene-edit-pano-wrap {
  display: flex; flex-direction: column;
  min-width: 0; min-height: 0;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
.scene-edit-sidebar {
  display: flex; flex-direction: column; gap: 1rem;
  min-height: 0;
}
.scene-edit-sidebar-card {
  flex: 1 1 0;
  display: flex; flex-direction: column;
  min-height: 0;
  padding: 1.25rem;
  /* Card already has its own background+border from .card. */
}
.scene-edit-sidebar-title {
  margin: 0 0 0.75rem;
  flex: none;
}
.scene-edit-sidebar-body {
  flex: 1 1 0;
  min-height: 0;
  overflow-y: auto;
  /* Trim the scrollbar gutter so the list breathes against the right edge. */
  margin-right: -0.25rem;
  padding-right: 0.25rem;
}
.scene-edit-sidebar-body .link-list {
  margin: 0; padding: 0;
}
.admin-pano {
  flex: 1 1 0;
  width: 100%;
  min-height: 0;
  background: #111;
  /* Marzipano appends `position: absolute` children here; the container must
     be a positioning context or the stage canvas escapes and covers the
     whole viewport. We don't load marzipano.css from the CDN, so set the
     equivalent of its `.marzipano-viewer` rule ourselves. */
  position: relative;
  overflow: hidden;
}
@media (max-width: 900px) {
  .admin-pano { height: 60vh; min-height: 360px; flex: none; }
}
.admin-pano-bar {
  flex: none;
  padding: 0.85rem 1.1rem;
  border-top: 1px solid var(--line);
  background: var(--ivory);
  font-size: 0.88rem;
}
.link-list { list-style: none; padding: 0; margin: 0; }
.link-list li {
  display: flex; justify-content: space-between; align-items: center;
  gap: 0.75rem; padding: 0.75rem 0;
  border-bottom: 1px solid var(--line);
}
.link-list li:last-child { border-bottom: none; }
.link-title { font-family: var(--font-display); font-size: 1rem; color: var(--ink); }
.link-meta  { font-size: 0.78rem; color: var(--muted); margin-top: 0.15rem; }
.link-list form { margin: 0; }

.place-modal {
  position: fixed; inset: 0; z-index: 100;
  background: rgba(20, 17, 14, 0.55);
  display: grid; place-items: center; padding: 1rem;
}
.place-modal[hidden] { display: none; }
.place-modal-card {
  background: var(--ivory); border-radius: var(--radius-lg);
  padding: 2rem; width: 100%; max-width: 520px;
  max-height: 90vh; overflow-y: auto;
  box-shadow: var(--shadow-lg); border: 1px solid var(--line);
}

/* -------- Visual icon picker (admin scene-link modal) -------- */
.icon-pick-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(56px, 1fr));
  gap: 0.5rem; padding: 0.25rem 0;
}
.icon-pick-btn {
  background: white; border: 1.5px solid var(--line); border-radius: 10px;
  padding: 0.6rem; cursor: pointer; color: var(--ink);
  display: grid; place-items: center;
  transition: border-color 0.15s ease, transform 0.15s ease, background 0.15s ease;
  aspect-ratio: 1;
}
.icon-pick-btn:hover { border-color: var(--accent); transform: translateY(-1px); }
.icon-pick-btn.selected {
  border-color: var(--accent); background: rgba(180, 105, 42, 0.08);
  box-shadow: 0 0 0 2px rgba(180, 105, 42, 0.15);
}
.icon-pick-btn svg {
  width: 22px; height: 22px;
  stroke: var(--ink); fill: none;
  stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round;
}
.icon-pick-btn.selected svg { stroke: var(--accent-2); }

/* -------- Memory event icon picker (timeline form) -------- */
.event-icon-picker {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(88px, 1fr));
  gap: 0.6rem; margin-top: 0.4rem;
}
.event-icon-btn {
  background: var(--ivory); border: 1.5px solid var(--line); border-radius: 12px;
  padding: 0.85rem 0.5rem 0.65rem; cursor: pointer; color: var(--ink);
  display: flex; flex-direction: column; align-items: center; gap: 0.45rem;
  transition: border-color 0.15s ease, transform 0.15s ease, background 0.15s ease;
  font-family: var(--font-sans);
}
.event-icon-btn:hover { border-color: var(--accent); transform: translateY(-2px); }
.event-icon-btn.selected {
  border-color: var(--accent); background: white;
  box-shadow: 0 0 0 2px rgba(180, 105, 42, 0.18), var(--shadow);
}
.event-icon-btn svg {
  width: 26px; height: 26px;
  stroke: var(--ink); fill: none;
  stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round;
}
.event-icon-btn.selected svg { stroke: var(--accent-2); }
.event-icon-label {
  font-size: 0.7rem; color: var(--muted); letter-spacing: 0.02em;
  text-align: center; line-height: 1.2;
}
.event-icon-btn.selected .event-icon-label { color: var(--accent-2); }
.event-icon-none {
  font-family: var(--font-display); font-size: 1.5rem; color: var(--muted);
  width: 26px; height: 26px; display: grid; place-items: center;
}

/* Dark-theme overrides for the icon picker when it's embedded in the
   viewer's note panel. The light-form variant above renders dark ink
   on ivory which is invisible against the panel's near-black backdrop. */
.note-panel .event-icon-picker {
  grid-template-columns: repeat(auto-fill, minmax(72px, 1fr));
  gap: 0.45rem;
  margin-top: 0.35rem;
}
.note-panel .event-icon-btn {
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.12);
  color: rgba(255, 255, 255, 0.85);
  padding: 0.6rem 0.4rem 0.45rem;
  border-radius: 10px;
}
.note-panel .event-icon-btn:hover {
  border-color: var(--accent);
  background: rgba(255, 255, 255, 0.08);
  transform: translateY(-1px);
}
.note-panel .event-icon-btn.selected {
  border-color: var(--accent);
  background: rgba(180, 105, 42, 0.22);
  box-shadow: 0 0 0 2px rgba(180, 105, 42, 0.32);
}
.note-panel .event-icon-btn svg {
  width: 22px; height: 22px;
  stroke: rgba(255, 255, 255, 0.78);
  fill: none;
}
.note-panel .event-icon-btn.selected svg { stroke: var(--accent); }
.note-panel .event-icon-label {
  color: rgba(255, 255, 255, 0.55);
  font-size: 0.65rem;
}
.note-panel .event-icon-btn.selected .event-icon-label { color: var(--accent); }
.note-panel .event-icon-none {
  color: rgba(255, 255, 255, 0.5);
  font-size: 1.2rem;
  width: 22px; height: 22px;
}

/* -------- Memory card icon (timeline) -------- */
.memory-card-title {
  display: flex; align-items: flex-start; gap: 0.85rem;
  flex: 1; min-width: 0;
}
.memory-icon {
  display: grid; place-items: center;
  width: 44px; height: 44px; flex-shrink: 0;
  background: var(--paper); border-radius: 50%;
  border: 1px solid var(--line);
  margin-top: 0.15rem;
}
.memory-icon svg {
  width: 22px; height: 22px;
  stroke: var(--accent-2); fill: none;
  stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round;
}

/* -------- Eyebrow label (page kicker) -------- */
.app-header .eyebrow {
  display: block; font-size: 0.72rem; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--accent-2); margin-bottom: 0.35rem;
}

/* Hero secondary CTA wrapped in a <form> so the demo login can be
   POST + CSRF-protected. Reset the default form margin so it sits
   flush next to the primary <a> button. */
.hero-cta-form { margin: 0; padding: 0; display: inline-flex; }

/* ================================================================
   Promotion banner — full-bleed strip between hero and "How it works".
   Admin-editable via Site settings → Landing → Promotion banner.
   Hidden entirely when `landing.promo.enabled` is off.
   ================================================================ */
.promo-banner {
  position: relative;
  background:
    radial-gradient(circle at 18% 50%, rgba(255, 252, 247, 0.10) 0%, transparent 55%),
    linear-gradient(135deg, var(--accent) 0%, var(--accent-2) 65%, #5e2f0e 100%);
  color: var(--ivory);
  padding: 2.25rem 0;
  overflow: hidden;
  box-shadow: 0 8px 30px rgba(180, 105, 42, 0.25);
}
/* Subtle diagonal sheen — feels promotional without being noisy. */
.promo-banner::before {
  content: "";
  position: absolute; inset: 0;
  background:
    repeating-linear-gradient(
      135deg,
      transparent 0 26px,
      rgba(255, 252, 247, 0.04) 26px 28px
    );
  pointer-events: none;
}
.promo-banner-inner {
  position: relative;
  display: flex; align-items: center; justify-content: space-between;
  gap: 2rem; flex-wrap: wrap;
}

.promo-banner-text {
  flex: 1 1 320px;
  min-width: 0;
}
.promo-banner-eyebrow {
  display: inline-block;
  font-size: 0.72rem; letter-spacing: 0.22em; text-transform: uppercase;
  color: rgba(255, 252, 247, 0.78);
  background: rgba(255, 252, 247, 0.12);
  border: 1px solid rgba(255, 252, 247, 0.22);
  padding: 0.3rem 0.7rem; border-radius: 999px;
  margin-bottom: 0.6rem;
  font-weight: 600;
}
.promo-banner-title {
  font-family: var(--font-display);
  font-size: 1.6rem; line-height: 1.15;
  color: var(--ivory);
  margin: 0 0 0.4rem;
  letter-spacing: -0.01em;
}
.promo-banner-body {
  margin: 0;
  color: rgba(255, 252, 247, 0.88);
  font-size: 0.96rem; line-height: 1.5;
  max-width: 60ch;
}

.promo-banner-action {
  display: flex; align-items: center; gap: 1.25rem;
  flex: 0 1 auto;
}
.promo-banner-price-block {
  display: flex; flex-direction: column;
  align-items: flex-end;
  line-height: 1.05;
}
.promo-banner-price-was {
  font-size: 0.85rem;
  color: rgba(255, 252, 247, 0.65);
  text-decoration: line-through;
  text-decoration-thickness: 1.5px;
  margin-bottom: 0.15rem;
  font-variant-numeric: tabular-nums;
}
.promo-banner-price {
  font-family: var(--font-display);
  font-size: 2.1rem;
  font-weight: 500;
  color: var(--ivory);
  letter-spacing: -0.01em;
  font-variant-numeric: tabular-nums;
}
/* CTA button — light cream pill on the dark amber bg, inverts the
   normal .btn-primary look so it pops against the banner. */
.promo-banner-cta.btn-primary {
  background: var(--ivory);
  color: var(--ink);
  border-color: var(--ivory);
  box-shadow: 0 6px 18px rgba(20, 17, 14, 0.28);
  padding: 0.85rem 1.4rem;
  font-weight: 500;
}
.promo-banner-cta.btn-primary:hover {
  background: white;
  color: var(--ink);
  transform: translateY(-1px);
  box-shadow: 0 10px 26px rgba(20, 17, 14, 0.34);
}

/* Tablet & mobile: stack text over action, keep the price + CTA
   side-by-side until they no longer fit, then drop the CTA below. */
@media (max-width: 820px) {
  .promo-banner { padding: 1.75rem 0; }
  .promo-banner-inner { flex-direction: column; align-items: flex-start; gap: 1.25rem; }
  .promo-banner-action {
    width: 100%;
    justify-content: space-between;
    gap: 1rem;
  }
  .promo-banner-price-block { align-items: flex-start; }
  .promo-banner-title { font-size: 1.4rem; }
}
@media (max-width: 480px) {
  .promo-banner-action {
    flex-direction: column;
    align-items: stretch;
  }
  .promo-banner-price-block {
    flex-direction: row;
    align-items: baseline;
    gap: 0.6rem;
  }
  .promo-banner-price-was { margin-bottom: 0; }
  .promo-banner-cta.btn-primary {
    width: 100%;
    text-align: center;
    justify-content: center;
  }
}

/* ================================================================
   /payment page — Stripe Checkout tier cards.
   Hero block reuses .hero structure with a decorative-only visual.
   ================================================================ */
.hero-payment .hero-visual {
  background:
    radial-gradient(circle at 25% 30%, rgba(180, 105, 42, 0.22), transparent 55%),
    linear-gradient(135deg, rgba(180, 105, 42, 0.12), rgba(20, 17, 14, 0.55)),
    var(--ink);
}

.tier-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 1.5rem;
  max-width: 980px;
  margin: 0 auto;
}
.tier-card {
  background: var(--ivory);
  border: 1px solid var(--line);
  border-radius: 18px;
  padding: 2rem 1.75rem 1.5rem;
  display: flex; flex-direction: column;
  transition: transform 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
}
.tier-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 16px 40px rgba(20, 17, 14, 0.12);
  border-color: var(--accent);
}
.tier-card-head { margin-bottom: 1.25rem; }
.tier-card-name {
  font-family: var(--font-display);
  font-size: 1.35rem; line-height: 1.15;
  color: var(--ink); margin: 0 0 0.4rem;
}
.tier-card-desc {
  margin: 0;
  font-size: 0.9rem; color: var(--ink-2);
  line-height: 1.5;
}
.tier-card-price {
  font-family: var(--font-display);
  font-size: 2.6rem; font-weight: 500;
  color: var(--accent-2); letter-spacing: -0.02em;
  line-height: 1; margin: 0.5rem 0 1.5rem;
  font-variant-numeric: tabular-nums;
}
.tier-card-price-symbol {
  font-size: 1.4rem; vertical-align: top; margin-right: 0.1rem;
  color: var(--accent);
}
/* The Pay button is a plain <a> now (no wrapping form). margin-top:auto
   keeps it pinned to the bottom of the flex-column card regardless of
   how long the tier description above it runs. */
.tier-card-cta {
  margin-top: auto;
  font-size: 1rem;
  padding: 0.85rem 1.25rem;
  letter-spacing: 0.01em;
}
.tier-grid-footnote {
  text-align: center;
  margin: 2rem auto 0;
  max-width: 540px;
  font-size: 0.85rem;
}

/* /payment/success — definition list summary */
.payment-summary {
  display: grid;
  grid-template-columns: 140px 1fr;
  gap: 0.55rem 1.25rem;
  margin: 0;
}
.payment-summary dt { color: var(--muted); font-size: 0.85rem; }
.payment-summary dd { margin: 0; color: var(--ink); }

@media (max-width: 600px) {
  .tier-card { padding: 1.5rem 1.25rem 1.25rem; }
  .tier-card-price { font-size: 2.2rem; margin: 0.4rem 0 1.25rem; }
  .payment-summary { grid-template-columns: 1fr; gap: 0.15rem 0; }
  .payment-summary dt { margin-top: 0.5rem; }
}

/* ================================================================
   Admin → Payments tab — dynamic tier rows
   ================================================================ */
.tier-row {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 1rem;
  margin-bottom: 0.75rem;
}
.tier-row .row { gap: 0.75rem; }
.tier-row .field { margin-bottom: 0.5rem; }
