/* Screen-reader only, visually hidden */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

:root {
  --ink: #1d2430;
  --ink-light: #4a5568;
  --paper: #f4f0e8;
  --paper2: #fbf8f3;
  --white: #ffffff;
  --accent: #c93545;
  --accent-light: #e05a68;
  --accent-bg: rgba(201, 53, 69, 0.08);
  --accent-soft: #fef3f2;
  --accent-border: rgba(201, 53, 69, 0.25);
  /*
   * The accent has two jobs. As TEXT and icons it has to read on the page;
   * as a FILL behind white text (buttons, selected chips) it has to be dark
   * enough for white. One colour cannot do both in dark mode: #e8636f reads
   * well on #1e1e1e, but white on it is 3.3:1. --accent-fill is the button
   * colour (white on it: 5.1:1 here, 4.6:1 in dark).
   */
  --accent-fill: #c93545;
  --text-secondary: #4a5568;
  --gold: #ba9455;
  --gold-light: #d4b87a;
  --gold-bg: rgba(186, 148, 85, 0.1);
  --transport: #2563eb;
  --transport-bg: rgba(37, 99, 235, 0.08);
  --walk: #16a34a;
  --walk-bg: rgba(22, 163, 74, 0.08);
  --food: #d97706;
  --food-bg: rgba(217, 119, 6, 0.08);
  --shopping: #7c3aed;
  --shopping-bg: rgba(124, 58, 237, 0.08);
  --muted: #586069;
  --border: #e8e0d4;
  /*
   * A control's outline: an input, a chip, a toggle track. --border is a
   * divider at 1.3:1, which leaves an unselected chip or an empty field
   * barely visible; this one is 3:1 on the page and on cards.
   */
  --border-strong: #8f8679;
  /*
   * Gold, walk green and food orange are bright enough for icons and
   * fills, but as small TEXT on white they are 2.8 to 3.3:1. These are the
   * text versions, 4.5:1 or better; dark mode keeps the bright ones.
   */
  --gold-text: #7a5c29;
  /* A stop the plan has you at after it shuts, or with minutes to spare. */
  --hours-late: #b42318;
  --hours-late-bg: rgba(180, 35, 24, 0.08);
  --hours-tight: #8a4b06;
  --hours-tight-bg: rgba(217, 119, 6, 0.1);
  /* Text on a gold fill: dark in both themes (gold brightens in dark mode). */
  --on-gold: #1d1a18;
  --walk-text: #15803d;
  --food-text: #b45309;
  --shadow: 0 1px 3px rgba(29,36,48,0.06), 0 1px 2px rgba(29,36,48,0.04);
  --shadow-md: 0 4px 12px rgba(29,36,48,0.08), 0 2px 4px rgba(29,36,48,0.04);
  --shadow-lg: 0 8px 24px rgba(29,36,48,0.1), 0 4px 8px rgba(29,36,48,0.06);
  --radius: 14px;
  --radius-sm: 8px;
  --nav-height: 80px;
  --header-height: 56px;
  /*
   * The strip the phone keeps for itself at the top: the notch, the clock,
   * the signal and battery icons.
   *
   * `index.html` asks for `viewport-fit=cover`, which means the page is drawn
   * edge to edge UNDERNEATH all of that. Left, right and bottom were handled;
   * the top never was, so on a real phone the app's own title and clock were
   * printed on top of the system clock and battery. It looked fine in every
   * desktop browser because there the inset is zero.
   *
   * `--header-total` is what the rest of the layout should reserve: the bar
   * plus whatever the device is claiming above it.
   */
  --safe-top: env(safe-area-inset-top, 0px);
  --header-total: calc(var(--header-height) + var(--safe-top));
  --glass-bg: rgba(255, 255, 255, 0.72);
  --glass-border: rgba(255, 255, 255, 0.2);
  --glass-blur: 16px;

  /* Named easing curves for personality */
  --ease-out-expo: cubic-bezier(0.19, 1, 0.22, 1);
  --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
  --ease-smooth: cubic-bezier(0.4, 0, 0.2, 1);

  /* 8pt Spacing Scale */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --space-8: 64px;

  /* Typography Scale (with line-heights on 8pt grid) */
  --text-xs: 11px;
  --lh-xs: 16px;
  --text-sm: 13px;
  --lh-sm: 16px;
  --text-base: 15px;
  --lh-base: 24px;
  --text-lg: 18px;
  --lh-lg: 24px;
  --text-xl: 22px;
  --lh-xl: 32px;
  --text-2xl: 28px;
  --lh-2xl: 32px;

  /* Semantic Color Tokens */
  --color-text-primary: var(--ink);
  --color-text-secondary: var(--ink-light);
  --color-text-tertiary: var(--muted);
  --color-surface: var(--paper);
  --color-surface-elevated: var(--white);
  --color-border: var(--border);
  --color-border-focus: var(--accent);
  --color-status-error: #ef4444;
  --color-status-error-bg: rgba(239, 68, 68, 0.08);
  --color-status-warning: #d97706;
  --color-status-warning-bg: rgba(217, 119, 6, 0.08);
  --color-status-success: #16a34a;
  --color-status-success-bg: rgba(22, 163, 74, 0.08);
}

/* Dark mode - explicit */
[data-theme="dark"] {
  --ink: #e0e0e0;
  --ink-light: #a0a0a0;
  --paper: #121212;
  --paper2: #1a1a1a;
  --white: #1e1e1e;
  --accent: #e8636f;
  --accent-light: #f0868f;
  --accent-bg: rgba(232, 99, 111, 0.12);
  --accent-fill: #c94a56;
  --accent-soft: #2b1d1f;
  --accent-border: rgba(232, 99, 111, 0.35);
  --text-secondary: #a0a0a0;
  --gold: #d4b87a;
  --gold-light: #c9a654;
  --gold-bg: rgba(212, 184, 122, 0.12);
  --transport: #60a5fa;
  --transport-bg: rgba(96, 165, 250, 0.12);
  --walk: #4ade80;
  --walk-bg: rgba(74, 222, 128, 0.12);
  --food: #fbbf24;
  --food-bg: rgba(251, 191, 36, 0.12);
  --shopping: #a78bfa;
  --shopping-bg: rgba(167, 139, 250, 0.12);
  --muted: #9ca3af;
  --border: rgba(255,255,255,0.08);
  --border-strong: #707070;
  --gold-text: #d4b87a;
  --hours-late: #ff8a80;
  --hours-late-bg: rgba(255, 138, 128, 0.12);
  --hours-tight: #f6c177;
  --hours-tight-bg: rgba(246, 193, 119, 0.12);
  --walk-text: #4ade80;
  --food-text: #fbbf24;
  --shadow: 0 1px 3px rgba(0,0,0,0.3), 0 1px 2px rgba(0,0,0,0.2);
  --shadow-md: 0 4px 12px rgba(0,0,0,0.4), 0 2px 4px rgba(0,0,0,0.2);
  --shadow-lg: 0 8px 24px rgba(0,0,0,0.5), 0 4px 8px rgba(0,0,0,0.3);
  --glass-bg: rgba(18, 18, 18, 0.75);
  --glass-border: rgba(255, 255, 255, 0.06);
  --color-text-primary: var(--ink);
  --color-text-secondary: var(--ink-light);
  --color-text-tertiary: var(--muted);
  --color-surface: var(--paper);
  --color-surface-elevated: var(--white);
  --color-border: var(--border);
  --color-border-focus: var(--accent);
  --color-status-error: #f87171;
  --color-status-error-bg: rgba(248, 113, 113, 0.12);
  --color-status-warning: #fbbf24;
  --color-status-warning-bg: rgba(251, 191, 36, 0.12);
  --color-status-success: #4ade80;
  --color-status-success-bg: rgba(74, 222, 128, 0.12);
}

/* Dark mode - system preference fallback */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --ink: #e0e0e0;
    --ink-light: #a0a0a0;
    --paper: #121212;
    --paper2: #1a1a1a;
    --white: #1e1e1e;
    --accent: #e8636f;
    --accent-light: #f0868f;
    --accent-bg: rgba(232, 99, 111, 0.12);
    --accent-fill: #c94a56;
    --accent-soft: #2b1d1f;
    --accent-border: rgba(232, 99, 111, 0.35);
    --text-secondary: #a0a0a0;
    --gold: #d4b87a;
    --gold-light: #c9a654;
    --gold-bg: rgba(212, 184, 122, 0.12);
    --transport: #60a5fa;
    --transport-bg: rgba(96, 165, 250, 0.12);
    --walk: #4ade80;
    --walk-bg: rgba(74, 222, 128, 0.12);
    --food: #fbbf24;
    --food-bg: rgba(251, 191, 36, 0.12);
    --shopping: #a78bfa;
    --shopping-bg: rgba(167, 139, 250, 0.12);
    --muted: #9ca3af;
    --border: rgba(255,255,255,0.08);
    --border-strong: #707070;
    --gold-text: #d4b87a;
    --hours-late: #ff8a80;
    --hours-late-bg: rgba(255, 138, 128, 0.12);
    --hours-tight: #f6c177;
    --hours-tight-bg: rgba(246, 193, 119, 0.12);
    --walk-text: #4ade80;
    --food-text: #fbbf24;
    --shadow: 0 1px 3px rgba(0,0,0,0.3), 0 1px 2px rgba(0,0,0,0.2);
    --shadow-md: 0 4px 12px rgba(0,0,0,0.4), 0 2px 4px rgba(0,0,0,0.2);
    --shadow-lg: 0 8px 24px rgba(0,0,0,0.5), 0 4px 8px rgba(0,0,0,0.3);
    --glass-bg: rgba(18, 18, 18, 0.75);
    --glass-border: rgba(255, 255, 255, 0.06);
    --color-text-primary: var(--ink);
    --color-text-secondary: var(--ink-light);
    --color-text-tertiary: var(--muted);
    --color-surface: var(--paper);
    --color-surface-elevated: var(--white);
    --color-border: var(--border);
    --color-border-focus: var(--accent);
    --color-status-error: #f87171;
    --color-status-error-bg: rgba(248, 113, 113, 0.12);
    --color-status-warning: #fbbf24;
    --color-status-warning-bg: rgba(251, 191, 36, 0.12);
    --color-status-success: #4ade80;
    --color-status-success-bg: rgba(74, 222, 128, 0.12);
  }
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html, body {
  /* Noto Sans JP was loaded from Google Fonts for every country, including the
     four that do not use Japanese. The system stack renders CJK correctly on
     Android, iOS, macOS and Windows without a network request, which matters
     more in an offline app than a specific typeface does. */
  font-family: system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue',
               'Hiragino Sans', 'Noto Sans CJK JP', 'Malgun Gothic',
               'Microsoft YaHei', sans-serif;
  background: var(--paper);
  color: var(--ink);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  min-height: 100%;
}

/*
 * THE WINDOW SCROLLS, NOT THE BODY.
 *
 * `overflow-x: hidden; height: 100%` on both html and body made <body> a
 * scroll box exactly one screen tall, with the whole app scrolling inside it.
 * Everything that asked the window how far down you were heard 0: the saved
 * position for "back", the scroll-to-top button (never shown), and the pull
 * to refresh, which armed while you were halfway down a page. On html the
 * value goes to the viewport, which is what clips sideways now; `clip` on the
 * body and on each page cuts off a sliding page without making a scroll box.
 */
html { overflow-x: hidden; }
body { overflow-x: clip; }

body {
  padding-top: var(--header-total);
  padding-bottom: calc(var(--nav-height) + env(safe-area-inset-bottom, 0px));
}

/* Grain texture - desktop only for performance */
@media (min-width: 481px) {
  body::after {
    content: '';
    position: fixed;
    top: 0; left: 0; width: 100%; height: 100%;
    pointer-events: none; z-index: 9999; opacity: 0.02;
    background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  }
}

#app {
  min-height: calc(100vh - var(--header-total) - var(--nav-height));
  max-width: 480px;
  margin: 0 auto;
  padding: 0;
}

a { color: var(--accent); text-decoration: none; }
a:hover { text-decoration: underline; }

/* Lucide SVG icons */
.lucide { display: inline-block; vertical-align: middle; flex-shrink: 0; }
.lucide.icon-filled { fill: currentColor; }

img { max-width: 100%; height: auto; }

/* Typography */
.text-xs { font-size: 11px; }
.text-sm { font-size: 13px; }
.text-base { font-size: 15px; }
.text-lg { font-size: 18px; }
.text-xl { font-size: 22px; }
.text-2xl { font-size: 28px; }
.text-3xl { font-size: 36px; }
.font-light { font-weight: 300; }
.font-medium { font-weight: 500; }
.font-semibold { font-weight: 600; }
.font-bold { font-weight: 700; }
.text-muted { color: var(--muted); }
.text-accent { color: var(--accent); }
.text-gold { color: var(--gold-text); }
.uppercase { text-transform: uppercase; letter-spacing: 0.08em; }

/* Premium typography */
h2.heading { letter-spacing: -0.02em; }
.text-xs, .text-sm { letter-spacing: 0.01em; }

/* Body text gets more room between lines. Regular weight: the selector lost
   its commas and never applied, so 300 was never seen - and is too thin to
   read on a dark screen in daylight. */
.day-card-desc, .tip-card-content, .sheet-desc, .phrase-context {
  line-height: 1.7;
}

/* Layout */
.px-4 { padding-left: 16px; padding-right: 16px; }
.py-3 { padding-top: 12px; padding-bottom: 12px; }
.py-4 { padding-top: 16px; padding-bottom: 16px; }
.mt-2 { margin-top: 8px; }
.mt-3 { margin-top: 12px; }
.mt-4 { margin-top: 16px; }
.mb-2 { margin-bottom: 8px; }
.mb-3 { margin-bottom: 12px; }
.gap-2 { gap: 8px; }
.gap-3 { gap: 12px; }

/* Scroll */
.scroll-x {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.scroll-x::-webkit-scrollbar { display: none; }

/* Animations */
@keyframes fadeIn {
  from { opacity: 0; transform: translateY(8px); }
  to { opacity: 1; transform: translateY(0); }
}

@keyframes slideInRight {
  from { opacity: 0; transform: translateX(20px); }
  to { opacity: 1; transform: translateX(0); }
}

@keyframes slideInLeft {
  from { opacity: 0; transform: translateX(-20px); }
  to { opacity: 1; transform: translateX(0); }
}

.fade-in { animation: fadeIn 0.3s ease-out; }
.slide-right { animation: slideInRight 0.3s ease-out; }
.slide-left { animation: slideInLeft 0.3s ease-out; }

/* ── Page Transitions ── */
.page-wrapper { overflow-x: clip; min-height: 100%; }

@keyframes pageEnterRight {
  from { opacity: 0; transform: translateX(30%); }
  to { opacity: 1; transform: translateX(0); }
}

@keyframes pageExitLeft {
  from { opacity: 1; transform: translateX(0); }
  to { opacity: 0; transform: translateX(-15%); }
}

@keyframes pageEnterLeft {
  from { opacity: 0; transform: translateX(-30%); }
  to { opacity: 1; transform: translateX(0); }
}

@keyframes pageExitRight {
  from { opacity: 1; transform: translateX(0); }
  to { opacity: 0; transform: translateX(15%); }
}

.page-enter-right {
  animation: pageEnterRight 280ms cubic-bezier(0.2, 0, 0, 1) both;
  will-change: transform, opacity;
}

.page-exit-left {
  animation: pageExitLeft 280ms cubic-bezier(0.2, 0, 0, 1) both;
  will-change: transform, opacity;
}

.page-enter-left {
  animation: pageEnterLeft 280ms cubic-bezier(0.2, 0, 0, 1) both;
  will-change: transform, opacity;
}

.page-exit-right {
  animation: pageExitRight 280ms cubic-bezier(0.2, 0, 0, 1) both;
  will-change: transform, opacity;
}

/* ── Native App Feel ── */
@media (display-mode: standalone) {
  html, body { overscroll-behavior: none; }
}

/* Disable text selection on UI chrome */
button, nav, .header, .bottom-nav, .filter-chip, .day-chip, .quick-link, .nav-item, .lang-toggle,
.tag, .region-badge, .day-nav-btn, .back-btn {
  user-select: none;
  -webkit-user-select: none;
}

/* Ensure all form elements are always interactive */
input, textarea, select, [contenteditable] {
  user-select: text !important;
  -webkit-user-select: text !important;
}

/* Allow selection on content */
.day-card-desc, .tip-card-content, .phrase-jp, .phrase-romaji, .phrase-meaning, .phrase-context,
.place-card-name, p, article {
  user-select: text;
  -webkit-user-select: text;
}

/* Smooth scrolling */
.scroll-x, .day-strip, .filter-row {
  scroll-behavior: smooth;
}

/* ── Spring Easing for Modals/Sheets ── */
.spring-enter {
  animation: springIn 400ms cubic-bezier(0.34, 1.56, 0.64, 1) both;
}
@keyframes springIn {
  from { transform: translateY(100%); }
  to { transform: translateY(0); }
}

/* ── Staggered Card Animations ── */
@keyframes staggerFadeIn {
  from { opacity: 0; transform: translateY(12px); }
  to { opacity: 1; transform: translateY(0); }
}

.stagger-item {
  opacity: 0;
  animation: staggerFadeIn 0.3s ease-out forwards;
  animation-delay: calc(var(--i, 0) * 50ms);
}

/* ── M3 Elevation System ── */
.elevation-0 { box-shadow: none; }
.elevation-1 { box-shadow: 0 1px 2px rgba(0,0,0,0.15), 0 1px 3px 1px rgba(0,0,0,0.08); }
.elevation-2 { box-shadow: 0 1px 2px rgba(0,0,0,0.15), 0 2px 6px 2px rgba(0,0,0,0.08); }
.elevation-3 { box-shadow: 0 4px 8px 3px rgba(0,0,0,0.08), 0 1px 3px rgba(0,0,0,0.15); }
.elevation-4 { box-shadow: 0 6px 10px 4px rgba(0,0,0,0.08), 0 2px 3px rgba(0,0,0,0.15); }

/* ── Ripple Effect ── */
@keyframes ripple {
  from { transform: scale(0); opacity: 0.35; }
  to { transform: scale(2.5); opacity: 0; }
}

.ripple-target {
  position: relative;
  overflow: hidden;
}

.ripple-target::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 100%;
  aspect-ratio: 1;
  border-radius: 50%;
  background: radial-gradient(circle, var(--accent) 0%, transparent 70%);
  transform: translate(-50%, -50%) scale(0);
  opacity: 0;
  pointer-events: none;
}

