/* ============================================================ THEME TOKENS
   Every colour in the UI resolves through these custom properties, so a
   theme is just a redefinition of the token set — no component CSS changes.
   `data-theme` is stamped on <html> server-side from the `theme` cookie, so
   server-rendered pages (login/signup) paint in the right theme immediately
   instead of flashing the default first.

   NOT tokenised on purpose: the category colours (food/drink/hotel/...).
   Those encode which category an item is — they are data, not decoration,
   the user can already recolour them, and they must stay recognisable
   across every theme. Semantic status colours (danger) do get tokens,
   because they need to stay legible on each theme's own background.
   ------------------------------------------------------------------------ */
:root, [data-theme="light"] {
  color-scheme: light;
  --bg: #fff;
  --bg-soft: #f9fafb;
  --surface: #fff;
  --surface-alt: #f3f4f6;
  --text: #1f2937;
  --text-soft: #374151;
  --text-muted: #6b7280;
  --text-faint: #6f7787;
  --border: #e5e7eb;
  --border-strong: #d1d5db;
  --divider: #eef0f3;
  --accent: #1f2937;
  --accent-hover: #4b5563;
  --accent-text: #fff;
  --header-btn: #374151;
  --link: #2563eb;
  --danger: #dc2626;
  --ai: #7c3aed;
  --toast-bg: #111827;
  --toast-text: #fff;
  --handle: #cbd5e1;
  --shadow-sm: rgba(0, 0, 0, .18);
  --shadow-md: rgba(0, 0, 0, .25);
  --shadow-lg: rgba(0, 0, 0, .34);
  --backdrop: rgba(0, 0, 0, .35);
  --spot-dim: rgba(17, 24, 39, .58);
  --spot-ring: rgba(255, 255, 255, .85);
}

/* Cool neutral dark. #1f2937 as an accent would disappear against a dark
   ground, so the accent shifts to a blue that still reads as interactive. */
[data-theme="dark"] {
  color-scheme: dark;
  --bg: #151922;
  --bg-soft: #1b212c;
  --surface: #272e3c;
  --surface-alt: #333b4b;
  --text: #f2f5fa;
  --text-soft: #d7dde7;
  --text-muted: #aeb7c6;
  --text-faint: #98a2b3;
  --border: #4d5970;
  --border-strong: #606d85;
  --divider: #333b4b;
  --accent: #3f6fe0;
  --accent-hover: #5b84ea;
  --accent-text: #fff;
  --header-btn: #333b4b;
  --link: #7aa2ff;
  --danger: #f87171;
  --ai: #a78bfa;
  --toast-bg: #333b4b;
  --toast-text: #e7eaf0;
  --handle: #606d85;
  --shadow-sm: rgba(0, 0, 0, .5);
  --shadow-md: rgba(0, 0, 0, .6);
  --shadow-lg: rgba(0, 0, 0, .7);
  --backdrop: rgba(0, 0, 0, .5);
  --spot-dim: rgba(0, 0, 0, .72);
  --spot-ring: rgba(255, 255, 255, .7);
}

/* "Auto" follows the device. Plain CSS has no way to alias one token block
   to two selectors, so the dark palette is repeated here verbatim — keep
   the two in sync when editing. */
@media (prefers-color-scheme: dark) {
  [data-theme="auto"] {
    color-scheme: dark;
    --bg: #151922;
    --bg-soft: #1b212c;
    --surface: #272e3c;
    --surface-alt: #333b4b;
    --text: #f2f5fa;
    --text-soft: #d7dde7;
    --text-muted: #aeb7c6;
    --text-faint: #98a2b3;
    --border: #4d5970;
    --border-strong: #606d85;
    --divider: #333b4b;
    --accent: #3f6fe0;
    --accent-hover: #5b84ea;
    --accent-text: #fff;
    --header-btn: #333b4b;
    --link: #7aa2ff;
    --danger: #f87171;
    --ai: #a78bfa;
    --toast-bg: #333b4b;
    --toast-text: #e7eaf0;
    --handle: #606d85;
    --shadow-sm: rgba(0, 0, 0, .5);
    --shadow-md: rgba(0, 0, 0, .6);
    --shadow-lg: rgba(0, 0, 0, .7);
    --backdrop: rgba(0, 0, 0, .5);
    --spot-dim: rgba(0, 0, 0, .72);
    --spot-ring: rgba(255, 255, 255, .7);
  }
}

