/* Design tokens — dark-first, teal accent. Light theme overrides below. */
:root {
  --bg: #0b1016;
  --panel: #0d141c;
  --card: #111925;
  --card-2: #0f1620;
  --line: #1e2836;
  --line-soft: #17202c;
  --ink: #dde6ef;
  --ink-strong: #f1f6fa;
  --muted: #7d8da0;
  --accent: #2dd4bf;
  --accent-strong: #14b8a6;
  --accent-soft: rgba(45, 212, 191, 0.11);
  --accent-ink: #062621;
  --link: #7dd3fc;
  --ok: #34d399;
  --ok-soft: rgba(52, 211, 153, 0.12);
  --warn: #fbbf24;
  --warn-soft: rgba(251, 191, 36, 0.12);
  --danger: #f87171;
  --danger-soft: rgba(248, 113, 113, 0.12);
  --sky: #7dd3fc;
  --sky-soft: rgba(125, 211, 252, 0.12);
  --pink: #f472b6;
  --pink-soft: rgba(244, 114, 182, 0.12);
  --coral: #fb923c;
  --coral-soft: rgba(251, 146, 60, 0.12);
  --glow-a: rgba(45, 212, 191, 0.055);
  --glow-b: rgba(125, 211, 252, 0.05);
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.45), 0 10px 22px -12px rgba(0, 0, 0, 0.4);
  --radius: 10px;
  /* Contextual accent: components tinted per trip read var(--hue); a .hue-N
     class up the tree (sidebar rows, Home cards, the trip workspace) swaps
     it. Without one it falls back to the brand teal. */
  --hue: var(--accent);
  --hue-soft: var(--accent-soft);
}

html[data-theme='light'] {
  --bg: #f4f6f8;
  --panel: #ffffff;
  --card: #ffffff;
  --card-2: #f8fafc;
  --line: #dde3ea;
  --line-soft: #e8edf2;
  --ink: #24303c;
  --ink-strong: #101820;
  --muted: #64748b;
  --accent: #0d9488;
  --accent-strong: #0f766e;
  --accent-soft: rgba(13, 148, 136, 0.1);
  --accent-ink: #ffffff;
  --link: #0369a1;
  --ok: #059669;
  --ok-soft: rgba(5, 150, 105, 0.1);
  --warn: #b45309;
  --warn-soft: rgba(180, 83, 9, 0.1);
  --danger: #dc2626;
  --danger-soft: rgba(220, 38, 38, 0.08);
  --sky: #0284c7;
  --sky-soft: rgba(2, 132, 199, 0.08);
  --pink: #db2777;
  --pink-soft: rgba(219, 39, 119, 0.07);
  --coral: #ea580c;
  --coral-soft: rgba(234, 88, 12, 0.07);
  --glow-a: rgba(13, 148, 136, 0.06);
  --glow-b: rgba(2, 132, 199, 0.04);
  --shadow: 0 1px 2px rgba(16, 24, 32, 0.06), 0 10px 22px -14px rgba(16, 24, 32, 0.14);
}

/* Deterministic per-trip hues (dom.js tripHueClass). Each maps --hue onto a
   theme-aware token pair, so the same trip keeps its color in both themes. */
.hue-0 { --hue: var(--accent); --hue-soft: var(--accent-soft); }
.hue-1 { --hue: var(--sky); --hue-soft: var(--sky-soft); }
.hue-2 { --hue: var(--pink); --hue-soft: var(--pink-soft); }
.hue-3 { --hue: var(--coral); --hue-soft: var(--coral-soft); }
.hue-4 { --hue: var(--warn); --hue-soft: var(--warn-soft); }
.hue-5 { --hue: var(--ok); --hue-soft: var(--ok-soft); }

* { box-sizing: border-box; }
/* JS toggles visibility via the hidden attribute; it must beat any class
   that sets display (menus, POI panels, the new-trip composer). */
[hidden] { display: none !important; }
html, body { height: 100%; }
body {
  margin: 0;
  font-family: system-ui, -apple-system, 'Segoe UI', sans-serif;
  font-size: 14.5px;
  /* Faint accent glow in the top corners — depth without a loud gradient. */
  background:
    radial-gradient(55rem 26rem at 88% -8%, var(--glow-a), transparent 65%),
    radial-gradient(40rem 22rem at -5% 0%, var(--glow-b), transparent 60%),
    var(--bg);
  background-attachment: fixed;
  color: var(--ink);
  line-height: 1.5;
}

/* Views fade-and-rise in as they render; each top-level card cascades. */
@media (prefers-reduced-motion: no-preference) {
  #app > * { animation: view-in 200ms ease-out backwards; }
  @keyframes view-in {
    from { opacity: 0; transform: translateY(5px); }
    to { opacity: 1; transform: none; }
  }
}

a { color: var(--link); text-decoration: none; }
a:hover { text-decoration: underline; }

::selection { background: color-mix(in srgb, var(--accent) 28%, transparent); }
/* Keyboard focus ring on controls that don't already draw their own
   (inputs/selects/textareas have an inset :focus outline above). The
   role=button elements are the cards, rows and headers dom.js's clickable()
   turns into tab stops. */
a:focus-visible, button:focus-visible, summary:focus-visible, [role='button']:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: 6px;
}
html { scrollbar-width: thin; scrollbar-color: var(--line) transparent; }

/* --- Shell / sidebar --- */
#shell { display: grid; grid-template-columns: 232px 1fr; min-height: 100vh; }
body.logged-out #shell { grid-template-columns: 1fr; }
body.logged-out #sidebar { display: none; }

#sidebar {
  background: var(--panel);
  border-right: 1px solid var(--line-soft);
  display: flex;
  flex-direction: column;
  position: sticky;
  top: 0;
  height: 100vh;
  padding: 0.9rem 0.75rem;
}
.brand-row { display: flex; align-items: center; gap: 0.55rem; padding: 0.25rem 0.5rem 1rem; }
.brand-mark {
  display: grid;
  place-items: center;
  width: 28px;
  height: 28px;
  border-radius: 8px;
  background: linear-gradient(135deg, var(--accent-soft), var(--sky-soft));
  box-shadow: inset 0 0 0 1px var(--accent-soft);
  color: var(--accent);
}
.brand-name { font-weight: 700; color: var(--ink-strong); letter-spacing: -0.01em; }

#sidebar nav { flex: 1; display: flex; flex-direction: column; gap: 2px; }
.nav-label {
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted);
  padding: 0.9rem 0.55rem 0.3rem;
}
#sidebar nav a {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  color: var(--muted);
  padding: 0.42rem 0.55rem;
  border-radius: 8px;
  font-weight: 500;
}
#sidebar nav a { transition: background 120ms, color 120ms; }
#sidebar nav a:hover { color: var(--ink); background: var(--card); text-decoration: none; }
#sidebar nav a.active { color: var(--hue); background: var(--hue-soft); box-shadow: inset 2.5px 0 0 var(--hue); }
/* Nav icons carry their section's color even at rest (labels stay muted). */
#sidebar nav a svg { flex: none; opacity: 0.9; color: var(--hue); }

/* Per-destination nav colors, shared by the sidebar and the mobile tab bar. */
.nav-trips { --hue: var(--accent); --hue-soft: var(--accent-soft); }
.nav-templates { --hue: var(--sky); --hue-soft: var(--sky-soft); }
.nav-friends { --hue: var(--pink); --hue-soft: var(--pink-soft); }
.nav-people { --hue: var(--pink); --hue-soft: var(--pink-soft); }
.nav-crews { --hue: var(--coral); --hue-soft: var(--coral-soft); }
.nav-settings { --hue: var(--warn); --hue-soft: var(--warn-soft); }
.nav-help { --hue: var(--ok); --hue-soft: var(--ok-soft); }