.ripple-target:active::after {
  animation: ripple 0.5s ease-out;
}

/* Number counter animation */
@keyframes countUp {
  from { transform: translateY(20px); opacity: 0; }
  to { transform: translateY(0); opacity: 1; }
}
.count-animate {
  animation: countUp 0.6s var(--ease-out-expo) both;
}

/* ============================================================
   Inputs at 16px
   ============================================================
   iOS zooms the page in when a text field smaller than 16px takes focus, and
   never zooms back out. The usual workaround is `user-scalable=no` in the
   viewport meta, which fixes the symptom by removing pinch-zoom from everyone,
   including the people who need it - a WCAG 1.4.4 failure.

   Setting the fields to 16px fixes the cause instead, so the viewport meta no
   longer has to lie. This is a floor, not a size: anything that wants to look
   smaller can, as long as it is not a field you type into.
*/
input[type="text"],
input[type="search"],
input[type="number"],
input[type="date"],
input[type="password"],
input[type="email"],
input[type="tel"],
input[type="time"],
select,
textarea {
  font-size: 16px;
}

/* Room for the notch and the home indicator, now that the viewport is
   `viewport-fit=cover`. */
body {
  padding-left: env(safe-area-inset-left);
  padding-right: env(safe-area-inset-right);
}

/*
 * REDUCE MOTION, EVERYWHERE.
 *
 * One rule in the whole app honoured the setting; the page slides, the sheet
 * spring, ripples and the loading shimmer always ran. With it on, every
 * animation and transition finishes at once - things still appear and
 * change, they just do not move to get there.
 */
/* Arrows that mean "next" or "forward" point the other way in Arabic and
   Hebrew, where the page runs right to left (i18n.js sets dir on <html>). */
[dir="rtl"] .lucide-chevron-right,
[dir="rtl"] .lucide-chevron-left,
[dir="rtl"] .lucide-arrow-right,
[dir="rtl"] .lucide-arrow-left,
[dir="rtl"] .lucide-arrow-right-left {
  transform: scaleX(-1);
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    animation-delay: 0ms !important;
    transition-duration: 0.01ms !important;
    transition-delay: 0ms !important;
    scroll-behavior: auto !important;
  }
}
/* ── Header ── */
.header {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  /* The bar is `--header-height` tall, and sits below whatever the phone
     claims at the top. Padding rather than margin, so the glass background
     still fills the notch area instead of leaving a transparent strip. */
  height: var(--header-total);
  padding-top: var(--safe-top);
  background: var(--glass-bg);
  border-bottom: 1px solid var(--glass-border);
  backdrop-filter: blur(var(--glass-blur)) saturate(180%);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(180%);
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-left: max(16px, env(safe-area-inset-left, 0px));
  padding-right: max(16px, env(safe-area-inset-right, 0px));
  z-index: 100;
}

.header-title {
  /* An h1 for the screen reader, unchanged for the eye. */
  margin: 0;
  font-size: 16px;
  font-weight: 600;
  color: var(--ink);
  display: flex;
  align-items: center;
  gap: 8px;
}

.header-title .jp {
  font-size: 12px;
  color: var(--muted);
  font-weight: 400;
}

.lang-toggle {
  display: flex;
  align-items: center;
  gap: 4px;
  background: var(--accent-bg);
  border: 1px solid var(--accent);
  color: var(--accent);
  border-radius: 20px;
  padding: 4px 12px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.2s;
}

.lang-toggle:active {
  background: var(--accent-fill);
  color: white;
}

.back-btn {
  background: none;
  border: none;
  color: var(--accent);
  font-size: 20px;
  cursor: pointer;
  padding: 8px 12px 8px 0;
  min-width: 44px;
  min-height: 44px;
  display: flex;
  align-items: center;
}

/* ── Bottom Navigation ── */
.bottom-nav {
  position: fixed;
  /* Above the gesture bar, not under it. With `viewport-fit=cover` a flat 12px
     put the nav labels behind the Android navigation pill, which is what
     clipped "Explore". */
  bottom: calc(12px + env(safe-area-inset-bottom, 0px));
  left: max(16px, env(safe-area-inset-left, 0px));
  right: max(16px, env(safe-area-inset-right, 0px));
  height: 56px;
  background: var(--glass-bg);
  backdrop-filter: blur(var(--glass-blur)) saturate(180%);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(180%);
  border: 1px solid var(--glass-border);
  border-radius: 28px;
  display: flex;
  align-items: center;
  justify-content: space-around;
  z-index: 100;
  box-shadow: 0 4px 24px rgba(0,0,0,0.12);
  padding: 0 8px;
}

.bottom-nav::before {
  content: '';
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  /* One equal slot per tab (BottomNav sets --tab-count), inside the 8px side
     padding: sized for five, the pill missed the fourth tab once there were four. */
  inset-inline-start: calc(8px + var(--active-index, 0) * (100% - 16px) / var(--tab-count, 4) + 6px);
  width: calc((100% - 16px) / var(--tab-count, 4) - 12px);
  height: 40px;
  background: var(--accent-bg);
  border-radius: 20px;
  transition: left 300ms cubic-bezier(0.2, 0, 0, 1);
}

/* A screen that belongs to no tab (the planner) lights none. */
.bottom-nav.no-active::before { opacity: 0; }

.nav-item {
  display: flex;
  flex: 1 1 0;
  min-width: 0;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: 8px 14px;
  min-height: 44px;
  cursor: pointer;
  border: none;
  background: none;
  color: var(--muted);
  font-size: 11px;
  font-weight: 500;
  transition: color 0.2s, transform 100ms ease;
  -webkit-tap-highlight-color: transparent;
}

.nav-item:active {
  transform: scale(0.9);
}

.nav-item.active {
  color: var(--accent);
}

.nav-item.active .nav-icon {
  transform: scale(1.1);
  transition: transform 200ms var(--ease-spring, cubic-bezier(0.34, 1.56, 0.64, 1));
}

.nav-item .nav-icon {
  font-size: 24px;
  line-height: 1;
}

/* ── Cards ── */
.card {
  background: var(--white);
  border: none;
  border-radius: var(--radius);
  padding: 14px 16px;
  box-shadow: 0 0 0 1px rgba(0,0,0,0.04), 0 1px 3px rgba(0,0,0,0.06);
  transition: transform 100ms ease, box-shadow 100ms ease;
}

.card:active {
  transform: scale(0.98);
  box-shadow: var(--shadow-md);
}

.card-compact {
  background: var(--white);
  border: none;
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  box-shadow: 0 0 0 1px rgba(0,0,0,0.04), 0 1px 3px rgba(0,0,0,0.06);
}

/* Card: Featured, for NOW card, hero cards, CTAs */
.card-featured {
  background: linear-gradient(135deg, var(--color-surface-elevated) 0%, var(--paper2) 100%);
  border-inline-start: 3px solid var(--accent);
  box-shadow: var(--shadow-md);
}

/* Card: Subtle, for secondary info, notes, suggestions */
.card-subtle {
  background: var(--paper2);
  box-shadow: none;
  border: 1px solid var(--border);
}

/* Card: Interactive, for tappable items with hover feedback */
.card-interactive {
  box-shadow: 0 0 0 1px rgba(0,0,0,0.04), var(--shadow);
  transition: transform 150ms var(--ease-smooth), box-shadow 150ms var(--ease-smooth);
}
.card-interactive:active {
  transform: scale(0.98) translateY(1px);
  box-shadow: 0 0 0 1px rgba(0,0,0,0.04), 0 1px 2px rgba(0,0,0,0.04);
}

/* More alive button press, scale + subtle shadow shift */
.btn:active, .quick-link:active, .filter-chip:active {
  transform: scale(0.96);
  box-shadow: 0 1px 2px rgba(0,0,0,0.1);
}
.btn-icon:active {
  transform: scale(0.88);
}

/* ── Day Card (in timeline) ── */
.day-card {
  display: flex;
  gap: 12px;
  padding: 12px 0;
  border-bottom: 1px dotted var(--border);
  animation: fadeIn 0.3s ease-out;
}

.day-card:last-child { border-bottom: none; }

.day-card-time {
  flex-shrink: 0;
  width: 52px;
  font-size: 13px;
  font-weight: 600;
  color: var(--accent);
  padding-top: 2px;
}

.day-card-content {
  flex: 1;
  min-width: 0;
}

.day-card-title {
  font-size: 15px;
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 4px;
}

.day-card-desc {
  font-size: 13px;
  color: var(--ink-light);
  line-height: 1.5;
}

.day-card-icon {
  flex-shrink: 0;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
}

.icon-transport { background: var(--transport-bg); }
.icon-sightseeing { background: var(--accent-bg); }
.icon-food { background: var(--food-bg); }
.icon-shopping { background: var(--shopping-bg); }
.icon-walking { background: var(--walk-bg); }
.icon-accommodation { background: var(--gold-bg); }

/* ── Transport Badge ── */
.transport-badge {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 4px 10px;
  border-radius: 20px;
  font-size: 11px;
  font-weight: 600;
  margin: 4px 0;
}

.transport-badge.train {
  background: var(--transport-bg);
  color: var(--transport);
}

.transport-badge.bus {
  background: #f0fdf4;
  color: #15803d;
}

.transport-badge.walk {
  background: var(--walk-bg);
  color: var(--walk-text);
}

.transport-badge.boat {
  background: #eff6ff;
  color: #1d4ed8;
}

.transport-badge.plane {
  background: #faf5ff;
  color: #7c3aed;
}

.transport-badge .cost {
  background: rgba(0,0,0,0.06);
  padding: 1px 6px;
  border-radius: 10px;
  font-size: 11px;
}

/* ── Place Card ── */
.place-card {
  background: var(--white);
  border: none;
  border-radius: var(--radius-sm);
  padding: 10px 12px;
  display: flex;
  gap: 10px;
  align-items: flex-start;
  cursor: pointer;
  box-shadow: 0 0 0 1px rgba(0,0,0,0.04), 0 1px 3px rgba(0,0,0,0.06);
  transition: transform 100ms ease, box-shadow 100ms ease;
}

.place-card:active {
  transform: scale(0.98);
  box-shadow: var(--shadow-md);
}

.place-card-icon {
  flex-shrink: 0;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 16px;
}

/*
 * A photograph in the same slot the category glyph occupies, so a list does
 * not reflow when the manifest lands and half the cards gain a picture.
 * Square rather than round: a circular crop of a temple is mostly sky.
 */
.place-card-thumb {
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  border-radius: 7px;
  overflow: hidden;
  background: var(--paper2);
}
.place-card-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.place-card-info {
  flex: 1;
  min-width: 0;
}