/* Near-black with a vivid violet accent — high contrast, low chroma ground
   so the accent carries the whole page. */
[data-theme="modern"] {
  color-scheme: dark;
  --bg: #13131f;
  --bg-soft: #1a1a2b;
  --surface: #26263c;
  --surface-alt: #33334f;
  --text: #f4f2fe;
  --text-soft: #dad6f0;
  --text-muted: #b4adcf;
  --text-faint: #9e96bd;
  --border: #525079;
  --border-strong: #666390;
  --divider: #33334f;
  --accent: #7455e6;
  --accent-hover: #8a70ee;
  --accent-text: #fff;
  --header-btn: #33334f;
  --link: #8b9dff;
  --danger: #ff6b81;
  --ai: #c4a5ff;
  --toast-bg: #33334f;
  --toast-text: #f0eefc;
  --handle: #666390;
  --shadow-sm: rgba(0, 0, 0, .5);
  --shadow-md: rgba(0, 0, 0, .62);
  --shadow-lg: rgba(0, 0, 0, .72);
  --backdrop: rgba(10, 10, 20, .55);
  --spot-dim: rgba(6, 6, 12, .74);
  --spot-ring: rgba(160, 140, 255, .8);
}

/* Parchment + sepia — warm, low-glare, suits a travel journal. */
[data-theme="antique"] {
  color-scheme: light;
  --bg: #f4ecd8;
  --bg-soft: #ece0c6;
  --surface: #fdf8ec;
  --surface-alt: #f0e4cc;
  --text: #3f3222;
  --text-soft: #5c4a33;
  --text-muted: #7a6549;
  --text-faint: #7d6c50;
  --border: #ddcba6;
  --border-strong: #c9b287;
  --divider: #e6d8b8;
  --accent: #8b5e34;
  --accent-hover: #a3703f;
  --accent-text: #fdf8ec;
  --header-btn: #6f4a29;
  --link: #9c5a2d;
  --danger: #a83232;
  --ai: #7a5c9e;
  --toast-bg: #3f3222;
  --toast-text: #f4ecd8;
  --handle: #c9b287;
  --shadow-sm: rgba(72, 54, 30, .2);
  --shadow-md: rgba(72, 54, 30, .28);
  --shadow-lg: rgba(72, 54, 30, .36);
  --backdrop: rgba(63, 50, 34, .38);
  --spot-dim: rgba(63, 50, 34, .6);
  --spot-ring: rgba(253, 248, 236, .9);
}

/* Soft rose — light and airy. */
[data-theme="sakura"] {
  color-scheme: light;
  --bg: #fff5f7;
  --bg-soft: #ffeaf0;
  --surface: #fff;
  --surface-alt: #ffe0e9;
  --text: #4a2c38;
  --text-soft: #6d4354;
  --text-muted: #96697c;
  --text-faint: #8a6274;
  --border: #f7d3de;
  --border-strong: #f0b8c9;
  --divider: #fbe4ea;
  --accent: #c9436f;
  --accent-hover: #d85c85;
  --accent-text: #fff;
  --header-btn: #b83a63;
  --link: #d1477a;
  --danger: #d63c4e;
  --ai: #9b6dd6;
  --toast-bg: #4a2c38;
  --toast-text: #fff5f7;
  --handle: #f0b8c9;
  --shadow-sm: rgba(120, 50, 75, .16);
  --shadow-md: rgba(120, 50, 75, .22);
  --shadow-lg: rgba(120, 50, 75, .3);
  --backdrop: rgba(74, 44, 56, .34);
  --spot-dim: rgba(74, 44, 56, .58);
  --spot-ring: rgba(255, 255, 255, .9);
}

/* Deep green, earthy — the darkest of the light-text themes. */
[data-theme="forest"] {
  color-scheme: dark;
  --bg: #13221a;
  --bg-soft: #1a2c22;
  --surface: #263b2e;
  --surface-alt: #324b3a;
  --text: #f2fbf4;
  --text-soft: #d3e6d9;
  --text-muted: #a9c0b1;
  --text-faint: #96ad9e;
  --border: #4c6b58;
  --border-strong: #5f8069;
  --divider: #324b3a;
  --accent: #5cb37f;
  --accent-hover: #74c795;
  --accent-text: #08130c;
  --header-btn: #324b3a;
  --link: #7fd1a0;
  --danger: #ef7d7d;
  --ai: #a9c98a;
  --toast-bg: #324b3a;
  --toast-text: #e3efe6;
  --handle: #5f8069;
  --shadow-sm: rgba(0, 0, 0, .45);
  --shadow-md: rgba(0, 0, 0, .55);
  --shadow-lg: rgba(0, 0, 0, .66);
  --backdrop: rgba(6, 18, 11, .55);
  --spot-dim: rgba(4, 12, 8, .72);
  --spot-ring: rgba(227, 239, 230, .75);
}