.side-footer { border-top: 1px solid var(--line-soft); padding-top: 0.7rem; display: grid; gap: 0.5rem; }
.side-user { display: flex; align-items: center; gap: 0.55rem; padding: 0 0.3rem; }
.side-user-text { display: grid; line-height: 1.25; }
#whoami-name { font-weight: 600; font-size: 0.88rem; color: var(--ink-strong); }
.avatar {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--accent-soft);
  color: var(--accent);
  display: grid;
  place-items: center;
  font-size: 0.75rem;
  font-weight: 700;
  flex: none;
}

#main-col { min-width: 0; }
#app { max-width: 62rem; width: 100%; margin: 0 auto; padding: 1.5rem 1.5rem 4rem; min-width: 0; }
#app.wide { max-width: 84rem; }

/* --- Announcement banners (operator notices, dismissable) --- */
#banners { max-width: 62rem; width: 100%; margin: 0 auto; padding: 1rem 1.5rem 0; display: grid; gap: 0.5rem; }
#banners:empty { display: none; }
.banner {
  display: flex;
  align-items: flex-start;
  gap: 0.6rem;
  background: var(--accent-soft);
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
  border-radius: 9px;
  padding: 0.55rem 0.6rem 0.55rem 0.85rem;
  font-size: 0.9rem;
}
.banner .banner-body { white-space: pre-wrap; }

/* --- Type --- */
h1 { font-size: 1.45rem; margin: 0.25rem 0 0.35rem; color: var(--ink-strong); letter-spacing: -0.015em; }
/* Editable trip title: looks like a heading until you engage it. */
h1 input {
  font: inherit;
  color: inherit;
  background: transparent;
  border: 1px solid transparent;
  border-radius: 8px;
  padding: 0.05rem 0.4rem;
  margin-left: -0.4rem;
  min-width: 0;
  max-width: 100%;
}
h1 input:hover { border-color: var(--line); }
h1 input:focus { border-color: var(--line); background: var(--card-2); outline: 2px solid var(--accent); outline-offset: -1px; }
h2 { font-size: 1rem; margin: 0; color: var(--ink-strong); }
h3 { font-size: 0.92rem; margin: 0.9rem 0 0.35rem; color: var(--ink-strong); }
.page-sub { color: var(--muted); margin: 0 0 1.25rem; }
.section-label {
  display: flex;
  align-items: center;
  gap: 0.45rem;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--muted);
  margin: 1.5rem 0 0.5rem;
}
.section-label::before {
  content: '';
  width: 14px;
  height: 3px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--accent), var(--sky));
  opacity: 0.75;
}
.muted { color: var(--muted); }
.small { font-size: 0.83rem; }
code { background: var(--card-2); border: 1px solid var(--line-soft); border-radius: 5px; padding: 0.05em 0.35em; font-size: 0.85em; }

/* --- Cards --- */
.card {
  background: var(--card);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius);
  padding: 0.95rem 1.05rem;
  margin-bottom: 0.8rem;
  box-shadow: var(--shadow);
}
.card.clickable { cursor: pointer; transition: border-color 120ms, transform 120ms, box-shadow 120ms; }
.card.clickable:hover {
  border-color: var(--hue);
  transform: translateY(-1px);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.22), 0 0 0 1px var(--hue-soft);
}
/* Trip cards carry their hue as a left ribbon (Home's "More trips" list). */
.card.trip-hue-card { box-shadow: inset 3px 0 0 var(--hue), var(--shadow); }
.card.trip-hue-card.clickable:hover {
  box-shadow: inset 3px 0 0 var(--hue), 0 4px 14px rgba(0, 0, 0, 0.22), 0 0 0 1px var(--hue-soft);
}

/* Decorated cards — the hero's art language for every feature widget: a color
   wash rising from the head, line art in the corner drawn from what the card
   is about (an .art-* class picks it), and a border tinted toward the card's
   color. Color via modifier (.warn/.ok/...). The art is a mask-image SVG
   painted with the card's color, so it stays crisp and theme-aware; the
   data: URIs are covered by the CSP's img-src. */
.card.deco {
  --deco: var(--accent);
  --deco-soft: var(--accent-soft);
  position: relative;
  overflow: hidden;
  border-color: color-mix(in srgb, var(--deco) 16%, var(--line-soft));
  background:
    radial-gradient(24rem 9rem at -4% -12%, var(--deco-soft), transparent 62%),
    var(--card);
}
.card.deco::after {
  content: '';
  position: absolute;
  right: -1.6rem;
  top: -1.6rem;
  width: 8.5rem;
  height: 8.5rem;
  background: var(--deco);
  opacity: 0.11;
  pointer-events: none;
  -webkit-mask-image: var(--deco-art);
  mask-image: var(--deco-art);
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
}
.card.deco.warn { --deco: var(--warn); --deco-soft: var(--warn-soft); }
.card.deco.ok { --deco: var(--ok); --deco-soft: var(--ok-soft); }
.card.deco.sky { --deco: var(--sky); --deco-soft: var(--sky-soft); }
/* The card's icon chip and row icons inherit the deco color automatically. */
.card.deco .card-icon { --ci: var(--deco); --ci-soft: var(--deco-soft); }

/* The corner-art vocabulary. Default: radar rings with POI blips (places on
   the map) — also the hero's art. Each other widget draws its own subject. */
.card.deco {
  --deco-art: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 96 96'><g fill='none' stroke='black' stroke-width='2'><circle cx='48' cy='48' r='15'/><circle cx='48' cy='48' r='30'/><circle cx='48' cy='48' r='45'/></g><g fill='black'><circle cx='48' cy='48' r='2.5'/><circle cx='59' cy='37' r='3'/><circle cx='30' cy='57' r='3'/><circle cx='72' cy='66' r='3'/></g></svg>");
}
/* Two people in the same place at the same time. */
.card.deco.art-overlap {
  --deco-art: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 96 96'><g fill='none' stroke='black' stroke-width='2.5'><circle cx='36' cy='48' r='23'/><circle cx='60' cy='48' r='23'/></g><g fill='black'><circle cx='36' cy='48' r='3'/><circle cx='60' cy='48' r='3'/></g></svg>");
}
/* Someone is waiting on your answer. */
.card.deco.art-clock {
  --deco-art: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 96 96'><g fill='none' stroke='black' stroke-width='2.5'><circle cx='48' cy='48' r='36'/><path d='M48 15v7M81 48h-7M48 81v-7M15 48h7'/><path d='M48 48V30M48 48l13 8' stroke-width='3' stroke-linecap='round'/></g></svg>");
}
/* A queue of requests, draining. */
.card.deco.art-queue {
  --deco-art: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 96 96'><g fill='none' stroke='black' stroke-width='2.5'><rect x='18' y='18' width='60' height='12' rx='6'/><rect x='26' y='42' width='52' height='12' rx='6'/><rect x='34' y='66' width='44' height='12' rx='6'/></g></svg>");
}
/* People, connected. */
.card.deco.art-people {
  --deco-art: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 96 96'><g fill='none' stroke='black' stroke-width='2'><path d='M44 35 56 39M58 50 49 59M42 58 38 40'/></g><g fill='none' stroke='black' stroke-width='2.5'><circle cx='36' cy='32' r='8'/><circle cx='63' cy='42' r='8'/><circle cx='44' cy='66' r='8'/></g></svg>");
}
/* A route between waypoints — steps on the way. */
.card.deco.art-route {
  --deco-art: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 96 96'><path d='M14 78C26 30 56 88 82 22' fill='none' stroke='black' stroke-width='2.5' stroke-dasharray='7 6' stroke-linecap='round'/><g fill='black'><circle cx='14' cy='78' r='4'/><circle cx='82' cy='22' r='4'/></g><circle cx='43' cy='57' r='4' fill='none' stroke='black' stroke-width='2.5'/></svg>");
}
/* Account security. */
.card.deco.art-shield {
  --deco-art: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 96 96'><path d='M48 12l30 12v20c0 22-15 34-30 42-15-8-30-20-30-42V24z' fill='none' stroke='black' stroke-width='2.5' stroke-linejoin='round'/><path d='M36 48l9 9 16-18' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/></svg>");
}
/* A day with something on it. */
.card.deco.art-cal {
  --deco-art: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 96 96'><g fill='none' stroke='black' stroke-width='2.5'><rect x='14' y='20' width='68' height='62' rx='9'/><path d='M14 38h68M32 12v14M64 12v14'/></g><g fill='black'><circle cx='33' cy='53' r='3'/><circle cx='48' cy='53' r='3'/><circle cx='63' cy='53' r='3'/><circle cx='33' cy='67' r='3'/><circle cx='48' cy='67' r='5.5'/></g></svg>");
}
.card-head { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.55rem; }
.card-head .aside { margin-left: auto; color: var(--muted); font-size: 0.82rem; }
.section-label .aside {
  margin-left: auto;
  color: var(--muted);
  font-size: 0.8rem;
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
}
.card-icon {
  --ci: var(--accent);
  --ci-soft: var(--accent-soft);
  display: grid;
  place-items: center;
  width: 26px;
  height: 26px;
  border-radius: 7px;
  /* Gradient chip + hairline ring — the brand-mark treatment, per color. */
  background: linear-gradient(135deg, var(--ci-soft), color-mix(in srgb, var(--ci-soft) 35%, transparent));
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--ci) 28%, transparent);
  color: var(--ci);
  flex: none;
}
.card-icon.warn { --ci: var(--warn); --ci-soft: var(--warn-soft); }
.card-icon.danger { --ci: var(--danger); --ci-soft: var(--danger-soft); }
.card-icon.sky { --ci: var(--sky); --ci-soft: var(--sky-soft); }
.card-icon.ok { --ci: var(--ok); --ci-soft: var(--ok-soft); }