.place-card-name {
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.place-card-meta {
  font-size: 11px;
  color: var(--muted);
  margin-top: 2px;
}

.place-card-distance {
  font-size: 11px;
  color: var(--accent);
  font-weight: 600;
}

.place-card .maps-link {
  flex-shrink: 0;
  color: var(--transport);
  font-size: 18px;
  padding: 4px;
  min-width: 44px;
  min-height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* Favorite button - filled heart when active */
.fav-btn.fav-active .lucide-heart {
  fill: currentColor;
}

/* ── Category Tags ── */
.tag {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 10px;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.tag-food { background: var(--food-bg); color: var(--food-text); }
.tag-tourism { background: var(--accent-bg); color: var(--accent); }
.tag-shopping { background: var(--shopping-bg); color: #7c3aed; }
.tag-general { background: var(--gold-bg); color: var(--gold-text); }
.tag-transport { background: var(--transport-bg); color: var(--transport); }

/* ── Hidden gem and busy (src/place-labels.js) ──
   One chip, two colours. Inline in an Explore row's sub line, so the row
   keeps its height; on the sheet the colour classes ride on .sheet-badge. */
.place-label {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 1px 7px;
  border-radius: 9px;
  font-size: 11px;
  font-weight: 600;
  line-height: 16px;
  vertical-align: 1px;
}

.place-label-hidden-gem { background: var(--gold-bg); color: var(--gold-text); }
.place-label-busy { background: var(--accent-bg); color: var(--accent); }

/* ── Region Badge ── */
.region-badge {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 12px;
  font-size: 11px;
  font-weight: 600;
  background: var(--accent-fill);
  color: white;
}

/* ── Price Tag ── */
.price-tag {
  display: inline-block;
  background: #f5ecd4;
  color: #7a5e2b;
  font-size: 11px;
  padding: 1px 7px;
  border-radius: 10px;
  font-weight: 700;
}

.free-tag {
  background: #dcefd9;
  color: #2d6a2d;
}

/* ── Search Input ── */
.search-input {
  width: 100%;
  /* 10px of padding round a 16px font came to 42px, two short of the 44px
     minimum touch target - and a search box is the one control on the page
     people aim at while walking. */
  min-height: 44px;
  padding: 12px 14px;
  padding-inline-start: 36px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  background: var(--white);
  font-size: 16px;
  font-family: inherit;
  color: var(--ink);
  outline: none;
  transition: border-color 0.2s;
}

.search-input:focus {
  border-color: var(--accent);
}

.search-wrap {
  position: relative;
}

.search-wrap .search-icon {
  position: absolute;
  inset-inline-start: 12px;
  top: 50%;
  transform: translateY(-50%);
  color: var(--muted);
  display: flex;
  align-items: center;
  pointer-events: none;
  z-index: 1;
}

/* ── Filter Chips ── */
.filter-row {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  padding: 8px 16px;
  scrollbar-width: none;
}

.filter-row::-webkit-scrollbar { display: none; }

.filter-chip {
  flex-shrink: 0;
  padding: 6px 14px;
  border-radius: 20px;
  border: 1px solid var(--border-strong);
  background: var(--white);
  font-size: 12px;
  font-weight: 500;
  color: var(--ink-light);
  cursor: pointer;
  transition: all 0.2s;
  -webkit-tap-highlight-color: transparent;
}

.filter-chip:active {
  transform: scale(0.95);
}

/*
 * Chips that are OPTIONS rather than filters.
 *
 * `.filter-chip` is `flex-shrink: 0` because the filter rows scroll sideways
 * and a chip that shrank would be unreadable. In a wrapping container that
 * same rule is wrong: the chip keeps its max-content width, and "A bit of both
 * · Trains between cities, a car where it helps" ran straight off the right
 * edge of the phone with no way to read the end of it.
 *
 * These are one-per-line choices, so they shrink, wrap and align left like the
 * sentences they are.
 */
.option-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.option-chips > .filter-chip {
  flex: 1 1 100%;
  min-width: 0;
  max-width: 100%;
  white-space: normal;
  text-align: start;
  line-height: 1.45;
}

.filter-chip.active {
  background: var(--accent-fill);
  border-color: var(--accent-fill);
  color: white;
}

/* ── Phrase Card ── */
.phrase-card {
  background: var(--white);
  border: none;
  border-radius: var(--radius-sm);
  padding: 12px 14px;
  box-shadow: 0 0 0 1px rgba(0,0,0,0.04), 0 1px 3px rgba(0,0,0,0.06);
  transition: transform 100ms ease;
  cursor: pointer;
}

.phrase-card:active {
  transform: scale(0.98);
}

/* Listen and Copy: two named 44px targets in the card's top corner. The
   phrase and its romanisation make room for them; the meaning below, which
   starts past the buttons, keeps the card's full width. */
.phrase-actions {
  position: absolute;
  top: 2px;
  inset-inline-end: 2px;
  display: flex;
}
.phrase-act {
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 22px;
  background: none;
  color: var(--text-secondary);
  cursor: pointer;
}
.phrase-act.speak-btn { color: var(--accent); }
.phrase-act:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.phrase-card.has-actions .phrase-jp,
.phrase-card.has-actions .phrase-romaji { padding-inline-end: 84px; }

.phrase-jp {
  font-size: 20px;
  font-weight: 500;
  color: var(--accent);
  font-family: 'Noto Sans JP', sans-serif;
}

.phrase-romaji {
  font-size: 13px;
  color: var(--gold-text);
  font-style: italic;
  margin-top: 2px;
}

.phrase-meaning {
  font-size: 13px;
  color: var(--ink);
  margin-top: 4px;
}

.phrase-context {
  font-size: 11px;
  color: var(--muted);
  margin-top: 2px;
}

/* ── Section Header ── */
.section-header {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent);
  padding: 16px 16px 8px;
}

/* ── Tip Card ── */
.tip-card {
  background: var(--white);
  border: none;
  border-radius: var(--radius);
  padding: 14px 16px;
  margin: 0 16px 10px;
  box-shadow: 0 0 0 1px rgba(0,0,0,0.04), 0 1px 3px rgba(0,0,0,0.06);
  transition: transform 100ms ease;
  cursor: pointer;
}

.tip-card:active {
  transform: scale(0.98);
}

.tip-card-title {
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 0;
  display: flex;
  align-items: center;
  gap: 8px;
}

.tip-card-content {
  font-size: 13px;
  color: var(--ink-light);
  line-height: 1.6;
}

/* ── Emergency Card ── */
.emergency-card {
  background: var(--white);
  border: 1px solid #fecaca;
  border-inline-start: 4px solid #ef4444;
  border-radius: var(--radius-sm);
  padding: 12px 14px;
  display: flex;
  align-items: center;
  gap: 12px;
  transition: transform 100ms ease;
}

.emergency-card:active {
  transform: scale(0.98);
}

.emergency-card .phone {
  font-size: 18px;
  font-weight: 700;
  color: var(--accent);
}

.emergency-card .label {
  font-size: 13px;
  color: var(--ink);
  font-weight: 500;
}

/* ── Day Strip (horizontal scroll) ── */
.day-strip {
  display: flex;
  gap: 10px;
  padding: 12px 16px;
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-mask-image: linear-gradient(to right, transparent 0%, black 16px, black calc(100% - 16px), transparent 100%);
  mask-image: linear-gradient(to right, transparent 0%, black 16px, black calc(100% - 16px), transparent 100%);
}

.day-strip::-webkit-scrollbar { display: none; }

.day-chip {
  flex-shrink: 0;
  width: 60px;
  padding: 8px 6px;
  border-radius: var(--radius-sm);
  border: none;
  background: var(--white);
  text-align: center;
  cursor: pointer;
  transition: all 0.2s;
  -webkit-tap-highlight-color: transparent;
  box-shadow: 0 0 0 1px rgba(0,0,0,0.04), 0 1px 3px rgba(0,0,0,0.06);
}

.day-chip:active, .day-chip.active {
  background: var(--accent-fill);
  border-color: var(--accent-fill);
  color: white;
}

.day-chip.active .day-chip-num, .day-chip.active .day-chip-date {
  color: white;
}

.day-chip.today {
  border-color: var(--gold);
  box-shadow: 0 0 0 2px var(--gold-bg);
}

.day-chip-num {
  font-size: 18px;
  font-weight: 700;
  color: var(--ink);
  line-height: 1;
}

.day-chip-date {
  font-size: 11px;
  color: var(--muted);
  margin-top: 4px;
}

.day-chip-region {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  color: var(--accent);
  margin-top: 2px;
}

.day-chip.active .day-chip-region { color: var(--gold-light); }

/* ── Nearby Section ── */
.nearby-section {
  background: var(--paper2);
  border: none;
  border-radius: var(--radius);
  padding: 12px;
  margin-top: 12px;
  box-shadow: 0 0 0 1px rgba(0,0,0,0.04), 0 1px 3px rgba(0,0,0,0.06);
}

.nearby-header {
  font-size: 12px;
  font-weight: 600;
  color: var(--gold-text);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-bottom: 8px;
  display: flex;
  align-items: center;
  gap: 6px;
}

.nearby-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

/* ── Map ── */
.map-container {
  width: 100%;
  height: 300px;
  border-radius: var(--radius);
  overflow: hidden;
  border: 1px solid var(--border);
}

/* .map-container.fullscreen moved to pages.css as .map-container-fullscreen */

/* ── Loading ── */
.loading {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 40px;
  color: var(--muted);
  font-size: 14px;
}

/* Dark mode overrides for hardcoded colors */
[data-theme="dark"] .transport-badge.bus { background: rgba(22, 163, 74, 0.12); }
[data-theme="dark"] .transport-badge.boat { background: rgba(29, 78, 216, 0.12); }
[data-theme="dark"] .transport-badge.plane { background: rgba(124, 58, 237, 0.12); }
[data-theme="dark"] .emergency-card { border-color: rgba(239, 68, 68, 0.3); border-left-color: #ef4444; }
[data-theme="dark"] .price-tag { background: rgba(186, 148, 85, 0.2); color: var(--gold-text); }
[data-theme="dark"] .free-tag { background: rgba(22, 163, 74, 0.2); color: var(--walk-text); }

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .transport-badge.bus { background: rgba(22, 163, 74, 0.12); }
  :root:not([data-theme="light"]) .transport-badge.boat { background: rgba(29, 78, 216, 0.12); }
  :root:not([data-theme="light"]) .transport-badge.plane { background: rgba(124, 58, 237, 0.12); }
  :root:not([data-theme="light"]) .emergency-card { border-color: rgba(239, 68, 68, 0.3); border-left-color: #ef4444; }
  :root:not([data-theme="light"]) .price-tag { background: rgba(186, 148, 85, 0.2); color: var(--gold-text); }
  :root:not([data-theme="light"]) .free-tag { background: rgba(22, 163, 74, 0.2); color: var(--walk-text); }
}

/* ── Dark mode shadow-border overrides ── */
[data-theme="dark"] .card,
[data-theme="dark"] .card-compact,
[data-theme="dark"] .place-card,
[data-theme="dark"] .phrase-card,
[data-theme="dark"] .tip-card,
[data-theme="dark"] .day-list-item,
[data-theme="dark"] .quick-link,
[data-theme="dark"] .day-chip,
[data-theme="dark"] .nearby-section {
  box-shadow: 0 0 0 1px rgba(255,255,255,0.06), 0 1px 3px rgba(0,0,0,0.3);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .card,
  :root:not([data-theme="light"]) .card-compact,
  :root:not([data-theme="light"]) .place-card,
  :root:not([data-theme="light"]) .phrase-card,
  :root:not([data-theme="light"]) .tip-card,
  :root:not([data-theme="light"]) .day-list-item,
  :root:not([data-theme="light"]) .quick-link,
  :root:not([data-theme="light"]) .day-chip,
  :root:not([data-theme="light"]) .nearby-section {
    box-shadow: 0 0 0 1px rgba(255,255,255,0.06), 0 1px 3px rgba(0,0,0,0.3);
  }
}

/* ── Toast ── */
.toast {
  position: fixed;
  bottom: calc(var(--nav-height) + 16px);
  left: 50%;
  transform: translateX(-50%) translateY(20px);
  background: var(--ink);
  color: var(--paper);
  padding: 10px 20px;
  border-radius: 24px;
  font-size: 13px;
  font-weight: 500;
  z-index: 200;
  opacity: 0;
  transition: opacity 200ms ease, transform 200ms ease;
  pointer-events: none;
  white-space: nowrap;
  box-shadow: 0 4px 12px rgba(0,0,0,0.15);
}

.toast.visible {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

@supports not (backdrop-filter: blur(1px)) {
  .header { background: var(--white); }
  .bottom-nav { background: var(--white); }
}

/* ── Accordion ── */
.accordion-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 0;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
  transition: transform 100ms ease;
}
.accordion-header:active {
  transform: scale(0.97);
}

.accordion-header .accordion-chevron {
  transition: transform 300ms ease;
  color: var(--muted);
}

.accordion-header.open .accordion-chevron {
  transform: rotate(180deg);
}

.accordion-body {
  max-height: 0;
  overflow: hidden;
  transition: max-height 400ms cubic-bezier(0.2, 0, 0, 1);
}

.accordion-body.open {
  max-height: 3000px;
}

/* Expandable tip cards */
.tip-card .tip-card-content {
  max-height: 0;
  overflow: hidden;
  transition: max-height 300ms ease;
  margin-top: 0;
}

.tip-card.expanded .tip-card-content {
  max-height: 500px;
  margin-top: 8px;
}

.tip-card .expand-chevron {
  transition: transform 300ms ease;
  margin-inline-start: auto;
  color: var(--muted);
}

.tip-card.expanded .expand-chevron {
  transform: rotate(180deg);
}

/* ── Settings Page ── */
.color-swatch {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 3px solid transparent;
  cursor: pointer;
  transition: transform 100ms ease, border-color 200ms ease;
  display: flex;
  align-items: center;
  justify-content: center;
}
.color-swatch.active {
  border-color: var(--ink);
  transform: scale(1.1);
}
.color-swatch:active { transform: scale(0.9); }

.toggle-switch {
  position: relative;
  width: 48px;
  height: 28px;
  border-radius: 14px;
  background: var(--border);
  cursor: pointer;
  transition: background 200ms ease;
  flex-shrink: 0;
}
.toggle-switch.on { background: var(--accent-fill); }
.toggle-switch::after {
  content: '';
  position: absolute;
  top: 2px;
  inset-inline-start: 2px;
  width: 24px;
  height: 24px;
  border-radius: 50%;
  background: white;
  transition: transform 200ms ease;
  box-shadow: 0 1px 3px rgba(0,0,0,0.2);
}
.toggle-switch.on::after { transform: translateX(20px); }
[dir="rtl"] .toggle-switch.on::after { transform: translateX(-20px); }

.settings-section {
  margin-bottom: 24px;
}
.settings-section-title {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 12px;
}
.settings-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 0;
  border-bottom: 1px solid var(--border);
}
.settings-row:last-child { border-bottom: none; }
.settings-label {
  font-size: 14px;
  color: var(--ink);
}
.settings-input {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--white);
  font-size: 14px;
  font-family: inherit;
  color: var(--ink);
  outline: none;
  margin-bottom: 8px;
}
.settings-input:focus { border-color: var(--accent); }
.settings-select {
  padding: 8px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--white);
  font-size: 14px;
  font-family: inherit;
  color: var(--ink);
  outline: none;
}
.settings-select:focus { border-color: var(--accent); }
.settings-btn {
  background: var(--accent-fill);
  color: white;
  border: none;
  border-radius: var(--radius-sm);
  padding: 10px 20px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  font-family: inherit;
  transition: transform 100ms ease;
}
.settings-btn:active { transform: scale(0.97); }
.settings-btn-outline {
  background: transparent;
  color: var(--accent);
  border: 1px solid var(--accent);
  border-radius: var(--radius-sm);
  padding: 10px 20px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  font-family: inherit;
  transition: transform 100ms ease;
}
.settings-btn-outline:active { transform: scale(0.97); }
.settings-btn-danger {
  background: transparent;
  color: #ef4444;
  border: 1px solid #ef4444;
  border-radius: var(--radius-sm);
  padding: 10px 20px;
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  font-family: inherit;
  transition: transform 100ms ease;
}
.settings-btn-danger:active { transform: scale(0.97); }

.lang-seg {
  display: flex;
  border: 1px solid var(--accent);
  border-radius: var(--radius-sm);
  overflow: hidden;
}
.lang-seg button {
  flex: 1;
  padding: 8px 20px;
  border: none;
  background: transparent;
  color: var(--accent);
  font-size: 14px;
  font-weight: 600;
  cursor: pointer;
  font-family: inherit;
  transition: all 200ms ease;
}
.lang-seg button.active {
  background: var(--accent-fill);
  color: white;
}

.color-picker-input {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  border: 3px solid var(--border);
  cursor: pointer;
  padding: 0;
  overflow: hidden;
  background: none;
}
.color-picker-input::-webkit-color-swatch-wrapper { padding: 0; }
.color-picker-input::-webkit-color-swatch { border: none; border-radius: 50%; }
.color-picker-input::-moz-color-swatch { border: none; border-radius: 50%; }

/* ── Speak Button Animation ── */
.speak-btn.speaking {
  animation: speakPulse 0.8s ease infinite;
}
@keyframes speakPulse {
  0%, 100% { opacity: 0.5; transform: scale(1); }
  50% { opacity: 1; transform: scale(1.2); }
}

/* ── Timeline ── */
.timeline {
  position: relative;
  padding-inline-start: 28px;
}

.timeline::before {
  content: '';
  position: absolute;
  inset-inline-start: 8px;
  top: 24px;
  bottom: 24px;
  width: 2px;
  background: var(--border);
}

.timeline-item {
  position: relative;
  padding-bottom: 4px;
}

.timeline-dot {
  position: absolute;
  inset-inline-start: -28px;
  top: 14px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 2px solid var(--accent);
  background: var(--white);
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}

.timeline-dot.active {
  background: var(--accent-fill);
  box-shadow: 0 0 0 4px var(--accent-bg);
}

.timeline-dot.active::after {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: white;
}

/* The way into Explore, narrowed to the day, at the end of its timeline. */
.day-add-stop {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-height: 48px;
  padding: 0 14px;
  border: 1px dashed var(--accent);
  border-radius: var(--radius);
  color: var(--accent);
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
}

.timeline-connector {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px 0 4px 0;
  margin-inline-start: -28px;
  padding-inline-start: 28px;
  font-size: 11px;
  color: var(--muted);
  position: relative;
}

.timeline-connector::before {
  content: '';
  position: absolute;
  inset-inline-start: 12px;
  top: 0;
  bottom: 0;
  width: 2px;
  background: var(--border);
  border-style: dashed;
}

/* Collapsible activity cards */
.day-card {
  cursor: pointer;
}

/* Folded away is out of reach too: `visibility` takes Navigate, Reminder and
   Change out of the tab order (focus used to land on them inside a 0px box),
   and switches only once the fold has finished. */
.day-card-desc, .day-card-extra {
  max-height: 0;
  overflow: hidden;
  visibility: hidden;
  transition: max-height 300ms cubic-bezier(0.2, 0, 0, 1), margin 200ms ease, visibility 0s linear 300ms;
  margin-top: 0;
}

.day-card.expanded .day-card-desc, .day-card.expanded .day-card-extra {
  max-height: 500px;
  margin-top: 4px;
  visibility: visible;
  transition-delay: 0s;
}

.day-card-expand {
  color: var(--muted);
  transition: transform 200ms ease;
  margin-inline-start: auto;
  background: none;
  border: none;
  padding: 0;
  min-width: 44px;
  min-height: 44px;
  margin-block: -12px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  font: inherit;
}

.day-card.expanded .day-card-expand {
  transform: rotate(180deg);
}

/* Current activity badge */
.activity-badge {
  display: inline-block;
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  padding: 2px 6px;
  border-radius: 4px;
  margin-inline-start: 8px;
}

.badge-now {
  background: var(--accent-fill);
  color: white;
}

.badge-next {
  background: var(--gold-bg);
  color: var(--gold-text);
}

/* Daily summary bar */
.day-summary {
  display: flex;
  gap: 12px;
  padding: 8px 12px;
  background: var(--paper2);
  border-radius: var(--radius-sm);
  margin-bottom: 16px;
  font-size: 11px;
  color: var(--muted);
  flex-wrap: wrap;
}

.day-summary-item {
  display: flex;
  align-items: center;
  gap: 4px;
}

/* ── Checklist ── */
.checklist-item {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 0;
  border-bottom: 1px solid var(--border);
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: transform 100ms ease;
}
.checklist-item:active { transform: scale(0.97); }
.checklist-item:last-child { border-bottom: none; }
.checklist-item.checked .checklist-label { text-decoration: line-through; color: var(--muted); }
.checklist-check {
  width: 22px; height: 22px; border-radius: 50%;
  border: 2px solid var(--border); display: flex;
  align-items: center; justify-content: center;
  flex-shrink: 0; transition: all 200ms ease;
}
.checklist-item.checked .checklist-check {
  background: var(--accent-fill); border-color: var(--accent-fill); color: white;
}
.checklist-label { font-size: 14px; color: var(--ink); }
.checklist-progress {
  height: 6px; background: var(--border); border-radius: 3px;
  overflow: hidden; margin: 8px 0 16px;
}
.checklist-progress-bar {
  height: 100%; background: var(--accent-fill); border-radius: 3px;
  transition: width 300ms ease;
}

/* ── Wishlist Item ── */
.wishlist-item [data-check] {
  -webkit-tap-highlight-color: transparent;
  transition: transform 100ms ease, all 200ms ease;
}
.wishlist-item [data-check]:active {
  transform: scale(0.9);
}

/* ── Medical Phrase Card ── */
.medical-phrase {
  background: var(--white);
  border-radius: var(--radius-sm);
  padding: 12px 14px;
  margin-bottom: 8px;
  box-shadow: 0 0 0 1px rgba(0,0,0,0.04), 0 1px 3px rgba(0,0,0,0.06);
  display: flex;
  align-items: center;
  gap: 10px;
}
.medical-phrase-text { flex: 1; min-width: 0; }
.medical-phrase .speak-btn {
  flex-shrink: 0;
  background: none;
  border: none;
  color: var(--accent);
  cursor: pointer;
  padding: 8px;
  min-width: 44px;
  min-height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* ── Place Bottom Sheet ── */
/* ---- layering ------------------------------------------------------------
   Page furniture (map FABs, the itinerary link, the currency button) sits at
   900-1000. Bottom sheets are modal, so they go above ALL of it, at 500 they
   were underneath, and every floating control in the app punched through them
   one at a time as each was noticed. One scale, stated once. */
.sheet-backdrop {
  position: fixed;
  top: 0; left: 0; right: 0; bottom: 0;
  background: rgba(0,0,0,0.4);
  z-index: 1500;
  opacity: 0;
  pointer-events: none;
  transition: opacity 300ms ease;
}
.sheet-backdrop.visible {
  opacity: 1;
  pointer-events: auto;
}

/* Floating page furniture sits above the page, which put it on top of every
   bottom sheet. A sheet is modal, so nothing outside it should be reachable
   while it is open; it fades rather than sitting dimmed behind the scrim. */
body:has(.sheet-backdrop.visible) .map-fab,
body:has(.sheet-backdrop.visible) .map-itinerary-link {
  opacity: 0 !important;
  pointer-events: none !important;
  transition: opacity 180ms ease;
}

/* Planning is a focused, linear task. The bottom nav invites you to leave it
   half-finished, so it steps aside until there is a trip to browse. */
body.planning .bottom-nav {
  display: none !important;
}
body.planning #app,
body.planning main {
  padding-bottom: 0;
}
/* The body keeps room for the nav at its foot; while planning there is none,
   and the space would sit under the pinned buttons below. */
body.planning {
  padding-bottom: 0;
}

/* The planner's buttons, pinned to the foot of the screen (NewTrip.js
   actionBar). Continue used to sit below the fold on the first step. */
.wizard-actions {
  position: sticky;
  bottom: 0;
  z-index: 5;
  margin: 22px -16px 0;
  padding: 12px 16px calc(12px + env(safe-area-inset-bottom, 0px));
  background: var(--paper);
  border-top: 1px solid var(--border);
}
/* A control focused near the foot of the screen is scrolled clear of the bar
   instead of being focused behind it. */
html:has(body.planning) {
  scroll-padding-bottom: calc(96px + env(safe-area-inset-bottom, 0px));
}
/* Leaflet's panes carry z-indexes of 400 and up; kept inside the map, so the
   pinned bar is drawn over the destination map rather than under it. */
#dest-map {
  isolation: isolate;
}

/* A file picker whose input is hidden visually (.sr-only) but still in the
   keyboard order: its label shows where the focus is. */
.file-pick:focus-within {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.place-sheet {
  position: fixed;
  bottom: 0; left: 0; right: 0;
  max-width: 480px;
  margin: 0 auto;
  background: var(--white);
  border-radius: 20px 20px 0 0;
  padding: 8px 20px 24px;
  z-index: 1501;
  transform: translateY(100%);
  transition: transform 400ms cubic-bezier(0.34, 1.56, 0.64, 1);
  max-height: 70vh;
  overflow-y: auto;
  box-shadow: 0 -4px 24px rgba(0,0,0,0.15);
}
/* A sheet that pins its own header and footer.
 *
 * `.place-sheet` scrolls as a whole, which is right for a simple sheet. The
 * settings and interests sheets ALSO gave their body a max-height and
 * overflow-y, so the sheet scrolled and the body inside it scrolled: two
 * scrollbars side by side, and content that could be scrolled out of reach of
 * both. One scroll region, between a fixed head and a fixed foot.
 */
.place-sheet.sheet-sectioned {
  display: flex;
  flex-direction: column;
  max-height: 88vh;
  overflow: hidden;
  padding-bottom: 0;
}
.place-sheet.sheet-sectioned > .sheet-scroll {
  flex: 1 1 auto;
  overflow-y: auto;
  /* The sheet already pads its sides, so a second horizontal padding pushed
     the content wider than the box and produced a sideways scrollbar under
     the vertical one. Nothing in a settings sheet should scroll sideways. */
  overflow-x: hidden;
  -webkit-overflow-scrolling: touch;
  /* Without this a flex child refuses to shrink below its content height and
     the scroll never engages. */
  min-height: 0;
  overscroll-behavior: contain;
}
.place-sheet.sheet-sectioned > .sheet-foot {
  flex: 0 0 auto;
  padding: 12px 18px calc(18px + env(safe-area-inset-bottom, 0px));
  background: var(--white);
  border-top: 1px solid var(--border);
}

.place-sheet.visible {
  transform: translateY(0);
}

.sheet-handle {
  width: 36px;
  height: 4px;
  border-radius: 2px;
  background: var(--border);
  margin: 4px auto 16px;
}

.sheet-header {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  margin-bottom: 12px;
}

.sheet-title {
  font-size: 18px;
  font-weight: 700;
  color: var(--ink);
  line-height: 1.2;
}

.sheet-subtitle {
  font-size: 13px;
  color: var(--muted);
  margin-top: 2px;
}

.sheet-badges {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 12px;
}

.sheet-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 4px 10px;
  border-radius: 12px;
  font-size: 11px;
  font-weight: 600;
}

.sheet-desc {
  font-size: 14px;
  color: var(--ink-light);
  line-height: 1.6;
  margin-bottom: 16px;
}

.sheet-actions {
  display: flex;
  gap: 8px;
  margin-bottom: 12px;
}

.sheet-action-btn {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: 12px 8px;
  border-radius: var(--radius-sm);
  background: var(--accent-bg);
  color: var(--accent);
  text-decoration: none;
  font-size: 11px;
  font-weight: 600;
  transition: transform 100ms ease;
}
.sheet-action-btn:hover { text-decoration: none; }
.sheet-action-btn:active { transform: scale(0.95); }

.sheet-region {
  font-size: 12px;
  color: var(--muted);
  display: flex;
  align-items: center;
  gap: 4px;
}

/* ── Button System ── */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  min-height: 44px;
  padding: 10px 20px;
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  border: none;
  transition: transform 100ms ease, opacity 100ms ease;
  -webkit-tap-highlight-color: transparent;
  user-select: none;
}
.btn:active { transform: scale(0.97); }
.btn:disabled { opacity: 0.4; cursor: default; transform: none; }
.btn:focus-visible { outline: 2px solid var(--color-border-focus); outline-offset: 2px; }