/* ===================================================================== base */
* { box-sizing: border-box; }
html, body {
  height: 100%; margin: 0; font-family: "Segoe UI", "Microsoft JhengHei", sans-serif;
}
/* iPhones with a Dynamic Island / notch (15/16/17+) render WebView content
   under the status-bar cutout and home-indicator area unless the page
   opts in (viewport-fit=cover, set in each template's <meta viewport>) AND
   reserves that space itself — otherwise buttons placed there are visible
   but the system intercepts touches for its own gestures instead of
   passing them to the page. body becomes a flex column so the header can
   grow by the safe-area amount without breaking the layout math below. */
body {
  display: flex; flex-direction: column;
  background: var(--bg); color: var(--text);
}

header {
  display: flex; align-items: center; justify-content: space-between;
  flex: 0 0 auto;
  padding: 8px 14px; background: var(--accent); color: var(--accent-text);
  padding-top: calc(8px + env(safe-area-inset-top));
  padding-left: calc(14px + env(safe-area-inset-left));
  padding-right: calc(14px + env(safe-area-inset-right));
}
/* min-width:0 + ellipsis lets a long localized title truncate instead of
   shoving the action buttons off the edge on a narrow window. */
header h1 { font-size: 1.05rem; margin: 0; min-width: 0; overflow: hidden;
  text-overflow: ellipsis; white-space: nowrap; }
/* font-size lives on the container so JS (fitHeader) can scale every button
   at once; buttons inherit it. */
.header-actions { flex: 0 0 auto; display: flex; align-items: center; font-size: .9rem; }
.header-actions button {
  margin-left: 6px; padding: 6px 12px; border: 0; border-radius: 6px;
  background: var(--header-btn); color: var(--accent-text); cursor: pointer; font-size: inherit;
  white-space: nowrap;
}
.header-actions button:hover { background: var(--accent-hover); }

#layout { display: flex; flex: 1; min-height: 0; }
#sidebar {
  width: 340px; min-width: 260px; display: flex; flex-direction: column;
  border-right: 1px solid var(--border); background: var(--bg-soft);
  padding-left: env(safe-area-inset-left);
  padding-bottom: env(safe-area-inset-bottom);
}
#map { flex: 1; }

#search-row { display: flex; align-items: center; gap: 6px; margin: 10px 10px 6px; }
#search { flex: 1; min-width: 0; padding: 8px 10px; border: 1px solid var(--border-strong);
  border-radius: 8px; background: var(--surface); color: var(--text); }
#btn-tools {
  flex: 0 0 auto; width: 38px; height: 38px; padding: 0; font-size: 1.1rem;
  border: 1px solid var(--border-strong); border-radius: 8px; background: var(--surface); color: var(--text-soft);
  cursor: pointer; line-height: 1;
}
#btn-tools:hover { background: var(--surface-alt); }
/* Pressed/active look while the tools panel is open. */
#btn-tools.on { background: var(--accent); color: var(--accent-text); border-color: var(--accent); }
/* The collapsible panel holding sort + bulk-edit controls. [hidden] keeps it
   out of the layout entirely until toggled. */
#tools-panel { margin-bottom: 4px; }
#sort-row { display: flex; align-items: center; gap: 6px; margin: 0 10px 6px; font-size: .85rem; color: var(--text-muted); }
#sort-row select { flex: 1; padding: 5px 8px; border: 1px solid var(--border-strong); border-radius: 8px;
  background: var(--surface); color: var(--text); }