/* --- Badges / pills --- */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  border-radius: 7px;
  padding: 0.08rem 0.55rem;
  font-size: 0.82rem;
  font-weight: 600;
  background: var(--accent-soft);
  color: var(--accent);
}
.badge::before { content: ''; width: 5px; height: 5px; border-radius: 50%; background: currentColor; }
.badge.warn { background: var(--warn-soft); color: var(--warn); }
.badge.danger { background: var(--danger-soft); color: var(--danger); }
.badge.ok { background: var(--ok-soft); color: var(--ok); }
.badge.plain { background: var(--card-2); color: var(--muted); }

.pill {
  display: inline-block;
  padding: 0.02rem 0.5rem;
  border-radius: 999px;
  border: 1px solid var(--line);
  font-size: 0.76rem;
  color: var(--muted);
  background: var(--card-2);
}
.pill.on { border-color: transparent; background: var(--ok-soft); color: var(--ok); }
.pill.warn { border-color: transparent; background: var(--warn-soft); color: var(--warn); }

/* --- Needs-you list --- */
ul.needs { list-style: none; padding: 0; margin: 0; }
ul.needs li { display: flex; align-items: center; gap: 0.7rem; padding: 0.5rem 0.15rem; border-bottom: 1px solid var(--line-soft); }
ul.needs li:last-child { border-bottom: none; }
.show-all { display: flex; justify-content: center; padding: 0.2rem 0; }
ul.needs a { color: var(--link); }

/* --- Layout helpers --- */
/* A hairline under a row that isn't an <li> (a dialog's audience rows, the
   share-link list, the shared-with-you rows): the rule lived as the same
   inline border-bottom string in six places. Each list keeps its own padding
   inline, and the last row opts out by leaving the class off — several of
   these lists have something appended after them. */
.divided-row { border-bottom: 1px solid var(--line-soft); }
/* A block a dialog fences off from the body above it (presence note, the
   follower list in the Sharing dialog). */
.dialog-section { border-top: 1px solid var(--line-soft); padding-top: 0.8rem; }
.row { display: flex; align-items: center; gap: 0.6rem; flex-wrap: wrap; }
.row.between { justify-content: space-between; }
/* A row of actions pushed to the right — a dialog's Cancel/Confirm pair. */
.row.end { justify-content: flex-end; }
/* A name over its one-line subtitle: the shape of every clickable row and
   card in the app (trip cards, friend rows, the resume row, Help's tour
   card). min-width lets the name ellipsize instead of stretching its row. */
.stack { display: grid; line-height: 1.35; min-width: 0; }
/* An icon that reads as part of the sentence next to it, not as a control. */
.icon-muted { color: var(--muted); display: flex; }
.grow { flex: 1; }
/* Growing inputs in a row: a real flex-basis so the row wraps instead of the
   input's intrinsic width pushing its neighbors past the card edge. */
.row > input.grow { flex: 1 1 7rem; min-width: 7rem; width: auto; }