.btn-primary { background: var(--accent-fill); color: white; }
.btn-secondary { background: var(--color-surface-elevated); color: var(--color-text-primary); border: 1px solid var(--color-border); }
.btn-ghost { background: transparent; color: var(--accent); }
.btn-danger { background: var(--color-status-error); color: white; }
.btn-icon {
  min-height: 44px; min-width: 44px;
  padding: 0; border-radius: 50%;
  background: transparent; color: var(--color-text-tertiary);
}
.btn-icon:active { transform: scale(0.9); }

/* Loading spinner */
.btn-loading { position: relative; color: transparent; pointer-events: none; }
.btn-loading::after {
  content: '';
  position: absolute;
  width: 16px; height: 16px;
  border: 2px solid rgba(255,255,255,0.3);
  border-top-color: white;
  border-radius: 50%;
  animation: btnSpin 0.6s linear infinite;
}
@keyframes btnSpin { to { transform: rotate(360deg); } }

/* ── Input System ── */
.input {
  width: 100%;
  padding: 12px var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  background: var(--color-surface-elevated);
  font-size: 16px;
  font-family: inherit;
  color: var(--color-text-primary);
  outline: none;
  transition: border-color 200ms ease, box-shadow 200ms ease;
}
.input:focus {
  border-color: var(--color-border-focus);
  box-shadow: 0 0 0 3px var(--accent-bg);
}
.input-error {
  border-color: var(--color-status-error);
}
.input-error:focus {
  box-shadow: 0 0 0 3px var(--color-status-error-bg);
}
.input:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
.input-help {
  font-size: var(--text-xs);
  color: var(--color-text-tertiary);
  margin-top: var(--space-1);
}
.input-error-text {
  font-size: var(--text-xs);
  color: var(--color-status-error);
  margin-top: var(--space-1);
}

/* ============================================================
   Place sheet, second pass
   ============================================================
   Everything below exists because the sheet now shows the fields the shipped
   data actually has - a photo, an opening window, dish guidance, source links -
   rather than the six fields of the old curated schema that are present on
   zero records.
*/

.sheet-badge {
  /* The badges had no ground of their own, so the ones without an inline
     background inherited the sheet and read as loose text. */
  background: var(--paper2);
  color: var(--ink);
}

.sheet-hero {
  position: relative;
  margin: 4px -20px 12px;
  height: 170px;
  overflow: hidden;
  background: var(--paper2);
}

/*
 * Photo credit. Commons images are free to reuse but most of them require
 * attribution, so the picture links to its file page where the author and the
 * licence are stated. Set quietly, over a scrim so it stays legible on a
 * bright photograph without dimming the whole image.
 */
.hero-credit {
  position: absolute;
  inset-inline-end: 0;
  bottom: 0;
  padding-block: 3px;
  padding-inline: 12px 8px;
  font-size: 11px;
  letter-spacing: .02em;
  color: rgba(255, 255, 255, .82);
  background: linear-gradient(to right, transparent, rgba(0, 0, 0, .55) 35%);
  text-decoration: none;
}
.hero-credit:hover,
.hero-credit:focus-visible { color: #fff; text-decoration: underline; }
.sheet-hero img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Is it open? The one question worth answering above the fold. */
.sheet-hours {
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 9px 12px;
  border-radius: var(--radius-sm);
  font-size: 13px;
  font-weight: 600;
  margin-bottom: 10px;
}
.sheet-hours-open   { background: var(--walk-bg); color: var(--walk-text); }
.sheet-hours-soon   { background: var(--gold-bg); color: var(--gold-text); }
.sheet-hours-closed { background: var(--paper2); color: var(--muted); }
/* A guess must never look like a fact. The pipeline marks assumed hours with
   `hoursSource: 'default'`; this is what that looks like on screen. */
.sheet-hours-guess {
  margin-inline-start: auto;
  font-size: 11px;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  opacity: 0.7;
}

/* What to order. The data has no per-restaurant review and never will, but it
   knows what kind of place this is, and that is the answerable question. */
.sheet-food {
  background: var(--food-bg);
  border-radius: var(--radius-sm);
  padding: 12px 14px;
  margin-bottom: 12px;
}
.sheet-food-head {
  display: flex;
  align-items: baseline;
  gap: 7px;
  flex-wrap: wrap;
  color: var(--food-text);
  font-weight: 700;
  font-size: 13.5px;
  margin-bottom: 6px;
}
.sheet-food-local { font-weight: 500; opacity: 0.75; }
.sheet-food-price { margin-inline-start: auto; font-size: 11.5px; font-weight: 600; opacity: 0.8; }
.sheet-food-why,
.sheet-food-order,
.sheet-food-how {
  margin: 0 0 6px;
  font-size: 13px;
  line-height: 1.55;
  color: var(--ink);
}
.sheet-food-how { color: var(--text-secondary); font-size: 12.5px; margin-bottom: 0; }
.sheet-food p:last-child { margin-bottom: 0; }

/* Read more, from the source the description came from. */
.sheet-links {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 12px;
}
.sheet-link {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 9px 12px;
  min-height: 40px;
  box-sizing: border-box;
  border-radius: var(--radius-sm);
  background: var(--accent-bg);
  color: var(--accent);
  font-size: 12.5px;
  font-weight: 600;
  text-decoration: none;
}

/* Place text is English-only in the data. Saying so is more honest than
   silently serving English inside a Spanish interface. */
.sheet-translate-row {
  display: flex;
  align-items: center;
  gap: 10px;
  margin: -6px 0 12px;
  flex-wrap: wrap;
}
.sheet-src-lang {
  font-size: 11.5px;
  color: var(--muted);
}
.sheet-translate-btn {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 7px 12px;
  min-height: 36px;
  border: 1px solid var(--accent);
  border-radius: 18px;
  background: none;
  color: var(--accent);
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
}
.sheet-translated {
  font-size: 11px;
  color: var(--muted);
  margin: -6px 0 12px;
  font-style: italic;
}

.sheet-contact {
  display: flex;
  flex-direction: column;
  gap: 5px;
  margin-top: 12px;
  font-size: 12.5px;
  color: var(--text-secondary);
  line-height: 1.5;
}
.sheet-contact a { color: var(--transport); text-decoration: none; }

/* ============================================================
   Header clock
   ============================================================
   Home time beside destination time, replacing a hardcoded Spain/Japan pair.
   A button rather than a label because it is the way into the setting that
   controls it: whoever notices the wrong home city is exactly who wants to
   change it.
*/
.header-clock {
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 8px 10px;
  min-height: 40px;
  border: none;
  background: none;
  border-radius: 14px;
  font: inherit;
  font-size: 11.5px;
  font-weight: 600;
  color: var(--muted);
  white-space: nowrap;
  letter-spacing: 0.02em;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.header-clock:active { background: var(--accent-bg); }

/* ============================================================
   Touch targets
   ============================================================
   `.filter-chip` is the control this app is made of: category and region
   filters, sorting, day selection, interest weighting, pacing, budget posture,
   map layers. It was 6px of padding at 12px type, about 28px tall, against a
   44px minimum - in an app used one-handed, walking, in sunlight.

   The chip itself grows rather than gaining an invisible overlay. A
   pseudo-element hit area was the first attempt and is wrong here: these chips
   wrap onto several lines in the planner, and a 44px target on a 36px chip
   would overlap the row above and steal its taps.

   40px is the compromise: comfortably tappable, and it keeps a four-row
   interest picker on one screen.
*/
.filter-chip {
  padding: 10px 14px;
  font-size: 13px;
  min-height: 40px;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  line-height: 1.2;
}
/* Wrapping rows need vertical breathing room the horizontal gap does not give. */
.filter-row { gap: 8px; padding: 8px 16px; }

/* Opting out is explicit, and only where a row is genuinely dense: the map's
   Plan B strip and the day scrubber, where every chip is one of twenty. */
.filter-chip.chip-compact {
  padding: 7px 11px;
  font-size: 12px;
  min-height: 34px;
}

/* ============================================================
   Map filter sheet
   ============================================================
   The map overlay used to stack six filter rows over the map: search,
   category, subcategory, day, Plan B and district. On a 640px viewport that
   is ~250px of chrome covering the thing you opened the map to see, and one
   of the six could never return a result.

   Two rows stay pinned - search and the day scrubber, which is what you use
   while looking at the map. The rest lives here, behind one button that shows
   how many filters are active.
*/
.map-filter-sheet {
  max-height: 82vh;
  padding-bottom: 28px;
}
.map-filter-head {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 4px 0 14px;
  font-size: 16px;
  border-bottom: 1px solid var(--border);
  margin-bottom: 14px;
}
.map-filter-section { margin-bottom: 18px; }
.map-filter-title {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 8px;
}
.map-filter-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

/*
 * Thumbnail beside a highlight on the trip result screen and in the day view.
 * Wider than tall: these are photographs of buildings and landscapes, and a
 * 4:3 crop keeps the subject rather than the sky.
 */
.highlight-thumb {
  flex: none;
  width: 76px;
  height: 57px;
  border-radius: 7px;
  overflow: hidden;
  background: var(--paper2);
}
.highlight-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Photo in the day timeline, in the slot the activity glyph occupies. */
.day-card-thumb {
  flex-shrink: 0;
  width: 36px;
  height: 36px;
  border-radius: 8px;
  overflow: hidden;
  background: var(--paper2);
}
.day-card-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* ------------------------------------------------------- foldable settings
 *
 * The More page is 3,733 px tall and 2,700 of that is settings. The class is
 * added by More.js at render rather than written into the markup, so this
 * styles only the sections that opted in - `.settings-section-title` is used
 * on other pages too, and a rule on the bare class would fold the wizard.
 */
.settings-foldable > .settings-section-title {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  cursor: pointer;
  /* The heading is the tap target, so it has to be one: 11px of uppercase
     label is about 15px tall on its own. */
  min-height: 44px;
  margin-bottom: 0;
  border-bottom: 1px solid var(--border);
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}
.settings-foldable > .settings-section-title::after {
  content: '';
  width: 7px;
  height: 7px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(45deg) translate(-2px, -2px);
  opacity: .65;
  transition: transform 160ms ease;
  flex: none;
}
.settings-foldable.open > .settings-section-title::after {
  transform: rotate(-135deg) translate(-2px, -2px);
}
.settings-foldable > .settings-section-title:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
/* !important because some rows carry an inline display:flex, which beat this
   and showed a folded section's last row under its closed header. */
.settings-foldable:not(.open) > *:not(.settings-section-title) { display: none !important; }
.settings-foldable.open > .settings-section-title { margin-bottom: 12px; }
/* A folded section is one row, so the 24px gap between sections reads as a
   gap in a list rather than as separation between blocks. */
.settings-foldable:not(.open) { margin-bottom: 0; }

@media (prefers-reduced-motion: reduce) {
  .settings-foldable > .settings-section-title::after { transition: none; }
}

/* Settings (More.js): three groups of rows. A folded section reads as a row -
   its name, its current value, a chevron - rather than as a shouted label. */
.settings-group { margin-bottom: 22px; }
.settings-group-title {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 0 0 4px;
}
.settings-group .settings-foldable > .settings-section-title {
  font-size: 15px;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  color: var(--ink);
}
.settings-group .settings-foldable { margin-bottom: 0; }
.settings-group .settings-foldable.open { margin-bottom: 14px; }
.settings-value {
  margin-inline-start: auto;
  font-size: 14px;
  font-weight: 400;
  color: var(--muted);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}

/* Kit (Kit.js): the trip's tools as tiles that say something live. */
.kit-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
}
.kit-tile {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 4px;
  min-height: 104px;
  padding: 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--white);
  color: var(--ink);
  text-decoration: none;
  text-align: start;
  font: inherit;
  cursor: pointer;
}
.kit-tile:focus-visible,
.kit-emergency:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.kit-tile-icon {
  width: 36px;
  height: 36px;
  border-radius: 10px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 4px;
}
.kit-tile-title { font-weight: 600; font-size: 14px; line-height: 1.3; }
.kit-tile-line { font-size: 12.5px; color: var(--text-secondary); line-height: 1.35; }
/* Emergency leads, and is the one red thing on the tab. The red marks it -
   the border and the icon; the text stays in the text colours, because the
   status red is under 4.5:1 on a white card. */