/* Theme + basemap pickers share the option-row look. */
#mapstyle-list, #theme-list { display: flex; flex-direction: column; gap: 6px; margin: 8px 0; }
#theme-list { max-height: 52vh; overflow-y: auto; }
.mapstyle-row, .theme-row {
  display: flex; align-items: center; gap: 10px; width: 100%;
  padding: 7px 10px; border: 1px solid var(--border); border-radius: 10px;
  background: var(--surface); color: var(--text); cursor: pointer; font: inherit; text-align: left;
}
.mapstyle-row:hover, .theme-row:hover { border-color: var(--text-faint); }
.mapstyle-row.active, .theme-row.active { border-color: var(--accent); background: var(--bg-soft); }
.mapstyle-thumb {
  width: 46px; height: 46px; flex: 0 0 auto; border-radius: 8px;
  object-fit: cover; background: var(--divider); border: 1px solid var(--border);
}
.mapstyle-name, .theme-name { flex: 1; min-width: 0; font-size: .9rem; }
.mapstyle-tick, .theme-tick { flex: 0 0 auto; color: var(--accent); font-weight: 700; }
/* Live swatch: three bars painted with that theme's own tokens, so the
   preview is the real palette rather than a hand-picked approximation. */
.theme-swatch {
  width: 46px; height: 30px; flex: 0 0 auto; border-radius: 8px; overflow: hidden;
  display: flex; border: 1px solid var(--border);
}
.theme-swatch i { flex: 1; display: block; }

/* Category-tag manager (dlg-cats) */
#cats-list { display: flex; flex-direction: column; gap: 6px; margin: 8px 0; max-height: 50vh; overflow-y: auto; }
.cat-row { display: flex; align-items: center; gap: 8px; }
.cat-row .cat-color { width: 34px; height: 28px; padding: 0; border: 1px solid var(--border-strong); border-radius: 6px; background: none; cursor: pointer; flex: 0 0 auto; }
.cat-row .cat-name { flex: 1; }
.cat-row .cat-name-input { flex: 1; padding: 6px 8px; border: 1px solid var(--border-strong); border-radius: 6px;
  background: var(--surface); color: var(--text); }
#cats-add-row { display: flex; align-items: center; gap: 8px; margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--divider); }
#cats-add-row .cat-name, #cats-new-label { flex: 1; padding: 6px 8px; border: 1px solid var(--border-strong); border-radius: 6px;
  background: var(--surface); color: var(--text); }
#cats-new-color { width: 34px; height: 28px; padding: 0; border: 1px solid var(--border-strong); border-radius: 6px; background: none; cursor: pointer; flex: 0 0 auto; }
/* Category chips: one horizontally-scrollable row (no wrapping into 3-4
   lines). Keeps the sidebar short while every category stays reachable. */
#filters {
  display: flex; flex-wrap: nowrap; gap: 6px; padding: 2px 10px 8px;
  overflow-x: auto; scrollbar-width: thin; -webkit-overflow-scrolling: touch;
}
.chip {
  flex: 0 0 auto; white-space: nowrap;
  border: 1px solid var(--border-strong); background: var(--surface); color: var(--text);
  border-radius: 999px; padding: 3px 10px; font-size: .8rem; cursor: pointer;
}
.chip.active { background: var(--accent); color: var(--accent-text); border-color: var(--accent); }

#bulk-bar {
  display: flex; align-items: center; gap: 6px; flex-wrap: wrap;
  padding: 6px 10px; margin: 0 2px 4px; font-size: .78rem; color: var(--text-soft);
}
#bulk-bar .bulk-all { display: flex; align-items: center; gap: 4px; cursor: pointer; white-space: nowrap; }
#bulk-count { color: var(--text-muted); white-space: nowrap; }
#bulk-category { font-size: .78rem; padding: 3px 5px; border: 1px solid var(--border-strong); border-radius: 6px;
  background: var(--surface); color: var(--text); }
#bulk-apply {
  font-size: .78rem; padding: 3px 10px; border-radius: 6px; cursor: pointer;
  border: 1px solid var(--accent); background: var(--accent); color: var(--accent-text);
}
#bulk-apply:disabled { opacity: .4; cursor: default; background: var(--surface); color: var(--accent); }
#bulk-delete {
  font-size: .78rem; padding: 3px 10px; border-radius: 6px; cursor: pointer;
  border: 1px solid var(--danger); background: var(--surface); color: var(--danger);
}
#bulk-delete:disabled { opacity: .4; cursor: default; }