/* --- Buttons --- */
button, .btn {
  font: inherit;
  font-weight: 500;
  border: 1px solid var(--line);
  background: var(--card-2);
  color: var(--ink);
  border-radius: 8px;
  padding: 0.36rem 0.85rem;
  cursor: pointer;
  transition: border-color 120ms, background 120ms;
}
a.btn:hover { text-decoration: none; }
button:hover, .btn:hover { border-color: var(--accent); color: var(--ink-strong); }
button.primary {
  background: linear-gradient(180deg, var(--accent), var(--accent-strong));
  border-color: var(--accent-strong);
  color: var(--accent-ink);
  font-weight: 600;
  transition: border-color 120ms, box-shadow 120ms, filter 120ms;
}
html[data-theme='dark'] button.primary { color: #04211c; }
button.primary:hover { filter: brightness(1.07); box-shadow: 0 2px 12px var(--accent-soft); }
button.danger { color: var(--danger); }
button.danger:hover { border-color: var(--danger); }
button.attn { border-color: var(--warn); color: var(--warn); background: var(--warn-soft); }
button.ghost { border-color: transparent; background: transparent; color: var(--muted); }
button.ghost:hover { color: var(--ink); border-color: transparent; }
button:disabled { opacity: 0.45; cursor: default; }

button.seg { border-radius: 0; margin-left: -1px; padding: 0.22rem 0.6rem; font-size: 0.85rem; background: var(--card-2); }
button.seg:first-of-type { border-radius: 8px 0 0 8px; margin-left: 0; }
button.seg:last-of-type { border-radius: 0 8px 8px 0; }
button.seg.sel-yes { background: var(--ok-soft); border-color: var(--ok); color: var(--ok); }
button.seg.sel-maybe { background: var(--warn-soft); border-color: var(--warn); color: var(--warn); }
button.seg.sel-no { background: var(--danger-soft); border-color: var(--danger); color: var(--danger); }

/* --- Forms --- */
input, select, textarea {
  font: inherit;
  border: 1px solid var(--line);
  border-radius: 8px;
  padding: 0.36rem 0.6rem;
  background: var(--card-2);
  color: var(--ink);
}
input::placeholder { color: var(--muted); opacity: 0.8; }
input:focus, select:focus, textarea:focus { outline: 2px solid var(--accent); outline-offset: -1px; }
input[type='checkbox'] { accent-color: var(--accent-strong); width: 15px; height: 15px; }
input[type='date'] { color-scheme: dark; }
html[data-theme='light'] input[type='date'] { color-scheme: light; }
label { font-size: 0.84rem; color: var(--muted); display: block; margin-bottom: 0.18rem; }
.field { margin-bottom: 0.8rem; }

.auth-box {
  max-width: 25rem;
  margin: 4.5rem auto 0;
  /* Gradient hairline border: the one place the brand gets to show off. */
  border: 1px solid transparent;
  background:
    linear-gradient(var(--card), var(--card)) padding-box,
    linear-gradient(135deg, var(--accent), var(--sky)) border-box;
}
.auth-box h1 { margin-bottom: 0.5rem; }
.auth-brand {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border-radius: 13px;
  margin-bottom: 0.9rem;
  background: linear-gradient(135deg, var(--accent-soft), var(--sky-soft));
  box-shadow: inset 0 0 0 1px var(--accent-soft);
  color: var(--accent);
}
.error { color: var(--danger); font-size: 0.9rem; margin: 0.5rem 0; }
/* Auth actions align full-width so the passkey and Google buttons match. */
.auth-box button.primary { display: block; width: 100%; }
.auth-box .row { display: block; }
/* "Continue with Google" — deliberately quieter than the passkey primary. */
.auth-box button.google-btn { display: block; width: 100%; margin-top: 0.6rem; }

/* --- Lists / tables --- */
ul.plain { list-style: none; padding: 0; margin: 0; }
ul.plain li { padding: 0.45rem 0; border-bottom: 1px solid var(--line-soft); }
ul.plain li:last-child { border-bottom: none; }

table { border-collapse: collapse; width: 100%; font-size: 0.88rem; }
th, td { text-align: left; padding: 0.4rem 0.55rem; border-bottom: 1px solid var(--line-soft); }
th { color: var(--muted); font-weight: 600; font-size: 0.78rem; text-transform: uppercase; letter-spacing: 0.05em; }
/* Wide tables scroll inside their card instead of stretching the page
   sideways (which drags every other card along on small screens). */
.table-scroll { overflow-x: auto; }
.table-scroll td { white-space: nowrap; }
.table-scroll td.row { flex-wrap: nowrap; }

/* --- Board filters --- */
.filter-bar { position: sticky; top: 0; z-index: 4; background: var(--bg); padding: 0.4rem 0 0.5rem; }
.filter-bar .card { margin-bottom: 0; }
/* One scrollable line per filter group — wrapped chips stacked the filter
   card to most of a phone screen. Rows bleed across the card's side padding
   so chips slide out under the card edge instead of clipping mid-card. */
.chip-row {
  display: flex;
  gap: 0.35rem;
  margin: 0.5rem -1.05rem 0;
  padding: 0 1.05rem;
  overflow-x: auto;
  scrollbar-width: none;
}
.chip-row::-webkit-scrollbar { display: none; }
.chip {
  font: inherit;
  font-size: 0.83rem;
  padding: 0.14rem 0.7rem;
  border-radius: 999px;
  border: 1px solid var(--line);
  background: var(--card-2);
  color: var(--muted);
  cursor: pointer;
  flex: none;
  white-space: nowrap;
}
.chip { transition: border-color 120ms, color 120ms, background 120ms; }
.chip:hover { border-color: var(--accent); color: var(--ink); }
a.chip { display: inline-block; }
a.chip:hover { text-decoration: none; }
.chip.active { background: var(--accent-soft); border-color: var(--accent); color: var(--accent); font-weight: 600; box-shadow: 0 1px 6px var(--accent-soft); }

/* --- POIs / board --- */
.poi { border-bottom: 1px solid var(--line-soft); padding: 0.65rem 0; }
.poi:last-child { border-bottom: none; }
.poi .name { font-weight: 600; color: var(--ink-strong); cursor: pointer; }
.poi .name:hover { color: var(--accent); }
.cluster-head {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin: 1.1rem 0 0.2rem;
  font-size: 0.72rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--muted);
}
/* Ties each list section to its map pins' ring color. */
.cluster-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  border: 2.5px solid currentColor;
  flex: none;
}

.friend-board { border-left: 3px solid var(--accent); padding-left: 0.8rem; margin: 0.8rem 0; }
.day-group { margin-bottom: 0.5rem; }

/* --- Friends list rows --- */
li.friend-row { cursor: pointer; padding: 0.55rem 0.35rem; transition: background 120ms; }
li.friend-row:hover { background: var(--card-2); }

/* --- Sidebar epic list --- */
.side-epic { display: flex; align-items: center; gap: 0.55rem; padding: 0.32rem 0.55rem; border-radius: 8px; color: var(--muted); }
.side-epic:hover { background: var(--card); text-decoration: none; color: var(--ink); }
.side-epic.active { background: var(--hue-soft); }
.side-epic.active .side-epic-name { color: var(--hue); }
.side-epic-dot { width: 6px; height: 6px; border-radius: 50%; background: var(--hue); opacity: 0.85; flex: none; box-shadow: 0 0 0 3px var(--hue-soft); }
.side-epic-text { display: grid; line-height: 1.2; min-width: 0; }
.side-epic-name { font-weight: 500; font-size: 0.87rem; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.side-epic-empty { padding: 0.1rem 0.55rem; }

/* --- Epic workspace tabs --- */
.tabs {
  display: flex;
  gap: 0.25rem;
  border-bottom: 1px solid var(--line);
  margin-bottom: 1.1rem;
  overflow-x: auto;
  overflow-y: hidden;
  scrollbar-width: none;
}
.tabs::-webkit-scrollbar { display: none; }
.tab {
  display: grid;
  gap: 0.05rem;
  padding: 0.45rem 0.9rem 0.55rem;
  color: var(--muted);
  border-bottom: 2px solid transparent;
  white-space: nowrap;
  font-weight: 500;
  flex: none;
}
.tab:hover { color: var(--ink); text-decoration: none; }
.tab.active { color: var(--hue); border-bottom-color: var(--hue); }
.tab-kicker { font-size: 0.68rem; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); }

/* --- Map --- */
.map-box { height: 340px; border-radius: var(--radius); overflow: hidden; border: 1px solid var(--line-soft); }
/* A card that holds nothing but a map (and, on the board, its legend): the
   map draws its own edge, so the card's usual padding would double it. */
.card.map-card { padding: 0.4rem; }
.leaflet-container { background: var(--card-2); font: inherit; }
/* OSM tiles restyled for dark mode — one tile source, no keyed provider. */
html[data-theme='dark'] .leaflet-tile {
  filter: invert(1) hue-rotate(180deg) brightness(0.85) contrast(0.85) saturate(0.45);
}
.map-box.picking { cursor: crosshair; outline: 2px solid var(--accent); outline-offset: -2px; }
/* Fullscreen map: fixed over everything below dialogs/toast. !important beats
   the per-context height rules (.board-map-col .map-box, mobile 220px) and
   the inline position:relative Leaflet writes on the container at init. */
.map-box.map-full {
  position: fixed !important;
  inset: 0;
  width: 100vw;
  height: 100dvh !important;
  z-index: 1000;
  border-radius: 0;
  border: none;
}
.map-fs-btn { display: grid; place-items: center; }
.leaflet-bar .map-fs-btn svg { display: block; }
.map-legend { display: flex; flex-wrap: wrap; gap: 0.35rem 0.7rem; align-items: center; padding: 0.4rem 0.6rem 0.15rem; }
.map-legend .dot {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  border: 2.5px solid currentColor;
  background: transparent;
  margin-right: 0.3rem;
  vertical-align: -1px;
}
.leaflet-popup-content-wrapper, .leaflet-popup-tip { background: var(--card); color: var(--ink); box-shadow: var(--shadow); }
.map-pop-muted { color: var(--muted); font-size: 0.8rem; }
/* Popup name as a link back to the list row: strip the button chrome so it
   reads like the list's clickable .name. */