.kit-emergency {
  display: flex;
  align-items: center;
  gap: 12px;
  min-height: 64px;
  padding: 14px;
  border: 1.5px solid var(--color-status-error);
  border-radius: var(--radius);
  background: var(--color-status-error-bg);
  color: var(--ink);
  text-decoration: none;
}
.kit-emergency-icon {
  width: 40px;
  height: 40px;
  flex: none;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--color-status-error);
  background: var(--white);
}

/* ---- Planning progress (components/PlanProgress.js) ----------------------
   The journey moves by transform only, which the compositor animates on its
   own: it keeps going while the planner holds the page. */
.plan-progress {
  position: fixed; inset: 0; z-index: 2000;
  display: flex; align-items: center; justify-content: center;
  padding: 24px; background: rgba(0, 0, 0, 0.38);
  opacity: 0; transition: opacity 0.22s var(--ease-smooth, ease);
}
.plan-progress.visible { opacity: 1; }
.plan-progress-card {
  width: min(360px, 100%); background: var(--paper); color: var(--ink);
  border-radius: var(--radius); box-shadow: var(--shadow-lg); padding: 22px 20px 18px;
}
.pp-journey { position: relative; height: 30px; margin: 2px 4px 16px; }
.pp-track {
  position: absolute; left: 8px; right: 8px; top: 14px;
  border-top: 2px dashed var(--border-strong, var(--border));
}
.pp-stop {
  position: absolute; top: 9px; width: 12px; height: 12px; border-radius: 50%;
  background: var(--paper); border: 2px solid var(--accent);
}
.pp-stop-a { left: 0; }
.pp-stop-b { right: 0; }
.pp-lane { position: absolute; left: 0; top: 0; width: calc(100% - 30px); height: 30px; }
.pp-mover {
  position: absolute; inset: 0; will-change: transform;
  animation: pp-move 2.6s ease-in-out infinite alternate;
}
.pp-traveller {
  position: absolute; left: 0; top: 0; width: 30px; height: 30px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--accent); color: #fff; box-shadow: var(--shadow-md);
}
@keyframes pp-move { from { transform: translateX(0); } to { transform: translateX(100%); } }
.pp-title { margin: 0 0 12px; font-size: 17px; font-weight: 700; text-wrap: balance; }
.pp-stages { list-style: none; margin: 0; padding: 0; display: grid; gap: 9px; }
.pp-stages li {
  display: flex; align-items: center; gap: 10px; font-size: 13.5px;
  color: var(--muted); transition: color 0.2s;
}
.pp-stages li.active, .pp-stages li.done { color: var(--ink); }
.pp-mark {
  position: relative; flex: none; width: 16px; height: 16px; border-radius: 50%;
  border: 2px solid var(--border-strong, var(--border));
}
.pp-stages li.active .pp-mark {
  border-color: var(--accent); border-right-color: transparent;
  animation: pp-spin 0.8s linear infinite;
}
.pp-stages li.done .pp-mark { background: var(--accent); border-color: var(--accent); }
.pp-stages li.done .pp-mark::after {
  content: ''; position: absolute; left: 4px; top: 1px; width: 4px; height: 8px;
  border: solid #fff; border-width: 0 2px 2px 0; transform: rotate(45deg);
}
@keyframes pp-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .pp-mover, .pp-stages li.active .pp-mark { animation: none; }
}

/* ── Trip dates on a calendar (components/DateRange.js) ──
   One month on a phone, two side by side once there is room; the trip is a
   band from its first day to its last, rounded at each end. */
.date-range { position: relative; margin-bottom: 8px; }
.dr-bar {
  position: absolute; inset-inline: 0; top: 0; z-index: 1;
  display: flex; justify-content: space-between; pointer-events: none;
}
.dr-nav {
  pointer-events: auto; width: 44px; height: 44px; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  border: 1px solid var(--border); border-radius: 50%;
  background: var(--paper); color: var(--ink); cursor: pointer;
}
.dr-nav:disabled { opacity: .35; cursor: default; }
.dr-nav:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.dr-months {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 18px 32px;
}
.dr-title {
  min-height: 44px; padding: 0 50px;
  display: flex; align-items: center; justify-content: center; flex-wrap: wrap; gap: 4px 8px;
  font-weight: 700; font-size: 15px; text-align: center; text-wrap: balance;
}
.dr-mark { font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: 10px; white-space: nowrap; }
.dr-mark-best { background: var(--accent-bg); color: var(--accent); }
.dr-mark-avoid { background: var(--gold-bg); color: var(--gold-text); }
.dr-grid { display: flex; flex-direction: column; gap: 3px; margin-top: 4px; }
.dr-row { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); }
.dr-row > [role="gridcell"] { display: flex; min-width: 0; }
.dr-wd { text-align: center; font-size: 11px; font-weight: 700; color: var(--muted); padding: 4px 0; }
.dr-day {
  flex: 1; min-width: 0; height: 42px; padding: 0;
  border: none; border-radius: 0; background: transparent; color: var(--ink);
  font: inherit; font-size: 14px; font-variant-numeric: tabular-nums; cursor: pointer;
}
.dr-day:disabled { color: var(--muted); opacity: .45; cursor: default; }
/* Today is ringed, unless the trip's band is already drawn over it. */
.dr-day.is-today { box-shadow: inset 0 0 0 1.5px var(--border-strong); border-radius: 21px; }
.dr-day.in-range { background: var(--accent-bg); border-radius: 0; box-shadow: none; }
.dr-day.is-start, .dr-day.is-end {
  background: var(--accent-fill); color: #fff; font-weight: 700; border-radius: 0; box-shadow: none;
}
.dr-day.is-start { border-start-start-radius: 21px; border-end-start-radius: 21px; }
.dr-day.is-end { border-start-end-radius: 21px; border-end-end-radius: 21px; }
.dr-day:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; position: relative; z-index: 1; }
@media (hover: hover) {
  .dr-day:not(:disabled):not(.is-start):not(.is-end):hover { background: var(--paper2); border-radius: 21px; }
}
.dr-hint { margin-top: 8px; font-size: 12px; color: var(--muted); text-align: center; }
.dr-sum {
  margin-top: 10px; padding: 8px 8px 8px 12px;
  display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 4px 10px;
  background: var(--paper2); border-radius: var(--radius-sm); font-size: 13px;
}
.dr-clear {
  min-height: 40px; padding: 6px 10px; border: none; background: none;
  color: var(--accent); font: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
}

/* ── A time, with a step either side (components/TimeField.js) ── */
.time-field { display: flex; flex-direction: column; gap: 8px; }
.tf-row { display: flex; align-items: stretch; gap: 6px; }
.tf-step {
  flex: none; width: 44px; min-height: 44px; padding: 0;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--paper); color: var(--ink); font: inherit; font-size: 20px; line-height: 1; cursor: pointer;
}
.tf-step:active { transform: scale(.95); }
.tf-step:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.time-field .tf-input {
  flex: 1; min-width: 0; min-height: 44px; padding: 8px 10px;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--paper); color: var(--ink); font: inherit; font-size: 16px;
  font-variant-numeric: tabular-nums; text-align: center; box-sizing: border-box;
}
.tf-chips { display: flex; flex-wrap: wrap; gap: 6px; }
.time-field .tf-chip { flex-shrink: 1; min-height: 36px; padding: 6px 11px; font-size: 12px; }
.tf-chip-time { opacity: .7; font-variant-numeric: tabular-nums; }
.tf-chip.active .tf-chip-time { opacity: .9; }

/* ── Swipe a few places (components/SwipeDeck.js, NewTrip.js) ──
   Cards are photographs, so their colours are a photograph's whatever the
   theme: white words on a dark fade, and a dark panel while a photo is
   missing. Everything around them follows the theme. */
.swipe-deck { display: flex; flex-direction: column; align-items: center; gap: 12px; }
/* As tall as the screen allows with the heading above and the buttons and the
   wizard's pinned bar below all still in view: about 440px of a phone is
   theirs. svh where it exists, so a browser's collapsing toolbar is not
   counted as room. */