#list { overflow-y: auto; flex: 1; padding: 0 8px 12px; }
.card {
  background: var(--surface); border: 1px solid var(--border); border-radius: 10px;
  padding: 9px 11px; margin: 6px 2px; cursor: pointer;
}
.card:hover { border-color: var(--text-faint); }
.card .top { display: flex; gap: 6px; align-items: center; }
.card .sel { margin: 0 6px 0 0; cursor: pointer; flex: 0 0 auto; }
.card .name {
  font-weight: 600; font-size: .93rem; border: 1px solid transparent; background: none;
  font-family: inherit; padding: 1px 3px; border-radius: 4px; flex: 1; min-width: 0;
  color: var(--text);
}
.card .name:hover, .card .name:focus { border-color: var(--border-strong); background: var(--surface); }
.card .dist { color: var(--link); font-size: .78rem; white-space: nowrap; }
.card .addr { color: var(--text-muted); font-size: .8rem; margin-top: 2px; }
.card .cap  { color: var(--text-faint); font-size: .78rem; margin-top: 2px;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.card .row { margin-top: 6px; display: flex; gap: 5px; flex-wrap: wrap; align-items: center; }
/* Category colours are data, not theme — see the note at the top. */
.badge { font-size: .72rem; border-radius: 6px; padding: 1px 7px; color: #fff; }
.badge.food { background: #e11d48; } .badge.drink { background: #b45309; }
.badge.hotel { background: #7c3aed; } .badge.attraction { background: #059669; }
.badge.other { background: #6b7280; }
.cat-select {
  font-size: .72rem; border-radius: 6px; padding: 1px 4px; color: #fff; border: none;
  cursor: pointer;
}
.cat-select.food { background: #e11d48; } .cat-select.drink { background: #b45309; }
.cat-select.hotel { background: #7c3aed; } .cat-select.attraction { background: #059669; }
.cat-select.other { background: #6b7280; }
.cat-select option { color: var(--text); background: var(--surface); }
.nogeo { font-size: .72rem; color: var(--danger); }
.mini {
  font-size: .74rem; padding: 2px 8px; border-radius: 6px; cursor: pointer;
  border: 1px solid var(--border-strong); background: var(--surface); color: var(--text);
}
.mini.ai { border-color: var(--ai); color: var(--ai); }
.mini:disabled { opacity: .5; cursor: wait; }
.section-title { font-size: .78rem; color: var(--text-muted); margin: 12px 6px 2px; }

dialog {
  border: 0; border-radius: 12px; padding: 18px 20px; width: min(480px, 92vw);
  box-shadow: 0 12px 40px var(--shadow-md);
  background: var(--surface); color: var(--text);
}
dialog::backdrop { background: var(--backdrop); }
dialog h2 { margin: 0 0 10px; font-size: 1.05rem; }
dialog h3 { margin: 14px 0 4px; font-size: .9rem; }
dialog label { display: block; font-size: .82rem; color: var(--text-soft); margin: 8px 0; }
dialog input, dialog textarea {
  display: block; width: 100%; margin-top: 3px; padding: 7px 9px;
  border: 1px solid var(--border-strong); border-radius: 8px; font: inherit;
  background: var(--surface); color: var(--text);
  /* iOS auto-zooms the whole page on focus if font-size is under 16px,
     and doesn't zoom back out on its own — pin it to 16px to prevent that. */
  font-size: 16px;
}
/* Checkboxes/radios must NOT inherit the full-width block styling above,
   or they stretch across the row and shove their label out of place
   (e.g. the pack-manager "published" toggle). */
dialog input[type="checkbox"], dialog input[type="radio"] {
  width: auto; display: inline-block; margin: 0; flex: 0 0 auto;
}
dialog .hint { font-size: .78rem; color: var(--text-muted); margin: 2px 0 6px; }
.dlg-actions { margin-top: 14px; display: flex; gap: 8px; justify-content: flex-end; }
dialog button { padding: 7px 14px; border-radius: 8px; border: 1px solid var(--border-strong);
  background: var(--surface); color: var(--text); cursor: pointer; }
dialog button.primary { background: var(--accent); color: var(--accent-text); border-color: var(--accent); }

#toast {
  position: fixed; bottom: 18px; left: 50%; transform: translateX(-50%);
  background: var(--toast-bg); color: var(--toast-text); padding: 9px 16px; border-radius: 8px;
  font-size: .85rem; opacity: 0; pointer-events: none; transition: opacity .25s;
  max-width: 90vw; z-index: 2000;
}
#toast.show { opacity: .95; }

/* ---- first-run guided tour (spotlight overlay) ---- */
/* The full-screen overlay captures clicks so the page can't be operated mid
   tour; the tooltip is a child with its own pointer events, and the hole is a
   purely-visual cutout made by a huge box-shadow. */
#tour-overlay { position: fixed; inset: 0; z-index: 3000; }
#tour-hole {
  position: fixed; border-radius: 10px; pointer-events: none;
  box-shadow: 0 0 0 9999px var(--spot-dim);
  outline: 2px solid var(--spot-ring); transition: all .2s ease;
}
#tour-pop {
  position: fixed; z-index: 3001; width: min(320px, 86vw);
  background: var(--surface); color: var(--text); border-radius: 12px; padding: 14px 16px;
  box-shadow: 0 16px 44px var(--shadow-lg);
}
.tour-counter { font-size: .72rem; color: var(--text-muted); letter-spacing: .04em; }
.tour-title { font-weight: 700; font-size: 1rem; margin: 3px 0 6px; }
.tour-body { font-size: .88rem; color: var(--text-soft); line-height: 1.55; }
.tour-actions { display: flex; align-items: center; gap: 8px; margin-top: 14px; }
.tour-actions button {
  padding: 7px 14px; border-radius: 8px; border: 1px solid var(--border-strong);
  background: var(--surface); color: var(--text); cursor: pointer; font: inherit; font-size: .85rem;
}
.tour-actions .tour-skip { border: 0; color: var(--text-muted); padding-left: 0; }
.tour-actions .primary { background: var(--accent); color: var(--accent-text); border-color: var(--accent); }

/* Leaflet popups are injected outside our containers, so they need the
   surface tokens applied explicitly or they stay white on a dark theme. */
.leaflet-popup-content { font-size: .85rem; }
.leaflet-popup-content-wrapper, .leaflet-popup-tip {
  background: var(--surface); color: var(--text);
}
.popup-name { font-weight: 700; margin-bottom: 2px; }
.popup-cap { color: var(--text-muted); max-height: 90px; overflow-y: auto; white-space: pre-wrap; margin: 4px 0; }

/* Drag handle for the mobile bottom sheet — hidden on desktop. */
#sheet-handle { display: none; }

@media (max-width: 720px) {
  /* Header: reclaim horizontal space so the action buttons stop squeezing.
     Drop the long title text (keep the 📍), tighten button padding. */
  header { padding-left: calc(10px + env(safe-area-inset-left));
           padding-right: calc(10px + env(safe-area-inset-right)); }
  header h1 .ttl { display: none; }
  /* Smaller base + tighter spacing on phones; fitHeader() shrinks further only
     if a language still overflows, so labels stay as large as will fit. */
  .header-actions { font-size: .82rem; }
  .header-actions button { margin-left: 4px; padding: 6px 8px; }

  /* Map fills the whole area; the sidebar rides above it as a draggable
     bottom sheet (Google-Maps style) instead of a fixed 45% split. */
  #layout { display: block; position: relative; }
  #map { position: absolute; inset: 0; height: 100%; }

  #sidebar {
    position: fixed; left: 0; right: 0; bottom: 0;
    width: 100%; height: 88vh; z-index: 1000;
    border-right: 0; border-top: 1px solid var(--border);
    border-top-left-radius: 16px; border-top-right-radius: 16px;
    box-shadow: 0 -6px 24px var(--shadow-sm);
    /* translateY is a % of the sheet's own height; JS snaps this between
       full (~0.04), half (0.5) and peek (0.86). Default = half. */
    transform: translateY(var(--sheet-offset, 50%));
    transition: transform .28s cubic-bezier(.4, 0, .2, 1);
  }
  /* 44px is the minimum comfortable touch target; the visible pill stays
     small but the grabbable band around it is now full-thumb sized. */
  #sheet-handle {
    display: block; flex: 0 0 auto; height: 44px; position: relative;
    cursor: grab; touch-action: none;   /* let JS own the drag gesture */
  }
  #sheet-handle::before {
    content: ""; position: absolute; top: 14px; left: 50%;
    transform: translateX(-50%);
    width: 52px; height: 5px; border-radius: 999px; background: var(--handle);
  }
  /* The search row doubles as drag surface (JS ignores the field/buttons),
     so its background must not consume the touch gesture either. */
  #search-row { touch-action: none; }
  #search, #btn-tools { touch-action: auto; }
  /* Pull the search up into the space the taller handle now occupies. */
  #search-row { margin-top: -6px; }
}