.map-pop-link {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  font-weight: 600;
  color: var(--ink-strong);
  cursor: pointer;
}
.map-pop-link:hover { color: var(--accent); }
.poi-pin-wrap { background: none; border: none; }
.poi-pin {
  width: 100%;
  height: 100%;
  box-sizing: border-box;
  border: 3px solid currentColor;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: 10px;
  font-weight: 700;
  color: #fff;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.55);
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
}
.req-pin-wrap { background: none; border: none; }
.req-pin {
  width: 100%;
  height: 100%;
  box-sizing: border-box;
  border: 2px dashed var(--warn);
  border-radius: 50%;
  background: var(--warn-soft);
  color: var(--warn);
  display: grid;
  place-items: center;
  font-size: 10px;
  font-weight: 700;
}
/* A personal place: solid, ringed, in the accent — settled, where a catalog
   pin is a hollow ring and a pending suggestion is dashed. A friend's shared
   pin overrides the background with their avatar color. */
.place-pin-wrap { background: none; border: none; }
.place-pin {
  width: 100%;
  height: 100%;
  box-sizing: border-box;
  border-radius: 50%;
  background: var(--accent);
  border: 2px solid var(--card);
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.35), 0 1px 4px rgba(0, 0, 0, 0.4);
}
.base-pin {
  background: var(--accent);
  border: 2px solid var(--ink-strong);
  border-radius: 3px;
  transform: rotate(45deg);
  box-shadow: var(--shadow);
}
/* You, on the Nearby map: a sky-blue dot with a slow pulse so it is found at
   a glance among the vote-colored pins. */
.here-pin-wrap { background: none; border: none; }
.here-pin {
  width: 100%;
  height: 100%;
  box-sizing: border-box;
  border-radius: 50%;
  background: var(--sky);
  border: 3px solid #fff;
  box-shadow: 0 0 0 2px var(--sky), 0 1px 4px rgba(0, 0, 0, 0.4);
}
@media (prefers-reduced-motion: no-preference) {
  .here-pin { animation: here-pulse 2.2s ease-out infinite; }
  @keyframes here-pulse {
    0% { box-shadow: 0 0 0 2px var(--sky), 0 0 0 0 color-mix(in srgb, var(--sky) 45%, transparent); }
    100% { box-shadow: 0 0 0 2px var(--sky), 0 0 0 14px transparent; }
  }
}

/* --- Nearby page --- */
/* A link styled as the primary button (the Nearby entry points): an <a> so
   it is a real navigation, with the primary button's look. */
a.btn.primary-link {
  background: linear-gradient(180deg, var(--accent), var(--accent-strong));
  border-color: var(--accent-strong);
  color: var(--accent-ink);
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
}
html[data-theme='dark'] a.btn.primary-link { color: #04211c; }
a.btn.primary-link:hover { filter: brightness(1.07); box-shadow: 0 2px 12px var(--accent-soft); }
a.btn { display: inline-flex; align-items: center; gap: 0.35rem; }
/* The plain-language gloss after a section head's count ("no vote yet"),
   which must not inherit the head's uppercase tracking. */
.cluster-head .tier-hint { text-transform: none; letter-spacing: 0; font-weight: 400; margin-left: 0.3rem; }
.nearby-map { height: min(48vh, 440px); }
.nearby-status { display: block; margin-top: 0.15rem; }
.nearby-row .nearby-meta { gap: 0.3rem; margin-top: 0.2rem; }
/* "179 m N · 2 min walk" wraps as one unit after the pills, never mid-phrase. */
.nearby-row .nearby-distance { white-space: nowrap; margin-left: 0.2rem; }
.nearby-row .nearby-directions { display: inline-flex; align-items: center; gap: 0.25rem; }
.nearby-row .nearby-votes { display: inline-flex; flex: none; align-self: flex-start; }
.nearby-row .poi-head { align-items: flex-start; }
.nearby-row .name { cursor: pointer; }
/* Phone width: the three vote buttons are a third of the screen, so they
   drop under the text rather than squeeze it into a narrow column. */
@media (max-width: 800px) {
  .nearby-row .poi-head { flex-wrap: wrap; }
  .nearby-row .nearby-votes { width: 100%; margin-top: 0.35rem; }
  .nearby-map { height: 50vh; }
}

/* --- Collapsible cards & modal --- */
.collapse-head { cursor: pointer; user-select: none; }
.collapse-head .chev { transition: transform 120ms; color: var(--muted); font-size: 0.8rem; }
.collapse-head.open .chev { transform: rotate(90deg); }

dialog.modal {
  background: var(--card);
  color: var(--ink);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.1rem 1.2rem;
  max-width: 28rem;
  width: calc(100vw - 2rem);
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.45);
}
dialog.modal::backdrop { background: rgba(4, 8, 12, 0.6); }

/* --- Toast --- */
#toast {
  position: fixed;
  bottom: 1.25rem;
  left: 50%;
  transform: translateX(-50%);
  background: var(--card);
  border: 1px solid var(--accent);
  color: var(--ink-strong);
  border-radius: 8px;
  padding: 0.5rem 1rem;
  max-width: 80%;
  z-index: 1100;
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.35);
}
#toast.err { border-color: var(--danger); color: var(--danger); }
@media (prefers-reduced-motion: no-preference) {
  #toast:not([hidden]) { animation: toast-in 220ms cubic-bezier(0.2, 0.9, 0.3, 1.15); }
  @keyframes toast-in {
    from { opacity: 0; transform: translate(-50%, 10px); }
    to { opacity: 1; transform: translate(-50%, 0); }
  }
}

/* --- Hero (next trip) --- */
.hero {
  padding: 1.3rem 1.5rem;
  border-color: var(--line);
  position: relative;
  overflow: hidden;
  background:
    radial-gradient(26rem 13rem at 100% 0%, var(--hue-soft), transparent 60%),
    radial-gradient(20rem 12rem at 0% 100%, var(--accent-soft), transparent 65%),
    var(--card);
}
/* Radar with POI blips in the corner — places lighting up on the map. */
.hero::after {
  content: '';
  position: absolute;
  right: -2.2rem;
  top: -2.2rem;
  width: 11.5rem;
  height: 11.5rem;
  background: var(--hue);
  opacity: 0.12;
  pointer-events: none;
  -webkit-mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 96 96'><g fill='none' stroke='black' stroke-width='1.6'><circle cx='48' cy='48' r='15'/><circle cx='48' cy='48' r='30'/><circle cx='48' cy='48' r='45'/></g><g fill='black'><circle cx='48' cy='48' r='2.5'/><circle cx='59' cy='37' r='3'/><circle cx='30' cy='57' r='3'/><circle cx='72' cy='66' r='3'/></g></svg>");
  mask-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 96 96'><g fill='none' stroke='black' stroke-width='1.6'><circle cx='48' cy='48' r='15'/><circle cx='48' cy='48' r='30'/><circle cx='48' cy='48' r='45'/></g><g fill='black'><circle cx='48' cy='48' r='2.5'/><circle cx='59' cy='37' r='3'/><circle cx='30' cy='57' r='3'/><circle cx='72' cy='66' r='3'/></g></svg>");
  -webkit-mask-size: contain;
  mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  mask-repeat: no-repeat;
}
/* The "Jump back in" row on Home: a hero kicker's label, at list scale. */
.resume-kicker {
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--hue);
}