.swipe-stage {
  position: relative;
  width: min(100%, 360px);
  height: clamp(260px, calc(100vh - 440px), 460px);
  height: clamp(260px, calc(100svh - 440px), 460px);
}
.swipe-stack { position: absolute; inset: 0; }
.swipe-card {
  position: absolute; inset: 0;
  border-radius: 18px; overflow: hidden;
  background: #222b36; color: #fff;
  box-shadow: 0 10px 28px rgba(16, 22, 30, 0.22), 0 2px 6px rgba(16, 22, 30, 0.12);
  touch-action: none; user-select: none; -webkit-user-select: none; cursor: grab;
  transform-origin: 50% 90%;
  transition: transform 300ms var(--ease-out-expo), opacity 220ms ease;
}
.swipe-card[data-depth="0"] { z-index: 3; }
/* The card behind comes forward as the top one is dragged away (--lift 0..1). */
.swipe-card[data-depth="1"] {
  z-index: 2; pointer-events: none;
  transform: translateY(calc(12px * (1 - var(--lift, 0)))) scale(calc(0.95 + 0.05 * var(--lift, 0)));
}
.swipe-card[data-depth="2"] { z-index: 1; pointer-events: none; transform: translateY(24px) scale(0.9); opacity: 0.6; }
.swipe-card[data-depth="gone"] {
  z-index: 4; pointer-events: none;
  transition: transform 280ms ease-in, opacity 280ms ease-in; opacity: 0;
}
.swipe-card.is-dragging { transition: none; cursor: grabbing; }
.swipe-card-fallback {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px;
  padding-bottom: 30%;
  background: linear-gradient(160deg, #3b4859 0%, #1f2731 100%);
  color: rgba(255, 255, 255, 0.5);
  font-size: 13px; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase;
}
.swipe-card-img {
  position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; opacity: 0;
  transition: opacity 240ms ease;
  pointer-events: none; -webkit-user-drag: none;
}
.swipe-card-img.is-loaded { opacity: 1; }
.swipe-card-body {
  position: absolute; inset: auto 0 0 0;
  padding: 56px 18px 18px;
  background: linear-gradient(to top, rgba(8, 12, 18, 0.9) 0%, rgba(8, 12, 18, 0.62) 55%, rgba(8, 12, 18, 0) 100%);
}
.swipe-card-name { margin: 0 0 4px; font-size: 22px; line-height: 1.2; font-weight: 700; text-wrap: balance; }
.swipe-card-line {
  margin: 0 0 6px; font-size: 14px; opacity: 0.92;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.swipe-card-where {
  margin: 0; display: flex; align-items: center; gap: 5px;
  font-size: 13px; opacity: 0.85;
}
.swipe-card-where span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.swipe-stamp {
  position: absolute; top: 24px;
  padding: 4px 10px;
  border: 3px solid currentColor; border-radius: 10px;
  background: rgba(8, 12, 18, 0.25);
  font-size: 24px; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase;
  opacity: 0; pointer-events: none; white-space: nowrap;
}
.swipe-stamp--like { inset-inline-start: 18px; color: #4ade80; transform: rotate(-12deg); }
.swipe-stamp--pass { inset-inline-end: 18px; color: #fb7185; transform: rotate(12deg); }
.swipe-stamp--must { left: 50%; top: 34%; color: #fcd34d; transform: translateX(-50%) rotate(-5deg); }
.swipe-done {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 8px;
  padding: 20px; overflow-y: auto; text-align: center;
  border: 1px solid var(--border); border-radius: 18px; background: var(--paper2);
}
.swipe-done-icon { color: var(--accent); }
.swipe-done-title { margin: 0; font-size: 20px; font-weight: 700; color: var(--ink); }
.swipe-done-tally { margin: 0 0 4px; font-size: 14px; color: var(--text-secondary); }
.swipe-done-lean { margin: 0; font-size: 14px; color: var(--ink); }
.swipe-done-next { margin: 8px 0 4px; font-size: 13px; line-height: 1.5; color: var(--muted); }
.swipe-again { min-height: 44px; padding: 8px 14px; font-size: 13px; }
.swipe-meta {
  width: min(100%, 360px);
  display: flex; align-items: center; gap: 10px;
  font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums;
}
.swipe-count { flex: none; min-width: 56px; }
.swipe-progress { flex: 1; height: 4px; border-radius: 2px; background: var(--border); overflow: hidden; }
.swipe-progress > span { display: block; height: 100%; width: 0; background: var(--accent); transition: width 250ms ease; }
.swipe-undo {
  flex: none; display: inline-flex; align-items: center; gap: 4px;
  min-height: 40px; padding: 4px 8px;
  border: none; background: none; color: var(--accent);
  font: inherit; font-size: 13px; font-weight: 600; cursor: pointer;
}
.swipe-undo:disabled { color: var(--muted); opacity: 0.5; cursor: default; }
.swipe-actions { display: flex; align-items: flex-start; justify-content: center; gap: 22px; }
.swipe-btn {
  display: flex; flex-direction: column; align-items: center; gap: 4px;
  padding: 0; border: none; background: none; color: var(--muted);
  font: inherit; font-size: 11px; font-weight: 600; cursor: pointer;
}
.swipe-btn-face {
  width: 60px; height: 60px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  background: var(--white); border: 1px solid var(--border);
  box-shadow: var(--shadow-md);
  transition: transform 140ms ease;
}
.swipe-btn:active .swipe-btn-face { transform: scale(0.9); }
.swipe-btn:focus-visible { outline: none; }
.swipe-btn:focus-visible .swipe-btn-face { outline: 3px solid var(--accent); outline-offset: 2px; }
.swipe-btn--pass { color: var(--hours-late); }
.swipe-btn--like { color: var(--walk); }
.swipe-btn--must { color: var(--gold); }
.swipe-btn--must .swipe-btn-face { width: 50px; height: 50px; margin-top: 5px; }
.swipe-btn-label { color: var(--muted); }
/* Keys are worth mentioning only where there is a keyboard. */
.swipe-hint { display: none; margin: 0; font-size: 12px; color: var(--muted); }
@media (hover: hover) and (pointer: fine) {
  .swipe-hint { display: block; }
}
.swipe-loading, .swipe-empty {
  display: flex; align-items: center; justify-content: center;
  min-height: 200px; padding: 20px; text-align: center;
  border: 1px dashed var(--border); border-radius: 18px;
  font-size: 13px; line-height: 1.5; color: var(--muted);
}
/* The interests the swipes picked, on the step after (NewTrip.js swipeNote). */
.swipe-from {
  display: flex; align-items: flex-start; gap: 8px;
  margin: 0 0 14px; padding: 10px 12px;
  border-radius: var(--radius-sm); background: var(--accent-bg);
  font-size: 13px; line-height: 1.45; color: var(--ink);
}
.swipe-from svg { flex: none; margin-top: 2px; color: var(--accent); }
/* ...and what they changed, on the finished plan. */
.swipe-outcome { margin: 14px 0 4px; }
.swipe-outcome-row {
  display: flex; align-items: center; gap: 8px;
  padding: 7px 0; border-top: 1px solid var(--border); font-size: 13.5px;
}
.swipe-outcome-row svg { flex: none; color: var(--gold); }
.swipe-outcome-day { margin-inline-start: auto; font-size: 12px; color: var(--muted); white-space: nowrap; }
.swipe-outcome-lean { padding: 7px 0 0; border-top: 1px solid var(--border); font-size: 13px; color: var(--text-secondary); }
/* ...and in Edit trip, where a must-see is taken back or the swipes cleared
   (trip-settings.js swipesBlock). A taken-back row stays put, as a like. */
.swipe-edit-tally { margin: 0 0 3px; font-size: 12.5px; color: var(--text-secondary); }
.swipe-edit-lean { margin: 0 0 8px; font-size: 13px; line-height: 1.45; color: var(--ink); }
.swipe-edit-list { margin-bottom: 10px; }
.swipe-edit-row {
  display: flex; align-items: center; gap: 9px;
  padding: 6px 0; border-top: 1px solid var(--border); font-size: 13.5px;
}
.swipe-edit-row:last-child { border-bottom: 1px solid var(--border); }
.swipe-edit-row > svg { flex: none; color: var(--gold); }
.swipe-edit-name { flex: 1; min-width: 0; overflow-wrap: anywhere; color: var(--ink); }
.swipe-edit-was { display: block; font-size: 12px; color: var(--muted); }
.swipe-edit-row.is-liked > svg { color: var(--walk); }
.swipe-edit-row.is-liked .swipe-edit-name { color: var(--text-secondary); }
.swipe-edit-row .filter-chip { flex: none; padding: 6px 11px; font-size: 12.5px; }
.swipe-edit-clear { padding: 8px 12px; }
.swipe-edit-cleared {
  display: flex; align-items: center; gap: 10px;
  padding: 10px 12px; border-radius: var(--radius-sm); background: var(--accent-bg);
  font-size: 13px; line-height: 1.45; color: var(--ink);
}
.swipe-edit-cleared .filter-chip { flex: none; }
@media (prefers-reduced-motion: reduce) {
  .swipe-card, .swipe-card[data-depth="gone"], .swipe-card-img,
  .swipe-progress > span, .swipe-btn-face { transition: none; }
}
/* ── Home Page ── */
.home-hero {
  position: relative;
  overflow: hidden;
  background: linear-gradient(135deg, var(--accent-fill) 0%, #8a1a2a 100%);
  color: white;
  padding: 24px 20px;
  text-align: center;
  margin: 0 -1px;
}

.home-hero::before {
  content: '';
  position: absolute;
  top: -40px;
  right: -40px;
  width: 160px;
  height: 160px;
  background: rgba(255,255,255,0.08);
  border-radius: 50%;
  filter: blur(40px);
  pointer-events: none;
}

.home-hero::after {
  content: '';
  position: absolute;
  bottom: -30px;
  left: -30px;
  width: 120px;
  height: 120px;
  background: rgba(186, 148, 85, 0.15);
  border-radius: 50%;
  filter: blur(40px);
  pointer-events: none;
}

.home-hero .trip-title {
  font-size: 28px;
  font-weight: 700;
  line-height: 1.1;
  margin-bottom: 4px;
  text-shadow: 0 1px 3px rgba(0,0,0,0.8), 0 4px 12px rgba(0,0,0,0.4);
}

.home-hero .trip-subtitle {
  font-size: 14px;
  opacity: 0.9;
  font-weight: 400;
  text-shadow: 0 1px 3px rgba(0,0,0,0.8), 0 2px 8px rgba(0,0,0,0.4);
}

.home-hero .countdown {
  margin-top: 16px;
  font-size: 42px;
  font-weight: 700;
  line-height: 1;
  text-shadow: 0 2px 4px rgba(0,0,0,0.8), 0 4px 16px rgba(0,0,0,0.5);
}

.home-hero .countdown-label {
  font-size: 12px;
  text-transform: uppercase;
  text-shadow: 0 1px 3px rgba(0,0,0,0.8), 0 2px 8px rgba(0,0,0,0.4);
  letter-spacing: 0.1em;
  opacity: 0.9;
  margin-top: 4px;
}

.home-hero .current-day {
  margin-top: 12px;
  background: rgba(255,255,255,0.15);
  border-radius: var(--radius);
  padding: 12px;
}

.home-hero .current-day-num {
  font-size: 32px;
  font-weight: 700;
}

.home-hero .current-day-title {
  font-size: 14px;
  opacity: 0.9;
}

.home-section {
  padding: 0 16px;
}

.home-section-title {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
  padding: 16px 0 8px;
}

.home-quick-links {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 8px;
  padding: 0 16px 16px;
}

.quick-link {
  background: var(--white);
  border: none;
  border-radius: var(--radius);
  padding: 12px 8px;
  text-align: center;
  cursor: pointer;
  box-shadow: 0 0 0 1px rgba(0,0,0,0.04), 0 1px 3px rgba(0,0,0,0.06);
  transition: transform 100ms ease, box-shadow 100ms ease;
  text-decoration: none;
  color: var(--ink);
  -webkit-tap-highlight-color: transparent;
}

.quick-link:hover { text-decoration: none; }
.quick-link:active { transform: scale(0.97); box-shadow: var(--shadow-md); }

.quick-link .ql-icon {
  font-size: 28px;
  margin-bottom: 6px;
}

.quick-link .ql-label {
  font-size: 11px;
  font-weight: 600;
  color: var(--ink);
  line-height: 1.3;
}

/* ── Day View ── */
.day-view {
  padding: 16px;
}

.day-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 4px 8px;
  margin-bottom: 16px;
}
/* With the phone's text at its largest, the region, weather and three
   buttons no longer fit beside the title; they wrap under it instead of
   running off the screen. */
.day-header-left { min-width: 0; flex: 1 1 160px; }
.day-header-tools { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 8px; margin-inline-start: auto; }

.day-header-left h2 {
  font-size: 20px;
  font-weight: 700;
  color: var(--ink);
  line-height: 1.2;
}

.day-header-left .day-date {
  font-size: 12px;
  color: var(--muted);
  margin-top: 2px;
}

.day-hotel {
  display: flex;
  align-items: center;
  gap: 8px;
  background: var(--gold-bg);
  border: 1px solid var(--gold-light);
  border-radius: var(--radius-sm);
  padding: 8px 12px;
  margin-bottom: 16px;
  font-size: 13px;
}

.day-hotel-icon { font-size: 16px; }
.day-hotel-name { font-weight: 600; color: var(--ink); }

.day-nav {
  display: flex;
  justify-content: space-between;
  padding: 12px 0;
  margin-top: 8px;
}

.day-nav-btn {
  display: flex;
  align-items: center;
  gap: 4px;
  background: none;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 8px 14px;
  font-size: 13px;
  font-weight: 500;
  color: var(--ink-light);
  cursor: pointer;
  font-family: inherit;
}

.day-nav-btn:active {
  background: var(--accent-bg);
  border-color: var(--accent);
  color: var(--accent);
  transform: scale(0.97);
}

.day-nav-btn:disabled {
  opacity: 0.3;
  cursor: default;
}

/* ── Day List ── */
.day-list {
  padding: 16px;
}

.day-list-item {
  display: flex;
  gap: 12px;
  padding: 12px;
  background: var(--white);
  border: none;
  border-radius: var(--radius-sm);
  margin-bottom: 8px;
  cursor: pointer;
  box-shadow: 0 0 0 1px rgba(0,0,0,0.04), 0 1px 3px rgba(0,0,0,0.06);
  transition: transform 100ms ease, box-shadow 100ms ease;
  text-decoration: none;
  color: inherit;
  -webkit-tap-highlight-color: transparent;
}

.day-list-item:hover { text-decoration: none; }
.day-list-item:active { transform: scale(0.98); box-shadow: var(--shadow-md); }

.day-list-item.today { border-color: var(--gold); }

.day-list-num {
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--accent-bg);
  color: var(--accent);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 18px;
  font-weight: 700;
}

.day-list-item.today .day-list-num {
  background: var(--accent-fill);
  color: white;
}

.day-list-info { flex: 1; min-width: 0; }

.day-list-title {
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
}

.day-list-date {
  font-size: 12px;
  color: var(--muted);
}

.day-list-preview {
  font-size: 12px;
  color: var(--ink-light);
  margin-top: 2px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.day-list-item.day-past { opacity: 0.6; }
.day-list-item.day-past .day-list-num { background: var(--walk-bg, #f0f0f0); color: var(--walk, #888); }

/* ── Explore: the map and the list, one surface (Explore.js) ──
   The search bar and the map stay pinned under the header; the list is a
   sheet that scrolls up over the map until it fills the screen. */
.explore2 { --explore-bar-h: 104px; position: relative; }
.explore2-bar {
  position: sticky;
  top: var(--header-total);
  z-index: 3;
  background: var(--paper);
  padding: 10px 16px 8px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.explore2-search { display: flex; gap: 8px; align-items: center; }
.explore2-search .search-wrap { flex: 1; min-width: 0; }
.explore2-view {
  flex: none;
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--white);
  color: var(--ink);
  cursor: pointer;
}
.explore2-chips {
  display: flex;
  gap: 6px;
  overflow-x: auto;
  scrollbar-width: none;
  margin: 0 -16px;
  padding: 0 16px 2px;
}
.explore2-chips::-webkit-scrollbar { display: none; }
.explore2-chip { flex: none; display: inline-flex; align-items: center; gap: 5px; white-space: nowrap; min-height: 36px; }
.explore2-chip-n { opacity: 0.7; font-size: 11px; font-variant-numeric: tabular-nums; }
.explore2-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--accent); display: inline-block; }

.explore2-map-wrap {
  position: sticky;
  top: calc(var(--header-total) + var(--explore-bar-h));
  /* Its own stacking context: Leaflet's panes (z-index 400 and up) stay under
     the sheet, the bar and the header instead of painting over them. */
  z-index: 0;
  isolation: isolate;
  height: 42vh;
  min-height: 220px;
}
.explore2-map { position: absolute; inset: 0; background: var(--paper2); }
.explore2-fullmap {
  position: absolute;
  right: 12px;
  bottom: 30px;
  z-index: 500;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  min-height: 36px;
  padding: 0 12px;
  border-radius: 999px;
  background: var(--white);
  color: var(--ink);
  font-size: 12.5px;
  font-weight: 600;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.18);
  text-decoration: none;
}
.explore2-fullmap:hover { text-decoration: none; }

.explore2-sheet {
  position: relative;
  z-index: 2;
  margin-top: -18px;
  background: var(--paper);
  border-radius: 18px 18px 0 0;
  box-shadow: 0 -6px 20px -12px rgba(0, 0, 0, 0.35);
  padding: 6px 16px 24px;
  /* Tall enough to cover the map entirely once scrolled up. */
  min-height: calc(100vh - var(--header-total) - var(--explore-bar-h) - var(--nav-height));
}
.explore2-grab { width: 38px; height: 4px; border-radius: 2px; background: var(--border); margin: 4px auto 10px; }
.explore2-head { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; margin-bottom: 4px; }
.explore2-head h2 { font-size: 17px; margin: 0; text-wrap: balance; }
.explore2-count { flex: none; font-size: 13px; color: var(--text-secondary); font-variant-numeric: tabular-nums; }

.explore2-filters { display: flex; flex-direction: column; gap: 10px; padding: 8px 0 12px; border-bottom: 1px solid var(--border); }
.explore2-filter-row { display: flex; flex-direction: column; gap: 4px; }
.explore2-filter-label { font-size: 12px; font-weight: 600; color: var(--text-secondary); }
.explore2-filter-row .filter-row { padding: 0; }

.explore2-list { list-style: none; margin: 0; padding: 0; }
.explore2-row { display: flex; align-items: center; gap: 8px; border-bottom: 1px solid var(--border); }
.explore2-open {
  flex: 1;
  min-width: 0;
  min-height: 64px;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 10px 0;
  background: none;
  border: 0;
  font: inherit;
  color: inherit;
  text-align: start;
  cursor: pointer;
}
.explore2-row-text { display: flex; flex-direction: column; min-width: 0; gap: 2px; }
.explore2-row-name { font-weight: 600; font-size: 15px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.explore2-row-sub { font-size: 13px; color: var(--text-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.explore2-row-sub svg { vertical-align: -2px; }
.explore2-hours { font-size: 12.5px; color: var(--text-secondary); }
/* The state is in the dot as well as the words: green is too faint on paper
   to carry text on its own. */
.explore2-hours::before {
  content: '';
  display: inline-block;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  margin-inline-end: 6px;
  vertical-align: 1px;
  background: var(--muted);
}
.explore2-hours.open::before { background: var(--walk); }
.explore2-hours.soon::before { background: var(--gold); }
.explore2-add {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  min-height: 36px;
  padding: 0 11px;
  border: 1px solid var(--accent);
  border-radius: 999px;
  background: transparent;
  color: var(--accent);
  font: inherit;
  font-size: 12.5px;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
}
.explore2-add:disabled { border-color: var(--border); color: var(--text-secondary); cursor: default; }
.explore2-more { text-align: center; padding: 16px; }
.no-trip-note {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin: 8px 0 4px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  font-size: 14px;
  font-weight: 600;
}
.explore2-empty { text-align: center; padding: 32px 16px; color: var(--muted); }
.explore2-empty-title { font-size: 15px; font-weight: 600; margin-top: 8px; color: var(--ink); }
.explore2-empty-sub { font-size: 13px; margin-top: 4px; }

/* The plan's stops on the map: today's numbered, or each day's number. */
.explore2-pin span {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: var(--accent-fill);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  border: 2px solid var(--white);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
  box-sizing: border-box;
}
.explore2-open:focus-visible,
.explore2-add:focus-visible,
.explore2-view:focus-visible,
.explore2-fullmap:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }


/* ── Phrases Page ── */
.phrases-page { padding: 12px 0; }
.phrase-category { padding: 0 16px; margin-bottom: 16px; }
.phrase-category-title {
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
  border-bottom: 1px solid var(--border);
  padding-bottom: 4px;
  margin-bottom: 8px;
}

.phrase-list { display: flex; flex-direction: column; gap: 8px; }

/* ── Tips Page ── */
.tips-page { padding: 12px 0; }

.tip-section { margin-bottom: 16px; }

.tip-section-title {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
  padding: 0 16px 8px;
}

/* ── Emergency Page ── */
.emergency-page { padding: 16px; }
.emergency-list { display: flex; flex-direction: column; gap: 10px; }

.emergency-title {
  font-size: 18px;
  font-weight: 700;
  color: var(--accent);
  margin-bottom: 12px;
}

/* ── Map Page ── */
.map-page {
  position: relative;
  padding: 0;
  height: calc(100vh - var(--header-total) - var(--nav-height));
  overflow: hidden;
}

.map-container-fullscreen {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
  will-change: transform;
}

.map-filters-overlay {
  position: absolute;
  top: 8px;
  left: 8px;
  right: 8px;
  z-index: 1000;
  display: flex;
  flex-direction: column;
  gap: 4px;
  pointer-events: none;
}

.map-filters-overlay .filter-row {
  pointer-events: auto;
  background: var(--glass-bg);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border-radius: 16px;
  padding: 6px 8px;
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
  /* Remove edge fade mask, the glass pill contains the content */
  -webkit-mask-image: none;
  mask-image: none;
}

.map-fab {
  position: absolute;
  bottom: 16px;
  right: 16px;
  z-index: 1000;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--white);
  border: none;
  box-shadow: 0 2px 8px rgba(0,0,0,0.2);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--accent);
  transition: transform 100ms ease;
}
.map-fab:active { transform: scale(0.9); }

.map-itinerary-link {
  position: absolute;
  bottom: 16px;
  left: 16px;
  z-index: 1000;
  background: var(--white);
  color: var(--accent, #c93545);
  padding: 8px 14px;
  border-radius: 20px;
  font-size: 12px;
  font-weight: 600;
  text-decoration: none;
  box-shadow: 0 2px 8px rgba(0,0,0,0.15);
  display: flex;
  align-items: center;
  gap: 4px;
}

/* Premium progress bar with glow */
.progress-bar-glow {
  position: relative;
  border-radius: 4px;
  height: 6px;
  background: rgba(255,255,255,0.2);
  overflow: visible;
}
.progress-bar-glow > div {
  height: 100%;
  border-radius: 4px;
  background: var(--gold);
  transition: width 600ms var(--ease-out-expo);
  box-shadow: 0 0 8px rgba(186, 148, 85, 0.5);
}

/* ── Countdown Pulse, more alive ── */
@keyframes countdownPulse {
  0%, 100% { transform: scale(1); opacity: 1; }
  50% { transform: scale(1.08); opacity: 0.9; }
}

/* ── Day Mode Selector ── */
.day-modes {
  display: flex;
  gap: 6px;
  padding: 0 0 12px;
  overflow-x: auto;
  scrollbar-width: none;
}
.day-modes::-webkit-scrollbar { display: none; }
.mode-chip {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 6px 12px;
  border-radius: 16px;
  border: 1px solid var(--border);
  background: var(--white);
  font-size: 12px;
  font-weight: 500;
  color: var(--ink-light);
  cursor: pointer;
  transition: all 200ms ease, transform 100ms ease;
  font-family: inherit;
  -webkit-tap-highlight-color: transparent;
}
.mode-chip:active { transform: scale(0.95); }
.mode-chip.active {
  background: var(--accent-fill);
  border-color: var(--accent-fill);
  color: white;
}

/* ── Day View Tabs ── */
.day-tabs {
  display: flex;
  gap: 0;
  border-bottom: 2px solid var(--border);
  margin-bottom: 16px;
}
.day-tab {
  flex: 1;
  padding: 10px;
  background: none;
  border: none;
  font-size: 13px;
  font-weight: 600;
  color: var(--muted);
  cursor: pointer;
  border-bottom: 2px solid transparent;
  margin-bottom: -2px;
  transition: all 200ms ease, transform 100ms ease;
  font-family: inherit;
  text-align: center;
  -webkit-tap-highlight-color: transparent;
}
.day-tab:active { transform: scale(0.97); }
.day-tab.active {
  color: var(--accent);
  border-bottom-color: var(--accent);
}

/* ── Rain Mode ── */
.rain-banner {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  padding: 14px;
  background: linear-gradient(135deg, #e0f0ff 0%, #f0f7ff 100%);
  border: 1px solid #bdd8f0;
  border-radius: var(--radius-sm);
  margin-bottom: 12px;
  color: #1a4a6e;
}
.rain-banner-icon {
  flex-shrink: 0;
  opacity: 0.8;
}
.rain-banner-text {
  flex: 1;
  min-width: 0;
}
.rain-suggestion {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 12px;
  background: var(--white);
  border-radius: var(--radius-sm);
  margin-bottom: 6px;
  box-shadow: 0 0 0 1px rgba(0,0,0,0.04), 0 1px 3px rgba(0,0,0,0.06);
}
.rain-suggestion-type {
  color: var(--accent);
  flex-shrink: 0;
}

/* ── Mode Banner ── */
.mode-banner {
  padding: 12px;
  border-radius: var(--radius-sm);
  margin-bottom: 12px;
}

/* ── Route Loading Pulse ── */
.route-loading { animation: routePulse 1s ease infinite; }
@keyframes routePulse { 0%,100% { opacity: 0.3; } 50% { opacity: 0.7; } }

/* Hero Image Backgrounds */
.home-hero.has-bg {
  background-size: cover;
  background-position: center;
  position: relative;
}
/* Override the decorative blurs, turn ::before into the dark scrim */
.home-hero.has-bg::before {
  top: 0; right: 0; bottom: 0; left: 0;
  width: auto; height: auto;
  border-radius: 0;
  filter: none;
  background: linear-gradient(to bottom, rgba(0,0,0,0.55) 0%, rgba(0,0,0,0.75) 100%);
  z-index: 1;
}
/* Kill the second decorative blur */
.home-hero.has-bg::after {
  display: none;
}
/* Lift all content above the scrim */
.home-hero.has-bg > * {
  position: relative;
  z-index: 2;
}

.day-hero-banner {
  height: 140px;
  background-size: cover;
  background-position: center;
  position: relative;
  display: flex;
  align-items: flex-end;
  padding: 16px 20px;
  color: white;
  isolation: isolate;
}
.day-hero-banner::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, rgba(0,0,0,0.3) 0%, rgba(0,0,0,0.65) 100%);
  z-index: -1;
}
.day-hero-banner h2 {
  text-shadow: 0 1px 4px rgba(0,0,0,0.5);
}

/* ═══ Utility Classes ═══
   Commonly-used inline patterns extracted for reuse & dark mode compat */

/* Layout */
.flex-center { display:flex; align-items:center; justify-content:center; }
.flex-between { display:flex; align-items:center; justify-content:space-between; }
.flex-col { display:flex; flex-direction:column; }
.gap-4 { gap:4px; } .gap-6 { gap:6px; } .gap-8 { gap:8px; } .gap-12 { gap:12px; }

/* Text */
.text-xs { font-size:11px; } .text-sm { font-size:13px; } .text-md { font-size:14px; }
.text-muted { color:var(--muted); } .text-ink { color:var(--ink); } .text-accent { color:var(--accent); }
.text-bold { font-weight:600; } .text-heavy { font-weight:700; }
.section-label { font-size:11px; font-weight:700; letter-spacing:0.1em; text-transform:uppercase; color:var(--accent); }

/* Surfaces */
.bg-paper { background:var(--paper); } .bg-elevated { background:var(--white); }
.bg-accent-subtle { background:var(--accent-bg); }
.border-subtle { border:1px solid var(--border); }

/* Input fields, dark-mode safe */
.field-input {
  padding:8px 12px; border:1px solid var(--border-strong); border-radius:var(--radius-sm);
  background:var(--paper); color:var(--ink); font-family:inherit; font-size:14px;
  outline:none; box-sizing:border-box;
  -webkit-user-select:text; user-select:text;
}
.field-input:focus { border-color:var(--accent); }

/* Icon button (no background, 44px touch target) */
.btn-icon-clear {
  background:none; border:none; cursor:pointer; padding:8px;
  min-width:44px; min-height:44px;
  display:flex; align-items:center; justify-content:center;
  color:var(--muted); transition:color 0.15s, transform 0.1s;
}
.btn-icon-clear:active { transform:scale(0.9); }

/* Photo grid */
.photo-grid {
  display:grid; grid-template-columns:repeat(auto-fill,minmax(100px,1fr)); gap:8px;
}
.photo-thumb {
  position:relative; width:100%; padding-bottom:100%;
  background:var(--border); border-radius:var(--radius-sm); overflow:hidden; cursor:pointer;
}
.photo-thumb img {
  position:absolute; top:0; left:0; width:100%; height:100%;
  object-fit:cover; border-radius:var(--radius-sm);
}

/* Day navigation buttons */
.day-nav-btn {
  display:flex; align-items:center; gap:4px;
  padding:8px 14px; border:1px solid var(--border); border-radius:var(--radius-sm);
  background:var(--paper); color:var(--ink); font-size:13px; font-weight:500;
  cursor:pointer; font-family:inherit; transition:transform 0.1s;
}
.day-nav-btn:disabled { opacity:0.3; cursor:default; }
.day-nav-btn:active:not(:disabled) { transform:scale(0.97); }

/* Toast with pointer-events for undo button */
.toast.visible { pointer-events:auto; }

/* Pull-to-refresh */
#pull-refresh-indicator {
  font-family:inherit;
}
/* ---- Trip editor modal (Trips page) ---- */
.trip-sheet {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  max-width: 480px;
  margin: 0 auto;
  background: var(--white);
  border-radius: 20px 20px 0 0;
  z-index: 501;
  transform: translateY(100%);
  transition: transform 320ms cubic-bezier(0.34, 1.3, 0.64, 1);
  max-height: 88vh;
  overflow-y: auto;
  box-shadow: 0 -4px 24px rgba(0, 0, 0, 0.18);
  padding-bottom: calc(20px + env(safe-area-inset-bottom, 0px));
}
.sheet-backdrop.visible .trip-sheet { transform: translateY(0); }

/* Map with no basemap tiles (offline, or a provider outage). Markers, routes
   and clusters still render; this just gives them a readable ground. */
.map-no-tiles {
  background:
    repeating-linear-gradient(45deg,
      var(--paper2) 0, var(--paper2) 12px,
      var(--paper) 12px, var(--paper) 24px);
}
.map-no-tiles .leaflet-tile-pane { opacity: 0; }

/* ============================================================
   Practical guide (money · getting around · data)
   ============================================================
   Three questions every traveller has in the week before flying, and the app
   had no answer to any of them. Deliberately dense and text-heavy: this is a
   page you read once at home, not one you glance at in a street.
*/
.practical-page { padding-bottom: 90px; }

.practical-h {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 8px;
}

.practical-block {
  margin-bottom: 18px;
}
.practical-block p {
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--ink);
  margin: 0;
}

.practical-card {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  padding: 13px 14px;
  margin-bottom: 9px;
  background: var(--white);
}
/* The option the country's own guide recommends, marked once rather than
   repeated in prose. */
.practical-card-rec {
  border-color: var(--walk);
  background: var(--walk-bg);
}
.practical-card p {
  font-size: 13px;
  line-height: 1.6;
  color: var(--text-secondary);
  margin: 0;
}
.practical-card-head {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-bottom: 6px;
}
.practical-name {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 14px;
  font-weight: 700;
  color: var(--ink);
}
.practical-tag {
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  padding: 3px 8px;
  border-radius: 10px;
  margin-inline-start: auto;
  white-space: nowrap;
}
.practical-price,
.practical-price-line {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--accent);
}
.practical-price { margin-inline-start: auto; }
.practical-price-line { margin-bottom: 5px; }
.practical-where {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 12px;
  color: var(--muted);
  margin-bottom: 5px;
  line-height: 1.45;
}
.practical-chip {
  font-size: 11px;
  padding: 3px 8px;
  border-radius: 10px;
  background: var(--paper2);
  color: var(--text-secondary);
}

/* ============================================================
   Day brief
   ============================================================
   What the day is FOR, above the list of what is on it. A timeline of five
   rows tells you what to do and nothing about why those five.
*/
.day-brief {
  margin: 0 16px 14px;
  padding: 12px 14px;
  background: var(--paper2);
  border-radius: var(--radius-sm);
  border-inline-start: 3px solid var(--accent);
}
.day-brief p {
  margin: 0;
  font-size: 13.5px;
  line-height: 1.6;
  color: var(--ink);
}
.day-brief-links {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
  margin-top: 9px;
}
.day-brief-link {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 7px 11px;
  min-height: 34px;
  box-sizing: border-box;
  border-radius: 16px;
  background: var(--white);
  border: 1px solid var(--border);
  color: var(--accent);
  font-size: 12px;
  font-weight: 600;
  text-decoration: none;
}

/*
 * Country flag in the destination picker.
 *
 * Occupies the same 44px slot `.day-list-num` uses on the itinerary list, so
 * the two lists line up. No circle behind it - a flag is already a filled
 * rectangle and a coloured disc around it just adds noise. The oversized
 * line-height keeps the emoji optically centred, which it is not by default
 * in most fonts.
 */
.country-flag {
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 32px;
  line-height: 1;
  /* Colour emoji fonts, so the flag renders as a flag rather than as the two
     letters its code points fall back to. */
  font-family: "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji",
               "Twemoji Mozilla", sans-serif;
}

/*
 * Fallback for platforms without flag emoji (Windows, most Linux desktops).
 * The ISO code, set as a small solid badge, so it reads as a chosen label
 * rather than as a font that failed.
 */
.flag-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 5px;
  min-width: 26px;
  height: 18px;
  border-radius: 4px;
  background: var(--accent-fill);
  color: #fff;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: .04em;
  font-family: inherit;
  vertical-align: middle;
}