.hero .kicker {
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--hue);
  margin-bottom: 0.15rem;
}
.hero .hero-name { font-size: 1.4rem; font-weight: 700; color: var(--ink-strong); letter-spacing: -0.015em; }
.countdown {
  background: var(--hue-soft);
  color: var(--hue);
  border: 1px solid color-mix(in srgb, var(--hue) 35%, transparent);
  border-radius: 999px;
  padding: 0.15rem 0.75rem;
  font-size: 0.83rem;
  font-weight: 600;
  white-space: nowrap;
}
/* A slow breathing glow — the one deliberately animated accent on Home. */
@media (prefers-reduced-motion: no-preference) {
  .countdown { animation: countdown-pulse 2.8s ease-in-out infinite; }
  @keyframes countdown-pulse {
    0%, 100% { box-shadow: 0 0 0 0 var(--hue-soft); }
    50% { box-shadow: 0 0 0 6px transparent; }
  }
}
.stay-chip {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  background: var(--card-2);
  border: 1px solid var(--line);
  border-radius: 9px;
  padding: 0.45rem 0.85rem;
  color: var(--ink);
  line-height: 1.3;
}
.stay-chip { transition: border-color 120ms, transform 120ms; }
.stay-chip:hover { border-color: var(--accent); text-decoration: none; transform: translateY(-1px); }
.stay-chip .stay-chip-text { display: grid; }
.stay-chip strong { color: var(--ink-strong); font-size: 0.9rem; }
.stay-chip .muted { font-size: 0.78rem; }
.chip-connector { display: flex; align-items: center; gap: 0.35rem; color: var(--muted); font-size: 0.8rem; }
.chip-connector .line { width: 1.2rem; height: 1px; background: var(--line); }

/* --- Inbox (needs-you) rows --- */
ul.needs li .needs-icon {
  display: grid;
  place-items: center;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--accent-soft);
  color: var(--accent);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, currentColor 22%, transparent);
  flex: none;
}
ul.needs li .needs-icon.warn { background: var(--warn-soft); color: var(--warn); }
ul.needs li .needs-icon.ok { background: var(--ok-soft); color: var(--ok); }
ul.needs li .grow { min-width: 0; }

/* --- Segmented view switch --- */
.segbar {
  display: inline-flex;
  background: var(--card-2);
  border: 1px solid var(--line);
  border-radius: 9px;
  padding: 3px;
  gap: 2px;
}
.segbar button {
  border: none;
  background: transparent;
  color: var(--muted);
  border-radius: 7px;
  padding: 0.3rem 1rem;
  font-weight: 500;
}
.segbar button { transition: background 120ms, color 120ms; }
.segbar button:hover { color: var(--ink); }
.segbar button.active { background: var(--accent-soft); color: var(--accent); font-weight: 600; box-shadow: 0 1px 5px var(--accent-soft); }
/* Legend-sized variant: the map ring-mode switch sits inline with the dots. */
.segbar.mini { padding: 2px; border-radius: 7px; }
.segbar.mini button { padding: 0.1rem 0.55rem; font-size: 0.78rem; border-radius: 5px; }

/* Header switches (Just me, Private): a label wrapping the switch so the word is the hit target too. */
.header-toggle { gap: 0.4rem; margin: 0; color: var(--muted); cursor: pointer; white-space: nowrap; }
.header-toggle:has(input:checked) { color: var(--ink); }

/* --- Vote control --- */
button.vote {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  border-radius: 999px;
  padding: 0.28rem 0.85rem;
  font-size: 0.85rem;
  font-weight: 500;
  background: var(--card-2);
  border: 1px solid var(--line);
  color: var(--muted);
  flex: none;
}
button.vote:hover { border-color: var(--accent); color: var(--ink); }
button.vote.yes {
  background: linear-gradient(180deg, var(--accent), var(--accent-strong));
  border-color: var(--accent-strong);
  color: var(--accent-ink);
  font-weight: 700;
  box-shadow: 0 1px 8px var(--accent-soft);
}
html[data-theme='dark'] button.vote.yes { color: #04211c; }
button.vote.yes:hover { filter: brightness(1.07); }
@media (prefers-reduced-motion: no-preference) {
  button.vote.yes, button.vote.maybe, button.vote.no { animation: vote-pop 180ms ease-out; }
  @keyframes vote-pop {
    0% { transform: scale(0.92); }
    60% { transform: scale(1.06); }
    100% { transform: scale(1); }
  }
}
button.vote.maybe { background: var(--warn-soft); border-color: var(--warn); color: var(--warn); font-weight: 600; }
button.vote.no { background: var(--danger-soft); border-color: transparent; color: var(--danger); opacity: 0.8; }

/* --- POI rows: compact + expanded --- */
.poi { cursor: pointer; }
.poi .poi-head { display: flex; align-items: center; gap: 0.7rem; }
.poi .poi-main { flex: 1; min-width: 0; }
.poi-x {
  background: var(--card-2);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 0.7rem 0.85rem;
  margin: 0.55rem -0.25rem 0.15rem;
  display: grid;
  gap: 0.55rem;
  cursor: default;
}
.poi-x .row input[type='text'], .poi-x input:not([type]) { background: var(--card); }
.poi-x select { background: var(--card); }
/* Brief highlight when a map popup jumps to this row; the class is removed
   by a timer, so under reduced motion it is a plain fill for the same span. */
.poi.flash { background: var(--accent-soft); border-radius: 10px; }
@media (prefers-reduced-motion: no-preference) {
  .poi.flash { animation: poi-flash 1.5s ease-out forwards; }
  @keyframes poi-flash {
    from { background: var(--accent-soft); }
    to { background: transparent; }
  }
}

/* --- Toggle switch --- */
input.switch {
  appearance: none;
  -webkit-appearance: none;
  width: 32px;
  height: 18px;
  border-radius: 999px;
  background: var(--line);
  border: none;
  position: relative;
  cursor: pointer;
  transition: background 120ms;
  flex: none;
  margin: 0;
  vertical-align: middle;
}
input.switch::after {
  content: '';
  position: absolute;
  top: 2px;
  left: 2px;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  background: var(--ink-strong);
  transition: transform 120ms;
}
input.switch:checked { background: var(--accent-strong); }
input.switch:checked::after { transform: translateX(14px); }
input.switch:disabled { opacity: 0.4; cursor: default; }

/* --- Board two-column layout --- */
.board-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: 1.1rem; align-items: start; }
.board-grid > .board-map-col { order: -1; } /* single column: map first */
@media (min-width: 1100px) {
  .board-grid { grid-template-columns: minmax(0, 7fr) minmax(20rem, 5fr); }
  .board-grid > .board-map-col { order: 0; }
  /* Sticky, but scrollable within the viewport: when the map + base +
     suggestions stack grows taller than the screen (e.g. base expanded),
     the column scrolls on its own instead of cutting off the bottom. */
  .board-map-col {
    position: sticky;
    top: 1rem;
    max-height: calc(100vh - 2rem);
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: thin;
    /* Sticky makes this a stacking context; sit above the sticky filter bar
       (z 4) so the fullscreen map isn't painted under it. The columns never
       overlap in normal layout, so this only matters in fullscreen. */
    z-index: 5;
  }
  .board-map-col .map-box { height: min(60vh, 520px); }
}

/* --- Dropdown menu --- */
.menu-wrap { position: relative; display: inline-block; }
.menu-btn { font-weight: 700; letter-spacing: 0.1em; color: var(--muted); padding: 0.36rem 0.6rem; }
.menu-pop {
  position: absolute;
  right: 0;
  top: calc(100% + 4px);
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 9px;
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.35);
  display: grid;
  min-width: 11rem;
  padding: 4px;
  z-index: 30;
}
.menu-item {
  border: none;
  background: transparent;
  text-align: left;
  padding: 0.45rem 0.7rem;
  border-radius: 6px;
  color: var(--ink);
}
.menu-item:hover { background: var(--card-2); border-color: transparent; }
.menu-item.danger { color: var(--danger); }

/* --- Trip timeline --- */
.tl-entry { display: flex; gap: 1rem; }
.tl-rail { width: 22px; flex: none; display: flex; flex-direction: column; align-items: center; }
.tl-dot { width: 13px; height: 13px; border-radius: 50%; border: 3px solid var(--hue); background: var(--bg); box-shadow: 0 0 0 3px var(--hue-soft); flex: none; margin-top: 1.1rem; }
.tl-dot.minor { width: 9px; height: 9px; border-width: 2px; border-color: var(--muted); box-shadow: none; opacity: 0.7; }
.tl-line { width: 2px; flex: 1; background: var(--line); }
/* Travel legs get a dashed rail — movement, not a stop. */
.tl-line.dashed { background: repeating-linear-gradient(180deg, var(--line) 0 5px, transparent 5px 10px); }
.tl-card { flex: 1; min-width: 0; margin-bottom: 0.85rem; }
.tl-card.travel { background: var(--card-2); }
.tl-add {
  border-style: dashed;
  color: var(--muted);
  background: transparent;
}
.reorder { color: var(--muted); }

/* --- Sharing dialog --- */
.share-summary {
  background: var(--accent-soft);
  border: 1px solid transparent;
  border-radius: 9px;
  padding: 0.6rem 0.85rem;
  font-size: 0.9rem;
}
dialog.modal.wide { max-width: 34rem; }

/* --- Public trip page (share.html) — same no-inline-CSS constraint. --- */
main.share { max-width: 44rem; margin: 0 auto; padding: 1.5rem 1.25rem 4rem; }
/* A visitor here has no account and so no Settings — this is the only theme
   control on the page. */
.share-theme { position: fixed; top: 0.8rem; right: 0.8rem; z-index: 2; }
.share-brand { display: flex; align-items: center; gap: 0.55rem; margin-bottom: 1.1rem; }

/* --- Standalone policy page (privacy.html) — inline <style> would need a
   CSP carve-out, so its layout lives here with the rest. --- */
main.policy { max-width: 46rem; margin: 0 auto; padding: 2.5rem 1.25rem 4rem; }
main.policy h1 { margin-bottom: 0.2rem; }
main.policy h2 { margin: 1.6rem 0 0.4rem; font-size: 1.05rem; }
main.policy ul { padding-left: 1.2rem; }
main.policy li { margin: 0.25rem 0; }

/* --- Bottom tab bar (mobile only) --- */
#tabbar { display: none; }

/* --- "More" sheet: the sidebar destinations the tab bar has no room for.
   Only openable from the tab bar, so it never appears on a wide screen. --- */
dialog.modal.nav-sheet {
  margin: auto auto 0;
  width: 100%;
  max-width: none;
  max-height: 80vh;
  overflow-y: auto;
  border-radius: var(--radius) var(--radius) 0 0;
  border-bottom: none;
  padding-bottom: calc(1.1rem + env(safe-area-inset-bottom));
}
dialog.modal.nav-sheet h2 { font-size: 1.05rem; }
.more-nav { display: flex; flex-direction: column; gap: 2px; }
.more-nav a {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  color: var(--ink);
  padding: 0.55rem;
  border-radius: 8px;
  font-weight: 500;
  min-height: 44px;
}
.more-nav a:hover { text-decoration: none; background: var(--card-2); }
.more-nav a svg { flex: none; opacity: 0.9; color: var(--hue); }
.more-nav a.active { color: var(--hue); background: var(--hue-soft); box-shadow: inset 2.5px 0 0 var(--hue); }
.more-nav .nav-label { padding: 0.75rem 0.55rem 0.2rem; }
.more-nav .nav-label:first-child { padding-top: 0.2rem; }
.more-nav .side-epic { padding: 0.45rem 0.55rem; }

/* --- Narrow screens: slim top bar + bottom tab bar --- */
@media (max-width: 800px) {
  /* Explicit rows: the top bar stays content-height and the main column takes
     all the leftover space. Without this, the grid's default stretch splits
     the extra height of short pages evenly across both rows, inflating the
     top bar into a huge empty band. */
  #shell { grid-template-columns: 1fr; grid-template-rows: auto 1fr; }
  #sidebar { position: static; height: auto; flex-direction: row; align-items: center; gap: 0.4rem; padding: 0.5rem 0.75rem; border-right: none; border-bottom: 1px solid var(--line-soft); }
  .brand-row { padding: 0; flex: 1; }
  #sidebar nav { display: none; }
  .side-footer { border-top: none; padding-top: 0; display: flex; align-items: center; }
  .side-user-text { display: none; }
  #app { padding: 1rem 0.9rem 5.5rem; }
  #tabbar {
    display: flex;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 50;
    background: var(--panel);
    border-top: 1px solid var(--line-soft);
    padding: 0.35rem 0.3rem calc(0.55rem + env(safe-area-inset-bottom));
  }
  body.logged-out #tabbar { display: none; }
  #tabbar a, #tabbar button {
    flex: 1;
    min-width: 0;
    display: grid;
    justify-items: center;
    gap: 2px;
    color: var(--muted);
    padding: 0.35rem 0;
    font-size: 0.68rem;
    font-weight: 500;
    white-space: nowrap;
    border-radius: 8px;
    min-height: 44px;
  }
  /* The "More" tab opens a sheet rather than a route, so it is a button —
     strip the control chrome so it sits flush with the four links. */
  #tabbar button { background: none; border: none; font-family: inherit; cursor: pointer; }
  #tabbar a:hover { text-decoration: none; }
  #tabbar a svg, #tabbar button svg { color: var(--hue); opacity: 0.9; }
  #tabbar a.active, #tabbar button.active { color: var(--hue); }
  #tabbar a.active svg, #tabbar button.active svg { filter: drop-shadow(0 0 5px var(--hue-soft)); opacity: 1; }
  .board-map-col .map-box { height: 220px; }
}

/* --- Welcome tour (tour.js) --- */
dialog.modal.tour { padding: 0; max-width: 30rem; overflow: hidden; }
.tour-art {
  height: 170px;
  display: grid;
  place-items: center;
  overflow: hidden;
  border-bottom: 1px solid var(--line-soft);
  background:
    radial-gradient(24rem 12rem at 85% -20%, var(--glow-a), transparent 70%),
    radial-gradient(20rem 12rem at 10% 115%, var(--glow-b), transparent 70%),
    var(--card-2);
}
.tour-body { padding: 1rem 1.3rem 0.1rem; }
.tour-body h2 { font-size: 1.12rem; margin: 0.25rem 0 0.3rem; letter-spacing: -0.01em; }
.tour-body p { margin: 0; color: var(--muted); font-size: 0.9rem; min-height: 4.4em; }
.tour-step {
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent);
}
.tour-foot { display: flex; align-items: center; gap: 0.5rem; padding: 0.9rem 1.3rem 1.1rem; }
.tour-dots { display: flex; gap: 6px; margin-right: auto; }
.tour-dots button { width: 7px; height: 7px; border-radius: 999px; border: none; padding: 0; background: var(--line); }
.tour-dots button { transition: background 160ms, width 160ms; }
.tour-dots button.on { background: var(--accent); width: 18px; }
@media (prefers-reduced-motion: no-preference) {
  .tour-art > *, .tour-body > * { animation: tour-in 200ms ease-out backwards; }
  @keyframes tour-in {
    from { opacity: 0; transform: translateX(7px); }
    to { opacity: 1; transform: none; }
  }
}