.country-flag .flag-badge {
  min-width: 36px;
  height: 26px;
  font-size: 13px;
  border-radius: 5px;
}

/*
 * A day marker carrying its own photograph.
 *
 * The number stays - it is how you navigate a fifteen-day list - so the photo
 * sits behind it under a scrim, and the digit gets a shadow so it holds up
 * over a bright sky as well as a dark temple interior.
 */
.day-list-photo {
  background-size: cover !important;
  background-position: center !important;
  color: #fff;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.65);
}
.day-list-item.today .day-list-photo { color: #fff; }

/*
 * The home hero and the day banner are both `background: url(...), gradient`,
 * so they need the same cover behaviour the day marker does. Without this the
 * photo tiles at its natural size instead of filling the banner.
 */
.home-hero.has-bg,
.day-hero-banner {
  background-size: cover !important;
  background-position: center !important;
}

/* The credit sits over the banner rather than inside its flex flow. */
.home-hero .hero-credit,
.day-hero-banner .hero-credit {
  position: absolute;
  inset-inline-end: 0;
  bottom: 0;
  z-index: 2;
}

/*
 * A day chip carrying its day's photograph. Three lines of text sit on it, so
 * the scrim is heavier than elsewhere and every line is forced white - the
 * region label is normally muted grey, which disappears over a picture.
 */
.day-chip.has-photo {
  background-size: cover !important;
  background-position: center !important;
  border-color: transparent;
}
.day-chip.has-photo .day-chip-num,
.day-chip.has-photo .day-chip-date,
.day-chip.has-photo .day-chip-region {
  color: #fff;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.7);
}

/* ---------------------------------------------------------------- map corners
 *
 * Three controls claimed the bottom-right of the map and none of them knew
 * about the others. Measured on a 747x387 viewport: the locate button sat at
 * (554, 247) 44x44, Leaflet's zoom stack at (570, 216) 34x64, and the OSM
 * attribution ran along the bottom to x=613. The button covered the lower half
 * of the zoom control and clipped the end of the attribution line, which is
 * the one thing on a map that is not ours to cover.
 *
 * So they are stacked instead: attribution on the floor, the locate button
 * clear of it, the zoom control above that.
 */
.map-fab { bottom: 28px; }

.leaflet-bottom.leaflet-right .leaflet-control-zoom {
  margin-bottom: 84px;
}

/* ── Today (Home.js) ─────────────────────────────────────────────────────
   One column of cards under the banner: what is next and when to leave,
   or what is left before the trip. Cards are separate objects; the rows in
   them are lists, so they share edges and padding. */
.today-body {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 14px 16px 24px;
}
.today-card {
  display: block;
  padding: 14px;
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--white);
  color: var(--ink);
  text-decoration: none;
  text-align: start;
  font: inherit;
}
.today-card-title { margin: 0; font-size: 15px; font-weight: 700; }
.today-card-sub { margin: 0 0 10px; font-size: 13px; color: var(--text-secondary); line-height: 1.45; }
.today-count {
  font-size: 13px;
  font-weight: 700;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
}
.today-eyebrow {
  margin: 0 0 4px;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
}
.today-link { font-size: 13px; font-weight: 600; color: var(--accent); text-decoration: none; min-height: 44px; display: inline-flex; align-items: center; }
.today-list { list-style: none; margin: 0; padding: 0; }
.today-list > li + li { border-top: 1px solid var(--border); }
.today-row {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 48px;
  padding: 6px 0;
  color: var(--ink);
  text-decoration: none;
}
.today-row-text { flex: 1; min-width: 0; display: flex; flex-direction: column; font-size: 14px; }
.today-row-hint { font-size: 12px; color: var(--text-secondary); }
.today-row-time { font-size: 13px; font-weight: 600; color: var(--text-secondary); font-variant-numeric: tabular-nums; min-width: 42px; }
.today-chevron { color: var(--muted); display: inline-flex; }
.today-mark {
  width: 30px;
  height: 30px;
  flex: none;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--paper2);
  color: var(--text-secondary);
}
.today-mark.done { background: var(--accent-fill); color: #fff; }
.today-cta {
  flex: none;
  min-height: 36px;
  padding: 0 14px;
  border: 1px solid var(--accent);
  border-radius: 18px;
  background: none;
  color: var(--accent);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}
.today-cta-primary,
.today-cta-secondary {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 44px;
  padding: 0 16px;
  border-radius: 22px;
  font: inherit;
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
}
.today-cta-primary { background: var(--accent-fill); color: #fff; border: 1px solid var(--accent-fill); }
.today-cta-secondary { background: none; color: var(--ink); border: 1px solid var(--border); }
.today-steps { margin: 0 0 14px; padding-inline-start: 22px; font-size: 14px; line-height: 1.7; }
.today-steps li::marker { color: var(--accent); font-weight: 700; }
.today-route { margin: 0; font-size: 14px; line-height: 2; }
.today-route a { color: var(--ink); text-decoration: none; white-space: nowrap; }
.today-route-days { font-size: 12px; color: var(--text-secondary); font-variant-numeric: tabular-nums; }
.today-route-sep { color: var(--muted); margin: 0 2px; }
.today-dayline { font-size: 14px; font-weight: 600; opacity: 0.9; margin-top: 6px; }
.today-weather { display: inline-block; margin-top: 6px; font-size: 14px; opacity: 0.9; }
.today-now { margin: 0 0 8px; font-size: 13px; color: var(--text-secondary); }
.today-next-title { font-size: 20px; font-weight: 700; line-height: 1.25; }
.today-next-leave { margin-top: 4px; font-size: 14px; color: var(--text-secondary); }
/* The next stop's last entry, judged at your arrival (Home.js nextHours). */
.today-next-hours { display: flex; align-items: center; gap: 6px; margin-top: 6px; font-size: 13.5px;
  color: var(--text-secondary); }
.today-next-hours.late { color: var(--hours-late); background: var(--hours-late-bg); font-weight: 600;
  padding: 6px 10px; border-radius: var(--radius-sm); }
.today-next-hours.tight { color: var(--hours-tight); background: var(--hours-tight-bg); font-weight: 600;
  padding: 6px 10px; border-radius: var(--radius-sm); }
.today-late-btn { display: inline-flex; align-items: center; gap: 6px; margin-top: 10px; min-height: 44px;
  padding: 8px 14px; border: 1px solid var(--border); border-radius: 999px; background: none;
  color: var(--text-secondary); font: inherit; font-size: 14px; font-weight: 600; cursor: pointer; }
.today-late-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.today-directions {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 12px;
  min-height: 48px;
  padding: 0 20px;
  border-radius: 24px;
  background: var(--accent-fill);
  color: #fff;
  font-weight: 700;
  text-decoration: none;
}
.today-actions {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 8px;
}
.today-action {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  min-height: 64px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--white);
  color: var(--ink);
  font-size: 12px;
  font-weight: 600;
  text-decoration: none;
}
.today-action svg { color: var(--accent); }
/* SOS is the one red control: border and icon, the label stays in ink. */
.today-action-sos { border-color: var(--color-status-error); }
.today-action-sos svg { color: var(--color-status-error); }
.today-rain { display: flex; gap: 12px; align-items: flex-start; border-color: var(--transport); }
.today-rain .today-mark { background: var(--transport-bg); color: var(--transport); }
.today-nearby { display: flex; align-items: center; gap: 12px; cursor: pointer; width: 100%; }
.today-nearby svg { color: var(--accent); flex: none; }
/* A row that opens something on the page (a place sheet) rather than a link. */
button.today-row {
  width: 100%;
  background: none;
  border: 0;
  font: inherit;
  text-align: start;
  cursor: pointer;
}
.today-meal-near { display: flex; align-items: center; gap: 4px; margin: 2px 0 4px; }
.today-meal-near svg { flex: none; color: var(--muted); }
.today-row:focus-visible,
.today-action:focus-visible,
.today-card:focus-visible,
.today-route a:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* ── A day (DayView.js): its own map, its plans one at a time ─────────── */
.day-map-wrap {
  position: relative;
  margin: 0 0 4px;
}
.day-mini-map {
  height: 180px;
  background: var(--paper2);
  cursor: pointer;
}
.day-mini-map:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.day-map-expand {
  position: absolute;
  right: 12px;
  bottom: 12px;
  z-index: 500;              /* above Leaflet's panes (400) */
  display: inline-flex;
  align-items: center;
  gap: 4px;
  min-height: 36px;
  padding: 0 12px;
  border-radius: 18px;
  background: var(--white);
  color: var(--ink);
  border: 1px solid var(--border);
  font-size: 13px;
  font-weight: 600;
  text-decoration: none;
  box-shadow: 0 1px 4px rgba(0,0,0,.18);
}
.plan-switch {
  display: flex;
  gap: 4px;
  margin: 0 16px 12px;
  padding: 4px;
  border-radius: 12px;
  background: var(--paper2);
  overflow-x: auto;
  scrollbar-width: none;
}
.plan-switch-btn {
  flex: 1 0 auto;
  min-height: 40px;
  padding: 0 12px;
  border: none;
  border-radius: 9px;
  background: none;
  color: var(--text-secondary);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
}
.plan-switch-btn[aria-selected="true"] {
  background: var(--white);
  color: var(--ink);
  box-shadow: 0 1px 3px rgba(0,0,0,.12);
}
.plan-switch-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.plan-view { display: flex; flex-direction: column; gap: 12px; }
.plan-why { margin: 0; font-size: 13px; color: var(--text-secondary); line-height: 1.5; }
.plan-list { display: flex; flex-direction: column; gap: 6px; }
.plan-row {
  display: flex;
  gap: 12px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--white);
}
.plan-time { min-width: 44px; font-size: 13px; font-weight: 700; color: var(--accent); font-variant-numeric: tabular-nums; }
.plan-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.plan-title { font-size: 14px; font-weight: 600; }
.plan-desc {
  font-size: 12.5px;
  color: var(--text-secondary);
  line-height: 1.4;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.plan-end { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--text-secondary); padding: 2px 12px; }
.plan-use {
  align-self: stretch;
  min-height: 48px;
  border: none;
  border-radius: 24px;
  background: var(--accent-fill);
  color: #fff;
  font: inherit;
  font-weight: 700;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  cursor: pointer;
}
/* Yesterday and tomorrow stay in reach at the foot of the day, above the
   tab bar, as well as a swipe away. */
.day-view .day-nav {
  position: sticky;
  bottom: calc(var(--nav-height) + env(safe-area-inset-bottom, 0px));
  z-index: 5;
  background: var(--paper);
  padding-top: 8px;
  padding-bottom: 8px;
}

/* Stop cards (DayOverview.js): the name, Navigate and ⋯ on one line, one
   line of description until the card is opened. These override the older
   fold rules in components.css, which hid the description entirely. */
.day-card .day-card-title { align-items: flex-start; gap: 8px; }
.day-card-name { flex: 1; min-width: 0; }
.day-card-actions { display: inline-flex; flex: none; margin: -10px -8px -10px 0; }
.day-card-nav,
.day-card-more {
  min-width: 44px;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: none;
  border-radius: 22px;
  background: none;
  cursor: pointer;
  text-decoration: none;
}
.day-card-nav { color: var(--transport); }
.day-card-more { color: var(--text-secondary); }
.day-card-nav:focus-visible,
.day-card-more:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.day-card-desc-row { display: flex; align-items: flex-start; gap: 4px; }
.day-card .day-card-desc {
  flex: 1;
  min-width: 0;
  max-height: none;
  margin-top: 2px;
  visibility: visible;
  transition: none;
  display: -webkit-box;
  -webkit-line-clamp: 1;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.day-card.expanded .day-card-desc { display: block; -webkit-line-clamp: unset; }
.day-card-desc-row .day-card-expand { margin-inline-start: auto; }
.day-card-cost { margin-top: 4px; }
/* A stop's hours (stop-hours.js): quiet when there is time, a chip when the
   plan has you there shut or with minutes to spare. */
.day-card-hours { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 4px;
  font-size: 12px; color: var(--text-secondary); }
.hours-chip { display: inline-flex; align-items: center; gap: 4px; padding: 2px 8px; border-radius: 999px;
  font-size: 12px; font-weight: 600; line-height: 1.5; border: none; font-family: inherit; cursor: pointer; }
.hours-chip.late, .hours-chip.closed { color: var(--hours-late); background: var(--hours-late-bg); }
.hours-chip.tight { color: var(--hours-tight); background: var(--hours-tight-bg); }
.hours-chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* On a phone the time column, the photo and two buttons left the name
   115px, and "Hakone Open-Air Museum" took four lines. The time moves
   above the name, beside the photo, and the name gets the room back. */
@media (max-width: 480px) {
  .day-card {
    display: grid;
    grid-template-columns: 36px minmax(0, 1fr);
    grid-template-areas: "media time" "media content";
    gap: 2px 10px;
  }
  .day-card-time {
    grid-area: time;
    width: auto;
    padding-top: 0;
    display: flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
  }
  .day-card-thumb,
  .day-card > .day-card-icon { grid-area: media; }
  .day-card-content { grid-area: content; }
}

/* The Plan tab's rows (DayList.js): the day's weather at the right edge. */
.day-list-weather {
  flex: none;
  margin-inline-start: auto;
  font-size: 12px;
  color: var(--text-secondary);
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* ── The planner's "More options" (NewTrip.js, How you travel) ── */
.wizard-more {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--white);
}
.wizard-more > summary {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-height: 48px;
  justify-content: center;
  padding-block: 10px;
  padding-inline: 14px 40px;
  cursor: pointer;
  list-style: none;
  position: relative;
  font-weight: 600;
}
.wizard-more > summary::-webkit-details-marker { display: none; }
.wizard-more > summary::after {
  content: '';
  position: absolute;
  inset-inline-end: 16px;
  top: 50%;
  width: 8px;
  height: 8px;
  border-right: 2px solid var(--muted);
  border-bottom: 2px solid var(--muted);
  transform: translateY(-70%) rotate(45deg);
}
.wizard-more[open] > summary::after { transform: translateY(-30%) rotate(-135deg); }
.wizard-more-sub { font-size: 12.5px; font-weight: 400; color: var(--text-secondary); }
.wizard-more-body { padding: 4px 14px 14px; }
.wizard-more > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ── "Make it yours" on the finished plan (NewTrip.js) ── */
.wizard-cards { display: flex; flex-direction: column; gap: 8px; }
.wizard-card {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  min-height: 60px;
  padding: 10px 12px;
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--white);
  color: var(--ink);
  font: inherit;
  text-align: start;
  cursor: pointer;
}
.wizard-card-icon {
  flex: none;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--accent-bg);
  color: var(--accent);
}
.wizard-card-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.wizard-card-title { font-weight: 600; font-size: 14.5px; }
.wizard-card-sub { font-size: 12.5px; color: var(--text-secondary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.wizard-card-go { flex: none; color: var(--muted); display: inline-flex; }
.wizard-card:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* ── "Why this route" at the top of the Plan tab (DayList.js) ── */
.plan-why-route {
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  background: var(--white);
  margin-bottom: 12px;
}
.plan-why-route > summary {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-height: 48px;
  justify-content: center;
  padding-block: 10px;
  padding-inline: 14px 40px;
  cursor: pointer;
  list-style: none;
  position: relative;
}
.plan-why-route > summary::-webkit-details-marker { display: none; }
.plan-why-route > summary::after {
  content: '';
  position: absolute;
  inset-inline-end: 16px;
  top: 50%;
  width: 8px;
  height: 8px;
  border-right: 2px solid var(--muted);
  border-bottom: 2px solid var(--muted);
  transform: translateY(-70%) rotate(45deg);
}
.plan-why-route[open] > summary::after { transform: translateY(-30%) rotate(-135deg); }
.plan-why-title { font-weight: 600; font-size: 14px; }
.plan-why-route-line { font-size: 12.5px; color: var(--text-secondary); }
.plan-why-route > p { margin: 0; padding: 0 14px 14px; font-size: 14px; line-height: 1.6; color: var(--ink); }
.plan-why-route > summary:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }

/* The route strip on Plan (DayList.js): each base and its days, a tap away. */
.plan-strip {
  display: flex;
  align-items: center;
  gap: 2px;
  margin: 0 0 12px;
  overflow-x: auto;
  scrollbar-width: none;
}
.plan-strip::-webkit-scrollbar { display: none; }
.plan-strip-stop {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 44px;
  padding: 0 12px;
  border: 1px solid var(--border);
  border-radius: 22px;
  background: var(--white);
  color: var(--ink);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
}
.plan-strip-days { font-size: 12px; font-weight: 600; color: var(--accent); font-variant-numeric: tabular-nums; }
.plan-strip-arrow { flex: none; display: inline-flex; color: var(--muted); }
.plan-strip-stop:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.plan-group-head { scroll-margin-top: 72px; }
.plan-group-head:focus { outline: none; }

/* ── "Not sure yet?" on the planner's first step (NewTrip.js) ── */
.not-sure-toggle {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  min-height: 52px;
  margin-bottom: 12px;
  padding: 10px 14px;
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--white);
  color: var(--ink);
  font: inherit;
  font-size: 13.5px;
  text-align: start;
  cursor: pointer;
}
.not-sure-toggle > svg { flex: none; color: var(--accent); }
.not-sure-toggle[aria-expanded="true"] { border-style: solid; border-color: var(--accent); }
.not-sure-panel { margin: -4px 0 16px; }
.like-tiles { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.like-tile {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 52px;
  padding: 8px 12px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--white);
  color: var(--ink);
  font: inherit;
  font-size: 13.5px;
  text-align: start;
  cursor: pointer;
}
.like-tile > svg { flex: none; color: var(--muted); }
.like-tile[aria-pressed="true"] { border-color: var(--accent); background: var(--accent-bg); }
.like-tile[aria-pressed="true"] > svg { color: var(--accent); }
.not-sure-note { margin: 12px 0 0; font-size: 13px; color: var(--text-secondary); }
.not-sure-months { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 12px; }
.not-sure-months-label { flex-basis: 100%; font-size: 13px; font-weight: 600; color: var(--ink); }
.not-sure-why { display: flex; align-items: center; gap: 4px; margin: 0 0 4px 2px; font-size: 12px; font-weight: 600; color: var(--accent); }
.not-sure-toggle:focus-visible,
.like-tile:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
/* ── Skeleton Loading ── */
@keyframes shimmer {
  0% { background-position: -200% 0; }
  100% { background-position: 200% 0; }
}

.skeleton {
  background: var(--border);
  border-radius: var(--radius-sm);
  position: relative;
  overflow: hidden;
}

.skeleton::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent);
  background-size: 200% 100%;
  animation: shimmer 1.5s infinite;
}

.skeleton-text {
  height: 14px;
  border-radius: 4px;
  margin-bottom: 8px;
}

.skeleton-text.short { width: 60%; }
.skeleton-text.medium { width: 80%; }
.skeleton-text.long { width: 100%; }

.skeleton-title {
  height: 20px;
  border-radius: 4px;
  margin-bottom: 10px;
  width: 70%;
}

.skeleton-card {
  border-radius: var(--radius);
  padding: 16px;
  background: var(--white);
  margin-bottom: 8px;
}

.skeleton-circle {
  width: 44px;
  height: 44px;
  border-radius: 50%;
}

.skeleton-chip {
  width: 60px;
  height: 60px;
  border-radius: var(--radius-sm);
}

.skeleton-hero {
  height: 160px;
  border-radius: 0;
  background: var(--accent-fill);
  opacity: 0.7;
}

/* Offline Banner */
.offline-banner {
  position: fixed;
  top: var(--header-total);
  left: 0;
  right: 0;
  background: var(--gold);
  color: #fff;
  font-size: 12px;
  font-weight: 600;
  text-align: center;
  padding: 6px 16px;
  z-index: 99;
  transform: translateY(-100%);
  transition: transform 300ms cubic-bezier(0.2, 0, 0, 1);
}

.offline-banner.visible {
  transform: translateY(0);
}

.offline-banner.online {
  background: var(--walk);
}
/*
 * WIDER THAN A PHONE.
 *
 * Every screen was a 480 px column (`#app` in base.css), so a tablet showed a
 * phone in the middle of itself and a desktop a strip with two blank thirds.
 * This file is loaded last and only ever adds to the phone layout, which stays
 * exactly as it was below 640 px:
 *
 *   640 px and up   a wider column, a centred tab bar, larger maps, wider sheets
 *   1024 px and up  the tabs become a rail down the side; the day and Explore
 *                   put their map beside the list instead of above it; Today
 *                   and Kit use the width; sheets become dialogs in the middle
 *
 * Reading screens keep a readable measure (760 px) however wide the window -
 * a line of text across a 27-inch monitor is not more usable for being long.
 */

/* ── Tablet and up ── */
@media (min-width: 640px) {
  #app { max-width: 760px; }

  /* The bar keeps its shape instead of stretching edge to edge. */
  .bottom-nav {
    left: 0;
    right: 0;
    margin-inline: auto;
    max-width: 560px;
  }

  .place-sheet,
  .trip-sheet { max-width: 600px; }

  .day-mini-map { height: 240px; }
  .explore2-map-wrap { height: 48vh; }

  .kit-grid { grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); }

  /* Today's cards side by side once each still has room to read. */
  .today-body {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    align-items: start;
  }
  .today-body > :only-child,
  .today-body > :first-child { grid-column: 1 / -1; }
}

/* ── Desktop ── */
@media (min-width: 1024px) {
  :root {
    /* No bar along the bottom: toasts, the Budget button and the undo bar,
       which all sit above it by this, come down to the edge of the window. */
    --nav-height: 0px;
    --rail-width: 88px;
  }

  body {
    padding-bottom: 32px;
    padding-inline-start: calc(var(--rail-width) + 32px);
  }
  /* The planner hides the tabs (components.css), so it has no rail to clear. */
  body.planning { padding-inline-start: 0; }

  #app {
    max-width: 1240px;
    padding-inline: 24px;
  }

  /* A readable column for every screen, unless it has a reason to be wide. */
  .page-wrapper > * {
    max-width: 760px;
    margin-inline: auto;
  }
  .page-wrapper > .day-view,
  .page-wrapper > .explore2,
  .page-wrapper > .today { max-width: none; }

  /* The tabs, as a rail down the side. */
  .bottom-nav {
    top: calc(var(--header-total) + 16px);
    bottom: auto;
    inset-inline-start: max(16px, env(safe-area-inset-left, 0px));
    inset-inline-end: auto;
    margin: 0;
    width: var(--rail-width);
    max-width: none;
    height: auto;
    flex-direction: column;
    justify-content: flex-start;
    gap: 4px;
    padding: 8px 6px;
    border-radius: 24px;
  }
  /* The sliding pill is measured across a row; in a column each tab lights
     itself instead. */
  .bottom-nav::before { display: none; }
  .nav-item {
    flex: 0 0 auto;
    width: 100%;
    padding: 10px 4px;
    border-radius: 18px;
  }
  .nav-item.active { background: var(--accent-bg); }
  .nav-item:hover { color: var(--accent); }

  /* The day: its stops on the left, its map standing beside them. */
  .day-view {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(340px, 42%);
    column-gap: 28px;
    align-items: start;
  }
  .day-view > .day-main { grid-column: 1; grid-row: 1; min-width: 0; }
  .day-view > .day-map-wrap {
    grid-column: 2;
    grid-row: 1;
    position: sticky;
    top: calc(var(--header-total) + 16px);
    margin: 0;
    border-radius: 16px;
    overflow: hidden;
  }
  .day-view .day-mini-map { height: calc(100vh - var(--header-total) - 48px); min-height: 360px; }

  /* Explore: the map fills the left, the search and the list run down the
     right - the list no longer has to slide up over the map. */
  .explore2 {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(360px, 440px);
    grid-template-rows: auto 1fr;
    align-items: start;
  }
  .explore2-map-wrap {
    grid-column: 1;
    grid-row: 1 / 3;
    top: var(--header-total);
    height: calc(100vh - var(--header-total));
    border-radius: 0 0 0 16px;
    overflow: hidden;
  }
  .explore2-bar { grid-column: 2; grid-row: 1; position: static; }
  .explore2-sheet {
    grid-column: 2;
    grid-row: 2;
    margin-top: 0;
    border-radius: 0;
    box-shadow: none;
    min-height: 0;
  }
  .explore2-grab { display: none; }

  /* Today: three columns when the window is wide enough to give them room. */
  .today { max-width: 1100px; margin-inline: auto; }
  .today-body { grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); }

  /* Sheets become dialogs in the middle of the window. They slid up from the
     bottom edge, which on a desktop is a long way from where the eye is. */
  .place-sheet {
    top: 50%;
    bottom: auto;
    left: 50%;
    right: auto;
    width: min(560px, calc(100vw - 48px));
    max-width: none;
    margin: 0;
    border-radius: 18px;
    max-height: min(82vh, 760px);
    opacity: 0;
    visibility: hidden;
    transform: translate(-50%, -46%) scale(0.98);
    transition: transform 220ms ease, opacity 180ms ease, visibility 0s linear 220ms;
    box-shadow: 0 24px 64px rgba(0, 0, 0, 0.28);
  }
  .place-sheet.visible {
    opacity: 1;
    visibility: visible;
    transform: translate(-50%, -50%);
    transition-delay: 0s;
  }
  .place-sheet.sheet-sectioned { max-height: min(86vh, 820px); }
  .place-sheet .sheet-handle { display: none; }

  .trip-sheet {
    top: 50%;
    bottom: auto;
    left: 50%;
    right: auto;
    width: min(520px, calc(100vw - 48px));
    max-width: none;
    margin: 0;
    border-radius: 18px;
    opacity: 0;
    transform: translate(-50%, -46%);
    transition: transform 220ms ease, opacity 180ms ease;
  }
  .sheet-backdrop.visible .trip-sheet { opacity: 1; transform: translate(-50%, -50%); }

  /* Things meant to be hovered say so. */
  .day-list-item:hover,
  .kit-tile:hover,
  .explore2-open:hover { filter: brightness(0.97); }
}

/* ── Very wide ── */
@media (min-width: 1600px) {
  #app { max-width: 1400px; }
}

/* ── A phone on its side: short, so sheets get every pixel of height ── */
@media (max-height: 500px) and (orientation: landscape) {
  .place-sheet,
  .trip-sheet { max-height: 94vh; }
  .place-sheet.sheet-sectioned { max-height: 96vh; }
  .day-mini-map { height: 160px; }
}