/* Tour slide art: small compositions from the app's own vocabulary. */
.tour-art-stack { display: grid; gap: 0.6rem; justify-items: center; }
.tour-art-row { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; justify-content: center; }
.tour-art-pin {
  width: 52px;
  height: 52px;
  border-radius: 15px;
  display: grid;
  place-items: center;
  background: linear-gradient(135deg, var(--accent-soft), var(--sky-soft));
  box-shadow: inset 0 0 0 1px var(--accent-soft);
  color: var(--accent);
}
.tour-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.3rem;
  font-size: 0.78rem;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 0.2rem 0.65rem;
  color: var(--ink);
  white-space: nowrap;
}
.tour-chip strong { color: var(--ink-strong); }
.tour-chip-big { border-radius: 10px; padding: 0.5rem 0.9rem; gap: 0.5rem; }
.tour-chip-big svg { color: var(--accent); flex: none; }
.tour-connector { display: inline-flex; align-items: center; gap: 0.3rem; color: var(--muted); font-size: 0.72rem; font-weight: 600; }
.tour-connector i { display: block; width: 20px; height: 1px; background: var(--line); }
.tour-avatar {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: 0.58rem;
  font-weight: 700;
  background: var(--accent-soft);
  color: var(--accent);
  flex: none;
}
.tour-avatar.v { background: var(--sky-soft); color: var(--sky); }
.tour-avatar.o { background: var(--warn-soft); color: var(--warn); }
.tour-map {
  width: 230px;
  height: 92px;
  border-radius: 10px;
  position: relative;
  border: 1px solid var(--line-soft);
  background:
    linear-gradient(120deg, var(--accent-soft), transparent 60%),
    repeating-linear-gradient(0deg, transparent 0 22px, var(--line-soft) 22px 23px),
    repeating-linear-gradient(90deg, transparent 0 22px, var(--line-soft) 22px 23px),
    var(--card);
}
.tour-map-pin {
  position: absolute;
  width: 13px;
  height: 13px;
  border-radius: 50% 50% 50% 0;
  transform: rotate(-45deg);
  border: 2px solid var(--card);
}
.tour-overlap { width: 240px; }
.tour-obar { display: flex; align-items: center; gap: 0.5rem; width: 100%; }
.tour-obar .tour-avatar { width: 24px; height: 24px; font-size: 0.5rem; }
.tour-track { flex: 1; height: 10px; border-radius: 999px; background: var(--card); border: 1px solid var(--line-soft); position: relative; }
.tour-span { position: absolute; top: 1px; bottom: 1px; border-radius: 999px; }
.tour-overlap-glow { position: absolute; top: -3px; bottom: -3px; left: 46%; width: 22%; border-radius: 7px; border: 1.5px dashed var(--accent); }

/* --- "?" help popovers (dom.js helpTip) --- */
.help-wrap { position: relative; display: inline-flex; flex: none; }
.help-btn {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  padding: 0;
  display: grid;
  place-items: center;
  font-size: 0.72rem;
  font-weight: 700;
  line-height: 1;
  color: var(--muted);
}
.help-btn:hover, .help-btn[aria-expanded='true'] { color: var(--accent); border-color: var(--accent); background: var(--accent-soft); }
.help-pop {
  position: absolute;
  z-index: 30;
  top: calc(100% + 8px);
  right: -10px;
  width: min(270px, 78vw);
  display: block;
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: 10px;
  box-shadow: 0 10px 34px rgba(0, 0, 0, 0.35);
  padding: 0.7rem 0.85rem;
  font-size: 0.82rem;
  font-weight: 400;
  text-align: left;
  cursor: auto;
}
.help-pop strong { display: block; color: var(--ink-strong); margin-bottom: 0.25rem; }
.help-pop p { margin: 0 0 0.45rem; color: var(--muted); line-height: 1.45; }
.help-pop a { font-size: 0.78rem; font-weight: 600; }

/* --- Getting-started checklist (dashboard empty state) --- */
.steps { display: grid; counter-reset: step; }
.step { display: flex; gap: 0.75rem; align-items: flex-start; padding: 0.6rem 0; border-bottom: 1px solid var(--line-soft); }
.step:last-child { border-bottom: none; padding-bottom: 0.2rem; }
.step-dot {
  counter-increment: step;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  flex: none;
  display: grid;
  place-items: center;
  font-size: 0.74rem;
  font-weight: 700;
  background: var(--accent-soft);
  color: var(--accent);
}
.step-dot:not(.done)::before { content: counter(step); }
.step-dot.done { background: var(--ok-soft); color: var(--ok); }
.step .btn, .step button { flex: none; margin-top: 0.15rem; }

/* --- Help page FAQ --- */
details.faq { border-bottom: 1px solid var(--line-soft); }
details.faq:last-of-type { border-bottom: none; }
details.faq summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  padding: 0.55rem 0.15rem;
  font-weight: 600;
  color: var(--ink);
}
details.faq summary::-webkit-details-marker { display: none; }
details.faq summary::before { content: '+'; color: var(--accent); font-weight: 700; width: 0.9em; flex: none; }
details.faq[open] summary::before { content: '–'; }
details.faq summary:hover { color: var(--ink-strong); }
details.faq > div { padding: 0 0.15rem 0.7rem 1.4em; font-size: 0.88rem; color: var(--muted); max-width: 60ch; line-height: 1.55; }

/* --- POI operational facts (catalog notes: hours, prices, closed days) --- */
.poi-ops { display: flex; align-items: flex-start; gap: 0.35rem; margin-top: 0.15rem; }
.poi-ops svg { flex: none; margin-top: 0.28em; opacity: 0.75; }

/* --- Report-a-data-issue: icon-only warning button in the POI panel --- */
button.report-issue {
  display: grid;
  place-items: center;
  flex: none;
  width: 28px;
  height: 28px;
  padding: 0;
  border-color: transparent;
  background: transparent;
  color: var(--warn);
  opacity: 0.8;
}
button.report-issue:hover {
  opacity: 1;
  color: var(--warn);
  border-color: var(--warn);
  background: var(--warn-soft);
}

/* --- Personal places: the "My places" card and the paste box --- */
/* A row in the places list. The pin glyph carries the same meaning as the map
   marker it stands for: accent = a place of mine, dashed warn = a suggestion
   the operator has not answered yet. */
.place-row { display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.place-row .grow { min-width: 0; }
.place-row .place-name { color: var(--ink-strong); font-weight: 500; }
.place-dot {
  width: 11px;
  height: 11px;
  border-radius: 50%;
  flex: none;
  background: var(--accent);
  box-shadow: 0 0 0 2px var(--accent-soft);
}
.place-dot.pending { background: transparent; border: 2px dashed var(--warn); box-shadow: none; }
.place-row .switch { margin-left: 0.2rem; }

/* The paste box and what it says back. The result block is rebuilt on every
   keystroke, so it owns its own spacing rather than the rows inside it. */
.place-add { display: grid; gap: 0.45rem; margin-top: 0.6rem; }
.place-add label { margin-bottom: 0; }
.place-result { display: grid; gap: 0.45rem; }
.place-result:empty { display: none; }
.place-result p { margin: 0; }
/* The line that says a locality was read out of the code — good news, so it
   is the accent rather than a warning. */
.place-read {
  border-left: 2px solid var(--accent);
  padding-left: 0.5rem;
  color: var(--ink);
}
/* A refusal that needs a decision (unknown locality), versus one that is
   simply "I can't read that". */
.place-refusal { color: var(--muted); }
.place-refusal.warn {
  color: var(--warn);
  background: var(--warn-soft);
  border-radius: 8px;
  padding: 0.4rem 0.6rem;
}

/* --- One-time events (§2.9): rows in the board's Events card & peek --- */
.event-row { padding: 0.55rem 0; border-top: 1px solid var(--line-soft); }
.event-row:first-child { border-top: none; }
.event-row .pill { vertical-align: 1px; }
